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