|
|
|
@ -0,0 +1,519 @@
|
|
|
|
|
define endian=big; define alignment=4;
|
|
|
|
|
define space ram type=ram_space size=4 default;
|
|
|
|
|
define space register type=register_space size=4;
|
|
|
|
|
|
|
|
|
|
define register offset=0 size=4 [
|
|
|
|
|
r0 r1 pc r3 sp fp r5 r7
|
|
|
|
|
rv r9 rr1 rr2 r12 r13 r14 rca
|
|
|
|
|
r16 r17 r18 r19 r20 r21 r22 r23
|
|
|
|
|
r24 r25 r26 r27 r28 r29 r30 r31
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
define token instr(32)
|
|
|
|
|
opcode0 = (31, 31)
|
|
|
|
|
opcode123 = (28, 30)
|
|
|
|
|
opcode012 = (29, 31)
|
|
|
|
|
opcode3 = (28, 28)
|
|
|
|
|
opcode = (28, 31)
|
|
|
|
|
# BR: condition codes
|
|
|
|
|
brddd = (25, 27)
|
|
|
|
|
brscc = (24, 24)
|
|
|
|
|
rd = (23, 27)
|
|
|
|
|
slmsb = (18, 22)
|
|
|
|
|
rs1 = (18, 22)
|
|
|
|
|
# RI: set flags
|
|
|
|
|
f = (17, 17)
|
|
|
|
|
# RM: increment rs1
|
|
|
|
|
p = (17, 17)
|
|
|
|
|
# RI: shift by 16
|
|
|
|
|
h = (16, 16)
|
|
|
|
|
# RM: add constant to rs1
|
|
|
|
|
q = (16, 16)
|
|
|
|
|
# RR: condition codes
|
|
|
|
|
rri = (16, 16)
|
|
|
|
|
# SL(S/I): operation
|
|
|
|
|
slop = (16,17)
|
|
|
|
|
slop1 = (17,17)
|
|
|
|
|
slop3 = (15,17)
|
|
|
|
|
rs2 = (11, 15)
|
|
|
|
|
# RI: immediate & immediate sign
|
|
|
|
|
immsign = (15, 15)
|
|
|
|
|
imm = (0, 15)
|
|
|
|
|
splsys = (13, 14)
|
|
|
|
|
splsse = (12, 13)
|
|
|
|
|
splspq = (10, 11)
|
|
|
|
|
# RR: operation
|
|
|
|
|
bbb = (8, 10)
|
|
|
|
|
# RR: special operation
|
|
|
|
|
jjjjj = (3, 7)
|
|
|
|
|
jmpdstrel = (2, 15)
|
|
|
|
|
jmpdst = (2, 24)
|
|
|
|
|
# BR: condition codes
|
|
|
|
|
brrel = (1,1)
|
|
|
|
|
# RR: condition codes
|
|
|
|
|
rrddd = (0, 2)
|
|
|
|
|
bri = (0, 0)
|
|
|
|
|
splsimmsign = (9, 9)
|
|
|
|
|
splsimm = (0, 9)
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
define register offset=0x100 size=32 [
|
|
|
|
|
callproc
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
define register offset=0x180 size=1 [
|
|
|
|
|
zf # zero
|
|
|
|
|
nf # negative
|
|
|
|
|
vf # overflow
|
|
|
|
|
cf # carry
|
|
|
|
|
|
|
|
|
|
# pseudoflags
|
|
|
|
|
gepf # greater than or equal
|
|
|
|
|
ltpf # less than
|
|
|
|
|
gtpf # greater than
|
|
|
|
|
lepf # less than or equal
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
define register offset=0x200 size=4 [
|
|
|
|
|
flagy
|
|
|
|
|
flaga
|
|
|
|
|
flagb
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
define context callproc
|
|
|
|
|
callrca = (0, 0) noflow
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
attach variables [ rd rs1 rs2 ] [
|
|
|
|
|
r0 r1 pc r3 sp fp r5 r7
|
|
|
|
|
rv r9 rr1 rr2 r12 r13 r14 rca
|
|
|
|
|
r16 r17 r18 r19 r20 r21 r22 r23
|
|
|
|
|
r24 r25 r26 r27 r28 r29 r30 r31
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rs1val: rs1 is rs1 { export rs1; }
|
|
|
|
|
rs1val: rs1 is rs1 & rs1=0 { export 0:4; }
|
|
|
|
|
rs1val: rs1 is rs1 & rs1=1 { export 0xffffffff:4; }
|
|
|
|
|
rs1val: rs1 is rs1 & rs1=2 { local tmp:4=inst_start; export tmp; }
|
|
|
|
|
|
|
|
|
|
rs2val: rs2 is rs2 { export rs2; }
|
|
|
|
|
rs2val: rs2 is rs2 & rs2=0 { export 0:4; }
|
|
|
|
|
rs2val: rs2 is rs2 & rs2=1 { export 0xffffffff:4; }
|
|
|
|
|
rs2val: rs2 is rs2 & rs2=2 { local tmp:4=inst_start; export tmp; }
|
|
|
|
|
|
|
|
|
|
# RI (Register Immediate) instructions
|
|
|
|
|
with : opcode0=0 {
|
|
|
|
|
# why is this needed?
|
|
|
|
|
val: is epsilon { export 0:4; }
|
|
|
|
|
|
|
|
|
|
flags: is val & f=0 { export val; }
|
|
|
|
|
flags: ".f" is val & f=1 {
|
|
|
|
|
zf = (val == 0);
|
|
|
|
|
nf = (val s< 0);
|
|
|
|
|
vf = 0;
|
|
|
|
|
cf = 0;
|
|
|
|
|
gepf = !nf;
|
|
|
|
|
ltpf = nf;
|
|
|
|
|
gtpf = !zf & gepf;
|
|
|
|
|
lepf = zf | ltpf;
|
|
|
|
|
export val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
immval: imm is imm & h=0 {
|
|
|
|
|
local res:4 = zext(imm:2);
|
|
|
|
|
export res;
|
|
|
|
|
}
|
|
|
|
|
immval: shifted is imm & h=1 [ shifted = imm << 16; ] {
|
|
|
|
|
local res:4 = zext(imm:2) << 16;
|
|
|
|
|
export res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# ADD
|
|
|
|
|
with : opcode123=0b000 {
|
|
|
|
|
val: is rs1val & immval { local res:4 = rs1val + immval; export res; }
|
|
|
|
|
flags: ".f" is f=1 & val & rs1val & immval {
|
|
|
|
|
zf = (val == 0);
|
|
|
|
|
nf = (val s< 0);
|
|
|
|
|
vf = scarry(rs1val, immval);
|
|
|
|
|
cf = carry(rs1val, immval);
|
|
|
|
|
gepf = (nf & vf) | (!nf & !vf);
|
|
|
|
|
ltpf = nf != vf;
|
|
|
|
|
gtpf = !zf & gepf;
|
|
|
|
|
lepf = zf | ltpf;
|
|
|
|
|
export val;
|
|
|
|
|
}
|
|
|
|
|
op: "add" is epsilon { }
|
|
|
|
|
# mov
|
|
|
|
|
with : rs1=0 {
|
|
|
|
|
op: "mov" is epsilon { }
|
|
|
|
|
operands: immval, %rd is immval & rd {}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# SUB
|
|
|
|
|
with : opcode123=0b010 {
|
|
|
|
|
val: is rs1val & immval { local res:4 = rs1val - immval; export res; }
|
|
|
|
|
flags: ".f" is f=1 & val & rs1val & immval {
|
|
|
|
|
zf = (val == 0);
|
|
|
|
|
nf = (val s< 0);
|
|
|
|
|
vf = scarry(rs1val, immval);
|
|
|
|
|
cf = !(rs1val < immval);
|
|
|
|
|
gepf = rs1val s>= immval;
|
|
|
|
|
ltpf = rs1val s< immval;
|
|
|
|
|
gtpf = rs1val s> immval;
|
|
|
|
|
lepf = rs1val s<= immval;
|
|
|
|
|
export val;
|
|
|
|
|
}
|
|
|
|
|
op: "sub" is epsilon { }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# AND
|
|
|
|
|
with : opcode123=0b100 {
|
|
|
|
|
val: is rs1val & immval { local res:4 = rs1val & immval; export res; }
|
|
|
|
|
op: "and" is epsilon { }
|
|
|
|
|
immval: imm is imm & h=0 {
|
|
|
|
|
local res:4 = zext(imm:2) | 0xffff0000;
|
|
|
|
|
export res;
|
|
|
|
|
}
|
|
|
|
|
immval: shifted is imm & h=1 [ shifted = imm << 16; ] {
|
|
|
|
|
local res:4 = (zext(imm:2) << 16) | 0xffff;
|
|
|
|
|
export res;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# OR
|
|
|
|
|
with : opcode123=0b101 {
|
|
|
|
|
val: is rs1val & immval { local res:4 = rs1val | immval; export res; }
|
|
|
|
|
op: "or" is epsilon { }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# XOR
|
|
|
|
|
with : opcode123=0b110 {
|
|
|
|
|
val: is rs1val & immval { local res:4 = rs1val ^ immval; export res; }
|
|
|
|
|
op: "xor" is epsilon { }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# SHIFT (untested)
|
|
|
|
|
with : opcode123=0b111 {
|
|
|
|
|
shiftnum: imm is imm {
|
|
|
|
|
local res:4 = sext(imm:2);
|
|
|
|
|
export res;
|
|
|
|
|
}
|
|
|
|
|
val: is rs1val & shiftnum & immsign=0 { local res:4 = rs1val << shiftnum; export res; }
|
|
|
|
|
val: is rs1val & shiftnum & h=0 & immsign=1 { local res:4 = rs1val >> -shiftnum; export res; }
|
|
|
|
|
val: is rs1val & shiftnum & h=1 & immsign=1 { local res:4 = rs1val s>> -shiftnum; export res; }
|
|
|
|
|
op: "sh" is h=0 { }
|
|
|
|
|
op: "sha" is h=1 { }
|
|
|
|
|
operands: %rs1val, shiftnum, %rd is rs1val & shiftnum & rd {
|
|
|
|
|
build shiftnum;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
operands: %rs1val, immval, %rd is rs1val & immval & rd {
|
|
|
|
|
build immval;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
:^op^flags operands is op & operands & rd & flags {
|
|
|
|
|
build operands;
|
|
|
|
|
build flags;
|
|
|
|
|
rd = flags;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
:nop is rd=0 & f=0 { }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# RR (Register Register) instructions
|
|
|
|
|
with : opcode=0b1100 {
|
|
|
|
|
rrcond: is rrddd=0b000 & rri=0 { }
|
|
|
|
|
rrcond: ".f" is rrddd=0b000 & rri=1 { goto inst_next; }
|
|
|
|
|
# a.k.k. HI
|
|
|
|
|
rrcond: ".ugt" is rrddd=0b001 & rri=0 { if (!(cf & !zf)) goto inst_next; }
|
|
|
|
|
# a.k.a. LS
|
|
|
|
|
rrcond: ".ule" is rrddd=0b010 & rri=1 { if (!(!cf | zf)) goto inst_next; }
|
|
|
|
|
# a.k.a. CC
|
|
|
|
|
rrcond: ".ult" is rrddd=0b010 & rri=0 { if(cf) goto inst_next; }
|
|
|
|
|
# a.k.a. CS
|
|
|
|
|
rrcond: ".uge" is rrddd=0b011 & rri=1 { if (!cf) goto inst_next; }
|
|
|
|
|
|
|
|
|
|
flags: is val & f=0 { export val; }
|
|
|
|
|
flags: ".f" is val & f=1 {
|
|
|
|
|
zf = (val == 0);
|
|
|
|
|
nf = (val s< 0);
|
|
|
|
|
vf = 0;
|
|
|
|
|
cf = 0;
|
|
|
|
|
gepf = !nf;
|
|
|
|
|
ltpf = nf;
|
|
|
|
|
gtpf = !zf & gepf;
|
|
|
|
|
lepf = zf | ltpf;
|
|
|
|
|
export val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# ADD
|
|
|
|
|
with : bbb=0b000 {
|
|
|
|
|
val: is rs1val & rs2val { local res:4 = rs1val + rs2val; export res; }
|
|
|
|
|
flags: ".f" is f=1 & val & rs1val & rs2val {
|
|
|
|
|
zf = (val == 0);
|
|
|
|
|
nf = (val s< 0);
|
|
|
|
|
vf = scarry(rs1val, rs2val);
|
|
|
|
|
cf = carry(rs1val, rs2val);
|
|
|
|
|
export val;
|
|
|
|
|
}
|
|
|
|
|
op: "add" is epsilon { }
|
|
|
|
|
# mov
|
|
|
|
|
with : rs2=0 {
|
|
|
|
|
op: "mov" is epsilon { }
|
|
|
|
|
operands: %rs1val, %rd is rs1val & rd {}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# SUB
|
|
|
|
|
with : bbb=0b010 {
|
|
|
|
|
val: is rs1val & rs2val { local res:4 = rs1val - rs2val; export res; }
|
|
|
|
|
flags: ".f" is f=1 & val & rs1val & rs2val {
|
|
|
|
|
zf = (val == 0);
|
|
|
|
|
nf = (val s< 0);
|
|
|
|
|
vf = scarry(rs1val, rs2val);
|
|
|
|
|
cf = !(rs1val < rs2val);
|
|
|
|
|
gepf = rs1val s>= rs2val;
|
|
|
|
|
ltpf = rs1val s< rs2val;
|
|
|
|
|
gtpf = rs1val s> rs2val;
|
|
|
|
|
lepf = rs1val s<= rs2val;
|
|
|
|
|
export val;
|
|
|
|
|
}
|
|
|
|
|
op: "sub" is epsilon { }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# AND
|
|
|
|
|
with : bbb=0b100 {
|
|
|
|
|
val: is rs1val & rs2val { local res:4 = rs1val & rs2val; export res; }
|
|
|
|
|
op: "and" is epsilon { }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# OR
|
|
|
|
|
with : bbb=0b101 {
|
|
|
|
|
val: is rs1val & rs2val { local res:4 = rs1val | rs2val; export res; }
|
|
|
|
|
op: "or" is epsilon { }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# XOR
|
|
|
|
|
with : bbb=0b110 {
|
|
|
|
|
val: is rs1val & rs2val { local res:4 = rs1val ^ rs2val; export res; }
|
|
|
|
|
op: "xor" is epsilon { }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# SHIFT (untested)
|
|
|
|
|
with : bbb=0b111 {
|
|
|
|
|
val: is rs1val & rs2val { local res:4 = rs1val << rs2val; export res; }
|
|
|
|
|
op: "sh" is epsilon { }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
operands: %rs1val, %rs2val, %rd is rs1val & rs2val & rd {}
|
|
|
|
|
|
|
|
|
|
:^op^rrcond operands is op & operands & rd & rrcond & flags {
|
|
|
|
|
build rrcond;
|
|
|
|
|
build flags;
|
|
|
|
|
rd = flags;
|
|
|
|
|
}
|
|
|
|
|
:^op^rrcond operands is op & operands & rd & rrcond & flags & rd=2 {
|
|
|
|
|
build rrcond;
|
|
|
|
|
build flags;
|
|
|
|
|
delayslot(4);
|
|
|
|
|
goto [flags];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
:nop is rd=0 & f=0 { }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# RM (Register Memory) instructions
|
|
|
|
|
with : opcode012=0b100 {
|
|
|
|
|
immsigned: imm is immsign=0 & imm { local v:4 = sext(imm:2); export v; }
|
|
|
|
|
immsigned: -val is immsign=1 & imm [ val=(imm^0xffff)+1; ] { local v:4 = sext(imm:2); export v; }
|
|
|
|
|
stdst: [%rs1val] is rs1val & imm=0 & p=0 & q=0 {
|
|
|
|
|
export rs1val;
|
|
|
|
|
}
|
|
|
|
|
stdst: immsigned[%rs1val] is rs1val & immsigned & p=1 & q=0 {
|
|
|
|
|
local v:4 = rs1val+immsigned; export v;
|
|
|
|
|
}
|
|
|
|
|
stdst: [--%rs1val] is rs1 & rs1val & imm=0xfffc & p=1 & q=1 {
|
|
|
|
|
rs1 = rs1val - 4;
|
|
|
|
|
local v:4 = rs1; export v;
|
|
|
|
|
}
|
|
|
|
|
stdst: [++%rs1val] is rs1 & rs1val & imm=0x0004 & p=1 & q=1 {
|
|
|
|
|
rs1 = rs1val + 4;
|
|
|
|
|
local v:4 = rs1val; export v;
|
|
|
|
|
}
|
|
|
|
|
stdst: [%rs1val++] is rs1 & rs1val & imm=0x0004 & p=0 & q=1 {
|
|
|
|
|
local v:4 = rs1;
|
|
|
|
|
rs1 = rs1val + 4;
|
|
|
|
|
export v;
|
|
|
|
|
}
|
|
|
|
|
# Stores
|
|
|
|
|
with : opcode3=1 {
|
|
|
|
|
:st %rd, stdst is rd & stdst {
|
|
|
|
|
*stdst = rd;
|
|
|
|
|
}
|
|
|
|
|
push: is rs1=4 & imm=0xfffc & p=1 & q=1 {}
|
|
|
|
|
:st %rd, stdst ! "call" is rd & stdst & rd=15 & push [ callrca=1; globalset(inst_next, callrca); ] {
|
|
|
|
|
*stdst = rd;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
# Loads
|
|
|
|
|
with : opcode3=0 {
|
|
|
|
|
:ld stdst, %rd is rd & stdst {
|
|
|
|
|
rd = *stdst;
|
|
|
|
|
}
|
|
|
|
|
:ld stdst, %rd ! "return" is rd & rd=2 & stdst {
|
|
|
|
|
local v:4 = *stdst;
|
|
|
|
|
delayslot(8);
|
|
|
|
|
return [v];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# SCC (Conditional Set) instructions
|
|
|
|
|
with : opcode=0b1110 & brscc=0 & brrel=1 {
|
|
|
|
|
bcond: "t" is brddd=0b000 & bri=0 { local c:1 = 1; export c; }
|
|
|
|
|
bcond: "f" is brddd=0b000 & bri=1 { local c:1 = 0; export c; }
|
|
|
|
|
bcond: "ugt" is brddd=0b001 & bri=0 { local c:1 = (cf & !zf); export c; }
|
|
|
|
|
bcond: "ule" is brddd=0b001 & bri=1 { local c:1 = (!cf | zf); export c; }
|
|
|
|
|
bcond: "ult" is brddd=0b010 & bri=0 { local c:1 = !cf; export c; }
|
|
|
|
|
bcond: "uge" is brddd=0b010 & bri=1 { local c:1 = cf; export c; }
|
|
|
|
|
bcond: "ne" is brddd=0b011 & bri=0 { local c:1 = !zf; export c; }
|
|
|
|
|
bcond: "eq" is brddd=0b011 & bri=1 { local c:1 = zf; export c; }
|
|
|
|
|
bcond: "pl" is brddd=0b101 & bri=0 { local c:1 = !nf; export c; }
|
|
|
|
|
bcond: "mi" is brddd=0b101 & bri=1 { local c:1 = nf; export c; }
|
|
|
|
|
bcond: "ge" is brddd=0b110 & bri=0 { local c:1 = gepf; export c; }
|
|
|
|
|
bcond: "lt" is brddd=0b110 & bri=1 { local c:1 = ltpf; export c; }
|
|
|
|
|
bcond: "gt" is brddd=0b111 & bri=0 { local c:1 = gtpf; export c; }
|
|
|
|
|
bcond: "le" is brddd=0b111 & bri=1 { local c:1 = lepf; export c; }
|
|
|
|
|
|
|
|
|
|
:s^bcond is bcond & rs1 {
|
|
|
|
|
rs1 = zext(bcond);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# BR (Conditional Branch) instructions
|
|
|
|
|
with : opcode=0b1110 {
|
|
|
|
|
bcond: "t" is brddd=0b000 & bri=0 { local c:1 = 1; export c; }
|
|
|
|
|
bcond: "f" is brddd=0b000 & bri=1 { local c:1 = 0; export c; }
|
|
|
|
|
bcond: "ugt" is brddd=0b001 & bri=0 { local c:1 = (cf & !zf); export c; }
|
|
|
|
|
bcond: "ule" is brddd=0b001 & bri=1 { local c:1 = (!cf | zf); export c; }
|
|
|
|
|
bcond: "ult" is brddd=0b010 & bri=0 { local c:1 = !cf; export c; }
|
|
|
|
|
bcond: "uge" is brddd=0b010 & bri=1 { local c:1 = cf; export c; }
|
|
|
|
|
bcond: "ne" is brddd=0b011 & bri=0 { local c:1 = !zf; export c; }
|
|
|
|
|
bcond: "eq" is brddd=0b011 & bri=1 { local c:1 = zf; export c; }
|
|
|
|
|
bcond: "pl" is brddd=0b101 & bri=0 { local c:1 = !nf; export c; }
|
|
|
|
|
bcond: "mi" is brddd=0b101 & bri=1 { local c:1 = nf; export c; }
|
|
|
|
|
bcond: "ge" is brddd=0b110 & bri=0 { local c:1 = gepf; export c; }
|
|
|
|
|
bcond: "lt" is brddd=0b110 & bri=1 { local c:1 = ltpf; export c; }
|
|
|
|
|
bcond: "gt" is brddd=0b111 & bri=0 { local c:1 = gtpf; export c; }
|
|
|
|
|
bcond: "le" is brddd=0b111 & bri=1 { local c:1 = lepf; export c; }
|
|
|
|
|
|
|
|
|
|
reloc: target is jmpdst & brrel=0 [ target=(jmpdst<<2); ] { export *[ram]:4 target; }
|
|
|
|
|
reloc: %rs1val+rel is jmpdstrel & rs1val & brrel=1 & brscc=1 [ rel=(jmpdstrel<<2); ] { local target:4=(jmpdstrel<<2)+rs1val; export *[ram]:4 target; }
|
|
|
|
|
|
|
|
|
|
:b^bcond reloc ! "loop" is reloc & bcond & callrca=0 & brrel=1 & brscc=1 & jmpdstrel=0 & rs1=2 {
|
|
|
|
|
delayslot(4);
|
|
|
|
|
goto inst_start;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
:b^bcond reloc is reloc & bcond & callrca=0 {
|
|
|
|
|
delayslot(4);
|
|
|
|
|
if (bcond) goto reloc;
|
|
|
|
|
}
|
|
|
|
|
:b^bcond target ! "call" is bcond & jmpdst & callrca=1 [ target = (jmpdst << 2); ] {
|
|
|
|
|
delayslot(4);
|
|
|
|
|
local to:4 = zext(jmpdst:4 << 2);
|
|
|
|
|
if (!bcond) goto <skip>;
|
|
|
|
|
call [to];
|
|
|
|
|
<skip>
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# SLI (Special Load Immediate) instructions
|
|
|
|
|
with : opcode=0b1111 & slop=0b10 {
|
|
|
|
|
:mov const, %rd is rd & slmsb & imm [
|
|
|
|
|
const=(slmsb<<16)|(imm);
|
|
|
|
|
] {
|
|
|
|
|
rd = (slmsb << 16) | (imm);
|
|
|
|
|
}
|
|
|
|
|
:mov const, %rd ! "call" is rd & slmsb & imm & rd=15 [
|
|
|
|
|
const=(slmsb<<16)|(imm);
|
|
|
|
|
callrca=1; globalset(inst_next, callrca);
|
|
|
|
|
] {
|
|
|
|
|
rd = (slmsb << 16) | (imm);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# SLS (Special Load/Store) instructions
|
|
|
|
|
with : opcode=0b1111 & slop1=0 {
|
|
|
|
|
with : slop=0b00 {
|
|
|
|
|
src: [addr] is slmsb & imm [
|
|
|
|
|
addr=(slmsb<<16)|(imm&0xfffc);
|
|
|
|
|
] { local v:4 = addr; export v; }
|
|
|
|
|
:ld src, %rd is rd & src {
|
|
|
|
|
rd = *src;
|
|
|
|
|
}
|
|
|
|
|
:ld src, %rd is rd & src & rd=2 {
|
|
|
|
|
delayslot(8);
|
|
|
|
|
goto [src];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
:st %rd, [addr] is slop=0b01 & slmsb & imm & rd [ addr=(slmsb<<16)|(imm&0xfffc); ] {
|
|
|
|
|
*addr:4 = rd;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# SPLS (Special Part-Word Load/Store) (SPLS)
|
|
|
|
|
with : opcode=0b1111 & slop3=0b110 {
|
|
|
|
|
immsigned: splsimm is splsimmsign=0 & splsimm { local v:4 = sext(splsimm:2); export v; }
|
|
|
|
|
immsigned: -val is splsimmsign=1 & splsimm [ val=(splsimm^0x3ff)+1; ] { local v:4 = sext(splsimm:2); export v; }
|
|
|
|
|
stdst: [%rs1] is rs1 & splsimm=0 & splspq=0b00 {
|
|
|
|
|
export rs1;
|
|
|
|
|
}
|
|
|
|
|
stdst: immsigned[%rs1] is rs1 & immsigned & splspq=0b10 {
|
|
|
|
|
local v:4 = rs1+immsigned; export v;
|
|
|
|
|
}
|
|
|
|
|
stdst: [--%rs1] is rs1 & splsimm=0x3ff & splspq=0b11 {
|
|
|
|
|
rs1 = rs1 - 1;
|
|
|
|
|
local v:4 = rs1; export v;
|
|
|
|
|
}
|
|
|
|
|
stdst: [++%rs1] is rs1 & splsimm=0x001 & splspq=0b11 {
|
|
|
|
|
rs1 = rs1 + 1;
|
|
|
|
|
local v:4 = rs1; export v;
|
|
|
|
|
}
|
|
|
|
|
stdst: [%rs1++] is rs1 & splsimm=0x001 & splspq=0b01 {
|
|
|
|
|
local v:4 = rs1;
|
|
|
|
|
rs1 = rs1 + 1;
|
|
|
|
|
export v;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
:uld.b stdst, %rd is splsys=0b10 & splsse=0b01 & rd & stdst {
|
|
|
|
|
local b:1 = *stdst;
|
|
|
|
|
local v:4 = zext(b);
|
|
|
|
|
rd = v;
|
|
|
|
|
}
|
|
|
|
|
:uld.h stdst, %rd is splsys=0b00 & splsse=0b01 & rd & stdst {
|
|
|
|
|
local b:2 = *stdst;
|
|
|
|
|
local v:4 = zext(b);
|
|
|
|
|
rd = v;
|
|
|
|
|
}
|
|
|
|
|
:ld.b stdst, %rd is splsys=0b10 & splsse=0b00 & rd & stdst {
|
|
|
|
|
local b:1 = *stdst;
|
|
|
|
|
local v:4 = zext(b);
|
|
|
|
|
rd = v;
|
|
|
|
|
}
|
|
|
|
|
:ld.h stdst, %rd is splsys=0b00 & splsse=0b00 & rd & stdst {
|
|
|
|
|
local b:2 = *stdst;
|
|
|
|
|
local v:4 = zext(b);
|
|
|
|
|
rd = v;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
:st.b %rd, stdst is splsys=0b11 & splsse=0b10 & rd & stdst {
|
|
|
|
|
*stdst = rd[0,8];
|
|
|
|
|
}
|
|
|
|
|
:st.h %rd, stdst is splsys=0b01 & splsse=0b10 & rd & stdst {
|
|
|
|
|
*stdst = rd[0,16];
|
|
|
|
|
}
|
|
|
|
|
}
|