mirror of
https://github.com/NationalSecurityAgency/ghidra
synced 2024-10-13 13:43:00 +00:00
1411 lines
31 KiB
Plaintext
1411 lines
31 KiB
Plaintext
# All assembly defintions taken from: http://www.shared-ptr.com/sh_insns.html
|
|
|
|
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 register offset=0 size=4
|
|
[r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15];
|
|
|
|
define register offset=0x100 size=4 [sr gbr vbr mach macl pr pc];
|
|
|
|
# SR Flags
|
|
@define T_FLAG "sr[0,1]"
|
|
@define S_FLAG "sr[1,1]"
|
|
@define I0_FLAG "sr[4,1]"
|
|
@define I1_FLAG "sr[5,1]"
|
|
@define I2_FLAG "sr[6,1]"
|
|
@define I3_FLAG "sr[7,1]"
|
|
@define Q_FLAG "sr[8,1]"
|
|
@define M_FLAG "sr[9,1]"
|
|
|
|
define token instr(16)
|
|
disp_00_03 = (0, 3)
|
|
sdisp_00_03 = (0, 3) signed
|
|
disp_00_07 = (0, 7)
|
|
sdisp_00_07 = (0, 7) signed
|
|
disp_00_11 = (0, 11)
|
|
sdisp_00_11 = (0, 11) signed
|
|
imm_00_07 = (0, 7)
|
|
simm_00_07 = (0, 7) signed
|
|
opcode_00_03 = (0, 3)
|
|
opcode_00_07 = (0, 7)
|
|
opcode_00_15 = (0, 15)
|
|
opcode_04_07 = (4, 7)
|
|
opcode_08_11 = (8, 11)
|
|
opcode_08_15 = (8, 15)
|
|
opcode_12_15 = (12, 15)
|
|
rm_04_07 = (4, 7)
|
|
rm_08_11 = (8, 11)
|
|
rn_04_07 = (4, 7)
|
|
rn_08_11 = (8, 11)
|
|
;
|
|
|
|
attach variables [ rm_04_07 rm_08_11 rn_04_07 rn_08_11 ] [
|
|
r0 r1 r2 r3 r4 r5 r6 r7
|
|
r8 r9 r10 r11 r12 r13 r14 r15
|
|
];
|
|
|
|
# helpers for branch
|
|
target00_07: target is sdisp_00_07 [ target = (sdisp_00_07 << 1) + inst_start + 4; ] {
|
|
export *:4 target;
|
|
}
|
|
|
|
target00_11: target is sdisp_00_11 [ target = (sdisp_00_11 << 1) + inst_start + 4; ] {
|
|
export *:4 target;
|
|
}
|
|
|
|
#
|
|
# Data Transfer Instructions
|
|
#
|
|
|
|
:mov rm_04_07, rn_08_11 is opcode_12_15=0b0110 & rn_08_11 & rm_04_07 & opcode_00_03=0b0011
|
|
{
|
|
rn_08_11 = rm_04_07;
|
|
}
|
|
|
|
:mov simm_00_07,rn_08_11 is opcode_12_15=0b1110 & rn_08_11 & simm_00_07
|
|
{
|
|
rn_08_11 = simm_00_07;
|
|
}
|
|
|
|
:mova @(disp,pc),r0 is r0 & pc & opcode_08_15=0b11000111 & disp_00_07 [disp = (disp_00_07 << 2); ]
|
|
{
|
|
local temp:4 = inst_start;
|
|
r0 = disp + (temp & 0xFFFFFFFC) + 4;
|
|
}
|
|
|
|
:mov.w @(target,pc),rn_08_11 is pc & opcode_12_15=0b1001 & rn_08_11 & disp_00_07 [ target = (disp_00_07 << 1) + 4; ]
|
|
{
|
|
local temp:4 = inst_start;
|
|
rn_08_11 = sext(*:2 (temp + target));
|
|
}
|
|
|
|
:mov.l @(disp,pc),rn_08_11 is pc & opcode_12_15=0b1101 & rn_08_11 & disp_00_07 [disp = (disp_00_07 << 2) + 4; ]
|
|
{
|
|
local temp:4 = inst_start;
|
|
rn_08_11 = *:4 ((temp & 0xFFFFFFFC) + disp);
|
|
}
|
|
|
|
:mov.b @rm_04_07,rn_08_11 is opcode_12_15=0b0110 & rn_08_11 & rm_04_07 & opcode_00_03=0b0000
|
|
{
|
|
rn_08_11 = sext(*:1 rm_04_07);
|
|
}
|
|
|
|
:mov.w @rm_04_07,rn_08_11 is opcode_12_15=0b0110 & rn_08_11 & rm_04_07 & opcode_00_03=0b0001
|
|
{
|
|
rn_08_11 = sext(*:2 rm_04_07);
|
|
}
|
|
|
|
:mov.l @rm_04_07,rn_08_11 is opcode_12_15=0b0110 & rn_08_11 & rm_04_07 & opcode_00_03=0b0010
|
|
{
|
|
rn_08_11 = *:4 rm_04_07;
|
|
}
|
|
|
|
:mov.b rm_04_07,@rn_08_11 is opcode_12_15=0b0010 & rn_08_11 & rm_04_07 & opcode_00_03=0b0000
|
|
{
|
|
*:1 rn_08_11 = rm_04_07:1;
|
|
}
|
|
|
|
:mov.w rm_04_07,@rn_08_11 is opcode_12_15=0b0010 & rn_08_11 & rm_04_07 & opcode_00_03=0b0001
|
|
{
|
|
*:2 rn_08_11 = rm_04_07:2;
|
|
}
|
|
|
|
:mov.l rm_04_07,@rn_08_11 is opcode_12_15=0b0010 & rn_08_11 & rm_04_07 & opcode_00_03=0b0010
|
|
{
|
|
*:4 rn_08_11 = rm_04_07;
|
|
}
|
|
|
|
:mov.b @rm_04_07+,rn_08_11 is opcode_12_15=0b0110 & rn_08_11 & rm_04_07 & opcode_00_03=0b0100 & opcode_04_07 & opcode_08_11
|
|
{
|
|
rn_08_11 = sext(*:1 rm_04_07);
|
|
|
|
local m:4 = opcode_04_07;
|
|
local n:4 = opcode_08_11;
|
|
|
|
# Check n != m
|
|
if(m == n) goto <END>;
|
|
rm_04_07 = rm_04_07 + 1;
|
|
|
|
<END>
|
|
}
|
|
|
|
:mov.w @rm_04_07+,rn_08_11 is opcode_12_15=0b0110 & rn_08_11 & rm_04_07 & opcode_00_03=0b0101 & opcode_04_07 & opcode_08_11
|
|
{
|
|
rn_08_11 = sext(*:2 rm_04_07);
|
|
|
|
local m:4 = opcode_04_07;
|
|
local n:4 = opcode_08_11;
|
|
|
|
# Check n != m
|
|
if(m == n) goto <END>;
|
|
rm_04_07 = rm_04_07 + 2;
|
|
|
|
<END>
|
|
}
|
|
|
|
:mov.l @rm_04_07+,rn_08_11 is opcode_12_15=0b0110 & rn_08_11 & rm_04_07 & opcode_00_03=0b0110 & opcode_04_07 & opcode_08_11
|
|
{
|
|
rn_08_11 = *:4 rm_04_07;
|
|
|
|
local m:4 = opcode_04_07;
|
|
local n:4 = opcode_08_11;
|
|
|
|
# Check n != m
|
|
if(m == n) goto <END>;
|
|
rm_04_07 = rm_04_07 + 4;
|
|
|
|
<END>
|
|
}
|
|
|
|
:mov.b rm_04_07,@-rn_08_11 is opcode_12_15=0b0010 & rn_08_11 & rm_04_07 & opcode_00_03=0b0100
|
|
{
|
|
rn_08_11 = rn_08_11 -1;
|
|
*:1 rn_08_11 = rm_04_07;
|
|
}
|
|
|
|
:mov.w rm_04_07,@-rn_08_11 is opcode_12_15=0b0010 & rn_08_11 & rm_04_07 & opcode_00_03=0b0101
|
|
{
|
|
rn_08_11 = rn_08_11 -2;
|
|
*:2 rn_08_11 = rm_04_07;
|
|
}
|
|
|
|
:mov.l rm_04_07,@-rn_08_11 is opcode_12_15=0b0010 & rn_08_11 & rm_04_07 & opcode_00_03=0b0110
|
|
{
|
|
rn_08_11 = rn_08_11 -4;
|
|
*:4 rn_08_11 = rm_04_07;
|
|
}
|
|
|
|
:mov.b @(disp_00_03,rm_04_07),r0 is r0 & opcode_08_15=0b10000100 & rm_04_07 & disp_00_03
|
|
{
|
|
r0 = sext(*:1 (disp_00_03 + rm_04_07));
|
|
}
|
|
|
|
:mov.w @(disp,rm_04_07),r0 is r0 & opcode_08_15=0b10000101 & rm_04_07 & disp_00_03 [ disp = disp_00_03 << 1; ]
|
|
{
|
|
r0 = sext(*:2 (disp + rm_04_07));
|
|
}
|
|
|
|
:mov.l @(disp,rm_04_07),rn_08_11 is opcode_12_15=0b0101 & rn_08_11 & rm_04_07 & disp_00_03 [ disp = disp_00_03 << 2; ]
|
|
{
|
|
rn_08_11 = *:4 (disp + rm_04_07);
|
|
}
|
|
|
|
:mov.b r0,@(disp_00_03,rn_04_07) is r0 & opcode_08_15=0b10000000 & rn_04_07 & disp_00_03
|
|
{
|
|
*:1 (rn_04_07 + disp_00_03) = r0:1;
|
|
}
|
|
|
|
:mov.w r0,@(disp,rn_04_07) is r0 & opcode_08_15=0b10000001 & rn_04_07 & disp_00_03 [ disp = disp_00_03 << 1; ]
|
|
{
|
|
*:2 (rn_04_07 + disp) = r0:2;
|
|
}
|
|
|
|
:mov.l rm_04_07,@(disp,rn_08_11) is opcode_12_15=0b0001 & rn_08_11 & rm_04_07 & disp_00_03 [ disp = disp_00_03 << 2; ]
|
|
{
|
|
*:4 (rn_08_11 + disp) = rm_04_07;
|
|
}
|
|
|
|
:mov.b @(r0,rm_04_07),rn_08_11 is r0 & opcode_12_15=0b0000 & rn_08_11 & rm_04_07 & opcode_00_03=0b1100
|
|
{
|
|
rn_08_11 = sext(*:1 (rm_04_07 + r0));
|
|
}
|
|
|
|
:mov.w @(r0,rm_04_07),rn_08_11 is r0 & opcode_12_15=0b0000 & rn_08_11 & rm_04_07 & opcode_00_03=0b1101
|
|
{
|
|
rn_08_11 = sext(*:2 (rm_04_07 + r0));
|
|
}
|
|
|
|
:mov.l @(r0,rm_04_07),rn_08_11 is r0 & opcode_12_15=0b0000 & rn_08_11 & rm_04_07 & opcode_00_03=0b1110
|
|
{
|
|
rn_08_11 = *:4 (rm_04_07 + r0);
|
|
}
|
|
|
|
:mov.b rm_04_07,@(r0,rn_08_11) is r0 & opcode_12_15=0b0000 & rn_08_11 & rm_04_07 & opcode_00_03=0b0100
|
|
{
|
|
*:1 (rn_08_11 + r0) = rm_04_07;
|
|
}
|
|
|
|
:mov.w rm_04_07,@(r0,rn_08_11) is r0 & opcode_12_15=0b0000 & rn_08_11 & rm_04_07 & opcode_00_03=0b0101
|
|
{
|
|
*:2 (rn_08_11 + r0) = rm_04_07;
|
|
}
|
|
|
|
:mov.l rm_04_07,@(r0,rn_08_11) is r0 & opcode_12_15=0b0000 & rn_08_11 & rm_04_07 & opcode_00_03=0b0110
|
|
{
|
|
*:4 (rn_08_11 + r0) = rm_04_07;
|
|
}
|
|
|
|
:mov.b @(disp_00_07,gbr),r0 is gbr & r0 & opcode_08_15=0b11000100 & disp_00_07
|
|
{
|
|
r0 = sext(*:1 (gbr + disp_00_07));
|
|
}
|
|
|
|
:mov.w @(disp,gbr),r0 is gbr & r0 & opcode_08_15=0b11000101 & disp_00_07 [disp = (disp_00_07 << 1); ]
|
|
{
|
|
r0 = sext(*:2 (gbr + disp));
|
|
}
|
|
|
|
:mov.l @(disp,gbr),r0 is gbr & r0 & opcode_08_15=0b11000110 & disp_00_07 [disp = (disp_00_07 << 2); ]
|
|
{
|
|
r0 = *:4 (gbr + disp);
|
|
}
|
|
|
|
:mov.b r0,@(disp_00_07,gbr) is r0 & gbr & opcode_08_15=0b11000000 & disp_00_07
|
|
{
|
|
*:1 (gbr + disp_00_07) = r0;
|
|
}
|
|
|
|
:mov.w r0,@(disp,gbr) is r0 & gbr & opcode_08_15=0b11000001 & disp_00_07 [disp = (disp_00_07 << 1); ]
|
|
{
|
|
*:2 (gbr + disp) = r0;
|
|
}
|
|
|
|
:mov.l r0,@(disp,gbr) is r0 & gbr & opcode_08_15=0b11000010 & disp_00_07 [disp = (disp_00_07 << 2); ]
|
|
{
|
|
*:4 (gbr + disp) = r0;
|
|
}
|
|
|
|
:movt rn_08_11 is opcode_12_15=0b0000 & rn_08_11 & opcode_00_07=0b00101001
|
|
{
|
|
rn_08_11 = zext($(T_FLAG));
|
|
}
|
|
|
|
:swap.b rm_04_07,rn_08_11 is opcode_12_15=0b0110 & rn_08_11 & rm_04_07 & opcode_00_03=0b1000
|
|
{
|
|
local temp0;
|
|
local temp1;
|
|
|
|
temp0 = rm_04_07 & 0xFFFF0000;
|
|
temp1 = (rm_04_07 & 0x000000FF) << 8;
|
|
|
|
rn_08_11 = (rm_04_07 & 0x0000FF00) >> 8;
|
|
rn_08_11 = rn_08_11 | temp1 | temp0;
|
|
}
|
|
|
|
:swap.w rm_04_07,rn_08_11 is opcode_12_15=0b0110 & rn_08_11 & rm_04_07 & opcode_00_03=0b1001
|
|
{
|
|
local temp;
|
|
|
|
temp = (rm_04_07 >> 16) & 0x0000FFFF;
|
|
|
|
rn_08_11 = rm_04_07 << 16;
|
|
rn_08_11 = rn_08_11 | temp;
|
|
}
|
|
|
|
:xtrct rm_04_07,rn_08_11 is opcode_12_15=0b0010 & rn_08_11 & rm_04_07 & opcode_00_03=0b1101
|
|
{
|
|
local high;
|
|
local low;
|
|
|
|
high = (rm_04_07 << 16) & 0xFFFF0000;
|
|
low = (rn_08_11 >> 16) & 0x0000FFFF;
|
|
rn_08_11 = high | low;
|
|
}
|
|
|
|
#
|
|
# Arithmetic Operation Instructions
|
|
#
|
|
:add rm_04_07,rn_08_11 is opcode_12_15=0b0011 & rn_08_11 & rm_04_07 & opcode_00_03=0b1100
|
|
{
|
|
rn_08_11 = rn_08_11 + rm_04_07;
|
|
}
|
|
|
|
:add imm_00_07,rn_08_11 is opcode_12_15=0b0111 & rn_08_11 & imm_00_07
|
|
{
|
|
rn_08_11 = rn_08_11 + sext(imm_00_07:1);
|
|
}
|
|
|
|
:addc rm_04_07,rn_08_11 is opcode_12_15=0b0011 & rn_08_11 & rm_04_07 & opcode_00_03=0b1110
|
|
{
|
|
local temp0;
|
|
local temp1;
|
|
|
|
temp1 = rn_08_11 + rm_04_07;
|
|
temp0 = temp1;
|
|
|
|
rn_08_11 = temp1 + zext($(T_FLAG));
|
|
|
|
$(T_FLAG) = (temp0 > temp1) | (temp1 > rn_08_11);
|
|
}
|
|
|
|
:addv rm_04_07,rn_08_11 is opcode_12_15=0b0011 & rn_08_11 & rm_04_07 & opcode_00_03=0b1111
|
|
{
|
|
local dest:1;
|
|
local src:1;
|
|
local ans:1;
|
|
|
|
dest = (rn_08_11 s< 0);
|
|
src = (rm_04_07 s< 0);
|
|
|
|
src = src + dest;
|
|
rn_08_11 = rn_08_11 + rm_04_07;
|
|
|
|
ans = (rn_08_11 s< 0);
|
|
|
|
ans = ans + dest;
|
|
|
|
$(T_FLAG) = (src == 0 || src == 2) && (ans == 1);
|
|
}
|
|
|
|
:cmp"/eq" imm_00_07,r0 is r0 & opcode_08_15=0b10001000 & imm_00_07
|
|
{
|
|
local temp:4 = sext(imm_00_07:1);
|
|
|
|
$(T_FLAG) = (r0 == temp);
|
|
}
|
|
|
|
:cmp"/eq" rm_04_07,rn_08_11 is opcode_12_15=0b0011 & rn_08_11 & rm_04_07 & opcode_00_03=0b0000
|
|
{
|
|
$(T_FLAG) = (rn_08_11 == rm_04_07);
|
|
}
|
|
|
|
:cmp"/hs" rm_04_07,rn_08_11 is opcode_12_15=0b0011 & rn_08_11 & rm_04_07 & opcode_00_03=0b0010
|
|
{
|
|
$(T_FLAG) = (rn_08_11 >= rm_04_07);
|
|
}
|
|
|
|
:cmp"/ge" rm_04_07,rn_08_11 is opcode_12_15=0b0011 & rn_08_11 & rm_04_07 & opcode_00_03=0b0011
|
|
{
|
|
$(T_FLAG) = (rn_08_11 s>= rm_04_07);
|
|
}
|
|
|
|
:cmp"/hi" rm_04_07,rn_08_11 is opcode_12_15=0b0011 & rn_08_11 & rm_04_07 & opcode_00_03=0b0110
|
|
{
|
|
$(T_FLAG) = (rn_08_11 > rm_04_07);
|
|
}
|
|
|
|
:cmp"/gt" rm_04_07,rn_08_11 is opcode_12_15=0b0011 & rn_08_11 & rm_04_07 & opcode_00_03=0b0111
|
|
{
|
|
$(T_FLAG) = (rn_08_11 s> rm_04_07);
|
|
}
|
|
|
|
:cmp"/pl" rn_08_11 is opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b00010101
|
|
{
|
|
$(T_FLAG) = (rn_08_11 s> 0);
|
|
}
|
|
|
|
:cmp"/pz" rn_08_11 is opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b00010001
|
|
{
|
|
$(T_FLAG) = (rn_08_11 s>= 0);
|
|
}
|
|
|
|
:cmp"/str" rm_04_07,rn_08_11 is opcode_12_15=0b0010 & rn_08_11 & rm_04_07 & opcode_00_03=0b1100
|
|
{
|
|
local temp:4;
|
|
local HH:4;
|
|
local HL:4;
|
|
local LH:4;
|
|
local LL:4;
|
|
|
|
temp = rn_08_11 ^ rm_04_07;
|
|
|
|
HH = (temp & 0xFF000000) >> 24;
|
|
HL = (temp & 0x00FF0000) >> 16;
|
|
LH = (temp & 0x0000FF00) >> 8;
|
|
LL = (temp & 0x000000FF);
|
|
|
|
$(T_FLAG) = (HH != 0) && (HL != 0) && (LH != 0) && (LL != 0);
|
|
}
|
|
|
|
:div0s rm_04_07,rn_08_11 is opcode_12_15=0b0010 & rn_08_11 & rm_04_07 & opcode_00_03=0b0111
|
|
{
|
|
$(Q_FLAG) = !((rn_08_11 & 0x80000000) == 0);
|
|
$(M_FLAG) = !((rm_04_07 & 0x80000000) == 0);
|
|
|
|
$(T_FLAG) = !($(M_FLAG) == $(Q_FLAG));
|
|
}
|
|
|
|
:div0u is opcode_00_15=0b0000000000011001
|
|
{
|
|
$(M_FLAG) = 0;
|
|
$(Q_FLAG) = 0;
|
|
$(T_FLAG) = 0;
|
|
}
|
|
|
|
:div1 rm_04_07,rn_08_11 is opcode_12_15=0b0011 & rn_08_11 & rm_04_07 & opcode_00_03=0b0100
|
|
{
|
|
local tmp0:4;
|
|
local tmp1:1;
|
|
local tmp2:4;
|
|
local old_q:1;
|
|
|
|
old_q = $(Q_FLAG);
|
|
$(Q_FLAG) = (0x80000000 & rn_08_11) != 0;
|
|
tmp2 = rm_04_07;
|
|
rn_08_11 = rn_08_11 << 1;
|
|
rn_08_11 = rn_08_11 | zext($(T_FLAG));
|
|
|
|
# BUGBUG: cleaner way to do this??
|
|
|
|
if(old_q == 0 && $(M_FLAG) == 0 && $(Q_FLAG) == 0) goto <OQ0_M0_Q0>;
|
|
if(old_q == 0 && $(M_FLAG) == 0 && $(Q_FLAG) == 1) goto <OQ0_M0_Q1>;
|
|
if(old_q == 0 && $(M_FLAG) == 1 && $(Q_FLAG) == 0) goto <OQ0_M1_Q0>;
|
|
if(old_q == 0 && $(M_FLAG) == 1 && $(Q_FLAG) == 1) goto <OQ0_M1_Q1>;
|
|
if(old_q == 1 && $(M_FLAG) == 0 && $(Q_FLAG) == 0) goto <OQ1_M0_Q0>;
|
|
if(old_q == 1 && $(M_FLAG) == 0 && $(Q_FLAG) == 1) goto <OQ1_M0_Q1>;
|
|
if(old_q == 1 && $(M_FLAG) == 1 && $(Q_FLAG) == 0) goto <OQ1_M1_Q0>;
|
|
if(old_q == 1 && $(M_FLAG) == 1 && $(Q_FLAG) == 1) goto <OQ1_M1_Q1>;
|
|
|
|
<OQ0_M0_Q0>
|
|
tmp0 = rn_08_11;
|
|
rn_08_11 = rn_08_11 - tmp2;
|
|
tmp1 = rn_08_11 > tmp0;
|
|
$(Q_FLAG) = tmp1;
|
|
goto <SET_FLAG>;
|
|
|
|
<OQ0_M0_Q1>
|
|
tmp0 = rn_08_11;
|
|
rn_08_11 = rn_08_11 - tmp2;
|
|
tmp1 = rn_08_11 > tmp0;
|
|
$(Q_FLAG) = tmp1 == 0;
|
|
goto <SET_FLAG>;
|
|
|
|
<OQ0_M1_Q0>
|
|
tmp0 = rn_08_11;
|
|
rn_08_11 = rn_08_11 + tmp2;
|
|
tmp1 = rn_08_11 < tmp0;
|
|
$(Q_FLAG) = tmp1 == 0;
|
|
goto <SET_FLAG>;
|
|
|
|
<OQ0_M1_Q1>
|
|
tmp0 = rn_08_11;
|
|
rn_08_11 = rn_08_11 + tmp2;
|
|
tmp1 = rn_08_11 < tmp0;
|
|
$(Q_FLAG) = tmp1;
|
|
goto <SET_FLAG>;
|
|
|
|
<OQ1_M0_Q0>
|
|
tmp0 = rn_08_11;
|
|
rn_08_11 = rn_08_11 + tmp2;
|
|
tmp1 = rn_08_11 < tmp0;
|
|
$(Q_FLAG) = tmp1;
|
|
goto <SET_FLAG>;
|
|
|
|
<OQ1_M0_Q1>
|
|
tmp0 = rn_08_11;
|
|
rn_08_11 = rn_08_11 + tmp2;
|
|
tmp1 = rn_08_11 < tmp0;
|
|
$(Q_FLAG) = tmp1;
|
|
goto <SET_FLAG>;
|
|
|
|
<OQ1_M1_Q0>
|
|
tmp0 = rn_08_11;
|
|
rn_08_11 = rn_08_11 - tmp2;
|
|
tmp1 = rn_08_11 > tmp0;
|
|
$(Q_FLAG) = tmp1 == 0;
|
|
goto <SET_FLAG>;
|
|
|
|
<OQ1_M1_Q1>
|
|
tmp0 = rn_08_11;
|
|
rn_08_11 = rn_08_11 - tmp2;
|
|
tmp1 = rn_08_11 > tmp0;
|
|
$(Q_FLAG) = tmp1;
|
|
goto <SET_FLAG>;
|
|
|
|
<SET_FLAG>
|
|
$(T_FLAG) = $(Q_FLAG) == $(M_FLAG);
|
|
}
|
|
|
|
@if SH_VERSION == "2"
|
|
:dmuls.l rm_04_07,rn_08_11 is opcode_12_15=0b0011 & rn_08_11 & rm_04_07 & opcode_00_03=0b1101
|
|
{
|
|
local a:8 = sext(rn_08_11);
|
|
local b:8 = sext(rm_04_07);
|
|
local result:8 = a * b;
|
|
|
|
mach = result(4);
|
|
macl = result:4;
|
|
}
|
|
|
|
:dmulu.l rm_04_07,rn_08_11 is opcode_12_15=0b0011 & rn_08_11 & rm_04_07 & opcode_00_03=0b0101
|
|
{
|
|
local a:8 = zext(rn_08_11);
|
|
local b:8 = zext(rm_04_07);
|
|
local result:8 = a * b;
|
|
|
|
mach = result(4);
|
|
macl = result:4;
|
|
}
|
|
|
|
:dt rn_08_11 is opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b00010000
|
|
{
|
|
rn_08_11 = rn_08_11 - 1;
|
|
$(T_FLAG) = (rn_08_11 == 0);
|
|
}
|
|
@endif
|
|
|
|
:exts.b rm_04_07,rn_08_11 is opcode_12_15=0b0110 & rn_08_11 & rm_04_07 & opcode_00_03=0b1110
|
|
{
|
|
rn_08_11 = rm_04_07;
|
|
|
|
if((rm_04_07 & 0x00000080) == 0) goto <UNSIGNED>;
|
|
|
|
rn_08_11 = rn_08_11 | 0xFFFFFF00;
|
|
goto <END>;
|
|
|
|
<UNSIGNED>
|
|
rn_08_11 = rn_08_11 & 0x000000FF;
|
|
|
|
<END>
|
|
}
|
|
|
|
:exts.w rm_04_07,rn_08_11 is opcode_12_15=0b0110 & rn_08_11 & rm_04_07 & opcode_00_03=0b1111
|
|
{
|
|
rn_08_11 = rm_04_07;
|
|
|
|
if((rm_04_07 & 0x00008000) == 0) goto <UNSIGNED>;
|
|
|
|
rn_08_11 = rn_08_11 | 0xFFFF0000;
|
|
goto <END>;
|
|
|
|
<UNSIGNED>
|
|
rn_08_11 = rn_08_11 & 0x0000FFFF;
|
|
|
|
<END>
|
|
}
|
|
|
|
:extu.b rm_04_07,rn_08_11 is opcode_12_15=0b0110 & rn_08_11 & rm_04_07 & opcode_00_03=0b1100
|
|
{
|
|
rn_08_11 = rm_04_07 & 0x000000FF;
|
|
}
|
|
|
|
:extu.w rm_04_07,rn_08_11 is opcode_12_15=0b0110 & rn_08_11 & rm_04_07 & opcode_00_03=0b1101
|
|
{
|
|
rn_08_11 = rm_04_07 & 0x0000FFFF;
|
|
}
|
|
|
|
@if SH_VERSION == "2"
|
|
:mac.l @rm_04_07+,@rn_08_11+ is opcode_12_15=0b0000 & rn_08_11 & rm_04_07 & opcode_00_03=0b1111
|
|
{
|
|
# BUGBUG: review this instruction
|
|
|
|
local RnL;
|
|
local RnH;
|
|
local RmL;
|
|
local RmH;
|
|
local Res0;
|
|
local Res1:4;
|
|
local Res2:4;
|
|
|
|
local temp0;
|
|
local temp1:4;
|
|
local temp2:4;
|
|
local temp3;
|
|
|
|
local tempm:4;
|
|
local tempn:4;
|
|
local fnLmL:4;
|
|
|
|
tempn = *:4 rn_08_11;
|
|
rn_08_11 = rn_08_11 + 4;
|
|
tempm = *:4 rm_04_07;
|
|
rm_04_07 = rm_04_07 + 4;
|
|
|
|
if((tempn ^ tempm) s<0) goto <NEG>;
|
|
fnLmL = 0;
|
|
goto <END>;
|
|
<NEG>
|
|
fnLmL = -1;
|
|
|
|
if( tempn s>= 0) goto <SKIP_TEMPN>;
|
|
tempn = 0 - tempn;
|
|
|
|
<SKIP_TEMPN>
|
|
if( tempm s>= 0) goto <SKIP_TEMPM>;
|
|
tempm = 0 - tempm;
|
|
|
|
<SKIP_TEMPM>
|
|
|
|
temp1 = tempn;
|
|
temp2 = tempm;
|
|
|
|
RnL = temp1 & 0x0000FFFF;
|
|
RnH = (temp1 >> 16) & 0x0000FFFF;
|
|
RmL = temp2 & 0x0000FFFF;
|
|
RmH = (temp2 >> 16) & 0x0000FFFF;
|
|
temp0 = RmL * RnL;
|
|
temp1 = RmH * RnL;
|
|
temp2 = RmL * RnH;
|
|
temp3 = RmH * RnH;
|
|
|
|
Res2 = 0;
|
|
Res1 = temp1 + temp2;
|
|
|
|
if(Res2 >= temp1) goto <SKIP_RES2_ADD>;
|
|
Res2 = Res2 + 0x00010000;
|
|
<SKIP_RES2_ADD>
|
|
|
|
temp1 = (Res1 << 16) & 0xFFFF0000;
|
|
|
|
Res0 = temp0 + temp1;
|
|
Res2 = Res2 + zext(Res0 < temp0);
|
|
|
|
Res2 = Res2 + ((Res1 >> 16) & 0x0000FFFF) + temp3;
|
|
|
|
if(fnLmL s>= 0) goto <CHECK_S>;
|
|
Res2 = ~Res2;
|
|
|
|
if(Res0 == 0) goto <RES0_0>;
|
|
Res0 = (~Res0) + 1;
|
|
goto <CHECK_S>;
|
|
|
|
<RES0_0>
|
|
Res2 = Res2 + 1;
|
|
|
|
<CHECK_S>
|
|
|
|
if($(S_FLAG) != 1) goto <S_0>;
|
|
|
|
Res0 = macl + Res0;
|
|
Res2 = Res2 + zext(macl > Res0);
|
|
|
|
Res2 = Res2 + (mach & 0x0000FFFF);
|
|
|
|
if((Res2 s>= 0) || Res2 >= 0xFFFF8000) goto <SKIP_1>;
|
|
Res2 = 0xFFFF8000;
|
|
Res0 = 0x00000000;
|
|
|
|
<SKIP_1>
|
|
if((Res2 s<= 0) || Res2 <= 0x00007FFF) goto <SKIP_2>;
|
|
Res2 = 0x00007FFF;
|
|
Res0 = 0xFFFFFFFF;
|
|
|
|
<SKIP_2>
|
|
mach = (Res2 & 0x0000FFFF) | (mach & 0xFFFF0000);
|
|
macl = Res0;
|
|
|
|
goto <END>;
|
|
|
|
<S_0>
|
|
Res0 = macl + Res0;
|
|
Res2 = Res2 + zext(macl > Res0);
|
|
|
|
Res2 = Res2 + mach;
|
|
mach = Res2;
|
|
macl = Res0;
|
|
|
|
<END>
|
|
}
|
|
@endif
|
|
|
|
:mac.w @rm_04_07+,@rn_08_11+ is opcode_12_15=0b0100 & rn_08_11 & rm_04_07 & opcode_00_03=0b1111
|
|
{
|
|
# BUGBUG: review this instruction
|
|
|
|
local tempm:4;
|
|
local tempn:4;
|
|
local dest;
|
|
local src:4;
|
|
local ans;
|
|
local templ:4;
|
|
|
|
tempn = *:2 rn_08_11;
|
|
rn_08_11 = rn_08_11 + 2;
|
|
tempm = *:2 rm_04_07;
|
|
rm_04_07 = rm_04_07 + 2;
|
|
|
|
templ = macl;
|
|
tempm = sext(tempn:2) * sext(tempm:2);
|
|
|
|
dest = (macl s< 0);
|
|
|
|
if(tempm s< 0) goto <ELSE>;
|
|
src = 0;
|
|
tempn = 0;
|
|
goto <ENDIF>;
|
|
|
|
<ELSE>
|
|
src = 1;
|
|
tempn = 0xFFFFFFFF;
|
|
|
|
<ENDIF>
|
|
src = src + zext(dest);
|
|
macl = macl + tempm;
|
|
|
|
ans = (macl s< 0);
|
|
|
|
ans = ans + dest;
|
|
|
|
# if (S == 1)
|
|
if($(S_FLAG) != 1) goto <S_0>;
|
|
|
|
if(ans != 1) goto <END>;
|
|
|
|
@if SH_VERSION == "1"
|
|
if(src != 0 && src != 2) goto <SKIP_BIT>;
|
|
mach = mach | 0x00000001;
|
|
<SKIP_BIT>
|
|
@endif
|
|
|
|
if(src == 0) goto <SRC_0>;
|
|
if(src == 2) goto <SRC_2>;
|
|
goto <END>;
|
|
|
|
<SRC_0>
|
|
macl = 0x7FFFFFFF;
|
|
goto <END>;
|
|
|
|
<SRC_2>
|
|
macl = 0x80000000;
|
|
goto <END>;
|
|
|
|
# if (S != 1)
|
|
<S_0>
|
|
|
|
mach = mach + tempn;
|
|
|
|
if(templ s<= macl) goto <SKIP_INC>;
|
|
macl = macl + 1;
|
|
<SKIP_INC>
|
|
|
|
@if SH_VERSION == "1"
|
|
if((mach & 0x00000200) == 0) goto <ZERO_EXTEND>;
|
|
mach = mach | 0xFFFFFC00;
|
|
goto <END>;
|
|
<ZERO_EXTEND>
|
|
mach = mach & 0x000003FF;
|
|
@endif
|
|
|
|
<END>
|
|
}
|
|
|
|
@if SH_VERSION == "2"
|
|
:mul.l rm_04_07,rn_08_11 is opcode_12_15=0b0000 & rn_08_11 & rm_04_07 & opcode_00_03=0b0111
|
|
{
|
|
macl = rn_08_11 * rm_04_07;
|
|
}
|
|
@endif
|
|
|
|
:muls.w rm_04_07,rn_08_11 is opcode_12_15=0b0010 & rn_08_11 & rm_04_07 & opcode_00_03=0b1111
|
|
{
|
|
macl = sext(rn_08_11:2 & 0xFFFF) * sext(rm_04_07:2 & 0xFFFF);
|
|
}
|
|
|
|
:mulu.w rm_04_07,rn_08_11 is opcode_12_15=0b0010 & rn_08_11 & rm_04_07 & opcode_00_03=0b1110
|
|
{
|
|
macl = (rn_08_11 & 0xFFFF) * (rm_04_07 & 0xFFFF);
|
|
}
|
|
|
|
:neg rm_04_07,rn_08_11 is opcode_12_15=0b0110 & rn_08_11 & rm_04_07 & opcode_00_03=0b1011
|
|
{
|
|
rn_08_11 = 0 - rm_04_07;
|
|
}
|
|
|
|
:negc rm_04_07,rn_08_11 is opcode_12_15=0b0110 & rn_08_11 & rm_04_07 & opcode_00_03=0b1010
|
|
{
|
|
local temp;
|
|
|
|
temp = 0 - rm_04_07;
|
|
rn_08_11 = temp - zext($(T_FLAG));
|
|
|
|
# BUGBUG: should temp be signed or unsigned??
|
|
# Documentation says if(0 < temp) not 0 != temp
|
|
$(T_FLAG) = (0 != temp) || (temp < rn_08_11);
|
|
}
|
|
|
|
:sub rm_04_07,rn_08_11 is opcode_12_15=0b0011 & rn_08_11 & rm_04_07 & opcode_00_03=0b1000
|
|
{
|
|
rn_08_11 = rn_08_11 - rm_04_07;
|
|
}
|
|
|
|
:subc rm_04_07,rn_08_11 is opcode_12_15=0b0011 & rn_08_11 & rm_04_07 & opcode_00_03=0b1010
|
|
{
|
|
local temp0;
|
|
local temp1;
|
|
|
|
temp1 = rn_08_11 - rm_04_07;
|
|
temp0 = rn_08_11;
|
|
|
|
rn_08_11 = temp1 - zext($(T_FLAG));
|
|
|
|
$(T_FLAG) = (temp0 < temp1 || temp1 < rn_08_11);
|
|
}
|
|
|
|
:subv rm_04_07,rn_08_11 is opcode_12_15=0b0011 & rn_08_11 & rm_04_07 & opcode_00_03=0b1011
|
|
{
|
|
local dest;
|
|
local src;
|
|
local ans;
|
|
|
|
dest = !(rn_08_11 s>= 0);
|
|
src = !(rm_04_07 s>= 0);
|
|
|
|
src = src + dest;
|
|
rn_08_11 = rn_08_11 - rm_04_07;
|
|
|
|
ans = (rn_08_11 s>= 0);
|
|
ans = ans + dest;
|
|
|
|
$(T_FLAG) = (src == 1) && (ans == 1);
|
|
}
|
|
|
|
#
|
|
# Logic Operation Instructions
|
|
#
|
|
:and rm_04_07,rn_08_11 is opcode_12_15=0b0010 & rn_08_11 & rm_04_07 & opcode_00_03=0b1001
|
|
{
|
|
rn_08_11 = rn_08_11 & rm_04_07;
|
|
}
|
|
|
|
:and imm_00_07,r0 is r0 & opcode_08_15=0b11001001 & imm_00_07
|
|
{
|
|
r0 = (r0 & imm_00_07) & 0x000000FF;
|
|
}
|
|
|
|
:and.b imm_00_07,@(r0,gbr) is r0 & gbr & opcode_08_15=0b11001101 & imm_00_07
|
|
{
|
|
local temp = *:1 (gbr + r0);
|
|
temp = (temp & imm_00_07) & 0x000000FF;
|
|
|
|
*:1 (gbr + r0) = temp;
|
|
}
|
|
|
|
:not rm_04_07,rn_08_11 is opcode_12_15=0b0110 & rn_08_11 & rm_04_07 & opcode_00_03=0b0111
|
|
{
|
|
rn_08_11 = ~rm_04_07;
|
|
}
|
|
|
|
:or rm_04_07,rn_08_11 is opcode_12_15=0b0010 & rn_08_11 & rm_04_07 & opcode_00_03=0b1011
|
|
{
|
|
rn_08_11 = rn_08_11 | rm_04_07;
|
|
}
|
|
|
|
:or imm_00_07,r0 is r0 & opcode_08_15=0b11001011 & imm_00_07
|
|
{
|
|
r0 = r0 | imm_00_07:4;
|
|
}
|
|
|
|
:or.b imm_00_07,@(r0,gbr) is r0 & gbr & opcode_08_15=0b11001111 & imm_00_07
|
|
{
|
|
local temp = *:1 (gbr + r0);
|
|
temp = (temp & imm_00_07) | 0x000000FF;
|
|
|
|
*:1 (gbr + r0) = temp;
|
|
}
|
|
|
|
:tas.b @rn_08_11 is opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b00011011
|
|
{
|
|
local temp = *:1 rn_08_11;
|
|
|
|
$(T_FLAG) = (temp == 0);
|
|
|
|
temp = temp | 0x80;
|
|
|
|
*:1 rn_08_11 = temp;
|
|
}
|
|
|
|
:tst rm_04_07,rn_08_11 is opcode_12_15=0b0010 & rn_08_11 & rm_04_07 & opcode_00_03=0b1000
|
|
{
|
|
$(T_FLAG) = ((rm_04_07 & rm_04_07) == 0);
|
|
}
|
|
|
|
:tst imm_00_07,r0 is r0 & opcode_08_15=0b11001000 & imm_00_07
|
|
{
|
|
local temp = r0 & (imm_00_07 & 0x000000FF);
|
|
|
|
$(T_FLAG) = (temp == 0);
|
|
}
|
|
|
|
:tst.b imm_00_07,@(r0,gbr) is r0 & gbr & opcode_08_15=0b11001100 & imm_00_07
|
|
{
|
|
local temp = *:1 (gbr + r0);
|
|
temp = temp & (imm_00_07 & 0x000000FF);
|
|
|
|
$(T_FLAG) = (temp == 0);
|
|
}
|
|
|
|
:xor rm_04_07,rn_08_11 is opcode_12_15=0b0010 & rn_08_11 & rm_04_07 & opcode_00_03=0b1010
|
|
{
|
|
rn_08_11 = rn_08_11 ^ rm_04_07;
|
|
}
|
|
|
|
:xor imm_00_07,r0 is r0 & opcode_08_15=0b11001010 & imm_00_07
|
|
{
|
|
r0 = r0 ^ (imm_00_07 & 0x000000FF);
|
|
}
|
|
|
|
:xor.b imm_00_07,@(r0,gbr) is r0 & gbr & opcode_08_15=0b11001110 & imm_00_07
|
|
{
|
|
local temp = *:1 (gbr + r0);
|
|
temp = temp & (imm_00_07 & 0x000000FF);
|
|
|
|
*:1 (gbr + r0) = temp;
|
|
}
|
|
|
|
#
|
|
#Shift Instructions
|
|
#
|
|
:rotcl rn_08_11 is opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b00100100
|
|
{
|
|
local temp:1;
|
|
|
|
temp = ((rn_08_11 & 0x80000000) != 0);
|
|
|
|
rn_08_11 = (rn_08_11 << 1) & 0xFFFFFFFE;
|
|
|
|
if($(T_FLAG) == 0) goto <SKIP_BIT>;
|
|
|
|
rn_08_11 = rn_08_11 | 0x1;
|
|
|
|
<SKIP_BIT>
|
|
|
|
$(T_FLAG) = temp;
|
|
}
|
|
|
|
:rotcr rn_08_11 is opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b00100101
|
|
{
|
|
local temp:1;
|
|
|
|
temp = !((rn_08_11 & 1) == 0);
|
|
|
|
rn_08_11 = (rn_08_11 >> 1) & 0x7FFFFFFF;
|
|
|
|
if($(T_FLAG) == 0) goto <SKIP_BIT>;
|
|
|
|
rn_08_11 = rn_08_11 | 0x80000000;
|
|
|
|
<SKIP_BIT>
|
|
|
|
$(T_FLAG) = temp;
|
|
}
|
|
|
|
:rotl rn_08_11 is opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b00000100
|
|
{
|
|
$(T_FLAG) = ((rn_08_11 & 0x80000000) != 0);
|
|
|
|
if($(T_FLAG) == 1) goto <SIGN_EXTEND>;
|
|
|
|
rn_08_11 = rn_08_11 & 0xFFFFFFFE;
|
|
goto <END>;
|
|
|
|
<SIGN_EXTEND>
|
|
|
|
rn_08_11 = rn_08_11 | 0x00000001;
|
|
|
|
<END>
|
|
}
|
|
|
|
:rotr rn_08_11 is opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b00000101
|
|
{
|
|
$(T_FLAG) = ((rn_08_11 & 0x1) != 0);
|
|
|
|
if($(T_FLAG) == 1) goto <SIGN_EXTEND>;
|
|
|
|
rn_08_11 = rn_08_11 & 0x7FFFFFFF;
|
|
goto <END>;
|
|
|
|
<SIGN_EXTEND>
|
|
|
|
rn_08_11 = rn_08_11 | 0x80000000;
|
|
|
|
<END>
|
|
}
|
|
|
|
:shal rn_08_11 is opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b00100000
|
|
{
|
|
# clear or set T
|
|
$(T_FLAG) = ((rn_08_11 & 0x80000000) != 0);
|
|
|
|
rn_08_11 = rn_08_11 << 1;
|
|
}
|
|
|
|
:shar rn_08_11 is opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b00100001
|
|
{
|
|
$(T_FLAG) = ((rn_08_11 & 1) == 1);
|
|
|
|
rn_08_11 = rn_08_11 >> 1;
|
|
|
|
if((rn_08_11 & 0x80000000) != 1) goto <SIGN_EXTEND>;
|
|
|
|
rn_08_11 = rn_08_11 & 0x7FFFFFFF;
|
|
goto <END>;
|
|
|
|
<SIGN_EXTEND>
|
|
|
|
rn_08_11 = rn_08_11 | 0x80000000;
|
|
|
|
<END>
|
|
}
|
|
|
|
:shll rn_08_11 is opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b00000000
|
|
{
|
|
# clear or set T
|
|
$(T_FLAG) = ((rn_08_11 & 0x80000000) != 0);
|
|
|
|
rn_08_11 = rn_08_11 << 1;
|
|
}
|
|
|
|
:shll2 rn_08_11 is opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b00001000
|
|
{
|
|
rn_08_11 = rn_08_11 << 2;
|
|
}
|
|
|
|
:shll8 rn_08_11 is opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b00011000
|
|
{
|
|
rn_08_11 = rn_08_11 << 8;
|
|
}
|
|
|
|
:shll16 rn_08_11 is opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b00101000
|
|
{
|
|
rn_08_11 = rn_08_11 << 16;
|
|
}
|
|
|
|
:shlr rn_08_11 is opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b00000001
|
|
{
|
|
# clear or set T
|
|
$(T_FLAG) = (rn_08_11 & 1) == 1;
|
|
|
|
rn_08_11 = rn_08_11 >> 1;
|
|
rn_08_11 = rn_08_11 & 0x7FFFFFFF;
|
|
}
|
|
|
|
:shlr2 rn_08_11 is opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b00001001
|
|
{
|
|
rn_08_11 = rn_08_11 >> 2;
|
|
rn_08_11 = rn_08_11 & 0x3FFFFFFF;
|
|
}
|
|
|
|
:shlr8 rn_08_11 is opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b00011001
|
|
{
|
|
rn_08_11 = rn_08_11 >> 8;
|
|
rn_08_11 = rn_08_11 & 0x00FFFFFF;
|
|
}
|
|
|
|
:shlr16 rn_08_11 is opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b00101001
|
|
{
|
|
rn_08_11 = rn_08_11 >> 16;
|
|
rn_08_11 = rn_08_11 & 0x0000FFFF;
|
|
}
|
|
|
|
#
|
|
# Branch Instructions
|
|
#
|
|
:bf target00_07 is opcode_08_15=0b10001011 & target00_07
|
|
{
|
|
if ($(T_FLAG) == 0) goto target00_07;
|
|
}
|
|
|
|
@if SH_VERSION == "2"
|
|
:bf"/s" target00_07 is opcode_08_15=0b10001111 & target00_07
|
|
{
|
|
delayslot(1);
|
|
if ($(T_FLAG)==0) goto target00_07;
|
|
}
|
|
@endif
|
|
|
|
:bt target00_07 is opcode_08_15=0b10001001 & target00_07
|
|
{
|
|
if ($(T_FLAG) == 1) goto target00_07;
|
|
}
|
|
|
|
@if SH_VERSION == "2"
|
|
:bt"/s" target00_07 is opcode_08_15=0b10001101 & target00_07
|
|
{
|
|
delayslot(1);
|
|
if ($(T_FLAG)==1) goto target00_07;
|
|
}
|
|
@endif
|
|
|
|
:bra target00_11 is opcode_12_15=0b1010 & target00_11
|
|
{
|
|
delayslot(1);
|
|
goto target00_11;
|
|
}
|
|
|
|
@if SH_VERSION == "2"
|
|
:braf rm_08_11 is opcode_12_15=0b0000 & rm_08_11 & opcode_00_07=0b00100011
|
|
{
|
|
local temp:4 = inst_start + 4 + rm_08_11;
|
|
delayslot(1);
|
|
goto [temp];
|
|
}
|
|
@endif
|
|
|
|
:bsr target00_11 is opcode_12_15=0b1011 & target00_11
|
|
{
|
|
pr = inst_start + 4;
|
|
delayslot(1);
|
|
call target00_11;
|
|
}
|
|
|
|
@if SH_VERSION == "2"
|
|
:bsrf rm_08_11 is opcode_12_15=0b0000 & rm_08_11 & opcode_00_07=0b00000011
|
|
{
|
|
pr = inst_start + 4;
|
|
delayslot(1);
|
|
call [rm_08_11];
|
|
}
|
|
@endif
|
|
|
|
:jmp @rm_08_11 is opcode_12_15=0b0100 & rm_08_11 & opcode_00_07=0b00101011
|
|
{
|
|
delayslot(1);
|
|
goto [rm_08_11];
|
|
}
|
|
|
|
:jsr @rm_08_11 is opcode_12_15=0b0100 & rm_08_11 & opcode_00_07=0b00001011
|
|
{
|
|
pr = inst_start + 4;
|
|
delayslot(1);
|
|
call [rm_08_11];
|
|
}
|
|
|
|
:rts is opcode_00_15=0b0000000000001011
|
|
{
|
|
delayslot(1);
|
|
return [pr];
|
|
}
|
|
|
|
#
|
|
# System Control Instructions
|
|
#
|
|
:clrmac is opcode_00_15=0b0000000000101000
|
|
{
|
|
mach = 0;
|
|
macl = 0;
|
|
}
|
|
|
|
:clrt is opcode_00_15=0b0000000000001000
|
|
{
|
|
$(T_FLAG) = 0;
|
|
}
|
|
|
|
:ldc rm_08_11,sr is sr & opcode_12_15=0b0100 & rm_08_11 & opcode_00_07=0b00001110
|
|
{
|
|
sr = rm_08_11 & 0x0FFF0FFF;
|
|
}
|
|
|
|
:ldc.l @rm_08_11+,sr is sr & opcode_12_15=0b0100 & rm_08_11 & opcode_00_07=0b00000111
|
|
{
|
|
sr = *rm_08_11 & 0x0FFF0FFF;
|
|
rm_08_11 = rm_08_11 + 4;
|
|
|
|
}
|
|
|
|
:ldc rm_08_11,gbr is gbr & opcode_12_15=0b0100 & rm_08_11 & opcode_00_07=0b00011110
|
|
{
|
|
gbr = rm_08_11;
|
|
}
|
|
|
|
:ldc.l @rm_08_11+,gbr is gbr & opcode_12_15=0b0100 & rm_08_11 & opcode_00_07=0b00010111
|
|
{
|
|
gbr = *rm_08_11;
|
|
rm_08_11 = rm_08_11 + 4;
|
|
}
|
|
|
|
:ldc rm_08_11,vbr is vbr & opcode_12_15=0b0100 & rm_08_11 & opcode_00_07=0b00101110
|
|
{
|
|
vbr = rm_08_11;
|
|
}
|
|
|
|
:ldc.l @rm_08_11+,vbr is vbr & opcode_12_15=0b0100 & rm_08_11 & opcode_00_07=0b00100111
|
|
{
|
|
vbr = *rm_08_11;
|
|
rm_08_11 = rm_08_11 + 4;
|
|
}
|
|
|
|
:lds rm_08_11,mach is mach & opcode_12_15=0b0100 & rm_08_11 & opcode_00_07=0b00001010
|
|
{
|
|
mach = rm_08_11;
|
|
|
|
@if SH_VERSION == "1"
|
|
if((mach & 0x00000200) == 0) goto <ZERO_EXTEND>;
|
|
|
|
# sign extend
|
|
mach = mach | 0xFFFFFC00;
|
|
goto <END>;
|
|
|
|
<ZERO_EXTEND>
|
|
mach = mach & 0x000003FF;
|
|
|
|
<END>
|
|
@endif
|
|
}
|
|
|
|
:lds.l @rm_08_11+,mach is mach & opcode_12_15=0b0100 & rm_08_11 & opcode_00_07=0b00000110
|
|
{
|
|
mach = *rm_08_11;
|
|
|
|
@if SH_VERSION == "1"
|
|
if((mach & 0x00000200) == 0) goto <ZERO_EXTEND>;
|
|
|
|
# sign extend
|
|
mach = mach | 0xFFFFFC00;
|
|
goto <END>;
|
|
|
|
<ZERO_EXTEND>
|
|
mach = mach & 0x000003FF;
|
|
|
|
<END>
|
|
@endif
|
|
|
|
rm_08_11 = rm_08_11 + 4;
|
|
}
|
|
|
|
:lds rm_08_11,macl is macl & opcode_12_15=0b0100 & rm_08_11 & opcode_00_07=0b00011010
|
|
{
|
|
macl = rm_08_11;
|
|
}
|
|
|
|
:lds.l @rm_08_11+,macl is macl & opcode_12_15=0b0100 & rm_08_11 & opcode_00_07=0b00010110
|
|
{
|
|
macl = *rm_08_11;
|
|
rm_08_11 = rm_08_11 + 4;
|
|
}
|
|
|
|
:lds rm_08_11,pr is pr & opcode_12_15=0b0100 & rm_08_11 & opcode_00_07=0b00101010
|
|
{
|
|
pr = rm_08_11;
|
|
}
|
|
|
|
:lds.l @rm_08_11+,pr is pr & opcode_12_15=0b0100 & rm_08_11 & opcode_00_07=0b00100110
|
|
{
|
|
pr = *rm_08_11;
|
|
rm_08_11 = rm_08_11 + 4;
|
|
}
|
|
|
|
:nop is opcode_00_15=0b0000000000001001
|
|
{
|
|
# BUGBUG: intentional nop
|
|
r0 = r0; # do this to suppress warning
|
|
}
|
|
|
|
:rte is opcode_00_15=0b0000000000101011
|
|
{
|
|
_pc:4 = *r15;
|
|
r15 = r15 + 4;
|
|
|
|
_sr:4 = *r15 & 0x000063F3;
|
|
r15 = r15 + 4;
|
|
|
|
delayslot(1);
|
|
|
|
pc = _pc;
|
|
sr = _sr;
|
|
|
|
goto [pc];
|
|
}
|
|
|
|
:sett is opcode_00_15=0b0000000000011000
|
|
{
|
|
$(T_FLAG) = 1;
|
|
}
|
|
|
|
:sleep is opcode_00_15=0b0000000000011011
|
|
{
|
|
# BUGBUG: call sleep();
|
|
r0 = r0;
|
|
}
|
|
|
|
:stc sr,rn_08_11 is sr & opcode_12_15=0b0000 & rn_08_11 & opcode_00_07=0b00000010
|
|
{
|
|
rn_08_11 = sr;
|
|
}
|
|
|
|
:stc.l sr,@-rn_08_11 is sr & opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b00000011
|
|
{
|
|
rn_08_11 = rn_08_11 -4;
|
|
*rn_08_11 = sr;
|
|
}
|
|
|
|
:stc gbr,rn_08_11 is gbr & opcode_12_15=0b0000 & rn_08_11 & opcode_00_07=0b00010010
|
|
{
|
|
rn_08_11 = gbr;
|
|
}
|
|
|
|
:stc.l gbr,@-rn_08_11 is gbr & opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b00010011
|
|
{
|
|
rn_08_11 = rn_08_11 -4;
|
|
*rn_08_11 = gbr;
|
|
}
|
|
|
|
:stc vbr,rn_08_11 is vbr & opcode_12_15=0b0000 & rn_08_11 & opcode_00_07=0b00100010
|
|
{
|
|
rn_08_11 = vbr;
|
|
}
|
|
|
|
:stc.l vbr,@-rn_08_11 is vbr & opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b00100011
|
|
{
|
|
rn_08_11 = rn_08_11 -4;
|
|
*rn_08_11 = vbr;
|
|
}
|
|
|
|
:sts mach,rn_08_11 is mach & opcode_12_15=0b0000 & rn_08_11 & opcode_00_07=0b00001010
|
|
{
|
|
rn_08_11 = mach;
|
|
|
|
@if SH_VERSION == "1"
|
|
if((rn_08_11 & 0x00000200) == 0) goto <ZERO_EXTEND>;
|
|
|
|
# sign extend
|
|
rn_08_11 = rn_08_11 | 0xFFFFFC00;
|
|
goto <END>;
|
|
|
|
<ZERO_EXTEND>
|
|
rn_08_11 = rn_08_11 & 0x000003FF;
|
|
|
|
<END>
|
|
@endif
|
|
}
|
|
|
|
:sts.l mach,@-rn_08_11 is mach & opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b00000010
|
|
{
|
|
rn_08_11 = rn_08_11 - 4;
|
|
|
|
local temp = mach;
|
|
|
|
@if SH_VERSION == "1"
|
|
if((temp & 0x00000200) == 0) goto <ZERO_EXTEND>;
|
|
|
|
# sign extend
|
|
temp = temp | 0xFFFFFC00;
|
|
goto <END>;
|
|
|
|
<ZERO_EXTEND>
|
|
temp = temp & 0x000003FF;
|
|
|
|
<END>
|
|
@endif
|
|
|
|
*rn_08_11 = temp;
|
|
}
|
|
|
|
:sts macl,rn_08_11 is macl & opcode_12_15=0b0000 & rn_08_11 & opcode_00_07=0b00011010
|
|
{
|
|
rn_08_11 = macl;
|
|
}
|
|
|
|
:sts.l macl,@-rn_08_11 is macl & opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b00010010
|
|
{
|
|
rn_08_11 = rn_08_11 -4;
|
|
*rn_08_11 = macl;
|
|
}
|
|
|
|
:sts pr,rn_08_11 is pr & opcode_12_15=0b0000 & rn_08_11 & opcode_00_07=0b00101010
|
|
{
|
|
rn_08_11 = pr;
|
|
}
|
|
|
|
:sts.l pr,@-rn_08_11 is pr & opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b00100010
|
|
{
|
|
rn_08_11 = rn_08_11 -4;
|
|
*rn_08_11 = pr;
|
|
}
|
|
|
|
:trapa imm_00_07 is opcode_08_15=0b11000011 & imm_00_07
|
|
{
|
|
r15 = r15 -4;
|
|
*r15 = sr;
|
|
|
|
r15 = r15- 4;
|
|
*r15 = pc + 2;
|
|
|
|
pc = *(vbr + (imm_00_07 * 4));
|
|
goto [pc];
|
|
}
|