2444 lines
74 KiB
Plaintext
2444 lines
74 KiB
Plaintext
# All assembly defintions taken from: http://www.shared-ptr.com/sh_insns.html
|
||
|
||
define endian=big;
|
||
|
||
define alignment=1;
|
||
|
||
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];
|
||
|
||
|
||
@if SH_VERSION == "2A"
|
||
define register offset=0x180 size=4 [tbr];
|
||
@endif
|
||
|
||
# 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 CS_FLAG "sr[13,1]"
|
||
@define BO_FLAG "sr[14,1]"
|
||
|
||
@if defined(FPU)
|
||
|
||
# Floating-Point Registers
|
||
define register offset=0x200 size=4 [ fr0 fr1 fr2 fr3 fr4 fr5 fr6 fr7 fr8 fr9 fr10 fr11 fr12 fr13 fr14 fr15 ];
|
||
define register offset=0x200 size=8 [ dr0 dr2 dr4 dr6 dr8 dr10 dr12 dr14 ];
|
||
|
||
# Floating-Point System Registers
|
||
define register offset=0x300 size=4 [fpscr fpul];
|
||
|
||
# FPSCR Flags (initial value = H'0004 0001)
|
||
@define FP_RM "fpscr[0,2]"
|
||
@define FP_FLAG "fpscr[2,5]"
|
||
@define FP_ENABLE "fpscr[7,5]"
|
||
@define FP_CAUSE "fpscr[12,6]"
|
||
@define FP_DN "fpscr[18,1]"
|
||
@define FP_PR "fpscr[19,1]"
|
||
@define FP_SZ "fpscr[20,1]"
|
||
@define FP_QIS "fpscr[22,1]"
|
||
|
||
@endif
|
||
|
||
@if SH_VERSION == "2A"
|
||
# The register banks space is defined below, there are 512 banks, each is 80 bytes long
|
||
define register offset=0x10000 size=40960 [ resbank_base ];
|
||
@endif
|
||
|
||
define token instr16(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
|
||
imm3_00_02 = (0, 2)
|
||
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_03_03 = (3, 3)
|
||
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)
|
||
rm_imm_08_11 = (8, 11)
|
||
rn_imm_08_11 = (8, 11)
|
||
;
|
||
|
||
@if SH_VERSION == "2A"
|
||
define token instr32(32)
|
||
l_disp_00_11 = (0, 11)
|
||
l_opcode_12_15 = (12, 15)
|
||
l_opcode_16_19 = (16, 19)
|
||
l_opcode_23_23 = (23, 23)
|
||
l_opcode_24_31 = (24, 31)
|
||
l_rm_20_23 = (20, 23)
|
||
l_rn_24_27 = (24, 27)
|
||
l_opcode_28_31 = (28, 31)
|
||
l_imm20_00_15 = (0, 15)
|
||
l_simm20_20_23 = (20, 23) signed
|
||
l_imm3_20_22 = (20, 22)
|
||
;
|
||
|
||
attach variables [ l_rn_24_27 l_rm_20_23 ] [
|
||
r0 r1 r2 r3 r4 r5 r6 r7
|
||
r8 r9 r10 r11 r12 r13 r14 r15
|
||
];
|
||
|
||
@endif
|
||
|
||
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
|
||
];
|
||
|
||
attach names [ rm_imm_08_11 rn_imm_08_11 ] [
|
||
r0 r1 r2 r3 r4 r5 r6 r7
|
||
r8 r9 r10 r11 r12 r13 r14 pr
|
||
];
|
||
|
||
@if defined(FPU)
|
||
|
||
define token finstr16(16)
|
||
fop_00_07 = (0, 7)
|
||
fop_00_03 = (0, 3)
|
||
fop_04_07 = (4, 7)
|
||
fop_12_15 = (12, 15)
|
||
fop_08_08 = (8, 8)
|
||
fop_04_04 = (4, 4)
|
||
fop_00_15 = (0, 15)
|
||
|
||
ffrn_08_11 = (8, 11)
|
||
ffrm_08_11 = (8, 11)
|
||
ffrn_04_07 = (4, 7)
|
||
ffrm_04_07 = (4, 7)
|
||
f_rm_04_07 = (4, 7)
|
||
f_rn_08_11 = (8, 11)
|
||
|
||
fdrn_09_11 = (9, 11)
|
||
fdrm_09_11 = (9, 11)
|
||
fdrn_05_07 = (5, 7)
|
||
fdrm_05_07 = (5, 7)
|
||
;
|
||
|
||
|
||
define token finstr32(32)
|
||
lfdisp_00_11 = (0, 11)
|
||
lfop_28_31 = (28, 31)
|
||
lfop_12_19 = (12, 19)
|
||
lffrm_24_27 = (24, 27)
|
||
lffrn_24_27 = (24, 27)
|
||
lffrm_20_23 = (20, 23)
|
||
lf_rm_20_23 = (20, 23)
|
||
lf_rn_24_27 = (24, 27)
|
||
lffrn_20_23 = (20, 23)
|
||
;
|
||
|
||
attach variables [ ffrn_08_11 ffrm_08_11 ffrn_04_07 ffrm_04_07 lffrm_24_27 lffrn_24_27 lffrm_20_23 lffrn_20_23 ]
|
||
[fr0 fr1 fr2 fr3 fr4 fr5 fr6 fr7 fr8 fr9 fr10 fr11 fr12 fr13 fr14 fr15];
|
||
|
||
attach variables [ f_rm_04_07 f_rn_08_11 lf_rm_20_23 lf_rn_24_27 ]
|
||
[r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15];
|
||
|
||
attach variables [ fdrn_09_11 fdrm_09_11 fdrn_05_07 fdrm_05_07 ]
|
||
[dr0 dr2 dr4 dr6 dr8 dr10 dr12 dr14];
|
||
|
||
@endif
|
||
|
||
|
||
# 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;
|
||
}
|
||
|
||
imm8: "#"^simm_00_07 is simm_00_07 { export *[const]:4 simm_00_07; }
|
||
|
||
:mov imm8,rn_08_11 is opcode_12_15=0b1110 & rn_08_11 & imm8
|
||
{
|
||
rn_08_11 = imm8;
|
||
}
|
||
|
||
disppc4: @(disp,pc) is disp_00_07 & pc
|
||
[ disp = (disp_00_07 << 2) + ((inst_start + 4) & 0xfffffffc); ]
|
||
{ local tmp:4 = disp; export tmp; }
|
||
|
||
disppc2: @(disp,pc) is disp_00_07 & pc
|
||
[ disp = (disp_00_07 << 1) + (inst_start + 4); ]
|
||
{ local tmp:4 = disp; export tmp; }
|
||
|
||
:mova disppc4,r0 is r0 & opcode_08_15=0b11000111 & disppc4
|
||
{
|
||
r0 = disppc4;
|
||
}
|
||
|
||
:mov.w disppc2,rn_08_11 is opcode_12_15=0b1001 & rn_08_11 & disppc2
|
||
{
|
||
rn_08_11 = sext(*:2 disppc2);
|
||
}
|
||
|
||
:mov.l disppc4,rn_08_11 is opcode_12_15=0b1101 & rn_08_11 & disppc4
|
||
{
|
||
rn_08_11 = *:4 disppc4;
|
||
}
|
||
|
||
: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;
|
||
}
|
||
|
||
# the following two instructions share the same opcodes but differ if rm == rn
|
||
: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);
|
||
}
|
||
|
||
:mov.b @rm_04_07+,rn_08_11 is opcode_12_15=0b0110 & rn_08_11 & rm_04_07 & opcode_00_03=0b0100
|
||
{
|
||
rn_08_11 = sext(*:1 rm_04_07);
|
||
rm_04_07 = rm_04_07 + 1;
|
||
}
|
||
|
||
# the following two instructions share the same opcodes but differ if rm == rn
|
||
: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);
|
||
}
|
||
|
||
: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);
|
||
rm_04_07 = rm_04_07 + 2;
|
||
}
|
||
|
||
# the following two instructions share the same opcodes but differ if rm == rn
|
||
: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;
|
||
}
|
||
|
||
: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;
|
||
rm_04_07 = rm_04_07 + 4;
|
||
}
|
||
|
||
: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:1;
|
||
}
|
||
|
||
: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:2;
|
||
}
|
||
|
||
: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:4;
|
||
}
|
||
|
||
: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:1;
|
||
}
|
||
|
||
:mov.w r0,@(disp,gbr) is r0 & gbr & opcode_08_15=0b11000001 & disp_00_07 [disp = (disp_00_07 << 1); ]
|
||
{
|
||
*:2 (gbr + disp) = r0:2;
|
||
}
|
||
|
||
:mov.l r0,@(disp,gbr) is r0 & gbr & opcode_08_15=0b11000010 & disp_00_07 [disp = (disp_00_07 << 2); ]
|
||
{
|
||
*:4 (gbr + disp) = r0:4;
|
||
}
|
||
|
||
:movt rn_08_11 is opcode_12_15=0b0000 & rn_08_11 & opcode_00_07=0b00101001
|
||
{
|
||
rn_08_11 = zext($(T_FLAG));
|
||
}
|
||
|
||
@if SH_VERSION == "2A"
|
||
|
||
# MOV.B R0, @Rn+ 0100nnnn10001011 R0 → (Rn), Rn + 1 → Rn
|
||
:mov.b r0, @rn_08_11+
|
||
is r0 & opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b10001011
|
||
{
|
||
*:1 (rn_08_11) = r0;
|
||
rn_08_11 = rn_08_11 + 1;
|
||
}
|
||
|
||
# MOV.W R0, @Rn+ 0100nnnn10011011 R0 → (Rn), Rn + 2 → Rn
|
||
:mov.w r0, @rn_08_11+
|
||
is r0 & opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b10011011
|
||
{
|
||
*:2 (rn_08_11) = r0;
|
||
rn_08_11 = rn_08_11 + 2;
|
||
}
|
||
|
||
# MOV.L R0, @Rn+ 0100nnnn10101011 R0 → (Rn), Rn + 4 → Rn
|
||
:mov.l r0, @rn_08_11+
|
||
is r0 & opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b10101011
|
||
{
|
||
*:4 (rn_08_11) = r0;
|
||
rn_08_11 = rn_08_11 + 4;
|
||
}
|
||
|
||
# MOV.B @-Rm, R0 0100mmmm11001011 Rm - 1 → Rm, (Rm) → sign extension → R0
|
||
:mov.b @-rm_08_11, r0
|
||
is r0 & opcode_12_15=0b0100 & rm_08_11 & opcode_00_07=0b11001011
|
||
{
|
||
rm_08_11 = rm_08_11 - 1;
|
||
r0 = sext(*:1 (rm_08_11));
|
||
}
|
||
|
||
# MOV.W @-Rm, R0 0100mmmm11011011 Rm - 2 → Rm, (Rm) → sign extension → R0
|
||
:mov.w @-rm_08_11, r0
|
||
is r0 & opcode_12_15=0b0100 & rm_08_11 & opcode_00_07=0b11011011
|
||
{
|
||
rm_08_11 = rm_08_11 - 2;
|
||
r0 = sext(*:2 (rm_08_11));
|
||
}
|
||
|
||
# MOV.L @-Rm, R0 0100mmmm11101011 Rm - 4 → Rm, (Rm) → R0
|
||
:mov.l @-rm_08_11, r0
|
||
is r0 & opcode_12_15=0b0100 & rm_08_11 & opcode_00_07=0b11101011
|
||
{
|
||
rm_08_11 = rm_08_11 - 4;
|
||
r0 = *:4 (rm_08_11);
|
||
}
|
||
|
||
# MOV.B Rm, @(disp12, Rn) 0011nnnnmmmm0001 0000dddddddddddd Rm -> (disp+Rn)
|
||
:mov.b l_rm_20_23, @(l_disp_00_11, l_rn_24_27) is l_opcode_28_31=0b0011 & l_rn_24_27 & l_rm_20_23 & l_opcode_16_19=0b0001 & l_opcode_12_15=0b0000 & l_disp_00_11
|
||
{
|
||
*:1 (l_rn_24_27 + l_disp_00_11) = l_rm_20_23;
|
||
}
|
||
|
||
# MOV.W Rm, @(disp12, Rn) 0011nnnnmmmm0001 0001dddddddddddd Rm → (disp×2+Rn)
|
||
:mov.w l_rm_20_23, @(disp, l_rn_24_27)
|
||
is l_opcode_28_31=0b0011 & l_rn_24_27 & l_rm_20_23 & l_opcode_16_19=0b0001 & l_opcode_12_15=0b0001 & l_disp_00_11
|
||
[ disp = 2*l_disp_00_11; ]
|
||
{
|
||
*:2 (l_rn_24_27 + disp) = l_rm_20_23;
|
||
}
|
||
|
||
# MOV.L Rm, @(disp12, Rn) 0011nnnnmmmm0001 0010dddddddddddd Rm → (disp×4+Rn)
|
||
:mov.l l_rm_20_23, @(disp, l_rn_24_27)
|
||
is l_opcode_28_31=0b0011 & l_rn_24_27 & l_rm_20_23 & l_opcode_16_19=0b0001 & l_opcode_12_15=0b0010 & l_disp_00_11
|
||
[ disp = 4*l_disp_00_11; ]
|
||
{
|
||
*:4 (l_rn_24_27 + disp) = l_rm_20_23;
|
||
}
|
||
|
||
# MOV.B @(disp12, Rm), Rn 0011nnnnmmmm0001 0100dddddddddddd (disp+Rm) → sign extension → Rn
|
||
:mov.b @(l_disp_00_11, l_rm_20_23), l_rn_24_27 is l_opcode_28_31=0b011 & l_rn_24_27 & l_rm_20_23 & l_opcode_16_19=0b0001 & l_opcode_12_15=0b0100 & l_disp_00_11
|
||
{
|
||
l_rn_24_27 = sext(*:1 (l_rm_20_23 + l_disp_00_11));
|
||
}
|
||
|
||
# MOV.W @(disp12, Rm), Rn 0011nnnnmmmm0001 0101dddddddddddd (disp×2+Rm) → sign extension → Rn
|
||
:mov.w @(disp, l_rm_20_23), l_rn_24_27
|
||
is l_opcode_28_31=0b011 & l_rn_24_27 & l_rm_20_23 & l_opcode_16_19=0b0001 & l_opcode_12_15=0b0101 & l_disp_00_11
|
||
[ disp = 2*l_disp_00_11; ]
|
||
{
|
||
l_rn_24_27 = sext(*:2 (l_rm_20_23 + disp));
|
||
}
|
||
|
||
# MOV.L @(disp12, Rm), Rn 0011nnnnmmmm0001 0110dddddddddddd (disp×4+Rm) → Rn
|
||
:mov.l @(disp, l_rm_20_23), l_rn_24_27
|
||
is l_opcode_28_31=0b011 & l_rn_24_27 & l_rm_20_23 & l_opcode_16_19=0b0001 & l_opcode_12_15=0b0110 & l_disp_00_11
|
||
[ disp = (4*l_disp_00_11); ]
|
||
{
|
||
l_rn_24_27 = *:4 (l_rm_20_23 + disp);
|
||
}
|
||
|
||
# MOVU.B @(disp12,Rm), Rn 0011nnnnmmmm0001 1000dddddddddddd (disp+Rm) → zero extension → Rn
|
||
:movu.b @(l_disp_00_11, l_rm_20_23), l_rn_24_27
|
||
is l_opcode_28_31=0b0011 & l_rn_24_27 & l_rm_20_23 & l_opcode_16_19=0b0001 & l_opcode_12_15=0b1000 & l_disp_00_11
|
||
{
|
||
l_rn_24_27 = zext(*:1 (l_disp_00_11 + l_rm_20_23));
|
||
}
|
||
|
||
# MOVU.W @(disp12,Rm), Rn 0011nnnnmmmm0001 1001dddddddddddd (disp×2+Rm) → zero extension → Rn
|
||
:movu.w @(disp, l_rm_20_23), l_rn_24_27
|
||
is l_opcode_28_31=0b0011 & l_rn_24_27 & l_rm_20_23 & l_opcode_16_19=0b0001 & l_opcode_12_15=0b1001 & l_disp_00_11
|
||
[ disp = l_disp_00_11 * 2; ]
|
||
{
|
||
l_rn_24_27 = zext(*:2 (disp + l_rm_20_23));
|
||
}
|
||
|
||
simm20: "#"value is l_simm20_20_23 & l_imm20_00_15
|
||
[ value = ((l_simm20_20_23 << 16) | l_imm20_00_15); ]
|
||
{ export *[const]:4 value; }
|
||
|
||
simm20s: "#"value is l_simm20_20_23 & l_imm20_00_15
|
||
[ value = ((l_simm20_20_23 << 16) | l_imm20_00_15) << 8; ]
|
||
{ export *[const]:4 value; }
|
||
|
||
|
||
# MOVI20 #imm20, Rn 0000nnnniiii0000 iiiiiiiiiiiiiiii imm → sign extension → Rn
|
||
:movi20 simm20, l_rn_24_27
|
||
is l_opcode_28_31=0b0000 & l_rn_24_27 & l_opcode_16_19=0b0000 & simm20
|
||
{
|
||
l_rn_24_27 = simm20;
|
||
}
|
||
|
||
# MOVI20S #imm20, Rn 0000nnnniiii0001 iiiiiiiiiiiiiiii imm<<8 → sign extension → Rn
|
||
:movi20s simm20s, l_rn_24_27
|
||
is l_opcode_28_31=0b0000 & l_rn_24_27 & l_opcode_16_19=0b0001 & simm20s
|
||
{
|
||
l_rn_24_27 = simm20s;
|
||
}
|
||
|
||
#
|
||
# movm* instuctions are only in SH2A. They don't collide, but could be ifdef'ed for 2A only
|
||
#
|
||
|
||
macro loadRegister(reg, ea) {
|
||
reg = *:4(ea);
|
||
ea = ea+4;
|
||
}
|
||
|
||
macro storeRegister(reg, ea) {
|
||
ea = ea-4;
|
||
*:4(ea) = reg;
|
||
}
|
||
|
||
MovMLReg1_0: rm_imm_08_11 is rm_imm_08_11 & rm_08_11=0 { storeRegister(r0,r15); }
|
||
MovMLReg1_0store: is rm_imm_08_11 { storeRegister(r0,r15); }
|
||
|
||
MovMLReg1_1: MovMLReg1_0 is MovMLReg1_0 { r0 = r0; }
|
||
MovMLReg1_1: rm_imm_08_11 is MovMLReg1_0store & rm_imm_08_11 & rm_08_11=1 { storeRegister(r1,r15); build MovMLReg1_0store; }
|
||
MovMLReg1_1store: is MovMLReg1_0store & rm_imm_08_11 { storeRegister(r1,r15); build MovMLReg1_0store; }
|
||
|
||
MovMLReg1_2: MovMLReg1_1 is MovMLReg1_1 { r0 = r0; }
|
||
MovMLReg1_2: rm_imm_08_11 is MovMLReg1_1store & rm_imm_08_11 & rm_08_11=2 { storeRegister(r2,r15); build MovMLReg1_1store; }
|
||
MovMLReg1_2store: is MovMLReg1_1store & rm_imm_08_11 { storeRegister(r2,r15); build MovMLReg1_1store; }
|
||
|
||
MovMLReg1_3: MovMLReg1_2 is MovMLReg1_2 { r0 = r0; }
|
||
MovMLReg1_3: rm_imm_08_11 is MovMLReg1_2store & rm_imm_08_11 & rm_08_11=3 { storeRegister(r3,r15); build MovMLReg1_2store; }
|
||
MovMLReg1_3store: is MovMLReg1_2store & rm_imm_08_11 { storeRegister(r3,r15); build MovMLReg1_2store; }
|
||
|
||
MovMLReg1_4: MovMLReg1_3 is MovMLReg1_3 { r0 = r0; }
|
||
MovMLReg1_4: rm_imm_08_11 is MovMLReg1_3store & rm_imm_08_11 & rm_08_11=4 { storeRegister(r4,r15); build MovMLReg1_3store; }
|
||
MovMLReg1_4store: is MovMLReg1_3store & rm_imm_08_11 { storeRegister(r4,r15); build MovMLReg1_3store; }
|
||
|
||
MovMLReg1_5: MovMLReg1_4 is MovMLReg1_4 { r0 = r0; }
|
||
MovMLReg1_5: rm_imm_08_11 is MovMLReg1_4store & rm_imm_08_11 & rm_08_11=5 { storeRegister(r5,r15); build MovMLReg1_4store; }
|
||
MovMLReg1_5store: is MovMLReg1_4store & rm_imm_08_11 { storeRegister(r5,r15); build MovMLReg1_4store; }
|
||
|
||
MovMLReg1_6: MovMLReg1_5 is MovMLReg1_5 { r0 = r0; }
|
||
MovMLReg1_6: rm_imm_08_11 is MovMLReg1_5store & rm_imm_08_11 & rm_08_11=6 { storeRegister(r6,r15); build MovMLReg1_5store; }
|
||
MovMLReg1_6store: is MovMLReg1_5store & rm_imm_08_11 { storeRegister(r6,r15); build MovMLReg1_5store; }
|
||
|
||
MovMLReg1_7: MovMLReg1_6 is MovMLReg1_6 { r0 = r0; }
|
||
MovMLReg1_7: rm_imm_08_11 is MovMLReg1_6store & rm_imm_08_11 & rm_08_11=7 { storeRegister(r7,r15); build MovMLReg1_6store; }
|
||
MovMLReg1_7store: is MovMLReg1_6store & rm_imm_08_11 { storeRegister(r7,r15); build MovMLReg1_6store; }
|
||
|
||
MovMLReg1_8: MovMLReg1_7 is MovMLReg1_7 { r0 = r0; }
|
||
MovMLReg1_8: rm_imm_08_11 is MovMLReg1_7store & rm_imm_08_11 & rm_08_11=8 { storeRegister(r8,r15); build MovMLReg1_7store; }
|
||
MovMLReg1_8store: is MovMLReg1_7store & rm_imm_08_11 { storeRegister(r8,r15); build MovMLReg1_7store; }
|
||
|
||
MovMLReg1_9: MovMLReg1_8 is MovMLReg1_8 { r0 = r0; }
|
||
MovMLReg1_9: rm_imm_08_11 is MovMLReg1_8store & rm_imm_08_11 & rm_08_11=9 { storeRegister(r9,r15); build MovMLReg1_8store; }
|
||
MovMLReg1_9store: is MovMLReg1_8store & rm_imm_08_11 { storeRegister(r9,r15); build MovMLReg1_8store; }
|
||
|
||
MovMLReg1_10: MovMLReg1_9 is MovMLReg1_9 { r0 = r0; }
|
||
MovMLReg1_10: rm_imm_08_11 is MovMLReg1_9store & rm_imm_08_11 & rm_08_11=10 { storeRegister(r10,r15); build MovMLReg1_9store; }
|
||
MovMLReg1_10store: is MovMLReg1_9store & rm_imm_08_11 { storeRegister(r10,r15); build MovMLReg1_9store; }
|
||
|
||
MovMLReg1_11: MovMLReg1_10 is MovMLReg1_10 { r0 = r0; }
|
||
MovMLReg1_11: rm_imm_08_11 is MovMLReg1_10store & rm_imm_08_11 & rm_08_11=11 { storeRegister(r11,r15); build MovMLReg1_10store; }
|
||
MovMLReg1_11store: is MovMLReg1_10store & rm_imm_08_11 { storeRegister(r11,r15); build MovMLReg1_10store; }
|
||
|
||
MovMLReg1_12: MovMLReg1_11 is MovMLReg1_11 { r0 = r0; }
|
||
MovMLReg1_12: rm_imm_08_11 is MovMLReg1_11store & rm_imm_08_11 & rm_08_11=12 { storeRegister(r12,r15); build MovMLReg1_11store; }
|
||
MovMLReg1_12store: is MovMLReg1_11store & rm_imm_08_11 { storeRegister(r12,r15); build MovMLReg1_11store; }
|
||
|
||
MovMLReg1_13: MovMLReg1_12 is MovMLReg1_12 { r0 = r0; }
|
||
MovMLReg1_13: rm_imm_08_11 is MovMLReg1_12store & rm_imm_08_11 & rm_08_11=13 { storeRegister(r13,r15); build MovMLReg1_12store; }
|
||
MovMLReg1_13store: is MovMLReg1_12store & rm_imm_08_11 { storeRegister(r13,r15); build MovMLReg1_12store; }
|
||
|
||
MovMLReg1_14: MovMLReg1_13 is MovMLReg1_13 { r0 = r0; }
|
||
MovMLReg1_14: rm_imm_08_11 is MovMLReg1_13store & rm_imm_08_11 & rm_08_11=14 { storeRegister(r14,r15); build MovMLReg1_13store; }
|
||
MovMLReg1_14store: is MovMLReg1_13store & rm_imm_08_11 { storeRegister(r14,r15); build MovMLReg1_13store; }
|
||
|
||
MovMLReg1_15: MovMLReg1_14 is MovMLReg1_14 { r0 = r0; }
|
||
MovMLReg1_15: rm_imm_08_11 is MovMLReg1_14store & rm_imm_08_11 & rm_08_11=15 { storeRegister(pr,r15); build MovMLReg1_14store; }
|
||
|
||
MovMLReg1: MovMLReg1_15 is MovMLReg1_15 {
|
||
build MovMLReg1_15;
|
||
}
|
||
|
||
# MOVML.L Rm, @-R15 0100mmmm11110001
|
||
:movml.l MovMLReg1, @-r15
|
||
is r15 & opcode_12_15=0b0100 & rm_imm_08_11 & opcode_00_07=0b11110001 & MovMLReg1
|
||
{
|
||
build MovMLReg1;
|
||
}
|
||
|
||
|
||
MovMLReg2_0: rm_imm_08_11 is rm_imm_08_11 & rm_08_11=0 { loadRegister(r0,r15); }
|
||
|
||
MovMLReg2_0load: is rm_imm_08_11 { loadRegister(r0,r15); }
|
||
|
||
MovMLReg2_1: MovMLReg2_0 is MovMLReg2_0 { r0 = r0; }
|
||
MovMLReg2_1: rm_imm_08_11 is MovMLReg2_0load & rm_imm_08_11 & rm_08_11=1 { build MovMLReg2_0load; loadRegister(r1,r15); }
|
||
MovMLReg2_1load: is MovMLReg2_0load & rm_imm_08_11 { build MovMLReg2_0load; loadRegister(r1,r15); }
|
||
|
||
MovMLReg2_2: MovMLReg2_1 is MovMLReg2_1 { r0 = r0; }
|
||
MovMLReg2_2: rm_imm_08_11 is MovMLReg2_1load & rm_imm_08_11 & rm_08_11=2 { build MovMLReg2_1load; loadRegister(r2,r15); }
|
||
MovMLReg2_2load: is MovMLReg2_1load & rm_imm_08_11 { build MovMLReg2_1load; loadRegister(r2,r15); }
|
||
|
||
MovMLReg2_3: MovMLReg2_2 is MovMLReg2_2 { r0 = r0; }
|
||
MovMLReg2_3: rm_imm_08_11 is MovMLReg2_2load & rm_imm_08_11 & rm_08_11=3 { build MovMLReg2_2load; loadRegister(r3,r15); }
|
||
MovMLReg2_3load: is MovMLReg2_2load & rm_imm_08_11 { build MovMLReg2_2load; loadRegister(r3,r15); }
|
||
|
||
MovMLReg2_4: MovMLReg2_3 is MovMLReg2_3 { r0 = r0; }
|
||
MovMLReg2_4: rm_imm_08_11 is MovMLReg2_3load & rm_imm_08_11 & rm_08_11=4 { build MovMLReg2_3load; loadRegister(r4,r15); }
|
||
|
||
MovMLReg2_4load: is MovMLReg2_3load & rm_imm_08_11 { build MovMLReg2_3load; loadRegister(r4,r15); }
|
||
|
||
MovMLReg2_5: MovMLReg2_4 is MovMLReg2_4 { r0 = r0; }
|
||
MovMLReg2_5: rm_imm_08_11 is MovMLReg2_4load & rm_imm_08_11 & rm_08_11=5 { build MovMLReg2_4load; loadRegister(r5,r15); }
|
||
|
||
MovMLReg2_5load: is MovMLReg2_4load & rm_imm_08_11 { build MovMLReg2_4load; loadRegister(r5,r15); }
|
||
|
||
MovMLReg2_6: MovMLReg2_5 is MovMLReg2_5 { r0 = r0; }
|
||
MovMLReg2_6: rm_imm_08_11 is MovMLReg2_5load & rm_imm_08_11 & rm_08_11=6 { build MovMLReg2_5load; loadRegister(r6,r15); }
|
||
|
||
MovMLReg2_6load: is MovMLReg2_5load & rm_imm_08_11 { build MovMLReg2_5load; loadRegister(r6,r15); }
|
||
|
||
MovMLReg2_7: MovMLReg2_6 is MovMLReg2_6 { r0 = r0; }
|
||
MovMLReg2_7: rm_imm_08_11 is MovMLReg2_6load & rm_imm_08_11 & rm_08_11=7 { build MovMLReg2_6load; loadRegister(r7,r15); }
|
||
|
||
MovMLReg2_7load: is MovMLReg2_6load & rm_imm_08_11 { build MovMLReg2_6load; loadRegister(r7,r15); }
|
||
|
||
MovMLReg2_8: MovMLReg2_7 is MovMLReg2_7 { r0 = r0; }
|
||
MovMLReg2_8: rm_imm_08_11 is MovMLReg2_7load & rm_imm_08_11 & rm_08_11=8 { build MovMLReg2_7load; loadRegister(r8,r15); }
|
||
|
||
MovMLReg2_8load: is MovMLReg2_7load & rm_imm_08_11 { build MovMLReg2_7load; loadRegister(r8,r15); }
|
||
|
||
MovMLReg2_9: MovMLReg2_8 is MovMLReg2_8 { r0 = r0; }
|
||
MovMLReg2_9: rm_imm_08_11 is MovMLReg2_8load & rm_imm_08_11 & rm_08_11=9 { build MovMLReg2_8load; loadRegister(r9,r15); }
|
||
|
||
MovMLReg2_9load: is MovMLReg2_8load & rm_imm_08_11 { build MovMLReg2_8load; loadRegister(r9,r15); }
|
||
|
||
MovMLReg2_10: MovMLReg2_9 is MovMLReg2_9 { r0 = r0; }
|
||
MovMLReg2_10: rm_imm_08_11 is MovMLReg2_9load & rm_imm_08_11 & rm_08_11=10 { build MovMLReg2_9load; loadRegister(r10,r15); }
|
||
|
||
MovMLReg2_10load: is MovMLReg2_9load & rm_imm_08_11 { build MovMLReg2_9load; loadRegister(r10,r15); }
|
||
|
||
MovMLReg2_11: MovMLReg2_10 is MovMLReg2_10 { r0 = r0; }
|
||
MovMLReg2_11: rm_imm_08_11 is MovMLReg2_10load & rm_imm_08_11 & rm_08_11=11 { build MovMLReg2_10load; loadRegister(r11,r15); }
|
||
MovMLReg2_11load: is MovMLReg2_10load & rm_imm_08_11 { build MovMLReg2_10load; loadRegister(r11,r15); }
|
||
|
||
MovMLReg2_12: MovMLReg2_11 is MovMLReg2_11 { r0 = r0; }
|
||
MovMLReg2_12: rm_imm_08_11 is MovMLReg2_11load & rm_imm_08_11 & rm_08_11=12 { build MovMLReg2_11load; loadRegister(r12,r15); }
|
||
|
||
MovMLReg2_12load: is MovMLReg2_11load & rm_imm_08_11 { build MovMLReg2_11load; loadRegister(r12,r15); }
|
||
|
||
MovMLReg2_13: MovMLReg2_12 is MovMLReg2_12 { r0 = r0; }
|
||
MovMLReg2_13: rm_imm_08_11 is MovMLReg2_12load & rm_imm_08_11 & rm_08_11=13 { build MovMLReg2_12load; loadRegister(r13,r15); }
|
||
|
||
MovMLReg2_13load: is MovMLReg2_12load & rm_imm_08_11 { build MovMLReg2_12load; loadRegister(r13,r15); }
|
||
|
||
MovMLReg2_14: MovMLReg2_13 is MovMLReg2_13 { r0 = r0; }
|
||
MovMLReg2_14: rm_imm_08_11 is MovMLReg2_13load & rm_imm_08_11 & rm_08_11=14 { build MovMLReg2_13load; loadRegister(r14,r15); }
|
||
|
||
MovMLReg2_14load: is MovMLReg2_13load & rm_imm_08_11 { build MovMLReg2_13load; loadRegister(r14,r15); }
|
||
|
||
MovMLReg2_15: MovMLReg2_14 is MovMLReg2_14 { r0 = r0; }
|
||
MovMLReg2_15: rm_imm_08_11 is MovMLReg2_14load & rm_imm_08_11 & rm_08_11=15 { build MovMLReg2_14load; storeRegister(pr,r15); }
|
||
|
||
MovMLReg2: MovMLReg2_15 is MovMLReg2_15 {
|
||
build MovMLReg2_15;
|
||
}
|
||
|
||
# MOVML.L @R15+, Rn 0100nnnn11110101
|
||
:movml.l @r15+, MovMLReg2
|
||
is r15 & opcode_12_15=0b0100 & rn_imm_08_11 & opcode_00_07=0b11110101 & MovMLReg2 {
|
||
build MovMLReg2;
|
||
}
|
||
|
||
|
||
MovMUReg1_0: rm_imm_08_11 is rm_imm_08_11 & rm_08_11=0 { storeRegister(r0,r15); }
|
||
|
||
MovMUReg1_1: MovMUReg1_0 is MovMUReg1_0 { storeRegister(r1,r15); build MovMUReg1_0; }
|
||
MovMUReg1_1: rm_imm_08_11 is rm_imm_08_11 & rm_08_11=1 { storeRegister(r1,r15); }
|
||
|
||
MovMUReg1_2: MovMUReg1_1 is MovMUReg1_1 { storeRegister(r2,r15); build MovMUReg1_1; }
|
||
MovMUReg1_2: rm_imm_08_11 is rm_imm_08_11 & rm_08_11=2 { storeRegister(r2,r15); }
|
||
|
||
MovMUReg1_3: MovMUReg1_2 is MovMUReg1_2 { storeRegister(r3,r15); build MovMUReg1_2; }
|
||
MovMUReg1_3: rm_imm_08_11 is rm_imm_08_11 & rm_08_11=3 { storeRegister(r3,r15); }
|
||
|
||
MovMUReg1_4: MovMUReg1_3 is MovMUReg1_3 { storeRegister(r4,r15); build MovMUReg1_3; }
|
||
MovMUReg1_4: rm_imm_08_11 is rm_imm_08_11 & rm_08_11=4 { storeRegister(r4,r15); }
|
||
|
||
MovMUReg1_5: MovMUReg1_4 is MovMUReg1_4 { storeRegister(r5,r15); build MovMUReg1_4; }
|
||
MovMUReg1_5: rm_imm_08_11 is rm_imm_08_11 & rm_08_11=5 { storeRegister(r5,r15); }
|
||
|
||
MovMUReg1_6: MovMUReg1_5 is MovMUReg1_5 { storeRegister(r6,r15); build MovMUReg1_5; }
|
||
MovMUReg1_6: rm_imm_08_11 is rm_imm_08_11 & rm_08_11=6 { storeRegister(r6,r15); }
|
||
|
||
MovMUReg1_7: MovMUReg1_6 is MovMUReg1_6 { storeRegister(r7,r15); build MovMUReg1_6; }
|
||
MovMUReg1_7: rm_imm_08_11 is rm_imm_08_11 & rm_08_11=7 { storeRegister(r7,r15); }
|
||
|
||
MovMUReg1_8: MovMUReg1_7 is MovMUReg1_7 { storeRegister(r8,r15); build MovMUReg1_7; }
|
||
MovMUReg1_8: rm_imm_08_11 is rm_imm_08_11 & rm_08_11=8 { storeRegister(r8,r15); }
|
||
|
||
MovMUReg1_9: MovMUReg1_8 is MovMUReg1_8 { storeRegister(r9,r15); build MovMUReg1_8; }
|
||
MovMUReg1_9: rm_imm_08_11 is rm_imm_08_11 & rm_08_11=9 { storeRegister(r9,r15); }
|
||
|
||
MovMUReg1_10: MovMUReg1_9 is MovMUReg1_9 { storeRegister(r10,r15); build MovMUReg1_9; }
|
||
MovMUReg1_10: rm_imm_08_11 is rm_imm_08_11 & rm_08_11=10 { storeRegister(r10,r15); }
|
||
|
||
MovMUReg1_11: MovMUReg1_10 is MovMUReg1_10 { storeRegister(r11,r15); build MovMUReg1_10; }
|
||
MovMUReg1_11: rm_imm_08_11 is rm_imm_08_11 & rm_08_11=11 { storeRegister(r11,r15); }
|
||
|
||
MovMUReg1_12: MovMUReg1_11 is MovMUReg1_11 { storeRegister(r12,r15); build MovMUReg1_11; }
|
||
MovMUReg1_12: rm_imm_08_11 is rm_imm_08_11 & rm_08_11=12 { storeRegister(r12,r15); }
|
||
|
||
MovMUReg1_13: MovMUReg1_12 is MovMUReg1_12 { storeRegister(r13,r15); build MovMUReg1_12; }
|
||
MovMUReg1_13: rm_imm_08_11 is rm_imm_08_11 & rm_08_11=13 { storeRegister(r13,r15); }
|
||
|
||
MovMUReg1_14: MovMUReg1_13 is MovMUReg1_13 { storeRegister(r14,r15); build MovMUReg1_13; }
|
||
MovMUReg1_14: rm_imm_08_11 is rm_imm_08_11 & rm_08_11=14 { storeRegister(r14,r15); }
|
||
|
||
MovMUReg1_15: MovMUReg1_14 is MovMUReg1_14 { storeRegister(pr,r15); build MovMUReg1_14; }
|
||
MovMUReg1_15: rm_imm_08_11 is rm_imm_08_11 & rm_08_11=15 { storeRegister(pr,r15); }
|
||
|
||
MovMUReg1: MovMUReg1_15 is MovMUReg1_15 {
|
||
build MovMUReg1_15;
|
||
}
|
||
|
||
# MOVMU.L Rm, @-R15 0100mmmm11110000
|
||
:movmu.l MovMUReg1, @-r15
|
||
is r15 & opcode_12_15=0b0100 & rm_imm_08_11 & opcode_00_07=0b11110000 & MovMUReg1
|
||
{
|
||
build MovMUReg1;
|
||
}
|
||
|
||
MovMUReg2_0: rm_imm_08_11 is rm_imm_08_11 & rm_08_11=0 { loadRegister(r0,r15); }
|
||
|
||
MovMUReg2_1: MovMUReg2_0 is MovMUReg2_0 { build MovMUReg2_0; loadRegister(pr,r15); }
|
||
MovMUReg2_1: rm_imm_08_11 is rm_imm_08_11 & rm_08_11=1 { loadRegister(r1,r15); }
|
||
|
||
MovMUReg2_2: MovMUReg2_1 is MovMUReg2_1 { build MovMUReg2_1; loadRegister(pr,r15); }
|
||
MovMUReg2_2: rm_imm_08_11 is rm_imm_08_11 & rm_08_11=2 { loadRegister(r2,r15); }
|
||
|
||
MovMUReg2_3: MovMUReg2_2 is MovMUReg2_2 { build MovMUReg2_2; loadRegister(pr,r15); }
|
||
MovMUReg2_3: rm_imm_08_11 is rm_imm_08_11 & rm_08_11=3 { loadRegister(r3,r15); }
|
||
|
||
MovMUReg2_4: MovMUReg2_3 is MovMUReg2_3 { build MovMUReg2_3; loadRegister(pr,r15); }
|
||
MovMUReg2_4: rm_imm_08_11 is rm_imm_08_11 & rm_08_11=4 { loadRegister(r4,r15); }
|
||
|
||
MovMUReg2_5: MovMUReg2_4 is MovMUReg2_4 { build MovMUReg2_4; loadRegister(pr,r15); }
|
||
MovMUReg2_5: rm_imm_08_11 is rm_imm_08_11 & rm_08_11=5 { loadRegister(r5,r15); }
|
||
|
||
MovMUReg2_6: MovMUReg2_5 is MovMUReg2_5 { build MovMUReg2_5; loadRegister(pr,r15); }
|
||
MovMUReg2_6: rm_imm_08_11 is rm_imm_08_11 & rm_08_11=6 { loadRegister(r6,r15); }
|
||
|
||
MovMUReg2_7: MovMUReg2_6 is MovMUReg2_6 { build MovMUReg2_6; loadRegister(pr,r15); }
|
||
MovMUReg2_7: rm_imm_08_11 is rm_imm_08_11 & rm_08_11=7 { loadRegister(r7,r15); }
|
||
|
||
MovMUReg2_8: MovMUReg2_7 is MovMUReg2_7 { build MovMUReg2_7; loadRegister(pr,r15); }
|
||
MovMUReg2_8: rm_imm_08_11 is rm_imm_08_11 & rm_08_11=8 { loadRegister(r8,r15); }
|
||
|
||
MovMUReg2_9: MovMUReg2_8 is MovMUReg2_8 { build MovMUReg2_8; loadRegister(pr,r15); }
|
||
MovMUReg2_9: rm_imm_08_11 is rm_imm_08_11 & rm_08_11=9 { loadRegister(r9,r15); }
|
||
|
||
MovMUReg2_10: MovMUReg2_9 is MovMUReg2_9 { build MovMUReg2_9; loadRegister(pr,r15); }
|
||
MovMUReg2_10: rm_imm_08_11 is rm_imm_08_11 & rm_08_11=10 { loadRegister(r10,r15); }
|
||
|
||
MovMUReg2_11: MovMUReg2_10 is MovMUReg2_10 { build MovMUReg2_10; loadRegister(pr,r15); }
|
||
MovMUReg2_11: rm_imm_08_11 is rm_imm_08_11 & rm_08_11=11 { loadRegister(r11,r15); }
|
||
|
||
MovMUReg2_12: MovMUReg2_11 is MovMUReg2_11 { build MovMUReg2_11; loadRegister(pr,r15); }
|
||
MovMUReg2_12: rm_imm_08_11 is rm_imm_08_11 & rm_08_11=12 { loadRegister(r12,r15); }
|
||
|
||
MovMUReg2_13: MovMUReg2_12 is MovMUReg2_12 { build MovMUReg2_12; loadRegister(pr,r15); }
|
||
MovMUReg2_13: rm_imm_08_11 is rm_imm_08_11 & rm_08_11=13 { loadRegister(r13,r15); }
|
||
|
||
MovMUReg2_14: MovMUReg2_13 is MovMUReg2_13 { build MovMUReg2_13; loadRegister(pr,r15); }
|
||
MovMUReg2_14: rm_imm_08_11 is rm_imm_08_11 & rm_08_11=14 { loadRegister(r14,r15); }
|
||
|
||
MovMUReg2_15: MovMUReg2_14 is MovMUReg2_14 { build MovMUReg2_14; loadRegister(pr,r15); }
|
||
MovMUReg2_15: rm_imm_08_11 is rm_imm_08_11 & rm_08_11=15 { loadRegister(pr,r15); }
|
||
|
||
MovMUReg2: MovMUReg2_15 is MovMUReg2_15 {
|
||
build MovMUReg2_15;
|
||
}
|
||
|
||
# MOVMU.L @R15+, Rn 0100nnnn11110100
|
||
:movmu.l @r15+, MovMUReg2
|
||
is r15 & opcode_12_15=0b0100 & rn_imm_08_11 & opcode_00_07=0b11110100 & MovMUReg2
|
||
{
|
||
build MovMUReg2;
|
||
}
|
||
|
||
|
||
# MOVRT Rn 0000nnnn00111001 ~ T → Rn
|
||
:movrt rn_08_11 is opcode_12_15=0b0000 & rn_08_11 & opcode_00_07=0b00111001
|
||
{
|
||
rn_08_11 = zext($(T_FLAG) == 0);
|
||
}
|
||
|
||
# NOTT 0000000001101000 ~ T → T
|
||
:nott is opcode_00_15=0b0000000001101000
|
||
{
|
||
$(T_FLAG) = ~$(T_FLAG);
|
||
}
|
||
|
||
@endif
|
||
|
||
: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 simm_00_07,rn_08_11 is opcode_12_15=0b0111 & rn_08_11 & simm_00_07
|
||
{
|
||
rn_08_11 = rn_08_11 + simm_00_07;
|
||
}
|
||
|
||
: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" simm_00_07,r0 is r0 & opcode_08_15=0b10001000 & simm_00_07
|
||
{
|
||
$(T_FLAG) = (r0 == simm_00_07);
|
||
}
|
||
|
||
: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);
|
||
}
|
||
|
||
@if SH_VERSION == "2A"
|
||
|
||
# The pseudo code for clips in the super-h manual looks incorrect,
|
||
# this solution was contributed by @mumbel
|
||
:clips.b rn_08_11 is opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b10010001
|
||
{
|
||
local uppercheck = (rn_08_11 s> 0x7f);
|
||
local lowercheck = (rn_08_11 s< -0x80);
|
||
if (!(uppercheck || lowercheck)) goto inst_next;
|
||
rn_08_11 = (0x0000007f * zext(uppercheck)) + (0xffffff80 * zext(lowercheck));
|
||
$(CS_FLAG)=1;
|
||
}
|
||
|
||
:clips.w rn_08_11 is opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b10010101
|
||
{
|
||
local uppercheck = (rn_08_11 s> 0x7fff);
|
||
local lowercheck = (rn_08_11 s< -0x8000);
|
||
if (!(uppercheck || lowercheck)) goto inst_next;
|
||
rn_08_11 = (0x00007fff * zext(uppercheck)) + (0xffff8000 * zext(lowercheck));
|
||
$(CS_FLAG)=1;
|
||
}
|
||
|
||
:clipu.b rn_08_11 is opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b10000001
|
||
{
|
||
if (rn_08_11 <= 0x000000ff) goto <end>;
|
||
rn_08_11 = 0x000000ff;
|
||
$(CS_FLAG) = 1;
|
||
<end>
|
||
}
|
||
|
||
:clipu.w rn_08_11 is opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b10000101
|
||
{
|
||
if (rn_08_11 <= 0x0000ffff) goto <end>;
|
||
rn_08_11 = 0x0000ffff;
|
||
$(CS_FLAG) = 1;
|
||
<end>
|
||
}
|
||
|
||
@endif
|
||
|
||
: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));
|
||
|
||
# FIXME: cleaner way to do this??
|
||
tmp0 = rn_08_11;
|
||
|
||
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>
|
||
rn_08_11 = rn_08_11 - tmp2;
|
||
tmp1 = rn_08_11 > tmp0;
|
||
$(Q_FLAG) = tmp1;
|
||
goto <SET_FLAG>;
|
||
|
||
<OQ0_M0_Q1>
|
||
rn_08_11 = rn_08_11 - tmp2;
|
||
tmp1 = rn_08_11 > tmp0;
|
||
$(Q_FLAG) = tmp1 == 0;
|
||
goto <SET_FLAG>;
|
||
|
||
<OQ0_M1_Q0>
|
||
rn_08_11 = rn_08_11 + tmp2;
|
||
tmp1 = rn_08_11 < tmp0;
|
||
$(Q_FLAG) = tmp1 == 0;
|
||
goto <SET_FLAG>;
|
||
|
||
<OQ0_M1_Q1>
|
||
rn_08_11 = rn_08_11 + tmp2;
|
||
tmp1 = rn_08_11 < tmp0;
|
||
$(Q_FLAG) = tmp1;
|
||
goto <SET_FLAG>;
|
||
|
||
<OQ1_M0_Q0>
|
||
rn_08_11 = rn_08_11 + tmp2;
|
||
tmp1 = rn_08_11 < tmp0;
|
||
$(Q_FLAG) = tmp1;
|
||
goto <SET_FLAG>;
|
||
|
||
<OQ1_M0_Q1>
|
||
rn_08_11 = rn_08_11 + tmp2;
|
||
tmp1 = rn_08_11 < tmp0;
|
||
$(Q_FLAG) = tmp1;
|
||
goto <SET_FLAG>;
|
||
|
||
<OQ1_M1_Q0>
|
||
rn_08_11 = rn_08_11 - tmp2;
|
||
tmp1 = rn_08_11 > tmp0;
|
||
$(Q_FLAG) = tmp1 == 0;
|
||
goto <SET_FLAG>;
|
||
|
||
<OQ1_M1_Q1>
|
||
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 == "2A"
|
||
|
||
:divs r0, rn_08_11 is r0 & opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b10010100
|
||
{
|
||
rn_08_11 = rn_08_11 s/ r0;
|
||
}
|
||
|
||
:divu r0, rn_08_11 is r0 & opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b10000100
|
||
{
|
||
rn_08_11 = rn_08_11 / r0;
|
||
}
|
||
|
||
@endif
|
||
|
||
@if (SH_VERSION == "2") || (SH_VERSION == "2A")
|
||
: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
|
||
{
|
||
local temp:1 = rm_04_07:1;
|
||
rn_08_11 = sext(temp);
|
||
}
|
||
|
||
:exts.w rm_04_07,rn_08_11 is opcode_12_15=0b0110 & rn_08_11 & rm_04_07 & opcode_00_03=0b1111
|
||
{
|
||
local temp:2 = rm_04_07:2;
|
||
rn_08_11 = sext(temp);
|
||
}
|
||
|
||
: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") || (SH_VERSION == "2A")
|
||
:mac.l @rm_04_07+,@rn_08_11+ is opcode_12_15=0b0000 & rn_08_11 & rm_04_07 & opcode_00_03=0b1111
|
||
{
|
||
# FIXME: 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;
|
||
|
||
fnLmL = -1 * zext((tempn ^ tempm) s<0);
|
||
|
||
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
|
||
{
|
||
# FIXME: 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);
|
||
|
||
src = zext(1*(tempm s>= 0));
|
||
tempn = sext(-1*(tempm s>= 0));
|
||
|
||
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;
|
||
|
||
macl = macl + zext(1*(templ s> macl));
|
||
|
||
@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") || (SH_VERSION == "2A")
|
||
: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
|
||
|
||
@if SH_VERSION == "2A"
|
||
:mulr r0, rn_08_11 is r0 & opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b10000000
|
||
{
|
||
rn_08_11 = r0 * rn_08_11;
|
||
}
|
||
@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));
|
||
|
||
# FIXME: 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 & zext(imm_00_07:1));
|
||
}
|
||
|
||
:and.b imm_00_07,@(r0,gbr) is r0 & gbr & opcode_08_15=0b11001101 & imm_00_07
|
||
{
|
||
local temp:1 = *:1 (gbr + r0);
|
||
temp = temp & imm_00_07:1;
|
||
|
||
*: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 = *:1 (gbr + r0);
|
||
temp = temp | imm_00_07:1;
|
||
|
||
*: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 & rn_08_11) == 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) | zext($(T_FLAG));
|
||
|
||
$(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) | (0x80000000 * zext($(T_FLAG)));
|
||
|
||
$(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);
|
||
|
||
rn_08_11 = (rn_08_11 << 1) | zext($(T_FLAG));
|
||
}
|
||
|
||
:rotr rn_08_11 is opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b00000101
|
||
{
|
||
$(T_FLAG) = ((rn_08_11 & 0x1) != 0);
|
||
|
||
rn_08_11 = (rn_08_11 >> 1) | (rn_08_11 << 31);
|
||
}
|
||
|
||
@if SH_VERSION == "2A"
|
||
:shad rm_04_07, rn_08_11 is opcode_12_15=0b0100 & rn_08_11 & rm_04_07 & opcode_00_03=0b1100
|
||
{
|
||
if (rm_04_07 s> 0) goto <shift_left>;
|
||
if (rm_04_07 s<= -32) goto <shift_right_32>;
|
||
# shift right
|
||
rn_08_11 = rn_08_11 s>> -rm_04_07;
|
||
goto <end>;
|
||
<shift_left>
|
||
rn_08_11 = rn_08_11 << (rm_04_07 & 0x0000001F);
|
||
goto <end>;
|
||
<shift_right_32>
|
||
rn_08_11 = -1 * zext(rn_08_11 s< 0);
|
||
<end>
|
||
}
|
||
@endif
|
||
|
||
: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 s>> 1;
|
||
}
|
||
|
||
@if SH_VERSION == "2A"
|
||
:shld rm_04_07, rn_08_11 is opcode_12_15=0b0100 & rn_08_11 & rm_04_07 & opcode_00_03=0b1101
|
||
{
|
||
if (rm_04_07 s> 0) goto <shift_left>;
|
||
if (rm_04_07 s<= -32) goto <shift_right_32>;
|
||
# shift right
|
||
rn_08_11 = rn_08_11 >> -rm_04_07;
|
||
goto <end>;
|
||
<shift_left>
|
||
rn_08_11 = rn_08_11 << (rm_04_07 & 0x0000001F);
|
||
goto <end>;
|
||
<shift_right_32>
|
||
rn_08_11 = 0;
|
||
<end>
|
||
}
|
||
@endif
|
||
|
||
: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;
|
||
}
|
||
|
||
:shlr2 rn_08_11 is opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b00001001
|
||
{
|
||
rn_08_11 = rn_08_11 >> 2;
|
||
}
|
||
|
||
:shlr8 rn_08_11 is opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b00011001
|
||
{
|
||
rn_08_11 = rn_08_11 >> 8;
|
||
}
|
||
|
||
:shlr16 rn_08_11 is opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b00101001
|
||
{
|
||
rn_08_11 = rn_08_11 >> 16;
|
||
}
|
||
|
||
#
|
||
# Branch Instructions
|
||
#
|
||
:bf target00_07 is opcode_08_15=0b10001011 & target00_07
|
||
{
|
||
if ($(T_FLAG) == 0) goto target00_07;
|
||
}
|
||
|
||
@if (SH_VERSION == "2") || (SH_VERSION == "2A")
|
||
: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") || (SH_VERSION == "2A")
|
||
: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") || (SH_VERSION == "2A")
|
||
: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_next;
|
||
delayslot(1);
|
||
call target00_11;
|
||
}
|
||
|
||
@if (SH_VERSION == "2") || (SH_VERSION == "2A")
|
||
:bsrf rm_08_11 is opcode_12_15=0b0000 & rm_08_11 & opcode_00_07=0b00000011
|
||
{
|
||
pr = inst_next;
|
||
local dest = rm_08_11 + inst_next;
|
||
|
||
delayslot(1);
|
||
call [dest];
|
||
}
|
||
@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_next;
|
||
delayslot(1);
|
||
call [rm_08_11];
|
||
}
|
||
|
||
:rts is opcode_00_15=0b0000000000001011
|
||
{
|
||
delayslot(1);
|
||
return [pr];
|
||
}
|
||
|
||
@if SH_VERSION == "2A"
|
||
|
||
# JSR/N @Rm 0100mmmm01001011 PC - 2 → PR, Rm → PC
|
||
:jsr"/n" @rm_08_11
|
||
is opcode_12_15=0b0100 & rm_08_11 & opcode_00_07=0b01001011
|
||
{
|
||
pr = inst_next;
|
||
call [rm_08_11];
|
||
}
|
||
|
||
# JSR/N @@(disp8, TBR) 10000011dddddddd PC - 2 → PR, (disp×4+TBR) → PC
|
||
:jsr"/n" @@(disp, tbr)
|
||
is tbr & opcode_08_15=0b10000011 & disp_00_07
|
||
[ disp = disp_00_07*4; ]
|
||
{
|
||
pr = inst_next;
|
||
call [tbr + disp*4];
|
||
}
|
||
|
||
# RTS/N 0000000001101011 PR → PC
|
||
:rts"/n"
|
||
is opcode_00_15=0b0000000001101011
|
||
{
|
||
return [pr];
|
||
}
|
||
|
||
:rtv"/n" rm_08_11 is opcode_12_15=0b0000 & rm_08_11 & opcode_00_07=0b01111011
|
||
{
|
||
r0 = rm_08_11;
|
||
return [pr];
|
||
}
|
||
|
||
@endif
|
||
|
||
|
||
#
|
||
# System Control Instructions
|
||
#
|
||
:clrmac is opcode_00_15=0b0000000000101000
|
||
{
|
||
mach = 0;
|
||
macl = 0;
|
||
}
|
||
|
||
:clrt is opcode_00_15=0b0000000000001000
|
||
{
|
||
$(T_FLAG) = 0;
|
||
}
|
||
|
||
@if SH_VERSION == "2A"
|
||
:ldbank @rm_08_11, r0 is r0 & opcode_12_15=0b0100 & rm_08_11 & opcode_00_07=0b11100101
|
||
{
|
||
local cnt = *:4 (rm_08_11);
|
||
local bn = (cnt & 0x0000FF80) >> 7;
|
||
local en = (cnt & 0x0000007C) >> 2;
|
||
local off = (bn * 80) + en * 4;
|
||
|
||
local rb = &resbank_base + off;
|
||
|
||
r0 = *[register]:4 (rb);
|
||
}
|
||
|
||
:stbank r0, @rn_08_11 is r0 & opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b11100001
|
||
{
|
||
local cnt = *:4 (rn_08_11);
|
||
local bn = (cnt & 0x0000FF80) >> 7;
|
||
local en = (cnt & 0x0000007C) >> 2;
|
||
local off = (bn * 80) + en * 4;
|
||
|
||
local rb = &resbank_base + off;
|
||
|
||
*[register]:4 (rb) = r0;
|
||
}
|
||
|
||
:resbank is opcode_00_15=0b0000000001011011
|
||
{
|
||
# This can be left as NOP, as it's used for saving/restoring context on interrupts
|
||
r0 = r0;
|
||
}
|
||
|
||
@endif
|
||
|
||
: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;
|
||
}
|
||
|
||
@if SH_VERSION == "2A"
|
||
:ldc rm_08_11, tbr is tbr & opcode_12_15=0b0100 & rm_08_11 & opcode_00_07=0b01001010
|
||
{
|
||
tbr = rm_08_11;
|
||
}
|
||
@endif
|
||
|
||
: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"
|
||
# sign extend 10 bit signed value from rm
|
||
mach = (mach << (32-10)) s>> (32-10);
|
||
@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"
|
||
# sign extend 10 bit signed value from rm
|
||
mach = (mach << (32-10)) s>> (32-10);
|
||
@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
|
||
{
|
||
# FIXME: 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;
|
||
|
||
return [pc];
|
||
}
|
||
|
||
:sett is opcode_00_15=0b0000000000011000
|
||
{
|
||
$(T_FLAG) = 1;
|
||
}
|
||
|
||
define pcodeop Sleep_Standby;
|
||
|
||
:sleep is opcode_00_15=0b0000000000011011
|
||
{
|
||
Sleep_Standby();
|
||
}
|
||
|
||
: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;
|
||
}
|
||
|
||
@if SH_VERSION == "2A"
|
||
:stc tbr,rn_08_11 is tbr & opcode_12_15=0b0000 & rn_08_11 & opcode_00_07=0b01001010
|
||
{
|
||
rn_08_11 = tbr;
|
||
}
|
||
@endif
|
||
|
||
: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"
|
||
# sign extend 10 bit signed value from rm
|
||
rn_08_11 = (rn_08_11 << (32-10)) s>> (32-10);
|
||
@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"
|
||
# sign extend 10 bit signed value from rm
|
||
temp = (temp << (32-10)) s>> (32-10);
|
||
@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];
|
||
}
|
||
|
||
@if defined(FPU)
|
||
|
||
#
|
||
# Floating-Point Instructions
|
||
#
|
||
|
||
# FABS FRn 1111nnnn01011101 |FRn| → FRn
|
||
:fabs ffrn_08_11 is fop_12_15=0b1111 & ffrn_08_11 & fop_00_07=0b01011101
|
||
{
|
||
ffrn_08_11 = abs(ffrn_08_11);
|
||
}
|
||
|
||
# TODO: FABS DRn 1111nnn001011101 |DRn| → DRn
|
||
|
||
# FADD FRm, FRn 1111nnnnmmmm0000 FRn + FRm → FRn
|
||
:fadd ffrm_04_07, ffrn_08_11 is fop_12_15=0b1111 & ffrn_08_11 & ffrm_04_07 & fop_00_03=0b0000
|
||
{
|
||
ffrn_08_11 = ffrn_08_11 f+ ffrm_04_07;
|
||
}
|
||
|
||
# TODO: FADD DRm, DRn 1111nnn0mmm00000 DRn + DRm → DRn
|
||
|
||
# FCMP/EQ FRm, FRn 1111nnnnmmmm0100 (FRn=FRm)? 1:0 → T
|
||
:fcmp"/eq" ffrm_04_07, ffrn_08_11 is fop_12_15=0b1111 & ffrn_08_11 & ffrm_04_07 & fop_00_03=0b0100
|
||
{
|
||
$(T_FLAG) = (ffrn_08_11 f== ffrm_04_07);
|
||
}
|
||
|
||
# TODO: FCMP/EQ DRm, DRn 1111nnn0mmm00100 (DRn=DRm)? 1:0 → T
|
||
|
||
# FCMP/GT FRm, FRn 1111nnnnmmmm0101 (FRn>FRm)? 1:0 → T
|
||
:fcmp"/gt" ffrm_04_07, ffrn_08_11 is fop_12_15=0b1111 & ffrn_08_11 & ffrm_04_07 & fop_00_03=0b0101
|
||
{
|
||
$(T_FLAG) = (ffrn_08_11 f> ffrm_04_07);
|
||
}
|
||
|
||
# TODO: FCMP/GT DRm, DRn 1111nnn0mmm00101 (DRn>DRm)? 1:0 → T
|
||
|
||
# FCNVDS DRm, FPUL 1111mmm010111101 (float) DRm → FPUL
|
||
:fcnvds fdrm_09_11, fpul is fpul & fop_12_15=0b1111 & fdrm_09_11 & fop_08_08=0b0 & fop_00_07=0b10111101
|
||
{
|
||
fpul = float2float(fdrm_09_11);
|
||
}
|
||
|
||
# FCNVSD FPUL, DRn 1111nnn010101101 (double) FPUL → DRn
|
||
:fcnvsd fpul, fdrn_09_11 is fpul & fop_12_15=0b1111 & fdrn_09_11 & fop_08_08=0b0 & fop_00_07=0b10101101
|
||
{
|
||
fdrn_09_11 = float2float(fpul);
|
||
}
|
||
|
||
# FDIV FRm, FRn 1111nnnnmmmm0011 FRn/FRm → FRn
|
||
:fdiv ffrm_04_07, ffrn_08_11 is fop_12_15=0b1111 & ffrn_08_11 & ffrm_04_07 & fop_00_03=0b0011
|
||
{
|
||
ffrn_08_11 = ffrn_08_11 f/ ffrm_04_07;
|
||
}
|
||
|
||
# TODO: FDIV DRm, DRn 1111nnn0mmm00011 DRn/DRm → DRn
|
||
|
||
# FLDI0 FRn 1111nnnn10001101 0 × 00000000 → FRn
|
||
:fldi0 ffrn_08_11 is fop_12_15=0b1111 & ffrn_08_11 & fop_00_07=0b10001101
|
||
{
|
||
ffrn_08_11 = 0x00000000;
|
||
}
|
||
|
||
# FLDI1 FRn 1111nnnn10011101 0 × 3F800000 → FRn
|
||
:fldi1 ffrn_08_11 is fop_12_15=0b1111 & ffrn_08_11 & fop_00_07=0b10011101
|
||
{
|
||
ffrn_08_11 = 0x3F800000;
|
||
}
|
||
|
||
|
||
# FLDS FRm, FPUL 1111mmmm00011101 FRm → FPUL
|
||
:flds ffrm_08_11, fpul is fpul & fop_12_15=0b1111 & ffrm_08_11 & fop_00_07=0b00011101
|
||
{
|
||
fpul = ffrm_08_11;
|
||
}
|
||
|
||
# FLOAT FPUL,FRn 1111nnnn00101101 (float) FPUL → FRn
|
||
:float fpul, ffrn_08_11 is fpul & fop_12_15=0b1111 & ffrn_08_11 & fop_00_07=0b00101101
|
||
{
|
||
ffrn_08_11 = int2float(fpul);
|
||
}
|
||
|
||
# TODO: FLOAT FPUL,DRn 1111nnn000101101 (double) FPUL → DRn
|
||
|
||
# FMAC FR0, FRm, FRn 1111nnnnmmmm1110 FR0 × FRm + FRn → FRn
|
||
:fmac fr0, ffrm_04_07, ffrn_08_11 is fr0 & fop_12_15=0b1111 & ffrn_08_11 & ffrm_04_07 & fop_00_03=0b1110
|
||
{
|
||
ffrn_08_11 = ffrn_08_11 f+ (ffrm_04_07 f* fr0);
|
||
}
|
||
|
||
# FMOV FRm, FRn 1111nnnnmmmm1100 FRm → FRn
|
||
:fmov ffrm_04_07, ffrn_08_11 is fop_12_15=0b1111 & ffrn_08_11 & ffrm_04_07 & fop_00_03=0b1100
|
||
{
|
||
ffrn_08_11 = ffrm_04_07;
|
||
}
|
||
|
||
# TODO: FMOV DRm, DRn 1111nnn0mmm01100 DRm → DRn
|
||
|
||
# FMOV.S @(R0, Rm), FRn 1111nnnnmmmm0110 (R0+Rm) → FRn
|
||
:fmov.s @(r0, f_rm_04_07), ffrn_08_11 is r0 & fop_12_15=0b1111 & ffrn_08_11 & f_rm_04_07 & fop_00_03=0b0110
|
||
{
|
||
ffrn_08_11 = *:4 (r0 + f_rm_04_07);
|
||
}
|
||
|
||
# TODO: FMOV.D @(R0, Rm), DRn 1111nnn0mmmm0110 (R0+Rm) → DRn
|
||
|
||
# FMOV.S @Rm+, FRn 1111nnnnmmmm1001 (Rm) → FRn, Rm+ = 4
|
||
:fmov.s @f_rm_04_07+, ffrn_08_11 is fop_12_15=0b1111 & ffrn_08_11 & f_rm_04_07 & fop_00_03=0b1001
|
||
{
|
||
ffrn_08_11 = *:4 (f_rm_04_07);
|
||
f_rm_04_07 = f_rm_04_07 + 4;
|
||
}
|
||
|
||
# TODO: FMOV.D @Rm+, DRn 1111nnn0mmmm1001 (Rm) → DRn, Rm+ = 8
|
||
|
||
# FMOV.S @Rm, FRn 1111nnnnmmmm1000 (Rm) → FRn
|
||
:fmov.s @f_rm_04_07, ffrn_08_11 is fop_12_15=0b1111 & ffrn_08_11 & f_rm_04_07 & fop_00_03=0b1000
|
||
{
|
||
ffrn_08_11 = *:4 (f_rm_04_07);
|
||
}
|
||
|
||
# TODO: FMOV.D @Rm, DRn 1111nnn0mmmm1000 (Rm) → DRn
|
||
|
||
# FMOV.S @(disp12,Rm),FRn 0011nnnnmmmm0001 0111dddddddddddd (disp×4+Rm) → FRn
|
||
:fmov.s @(disp12, lf_rm_20_23), lffrn_24_27
|
||
is lfop_28_31=0b0011 & lffrn_24_27 & lf_rm_20_23 & lfop_12_19=0b00010111 & lfdisp_00_11
|
||
[ disp12 = lfdisp_00_11 * 4; ]
|
||
{
|
||
lffrn_24_27 = *:4 (disp12 + lf_rm_20_23);
|
||
}
|
||
|
||
# TODO: FMOV.D @(disp12,Rm),DRn 0011nnn0mmmm0001 0111dddddddddddd (disp×8+Rm) → DRn
|
||
|
||
# FMOV.S FRm, @( R0,Rn ) 1111nnnnmmmm0111 FRm → (R0+Rn)
|
||
:fmov.s ffrm_04_07, @( r0, f_rn_08_11 ) is r0 & fop_12_15=0b1111 & f_rn_08_11 & ffrm_04_07 & fop_00_03=0b0111
|
||
{
|
||
*:4 (f_rn_08_11 + r0) = ffrm_04_07;
|
||
}
|
||
|
||
# TODO: FMOV.D DRm, @( R0,Rn ) 1111nnnnmmm00111 DRm → (R0+Rn)
|
||
|
||
# FMOV.S FRm, @-Rn 1111nnnnmmmm1011 Rn- = 4, FRm → (Rn)
|
||
:fmov.s ffrm_04_07, @-f_rn_08_11 is fop_12_15=0b1111 & f_rn_08_11 & ffrm_04_07 & fop_00_03=0b1011
|
||
{
|
||
f_rn_08_11 = f_rn_08_11 - 4;
|
||
*:4 (f_rn_08_11) = ffrm_04_07;
|
||
}
|
||
|
||
# TODO: FMOV.D DRm, @-Rn 1111nnnnmmm01011 Rn- = 8, DRm → (Rn)
|
||
|
||
# FMOV.S FRm, @Rn 1111nnnnmmmm1010 FRm → (Rn)
|
||
:fmov.s ffrm_04_07, @f_rn_08_11 is fop_12_15=0b1111 & f_rn_08_11 & ffrm_04_07 & fop_00_03=0b1010
|
||
{
|
||
*:4 (f_rn_08_11) = ffrm_04_07;
|
||
}
|
||
|
||
# TODO: FMOV.D DRm, @Rn 1111nnnnmmm01010 DRm → (Rn)
|
||
|
||
# FMOV.S FRm, @(disp12,Rn) 0011nnnnmmmm0001 0011dddddddddddd FRm → (disp×4+Rn)
|
||
:fmov.s lffrm_20_23, @(disp12, lf_rn_24_27)
|
||
is lfop_28_31=0b0011 & lf_rn_24_27 & lffrm_20_23 & lfop_12_19=0b00010011 & lfdisp_00_11
|
||
[ disp12 = lfdisp_00_11 * 4; ]
|
||
{
|
||
*:4 (disp12 + lf_rn_24_27) = lffrm_20_23;
|
||
}
|
||
|
||
|
||
# TODO: FMOV.D DRm, @(disp12,Rn) 0011nnnnmmm000010 011dddddddddddd DRm → (disp×8+Rn)
|
||
|
||
# FMUL FRm, FRn 1111nnnnmmmm0010 FRn × FRm → FRn
|
||
:fmul ffrm_04_07, ffrn_08_11 is fop_12_15=0b1111 & ffrn_08_11 & ffrm_04_07 & fop_00_03=0b0010
|
||
{
|
||
ffrn_08_11 = ffrn_08_11 f* ffrm_04_07;
|
||
}
|
||
|
||
# TODO: FMUL DRm, DRn 1111nnn0mmm00010 DRn × DRm → DRn
|
||
# FNEG FRn 1111nnnn01001101 -FRn → FRn
|
||
:fneg ffrn_08_11 is fop_12_15=0b1111 & ffrn_08_11 & fop_00_07=0b01001101
|
||
{
|
||
ffrn_08_11 = f- ffrn_08_11;
|
||
}
|
||
|
||
# TODO: FNEG DRn 1111nnn001001101 -DRn → DRn
|
||
# FSCHG 1111001111111101 FPSCR.SZ = ~ FPSCR.SZ
|
||
:fschg is fop_00_15=0b1111001111111101
|
||
{
|
||
$(FP_SZ) = ~ $(FP_SZ);
|
||
}
|
||
|
||
# FSQRT FRn 1111nnnn01101101 √FRn → FRn
|
||
:fsqrt ffrn_08_11 is fop_12_15=0b1111 & ffrn_08_11 & fop_00_07=0b01101101
|
||
{
|
||
ffrn_08_11 = sqrt(ffrn_08_11);
|
||
}
|
||
|
||
# TODO: FSQRT DRn 1111nnn001101101 √DRn → DRn
|
||
# FSTS FPUL, FRn 1111nnnn00001101 FPUL → FRn
|
||
:fsts fpul, ffrn_08_11 is fpul & fop_12_15=0b1111 & ffrn_08_11 & fop_00_07=0b00001101
|
||
{
|
||
ffrn_08_11 = fpul;
|
||
}
|
||
|
||
# FSUB FRm, FRn 1111nnnnmmmm0001 FRn - FRm → FRn
|
||
:fsub ffrm_04_07, ffrn_08_11 is fop_12_15=0b1111 & ffrn_08_11 & ffrm_04_07 & fop_00_03=0b0001
|
||
{
|
||
ffrn_08_11 = ffrn_08_11 f- ffrm_04_07;
|
||
}
|
||
|
||
# TODO: FSUB DRm, DRn 1111nnn0mmm00001 DRn - DRm → DRn
|
||
|
||
# FTRC FRm, FPUL 1111mmmm00111101 (long) FRm → FPUL
|
||
:ftrc ffrm_08_11, fpul is fpul & fop_12_15=0b1111 & ffrm_08_11 & fop_00_07=0b00111101
|
||
{
|
||
fpul = trunc(ffrm_08_11);
|
||
}
|
||
|
||
# FTRC DRm, FPUL 1111mmm000111101 (long) DRm → FPUL
|
||
|
||
@endif
|
||
|
||
|
||
@if defined(FPU)
|
||
|
||
#
|
||
# FPU-related CPU Instructions
|
||
#
|
||
|
||
# LDS Rm,FPSCR 0100mmmm01101010 Rm → FPSCR
|
||
:lds rm_08_11, fpscr is fpscr & opcode_12_15=0b0100 & rm_08_11 & opcode_00_07=0b01101010
|
||
{
|
||
fpscr = rm_08_11;
|
||
}
|
||
|
||
# LDS Rm,FPUL 0100mmmm01011010 Rm → FPUL
|
||
:lds rm_08_11, fpul is fpul & opcode_12_15=0b0100 & rm_08_11 & opcode_00_07=0b01011010
|
||
{
|
||
fpul = rm_08_11;
|
||
}
|
||
|
||
# LDS.L @Rm+, FPSCR 0100mmmm01100110 (Rm) → FPSCR, Rm+ = 4
|
||
:lds.l @rm_08_11+, fpscr is fpscr & opcode_12_15=0b0100 & rm_08_11 & opcode_00_07=0b01100110
|
||
{
|
||
fpscr = *:4 (rm_08_11);
|
||
rm_08_11 = rm_08_11 + 4;
|
||
}
|
||
|
||
# LDS.L @Rm+, FPUL 0100mmmm01010110 (Rm) → FPUL, Rm+ = 4
|
||
:lds.l @rm_08_11+, fpul is fpul & opcode_12_15=0b0100 & rm_08_11 & opcode_00_07=0b01010110
|
||
{
|
||
fpul = *:4 (rm_08_11);
|
||
rm_08_11 = rm_08_11 + 4;
|
||
}
|
||
|
||
# STS FPSCR, Rn 0000nnnn01101010 FPSCR → Rn
|
||
:sts fpscr, rn_08_11 is fpscr & opcode_12_15=0b0000 & rn_08_11 & opcode_00_07=0b01101010
|
||
{
|
||
rn_08_11 = fpscr;
|
||
}
|
||
|
||
# STS FPUL,Rn 0000nnnn01011010 FPUL → Rn
|
||
:sts fpul, rn_08_11 is fpul & opcode_12_15=0b0000 & rn_08_11 & opcode_00_07=0b01011010
|
||
{
|
||
rn_08_11 = fpul;
|
||
}
|
||
|
||
# STS.L FPSCR,@-Rn 0100nnnn01100010 Rn- = 4, fpscr → (Rn)
|
||
:sts.l fpscr, @-rn_08_11 is fpscr & opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b01100010
|
||
{
|
||
rn_08_11 = rn_08_11 - 4;
|
||
*:4 (rn_08_11) = fpscr;
|
||
}
|
||
|
||
# STS.L FPUL,@-Rn 0100nnnn01010010 Rn- = 4, FPUL → (Rn)
|
||
:sts.l fpul, @-rn_08_11 is fpul & opcode_12_15=0b0100 & rn_08_11 & opcode_00_07=0b01010010
|
||
{
|
||
rn_08_11 = rn_08_11 - 4;
|
||
*:4 (rn_08_11) = fpul;
|
||
}
|
||
|
||
# @if defined(FPU)
|
||
@endif
|
||
|
||
|
||
@if SH_VERSION == "2A"
|
||
|
||
#
|
||
# Bit Manipulation Instructions
|
||
#
|
||
# The BAND.B, BOR.B, and BXOR.B instructions perform logical operations between a bit in
|
||
# memory and the T bit, and store the result in the T bit. The BCLR.B and BSET.B instructions
|
||
# manipulate a bit in memory. The BST.B and BLD.B instructions execute a transfer between a bit
|
||
# in memory and the T bit. The BANDNOT.B and BORNOT.B instructions perform logical
|
||
# operations between the value resulting from inverting a bit in memory and the T bit, and store the
|
||
# result in the T bit. The BLDNOT.B instruction inverts a bit in memory and stores the result in the
|
||
# T bit. Bits other than the specified bit are not affected.
|
||
#
|
||
|
||
# BAND.B #imm3, @(disp12,Rn) 0011nnnn0iii1001 0100dddddddddddd (imm of (disp+Rn)) & T → T
|
||
:band.b "#"l_imm3_20_22 @(l_disp_00_11, l_rn_24_27)
|
||
is l_opcode_28_31=0b0011 & l_rn_24_27 & l_opcode_23_23=0b0 & l_imm3_20_22 & l_opcode_16_19=0b1001 & l_opcode_12_15=0b0100 & l_disp_00_11
|
||
{
|
||
local b = *:1 (l_disp_00_11 + l_rn_24_27);
|
||
$(T_FLAG) = ((b & (1 << l_imm3_20_22)) & $(T_FLAG) != 0);
|
||
}
|
||
|
||
# BANDNOT.B #imm3, @(disp12,Rn) 0011nnnn0iii1001 1100dddddddddddd ~ (imm of (disp+Rn)) & T → T
|
||
:bandnot.b "#"l_imm3_20_22, @(l_disp_00_11, l_rn_24_27)
|
||
is l_opcode_28_31=0b0011 & l_rn_24_27 & l_opcode_23_23=0b0 & l_imm3_20_22 & l_opcode_16_19=0b1001 & l_opcode_12_15=0b1100 & l_disp_00_11
|
||
{
|
||
local b = *:1 (l_disp_00_11 + l_rn_24_27);
|
||
$(T_FLAG) = ((~ (b & (1 << l_imm3_20_22)) & $(T_FLAG)) != 0);
|
||
}
|
||
|
||
# BCLR.B #imm3, @(disp12,Rn) 0011nnnn0iii1001 0000dddddddddddd 0 → (imm of (disp+Rn))
|
||
:bclr.b "#"l_imm3_20_22, @(l_disp_00_11, l_rn_24_27)
|
||
is l_opcode_28_31=0b0011 & l_rn_24_27 & l_opcode_23_23=0b0 & l_imm3_20_22 & l_opcode_16_19=0b1001 & l_opcode_12_15=0b0000 & l_disp_00_11
|
||
{
|
||
local addr = l_disp_00_11 + l_rn_24_27;
|
||
local b = *:1 (addr);
|
||
*:1 (addr) = b & (~(1 << l_imm3_20_22));
|
||
}
|
||
|
||
# BCLR #imm3, Rn 10000110nnnn0iii 0 → imm of Rn
|
||
:bclr "#"imm3_00_02, rn_04_07
|
||
is opcode_08_15=0b10000110 & rn_04_07 & opcode_03_03=0b0 & imm3_00_02
|
||
{
|
||
local b = *:1 (rn_04_07);
|
||
*:1 (rn_04_07) = b & (~(1 << imm3_00_02));
|
||
}
|
||
|
||
# BLD.B #imm3, @(disp12,Rn) 0011nnnn0iii1001 0011dddddddddddd (imm of (disp+Rn)) → T
|
||
:bld.b "#"l_imm3_20_22, @(l_disp_00_11, l_rn_24_27)
|
||
is l_opcode_28_31=0b0011 & l_rn_24_27 & l_opcode_23_23=0b0 & l_imm3_20_22 & l_opcode_16_19=0b1001 & l_opcode_12_15=0b0011 & l_disp_00_11
|
||
{
|
||
local b = *:1 (l_disp_00_11 + l_rn_24_27);
|
||
$(T_FLAG) = ((b & (1 << l_imm3_20_22)) != 0);
|
||
}
|
||
|
||
# BLD #imm3, Rn 10000111nnnn1iii imm of Rn → T
|
||
:bld "#"imm3_00_02, rn_04_07
|
||
is opcode_08_15=0b10000111 & rn_04_07 & opcode_03_03=0b1 & imm3_00_02
|
||
{
|
||
local b = *:1 (rn_04_07);
|
||
$(T_FLAG) = ((b & (1 << imm3_00_02)) != 0);
|
||
}
|
||
|
||
# BLDNOT.B #imm3, @(disp12,Rn) 0011nnnn0iii1001 1011dddddddddddd ~ (imm of (disp+Rn)) → T
|
||
:bldnot.b "#"l_imm3_20_22, @(l_disp_00_11, l_rn_24_27)
|
||
is l_opcode_28_31=0b0011 & l_rn_24_27 & l_opcode_23_23=0b0 & l_imm3_20_22 & l_opcode_16_19=0b1001 & l_opcode_12_15=0b1011 & l_disp_00_11
|
||
{
|
||
local b = *:1 (l_disp_00_11 + l_rn_24_27);
|
||
$(T_FLAG) = ((b & (1 << l_imm3_20_22)) == 0);
|
||
}
|
||
|
||
# BOR.B #imm3, @(disp12,Rn) 0011nnnn0iii1001 0101dddddddddddd (imm of (disp+ Rn)) | T → T
|
||
:bor.b "#"l_imm3_20_22, @(l_disp_00_11, l_rn_24_27)
|
||
is l_opcode_28_31=0b0011 & l_rn_24_27 & l_opcode_23_23=0b0 & l_imm3_20_22 & l_opcode_16_19=0b1001 & l_opcode_12_15=0b0101 & l_disp_00_11
|
||
{
|
||
local b = *:1 (l_disp_00_11 + l_rn_24_27);
|
||
local abit = b & (1 << l_imm3_20_22);
|
||
$(T_FLAG) = $(T_FLAG) | (abit != 0);
|
||
}
|
||
|
||
# BORNOT.B #imm3, @(disp12,Rn) 0011nnnn0iii1001 1101dddddddddddd ~ (imm of (disp+ Rn)) | T → T
|
||
:bornot.b "#"l_imm3_20_22, @(l_disp_00_11, l_rn_24_27)
|
||
is l_opcode_28_31=0b0011 & l_rn_24_27 & l_opcode_23_23=0b0 & l_imm3_20_22 & l_opcode_16_19=0b1001 & l_opcode_12_15=0b1101 & l_disp_00_11
|
||
{
|
||
local b = *:1 (l_disp_00_11 + l_rn_24_27);
|
||
local abit = b & (1 << l_imm3_20_22);
|
||
$(T_FLAG) = $(T_FLAG) | (abit == 0);
|
||
}
|
||
|
||
# BSET.B #imm3, @(disp12,Rn) 0011nnnn0iii1001 0001dddddddddddd 1 → (imm of (disp+Rn))
|
||
:bset.b "#"l_imm3_20_22, @(l_disp_00_11, l_rn_24_27)
|
||
is l_opcode_28_31=0b0011 & l_rn_24_27 & l_opcode_23_23=0b0 & l_imm3_20_22 & l_opcode_16_19=0b1001 & l_opcode_12_15=0b0001 & l_disp_00_11
|
||
{
|
||
local b = *:1 (l_disp_00_11 + l_rn_24_27);
|
||
local newb = b | (1 << l_imm3_20_22);
|
||
*:1 (l_disp_00_11 + l_rn_24_27) = newb;
|
||
}
|
||
|
||
# BSET #imm3, Rn 10000110nnnn1iii 1 → imm of Rn
|
||
:bset "#"imm3_00_02, rn_04_07
|
||
is opcode_08_15=0b10000110 & rn_04_07 & opcode_03_03=0b1 & imm3_00_02
|
||
{
|
||
rn_04_07 = rn_04_07 | (1 << imm3_00_02);
|
||
}
|
||
|
||
# BST.B #imm3 ,@(disp12,Rn) 0011nnnn0iii1001 0010dddddddddddd T → (imm of (disp+Rn))
|
||
:bst.b "#"l_imm3_20_22, @(l_disp_00_11, l_rn_24_27)
|
||
is l_opcode_28_31=0b0011 & l_rn_24_27 & l_opcode_23_23=0b0 & l_imm3_20_22 & l_opcode_16_19=0b1001 & l_opcode_12_15=0b0010 & l_disp_00_11
|
||
{
|
||
local b = *:1 (l_disp_00_11 + l_rn_24_27);
|
||
local ibit = 1 << l_imm3_20_22;
|
||
b = (b | ibit) * ($(T_FLAG) != 0) + (b & (~ibit)) * ($(T_FLAG) == 0);
|
||
*:1 (l_disp_00_11 + l_rn_24_27) = b;
|
||
}
|
||
|
||
# BST #imm3, Rn 10000111nnnn0iii T → imm of Rn
|
||
:bst "#"imm3_00_02, rn_04_07
|
||
is opcode_08_15=0b10000111 & rn_04_07 & opcode_03_03=0b0 & imm3_00_02
|
||
{
|
||
local ibit = 1 << imm3_00_02;
|
||
rn_04_07 = (rn_04_07 | ibit) * zext($(T_FLAG) != 0) + (rn_04_07 & (~ibit)) * zext($(T_FLAG) == 0);
|
||
}
|
||
|
||
# BXOR.B #imm3, @(disp12, Rn) 0011nnnn0iii1001 0110dddddddddddd (imm of (disp+ Rn)) ^ T → T
|
||
:bxor.b "#"l_imm3_20_22, @(l_disp_00_11, l_rn_24_27)
|
||
is l_opcode_28_31=0b0011 & l_rn_24_27 & l_opcode_23_23=0b0 & l_imm3_20_22 & l_opcode_16_19=0b1001 & l_opcode_12_15=0b0110 & l_disp_00_11
|
||
{
|
||
# extract bit to test
|
||
local b = *:1 (l_rn_24_27 + l_disp_00_11);
|
||
local abit = (b >> l_imm3_20_22) & 1;
|
||
|
||
$(T_FLAG) = $(T_FLAG) ^ abit;
|
||
}
|
||
|
||
@endif
|