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