196 lines
3.4 KiB
Z80 Assembly
196 lines
3.4 KiB
Z80 Assembly
org &1000
|
|
PrintChar equ &BB5A
|
|
|
|
;reg usage:
|
|
;DE = VM'S Program Counter
|
|
;IXL = VM's Accumulator
|
|
main:
|
|
ld ixl,0
|
|
ld de,Computer_Zero_RAM_2_plus_2
|
|
call Computer_Zero_VM
|
|
ld a,ixl
|
|
call ShowHex ;output to Amstrad CPC's screen
|
|
call NewLine
|
|
|
|
ld ixl,0
|
|
ld de,Computer_Zero_RAM_7x8
|
|
call Computer_Zero_VM
|
|
ld a,ixl
|
|
jp ShowHex ;output and return to basic.
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;these two functions are related to displaying the output
|
|
; and have nothing to do with the virtual machine itself.
|
|
ShowHex:
|
|
push af
|
|
and %11110000
|
|
rrca
|
|
rrca
|
|
rrca
|
|
rrca
|
|
call PrintHexChar
|
|
pop af
|
|
and %00001111
|
|
;call PrintHexChar
|
|
;execution flows into it naturally.
|
|
PrintHexChar:
|
|
;converts hex to ascii
|
|
or a ;Clear Carry Flag
|
|
daa
|
|
add a,&F0
|
|
adc a,&40
|
|
jp PrintChar
|
|
|
|
NewLine:
|
|
push af
|
|
ld a,13
|
|
call PrintChar
|
|
ld a,10
|
|
call PrintChar
|
|
pop af
|
|
ret
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
Computer_Zero_VM:
|
|
ld a,(de) ;opcode fetch
|
|
call UnpackOpcode ;stores opcode in B, operand in C
|
|
push de
|
|
ld de,Opcode_Table
|
|
ld a,b
|
|
rlca ;index times 2 for word data
|
|
|
|
ld e,a
|
|
ld a,(de)
|
|
ld L,a
|
|
inc de
|
|
ld a,(de)
|
|
ld h,a ;LD HL,(DE)
|
|
|
|
pop de
|
|
jp (hl)
|
|
;register state after this jump:
|
|
;DE = program counter
|
|
;HL = address of instruction implementation
|
|
;C = operand of the instruction we're about to execute
|
|
;IXL = accumulator
|
|
|
|
|
|
|
|
overhead:
|
|
ld a,e
|
|
inc a
|
|
and %00011111
|
|
;ensures we stay within the 32 byte address space.
|
|
ld e,a
|
|
jp Computer_Zero_VM
|
|
|
|
|
|
UnpackOpcode:
|
|
push af
|
|
and %11100000
|
|
rlca
|
|
rlca
|
|
rlca
|
|
ld b,a ;opcode in B
|
|
pop af
|
|
and %00011111
|
|
ld c,a ;operand in C
|
|
dummy:
|
|
ret
|
|
|
|
|
|
|
|
align 256 ;ensures the following table is page-aligned
|
|
;this lets us index it much faster.
|
|
Opcode_Table:
|
|
dw vmNOP
|
|
dw vmLDA
|
|
dw vmSTA
|
|
dw vmADD
|
|
dw vmSUB
|
|
dw vmBRZ
|
|
dw vmJMP
|
|
dw vmSTP
|
|
|
|
vmNOP:
|
|
jp overhead ;do nothing
|
|
vmLDA:
|
|
push de
|
|
ld e,c ;offset DE by the operand
|
|
ld a,(de) ;load from that address
|
|
ld ixl,a ;and store it in the accumulator
|
|
pop de
|
|
jp overhead
|
|
vmSTA:
|
|
push de
|
|
ld e,c ;offset DE by the operand
|
|
ld a,ixl ;get the accumulator
|
|
ld (de),a ;store it into (DE)
|
|
pop de
|
|
jp overhead
|
|
vmADD:
|
|
push de
|
|
ld e,c ;offset DE by the operand
|
|
ld a,(de) ;load from that address
|
|
add ixl ;and add that value to the accumulator
|
|
ld ixl,a ;then set the new accumulator
|
|
pop de
|
|
jp overhead
|
|
vmSUB:
|
|
push de
|
|
ld e,c ;offset DE by the operand
|
|
ld a,(de)
|
|
ld b,a
|
|
ld a,ixl
|
|
sub b
|
|
ld ixl,a
|
|
pop de
|
|
noBRZ:
|
|
jp overhead
|
|
vmBRZ:
|
|
ld a,ixl
|
|
or a
|
|
jr nz, noBRZ
|
|
vmJMP:
|
|
ld e,c
|
|
jp Computer_Zero_VM
|
|
vmSTP:
|
|
ret ;return to main
|
|
|
|
align 256
|
|
Computer_Zero_RAM_2_plus_2:
|
|
db %00100011,%01100100
|
|
db %11100000,%00000010
|
|
db %00000010,%00000000
|
|
db %00000000,%00000000
|
|
db %00000000,%00000000
|
|
db %00000000,%00000000
|
|
db %00000000,%00000000
|
|
db %00000000,%00000000
|
|
db %00000000,%00000000
|
|
db %00000000,%00000000
|
|
db %00000000,%00000000
|
|
db %00000000,%00000000
|
|
db %00000000,%00000000
|
|
db %00000000,%00000000
|
|
db %00000000,%00000000
|
|
align 256
|
|
Computer_Zero_RAM_7x8:
|
|
db %00101100,%01101010
|
|
db %01001100,%00101011
|
|
db %10001101,%01001011
|
|
db %10101000,%11000000
|
|
db %00101100,%11100000
|
|
db %00001000,%00000111
|
|
db %00000000,%00000001
|
|
db %00000000,%00000000
|
|
db %00000000,%00000000
|
|
db %00000000,%00000000
|
|
db %00000000,%00000000
|
|
db %00000000,%00000000
|
|
db %00000000,%00000000
|
|
db %00000000,%00000000
|
|
db %00000000,%00000000
|
|
db %00000000,%00000000
|