Skip to content
Permalink
Branch: master
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
281 lines (238 sloc) 11.2 KB
; Startup, check if we're in game
jmpS $GAME ; Execute game code only if we're running
jmpO +0 ; Infinite loop if we've recieved game over, reset to break it
; Clear memory contents
ALU = 0 ; Load 0
ALU1 -> buss, buss -> OP, buss -> M1, buss -> M2, buss -> PC
:CLRMEM PC -> mem_addr ; Look at PC
OP -> mem, M1 -> mem, M2 -> mem ; Clear it
ALU++ ; Incr
ALU1 -> PC, jmpZ $LOADP ; If 0 we're done looping
jmp $CLRMEM ; Else continue
:LOADP shall_load, jmp $POLL ; If we should start polling (start is pressed)
jmp -1
; Load in program to memory
:POLL IN -> buss ; Temporary start polling fbart
; Load program 1
ALU = 0, fifo_next ; PC1 = 0
ALU1 -> buss, buss -> FIFO, buss -> PC ; Insert it to FIFO
jmpIN $F1NUM ; Fetch number of rows from in
jmp -1 ; If not ready, stall
:F1NUM IN -> ALU1 ; Store number of rows in ALU1
:F1ROW jmpIN $F1OP ; Fetch OP
jmp -1
:F1OP IN -> OP ; Store OP
jmpIN $F1M1 ; Fetch M1
jmp -1
:F1M1 IN -> M1 ; Store M1
jmpIN $F1M2 ; Fetch M2
jmp -1
:F1M2 IN -> M2, PC -> mem_addr ; Store M2
OP -> mem, M1 -> mem, M2 -> mem ; Write line to mem
ALU--, PC++ ; Decr row counter, incr PC
jmpZ $LOAD2 ; If 0 we're done
jmp $F1ROW ; Else load next row
; Load program 2
:LOAD2 change_player ; Change player in FIFO
jmpIN $F2PC ; Fetch PC for player 2
jmp -1
:F2PC IN -> buss, buss -> FIFO, buss -> PC ; Insert to FIFO
jmpIN $F2NUM ; Fetch number of rows
jmp -1
:F2NUM IN -> ALU1 ; Store numbers of rows in ALU1
:F2ROW jmpIN $F2OP ; Fetch OP
jmp -1
:F2OP IN -> OP ; Store OP
jmpIN $F2M1 ; Fetch M1
jmp -1
:F2M1 IN -> M1 ; Store M1
jmpIN $F2M2 ; Fetch M2
jmp -1
:F2M2 IN -> M2, PC -> mem_addr ; Store M2
OP -> mem, M1 -> mem, M2 -> mem ; Write line to mem
ALU--, PC++ ; Decr row counter, incr PC
jmpZ $LEND ; If 0 we're done
jmp $F2ROW ; Else load next row
:LEND game_started, jmpZ 0
; Game sequence
:GAME change_player ; Change players turn
fifo_next
FIFO -> PC ; Fetch next PC
PC -> mem_addr
mem -> OP, mem -> M1, mem -> M2 ; Fetch data
OP -> IR, jmp $AMOD ; Go to adress decoding
; Calculate adress mode for A operand
:AMOD jmpAimm $BMOD ; If immediate we're done
M1 -> ALU1 ; Address is a relative offset
ALU1 += PC ; so add PC
ALU1 -> M1
jmpAdir $BMOD ; If direct, we're done
M1 -> mem_addr
mem -> M2 ; Check B address
M2 -> M1, jmpApre $APRE ; Move it to A's place. If pre-decr decr and come back
:AOFF M1 -> ALU1 ; Relative offset, add mem_addr
ALU1 += mem_addr
ALU1 -> M1
jmp $BMOD ; Do the same for the B operand
:APRE M1 -> ALU1 ; Decr
ALU--
ALU1 -> M1, ALU1 -> M2
M2 -> mem ; Write it back where it came from
jmp $AOFF ; Continue
; Calculate adress mode for B operand
:BMOD PC -> mem_addr ; Retrieve data
mem -> M2
jmpBimm $INSTR ; If immediate we're done
M2 -> ALU1 ; Relative address, add PC
ALU1 += PC
ALU1 -> M2
jmpBdir $INSTR ; If direct, we're done
M2 -> mem_addr
mem -> M2 ; Check B operand of the address
jmpBpre $BPRE
:BOFF M2 -> ALU1 ; Relative offset, add mem_addr
ALU1 += mem_addr
ALU1 -> M2
jmp $INSTR ; We're done
:BPRE M2 -> ALU1 ; Decr
ALU--
ALU1 -> M2
M2 -> mem ; Write it back where it came from
jmp $BOFF ; Continue
; Load up instruction and proceed to instruction decoding
; A operand is now in ADR1 and B in ADR2
; If immediate ignore these, they're also in M1 and M2
:INSTR M1 -> ADR1, M2 -> ADR2, op_addr -> uPC
; Execute instruction
;
; ADR1 is now the absolute address for the A operand
; ADR2 is for the B operand
; M1 and M2 holds copies of ADR1 and ADR2 always
;
; If immediate, the data is instead in M1 or M2
; DAT Executing data will eat up the PC
:DAT jmp $END
; MOV Move A to B
:MOV jmpAimm $IMOV ; Handle A immediate special case
ADR1 -> mem_addr ; Peek at memory from A absolute addr
mem -> OP, mem -> M1, mem -> M2
ADR2 -> mem_addr ; Copy it to B absolute addr
OP -> mem, M1 -> mem, M2 -> mem
jmp $ADDPC ; Keep using our PC
; If A immediate, move A to B op specified by B mem address
:IMOV ADR2 -> mem_addr, M1 -> M2 ; Examine B's absolute address
M2 -> mem ; Move A op there
jmp $ADDPC ; We want to keep our PC
; ADD Add A to B
:ADD jmpAimm $IADD ; A immediate special case
ADR1 -> mem_addr ; Examine A address
mem -> M1, mem -> M2
ADR2 -> mem_addr, M1 -> ALU1, M2 -> ALU2
mem -> M1, mem -> M2 ; Examine B address
ALU1 += M1, ALU2 += M2 ; Add them
ALU1 -> M1, ALU2 -> M2 ; And write back
M1 -> mem, M2 -> mem
jmp $ADDPC ; Continue
:IADD ADR2 -> mem_addr ; Alter in B's absolute address
M1 -> ALU1, mem -> M2 ; Add A to B op
ALU1 += M2
ALU1 -> M2
M2 -> mem ; Write it back
jmp $ADDPC ; Continue
; SUB Sub A from B
:SUB jmpAimm $ISUB
ADR2 -> mem_addr ; Examine B address
mem -> M1, mem -> M2
ADR1 -> mem_addr, M1 -> ALU1, M2 -> ALU2
mem -> M1, mem -> M2 ; Examine A address
ALU1 -= M1, ALU2 -= M2 ; Sub them
ALU1 -> M1, ALU2 -> M2, ADR2 -> mem_addr
M1 -> mem, M2 -> mem ; And write back
jmp $ADDPC ; Continue
:ISUB ADR2 -> mem_addr ; Alter in B's absolute address
mem -> M2 ; Load B op
M2 -> ALU1 ; Sub A op
ALU1 -= M1
ALU1 -> M2
M2 -> mem ; Write it back
jmp $ADDPC ; Continue
; JMP Jump to A
:JMP M1 -> FIFO, jmp $END ; Jump to adress of A op
; JMPZ Jump to A if B zero
:JMPZ jmpBimm $IJMPZ
ADR2 -> mem_addr ; Fetch B op
mem -> M2
:IJMPZ M2 -> ALU1
jmpZ $DOJMPZ ; If not zero
jmp $ADDPC ; Continue
:DOJMPZ jmp $JMP ; Else do a jump
; JMPN Jump to A if B non-zero
:JMPN jmpBimm $IJMPN
ADR2 -> mem_addr ; Fetch B op
mem -> M2
:IJMPN M2 -> ALU1
jmpZ $ADDPC ; If zero no jump
jmp $JMP ; Else do a jump
; CMP If A eq B skip next instr
:CMP jmpAimm $ICMP
ADR2 -> mem_addr ; Fetch mem operands +OP spec by B op
mem -> OP, mem -> M1, mem -> M2
ADR1 -> mem_addr, M1 -> ALU1, M2 -> ALU2
mem -> M1, mem -> M2 ; Fetch mem operands spec by A op
ALU1 -= M1, ALU2 -= M2 ; Compare
jmpE $CMPOP ; If eq compare OP as well
jmp $ADDPC ; Else continue with next instr
:CMPOP OP -> ALU1
mem -> OP
ALU1 -= OP
jmpZ $SKIP ; If eq, skip next instr
jmp $ADDPC ; Else continue as normal
:ICMP ADR2 -> mem_addr ; Fetch B op
mem -> M2, M1 -> ALU1
ALU1 -= M2 ; Compare
jmpZ $SKIP ; If eq, skip next instr
jmp $ADDPC ; Else continue as normal
; SLT if A is less than B skip next instr
:SLT jmpAimm $ISLT
ADR1 -> mem_addr ; Fetch B field spec by A
mem -> M2
M2 -> ALU1
:SLTCMP ADR2 -> mem_addr ; Fetch B field spec by B
mem -> M2
ALU1 -= M2 ; Compare A < B
jmpN $SKIP ; Skip next instr if A < B
jmp $ADDPC ; Else continue
:ISLT M1 -> ALU1, jmp $SLTCMP ; Place A in ALU for comparison, rest is the same
; DJN Decr B, if not zero jmp to A
:DJN jmpBimm $IDJN
ADR2 -> mem_addr ; Fetch B field spec by B
mem -> M2
:DODJN M2 -> ALU1 ; Decr
ALU--
ALU1 -> M2
M2 -> mem ; Write back
jmpZ $ADDPC ; If zero, continue
M1 -> FIFO, jmp $END ; Else jump to A
:IDJN M2 -> ALU1, PC -> mem_addr, jmp $DODJN ; B is immediate data, set PC as mem_addr
; SPL Place A in process queue
:SPL PC++
PC -> FIFO ; First add PC++ to queue
M1 -> FIFO, jmp $END ; Then add the address of A to queue
:SKIP PC++, jmp $ADDPC
; Keep the PC for next round
:ADDPC PC++
PC -> FIFO
:END check_gameover
:DELAY jmpC 0 ; Start over when we've spent enough time
jmp $DELAY
; Direct (default)
; The value is an offset to the memory location.
;
; # Immediate
; The value is the data
;
; @ Indirect
; Offset to a memory location. B operand of that is an offset to another memory location.
;
; < Pre-decrement indirect
; Offset to a memory location. B operand there, B--, inserted again. That is then used as an offset to another memory location.
You can’t perform that action at this time.