264 lines
5.8 KiB
Text
264 lines
5.8 KiB
Text
/* Copyright 2016-2022 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++;
|
|
})
|