From 8cdf27084773150b4f8daec7968bfb004f021b70 Mon Sep 17 00:00:00 2001 From: "paramjot@gmail.com" Date: Sun, 23 Jun 2019 17:58:32 -0400 Subject: [PATCH] Initial SuperH SH-1/SH-2 Processor Support --- Ghidra/Processors/SuperH/LICENSE | 21 + Ghidra/Processors/SuperH/Module.manifest | 1 + .../SuperH/data/languages/sh-1.slaspec | 4 + .../SuperH/data/languages/sh-2.slaspec | 3 + .../SuperH/data/languages/superh.cspec | 72 + .../SuperH/data/languages/superh.ldefs | 26 + .../SuperH/data/languages/superh.pspec | 5 + .../SuperH/data/languages/superh.sinc | 1410 +++++++++++++++++ 8 files changed, 1542 insertions(+) create mode 100644 Ghidra/Processors/SuperH/LICENSE create mode 100644 Ghidra/Processors/SuperH/Module.manifest create mode 100644 Ghidra/Processors/SuperH/data/languages/sh-1.slaspec create mode 100644 Ghidra/Processors/SuperH/data/languages/sh-2.slaspec create mode 100644 Ghidra/Processors/SuperH/data/languages/superh.cspec create mode 100644 Ghidra/Processors/SuperH/data/languages/superh.ldefs create mode 100644 Ghidra/Processors/SuperH/data/languages/superh.pspec create mode 100644 Ghidra/Processors/SuperH/data/languages/superh.sinc diff --git a/Ghidra/Processors/SuperH/LICENSE b/Ghidra/Processors/SuperH/LICENSE new file mode 100644 index 0000000000..c78c135cd6 --- /dev/null +++ b/Ghidra/Processors/SuperH/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2019 VGKintsugi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Ghidra/Processors/SuperH/Module.manifest b/Ghidra/Processors/SuperH/Module.manifest new file mode 100644 index 0000000000..8d1c8b69c3 --- /dev/null +++ b/Ghidra/Processors/SuperH/Module.manifest @@ -0,0 +1 @@ + diff --git a/Ghidra/Processors/SuperH/data/languages/sh-1.slaspec b/Ghidra/Processors/SuperH/data/languages/sh-1.slaspec new file mode 100644 index 0000000000..b8ca66cbaf --- /dev/null +++ b/Ghidra/Processors/SuperH/data/languages/sh-1.slaspec @@ -0,0 +1,4 @@ + +@define SH_VERSION "1" + +@include "superh.sinc" diff --git a/Ghidra/Processors/SuperH/data/languages/sh-2.slaspec b/Ghidra/Processors/SuperH/data/languages/sh-2.slaspec new file mode 100644 index 0000000000..aaa0eeaa3a --- /dev/null +++ b/Ghidra/Processors/SuperH/data/languages/sh-2.slaspec @@ -0,0 +1,3 @@ +@define SH_VERSION "2" + +@include "superh.sinc" diff --git a/Ghidra/Processors/SuperH/data/languages/superh.cspec b/Ghidra/Processors/SuperH/data/languages/superh.cspec new file mode 100644 index 0000000000..299439d4db --- /dev/null +++ b/Ghidra/Processors/SuperH/data/languages/superh.cspec @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Ghidra/Processors/SuperH/data/languages/superh.ldefs b/Ghidra/Processors/SuperH/data/languages/superh.ldefs new file mode 100644 index 0000000000..877b9461b9 --- /dev/null +++ b/Ghidra/Processors/SuperH/data/languages/superh.ldefs @@ -0,0 +1,26 @@ + + + + + SuperH SH-2 processor 32-bit big-endian + + + + SuperH SH-1 processor 32-bit big-endian + + + diff --git a/Ghidra/Processors/SuperH/data/languages/superh.pspec b/Ghidra/Processors/SuperH/data/languages/superh.pspec new file mode 100644 index 0000000000..114b5c47a8 --- /dev/null +++ b/Ghidra/Processors/SuperH/data/languages/superh.pspec @@ -0,0 +1,5 @@ + + + + + diff --git a/Ghidra/Processors/SuperH/data/languages/superh.sinc b/Ghidra/Processors/SuperH/data/languages/superh.sinc new file mode 100644 index 0000000000..e79aa81e3d --- /dev/null +++ b/Ghidra/Processors/SuperH/data/languages/superh.sinc @@ -0,0 +1,1410 @@ +# 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 ; + rm_04_07 = rm_04_07 + 1; + + +} + +: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 ; + rm_04_07 = rm_04_07 + 2; + + +} + +: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 ; + 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; +} + +: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 ; + if(old_q == 0 && $(M_FLAG) == 0 && $(Q_FLAG) == 1) goto ; + if(old_q == 0 && $(M_FLAG) == 1 && $(Q_FLAG) == 0) goto ; + if(old_q == 0 && $(M_FLAG) == 1 && $(Q_FLAG) == 1) goto ; + if(old_q == 1 && $(M_FLAG) == 0 && $(Q_FLAG) == 0) goto ; + if(old_q == 1 && $(M_FLAG) == 0 && $(Q_FLAG) == 1) goto ; + if(old_q == 1 && $(M_FLAG) == 1 && $(Q_FLAG) == 0) goto ; + if(old_q == 1 && $(M_FLAG) == 1 && $(Q_FLAG) == 1) goto ; + + + tmp0 = rn_08_11; + rn_08_11 = rn_08_11 - tmp2; + tmp1 = rn_08_11 > tmp0; + $(Q_FLAG) = tmp1; + goto ; + + + tmp0 = rn_08_11; + rn_08_11 = rn_08_11 - tmp2; + tmp1 = rn_08_11 > tmp0; + $(Q_FLAG) = tmp1 == 0; + goto ; + + + tmp0 = rn_08_11; + rn_08_11 = rn_08_11 + tmp2; + tmp1 = rn_08_11 < tmp0; + $(Q_FLAG) = tmp1 == 0; + goto ; + + + tmp0 = rn_08_11; + rn_08_11 = rn_08_11 + tmp2; + tmp1 = rn_08_11 < tmp0; + $(Q_FLAG) = tmp1; + goto ; + + + tmp0 = rn_08_11; + rn_08_11 = rn_08_11 + tmp2; + tmp1 = rn_08_11 < tmp0; + $(Q_FLAG) = tmp1; + goto ; + + + tmp0 = rn_08_11; + rn_08_11 = rn_08_11 + tmp2; + tmp1 = rn_08_11 < tmp0; + $(Q_FLAG) = tmp1; + goto ; + + + tmp0 = rn_08_11; + rn_08_11 = rn_08_11 - tmp2; + tmp1 = rn_08_11 > tmp0; + $(Q_FLAG) = tmp1 == 0; + goto ; + + + tmp0 = rn_08_11; + rn_08_11 = rn_08_11 - tmp2; + tmp1 = rn_08_11 > tmp0; + $(Q_FLAG) = tmp1; + goto ; + + + $(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 ; + + rn_08_11 = rn_08_11 | 0xFFFFFF00; + goto ; + + + rn_08_11 = rn_08_11 & 0x000000FF; + + +} + +: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 ; + + rn_08_11 = rn_08_11 | 0xFFFF0000; + goto ; + + + rn_08_11 = rn_08_11 & 0x0000FFFF; + + +} + +: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 ; + fnLmL = 0; + goto ; + + fnLmL = -1; + + if( tempn s>= 0) goto ; + tempn = 0 - tempn; + + + if( tempm s>= 0) goto ; + tempm = 0 - 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 ; + Res2 = Res2 + 0x00010000; + + + temp1 = (Res1 << 16) & 0xFFFF0000; + + Res0 = temp0 + temp1; + Res2 = Res2 + zext(Res0 < temp0); + + Res2 = Res2 + ((Res1 >> 16) & 0x0000FFFF) + temp3; + + if(fnLmL s>= 0) goto ; + Res2 = ~Res2; + + if(Res0 == 0) goto ; + Res0 = (~Res0) + 1; + goto ; + + + Res2 = Res2 + 1; + + + + if($(S_FLAG) != 1) goto ; + + Res0 = macl + Res0; + Res2 = Res2 + zext(macl > Res0); + + Res2 = Res2 + (mach & 0x0000FFFF); + + if((Res2 s>= 0) || Res2 >= 0xFFFF8000) goto ; + Res2 = 0xFFFF8000; + Res0 = 0x00000000; + + + if((Res2 s<= 0) || Res2 <= 0x00007FFF) goto ; + Res2 = 0x00007FFF; + Res0 = 0xFFFFFFFF; + + + mach = (Res2 & 0x0000FFFF) | (mach & 0xFFFF0000); + macl = Res0; + + goto ; + + + Res0 = macl + Res0; + Res2 = Res2 + zext(macl > Res0); + + Res2 = Res2 + mach; + mach = Res2; + macl = Res0; + + +} +@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 ; + src = 0; + tempn = 0; + goto ; + + + src = 1; + tempn = 0xFFFFFFFF; + + + src = src + zext(dest); + macl = macl + tempm; + + ans = (macl s< 0); + + ans = ans + dest; + + # if (S == 1) + if($(S_FLAG) != 1) goto ; + + if(ans != 1) goto ; + +@if SH_VERSION == "1" + if(src != 0 && src != 2) goto ; + mach = mach | 0x00000001; + +@endif + + if(src == 0) goto ; + if(src == 2) goto ; + goto ; + + + macl = 0x7FFFFFFF; + goto ; + + + macl = 0x80000000; + goto ; + + # if (S != 1) + + + mach = mach + tempn; + + if(templ s<= macl) goto ; + macl = macl + 1; + + +@if SH_VERSION == "1" + if((mach & 0x00000200) == 0) goto ; + mach = mach | 0xFFFFFC00; + goto ; + + mach = mach & 0x000003FF; +@endif + + +} + +@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 ; + + rn_08_11 = rn_08_11 | 0x1; + + + + $(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 ; + + rn_08_11 = rn_08_11 | 0x80000000; + + + + $(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 ; + + rn_08_11 = rn_08_11 & 0xFFFFFFFE; + goto ; + + + + rn_08_11 = rn_08_11 | 0x00000001; + + +} + +: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 ; + + rn_08_11 = rn_08_11 & 0x7FFFFFFF; + goto ; + + + + rn_08_11 = rn_08_11 | 0x80000000; + + +} + +: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 ; + + rn_08_11 = rn_08_11 & 0x7FFFFFFF; + goto ; + + + + rn_08_11 = rn_08_11 | 0x80000000; + + +} + +: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 ; + + # sign extend + mach = mach | 0xFFFFFC00; + goto ; + + + mach = mach & 0x000003FF; + + +@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 ; + + # sign extend + mach = mach | 0xFFFFFC00; + goto ; + + + mach = mach & 0x000003FF; + + +@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 ; + + # sign extend + rn_08_11 = rn_08_11 | 0xFFFFFC00; + goto ; + + + rn_08_11 = rn_08_11 & 0x000003FF; + + +@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 ; + + # sign extend + temp = temp | 0xFFFFFC00; + goto ; + + + temp = temp & 0x000003FF; + + +@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]; +}