blob: c6d928aa754fd029a060d07b5a0f0c40d931d6d0 [file] [log] [blame]
/* Copyright 2016-2021 Free Software Foundation, Inc.
Contributed by Dimitar Dimitrov <dimitar@dinux.eu>
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 <http://www.gnu.org/licenses/>. */
/*
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++;
})