Files
ghidra/Ghidra/Processors/NDS32/data/languages/nds32.sinc

1626 lines
57 KiB
Plaintext

### General ###
define endian=big;
define alignment=2;
define space ram type=ram_space size=4 wordsize=1 default;
define space register type=register_space size=4;
define space csreg type=ram_space size=2 wordsize=4;
@define CSR_REG_START "0x0000"
define register offset=0 size=4
[a0 a1 a2 a3 a4 a5 s0 s1 s2 s3 s4 s5 s6 s7 s8 ta t0 t1 t2 t3 t4 t5 t6 t7 t8 t9 p0 p1 fp gp lp sp];
define register offset=0x90 size=4
[pc mult_addr mult_inc];
define register offset=0x100 size=8
[d0 d1];
define register offset=0x100 size=4
[d0.hi d0.lo d1.hi d1.lo];
define register offset=0x200 size=4
[ itb lb lc le ifc_lp
fpcsr fpcfg
];
define register offset=0x1000 size=4
[ fs0 fs1 fs2 fs3 fs4 fs5 fs6 fs7
fs8 fs9 fs10 fs11 fs12 fs13 fs14 fs15
fs16 fs17 fs18 fs19 fs20 fs21 fs22 fs23
fs24 fs25 fs26 fs27 fs28 fs29 fs30 fs31
];
define register offset=0x1000 size=8
[ fd0 fd1 fd2 fd3 fd4 fd5 fd6 fd7
fd8 fd9 fd10 fd11 fd12 fd13 fd14 fd15
fd16 fd17 fd18 fd19 fd20 fd21 fd22 fd23
fd24 fd25 fd26 fd27 fd28 fd29 fd30 fd31
];
define csreg offset=0x0a9 size=4
[
ipc
];
define register offset=0x300 size=8 contextreg;
define context contextreg
counter = (22,26)
regNum = (27,31) # register for load/store multiple instructions
;
define token instr32(32)
OpSz = (31, 31)
Opc = (25, 30)
Rt = (20, 24)
Fst = (20, 24)
Fdt = (20, 24)
Rth = (21, 24)
Rtl = (21, 24)
Ra = (15, 19)
Fsa = (15, 19)
Fda = (15, 19)
Rb = (10, 14)
Fsb = (10, 14)
Fdb = (10, 14)
Rd = (5, 9)
Rs = (5, 9)
Sub5 = (0, 4)
Sub6 = (0, 5)
Sub7 = (0, 6)
Sub8 = (0, 7)
Sub3 = (7, 9)
fop4 = (6, 9)
cop4 = (0, 3)
f2op = (10, 14)
fcnd = (7, 9)
cmpe = (6, 6)
fbi = (7, 7)
cpn = (13, 14)
fsbi = (12, 12)
Imm8u = (7,14)
Imm5u = (10, 14)
Imm5s = (10, 14) signed
Br1t = (14, 14)
Br2t = (16, 19)
Alu2Mod = (6, 9)
Dtl = (22, 24)
Dt = (21, 21)
Dtlow = (21, 21)
Dthigh = (21, 21)
Dtr = (20, 20)
JIt = (24, 24)
Imm19s = (0, 18) signed
Imm18s = (0, 17) signed
Imm17s = (0, 16) signed
Imm16s = (0, 15) signed
Imm14s = (0, 13) signed
Imm15u = (0, 14)
Imm15s = (0, 14) signed
Imm20u = (0, 19)
Imm20s = (0, 19) signed
Imm24s = (0, 23) signed
Imm12s = (0, 11) signed
Imm11s = (8, 18) signed
Imm8s = (0, 7) signed
sv = (8, 9)
SrIdx = (10, 19)
Swid = (5, 19)
CctlZ = (11, 14)
CctlLevel = (10, 10)
CctlSub = (5, 9)
MsyncZ = (8, 19)
MsyncSub = (5, 7)
DtIt = (8, 9)
Jz = (6, 7)
JrHint = (5, 5)
ToggleL = (21, 24)
Toggle = (20, 20)
Usr = (15, 19)
Group = (10, 14)
DprefD = (24, 24)
DprefSub = (20, 23)
TlbopSub = (5, 9)
StandbyZ = (7, 9)
StandbySub = (5, 6)
GpSub1 = (19, 19)
GpSub2 = (18, 19)
GpSub3 = (17, 19)
sh = (5, 9)
Bxxc = (19, 19)
LsmwRa = (15, 19)
LsmwRb = (20, 24)
LsmwRb_ = (20, 24)
LsmwRe = (10, 14)
LsmwRe_ = (10, 14)
Enable4 = (6, 9)
Enable4_fp = (9, 9)
Enable4_gp = (8, 8)
Enable4_lp = (7, 7)
Enable4_sp = (6, 6)
LsmwLs = (5, 5)
LsmwBa = (4, 4)
LsmwId = (3, 3)
LsmwM = (2, 2)
LsmwSub = (0, 1)
;
attach variables [Rt Rs Ra Rb Rd LsmwRa LsmwRb LsmwRe] [
a0 a1 a2 a3 a4 a5 s0 s1 s2 s3 s4 s5 s6 s7 s8 ta t0 t1 t2 t3 t4 t5 t6 t7 t8 t9 p0 p1 fp gp lp sp
];
attach variables [Rtl] [
a0 a2 a4 s0 s2 s4 s6 s8 t0 t2 t4 t6 t8 p0 fp lp
];
attach variables [Rth] [
a1 a3 a5 s1 s3 s5 s7 ta t1 t3 t5 t7 t9 p1 gp sp
];
attach variables [Dt] [
d0 d1
];
attach variables [Dtlow] [
d0.lo d1.lo
];
attach variables [Dthigh] [
d0.hi d1.hi
];
attach variables [ Fst Fsa Fsb ]
[ fs0 fs1 fs2 fs3 fs4 fs5 fs6 fs7
fs8 fs9 fs10 fs11 fs12 fs13 fs14 fs15
fs16 fs17 fs18 fs19 fs20 fs21 fs22 fs23
fs24 fs25 fs26 fs27 fs28 fs29 fs30 fs31
];
attach variables [ Fdt Fda Fdb ]
[ fd0 fd1 fd2 fd3 fd4 fd5 fd6 fd7
fd8 fd9 fd10 fd11 fd12 fd13 fd14 fd15
fd16 fd17 fd18 fd19 fd20 fd21 fd22 fd23
fd24 fd25 fd26 fd27 fd28 fd29 fd30 fd31
];
@define I32 "(OpSz=0)"
@define LBGP "(Opc=0b010111)"
@define LWC "(Opc=0b011000)"
@define SWC "(Opc=0b011001)"
@define LDC "(Opc=0b011010)"
@define SDC "(Opc=0b011011)"
@define LSMW "(Opc=0b011101)"
@define MEM "(Opc=0b011100)"
@define HWGP "(Opc=0b011110)"
@define SBGP "(Opc=0b011111)"
@define ALU_1 "(Opc=0b100000)"
@define ALU_2 "(Opc=0b100001)"
@define JI "(Opc=0b100100)"
@define JREG "(Opc=0b100101)"
@define BR1 "(Opc=0b100110)"
@define BR2 "(Opc=0b100111)"
@define BR3 "(Opc=0b101101)"
@define MISC "(Opc=0b110010)"
@define COP "(Opc=0b110101)"
@define SIMD "(Opc=0b111000)"
@define ALU2Z "(Alu2Mod=0b0000)"
@define GPR "(Alu2Mod=0b0001)"
### ALU Instruction with Immediate ###
:addi Rt, Ra, Imm15s is $(I32) & Opc=0b101000 & Rt & Ra & Imm15s { Rt = Ra + Imm15s; }
:subri Rt, Ra, Imm15s is $(I32) & Opc=0b101001 & Rt & Ra & Imm15s { Rt = Imm15s - Ra; }
:andi Rt, Ra, Imm15u is $(I32) & Opc=0b101010 & Rt & Ra & Imm15u { Rt = Ra & Imm15u; }
:ori Rt, Ra, Imm15u is $(I32) & Opc=0b101100 & Rt & Ra & Imm15u { Rt = Ra | Imm15u; }
:xori Rt, Ra, Imm15u is $(I32) & Opc=0b101011 & Rt & Ra & Imm15u { Rt = Ra ^ Imm15u; }
:slti Rt, Ra, Imm15s is $(I32) & Opc=0b101110 & Rt & Ra & Imm15s { Rt = zext(Ra < Imm15s); }
:sltsi Rt, Ra, Imm15s is $(I32) & Opc=0b101111 & Rt & Ra & Imm15s { Rt = zext(Ra s< Imm15s); }
:movi Rt, Imm20s is $(I32) & Opc=0b100010 & Rt & Imm20s { Rt = Imm20s; }
:sethi Rt, Imm20u is $(I32) & Opc=0b100011 & Rt & Imm20u { Rt = Imm20u << 12;}
### ALU Instruction ###
:add Rt, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rd=0 & Sub5=0b00000 { Rt = Ra + Rb; }
:sub Rt, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rd=0 & Sub5=0b00001 { Rt = Ra - Rb; }
:and Rt, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rd=0 & Sub5=0b00010 { Rt = Ra & Rb; }
:xor Rt, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rd=0 & Sub5=0b00011 { Rt = Ra ^ Rb; }
:or Rt, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rd=0 & Sub5=0b00100 { Rt = Ra | Rb; }
:nor Rt, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rd=0 & Sub5=0b00101 { Rt = ~(Ra | Rb); }
:slt Rt, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rd=0 & Sub5=0b00110 { Rt = zext(Ra < Rb); }
:slts Rt, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rd=0 & Sub5=0b00111 { Rt = zext(Ra s< Rb); }
:sva Rt, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rd=0 & Sub5=0b11000 { Rt = zext(scarry(Ra, Rb)); }
:svs Rt, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rd=0 & Sub5=0b11001 { Rt = zext(sborrow(Ra, Rb)); }
:seb Rt, Ra is $(I32) & $(ALU_1) & Rt & Ra & Rb=0b00000 & Rd=0 & Sub5=0b10000 { local tmp = Ra; Rt = sext(tmp:1); }
:seh Rt, Ra is $(I32) & $(ALU_1) & Rt & Ra & Rb=0b00000 & Rd=0 & Sub5=0b10001 { local tmp = Ra; Rt = sext(tmp:2); }
:zeb Rt, Ra is $(I32) & Opc=0b101010 & Rt & Ra & Imm15u=0xff { local tmp = Ra; Rt = zext(tmp:1); }
:zeh Rt, Ra is $(I32) & $(ALU_1) & Rt & Ra & Rb=0b00000 & Rd=0 & Sub5=0b10011 { local tmp = Ra; Rt = zext(tmp:2); }
:wsbh Rt, Ra is $(I32) & $(ALU_1) & Rt & Ra & Rb=0b00000 & Rd=0 & Sub5=0b10100
{
Rt = ((Ra & 0x000000ff) << 8)
| ((Ra & 0x0000ff00) >> 8)
| ((Ra & 0x00ff0000) << 8)
| ((Ra & 0xff000000) >> 8);
}
### Shifter Instruction ###
:slli Rt, Ra, Imm5u is $(I32) & $(ALU_1) & Rt & Ra & Imm5u & Rd=0 & Sub5=0b01000 { Rt = Ra << Imm5u; }
:srli Rt, Ra, Imm5u is $(I32) & $(ALU_1) & Rt & Ra & Imm5u & Rd=0 & Sub5=0b01001 { Rt = Ra >> Imm5u; }
:srai Rt, Ra, Imm5u is $(I32) & $(ALU_1) & Rt & Ra & Imm5u & Rd=0 & Sub5=0b01010 { Rt = Ra s>> Imm5u; }
:rotri Rt, Ra, Imm5u is $(I32) & $(ALU_1) & Rt & Ra & Imm5u & Rd=0 & Sub5=0b01011 { Rt = (Ra >> Imm5u) | (Ra << (32 - Imm5u)); }
:sll Rt, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rd=0 & Sub5=0b01100 { tmp:4 = Rb & 0b11111; Rt = Ra << tmp; }
:srl Rt, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rd=0 & Sub5=0b01101 { tmp:4 = Rb & 0b11111; Rt = Ra >> tmp; }
:sra Rt, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rd=0 & Sub5=0b01110 { tmp:4 = Rb & 0b11111; Rt = Ra s>> tmp; }
:rotr Rt, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rd=0 & Sub5=0b01111 { tmp:4 = Rb & 0b11111; Rt = (Ra >> tmp) | (Ra << (32 - tmp)); }
### Multiply Instruction ###
:mul Rt, Ra, Rb is $(I32) & $(ALU_2) & Rt & Ra & Rb & $(ALU2Z) & Sub6=0b100100 { Rt = Ra * Rb; }
:mults64 Dt, Ra, Rb is $(I32) & $(ALU_2) & Dtl=0 & Dt & Dtr=0 & Ra & Rb & $(ALU2Z) & Sub6=0b101000 { Dt = sext(Ra) * sext(Rb); }
:mult64 Dt, Ra, Rb is $(I32) & $(ALU_2) & Dtl=0 & Dt & Dtr=0 & Ra & Rb & $(ALU2Z) & Sub6=0b101001 { Dt = zext(Ra) * zext(Rb); }
:madds64 Dt, Ra, Rb is $(I32) & $(ALU_2) & Dtl=0 & Dt & Dtr=0 & Ra & Rb & $(ALU2Z) & Sub6=0b101010 { Dt = Dt + (sext(Ra) * sext(Rb)); }
:madd64 Dt, Ra, Rb is $(I32) & $(ALU_2) & Dtl=0 & Dt & Dtr=0 & Ra & Rb & $(ALU2Z) & Sub6=0b101011 { Dt = Dt + (zext(Ra) * zext(Rb)); }
:msubs64 Dt, Ra, Rb is $(I32) & $(ALU_2) & Dtl=0 & Dt & Dtr=0 & Ra & Rb & $(ALU2Z) & Sub6=0b101100 { Dt = Dt - (sext(Ra) * sext(Rb)); }
:msub64 Dt, Ra, Rb is $(I32) & $(ALU_2) & Dtl=0 & Dt & Dtr=0 & Ra & Rb & $(ALU2Z) & Sub6=0b101101 { Dt = Dt - (zext(Ra) * zext(Rb)); }
:mult32 Dtlow, Ra, Rb is $(I32) & $(ALU_2) & Dtl=0 & Dtlow & Dtr=0 & Ra & Rb & $(ALU2Z) & Sub6=0b110001 { Dtlow = Ra * Rb; }
:madd32 Dtlow, Ra, Rb is $(I32) & $(ALU_2) & Dtl=0 & Dtlow & Dtr=0 & Ra & Rb & $(ALU2Z) & Sub6=0b110011 { Dtlow = Dtlow + (Ra * Rb); }
:msub32 Dtlow, Ra, Rb is $(I32) & $(ALU_2) & Dtl=0 & Dtlow & Dtr=0 & Ra & Rb & $(ALU2Z) & Sub6=0b110101 { Dtlow = Dtlow - (Ra * Rb); }
# Group 0
UsrName: d0.lo is Group=0 & Usr=0 & d0.lo { export d0.lo; }
UsrName: d0.hi is Group=0 & Usr=1 & d0.hi { export d0.hi; }
UsrName: d1.lo is Group=0 & Usr=2 & d1.lo { export d1.lo; }
UsrName: d1.hi is Group=0 & Usr=3 & d1.hi { export d1.hi; }
UsrName: lb is Group=0 & Usr=25 & lb { export lb; }
UsrName: le is Group=0 & Usr=26 & le { export le; }
UsrName: lc is Group=0 & Usr=27 & lc { export lc; }
UsrName: itb is Group=0 & Usr=28 & itb { export itb; }
UsrName: ifc_lp is Group=0 & Usr=29 & ifc_lp { export ifc_lp; }
#UsrName: pc is Group=0 & Usr=31 & pc { export pc; } # handled separately
# Group 1
UsrName: "dma_cfg" is Group=1 & Usr=0 { tmp:2 = 0x280; export *[csreg]:4 tmp; }
UsrName: "dma_gcsw" is Group=1 & Usr=1 { tmp:2 = 0x288; export *[csreg]:4 tmp; }
UsrName: "dma_chnsel" is Group=1 & Usr=2 { tmp:2 = 0x290; export *[csreg]:4 tmp; }
UsrName: "dma_act" is Group=1 & Usr=3 { tmp:2 = 0x298; export *[csreg]:4 tmp; }
UsrName: "dma_setup" is Group=1 & Usr=4 { tmp:2 = 0x2a0; export *[csreg]:4 tmp; }
UsrName: "dma_isaddr" is Group=1 & Usr=5 { tmp:2 = 0x2a8; export *[csreg]:4 tmp; }
UsrName: "dma_esaddr" is Group=1 & Usr=6 { tmp:2 = 0x2b0; export *[csreg]:4 tmp; }
UsrName: "dma_tcnt" is Group=1 & Usr=7 { tmp:2 = 0x2b8; export *[csreg]:4 tmp; }
UsrName: "dma_status" is Group=1 & Usr=8 { tmp:2 = 0x2c0; export *[csreg]:4 tmp; }
UsrName: "dma_2dset" is Group=1 & Usr=9 { tmp:2 = 0x2c8; export *[csreg]:4 tmp; }
UsrName: "dma_rcnt" is Group=1 & Usr=23 { tmp:2 = 0x2b9; export *[csreg]:4 tmp; }
UsrName: "dma_hstatus" is Group=1 & Usr=24 { tmp:2 = 0x2c1; export *[csreg]:4 tmp; }
UsrName: "dma_2dsctl" is Group=1 & Usr=25 { tmp:2 = 0x2c9; export *[csreg]:4 tmp; }
# Group 2
UsrName: "pfmc0" is Group=2 & Usr=0 { tmp:2 = 0x200; export *[csreg]:4 tmp; }
UsrName: "pfmc1" is Group=2 & Usr=1 { tmp:2 = 0x201; export *[csreg]:4 tmp; }
UsrName: "pfmc2" is Group=2 & Usr=2 { tmp:2 = 0x202; export *[csreg]:4 tmp; }
UsrName: "pfm_ctl" is Group=2 & Usr=4 { tmp:2 = 0x208; export *[csreg]:4 tmp; }
:mfusr Rt, UsrName is $(I32) & $(ALU_2) & Rt & UsrName & $(ALU2Z) & Sub6=0b100000 { Rt = UsrName; }
:mfusr Rt, pc is $(I32) & $(ALU_2) & Rt & Group=0 & Usr=0b11111 & $(ALU2Z) & Sub6=0b100000 & pc { Rt = inst_next; }
:mtusr Rt, UsrName is $(I32) & $(ALU_2) & Rt & UsrName & $(ALU2Z) & Sub6=0b100001 { UsrName = Rt; }
:mtusr Rt, pc is $(I32) & $(ALU_2) & Rt & Group=0 & Usr=0b11111 & $(ALU2Z) & Sub6=0b100001 & pc { pc = Rt; goto[pc]; } # Not sure this works correctly
### Divide Instructions ###
:div Dt, Ra, Rb is $(I32) & $(ALU_2) & Dtl=0 & Dt & Dtlow & Dthigh & Dtr=0 & Ra & Rb & $(ALU2Z) & Sub6=0b101111 { Dtlow = Ra / Rb; Dthigh = Ra % Rb; }
:divs Dt, Ra, Rb is $(I32) & $(ALU_2) & Dtl=0 & Dt & Dtlow & Dthigh & Dtr=0 & Ra & Rb & $(ALU2Z) & Sub6=0b101110 { Dtlow = Ra s/ Rb; Dthigh = Ra s% Rb; }
### Load / Store Instruction (immediate) ###
ByteOffset: off is Imm15s [ off = Imm15s << 0; ] { export *[const]:4 off; }
HalfOffset: off is Imm15s [ off = Imm15s << 1; ] { export *[const]:4 off; }
WordOffset: off is Imm15s [ off = Imm15s << 2; ] { export *[const]:4 off; }
AddrByteRaImm15s: [Ra + ByteOffset] is Ra & ByteOffset { addr:4 = Ra + ByteOffset; export addr; }
AddrHalfRaImm15s: [Ra + HalfOffset] is Ra & HalfOffset { addr:4 = Ra + HalfOffset; export addr; }
AddrWordRaImm15s: [Ra + WordOffset] is Ra & WordOffset { addr:4 = Ra + WordOffset; export addr; }
:lwi Rt, AddrWordRaImm15s is $(I32) & Opc=0b000010 & Rt & AddrWordRaImm15s { Rt = *AddrWordRaImm15s; }
:lhi Rt, AddrHalfRaImm15s is $(I32) & Opc=0b000001 & Rt & AddrHalfRaImm15s { local tmp:2 = *AddrHalfRaImm15s; Rt = zext(tmp); }
:lhsi Rt, AddrHalfRaImm15s is $(I32) & Opc=0b010001 & Rt & AddrHalfRaImm15s { local tmp:2 = *AddrHalfRaImm15s; Rt = sext(tmp); }
:lbi Rt, AddrByteRaImm15s is $(I32) & Opc=0b000000 & Rt & AddrByteRaImm15s { local tmp:1 = *AddrByteRaImm15s; Rt = zext(tmp); }
:lbsi Rt, AddrByteRaImm15s is $(I32) & Opc=0b010000 & Rt & AddrByteRaImm15s { local tmp:1 = *AddrByteRaImm15s; Rt = sext(tmp); }
:swi Rt, AddrWordRaImm15s is $(I32) & Opc=0b001010 & Rt & AddrWordRaImm15s { *AddrWordRaImm15s = Rt; }
:shi Rt, AddrHalfRaImm15s is $(I32) & Opc=0b001001 & Rt & AddrHalfRaImm15s { local tmp = Rt; *AddrHalfRaImm15s = tmp:2; }
:sbi Rt, AddrByteRaImm15s is $(I32) & Opc=0b001000 & Rt & AddrByteRaImm15s { local tmp = Rt; *AddrByteRaImm15s = tmp:1; }
### Load / Store Instruction (immediate, postincr) ###
:lwi.bi Rt, [Ra], WordOffset is $(I32) & Opc=0b000110 & Rt & Ra & WordOffset { Rt = *Ra; Ra = Ra + WordOffset; }
:lhi.bi Rt, [Ra], HalfOffset is $(I32) & Opc=0b000101 & Rt & Ra & HalfOffset { local tmp:2 = *Ra; Rt = zext(tmp); Ra = Ra + HalfOffset; }
:lhsi.bi Rt, [Ra], HalfOffset is $(I32) & Opc=0b010101 & Rt & Ra & HalfOffset { local tmp:2 = *Ra; Rt = sext(tmp); Ra = Ra + HalfOffset; }
:lbi.bi Rt, [Ra], ByteOffset is $(I32) & Opc=0b000100 & Rt & Ra & ByteOffset { local tmp:1 = *Ra; Rt = zext(tmp); Ra = Ra + ByteOffset; }
:lbsi.bi Rt, [Ra], ByteOffset is $(I32) & Opc=0b010100 & Rt & Ra & ByteOffset { local tmp:1 = *Ra; Rt = sext(tmp); Ra = Ra + ByteOffset; }
:swi.bi Rt, [Ra], WordOffset is $(I32) & Opc=0b001110 & Rt & Ra & WordOffset { *Ra = Rt; Ra = Ra + WordOffset; }
:shi.bi Rt, [Ra], HalfOffset is $(I32) & Opc=0b001101 & Rt & Ra & HalfOffset { local tmp = Rt; *Ra = tmp:2; Ra = Ra + HalfOffset; }
:sbi.bi Rt, [Ra], ByteOffset is $(I32) & Opc=0b001100 & Rt & Ra & ByteOffset { local tmp = Rt; *Ra = tmp:1; Ra = Ra + ByteOffset; }
### Load / Store Instruction (register) ###
OffsetRbsv: (Rb "<<" sv) is Rb & sv { off:4 = Rb << sv; export off; }
AddrRaRbsv: [Ra + OffsetRbsv] is Ra & OffsetRbsv { addr:4 = Ra + OffsetRbsv; export addr; }
:lw Rt, AddrRaRbsv is $(I32) & $(MEM) & Rt & AddrRaRbsv & Sub8=0b00000010 { Rt = *AddrRaRbsv; }
:lh Rt, AddrRaRbsv is $(I32) & $(MEM) & Rt & AddrRaRbsv & Sub8=0b00000001 { local tmp:2 = *AddrRaRbsv; Rt = zext(tmp); }
:lhs Rt, AddrRaRbsv is $(I32) & $(MEM) & Rt & AddrRaRbsv & Sub8=0b00010001 { local tmp:2 = *AddrRaRbsv; Rt = sext(tmp); }
:lb Rt, AddrRaRbsv is $(I32) & $(MEM) & Rt & AddrRaRbsv & Sub8=0b00000000 { local tmp:1 = *AddrRaRbsv; Rt = zext(tmp); }
:lbs Rt, AddrRaRbsv is $(I32) & $(MEM) & Rt & AddrRaRbsv & Sub8=0b00010000 { local tmp:1 = *AddrRaRbsv; Rt = sext(tmp); }
:sw Rt, AddrRaRbsv is $(I32) & $(MEM) & Rt & AddrRaRbsv & Sub8=0b00001010 { *AddrRaRbsv = Rt; }
:sh Rt, AddrRaRbsv is $(I32) & $(MEM) & Rt & AddrRaRbsv & Sub8=0b00001001 { local tmp = Rt; *AddrRaRbsv = tmp:2; }
:sb Rt, AddrRaRbsv is $(I32) & $(MEM) & Rt & AddrRaRbsv & Sub8=0b00001000 { local tmp = Rt; *AddrRaRbsv = tmp:1; }
### Load / Store Instruction (register, postincr) ###
:lw.bi Rt, [Ra], OffsetRbsv is $(I32) & $(MEM) & Rt & Ra & OffsetRbsv & Sub8=0b00000110 { Rt = *Ra; Ra = Ra + OffsetRbsv; }
:lh.bi Rt, [Ra], OffsetRbsv is $(I32) & $(MEM) & Rt & Ra & OffsetRbsv & Sub8=0b00000101 { local tmp:2 = *Ra; Rt = zext(tmp); Ra = Ra + OffsetRbsv; }
:lhs.bi Rt, [Ra], OffsetRbsv is $(I32) & $(MEM) & Rt & Ra & OffsetRbsv & Sub8=0b00010101 { local tmp:2 = *Ra; Rt = sext(tmp); Ra = Ra + OffsetRbsv; }
:lb.bi Rt, [Ra], OffsetRbsv is $(I32) & $(MEM) & Rt & Ra & OffsetRbsv & Sub8=0b00000100 { local tmp:1 = *Ra; Rt = zext(tmp); Ra = Ra + OffsetRbsv; }
:lbs.bi Rt, [Ra], OffsetRbsv is $(I32) & $(MEM) & Rt & Ra & OffsetRbsv & Sub8=0b00010100 { local tmp:1 = *Ra; Rt = sext(tmp); Ra = Ra + OffsetRbsv; }
:sw.bi Rt, [Ra], OffsetRbsv is $(I32) & $(MEM) & Rt & Ra & OffsetRbsv & Sub8=0b00001110 { *Ra = Rt; Ra = Ra + OffsetRbsv; }
:sh.bi Rt, [Ra], OffsetRbsv is $(I32) & $(MEM) & Rt & Ra & OffsetRbsv & Sub8=0b00001101 { local tmp = Rt; *Ra = tmp:2; Ra = Ra + OffsetRbsv; }
:sb.bi Rt, [Ra], OffsetRbsv is $(I32) & $(MEM) & Rt & Ra & OffsetRbsv & Sub8=0b00001100 { local tmp = Rt; *Ra = tmp:1; Ra = Ra + OffsetRbsv; }
### Load / Store Multiple Word Instruction ###
@include "lsmw.sinc"
LsmwBa_: "b" is LsmwBa=0 { }
LsmwBa_: "a" is LsmwBa=1 { }
LsmwId_: "i" is LsmwId=0 { }
LsmwId_: "d" is LsmwId=1 { }
LsmwM_: "" is LsmwRa & LsmwM=0 { }
LsmwM_: "m" is LsmwRa & LsmwM=1 { LsmwRa = mult_addr; }
:lmw.^LsmwBa_^LsmwId_^LsmwM_ LsmwRb, [LsmwRa], LsmwRe, Enable4 is ($(I32) & $(LSMW) & LsmwRb & LsmwRa & LsmwRe & Enable4 & LsmwLs=0 & LsmwBa_ & LsmwId_ & LsmwM_ & LsmwSub=0b00) ... & Lmw.regs
{
mult_addr = LsmwRa;
build Lmw.regs;
build LsmwM_;
}
:smw.^LsmwBa_^LsmwId_^LsmwM_ LsmwRb, [LsmwRa], LsmwRe, Enable4 is ($(I32) & $(LSMW) & LsmwRb & LsmwRa & LsmwRe & Enable4 & LsmwLs=1 & LsmwBa_ & LsmwId_ & LsmwM_ & LsmwSub=0b00) ... & Smw.regs
{
mult_addr = LsmwRa;
build Smw.regs;
build LsmwM_;
}
### Load / Store Instruction for Atomic Updates ###
:llw Rt, AddrRaRbsv is $(I32) & $(MEM) & Rt & AddrRaRbsv & Sub8=0b00011000 { Rt = *AddrRaRbsv; }
:scw Rt, AddrRaRbsv is $(I32) & $(MEM) & Rt & AddrRaRbsv & Sub8=0b00011001 { *AddrRaRbsv = Rt; }
### Load / Store Instructions with User-mode Privilege ###
# TODO : special constraint (user-mode address translation)
:lwup Rt, AddrRaRbsv is $(I32) & $(MEM) & Rt & AddrRaRbsv & Sub8=0b00100010 { Rt = *AddrRaRbsv; }
:swup Rt, AddrRaRbsv is $(I32) & $(MEM) & Rt & AddrRaRbsv & Sub8=0b00101010 { *AddrRaRbsv = Rt; }
### Jump Instruction ###
Rel24: addr is Imm24s [ addr = inst_start + (Imm24s << 1); ] { export *:4 addr; }
:j Rel24 is $(I32) & $(JI) & JIt=0 & Rel24 { goto Rel24; }
:jal Rel24 is $(I32) & $(JI) & JIt=1 & Rel24 { lp = inst_next; call Rel24; }
:jr Rb is $(I32) & $(JREG) & Rt=0 & Ra=0 & Rb & DtIt=0b00 & Jz=0 & JrHint=0 & Sub5=0b00000 { goto [Rb]; }
:ret Rb is $(I32) & $(JREG) & Rt=0 & Ra=0 & Rb & DtIt=0b00 & Jz=0 & JrHint=1 & Sub5=0b00000 { return [Rb]; }
:jral Rt,Rb is $(I32) & $(JREG) & Rt & Ra=0 & Rb & DtIt=0b00 & Jz=0 & JrHint=0 & Sub5=0b00001 { Rt = inst_next; call [Rb]; }
### Branch Instruction ###
Rel14: addr is Imm14s [ addr = inst_start + (Imm14s << 1); ] { export *:4 addr; }
Rel16: addr is Imm16s [ addr = inst_start + (Imm16s << 1); ] { export *:4 addr; }
:beq Rt, Ra, Rel14 is $(I32) & $(BR1) & Rt & Ra & Br1t=0 & Rel14 { if(Rt == Ra) goto Rel14; }
:bne Rt, Ra, Rel14 is $(I32) & $(BR1) & Rt & Ra & Br1t=1 & Rel14 { if(Rt != Ra) goto Rel14; }
:beqz Rt, Rel16 is $(I32) & $(BR2) & Rt & Br2t=0b0010 & Rel16 { if(Rt == 0) goto Rel16; }
:bnez Rt, Rel16 is $(I32) & $(BR2) & Rt & Br2t=0b0011 & Rel16 { if(Rt != 0) goto Rel16; }
:bgez Rt, Rel16 is $(I32) & $(BR2) & Rt & Br2t=0b0100 & Rel16 { if(Rt s>= 0) goto Rel16; }
:bltz Rt, Rel16 is $(I32) & $(BR2) & Rt & Br2t=0b0101 & Rel16 { if(Rt s< 0) goto Rel16; }
:bgtz Rt, Rel16 is $(I32) & $(BR2) & Rt & Br2t=0b0110 & Rel16 { if(Rt s> 0) goto Rel16; }
:blez Rt, Rel16 is $(I32) & $(BR2) & Rt & Br2t=0b0111 & Rel16 { if(Rt s<= 0) goto Rel16; }
### Branch with link Instruction ###
:bgezal Rt, Rel16 is $(I32) & $(BR2) & Rt & Br2t=0b1100 & Rel16
{
lp = inst_next;
if(Rt s>= 0) goto <end>;
call Rel16;
<end>
}
:bltzal Rt, Rel16 is $(I32) & $(BR2) & Rt & Br2t=0b1101 & Rel16
{
lp = inst_next;
if(Rt s< 0) goto <end>;
call Rel16;
<end>
}
### Read / Write System Registers ###
# TODO : special instruction, do we create the system registers ?
define pcodeop mfsr;
define pcodeop mtsr;
csr: csr_reg is SrIdx [ csr_reg = $(CSR_REG_START) + SrIdx; ] { export *[csreg]:4 csr_reg; }
:mfsr Rt, csr is $(I32) & $(MISC) & Rt & csr & Rd=0 & Sub5=0b00010 { Rt = csr; }
:mtsr Rt, csr is $(I32) & $(MISC) & Rt & csr & Rd=0 & Sub5=0b00011 { csr = Rt; }
### Jump Register with System Register Update ###
# TODO : special constraint (address translation off)
:jr.itoff Rb is $(I32) & $(JREG) & Rt=0 & Ra=0 & Rb & DtIt=0b01 & Jz=0 & JrHint=0 & Sub5=0b00000 { goto [Rb]; }
:jr.toff Rb is $(I32) & $(JREG) & Rt=0 & Ra=0 & Rb & DtIt=0b11 & Jz=0 & JrHint=0 & Sub5=0b00000 { goto [Rb]; }
:jral.iton Rt,Rb is $(I32) & $(JREG) & Rt & Ra=0 & Rb & DtIt=0b01 & Jz=0 & JrHint=0 & Sub5=0b00001 { Rt = inst_next; call [Rb]; }
:jral.ton Rt,Rb is $(I32) & $(JREG) & Rt & Ra=0 & Rb & DtIt=0b11 & Jz=0 & JrHint=0 & Sub5=0b00001 { Rt = inst_next; call [Rb]; }
### MMU Instruction ###
define pcodeop TLB_TargetRead;
define pcodeop TLB_TargetWrite;
define pcodeop TLB_RWrite;
define pcodeop TLB_RWriteLock;
define pcodeop TLB_Unlock;
define pcodeop TLB_Probe;
define pcodeop TLB_Invalidate;
define pcodeop TLB_FlushAll;
:tlbop Ra,"TargetRead" is $(I32) & $(MISC) & Rt & Ra & Rb=0 & TlbopSub=0 & Sub5=0b01110 { TLB_TargetRead(Ra:4); }
:tlbop Ra,"TargetWrite" is $(I32) & $(MISC) & Rt & Ra & Rb=0 & TlbopSub=1 & Sub5=0b01110 { TLB_TargetWrite(Ra:4); }
:tlbop Ra,"RWrite" is $(I32) & $(MISC) & Rt & Ra & Rb=0 & TlbopSub=2 & Sub5=0b01110 { TLB_RWrite(Ra:4); }
:tlbop Ra,"RWriteLock" is $(I32) & $(MISC) & Rt & Ra & Rb=0 & TlbopSub=3 & Sub5=0b01110 { TLB_RWriteLock(Ra:4); }
:tlbop Ra,"Unlock" is $(I32) & $(MISC) & Rt & Ra & Rb=0 & TlbopSub=4 & Sub5=0b01110 { TLB_Unlock(Ra:4); }
:tlbop Rt,Ra,"Probe" is $(I32) & $(MISC) & Rt & Ra & Rb=0 & TlbopSub=5 & Sub5=0b01110 { TLB_Probe(Rt:4, Ra:4); }
:tlbop Ra,"Invalidate" is $(I32) & $(MISC) & Rt & Ra & Rb=0 & TlbopSub=6 & Sub5=0b01110 { TLB_Invalidate(Ra:4); }
:tlbop "FlushAll" is $(I32) & $(MISC) & Rt & Ra & Rb=0 & TlbopSub=7 & Sub5=0b01110 { TLB_FlushAll(); }
### Conditional Move ###
:cmovz Rt, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rd=0 & Sub5=0b11010
{
if(Rb != 0) goto <end>;
Rt = Ra;
<end>
}
:cmovn Rt, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rd=0 & Sub5=0b11011
{
if(Rb == 0) goto <end>;
Rt = Ra;
<end>
}
### Synchronization Instruction ###
# TODO : special function, and subfunctions
define pcodeop msync;
define pcodeop isync;
:msync MsyncSub is $(I32) & $(MISC) & Rt=0 & MsyncZ=0 & MsyncSub & Sub5=0b01100 { msync(MsyncSub:1); }
:isync Rt is $(I32) & $(MISC) & Rt & Ra=0 & Rb=0 & Rd=0 & Sub5=0b01101 { isync(Rt:4); }
### Prefetch Instruction ###
define pcodeop dpref;
OffsetRbsv2: (Rb "<<" sv) is Rb & sv { off:4 = Rb << (sv + 1); export off; }
AddrRaRbsv2: [Ra + OffsetRbsv2] is Ra & OffsetRbsv2 { addr:4 = Ra + OffsetRbsv2; export addr; }
:dpref DprefSub, AddrRaRbsv2 is $(I32) & $(MEM) & DprefD=0 & DprefSub & AddrRaRbsv2 & Sub8=0b00010011 {
dpref(DprefSub:1, AddrRaRbsv2:4);
}
DprefD_: "w" is DprefD=0 { }
DprefD_: "d" is DprefD=1 { }
DprefiAddr: [Ra + Offset] is DprefD=0 & Ra & Imm15s [ Offset = Imm15s << 2; ] { export *[const]:4 Offset; }
DprefiAddr: [Ra + Offset] is DprefD=1 & Ra & Imm15s [ Offset = Imm15s << 3; ] { export *[const]:4 Offset; }
:dprefi.^DprefD_ DprefSub, DprefiAddr is $(I32) & Opc=0b010011 & DprefD_ & DprefSub & DprefiAddr {
dpref(DprefSub:1, DprefiAddr:4);
}
### NOP Instruction ###
:nop is $(I32) & $(ALU_1) & Rt=0 & Ra=0 & Imm5u=0 & Rd=0 & Sub5=0b01001 { }
### Serialization Instruction ###
define pcodeop dsb;
define pcodeop isb;
:dsb is $(I32) & $(MISC) & Rt=0 & Ra=0 & Rb=0 & Rd=0 & Sub5=0b01000 { dsb(); }
:isb is $(I32) & $(MISC) & Rt=0 & Ra=0 & Rb=0 & Rd=0 & Sub5=0b01001 { isb(); }
### Exception Generation Instruction ###
define pcodeop break;
define pcodeop syscall;
define pcodeop trap;
:break Swid is $(I32) & $(MISC) & Rt=0 & Swid & Sub5=0b01010 { break(Swid:4); }
:syscall Swid is $(I32) & $(MISC) & Rt=0 & Swid & Sub5=0b01011 { syscall(Swid:4); }
:trap Swid is $(I32) & $(MISC) & Rt=0 & Swid & Sub5=0b00101 { trap(Swid:4); }
:teqz Rt, Swid is $(I32) & $(MISC) & Rt & Swid & Sub5=0b00110
{
if(Rt != 0) goto <end>;
trap(Swid:4);
<end>
}
:tnez Rt, Swid is $(I32) & $(MISC) & Rt & Swid & Sub5=0b00111
{
if(Rt == 0) goto <end>;
trap(Swid:4);
<end>
}
### Special Return Instruction ###
:iret is $(I32) & $(MISC) & Rt=0 & Ra=0 & Rb=0 & Rd=0 & Sub5=0b00100 { return [ipc]; }
# TODO : special constraint (address translation off)
:ret.itoff Rb is $(I32) & $(JREG) & Rt=0 & Ra=0 & Rb & DtIt=0b01 & Jz=0 & JrHint=1 & Sub5=0b00000 { return [Rb]; }
:ret.toff Rb is $(I32) & $(JREG) & Rt=0 & Ra=0 & Rb & DtIt=0b11 & Jz=0 & JrHint=1 & Sub5=0b00000 { return [Rb]; }
### Cache Control Instruction ###
# TODO : special function, with subfunctions
define pcodeop cctl;
:cctl Rt, Ra, CctlLevel, CctlSub is $(I32) & $(MISC) & Rt & Ra & CctlZ=0 & CctlLevel & CctlSub & Sub5=0b00001 { cctl(Rt:4, Ra:4, CctlLevel:1, CctlSub:1); }
# Miscellaneous Instructions (Baseline)
# TODO : special function. Not sure if we use context or registers for this.
define pcodeop setgie;
SetgieEN: "d" is Toggle=0 { setgie(0:1); }
SetgieEN: "e" is Toggle=1 { setgie(1:1); }
:setgie.^SetgieEN is $(I32) & $(MISC) & ToggleL=0 & SetgieEN & SrIdx=0b0010000000 & Rd=0b00010 & Sub5=0b00011 { }
define pcodeop setend;
SetendBE: "l" is Toggle=0 { setend(0:1); }
SetendBE: "b" is Toggle=1 { setend(1:1); }
:setend.^SetendBE is $(I32) & $(MISC) & ToggleL=0 & SetendBE & SrIdx=0b0010000000 & Rd=0b00001 & Sub5=0b00011 { }
:standby StandbySub is $(I32) & $(MISC) & Rt=0 & Ra=0 & Rb=0 & StandbyZ=0 & StandbySub & Sub5=0b00000 { goto inst_start; }
### 32-bit Baseline V2 instructions ###
### ALU Instructions ###
:addi.gp is $(I32) & $(SBGP) & Rt & GpSub1=0b1 & Imm19s { Rt = gp + Imm19s; }
### Multiply and Divide Instructions (V2) ###
:mulr64 Rt, Ra, Rb is $(I32) & $(ALU_2) & Rt & Ra & Rb & $(GPR) & Sub6=0b101001 & Rtl & Rth
{
res:8 = zext(Ra) * zext(Rb);
Rtl = res[32,32];
Rth = res[0,32];
}
:mulsr64 Rt, Ra, Rb is $(I32) & $(ALU_2) & Rt & Ra & Rb & $(GPR) & Sub6=0b101000 & Rtl & Rth
{
res:8 = sext(Ra) * sext(Rb);
Rtl = res[32,32];
Rth = res[0,32];
}
:maddr32 Rt, Ra, Rb is $(I32) & $(ALU_2) & Rt & Ra & Rb & $(GPR) & Sub6=0b110011 { Rt = Rt + (Ra * Rb); }
:msubr32 Rt, Ra, Rb is $(I32) & $(ALU_2) & Rt & Ra & Rb & $(GPR) & Sub6=0b110101 { Rt = Rt - (Ra * Rb); }
:divr Rt, Rs, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rs & Sub5=0b10111 { local div = Ra / Rb; local mod = Ra % Rb; Rs = mod; Rt = div; }
:divsr Rt, Rs, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rs & Sub5=0b10110 { local div = Ra s/ Rb; local mod = Ra s% Rb; Rs = mod; Rt = div; }
### Load/Store Instructions ###
GpByteAddress: [+ off] is Imm19s [ off = Imm19s << 0; ] { addr:4 = gp + off; export addr; }
GpHalfAddress: [+ off] is Imm18s [ off = Imm18s << 1; ] { addr:4 = gp + off; export addr; }
GpWordAddress: [+ off] is Imm17s [ off = Imm17s << 2; ] { addr:4 = gp + off; export addr; }
:lbi.gp Rt, GpByteAddress is $(I32) & $(LBGP) & Rt & GpSub1=0b0 & GpByteAddress { local tmp:1 = *GpByteAddress; Rt = zext(tmp); }
:lbsi.gp Rt, GpByteAddress is $(I32) & $(LBGP) & Rt & GpSub1=0b1 & GpByteAddress { local tmp:1 = *GpByteAddress; Rt = sext(tmp); }
:lhi.gp Rt, GpHalfAddress is $(I32) & $(HWGP) & Rt & GpSub2=0b00 & GpHalfAddress { local tmp:2 = *GpHalfAddress; Rt = zext(tmp); }
:lhsi.gp Rt, GpHalfAddress is $(I32) & $(HWGP) & Rt & GpSub2=0b01 & GpHalfAddress { local tmp:2 = *GpHalfAddress; Rt = sext(tmp); }
:lwi.gp Rt, GpWordAddress is $(I32) & $(HWGP) & Rt & GpSub3=0b110 & GpWordAddress { Rt = *GpWordAddress; }
:sbi.gp Rt, GpByteAddress is $(I32) & $(SBGP) & Rt & GpSub1=0b0 & GpByteAddress { local tmp = Rt; *GpByteAddress = tmp:1; }
:shi.gp Rt, GpHalfAddress is $(I32) & $(HWGP) & Rt & GpSub2=0b10 & GpHalfAddress { local tmp = Rt; *GpHalfAddress = tmp:2; }
:swi.gp Rt, GpWordAddress is $(I32) & $(HWGP) & Rt & GpSub3=0b111 & GpWordAddress { *GpWordAddress = Rt; }
:lmwa.^LsmwBa_^LsmwId_^LsmwM_ LsmwRb, [LsmwRa], LsmwRe, Enable4 is ($(I32) & $(LSMW) & LsmwRb & LsmwRa & LsmwRe & Enable4 & LsmwLs=0 & LsmwBa_ & LsmwId_ & LsmwM_ & LsmwSub=0b01) ... & Lmwa.regs
{
mult_addr = LsmwRa;
build Lmwa.regs;
build LsmwM_;
}
:smwa.^LsmwBa_^LsmwId_^LsmwM_ LsmwRb, [LsmwRa], LsmwRe, Enable4 is ($(I32) & $(LSMW) & LsmwRb & LsmwRa & LsmwRe & Enable4 & LsmwLs=1 & LsmwBa_ & LsmwId_ & LsmwM_ & LsmwSub=0b01) ... & Smwa.regs
{
mult_addr = LsmwRa;
build Smwa.regs;
build LsmwM_;
}
:lbup Rt, AddrRaRbsv is $(I32) & $(MEM) & Rt & AddrRaRbsv & Sub8=0b00100000 { local tmp:1 = *AddrRaRbsv; Rt = zext(tmp); }
:sbup Rt, AddrRaRbsv is $(I32) & $(MEM) & Rt & AddrRaRbsv & Sub8=0b00101000 { local tmp = Rt; *AddrRaRbsv = tmp:1; }
### 32-bit Baseline V3 instructions ###
### ALU Instructions with Shift Operation (v3) ###
:add_slli Rt, Ra, Rb, sh is $(I32) & $(ALU_1) & Rt & Ra & Rb & sh & Sub5=0b00000 { Rt = Ra + (Rb << sh); }
:and_slli Rt, Ra, Rb, sh is $(I32) & $(ALU_1) & Rt & Ra & Rb & sh & Sub5=0b00010 { Rt = Ra & (Rb << sh); }
:or_slli Rt, Ra, Rb, sh is $(I32) & $(ALU_1) & Rt & Ra & Rb & sh & Sub5=0b00100 { Rt = Ra | (Rb << sh); }
:sub_slli Rt, Ra, Rb, sh is $(I32) & $(ALU_1) & Rt & Ra & Rb & sh & Sub5=0b00001 { Rt = Ra - (Rb << sh); }
:xor_slli Rt, Ra, Rb, sh is $(I32) & $(ALU_1) & Rt & Ra & Rb & sh & Sub5=0b00011 { Rt = Ra ^ (Rb << sh); }
:add_srli Rt, Ra, Rb, sh is $(I32) & $(ALU_1) & Rt & Ra & Rb & sh & Sub5=0b11100 { Rt = Ra + (Rb << sh); }
:and_srli Rt, Ra, Rb, sh is $(I32) & $(ALU_1) & Rt & Ra & Rb & sh & Sub5=0b11110 { Rt = Ra & (Rb << sh); }
:or_srli Rt, Ra, Rb, sh is $(I32) & $(ALU_1) & Rt & Ra & Rb & sh & Sub5=0b10101 { Rt = Ra | (Rb << sh); }
:sub_srli Rt, Ra, Rb, sh is $(I32) & $(ALU_1) & Rt & Ra & Rb & sh & Sub5=0b11101 { Rt = Ra - (Rb << sh); }
:xor_srli Rt, Ra, Rb, sh is $(I32) & $(ALU_1) & Rt & Ra & Rb & sh & Sub5=0b11111 { Rt = Ra ^ (Rb << sh); }
### Conditional Branch and Jump Instructions (V3) ###
Rel8: addr is Imm8s [ addr = inst_start + (Imm8s << 1); ] { export *:4 addr; }
:beqc Rt, Imm11s, Rel8 is $(I32) & $(BR3) & Rt & Bxxc=0 & Imm11s & Rel8 { if(Rt == Imm11s) goto Rel8; }
:bnec Rt, Imm11s, Rel8 is $(I32) & $(BR3) & Rt & Bxxc=1 & Imm11s & Rel8 { if(Rt != Imm11s) goto Rel8; }
:jralnez Rt,Rb is $(I32) & $(JREG) & Rt & Ra=0 & Rb & DtIt=0b00 & Jz=0 & JrHint=0 & Sub5=0b00011 { if(Rb == 0) goto <end>; Rt = inst_next; call [Rb]; <end> }
:jrnez Rb is $(I32) & $(JREG) & Rt=0 & Ra=0 & Rb & DtIt=0b00 & Jz=0 & JrHint=0 & Sub5=0b00010 { if(Rb == 0) goto <end>; goto [Rb]; <end> }
### Bit Manipulation Instructions (V3) ###
:bitc Rt, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rd=0 & Sub5=0b10010 { Rt = Ra & (~Rb); }
:bitci Rt, Ra, Imm15u is $(I32) & Opc=0b110011 & Rt & Ra & Imm15u { Rt = Ra & (~Imm15u); }
### Cache Control Instruction (V3) ###
# TODO: Add CCTL L1D_WBALL, level
### 32-bit ISA extension ###
### ALU Instruction (Performance) ###
:abs Rt, Ra is $(I32) & $(ALU_2) & Rt & Ra & Rb=0 & $(ALU2Z) & Sub6=0b000011
{
gez:4 = zext(Ra s>= 0);
ltz:4 = zext(Ra s< 0);
Rt = (Ra * gez) | ((-Ra) * ltz);
}
:ave Rt, Ra, Rb is $(I32) & $(ALU_2) & Rt & Ra & Rb & $(ALU2Z) & Sub6=0b000010
{
Rt = (Ra + Rb + 1) s>> 2;
}
:max Rt, Ra, Rb is $(I32) & $(ALU_2) & Rt & Ra & Rb & $(ALU2Z) & Sub6=0b000000
{
altb:4 = zext(Ra s< Rb);
ageb:4 = zext(Ra s>= Rb);
Rt = (Ra * ageb) | (Rb * altb);
}
:min Rt, Ra, Rb is $(I32) & $(ALU_2) & Rt & Ra & Rb & $(ALU2Z) & Sub6=0b000001
{
altb:4 = zext(Ra s< Rb);
ageb:4 = zext(Ra s>= Rb);
Rt = (Ra * altb) | (Rb * ageb);
}
:bset Rt, Ra, Imm5u is $(I32) & $(ALU_2) & Rt & Ra & Imm5u & $(ALU2Z) & Sub6=0b001000 { Rt = Ra | (1 << Imm5u); }
:bclr Rt, Ra, Imm5u is $(I32) & $(ALU_2) & Rt & Ra & Imm5u & $(ALU2Z) & Sub6=0b001001 { Rt = Ra & ~(1 << Imm5u); }
:btgl Rt, Ra, Imm5u is $(I32) & $(ALU_2) & Rt & Ra & Imm5u & $(ALU2Z) & Sub6=0b001010 { Rt = Ra ^ (1 << Imm5u); }
:btst Rt, Ra, Imm5u is $(I32) & $(ALU_2) & Rt & Ra & Imm5u & $(ALU2Z) & Sub6=0b001011 { Rt = (Ra >> Imm5u) & 1; }
:clips Rt, Ra, Imm5u is $(I32) & $(ALU_2) & Rt & Ra & Imm5u & $(ALU2Z) & Sub6=0b000100
{
local upper:4 = (1 << Imm5u) - 1;
local lower:4 = -(1 << Imm5u);
if(Ra s<= upper) goto <elif>;
Rt = upper;
goto <end>;
<elif>
if(Ra s>= lower) goto <else>;
Rt = lower;
goto <end>;
<else>
Rt = Ra;
<end>
}
:clip Rt, Ra, Imm5u is $(I32) & $(ALU_2) & Rt & Ra & Imm5u & $(ALU2Z) & Sub6=0b000101
{
local upper:4 = (1 << Imm5u) - 1;
if(Ra s<= upper) goto <elif>;
Rt = upper;
goto <end>;
<elif>
if(Ra s>= 0) goto <else>;
Rt = 0;
goto <end>;
<else>
Rt = Ra;
<end>
}
:clz Rt, Ra is $(I32) & $(ALU_2) & Rt & Ra & Imm5u=0 & $(ALU2Z) & Sub6=0b000111
{
countTmp:4 = 0;
inputTmp:4 = Ra;
<loopbegin>
if ((inputTmp & 0x80000000) != 0) goto <loopend>;
countTmp = countTmp + 1;
inputTmp = (inputTmp << 1) | 1;
goto <loopbegin>;
<loopend>
Rt = countTmp;
}
:clo Rt, Ra is $(I32) & $(ALU_2) & Rt & Ra & Imm5u=0 & $(ALU2Z) & Sub6=0b000110
{
countTmp:4 = 0;
inputTmp:4 = Ra;
<loopbegin>
if ((inputTmp & 0x80000000) == 0) goto <loopend>;
countTmp = countTmp + 1;
inputTmp = (inputTmp << 1) | 1;
goto <loopbegin>;
<loopend>
Rt = countTmp;
}
### Performance Extension V2 ###
# TODO : arithmetic functions: bs*
:bse is $(I32) & $(ALU_2) & Rt & Ra & Rb & $(ALU2Z) & Sub6=0b001100 unimpl
:bsp is $(I32) & $(ALU_2) & Rt & Ra & Rb & $(ALU2Z) & Sub6=0b001101 unimpl
macro add_abs_diff(dst, src1, src2, shift)
{
local src1_ = src1 >> shift;
local src2_ = src2 >> shift;
local src1__ = src1_:1;
local src2__ = src2_:1;
local a:1 = src1__ - src2__;
local agez:1 = zext(a s>= 0);
local altz:1 = zext(a s< 0);
local aabs:1 = (a * agez) | ((-a) * altz);
dst = dst + zext(aabs);
}
:pbsad Rt, Ra, Rb is $(I32) & $(SIMD) & Rt & Ra & Rb & Rd=0 & Sub5=0b0000
{
Rt = 0;
add_abs_diff(Rt, Ra, Rb, 0);
add_abs_diff(Rt, Ra, Rb, 8);
add_abs_diff(Rt, Ra, Rb, 16);
add_abs_diff(Rt, Ra, Rb, 24);
}
:pbsada Rt, Ra, Rb is $(I32) & $(SIMD) & Rt & Ra & Rb & Rd=0 & Sub5=0b0001
{
add_abs_diff(Rt, Ra, Rb, 0);
add_abs_diff(Rt, Ra, Rb, 8);
add_abs_diff(Rt, Ra, Rb, 16);
add_abs_diff(Rt, Ra, Rb, 24);
}
# 32-bit String Extension
:ffb Rt, Ra, Rb is $(I32) & $(ALU_2) & Rt & Ra & Rb & Sub3=0 & Sub7=0b0001110 {
match:1 = Rb[0,8];
m1:1 = (Ra[0,8] == match);
m2:1 = (Ra[8,8] == match);
m3:1 = (Ra[16,8] == match);
m4:1 = (Ra[24,8] == match);
Rt = -4;
if (m1) goto inst_next;
Rt = -3;
if (m2) goto inst_next;
Rt = -2;
if (m3) goto inst_next;
Rt = -1;
if (m4) goto inst_next;
Rt = 0;
# choosery method
# rd = 0 + (zext(m1)*-4) + (zext(m2)*-3) + (zext(m3)*-2) + (zext(m4)*-1);
}
:ffbi Rt, Ra, Imm8u is $(I32) & $(ALU_2) & Rt & Ra & Imm8u & Sub7=0b1001110 {
match:1 = Imm8u;
m1:1 = (Ra[0,8] == match);
m2:1 = (Ra[8,8] == match);
m3:1 = (Ra[16,8] == match);
m4:1 = (Ra[24,8] == match);
Rt = -4;
if (m1) goto inst_next;
Rt = -3;
if (m2) goto inst_next;
Rt = -2;
if (m3) goto inst_next;
Rt = -1;
if (m4) goto inst_next;
Rt = 0;
}
:ffmism Rt, Ra, Rb is $(I32) & $(ALU_2) & Rt & Ra & Rb & Sub3=0 & Sub7=0b0001111 {
match:1 = Rb[0,8];
m1:1 = (Ra[0,8] != Rb[0,8]);
m2:1 = (Ra[8,8] != Rb[8,8]);
m3:1 = (Ra[16,8] != Rb[16,8]);
m4:1 = (Ra[24,8] != Rb[24,8]);
@if ENDIAN == "little"
Rt = -4;
if (m1) goto inst_next;
Rt = -3;
if (m2) goto inst_next;
Rt = -2;
if (m3) goto inst_next;
Rt = -1;
if (m4) goto inst_next;
Rt = 0;
# choosery method
# rd = 0 + (zext(m1)*-4) + (zext(m2)*-3) + (zext(m3)*-2) + (zext(m4)*-1);
@else
Rt = -4;
if (m4) goto inst_next;
Rt = -3;
if (m3) goto inst_next;
Rt = -2;
if (m2) goto inst_next;
Rt = -1;
if (m1) goto inst_next;
Rt = 0;
@endif
}
:flmism Rt, Ra, Rb is $(I32) & $(ALU_2) & Rt & Ra & Rb & Sub3=0 & Sub7=0b1001111 {
match:1 = Rb[0,8];
m1:1 = (Ra[0,8] != Rb[0,8]);
m2:1 = (Ra[8,8] != Rb[8,8]);
m3:1 = (Ra[16,8] != Rb[16,8]);
m4:1 = (Ra[24,8] != Rb[24,8]);
@if ENDIAN == "little"
Rt = -1;
if (m4) goto inst_next;
Rt = -2;
if (m3) goto inst_next;
Rt = -3;
if (m2) goto inst_next;
Rt = -4;
if (m1) goto inst_next;
Rt = 0;
# choosery method
# rd = 0 + (zext(m1)*-4) + (zext(m2)*-3) + (zext(m3)*-2) + (zext(m4)*-1);
@else
Rt = -1;
if (m1) goto inst_next;
Rt = -2;
if (m2) goto inst_next;
Rt = -3;
if (m3) goto inst_next;
Rt = -4;
if (m4) goto inst_next;
Rt = 0;
@endif
}
########### 16b ############
define token instr16(16)
opsz = (15, 15)
opc4 = (11, 14)
opc5 = (10, 14)
opc6 = (9, 14)
opc7 = (8, 14)
opc8 = (7, 14)
opc10 = (5, 14)
re2 = (5, 6)
rt5 = (5, 9)
ra4 = (5, 8)
rt4 = (5, 8)
ra5 = (0, 4)
rb5 = (0, 4)
rt5b = (0, 4)
rt3 = (6, 8)
rt3b = (8, 10)
ra3 = (3, 5)
rb3 = (0, 2)
bit5 = (5,5)
bit6 = (6,6)
bit7 = (7,7)
bit8 = (8,8)
imm3u = (0, 2)
imm3ub = (3, 5)
imm4u = (5, 8)
imm5u = (0, 4)
imm5s = (0, 4) signed
imm6u = (0, 5)
imm7u = (0, 6)
imm8s = (0, 7) signed
imm10s = (0, 9) signed
xwi37_ls = (7, 7)
swid9 = (0, 8)
rt5e1 = (4, 7)
rt5e2 = (4, 7)
ra5e1 = (0, 3)
ra5e2 = (0, 3)
;
attach variables [rt5 ra5 rb5 rt5b] [
a0 a1 a2 a3 a4 a5 s0 s1 s2 s3 s4 s5 s6 s7 s8 ta t0 t1 t2 t3 t4 t5 t6 t7 t8 t9 p0 p1 fp gp lp sp
];
attach variables [ra4 rt4] [
a0 a1 a2 a3 a4 a5 s0 s1 s2 s3 s4 s5 t0 t1 t2 t3
];
attach variables [rt3 ra3 rt3b rb3] [
a0 a1 a2 a3 a4 a5 s0 s1
];
attach variables [ra5e1 rt5e1] [
a0 a2 a4 s0 s2 s4 s6 s8 t0 t2 t4 t6 t8 p0 fp lp
];
attach variables [ra5e2 rt5e2] [
a1 a3 a5 s1 s3 s5 s7 ta t1 t3 t5 t7 t9 p1 gp sp
];
attach variables [re2] [
s0 s2 s4 s8
];
@define I16 "(opsz=1)"
@define BFMI333 "(opc6=0b001011)"
@define XWI37 "(opc4=0b0111)"
@define XWI37SP "(opc4=0b1110)"
@define MISC33 "(opc6=0b111111)"
### Move Instruction ###
:movi55 rt5, imm5s is $(I16) & opc5=0b00001 & rt5 & imm5s { rt5 = imm5s; }
:mov55 rt5, ra5 is $(I16) & opc5=0b00000 & rt5 & ra5 { rt5 = ra5; }
### Add/Sub Instruction with Immediate ###
:addi45 rt4, imm5u is $(I16) & opc6=0b000110 & rt4 & imm5u { rt4 = rt4 + imm5u; }
:addi333 rt3, ra3, imm3u is $(I16) & opc6=0b001110 & rt3 & ra3 & imm3u { rt3 = ra3 + imm3u; }
:subi45 rt4, imm5u is $(I16) & opc6=0b000111 & rt4 & imm5u { rt4 = rt4 - imm5u; }
:subi333 rt3, ra3, imm3u is $(I16) & opc6=0b001111 & rt3 & ra3 & imm3u { rt3 = ra3 - imm3u; }
### Add/Sub Instruction ###
:add45 rt4, rb5 is $(I16) & opc6=0b000100 & rt4 & rb5 { rt4 = rt4 + rb5; }
:add333 rt3, ra3, rb3 is $(I16) & opc6=0b001100 & rt3 & ra3 & rb3 { rt3 = ra3 + rb3; }
:sub45 rt4, rb5 is $(I16) & opc6=0b000101 & rt4 & rb5 { rt4 = rt4 - rb5; }
:sub333 rt3, ra3, rb3 is $(I16) & opc6=0b001101 & rt3 & ra3 & rb3 { rt3 = ra3 - rb3; }
### Shift Instruction with Immediate ###
:srai45 rt4, imm5u is $(I16) & opc6=0b001000 & rt4 & imm5u { rt4 = rt4 s>> imm5u; }
:srli45 rt4, imm5u is $(I16) & opc6=0b001001 & rt4 & imm5u { rt4 = rt4 >> imm5u; }
:slli333 rt3, ra3, imm3u is $(I16) & opc6=0b001010 & rt3 & ra3 & imm3u { rt3 = ra3 << imm3u; }
### Bit Field Mask Instruction with Immediate ###
:zeb33 rt3, ra3 is $(I16) & $(BFMI333) & rt3 & ra3 & imm3u=0b000 { local tmp = ra3; rt3 = zext(tmp:1); }
:zeh33 rt3, ra3 is $(I16) & $(BFMI333) & rt3 & ra3 & imm3u=0b001 { local tmp = ra3; rt3 = zext(tmp:2); }
:seb33 rt3, ra3 is $(I16) & $(BFMI333) & rt3 & ra3 & imm3u=0b010 { local tmp = ra3; rt3 = sext(tmp:1); }
:seh33 rt3, ra3 is $(I16) & $(BFMI333) & rt3 & ra3 & imm3u=0b011 { local tmp = ra3; rt3 = sext(tmp:2); }
:xlsb33 rt3, ra3 is $(I16) & $(BFMI333) & rt3 & ra3 & imm3u=0b100 { rt3 = ra3 & 1; }
:x11b33 rt3, ra3 is $(I16) & $(BFMI333) & rt3 & ra3 & imm3u=0b101 { rt3 = ra3 & 0x7ff; }
### Load / Store Instruction ###
:lwi450 rt4,[ra5] is $(I16) & opc6=0b011010 & rt4 & ra5 { rt4 = *ra5; }
rel3w: off is imm3u [ off = imm3u << 2; ] { export *[const]:4 off; }
rel3h: off is imm3u [ off = imm3u << 1; ] { export *[const]:4 off; }
rel3b: off is imm3u [ off = imm3u << 0 ; ] { export *[const]:4 off; }
ra3_rel3w: [ra3 + rel3w] is ra3 & rel3w { addr:4 = ra3 + rel3w; export addr; }
ra3_rel3h: [ra3 + rel3h] is ra3 & rel3h { addr:4 = ra3 + rel3h; export addr; }
ra3_rel3b: [ra3 + rel3b] is ra3 & rel3b { addr:4 = ra3 + rel3b; export addr; }
:lwi333 rt3, ra3_rel3w is $(I16) & opc6=0b010000 & rt3 & ra3_rel3w { rt3 = *ra3_rel3w; }
:lwi333.bi rt3, [ra3], rel3w is $(I16) & opc6=0b010001 & rt3 & ra3 & rel3w { rt3 = *ra3; ra3 = ra3 + rel3w; }
:lhi333 rt3, ra3_rel3h is $(I16) & opc6=0b010010 & rt3 & ra3_rel3h { local tmp:2 = *ra3_rel3h; rt3 = zext(tmp); }
:lbi333 rt3, ra3_rel3b is $(I16) & opc6=0b010011 & rt3 & ra3_rel3b { local tmp:1 = *ra3_rel3b; rt3 = zext(tmp); }
:swi450 rt4, [ra5] is $(I16) & opc6=0b011011 & rt4 & ra5 { *ra5 = rt4; }
:swi333 rt3, ra3_rel3w is $(I16) & opc6=0b010100 & rt3 & ra3_rel3w { *ra3_rel3w = rt3; }
:swi333.bi rt3, [ra3], rel3w is $(I16) & opc6=0b010101 & rt3 & ra3 & rel3w { *ra3 = rt3; ra3 = ra3 + rel3w; }
:shi333 rt3, ra3_rel3h is $(I16) & opc6=0b010110 & rt3 & ra3_rel3h { local tmp = rt3; *ra3_rel3h = tmp:2; }
:sbi333 rt3, ra3_rel3b is $(I16) & opc6=0b010111 & rt3 & ra3_rel3b { local tmp = rt3; *ra3_rel3b = tmp:1; }
### Load/Store Instruction with Implied FP ###
rel7w: off is imm7u [ off = imm7u << 2; ] { export *[const]:4 off; }
fp_rel7w: [fp + rel7w] is fp & rel7w { addr:4 = fp + rel7w; export addr; }
:lwi37 rt3b, fp_rel7w is $(I16) & rt3b & $(XWI37) & xwi37_ls=0 & fp_rel7w { rt3b = *fp_rel7w; }
:swi37 rt3b, fp_rel7w is $(I16) & rt3b & $(XWI37) & xwi37_ls=1 & fp_rel7w { *fp_rel7w = rt3b; }
### Branch and Jump Instruction ###
rel8: addr is imm8s [ addr = inst_start + (imm8s << 1); ] { export *:4 addr; }
:beqs38 rt3b,rel8 is $(I16) & opc4=0b1010 & rt3b & rel8 { if(a5 == rt3b) goto rel8; }
:bnes38 rt3b,rel8 is $(I16) & opc4=0b1011 & rt3b & rel8 { if(a5 != rt3b) goto rel8; }
:beqz38 rt3b,rel8 is $(I16) & opc4=0b1000 & rt3b & rel8 { if(rt3b == 0) goto rel8; }
:bnez38 rt3b,rel8 is $(I16) & opc4=0b1001 & rt3b & rel8 { if(rt3b != 0) goto rel8; }
:j8 rel8 is $(I16) & opc7=0b1010101 & rel8 { goto rel8; }
:jr5 rb5 is $(I16) & opc10=0b1011101000 & rb5 { goto [rb5]; }
:ret5 rb5 is $(I16) & opc10=0b1011101100 & rb5 { return [rb5]; }
:jral5 rb5 is $(I16) & opc10=0b1011101001 & rb5 { lp = inst_next; call [rb5]; }
### Compare and Branch Instruction ###
:slti45 ra4, imm5u is $(I16) & opc6=0b110011 & ra4 & imm5u { ta = zext(ra4 < imm5u); }
:sltsi45 ra4, imm5u is $(I16) & opc6=0b110010 & ra4 & imm5u { ta = zext(ra4 s< imm5u); }
:slt45 ra4, rb5 is $(I16) & opc6=0b110001 & ra4 & rb5 { ta = zext(ra4 < rb5); }
:slts45 ra4, rb5 is $(I16) & opc6=0b110000 & ra4 & rb5 { ta = zext(ra4 s< rb5); }
:beqzs8 rel8 is $(I16) & opc7=0b1101000 & rel8 { if(ta == 0) goto rel8; }
:bnezs8 rel8 is $(I16) & opc7=0b1101001 & rel8 { if(ta != 0) goto rel8; }
### Misc Instruction ###
# V3 doesn't allow break16 with SWID greater than 31
:break16 swid9 is $(I16) & opc6=0b110101 & imm4u=0 & swid9 { break(swid9:4); }
:nop16 is $(I16) & opc6=0b001001 & rt4=0 & imm5u=0 { }
### ALU Instructions (V2) ###
:addi10.sp imm10s is $(I16) & opc5=0b11011 & imm10s { sp = sp + imm10s; }
### Load/Store Instruction (V2) ###
sp_rel7w: [+ rel7w] is rel7w { addr:4 = sp + rel7w; export addr; }
:lwi37.sp rt3b, sp_rel7w is $(I16) & rt3b & $(XWI37SP) & xwi37_ls=0 & sp_rel7w { rt3b = *sp_rel7w; }
:swi37.sp rt3b, sp_rel7w is $(I16) & rt3b & $(XWI37SP) & xwi37_ls=1 & sp_rel7w { *sp_rel7w = rt3b; }
### 16-bit Baseline V3 instructions ###
### ALU Instructions (V3 16-bit) ###
imm6u_: imm8 is imm6u [ imm8 = imm6u << 2; ] { export *[const]:4 imm8; }
:addri36.sp rt3, imm6u_ is $(I16) & opc6=0b011000 & rt3 & imm6u_ { rt3 = sp + imm6u_; }
:add5.pc rt5b is $(I16) & opc10=0b1011101101 & rt5b { rt5b = pc + rt5b; }
:and33 rt3, ra3 is $(I16) & $(MISC33) & rt3 & ra3 & imm3u=0b110 { rt3 = rt3 & ra3; }
:neg33 rt3, ra3 is $(I16) & $(MISC33) & rt3 & ra3 & imm3u=0b010 { rt3 = -ra3; }
:not33 rt3, ra3 is $(I16) & $(MISC33) & rt3 & ra3 & imm3u=0b011 { rt3 = ~ra3; }
:or33 rt3, ra3 is $(I16) & $(MISC33) & rt3 & ra3 & imm3u=0b111 { rt3 = rt3 | ra3; }
:xor33 rt3, ra3 is $(I16) & $(MISC33) & rt3 & ra3 & imm3u=0b101 { rt3 = rt3 ^ ra3; }
### Bit Manipulation Instructions (V3 16-bit) ###
:bmski33 rt3, imm3ub is $(I16) & opc6=0b001011 & rt3 & imm3ub & imm3u=0b110 { rt3 = (rt3 >> imm3ub) & 1; }
:fexti33 rt3, imm3ub is $(I16) & opc6=0b001011 & rt3 & imm3ub & imm3u=0b111 { rt3 = rt3 & ((1 << (imm3ub + 1)) - 1); }
### Misc. Instructions (V3 16-bit) ###
imm7n: off is imm5u [ off = -((32 - imm5u) << 2); ] { export *[const]:4 off; }
:lwi45.fe rt4, [imm7n] is $(I16) & opc6=0b011001 & rt4 & imm7n { addr:4 = s2 + imm7n; rt4 = *addr; }
:movd44 rt5e1, ra5e1 is $(I16) & opc7=0b1111101 & rt5e1 & rt5e2 & ra5e1 & ra5e2 { rt5e1 = ra5e1; rt5e2 = ra5e2; }
imm5u_: imm6 is imm5u [ imm6 = imm5u + 16; ] { export *[const]:4 imm6; }
:movpi45 rt4, imm5u_ is $(I16) & opc6=0b111101 & rt4 & imm5u_ { rt4 = imm5u_; }
:mul33 rt3, ra3 is $(I16) & $(MISC33) & rt3 & ra3 & imm3u=0b100 { rt3 = rt3 * ra3; }
# Note: POP25 and PUSH25 are highly untested ! And they just look messy :/
imm5u__: imm8 is imm5u [ imm8 = imm5u << 3; ] { export *[const]:4 imm8; }
macro push25_special() { Smwad(lp); Smwad(gp); Smwad(fp); }
macro push25_s0() { Smwad(s0); }
macro push25_s2() { Smwad(s2); Smwad(s1); push25_s0(); }
macro push25_s4() { Smwad(s4); Smwad(s3); push25_s2(); }
macro push25_s8() { Smwad(s8); Smwad(s7); Smwad(s6); Smwad(s5); push25_s4(); }
push25_re: re2 is re2 & re2=0 { push25_s0(); }
push25_re: re2 is re2 & re2=1 { push25_s2(); }
push25_re: re2 is re2 & re2=2 { push25_s4(); }
push25_re: re2 is re2 & re2=3 { push25_s8(); }
:push25 push25_re, imm5u__ is $(I16) & opc8=0b11111000 & re2 & push25_re & imm5u__ {
mult_addr = sp;
push25_special();
build push25_re;
sp = mult_addr - imm5u__;
if(re2 < 1) goto <end>;
s2 = pc & 0xfffffffc;
<end>
}
macro pop25_special() { LmwOp(fp); LmwOp(gp); LmwOp(lp); }
macro pop25_s0() { LmwOp(s0); }
macro pop25_s2() { pop25_s0(); LmwOp(s1); LmwOp(s2); }
macro pop25_s4() { pop25_s2(); LmwOp(s3); LmwOp(s4); }
macro pop25_s8() { pop25_s4(); LmwOp(s5); LmwOp(s6); LmwOp(s7); LmwOp(s8); }
pop25_re: re2 is re2 & re2=0 { pop25_s0(); }
pop25_re: re2 is re2 & re2=1 { pop25_s2(); }
pop25_re: re2 is re2 & re2=2 { pop25_s4(); }
pop25_re: re2 is re2 & re2=3 { pop25_s8(); }
:pop25 pop25_re, imm5u__ is $(I16) & opc8=0b11111001 & re2 & pop25_re & imm5u__ {
mult_addr = sp;
build pop25_re;
pop25_special();
sp = mult_addr + imm5u__;
return [lp];
}
# EX9.IT
imm9u_: imm9 is imm5u & imm4u [ imm9 = (imm4u << 5) | imm5u; ] { export *[const]:4 imm9; }
define pcodeop ex9;
# TODO: Depending on the value of ITB.HW the address is either set by hardware or set by ITB.Addr
:ex9.it imm9u_ is $(I16) & opc6=0b110101 & (bit5=1 | bit6=1 | bit7=1 | bit8=1) & imm9u_ {
ex9(imm9u_);
}
:ex9.it imm5u is $(I16) & opc10=0b1011101010 & imm5u {
ex9(imm5u:4);
}
##########################
# Floating Point Extension
# FPU_FS1
define pcodeop fadds;
:fadds Fst, Fsa, Fsb is $(I32) & $(COP) & fop4=0x0 & Fst & Fsa & Fsb & cop4=0x0 {
Fst = fadds(Fsa, Fsb);
}
define pcodeop fsubs;
:fsubs Fst, Fsa, Fsb is $(I32) & $(COP) & fop4=0x1 & Fst & Fsa & Fsb & cop4=0x0 {
Fst = fsubs(Fsa, Fsb);
}
define pcodeop fcpynss;
:fcpynss Fst, Fsa, Fsb is $(I32) & $(COP) & fop4=0x2 & Fst & Fsa & Fsb & cop4=0x0 {
Fst = fcpynss(Fsa, Fsb);
}
define pcodeop fcpyss;
:fcpyss Fst, Fsa, Fsb is $(I32) & $(COP) & fop4=0x3 & Fst & Fsa & Fsb & cop4=0x0 {
Fst = fcpyss(Fsa, Fsb);
}
define pcodeop fmadds;
:fmadds Fst, Fsa, Fsb is $(I32) & $(COP) & fop4=0x4 & Fst & Fsa & Fsb & cop4=0x0 {
Fst = fmadds(Fsa, Fsb);
}
define pcodeop fmsubs;
:fmsubs Fst, Fsa, Fsb is $(I32) & $(COP) & fop4=0x5 & Fst & Fsa & Fsb & cop4=0x0 {
Fst = fmsubs(Fsa, Fsb);
}
define pcodeop fcmovns;
:fcmovns Fst, Fsa, Fsb is $(I32) & $(COP) & fop4=0x6 & Fst & Fsa & Fsb & cop4=0x0 {
Fst = fcmovns(Fsa, Fsb);
}
define pcodeop fcmovzs;
:fcmovzs Fst, Fsa, Fsb is $(I32) & $(COP) & fop4=0x7 & Fst & Fsa & Fsb & cop4=0x0 {
Fst = fcmovzs(Fsa, Fsb);
}
define pcodeop fnmadds;
:fnmadds Fst, Fsa, Fsb is $(I32) & $(COP) & fop4=0x8 & Fst & Fsa & Fsb & cop4=0x0 {
Fst = fnmadds(Fsa, Fsb);
}
define pcodeop fnmsubs;
:fnmsubs Fst, Fsa, Fsb is $(I32) & $(COP) & fop4=0x9 & Fst & Fsa & Fsb & cop4=0x0 {
Fst = fnmsubs(Fsa, Fsb);
}
define pcodeop fmuls;
:fmuls Fst, Fsa, Fsb is $(I32) & $(COP) & fop4=0xa & Fst & Fsa & Fsb & cop4=0x0 {
Fst = fmuls(Fsa, Fsb);
}
define pcodeop fdivs;
:fdivs Fst, Fsa, Fsb is $(I32) & $(COP) & fop4=0xb & Fst & Fsa & Fsb & cop4=0x0 {
Fst = fdivs(Fsa, Fsb);
}
# FPU_FS1_F2OP
define pcodeop fs2d;
:fs2d Fdt, Fsa is $(I32) & $(COP) & fop4=0xf & Fdt & Fsa & f2op=0 & cop4=0x0 {
Fdt = fs2d(Fsa);
}
define pcodeop fsqrts;
:fsqrts Fst, Fsa is $(I32) & $(COP) & fop4=0xf & Fst & Fsa & f2op=1 & cop4=0x0 {
Fst = fsqrts(Fsa);
}
define pcodeop fabss;
:fabss Fst, Fsa is $(I32) & $(COP) & fop4=0xf & Fst & Fsa & f2op=0x5 & cop4=0x0 {
Fst = fabss(Fsa);
}
define pcodeop fui2s;
:fui2s Fst, Fsa is $(I32) & $(COP) & fop4=0xf & Fst & Fsa & f2op=0x8 & cop4=0x0 {
Fst = fui2s(Fsa);
}
define pcodeop fsi2s;
:fsi2s Fst, Fsa is $(I32) & $(COP) & fop4=0xf & Fst & Fsa & f2op=0xc & cop4=0x0 {
Fst = fsi2s(Fsa);
}
define pcodeop fs2ui;
:fs2ui Fst, Fsa is $(I32) & $(COP) & fop4=0xf & Fst & Fsa & f2op=0x10 & cop4=0x0 {
Fst = fs2ui(Fsa);
}
define pcodeop fs2ui.z;
:fs2ui.z Fst, Fsa is $(I32) & $(COP) & fop4=0xf & Fst & Fsa & f2op=0x14 & cop4=0x0 {
Fst = fs2ui.z(Fsa);
}
define pcodeop fs2si;
:fs2si Fst, Fsa is $(I32) & $(COP) & fop4=0xf & Fst & Fsa & f2op=0x18 & cop4=0x0 {
Fst = fs2si(Fsa);
}
define pcodeop fs2si.z;
:fs2si.z Fst, Fsa is $(I32) & $(COP) & fop4=0xf & Fst & Fsa & f2op=0x1c & cop4=0x0 {
Fst = fs2si.z(Fsa);
}
# FPU_FS2
fcond: "eq" is fcnd=0 { local tmp:1 = 0; export *[const]:1 tmp; }
fcond: "lt" is fcnd=1 { local tmp:1 = 1; export *[const]:1 tmp; }
fcond: "le" is fcnd=2 { local tmp:1 = 2; export *[const]:1 tmp; }
fcond: "un" is fcnd=3 { local tmp:1 = 3; export *[const]:1 tmp; }
fcmpe: "" is cmpe=0 { local tmp:1 = 0; export *[const]:1 tmp; }
fcmpe: ".e" is cmpe=1 { local tmp:1 = 1; export *[const]:1 tmp; }
define pcodeop fcmps;
:fcmp^fcond^"s"^fcmpe Fst, Fsa, Fsb is $(I32) & $(COP) & Fst & Fsa & Fsb & cop4=0x4 & fcond & fcmpe {
Fst = fcmps(Fsa, Fsb, fcond, fcmpe);
}
# FPU_FD1
define pcodeop faddd;
:faddd Fdt, Fda, Fdb is $(I32) & $(COP) & fop4=0x0 & Fdt & Fda & Fdb & cop4=0x8 {
Fdt = faddd(Fda, Fdb);
}
define pcodeop fsubd;
:fsubd Fdt, Fda, Fdb is $(I32) & $(COP) & fop4=0x1 & Fdt & Fda & Fdb & cop4=0x8 {
Fdt = fsubd(Fda, Fdb);
}
define pcodeop fcpynsd;
:fcpynsd Fdt, Fda, Fdb is $(I32) & $(COP) & fop4=0x2 & Fdt & Fda & Fdb & cop4=0x8 {
Fdt = fcpynsd(Fda, Fdb);
}
define pcodeop fcpysd;
:fcpysd Fdt, Fda, Fdb is $(I32) & $(COP) & fop4=0x3 & Fdt & Fda & Fdb & cop4=0x8 {
Fdt = fcpysd(Fda, Fdb);
}
define pcodeop fmaddd;
:fmaddd Fdt, Fda, Fdb is $(I32) & $(COP) & fop4=0x4 & Fdt & Fda & Fdb & cop4=0x8 {
Fdt = fmaddd(Fda, Fdb);
}
define pcodeop fmsubd;
:fmsubd Fdt, Fda, Fdb is $(I32) & $(COP) & fop4=0x5 & Fdt & Fda & Fdb & cop4=0x8 {
Fdt = fmsubd(Fda, Fdb);
}
define pcodeop fcmovnd;
:fcmovnd Fdt, Fda, Fdb is $(I32) & $(COP) & fop4=0x6 & Fdt & Fda & Fdb & cop4=0x8 {
Fdt = fcmovnd(Fda, Fdb);
}
define pcodeop fcmovzd;
:fcmovzd Fdt, Fda, Fdb is $(I32) & $(COP) & fop4=0x7 & Fdt & Fda & Fdb & cop4=0x8 {
Fdt = fcmovzd(Fda, Fdb);
}
define pcodeop fnmaddd;
:fnmaddd Fdt, Fda, Fdb is $(I32) & $(COP) & fop4=0x8 & Fdt & Fda & Fdb & cop4=0x8 {
Fdt = fnmaddd(Fda, Fdb);
}
define pcodeop fnmsubd;
:fnmsubd Fdt, Fda, Fdb is $(I32) & $(COP) & fop4=0x9 & Fdt & Fda & Fdb & cop4=0x8 {
Fdt = fnmsubd(Fda, Fdb);
}
define pcodeop fmuld;
:fmuld Fdt, Fda, Fdb is $(I32) & $(COP) & fop4=0xa & Fdt & Fda & Fdb & cop4=0x8 {
Fdt = fmuld(Fda, Fdb);
}
define pcodeop fdivd;
:fdivd Fdt, Fda, Fdb is $(I32) & $(COP) & fop4=0xb & Fdt & Fda & Fdb & cop4=0x8 {
Fdt = fdivd(Fda, Fdb);
}
# FPU_FD1_F2OP
define pcodeop fd2s;
:fd2s Fst, Fda is $(I32) & $(COP) & fop4=0xf & Fst & Fda & f2op=0 & cop4=0x8 {
Fst = fd2s(Fda);
}
define pcodeop fsqrtd;
:fsqrtd Fdt, Fda is $(I32) & $(COP) & fop4=0xf & Fdt & Fda & f2op=1 & cop4=0x8 {
Fdt = fsqrtd(Fda);
}
define pcodeop fabsd;
:fabsd Fdt, Fda is $(I32) & $(COP) & fop4=0xf & Fdt & Fda & f2op=0x5 & cop4=0x8 {
Fdt = fabsd(Fda);
}
define pcodeop fui2d;
:fui2d Fdt, Fsa is $(I32) & $(COP) & fop4=0xf & Fdt & Fsa & f2op=0x8 & cop4=0x8 {
Fdt = fui2d(Fsa);
}
define pcodeop fsi2d;
:fsi2d Fdt, Fsa is $(I32) & $(COP) & fop4=0xf & Fdt & Fsa & f2op=0xc & cop4=0x8 {
Fdt = fsi2d(Fsa);
}
define pcodeop fd2ui;
:fd2ui Fst, Fda is $(I32) & $(COP) & fop4=0xf & Fst & Fda & f2op=0x10 & cop4=0x8 {
Fst = fd2ui(Fda);
}
define pcodeop fd2ui.z;
:fd2ui.z Fst, Fda is $(I32) & $(COP) & fop4=0xf & Fst & Fda & f2op=0x14 & cop4=0x8 {
Fst = fs2ui.z(Fda);
}
define pcodeop fd2si;
:fd2si Fst, Fda is $(I32) & $(COP) & fop4=0xf & Fst & Fda & f2op=0x18 & cop4=0x8 {
Fst = fd2si(Fda);
}
define pcodeop fd2si.z;
:fd2si.z Fst, Fda is $(I32) & $(COP) & fop4=0xf & Fst & Fda & f2op=0x1c & cop4=0x8 {
Fst = fs2si.z(Fda);
}
# FPU_FS2
define pcodeop fcmpd;
:fcmp^fcond^"d"^fcmpe Fst, Fda, Fdb is $(I32) & $(COP) & Fst & Fda & Fdb & cop4=0xc & fcond & fcmpe {
Fst = fcmpd(Fda, Fdb, fcond, fcmpe);
}
# FPU_MFCP
define pcodeop fmfsr;
:fmfsr Rt, Fsa is $(I32) & $(COP) & fop4=0x0 & Rt & Fsa & f2op=0x0 & cop4=0x1 {
Rt = fmfsr(Fsa);
}
define pcodeop fmfdr;
:fmfdr Rt, Fda is $(I32) & $(COP) & fop4=0x1 & Rt & Fda & f2op=0x0 & cop4=0x1 {
Rt = fmfdr(Fda);
}
# FPU_MTCP
define pcodeop fmtsr;
:fmtsr Rt, Fsa is $(I32) & $(COP) & fop4=0x0 & Rt & Fsa & f2op=0x0 & cop4=0x9 {
Fsa = fmtsr(Rt);
}
define pcodeop fmtdr;
:fmtdr Rt, Fda is $(I32) & $(COP) & fop4=0x1 & Rt & Fda & f2op=0x0 & cop4=0x9 {
Fda = fmtdr(Rt);
}
# FPU_FLS
:fls Fst, AddrRaRbsv is $(I32) & $(COP) & Fst & AddrRaRbsv & fbi=0 & cop4=0x2 {
Fst = *AddrRaRbsv;
}
:fls.bi Fst [Ra], OffsetRbsv is $(I32) & $(COP) & Fst & Ra & OffsetRbsv & fbi=1 & cop4=2 {
Fst = *Ra;
Ra = Ra + OffsetRbsv;
}
# FPU_FLD
:fld Fdt, AddrRaRbsv is $(I32) & $(COP) & Fdt & AddrRaRbsv & fbi=0 & cop4=0x3 {
Fdt = *AddrRaRbsv;
}
:fld.bi Fdt [Ra], OffsetRbsv is $(I32) & $(COP) & Fdt & Ra & OffsetRbsv & fbi=1 & cop4=3 {
Fdt = *Ra;
Ra = Ra + OffsetRbsv;
}
# FPU_FSS
:fss Fst, AddrRaRbsv is $(I32) & $(COP) & Fst & AddrRaRbsv & fbi=0 & cop4=0xa {
*AddrRaRbsv = Fst;
}
:fss.bi Fst [Ra], OffsetRbsv is $(I32) & $(COP) & Fst & Ra & OffsetRbsv & fbi=1 & cop4=0xa {
*Ra = Fst;
Ra = Ra + OffsetRbsv;
}
# FPU_FSD
:fsd Fdt, AddrRaRbsv is $(I32) & $(COP) & Fdt & AddrRaRbsv & fbi=0 & cop4=0xb {
*AddrRaRbsv = Fdt;
}
:fsd.bi Fdt [Ra], OffsetRbsv is $(I32) & $(COP) & Fdt & Ra & OffsetRbsv & fbi=1 & cop4=0xb {
*Ra = Fdt;
Ra = Ra + OffsetRbsv;
}
# LWC0
AddrRaImm12s: [Ra + offs] is Ra & Imm12s [ offs = Imm12s << 2; ] { addr:4 = Ra + offs; export addr; }
OffImm12s: (offs) is Imm12s [ offs = Imm12s << 2; ] { export *[const]:4 offs; }
:flsi Fst, AddrRaImm12s is $(I32) & $(LWC) & Fst & cpn=0 & fsbi=0 & AddrRaImm12s {
Fst = *AddrRaImm12s;
}
:flsi.bi Fst [Ra], OffImm12s is $(I32) & $(LWC) & Fst & Ra & cpn=0 & fsbi=1 & OffImm12s {
Fst = *Ra;
Ra = Ra + OffImm12s;
}
# LDC0
:fldi Fdt, AddrRaImm12s is $(I32) & $(LDC) & Fdt & cpn=0 & fsbi=0 & AddrRaImm12s {
Fdt = *AddrRaImm12s;
}
:fldi.bi Fdt [Ra], OffImm12s is $(I32) & $(LDC) & Fdt & Ra & cpn=0 & fsbi=1 & OffImm12s {
Fdt = *Ra;
Ra = Ra + OffImm12s;
}
# SWC0
:fssi Fst, AddrRaImm12s is $(I32) & $(SWC) & Fst & cpn=0 & fsbi=0 & AddrRaImm12s {
*AddrRaImm12s = Fst;
}
:fssi.bi Fst [Ra], OffImm12s is $(I32) & $(SWC) & Fst & Ra & cpn=0 & fsbi=1 & OffImm12s {
*Ra = Fst;
Ra = Ra + OffImm12s;
}
# SDC0
:fsdi Fdt, AddrRaImm12s is $(I32) & $(SDC) & Fdt & cpn=0 & fsbi=0 & AddrRaImm12s {
*AddrRaImm12s = Fdt;
}
:fsdi.bi Fdt [Ra], OffImm12s is $(I32) & $(SDC) & Fdt & Ra & cpn=0 & fsbi=1 & OffImm12s {
*Ra = Fdt;
Ra = Ra + OffImm12s;
}
:fmfcfg Rt is $(I32) & $(COP) & fop4=0xc & Rt & f2op=0x0 & cop4=0x1 {
Rt = fpcfg;
}
:fmfcsr Rt is $(I32) & $(COP) & fop4=0xc & Rt & f2op=0x1 & cop4=0x1 {
Rt = fpcsr;
}
:fmtcsr Rt is $(I32) & $(COP) & fop4=0xc & Rt & Fsa & f2op=0x1 & cop4=0x9 {
fpcsr = Rt;
}