Training courses

Kernel and Embedded Linux

Bootlin training courses

Embedded Linux, kernel,
Yocto Project, Buildroot, real-time,
graphics, boot time, debugging...

Bootlin logo

Elixir Cross Referencer

/* Copyright 2016-2020 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++;
	     })