/* Copyright 2016-2020 Free Software Foundation, Inc. Contributed by Dimitar Dimitrov This file is part of the PRU simulator. This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ /* PRU Instruction Set Architecture INSTRUCTION (NAME, SEMANTICS) */ INSTRUCTION (add, OP2 = (IO ? IMM8 : RS2); RD = RS1 + OP2; CARRY = (((uint64_t) RS1 + (uint64_t) OP2) >> RD_WIDTH) & 1; PC++) INSTRUCTION (adc, OP2 = (IO ? IMM8 : RS2); RD = RS1 + OP2 + CARRY; CARRY = (((uint64_t) RS1 + (uint64_t) OP2 + (uint64_t) CARRY) >> RD_WIDTH) & 1; PC++) INSTRUCTION (sub, OP2 = (IO ? IMM8 : RS2); RD = RS1 - OP2; CARRY = (((uint64_t) RS1 - (uint64_t) OP2) >> RD_WIDTH) & 1; PC++) INSTRUCTION (suc, OP2 = (IO ? IMM8 : RS2); RD = RS1 - OP2 - CARRY; CARRY = (((uint64_t) RS1 - (uint64_t) OP2 - (uint64_t) CARRY) >> RD_WIDTH) & 1; PC++) INSTRUCTION (rsb, OP2 = (IO ? IMM8 : RS2); RD = OP2 - RS1; CARRY = (((uint64_t) OP2 - (uint64_t) RS1) >> RD_WIDTH) & 1; PC++) INSTRUCTION (rsc, OP2 = (IO ? IMM8 : RS2); RD = OP2 - RS1 - CARRY; CARRY = (((uint64_t) OP2 - (uint64_t) RS1 - (uint64_t) CARRY) >> RD_WIDTH) & 1; PC++) INSTRUCTION (lsl, OP2 = (IO ? IMM8 : RS2); RD = RS1 << (OP2 & 0x1f); PC++) INSTRUCTION (lsr, OP2 = (IO ? IMM8 : RS2); RD = RS1 >> (OP2 & 0x1f); PC++) INSTRUCTION (and, OP2 = (IO ? IMM8 : RS2); RD = RS1 & OP2; PC++) INSTRUCTION (or, OP2 = (IO ? IMM8 : RS2); RD = RS1 | OP2; PC++) INSTRUCTION (xor, OP2 = (IO ? IMM8 : RS2); RD = RS1 ^ OP2; PC++) INSTRUCTION (not, RD = ~RS1; PC++) INSTRUCTION (min, OP2 = (IO ? IMM8 : RS2); RD = RS1 < OP2 ? RS1 : OP2; PC++) INSTRUCTION (max, OP2 = (IO ? IMM8 : RS2); RD = RS1 > OP2 ? RS1 : OP2; PC++) INSTRUCTION (clr, OP2 = (IO ? IMM8 : RS2); RD = RS1 & ~(1u << (OP2 & 0x1f)); PC++) INSTRUCTION (set, OP2 = (IO ? IMM8 : RS2); RD = RS1 | (1u << (OP2 & 0x1f)); PC++) INSTRUCTION (jmp, OP2 = (IO ? IMM16 : RS2); PC = OP2) INSTRUCTION (jal, OP2 = (IO ? IMM16 : RS2); RD = PC + 1; PC = OP2) INSTRUCTION (ldi, RD = IMM16; PC++) INSTRUCTION (halt, pru_sim_syscall (sd, cpu); PC++) INSTRUCTION (slp, if (!WAKEONSTATUS) { RAISE_SIGINT (sd); } else { PC++; }) INSTRUCTION (qbgt, OP2 = (IO ? IMM8 : RS2); PC = (OP2 > RS1) ? (PC + BROFF) : (PC + 1)) INSTRUCTION (qbge, OP2 = (IO ? IMM8 : RS2); PC = (OP2 >= RS1) ? (PC + BROFF) : (PC + 1)) INSTRUCTION (qblt, OP2 = (IO ? IMM8 : RS2); PC = (OP2 < RS1) ? (PC + BROFF) : (PC + 1)) INSTRUCTION (qble, OP2 = (IO ? IMM8 : RS2); PC = (OP2 <= RS1) ? (PC + BROFF) : (PC + 1)) INSTRUCTION (qbeq, OP2 = (IO ? IMM8 : RS2); PC = (OP2 == RS1) ? (PC + BROFF) : (PC + 1)) INSTRUCTION (qbne, OP2 = (IO ? IMM8 : RS2); PC = (OP2 != RS1) ? (PC + BROFF) : (PC + 1)) INSTRUCTION (qba, OP2 = (IO ? IMM8 : RS2); PC = PC + BROFF) INSTRUCTION (qbbs, OP2 = (IO ? IMM8 : RS2); PC = (RS1 & (1u << (OP2 & 0x1f))) ? (PC + BROFF) : (PC + 1)) INSTRUCTION (qbbc, OP2 = (IO ? IMM8 : RS2); PC = !(RS1 & (1u << (OP2 & 0x1f))) ? (PC + BROFF) : (PC + 1)) INSTRUCTION (lbbo, pru_dmem2reg (cpu, XBBO_BASEREG + (IO ? IMM8 : RS2), BURSTLEN, RD_REGN, RDB); PC++) INSTRUCTION (sbbo, pru_reg2dmem (cpu, XBBO_BASEREG + (IO ? IMM8 : RS2), BURSTLEN, RD_REGN, RDB); PC++) INSTRUCTION (lbco, pru_dmem2reg (cpu, CTABLE[CB] + (IO ? IMM8 : RS2), BURSTLEN, RD_REGN, RDB); PC++) INSTRUCTION (sbco, pru_reg2dmem (cpu, CTABLE[CB] + (IO ? IMM8 : RS2), BURSTLEN, RD_REGN, RDB); PC++) INSTRUCTION (xin, DO_XIN (XFR_WBA, RD_REGN, RDB, XFR_LENGTH); PC++) INSTRUCTION (xout, DO_XOUT (XFR_WBA, RD_REGN, RDB, XFR_LENGTH); PC++) INSTRUCTION (xchg, DO_XCHG (XFR_WBA, RD_REGN, RDB, XFR_LENGTH); PC++) INSTRUCTION (sxin, sim_io_eprintf (sd, "SXIN instruction not supported by sim\n"); RAISE_SIGILL (sd)) INSTRUCTION (sxout, sim_io_eprintf (sd, "SXOUT instruction not supported by sim\n"); RAISE_SIGILL (sd)) INSTRUCTION (sxchg, sim_io_eprintf (sd, "SXCHG instruction not supported by sim\n"); RAISE_SIGILL (sd)) INSTRUCTION (loop, OP2 = (IO ? IMM8 + 1 : RS2_w0); if (OP2 == 0) { PC = LOOPEND; } else { LOOPTOP = PC + 1; LOOPEND = PC + LOOP_JMPOFFS; LOOPCNT = OP2; LOOP_IN_PROGRESS = 1; PC++; }) INSTRUCTION (iloop, OP2 = (IO ? IMM8 + 1 : RS2_w0); if (OP2 == 0) { PC = LOOPEND; } else { LOOPTOP = PC + 1; LOOPEND = PC + LOOP_JMPOFFS; LOOPCNT = OP2; LOOP_IN_PROGRESS = 1; PC++; }) INSTRUCTION (lmbd, { int lmbd_i; OP2 = (IO ? IMM8 : RS2); for (lmbd_i = RS1_WIDTH - 1; lmbd_i >= 0; lmbd_i--) { if (!(((RS1 >> lmbd_i) ^ OP2) & 1)) break; } RD = (lmbd_i < 0) ? 32 : lmbd_i; PC++; })