Last active
February 8, 2020 03:59
-
-
Save moonheart08/21e30d016522ab321ba6e7fd0fbac4a0 to your computer and use it in GitHub Desktop.
A SuperH-alike
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#bankdef "bootrom" { | |
#addr 0x0 | |
#size 0x4000 | |
#outp 0x0 | |
} | |
#bankdef "invalidaccess_0" { | |
#addr 0x4000 | |
#size 0xBFFF ; I bet you I messed up at least once here | |
; and made some banks overlap, or put gaps | |
; between banks | |
} | |
#bankdef "cacheram" { | |
#addr 0x00010000 | |
#size 0xFFFF | |
} | |
#bankdef "scratchram" { | |
#addr 0x00020000 | |
#size 2048 | |
} | |
; 2GiB max. | |
#bankdef "mainram" { | |
#addr 0x10000000 | |
#size 0x7FFFFFFF | |
} | |
#bankdef "scuspace" { | |
#addr 0xF0000000 | |
#size 0x0FFFFFFF | |
} | |
#bankdef "cpuconfigspace" { | |
#addr 0xF000F000 | |
#size 0x00000FFF | |
} | |
arith_count = 13 | |
arith_space_len = arith_count * 7 | |
arith_space_end = arith_space_len - 1 | |
comp_count = 7 | |
comp_space_begin = arith_space_end + 1 | |
comp_space_len = comp_count * 5 | |
comp_space_end = comp_space_begin + comp_space_len | |
muldiv_count = 4 | |
muldiv_space_begin = comp_space_end - 1 | |
muldiv_space_len = muldiv_count * 5 | |
muldiv_space_end = muldiv_space_len + muldiv_space_begin - 1 | |
mov_len_count = 3 | |
mov_space_begin = muldiv_space_end + 1 | |
mov_space_len = mov_len_count * 18 | |
mov_space_end = mov_space_len + mov_space_begin - 1 | |
#cpudef "mx08" | |
{ | |
#bits 8 | |
#tokendef gpr { | |
R0 = 0, | |
R1 = 1, | |
R2 = 2, | |
R3 = 3, | |
R4 = 4, | |
R5 = 5, | |
R6 = 6, | |
R7 = 7, | |
R8 = 8, | |
R9 = 9, | |
R10 = 10, | |
R11 = 11, | |
R12 = 12, | |
R13 = 13, | |
R14 = 14, | |
R15 = 15, | |
} | |
#tokendef user_sr { | |
SR = 0, ; Status Register | |
PRA = 1, ; Procedure Return Address | |
GBR = 2, ; General Base Register | |
PC = 3, ; Program Counter | |
UCR = 4, ; User Control Register | |
MULH = 5, ; Upper 16 bits of multiply result CRA-M/CRA-X only | |
DIVR = 6, ; Division Remainder CRA-M/CRA-X only | |
} | |
#tokendef priv_sr { | |
VBR = 0, ; Vector Base Register | |
PCR = 1, ; Privileged Control Register | |
UNDOC_CCR = 2, ; Cache Control Register CRA-M/X ONLY | |
SPC = 3, ; Saved Program Counter CRA-M/X ONLY | |
SSR = 4, ; Saved Status Register CRA-M/X ONLY | |
SRA = 5, ; Saved Return Address CRA-M/X ONLY | |
SGR = 6, ; Saved General Register (R15) CRA-M/X ONLY | |
PR0 = 7, ; Privileged Register 0 (arbitrary data) | |
PR1 = 8, ; Privileged Register 1 | |
EXT = 14, ; EXTernal IO Lines | |
CIF = 15, ; CPU IdentiFication | |
} | |
#tokendef arith { | |
add = 0, | |
addc = 1, | |
addv = 2, | |
sub = 3, | |
subc = 4, | |
subv = 5, | |
and = 6, | |
or = 7, | |
xor = 8, | |
not = 9, | |
neg = 10, | |
negc = 11, | |
tst = 12, | |
} | |
#tokendef muldiv { | |
mul = 0, | |
mulu = 1, | |
div = 2, | |
divu = 3, | |
} | |
#tokendef cmp_checks { | |
eq = 0, | |
uge = 1, | |
sge = 2, | |
ugt = 3, | |
sgt = 4, | |
gez = 5, | |
gtz = 6, | |
} | |
#tokendef oper_sizes { | |
b = 0, | |
w = 1, | |
l = 2, | |
} | |
#tokendef jmpbra { | |
jmp = 0 | |
brt = 1, | |
brf = 2, | |
rts = 3, | |
jts = 4, | |
} | |
; SHORTCUTS | |
db {val} -> { | |
assert(val <= 0x7f) | |
assert(val >= !0x7f) | |
val[7:0] | |
} | |
db {val} -> { | |
assert(reladdr <= 0xff) | |
assert(reladdr >= 0x00) | |
val[7:0] | |
} | |
dw {val} -> { | |
;#align 2 | |
assert(val <= 0x7fff) | |
assert(val >= !0x7fff) | |
val[15:0] | |
} | |
dw {val} -> { | |
;#align 2 | |
assert(val <= 0xffff) | |
assert(val >= 0x0000) | |
val[15:0] | |
} | |
dl {val} -> { | |
;#align 4 | |
assert(val <= 0x7fffffff) | |
assert(val >= !0x7fffffff) | |
val[31:0] | |
} | |
dl {val} -> { | |
;#align 4 | |
assert(val <= 0xffffffff) | |
assert(val >= 0x00000000) | |
val[31:0] | |
} | |
; ARITHMETIC | |
nop -> { | |
0x0700 | |
} | |
{op: arith} {a: gpr}, {b: gpr} -> ((arith_count * 0) + op)[7:0] @ a[3:0] @ b[3:0] | |
{op: arith} @{a: gpr}, {b: gpr} -> ((arith_count * 1) + op)[7:0] @ a[3:0] @ b[3:0] | |
{op: arith} @({a: gpr}, GBR), {b: gpr} -> ((arith_count * 2) + op)[7:0] @ a[3:0] @ b[3:0] | |
{op: arith} @({a: gpr}, PC), {b: gpr} -> ((0xD * 3) + op)[7:0] @ a[3:0] @ b[3:0] | |
{op: arith}.b #{imm}, r0 -> ((0xD * 4) + op)[7:0] @ imm[7:0] | |
{op: arith} @(#{disp}, PC), r0 -> ((0xD * 5) + op)[7:0] @ imm[7:0] | |
{op: arith} @({a: gpr}, R0), {b: gpr} -> ((arith_count * 6) + op)[7:0] @ a[3:0] @ b[3:0] | |
{op: arith} @(r#{disp}, PC), r0 -> { | |
reladdr = disp - pc - 2 | |
assert(reladdr <= 0x7f) | |
assert(reladdr >= !0x7f) | |
assert(disp % 4 == 0) | |
fdisp = reladdr / 4 | |
((0xD * 5) + op)[7:0] @ fdisp[7:0] | |
} | |
; SHIFTS, ROTATES, EXTRACTS | |
shl {a: gpr}, #{imm} -> { | |
assert(imm > 0) | |
assert(imm < 17) | |
timm = imm-1 ;shift by 0 not valid | |
0x5 @ 0xb @ a[3:0] @ timm[3:0] | |
} | |
shr {a: gpr}, #{imm} -> { | |
assert(imm > 0) | |
assert(imm < 17) | |
timm = imm-1 ;shift by 0 not valid | |
0x5 @ 0xc @ a[3:0] @ timm[3:0] | |
} | |
shra {a: gpr}, #{imm} -> { | |
assert(imm > 0) | |
assert(imm < 17) | |
timm = imm-1 ;shift by 0 not valid | |
0x5 @ 0xd @ a[3:0] @ timm[3:0] | |
} | |
rotl {a: gpr}, #{imm} -> { | |
assert(imm > 0) | |
assert(imm < 17) | |
timm = imm-1 ;shift by 0 not valid | |
0x5 @ 0xe @ a[3:0] @ timm[3:0] | |
} | |
rotr {a: gpr}, #{imm} -> { | |
assert(imm > 0) | |
assert(imm < 17) | |
timm = imm-1 ;shift by 0 not valid | |
0x5 @ 0xf @ a[3:0] @ timm[3:0] | |
} | |
; Technically arithmetic instructions, it's the immediate not | |
ld.b #{imm}, R0 -> ((arith_count * 4) + 9)[7:0] @ !imm[7:0] | |
ld.b r#{imm}, R0 -> { | |
reladdr = imm - pc - 2 | |
assert(reladdr <= 0x7f) | |
assert(reladdr >= !0x7f) | |
((arith_count * 4) + 9)[7:0] @ !reladdr[7:0] | |
} | |
ext.n {a: gpr}, #{offs}, R0 -> 0x6 @ 0x0 @ a[3:0] @ 0b0 @ offs[2:0] | |
ext.b {a: gpr}, #{offs}, R0 -> 0x6 @ 0x0 @ a[3:0] @ 0b10 @ offs[1:0] | |
ext.w {a: gpr}, #{offs}, R0 -> 0x6 @ 0x0 @ a[3:0] @ 0b110 @ offs[0:0] | |
ext.l {a: gpr}, #{offs}, R0 -> 0x6 @ 0x0 @ a[3:0] @ 0b1110 | |
ext.invalid {a: gpr}, #{offs}, R0 -> 0x6 @ 0x0 @ a[3:0] @ 0b1111 | |
; COMPARES | |
cmp.{c: cmp_checks} {a: gpr}, {b: gpr} -> ((comp_count * 0) + c + comp_space_begin)[7:0] @ a[3:0] @ b[3:0] | |
cmp.{c: cmp_checks} @{a: gpr}, {b: gpr} -> ((comp_count * 1) + c + comp_space_begin)[7:0] @ a[3:0] @ b[3:0] | |
cmp.{c: cmp_checks} @({a: gpr}, R0), {b: gpr} -> ((comp_count * 2) + c + comp_space_begin)[7:0] @ a[3:0] @ b[3:0] | |
cmp.{c: cmp_checks} @(#{imm}, PC), {b: gpr} -> ((comp_count * 3) + c + comp_space_begin)[7:0] @ imm[7:0] | |
cmp.{c: cmp_checks} #{imm}, R0 -> ((comp_count * 4) + c + comp_space_begin)[7:0] @ imm[7:0] | |
dt {a: gpr}, #{imm} -> { | |
assert(imm >= 0x0) | |
assert(imm <= 0xF) | |
((comp_count * 5) + comp_space_begin)[7:0] @ a[3:0] @ imm[3:0] | |
} | |
; MULTIPLY DIVIDE | |
{op: muldiv} {a: gpr}, {b: gpr} -> ((muldiv_count * 0) + muldiv_space_begin + op)[7:0] @ a[3:0] @ b[3:0] | |
{op: muldiv} @{a: gpr}, {b: gpr} -> ((muldiv_count * 1) + muldiv_space_begin + op)[7:0] @ a[3:0] @ b[3:0] | |
{op: muldiv} @({a: gpr}, R0), {b: gpr} -> ((muldiv_count * 2) + muldiv_space_begin + op)[7:0] @ a[3:0] @ b[3:0] | |
{op: muldiv} @(#{imm}, PC), {b: gpr} -> ((muldiv_count * 3) + muldiv_space_begin + op)[7:0] @ imm[7:0] | |
{op: muldiv} #{imm}, R0 -> ((muldiv_count * 4) + muldiv_space_begin + op)[7:0] @ imm[7:0] | |
; LOADS/STORES | |
;good lord ld/st space is huge | |
ld.{s: oper_sizes} @{a: gpr}, {b: gpr} -> ((mov_len_count * 0) + mov_space_begin + s)[7:0] @ a[3:0] @ b[3:0] | |
ld.{s: oper_sizes} @{a: gpr}+, {b: gpr} -> ((mov_len_count * 1) + mov_space_begin + s)[7:0] @ a[3:0] @ b[3:0] | |
ld.{s: oper_sizes} @-{a: gpr}, {b: gpr} -> ((mov_len_count * 2) + mov_space_begin + s)[7:0] @ a[3:0] @ b[3:0] | |
ld.{s: oper_sizes} @({a: gpr}, GBR), {b: gpr} -> ((mov_len_count * 3) + mov_space_begin + s)[7:0] @ a[3:0] @ b[3:0] | |
ld.{s: oper_sizes} @({a: gpr}, PC), {b: gpr} -> ((mov_len_count * 4) + mov_space_begin + s)[7:0] @ a[3:0] @ b[3:0] | |
ld.{s: oper_sizes} @({a: gpr}, R0), {b: gpr} -> ((mov_len_count * 5) + mov_space_begin + s)[7:0] @ a[3:0] @ b[3:0] | |
ld.{s: oper_sizes} @({a: gpr}, {b: gpr}), R0 -> ((mov_len_count * 6) + mov_space_begin + s)[7:0] @ a[3:0] @ b[3:0] | |
ld.{s: oper_sizes} @(#{disp}, GBR), R0 -> ((mov_len_count * 7) + mov_space_begin + s)[7:0] @ disp[7:0] | |
ld.{s: oper_sizes} @(#{disp}, PC), R0 -> ((mov_len_count * 8) + mov_space_begin + s)[7:0] @ disp[7:0] | |
st.{s: oper_sizes} {a: gpr}, @{b: gpr} -> ((mov_len_count * 9) + mov_space_begin + s)[7:0] @ a[3:0] @ b[3:0] | |
st.{s: oper_sizes} {a: gpr}, @{b: gpr}+ -> ((mov_len_count * 10) + mov_space_begin + s)[7:0] @ a[3:0] @ b[3:0] | |
st.{s: oper_sizes} {a: gpr}, @-{b: gpr} -> ((mov_len_count * 11) + mov_space_begin + s)[7:0] @ a[3:0] @ b[3:0] | |
st.{s: oper_sizes} {a: gpr}, @({b: gpr}, GBR) -> ((mov_len_count * 12) + mov_space_begin + s)[7:0] @ a[3:0] @ b[3:0] | |
st.{s: oper_sizes} {a: gpr}, @({b: gpr}, PC) -> ((mov_len_count * 13) + mov_space_begin + s)[7:0] @ a[3:0] @ b[3:0] | |
st.{s: oper_sizes} {a: gpr}, @({b: gpr}, R0) -> ((mov_len_count * 14) + mov_space_begin + s)[7:0] @ a[3:0] @ b[3:0] | |
st.{s: oper_sizes} R0, @({a: gpr}, {b: gpr}) -> ((mov_len_count * 15) + mov_space_begin + s)[7:0] @ a[3:0] @ b[3:0] | |
st.{s: oper_sizes} R0, @(#{disp}, GBR) -> ((mov_len_count * 16) + mov_space_begin + s)[7:0] @ disp[7:0] | |
st.{s: oper_sizes} R0, @(#{disp}, PC) -> ((mov_len_count * 17) + mov_space_begin + s)[7:0] @ disp[7:0] | |
; JUMPS | |
jmp #{label} -> { | |
reladdr = label - pc - 2 | |
assert(reladdr <= 0x7f) | |
assert(reladdr >= !0x7f) | |
assert(reladdr != 0x00) | |
0xE @ 0x0 @ reladdr[7:0] | |
} | |
brf #{label} -> { | |
reladdr = label - pc - 2 | |
assert(reladdr <= 0x7f) | |
assert(reladdr >= !0x7f) | |
0xE @ 0x1 @ reladdr[7:0] | |
} | |
brt #{label} -> { | |
reladdr = label - pc - 2 | |
assert(reladdr <= 0x7f) | |
assert(reladdr >= !0x7f) | |
0xE @ 0x2 @ reladdr[7:0] | |
} | |
jmp @{addr: gpr} -> { | |
0xE @ 0x1 @ 0x0 @ addr[3:0] | |
} | |
jmp @(PC + {addr: gpr}) -> { | |
0xE @ 0x1 @ 0x1 @ addr[3:0] | |
} | |
brf @{addr: gpr} -> { | |
0xE @ 0x1 @ 0x2 @ addr[3:0] | |
} | |
brf @(PC + {addr: gpr}) -> { | |
0xE @ 0x1 @ 0x3 @ addr[3:0] | |
} | |
brt @{addr: gpr} -> { | |
0xE @ 0x1 @ 0x5 @ addr[3:0] | |
} | |
brt @(PC + {addr: gpr}) -> { | |
0xE @ 0x1 @ 0x6 @ addr[3:0] | |
} | |
; jump to subroutine | |
jtr @{addr: gpr} -> { | |
0xE @ 0x3 @ 0x0 @ addr[3:0] | |
} | |
; return to subroutine | |
rts -> { | |
0xE @ 0x3 @ 0x1 @ 0x0 | |
} | |
trap #{imm} -> { | |
0xE @ 0x4 @ 0b00 @ imm[5:0] | |
} | |
; return from interrupt | |
; swaps EBR and GBR | |
rfi -> { | |
0xE @ 0x5 @ 0x0 @ 0x0 | |
} | |
; clear interrupt state | |
cis -> { | |
0xE @ 0x5 @ 0x0 @ 0x1 | |
} | |
; jump to userspace. Privileged instruction. | |
; Sets RB to 0 | |
jtu @{addr: gpr} -> { | |
0xE @ 0x5 @ 0x1 @ addr[3:0] | |
} | |
; SPECIAL | |
ldu {u: user_sr}, {a: gpr} -> 0xF @ 0x0 @ u[3:0] @ a[3:0] | |
stu {a: gpr}, {u: user_sr} -> 0xF @ 0x1 @ a[3:0] @ u[3:0] | |
ldp {p: priv_sr}, {a: gpr} -> 0xF @ 0x2 @ p[3:0] @ a[3:0] | |
stp {a: gpr}, {p: priv_sr} -> 0xF @ 0x3 @ a[3:0] @ p[3:0] | |
; the 4 binary operations, all for T | |
rsett -> { | |
0xF @ 0x4 @ 0x0 @ 0x0 | |
} | |
sett -> { | |
0xF @ 0x4 @ 0x1 @ 0x0 | |
} | |
invt -> { | |
0xF @ 0x4 @ 0x2 @ 0x0 | |
} | |
ei -> { | |
0xF @ 0x5 @ 0x0 @ 0x0 | |
} | |
di -> { | |
0xF @ 0x5 @ 0x0 @ 0x1 | |
} | |
reset -> { | |
0xF @ 0x5 @ 0x1 @ 0x0 | |
} | |
;readback, bypass cache. 32-bit only | |
ldnc @{a: gpr}, {b:gpr} -> { | |
0xF @ 0x6 @ a[3:0] @ b[3:0] | |
} | |
;writethrough, bypass cache. 32-bit only | |
stnc {a: gpr}, @{b:gpr} -> { | |
0xF @ 0x7 @ a[3:0] @ b[3:0] | |
} | |
xchg {a: gpr}, {b: gpr} -> { | |
0xF @ 0x8 @ a[3:0] @ b[3:0] | |
} | |
halt -> 0xFFFF | |
} | |
; SR layout | |
; 1000_0000_0000_IIII_ < PRIV | USER > _0000_0000_000R_00ST | |
; T | Test bit | |
; S | Saved Test bit | |
; R | Division Remainder not Zero | |
; I | Interrupt Mask | |
#bank "bootrom" | |
rom_vbr: | |
dl scratch ;V00 POR_RESET GBR | |
dl power_on_reset ;V00 POR_RESET | |
dl manual_reset ;V01 MANU_RESET | |
dl unhandled ;V02 ILLINSTR | |
dl unhandled ;V03 ILLSLOT | |
dl unhandled ;V04 UNALIGNED | |
dl unhandled ;V05 MMUACCESS | |
dl unhandled ;V06 DMAACCESS | |
dl unhandled ;V07 NMI | |
dl unhandled ;V08 EXTINT | |
dl unhandled ;V09 CTL1CHG | |
dl unhandled ;V0A CTL2CHG | |
dl unhandled ;V0B INVALPC | |
dl unhandled ;V0C RESERVED | |
dl unhandled ;V0D RESERVED | |
dl unhandled ;V0E RESERVED | |
dl unhandled ;V0F RESERVED | |
dl unhandled ;V10 UTRAP0 | |
dl unhandled ;V11 UTRAP1 | |
dl unhandled ;V12 UTRAP2 | |
dl unhandled ;V13 UTRAP3 | |
dl unhandled ;V14 UTRAP4 | |
dl unhandled ;V15 UTRAP5 | |
dl unhandled ;V16 UTRAP6 | |
dl unhandled ;V17 UTRAP7 | |
dl unhandled ;V18 UTRAP8 | |
dl unhandled ;V19 UTRAP9 | |
dl unhandled ;V1A UTRAP10 | |
dl unhandled ;V1B UTRAP11 | |
dl unhandled ;V1C UTRAP12 | |
dl unhandled ;V1D UTRAP13 | |
dl unhandled ;V1E UTRAP14 | |
dl unhandled ;V1F UTRAP15 | |
#addr 0x200 ; 127 interrupt vectors | |
unhandled: | |
manual_reset: | |
power_on_reset: | |
; Registers that are initialized on boot: | |
; PC | Initialized from 0x0004 in the bootrom, POW_RESET vector. | |
; GBR | Initialized from 0x0000 in the bootrom, POW_RESET GBR. | |
; VBR | Initialized as 0x0000_0000. | |
; SR | Initialized as 0x000F_0000. | |
; UCR | Initialized as 0x????_????. | |
; PCR | Initialized as 0x????_????. | |
; CCR | Initialized as 0x????_????. | |
; EXT | Initialized as 0x0000_0000. | |
; CIF | Initialization depends on CPU model. | |
; All other registers have undefined value, which should NOT be depended on. | |
; system memory is completely uninitalized by default. Cache is cleared | |
; (all entries marked invalid) when it is reconfigured. | |
ld.b #1, r0 | |
add r1, r2 | |
add r2, r3 | |
add r4, r5 | |
halt | |
#d16 arith_space_end | |
#bank "scratchram" | |
ram_vbr: | |
#res 0x200 | |
scratch: | |
word_bank: #res 4 | |
#bank "cpuconfigspace" | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment