Skip to content

Instantly share code, notes, and snippets.

@moonheart08
Last active February 8, 2020 03:59
Show Gist options
  • Save moonheart08/21e30d016522ab321ba6e7fd0fbac4a0 to your computer and use it in GitHub Desktop.
Save moonheart08/21e30d016522ab321ba6e7fd0fbac4a0 to your computer and use it in GitHub Desktop.
A SuperH-alike
#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