Skip to content

Instantly share code, notes, and snippets.

@moonheart08
Last active February 12, 2020 19:44
Show Gist options
  • Save moonheart08/1f852ab8a5f3e9853e940fe073e6883c to your computer and use it in GitHub Desktop.
Save moonheart08/1f852ab8a5f3e9853e940fe073e6883c to your computer and use it in GitHub Desktop.
#bankdef "bootrom" {
#addr 0x0
#size 0x1000
#outp 0x0
}
#bankdef "ram" {
#addr 0x1000
#size 0x8000
}
#cpudef
{
#bits 8
#tokendef Locals {
A = 0,
B = 1,
C = 2,
D = 3,
E = 4,
F = 5,
SP = 6, ; Stack pointer
RSP = 7, ; Return stack pointer
}
pushloc {l: Locals} -> 0x0 @ l[3:0]
poploc {l: Locals} -> 0x0 @ (8 + l)[3:0]
dup -> 0x10 ; A -> A, A
drop -> 0x11 ; A -> ()
swap -> 0x12 ; A, B -> B, A
pick -> 0x13 ; A -> SP[A];
pick.i {i} -> {
0b10 @ i[5:0] @ 0x13
}
pull -> 0x14 ; A -> SP[A]; pop SP[A]
pull.i {i} -> {
0x5 @ i[3:0] @ 0x27
}
insert -> 0x15 ; A, B -> SP[A] = B
load -> 0x16 ; A -> A[0]
store -> 0x17 ; A, B -> A[0] = B
; literally just add/sub related instrs
add -> 0x18 ; A, B -> A + B
sub -> 0x19 ; A, B -> A - B
addc -> 0x1A ; A, B, (Carry Flag) -> A addc B
subb -> 0x1B ; A, B, (Carry Flag) -> A addc B
pushc -> 0x1C ; () -> (Carry Flag)
pusho -> 0x1D ; () -> (Overflow Flag)
popc -> 0x1E ; A -> (Carry Flag) = A
popo -> 0x1F ; A -> (Overflow Flag) = A
; bitwise
and -> 0x20 ; A, B -> A & B
or -> 0x21 ; A, B -> A | B
xor -> 0x22 ; A, B -> A ^ B
not -> 0x23 ; A -> !A
shl -> 0x24 ; A, B -> A >> B
shr -> 0x25 ; A, B -> A << B
shra -> 0x26 ; A, B -> A <<< B
; ERRATA BEHAVIOR:
; If prefixed with offs {n} for any offset
; besides zero, it will function similarly to
; the pull instruction, with a constant source
nop -> 0x27 ; A -> A
; extended arithmetic
inc -> 0x28 ; A -> A + 1
dec -> 0x29 ; A -> A - 1
inc2 -> 0x2A ; A -> A + 2
dec2 -> 0x2B ; A -> A - 2
; IO operations
loadio -> 0x2C ; A -> IO[A]
storeio -> 0x2D ; A, B -> IO[A] = B
; Control register
loadcr -> 0x2E ; () -> CR
storecr -> 0x2F ; A -> CR = A
; Jumps/call/ret
call -> 0x30 ; A -> pushrsp PC; jump A
ret -> 0x31 ; () -> A = poprsp; jump A
pushrsp -> 0x32 ; () -> pushrsp
poprsp -> 0x33 ; A -> poprsp A
jump -> 0x34 ; A -> jump A
; Why this set of jumps and not some other jump design?
; coz.
jc -> 0x35 ; A -> if (Carry Flag) then jump A
jo -> 0x36 ; A -> if (Overflow Flag) then jump A
jz -> 0x37 ; A -> if (Zero Flag) then jump A
jnc -> 0x38 ; A -> if not (Carry Flag) then jump A
jno -> 0x39 ; A -> if not (Overflow Flag) then jump A
jnz -> 0x3A ; A -> if not (Zero Flag) then jump A
jmpr {addr} -> {
reladdr = addr - pc
assert(reladdr <= 0x7f)
assert(reladdr >= !0x7f)
0x3B @ reladdr[7:0]
}
jcr {addr} -> {
reladdr = addr - pc
assert(reladdr <= 0x7f)
assert(reladdr >= !0x7f)
0x3C @ reladdr[7:0]
}
jor {addr} -> {
reladdr = addr - pc
assert(reladdr <= 0x7f)
assert(reladdr >= !0x7f)
0x3D @ reladdr[7:0]
}
jzr {addr} -> {
reladdr = addr - pc
assert(reladdr <= 0x7f)
assert(reladdr >= !0x7f)
0x3E @ reladdr[7:0]
}
jncr {addr} -> {
reladdr = addr - pc
assert(reladdr <= 0x7f)
assert(reladdr >= !0x7f)
0x40 @ reladdr[7:0]
}
jnor {addr} -> {
reladdr = addr - pc
assert(reladdr <= 0x7f)
assert(reladdr >= !0x7f)
0x41 @ reladdr[7:0]
}
jnzr {addr} -> {
reladdr = addr - pc
assert(reladdr <= 0x7f)
assert(reladdr >= !0x7f)
0x42 @ reladdr[7:0]
}
nc -> 0x48 ; This is a prefix. if applied, the next
; instruction does not consume it's arguments.
; Magic!
rel -> 0x49 ; Makes a value on the stack relative to PC
; A -> PC + (signed byte)A
snip -> 0x4A ; A, B -> B; shorthand for offs 1 drop
offs {n} -> 0x5 @ n[3:0]
; Offset the next instruction's interaction
; with the stack by n
imm.6 {i} -> {
0b10 @ i[5:0]
}
imm.13 {i} -> {
0b110 @ i[12:0]
}
imm.16 {i} -> {
0b11100000 @ i[15:0]
}
}
#bank "bootrom"
boot:
imm.13 retstack
poploc rsp
imm.13 stack
poploc sp
imm.13 reset_alloc
call
jmpr pc
reset_alloc:
imm.13 200 ;X
imm.13 alloc_usage_buf ;X Y
imm.6 0
imm.13 memset
jump ; tail call optimization
; call
; ret
memset:
; X Y FILL
poploc a
.lp:
inc
dup ; X Y Y
pushloc a ; X Y Y A
store ; X Y
offs 1
dec
jnzr .lp
drop ; X
drop ; ()
ret
; May want a microcoded memcpy
; OR, could spend time optimizing this
; but juggling stack is hard
memcpy:
; L = length
; X = source
; Y = dest
; L X Y
.lp:
nc
load ; L X Y [Y]
pick.i 2 ; L X Y [Y] X
store ; L X Y | [X] = [Y]
offs 2
dec ; X Y L-1
jzr .escape
offs 2
inc ; Y L-1 X+1
offs 2
inc ; L-1 X+1 Y+1
jmpr .lp
.escape:
ret
#bank "ram"
retstack:
; 32 entries
#res 0x0040
stack:
; 1024 entries
#res 0x0800
alloc_data:
alloc_usage_buf:
#res 200 ; 1600 bits, to mark 32-byte segments as in use.
memory:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment