1*56bb7041Schristos/* Copyright 2016-2020 Free Software Foundation, Inc. 2*56bb7041Schristos Contributed by Dimitar Dimitrov <dimitar@dinux.eu> 3*56bb7041Schristos 4*56bb7041Schristos This file is part of the PRU simulator. 5*56bb7041Schristos 6*56bb7041Schristos This library is free software; you can redistribute it and/or modify 7*56bb7041Schristos it under the terms of the GNU General Public License as published by 8*56bb7041Schristos the Free Software Foundation; either version 3 of the License, or 9*56bb7041Schristos (at your option) any later version. 10*56bb7041Schristos 11*56bb7041Schristos This program is distributed in the hope that it will be useful, 12*56bb7041Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 13*56bb7041Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14*56bb7041Schristos GNU General Public License for more details. 15*56bb7041Schristos 16*56bb7041Schristos You should have received a copy of the GNU General Public License 17*56bb7041Schristos along with this program; if not, see <http://www.gnu.org/licenses/>. */ 18*56bb7041Schristos 19*56bb7041Schristos/* 20*56bb7041Schristos PRU Instruction Set Architecture 21*56bb7041Schristos 22*56bb7041Schristos INSTRUCTION (NAME, 23*56bb7041Schristos SEMANTICS) 24*56bb7041Schristos */ 25*56bb7041Schristos 26*56bb7041SchristosINSTRUCTION (add, 27*56bb7041Schristos OP2 = (IO ? IMM8 : RS2); 28*56bb7041Schristos RD = RS1 + OP2; 29*56bb7041Schristos CARRY = (((uint64_t) RS1 + (uint64_t) OP2) >> RD_WIDTH) & 1; 30*56bb7041Schristos PC++) 31*56bb7041Schristos 32*56bb7041SchristosINSTRUCTION (adc, 33*56bb7041Schristos OP2 = (IO ? IMM8 : RS2); 34*56bb7041Schristos RD = RS1 + OP2 + CARRY; 35*56bb7041Schristos CARRY = (((uint64_t) RS1 + (uint64_t) OP2 + (uint64_t) CARRY) 36*56bb7041Schristos >> RD_WIDTH) & 1; 37*56bb7041Schristos PC++) 38*56bb7041Schristos 39*56bb7041SchristosINSTRUCTION (sub, 40*56bb7041Schristos OP2 = (IO ? IMM8 : RS2); 41*56bb7041Schristos RD = RS1 - OP2; 42*56bb7041Schristos CARRY = (((uint64_t) RS1 - (uint64_t) OP2) >> RD_WIDTH) & 1; 43*56bb7041Schristos PC++) 44*56bb7041Schristos 45*56bb7041SchristosINSTRUCTION (suc, 46*56bb7041Schristos OP2 = (IO ? IMM8 : RS2); 47*56bb7041Schristos RD = RS1 - OP2 - CARRY; 48*56bb7041Schristos CARRY = (((uint64_t) RS1 - (uint64_t) OP2 - (uint64_t) CARRY) 49*56bb7041Schristos >> RD_WIDTH) & 1; 50*56bb7041Schristos PC++) 51*56bb7041Schristos 52*56bb7041SchristosINSTRUCTION (rsb, 53*56bb7041Schristos OP2 = (IO ? IMM8 : RS2); 54*56bb7041Schristos RD = OP2 - RS1; 55*56bb7041Schristos CARRY = (((uint64_t) OP2 - (uint64_t) RS1) >> RD_WIDTH) & 1; 56*56bb7041Schristos PC++) 57*56bb7041Schristos 58*56bb7041SchristosINSTRUCTION (rsc, 59*56bb7041Schristos OP2 = (IO ? IMM8 : RS2); 60*56bb7041Schristos RD = OP2 - RS1 - CARRY; 61*56bb7041Schristos CARRY = (((uint64_t) OP2 - (uint64_t) RS1 - (uint64_t) CARRY) 62*56bb7041Schristos >> RD_WIDTH) & 1; 63*56bb7041Schristos PC++) 64*56bb7041Schristos 65*56bb7041SchristosINSTRUCTION (lsl, 66*56bb7041Schristos OP2 = (IO ? IMM8 : RS2); 67*56bb7041Schristos RD = RS1 << (OP2 & 0x1f); 68*56bb7041Schristos PC++) 69*56bb7041Schristos 70*56bb7041SchristosINSTRUCTION (lsr, 71*56bb7041Schristos OP2 = (IO ? IMM8 : RS2); 72*56bb7041Schristos RD = RS1 >> (OP2 & 0x1f); 73*56bb7041Schristos PC++) 74*56bb7041Schristos 75*56bb7041SchristosINSTRUCTION (and, 76*56bb7041Schristos OP2 = (IO ? IMM8 : RS2); 77*56bb7041Schristos RD = RS1 & OP2; 78*56bb7041Schristos PC++) 79*56bb7041Schristos 80*56bb7041SchristosINSTRUCTION (or, 81*56bb7041Schristos OP2 = (IO ? IMM8 : RS2); 82*56bb7041Schristos RD = RS1 | OP2; 83*56bb7041Schristos PC++) 84*56bb7041Schristos 85*56bb7041SchristosINSTRUCTION (xor, 86*56bb7041Schristos OP2 = (IO ? IMM8 : RS2); 87*56bb7041Schristos RD = RS1 ^ OP2; 88*56bb7041Schristos PC++) 89*56bb7041Schristos 90*56bb7041SchristosINSTRUCTION (not, 91*56bb7041Schristos RD = ~RS1; 92*56bb7041Schristos PC++) 93*56bb7041Schristos 94*56bb7041SchristosINSTRUCTION (min, 95*56bb7041Schristos OP2 = (IO ? IMM8 : RS2); 96*56bb7041Schristos RD = RS1 < OP2 ? RS1 : OP2; 97*56bb7041Schristos PC++) 98*56bb7041Schristos 99*56bb7041SchristosINSTRUCTION (max, 100*56bb7041Schristos OP2 = (IO ? IMM8 : RS2); 101*56bb7041Schristos RD = RS1 > OP2 ? RS1 : OP2; 102*56bb7041Schristos PC++) 103*56bb7041Schristos 104*56bb7041SchristosINSTRUCTION (clr, 105*56bb7041Schristos OP2 = (IO ? IMM8 : RS2); 106*56bb7041Schristos RD = RS1 & ~(1u << (OP2 & 0x1f)); 107*56bb7041Schristos PC++) 108*56bb7041Schristos 109*56bb7041SchristosINSTRUCTION (set, 110*56bb7041Schristos OP2 = (IO ? IMM8 : RS2); 111*56bb7041Schristos RD = RS1 | (1u << (OP2 & 0x1f)); 112*56bb7041Schristos PC++) 113*56bb7041Schristos 114*56bb7041SchristosINSTRUCTION (jmp, 115*56bb7041Schristos OP2 = (IO ? IMM16 : RS2); 116*56bb7041Schristos PC = OP2) 117*56bb7041Schristos 118*56bb7041SchristosINSTRUCTION (jal, 119*56bb7041Schristos OP2 = (IO ? IMM16 : RS2); 120*56bb7041Schristos RD = PC + 1; 121*56bb7041Schristos PC = OP2) 122*56bb7041Schristos 123*56bb7041SchristosINSTRUCTION (ldi, 124*56bb7041Schristos RD = IMM16; 125*56bb7041Schristos PC++) 126*56bb7041Schristos 127*56bb7041SchristosINSTRUCTION (halt, 128*56bb7041Schristos pru_sim_syscall (sd, cpu); 129*56bb7041Schristos PC++) 130*56bb7041Schristos 131*56bb7041SchristosINSTRUCTION (slp, 132*56bb7041Schristos if (!WAKEONSTATUS) 133*56bb7041Schristos { 134*56bb7041Schristos RAISE_SIGINT (sd); 135*56bb7041Schristos } 136*56bb7041Schristos else 137*56bb7041Schristos { 138*56bb7041Schristos PC++; 139*56bb7041Schristos }) 140*56bb7041Schristos 141*56bb7041SchristosINSTRUCTION (qbgt, 142*56bb7041Schristos OP2 = (IO ? IMM8 : RS2); 143*56bb7041Schristos PC = (OP2 > RS1) ? (PC + BROFF) : (PC + 1)) 144*56bb7041Schristos 145*56bb7041SchristosINSTRUCTION (qbge, 146*56bb7041Schristos OP2 = (IO ? IMM8 : RS2); 147*56bb7041Schristos PC = (OP2 >= RS1) ? (PC + BROFF) : (PC + 1)) 148*56bb7041Schristos 149*56bb7041SchristosINSTRUCTION (qblt, 150*56bb7041Schristos OP2 = (IO ? IMM8 : RS2); 151*56bb7041Schristos PC = (OP2 < RS1) ? (PC + BROFF) : (PC + 1)) 152*56bb7041Schristos 153*56bb7041SchristosINSTRUCTION (qble, 154*56bb7041Schristos OP2 = (IO ? IMM8 : RS2); 155*56bb7041Schristos PC = (OP2 <= RS1) ? (PC + BROFF) : (PC + 1)) 156*56bb7041Schristos 157*56bb7041SchristosINSTRUCTION (qbeq, 158*56bb7041Schristos OP2 = (IO ? IMM8 : RS2); 159*56bb7041Schristos PC = (OP2 == RS1) ? (PC + BROFF) : (PC + 1)) 160*56bb7041Schristos 161*56bb7041SchristosINSTRUCTION (qbne, 162*56bb7041Schristos OP2 = (IO ? IMM8 : RS2); 163*56bb7041Schristos PC = (OP2 != RS1) ? (PC + BROFF) : (PC + 1)) 164*56bb7041Schristos 165*56bb7041SchristosINSTRUCTION (qba, 166*56bb7041Schristos OP2 = (IO ? IMM8 : RS2); 167*56bb7041Schristos PC = PC + BROFF) 168*56bb7041Schristos 169*56bb7041SchristosINSTRUCTION (qbbs, 170*56bb7041Schristos OP2 = (IO ? IMM8 : RS2); 171*56bb7041Schristos PC = (RS1 & (1u << (OP2 & 0x1f))) ? (PC + BROFF) : (PC + 1)) 172*56bb7041Schristos 173*56bb7041SchristosINSTRUCTION (qbbc, 174*56bb7041Schristos OP2 = (IO ? IMM8 : RS2); 175*56bb7041Schristos PC = !(RS1 & (1u << (OP2 & 0x1f))) ? (PC + BROFF) : (PC + 1)) 176*56bb7041Schristos 177*56bb7041SchristosINSTRUCTION (lbbo, 178*56bb7041Schristos pru_dmem2reg (cpu, XBBO_BASEREG + (IO ? IMM8 : RS2), 179*56bb7041Schristos BURSTLEN, RD_REGN, RDB); 180*56bb7041Schristos PC++) 181*56bb7041Schristos 182*56bb7041SchristosINSTRUCTION (sbbo, 183*56bb7041Schristos pru_reg2dmem (cpu, XBBO_BASEREG + (IO ? IMM8 : RS2), 184*56bb7041Schristos BURSTLEN, RD_REGN, RDB); 185*56bb7041Schristos PC++) 186*56bb7041Schristos 187*56bb7041SchristosINSTRUCTION (lbco, 188*56bb7041Schristos pru_dmem2reg (cpu, CTABLE[CB] + (IO ? IMM8 : RS2), 189*56bb7041Schristos BURSTLEN, RD_REGN, RDB); 190*56bb7041Schristos PC++) 191*56bb7041Schristos 192*56bb7041SchristosINSTRUCTION (sbco, 193*56bb7041Schristos pru_reg2dmem (cpu, CTABLE[CB] + (IO ? IMM8 : RS2), 194*56bb7041Schristos BURSTLEN, RD_REGN, RDB); 195*56bb7041Schristos PC++) 196*56bb7041Schristos 197*56bb7041SchristosINSTRUCTION (xin, 198*56bb7041Schristos DO_XIN (XFR_WBA, RD_REGN, RDB, XFR_LENGTH); 199*56bb7041Schristos PC++) 200*56bb7041Schristos 201*56bb7041SchristosINSTRUCTION (xout, 202*56bb7041Schristos DO_XOUT (XFR_WBA, RD_REGN, RDB, XFR_LENGTH); 203*56bb7041Schristos PC++) 204*56bb7041Schristos 205*56bb7041SchristosINSTRUCTION (xchg, 206*56bb7041Schristos DO_XCHG (XFR_WBA, RD_REGN, RDB, XFR_LENGTH); 207*56bb7041Schristos PC++) 208*56bb7041Schristos 209*56bb7041SchristosINSTRUCTION (sxin, 210*56bb7041Schristos sim_io_eprintf (sd, "SXIN instruction not supported by sim\n"); 211*56bb7041Schristos RAISE_SIGILL (sd)) 212*56bb7041Schristos 213*56bb7041SchristosINSTRUCTION (sxout, 214*56bb7041Schristos sim_io_eprintf (sd, "SXOUT instruction not supported by sim\n"); 215*56bb7041Schristos RAISE_SIGILL (sd)) 216*56bb7041Schristos 217*56bb7041SchristosINSTRUCTION (sxchg, 218*56bb7041Schristos sim_io_eprintf (sd, "SXCHG instruction not supported by sim\n"); 219*56bb7041Schristos RAISE_SIGILL (sd)) 220*56bb7041Schristos 221*56bb7041SchristosINSTRUCTION (loop, 222*56bb7041Schristos OP2 = (IO ? IMM8 + 1 : RS2_w0); 223*56bb7041Schristos if (OP2 == 0) 224*56bb7041Schristos { 225*56bb7041Schristos PC = LOOPEND; 226*56bb7041Schristos } 227*56bb7041Schristos else 228*56bb7041Schristos { 229*56bb7041Schristos LOOPTOP = PC + 1; 230*56bb7041Schristos LOOPEND = PC + LOOP_JMPOFFS; 231*56bb7041Schristos LOOPCNT = OP2; 232*56bb7041Schristos LOOP_IN_PROGRESS = 1; 233*56bb7041Schristos PC++; 234*56bb7041Schristos }) 235*56bb7041Schristos 236*56bb7041SchristosINSTRUCTION (iloop, 237*56bb7041Schristos OP2 = (IO ? IMM8 + 1 : RS2_w0); 238*56bb7041Schristos if (OP2 == 0) 239*56bb7041Schristos { 240*56bb7041Schristos PC = LOOPEND; 241*56bb7041Schristos } 242*56bb7041Schristos else 243*56bb7041Schristos { 244*56bb7041Schristos LOOPTOP = PC + 1; 245*56bb7041Schristos LOOPEND = PC + LOOP_JMPOFFS; 246*56bb7041Schristos LOOPCNT = OP2; 247*56bb7041Schristos LOOP_IN_PROGRESS = 1; 248*56bb7041Schristos PC++; 249*56bb7041Schristos }) 250