;; bootstrap routines for xcpu
_include xcpu_asm.h
;; special I/O device
_define IO_DEV_EXE 0x7
;; memory information
_define MEMORY_ADDR 0x110
_define MEMORY_AMOUNT 0x10000 - 0x110
_define STACK_ADDR 0x10000 - 0x1000
_define IOPORTS_ADDR 0x0104
;; now start the bootstrap code
;; turn the debug flag on
;cpuop CPU_DEBUG, 1
;; configure memory to default
assign A, MEMORY_ADDR
assign B, MEMORY_AMOUNT
config CONFIG_MEMORY
;; configure stack to default
assign A, STACK_ADDR
config CONFIG_STACK
;; configure io ports to default
assign A, IOPORTS_ADDR
config CONFIG_IOPORTS
;; load program to run into memory
;; select device
assign A, IOPORT_DEVICE
push A
assign A, IO_DEV_EXE
cpuop CPU_MEMOP, 0
memop A
;; select offset of program start offset
assign A, IOPORT_ADDR
push A
assign A, 0x4
memop A
;; read program start offset
assign A, IOPORT_RW
push A
cpuop CPU_MEMOP, 1
memop A
;; A now contains program start offset
;; select program size offset
assign B, IOPORT_ADDR
push B
assign B, 0x8
cpuop CPU_MEMOP, 0
memop B
;; read program size
assign B, IOPORT_RW
push B
cpuop CPU_MEMOP, 1
memop B
;; B now contains program size
;; add program start to program size
add B
;; select program load address offset
assign D, IOPORT_ADDR
push D
assign D, 0xc
cpuop CPU_MEMOP, 0
memop D
;; program load address
assign D, IOPORT_RW
push D
cpuop CPU_MEMOP, 1
memop D
;; now A has program start, B has program end, D has memory start
;; save load address on stack to call later
push D
;; keep program end on the stack
push B
;; keep start address in C
cpuop CPU_MOVE, 0
move A
cpuop CPU_MOVE, 1
move C
;; load program into memory
_label _loader_loop
;; point IO to current program offset (C)
assign A, IOPORT_ADDR
push A
cpuop CPU_MEMOP, 0
memop C
;; read word into B
assign A, IOPORT_RW
push A
cpuop CPU_MEMOP, 1
memop B
;; write word to current memory offset (D)
push D
cpuop CPU_MEMOP, 0
memop B
;; increment C and D to point at next word
assign A, 4
add C
add D
;; compare C with program end
pop A
push A
compare C
;; continue loop if C < end
assign A, _loader_loop
push A
jump JUMP_LT
;; reached end - clean up and hand off control
;; clear the stack
pop A
;; set up halt routine
assign A, halt_cpu
;; save the load address first
pop B
push A
push B
;; zero out flags (except debug)
cpuop CPU_JUMP1, 0
cpuop CPU_JUMP2, 0
cpuop CPU_SLR, 0
cpuop CPU_SRC, 0
cpuop CPU_MOVE, 0
;; zero out registers
assign A, 0
assign B, 0
assign C, 0
assign D, 0
;; start of memory is already on stack
;cpuop CPU_DEBUG, 1
jump JUMP_UNCOND
;; CPU termination routine
_label halt_cpu
halt