; Z80 emulator with CP/M support. The Z80-specific instructions themselves actually aren't
; implemented yet, making this more of an i8080 emulator.
;
; Copyright (C) 2010 Sprite_tm
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see .
.nolist
#if defined atmega8
.include "m8def.inc"
#elif defined atmega168
.include "m168def.inc"
#else /* default */
.include "m88def.inc"
;FUSE_H=0xDF
;FUSE_L=0xF7
#endif
.list
.listmac
#ifndef DRAM_DQ_ORDER /* If this is set to 1, the portbits */
#define DRAM_DQ_ORDER 0 /* for DRAM D1 and WE are swapped. */
#endif
#ifndef F_CPU
#define F_CPU 20000000 /* system clock in Hz; defaults to 20MHz */
#endif
#ifndef BAUD
#define BAUD 38400 /* console baud rate */
#endif
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) /* clever rounding */
#define RXBUFSIZE 64 /* USART recieve buffer size. Must be power of 2 */
#define REFR_RATE 64000 /* dram refresh rate in cycles/s. */
/* Most drams need 1/15.6µs. */
#define REFR_PRE 8 /* timer prescale factor */
#define REFR_CS 0x02 /* timer clock select for 1/8 */
#define REFR_CNT F_CPU / REFR_RATE / REFR_PRE
#if defined __ATmega8__
.equ refr_vect = OC2addr
#else
.equ refr_vect = OC2Aaddr
#endif
#define EM_Z80 0 /* we don't have any z80 instructions yet */
.equ MMC_DEBUG = 0
.equ INS_DEBUG = 0
.equ MEMTEST = 1
.equ BOOTWAIT = 1
.equ PORT_DEBUG = 0
.equ DISK_DEBUG = 0
.equ MEMFILL_CB = 1
.equ STACK_DBG = 0
.equ PRINT_PC = 0
;Port declarations
; Port D
.equ rxd = 0
.equ txd = 1
.equ ram_oe = 2
.equ ram_a8 = 3
.equ mmc_cs = 4
.equ ram_a5 = 5
.equ ram_a6 = 6
.equ ram_a7 = 7
.equ P_OE = PORTD
.equ RAM_AH_MASK = 0xE0 ; ram_a[7..5]
.equ PD_OUTPUT_MASK = 0xFE
;Port B
.equ ram_a4 = 0
.equ ram_a3 = 1
.equ ram_a2 = 2
.equ ram_a1 = 3
.equ mmc_mosi = 3
.equ ram_a0 = 4
.equ mmc_miso = 4
.equ ram_ras = 5
.equ mmc_sck = 5
.equ P_RAS = PORTB
.equ RAM_AL_MASK = 0x1F ; ram_a[4..0]
.equ PB_OUTPUT_MASK = 0x3F
;Port C
#if DRAM_DQ_ORDER == 1
.equ ram_d1 = 1
.equ ram_w = 4
#else /* original */
.equ ram_d1 = 4
.equ ram_w = 1
#endif
.equ ram_d0 = 0
.equ ram_d2 = 2
.equ ram_d3 = 3
.equ ram_cas= 5
.equ P_W = PORTC
.equ P_CAS = PORTC
.equ RAM_DQ_MASK = (1<",0
rcall printhex
rcall printstr
.db ".",13,0
pop temp
pop zh
pop zl
.endif
ret
;Wait till the mmc answers with the response in temp2, or till a timeout happens.
mmcWaitResp:
ldi zl,0
ldi zh,0
mmcWaitResploop:
rcall mmcByteNoSend
cpi temp,0xff
brne mmcWaitResploopEnd
adiw zl,1
cpi zh,255
breq mmcWaitErr
rjmp mmcWaitResploop
mmcWaitResploopEnd:
ret
mmcWaitErr:
mov temp,temp2
rcall printhex
rcall printstr
.db ": Error: MMC resp timeout!",13,0
rjmp resetAVR
mmcInit:
ldi temp,0x53
out SPCR,temp
;Init start: send 80 clocks with cs disabled
sbi PORTD,mmc_cs
ldi temp2,20
mmcInitLoop:
mov temp,temp2
rcall mmcByte
dec temp2
brne mmcInitLoop
cbi PORTD,mmc_cs
rcall mmcByteNoSend
rcall mmcByteNoSend
rcall mmcByteNoSend
rcall mmcByteNoSend
rcall mmcByteNoSend
rcall mmcByteNoSend
sbi PORTD,mmc_cs
rcall mmcByteNoSend
rcall mmcByteNoSend
rcall mmcByteNoSend
rcall mmcByteNoSend
;Send init command
cbi PORTD,mmc_cs
ldi temp,0xff ;dummy
rcall mmcByte
ldi temp,0xff ;dummy
rcall mmcByte
ldi temp,0x40 ;cmd
rcall mmcByte
ldi temp,0 ;pxh
rcall mmcByte
ldi temp,0 ;pxl
rcall mmcByte
ldi temp,0 ;pyh
rcall mmcByte
ldi temp,0 ;pyl
rcall mmcByte
ldi temp,0x95 ;crc
rcall mmcByte
ldi temp,0xff ;return byte
rcall mmcByte
ldi temp2,0
rcall mmcWaitResp
sbi PORTD,mmc_cs
rcall mmcByteNoSend
;Read OCR till card is ready
ldi temp2,150
mmcInitOcrLoop:
push temp2
cbi PORTD,mmc_cs
ldi temp,0xff ;dummy
rcall mmcByte
ldi temp,0x41 ;cmd
rcall mmcByte
ldi temp,0 ;pxh
rcall mmcByte
ldi temp,0 ;pxl
rcall mmcByte
ldi temp,0 ;pyh
rcall mmcByte
ldi temp,0 ;pyl
rcall mmcByte
ldi temp,0x95 ;crc
rcall mmcByte
rcall mmcByteNoSend
ldi temp2,1
rcall mmcWaitResp
cpi temp,0
breq mmcInitOcrLoopDone
sbi PORTD,mmc_cs
rcall mmcByteNoSend
pop temp2
dec temp2
cpi temp2,0
brne mmcInitOcrLoop
ldi temp,4
rjmp mmcWaitErr
mmcInitOcrLoopDone:
pop temp2
sbi PORTD,mmc_cs
rcall mmcByteNoSend
ldi temp,0
out SPCR,temp
ret
;Call this with adrh:adrl = sector number
;16bit lba address means a max reach of 32M.
mmcReadSect:
ldi temp,0x50
out SPCR,temp
cbi PORTD,mmc_cs
rcall mmcByteNoSend
ldi temp,0x51 ;cmd (read sector)
rcall mmcByte
ldi temp,0
lsl adrl
rol adrh
rol temp
rcall mmcByte
mov temp,adrh ;pxl
rcall mmcByte
mov temp,adrl ;pyh
rcall mmcByte
ldi temp,0 ;pyl
rcall mmcByte
ldi temp,0x95 ;crc
rcall mmcByte
ldi temp,0xff ;return byte
rcall mmcByte
;resp
ldi temp2,2
rcall mmcWaitResp
;data token
ldi temp2,3
rcall mmcWaitResp
;Read sector to AVR RAM
ldi zl,low(sectbuff)
ldi zh,high(sectbuff)
mmcreadloop:
rcall mmcByteNoSend
st z+,temp
cpi zl,low(sectbuff+512)
brne mmcreadloop
cpi zh,high(sectbuff+512)
brne mmcreadloop
;CRC
rcall mmcByteNoSend
rcall mmcByteNoSend
sbi PORTD,mmc_cs
rcall mmcByteNoSend
ldi temp,0
out SPCR,temp
ret
;Call this with adrh:adrl = sector number
;16bit lba address means a max reach of 32M.
mmcWriteSect:
ldi temp,0x50
out SPCR,temp
cbi PORTD,mmc_cs
rcall mmcByteNoSend
ldi temp,0x58 ;cmd (write sector)
rcall mmcByte
ldi temp,0
lsl adrl
rol adrh
rol temp
rcall mmcByte
mov temp,adrh ;pxl
rcall mmcByte
mov temp,adrl ;pyh
rcall mmcByte
ldi temp,0 ;pyl
rcall mmcByte
ldi temp,0x95 ;crc
rcall mmcByte
ldi temp,0xff ;return byte
rcall mmcByte
;resp
ldi temp2,1
rcall mmcWaitResp
;Send data token
ldi temp,0xfe
rcall mmcByte
;Write sector from AVR RAM
ldi zl,low(sectbuff)
ldi zh,high(sectbuff)
mmcwriteloop:
ld temp,z+
rcall mmcByte
cpi zl,low(sectbuff+512)
brne mmcwriteloop
cpi zh,high(sectbuff+512)
brne mmcwriteloop
;CRC
rcall mmcByteNoSend
rcall mmcByteNoSend
;Status. Ignored for now.
rcall mmcByteNoSend
;Wait till the mmc has written everything
mmcwaitwritten:
rcall mmcByteNoSend
cpi temp,0xff
brne mmcwaitwritten
sbi PORTD,mmc_cs
rcall mmcByteNoSend
ldi temp,0
out SPCR,temp
ret
;Set up wdt to time out after 1 sec.
resetAVR:
cli
#if defined __ATmega8__
ldi temp,(1< 21 cycles
; ****************************************************************************
; ------------- system timer 10ms ---------------
.dseg
delay_timer:
.byte 1
timer_base:
timer_ms:
.byte 2
timer_s:
.byte 4
; don't change order here, clock put/get depends on it.
cntms_out: ; register for ms
.byte 2
utime_io: ; register for uptime.
.byte 4
cnt_1ms:
.byte 2
uptime:
.byte 4
timer_top:
.equ timer_size = timer_top - timer_base
.equ clkofs = cnt_1ms-cntms_out
.equ timerofs = cnt_1ms-timer_ms
.cseg
sysclockint:
push zl
in zl,SREG
push zl
push zh
lds zl,delay_timer
subi zl,1
brcs syscl1
sts delay_timer,zl
syscl1:
lds zl,cnt_1ms
lds zh,cnt_1ms+1
adiw z,1
sts cnt_1ms,zl
sts cnt_1ms+1,zh
cpi zl,low(1000)
ldi zl,high(1000) ;doesn't change flags
cpc zh,zl
brlo syscl_end
ldi zl,0
sts cnt_1ms,zl
sts cnt_1ms+1,zl
lds zl,uptime+0
inc zl
sts uptime+0,zl
brne syscl_end
lds zl,uptime+1
inc zl
sts uptime+1,zl
brne syscl_end
lds zl,uptime+2
inc zl
sts uptime+2,zl
brne syscl_end
lds zl,uptime+3
inc zl
sts uptime+3,zl
syscl_end:
pop zh
pop zl
out SREG,zl
pop zl
reti
; wait for temp ms
delay_ms:
sts delay_timer,temp
dly_loop:
lds temp,delay_timer
cpi temp,0
brne dly_loop
ret
;
clockget:
ldi temp,0xFF
subi temp2,TIMER_MSECS
brcs clkget_end ;Port number in range?
ldi zl,low(cntms_out)
ldi zh,high(cntms_out)
breq clkget_copy ;lowest byte requestet, latch clock
cpi temp2,6
brsh clkget_end ;Port number to high?
add zl,temp2
brcc PC+2
inc zh
ld temp,z
clkget_end:
ret
clkget_copy:
ldi temp2,6
cli
clkget_l:
ldd temp,z+clkofs
st z+,temp
dec temp2
brne clkget_l
sei
lds temp,cntms_out
;req. byte in temp
ret
clockput:
subi temp2,TIMERPORT
brcs clkput_end ;Port number in range?
brne clkput_1
; clock control
cpi temp,starttimercmd
breq timer_start
cpi temp,quitTimerCmd
breq timer_quit
cpi temp,printTimerCmd
breq timer_print
cpi temp,uptimeCmd
brne cp_ex
rjmp uptime_print
cp_ex:
ret
timer_quit:
rcall timer_print
rjmp timer_start
clkput_1:
dec temp2
ldi zl,low(cntms_out)
ldi zh,high(cntms_out)
breq clkput_copy ;lowest byte requestet, latch clock
cpi temp2,6
brsh clkput_end ;Port number to high?
add zl,temp2
brcc PC+2
inc zh
st z,temp
clkput_end:
ret
clkput_copy:
st z,temp
adiw z,5
ldi temp2,6
cli
clkput_l:
ldd temp,z+clkofs
st z+,temp
dec temp2
brne clkput_l
sei
ret
; start/reset timer
;
timer_start:
ldi zl,low(timer_ms)
ldi zh,high(timer_ms)
ldi temp2,6
cli
ts_loop:
ldd temp,z+timerofs
st z+,temp
dec temp2
brne ts_loop
sei
ret
; print timer
;
timer_print:
push adrh
push adrl
push oph
push opl
ldi zl,low(timer_ms)
ldi zh,high(timer_ms)
; put ms on stack (16 bit)
cli
ldd adrl,z+timerofs
ld temp2,z+
sub adrl,temp2
ldd adrh,z+timerofs
ld temp2,z+
sbc adrh,temp2
brsh tp_s
subi adrl,low(-1000)
sbci adrh,high(-1000)
sec
tp_s:
push adrh
push adrl
;
ldd temp,z+timerofs
ld adrl,z+
sbc temp,adrl
ldd temp2,z+timerofs
ld adrh,z+
sbc temp2,adrh
ldd opl,z+timerofs
ld adrl,z+
sbc opl,adrl
sei
ldd oph,z+timerofs
ld adrh,z+
sbc oph,adrh
rcall printstr
.db 13,"Timer running. Elapsed: ",0
rcall print_ultoa
rcall printstr
.db ",",0
ldi opl,0
ldi oph,0
pop temp
pop temp2
rcall print_ultoa
rcall printstr
.db "s.",0
pop opl
pop oph
pop adrl
pop adrh
ret
uptime_print:
push oph
push opl
ldi zl,low(cnt_1ms)
ldi zh,high(cnt_1ms)
cli
ld temp,z+
push temp
ld temp,z+
push temp
ld temp,z+
ld temp2,z+
ld opl,z+
sei
ld oph,z+
rcall printstr
.db 13,"Uptime: ",0
rcall print_ultoa
rcall printstr
.db ",",0
ldi opl,0
ldi oph,0
pop temp2
pop temp
rcall print_ultoa
rcall printstr
.db "s.",0,0
pop opl
pop oph
ret
; --------------- Debugging stuff ---------------
;Print a unsigned lonng value to the uart
; oph:opl:temp2:temp = value
print_ultoa:
push adrh
push adrl
push insdech
clr adrl ;adrl = stack level
ultoa1: ldi insdech, 32 ;adrh = oph:temp % 10
clr adrh ;oph:temp /= 10
ultoa2: lsl temp
rol temp2
rol opl
rol oph
rol adrh
cpi adrh,10
brcs ultoa3
subi adrh,10
inc temp
ultoa3: dec insdech
brne ultoa2
cpi adrh, 10 ;adrh is a numeral digit '0'-'9'
subi adrh, -'0'
push adrh ;Stack it
inc adrl
ldi insdech,0
cp temp,insdech ;Repeat until oph:temp gets zero
cpc temp2,insdech
cpc opl,insdech
cpc oph,insdech
brne ultoa1
ldi temp, '0'
ultoa5: cpi adrl,3 ; at least 3 digits (ms)
brge ultoa6
push temp
inc adrl
rjmp ultoa5
ultoa6: pop temp ;Flush stacked digits
rcall uartputc
dec adrl
brne ultoa6
pop insdech
pop adrl
pop adrh
ret
;Prints the lower nibble of temp in hex to the uart
printhexn:
push temp
andi temp,0xf
cpi temp,0xA
brlo printhexn_isno
subi temp,-('A'-10)
rcall uartputc
pop temp
ret
printhexn_isno:
subi temp,-'0'
rcall uartputc
pop temp
ret
;Prints temp in hex to the uart
printhex:
swap temp
rcall printhexn
swap temp
rcall printhexn
ret
;Prints the zero-terminated string following the call statement. WARNING: Destroys temp.
printstr:
pop zh
pop zl
push temp
lsl zl
rol zh
printstr_loop:
lpm temp,z+
cpi temp,0
breq printstr_end
rcall uartputc
cpi temp,13
brne printstr_loop
ldi temp,10
rcall uartputc
rjmp printstr_loop
printstr_end:
adiw zl,1
lsr zh
ror zl
pop temp
push zl
push zh
ret
; --------------- AVR HW <-> Z80 periph stuff ------------------
.equ memReadByte = dram_read
.equ memWriteByte = dram_write
; --------------------------------------------------------------
.dseg
#define RXBUFMASK RXBUFSIZE-1
rxcount:
.byte 1
rxidx_w:
.byte 1
rxidx_r:
.byte 1
rxfifo:
.byte RXBUFSIZE
.byte 0
.cseg
; Save received character in a circular buffer. Do nothing if buffer overflows.
rxint:
push temp
in temp,sreg
push temp
push zh
push zl
#ifdef __ATmega8__
in temp,UDR
#else
lds temp,UDR0
#endif
lds zh,rxcount ;if rxcount < RXBUFSIZE
cpi zh,RXBUFSIZE ; (room for at least 1 char?)
brsh rxi_ov ;
inc zh ;
sts rxcount,zh ; rxcount++
ldi zl,low(rxfifo) ;
lds zh,rxidx_w ;
add zl,zh ;
inc zh ;
andi zh,RXBUFMASK ;
sts rxidx_w,zh ; rxidx_w = ++rxidx_w % RXBUFSIZE
ldi zh,high(rxfifo) ;
brcc PC+2 ;
inc zh ;
st z,temp ; rxfifo[rxidx_w] = char
rxi_ov: ;endif
pop zl
pop zh
pop temp
out sreg,temp
pop temp
reti
;Fetches a char from the buffer to temp. If none available, waits till one is.
uartgetc:
lds temp,rxcount ; Number of characters in buffer
tst temp
breq uartgetc
push zh
push zl
ldi zl,low(rxfifo)
ldi zh,high(rxfifo)
lds temp,rxidx_r
add zl,temp
brcc PC+2
inc zh
inc temp
andi temp,RXBUFMASK
sts rxidx_r,temp
cli
lds temp,rxcount
dec temp
sts rxcount,temp
sei
ld temp,z ;don't forget to get the char
pop zl
pop zh
ret
;Sends a char from temp to the uart.
uartputc:
#if defined __ATmega8__
uartputc_l:
sbis UCSRA,UDRE
rjmp uartputc_l
out UDR,temp
#else
push temp
uartputc_l:
lds temp,UCSR0A
sbrs temp,UDRE0
rjmp uartputc_l
pop temp
sts UDR0,temp
#endif
ret
; ------------ Fetch phase stuff -----------------
.equ FETCH_NOP = (0<<0)
.equ FETCH_A = (1<<0)
.equ FETCH_B = (2<<0)
.equ FETCH_C = (3<<0)
.equ FETCH_D = (4<<0)
.equ FETCH_E = (5<<0)
.equ FETCH_H = (6<<0)
.equ FETCH_L = (7<<0)
.equ FETCH_AF = (8<<0)
.equ FETCH_BC = (9<<0)
.equ FETCH_DE = (10<<0)
.equ FETCH_HL = (11<<0)
.equ FETCH_SP = (12<<0)
.equ FETCH_MBC = (13<<0)
.equ FETCH_MDE = (14<<0)
.equ FETCH_MHL = (15<<0)
.equ FETCH_MSP = (16<<0)
.equ FETCH_DIR8 = (17<<0)
.equ FETCH_DIR16= (18<<0)
.equ FETCH_RST = (19<<0)
;Jump table for fetch routines. Make sure to keep this in sync with the .equs!
fetchjumps:
.dw do_fetch_nop
.dw do_fetch_a
.dw do_fetch_b
.dw do_fetch_c
.dw do_fetch_d
.dw do_fetch_e
.dw do_fetch_h
.dw do_fetch_l
.dw do_fetch_af
.dw do_fetch_bc
.dw do_fetch_de
.dw do_fetch_hl
.dw do_fetch_sp
.dw do_fetch_mbc
.dw do_fetch_mde
.dw do_fetch_mhl
.dw do_fetch_msp
.dw do_fetch_dir8
.dw do_fetch_dir16
.dw do_fetch_rst
do_fetch_nop:
ret
do_fetch_a:
mov opl,z_a
ret
do_fetch_b:
mov opl,z_b
ret
do_fetch_c:
mov opl,z_c
ret
do_fetch_d:
mov opl,z_d
ret
do_fetch_e:
mov opl,z_e
ret
do_fetch_h:
mov opl,z_h
ret
do_fetch_l:
mov opl,z_l
ret
do_fetch_af:
mov opl,z_flags
mov oph,z_a
ret
do_fetch_bc:
mov opl,z_c
mov oph,z_b
ret
do_fetch_de:
mov opl,z_e
mov oph,z_d
ret
do_fetch_hl:
mov opl,z_l
mov oph,z_h
ret
do_fetch_sp:
mov opl,z_spl
mov oph,z_sph
ret
do_fetch_mbc:
mov adrh,z_b
mov adrl,z_c
rcall memReadByte
mov opl,temp
ret
do_fetch_mde:
mov adrh,z_d
mov adrl,z_e
rcall memReadByte
mov opl,temp
ret
do_fetch_mhl:
mov adrh,z_h
mov adrl,z_l
rcall memReadByte
mov opl,temp
ret
do_fetch_msp:
mov adrh,z_sph
mov adrl,z_spl
rcall memReadByte
mov opl,temp
ldi temp,1
ldi temp2,0
add adrl,temp
adc adrh,temp2
rcall memReadByte
mov oph,temp
ret
do_fetch_dir8:
mov adrl,z_pcl
mov adrh,z_pch
rcall memReadByte
adiw z_pcl,1
mov opl,temp
ret
do_fetch_dir16:
mov adrl,z_pcl
mov adrh,z_pch
rcall memReadByte
mov opl,temp
adiw z_pcl,1
mov adrl,z_pcl
mov adrh,z_pch
rcall memReadByte
adiw z_pcl,1
mov oph,temp
ret
do_fetch_rst:
mov adrl,z_pcl
mov adrh,z_pch
subi adrl,1
sbci adrh,0
rcall memReadByte
andi temp,0x38
ldi oph,0
mov opl,temp
ret
; ------------ Store phase stuff -----------------
.equ STORE_NOP = (0<<5)
.equ STORE_A = (1<<5)
.equ STORE_B = (2<<5)
.equ STORE_C = (3<<5)
.equ STORE_D = (4<<5)
.equ STORE_E = (5<<5)
.equ STORE_H = (6<<5)
.equ STORE_L = (7<<5)
.equ STORE_AF = (8<<5)
.equ STORE_BC = (9<<5)
.equ STORE_DE = (10<<5)
.equ STORE_HL = (11<<5)
.equ STORE_SP = (12<<5)
.equ STORE_PC = (13<<5)
.equ STORE_MBC = (14<<5)
.equ STORE_MDE = (15<<5)
.equ STORE_MHL = (16<<5)
.equ STORE_MSP = (17<<5)
.equ STORE_RET = (18<<5)
.equ STORE_CALL = (19<<5)
.equ STORE_AM = (20<<5)
;Jump table for store routines. Make sure to keep this in sync with the .equs!
storejumps:
.dw do_store_nop
.dw do_store_a
.dw do_store_b
.dw do_store_c
.dw do_store_d
.dw do_store_e
.dw do_store_h
.dw do_store_l
.dw do_store_af
.dw do_store_bc
.dw do_store_de
.dw do_store_hl
.dw do_store_sp
.dw do_store_pc
.dw do_store_mbc
.dw do_store_mde
.dw do_store_mhl
.dw do_store_msp
.dw do_store_ret
.dw do_store_call
.dw do_store_am
do_store_nop:
ret
do_store_a:
mov z_a,opl
ret
do_store_b:
mov z_b,opl
ret
do_store_c:
mov z_c,opl
ret
do_store_d:
mov z_d,opl
ret
do_store_e:
mov z_e,opl
ret
do_store_h:
mov z_h,opl
ret
do_store_l:
mov z_l,opl
ret
do_store_af:
mov z_a,oph
mov z_flags,opl
ret
do_store_bc:
mov z_b,oph
mov z_c,opl
ret
do_store_de:
mov z_d,oph
mov z_e,opl
ret
do_store_hl:
mov z_h,oph
mov z_l,opl
ret
do_store_mbc:
mov adrh,z_b
mov adrl,z_c
mov temp,opl
rcall memWriteByte
ret
do_store_mde:
mov adrh,z_d
mov adrl,z_e
mov temp,opl
rcall memWriteByte
ret
do_store_mhl:
mov adrh,z_h
mov adrl,z_l
mov temp,opl
rcall memWriteByte
ret
do_store_msp:
mov adrh,z_sph
mov adrl,z_spl
mov temp,opl
rcall memWriteByte
ldi temp,1
ldi temp2,0
add adrl,temp
adc adrh,temp2
mov temp,oph
rcall memWriteByte
ret
do_store_sp:
mov z_sph,oph
mov z_spl,opl
ret
do_store_pc:
mov z_pch,oph
mov z_pcl,opl
ret
do_store_ret:
rcall do_op_pop16
mov z_pcl,opl
mov z_pch,oph
ret
do_store_call:
push opl
push oph
mov opl,z_pcl
mov oph,z_pch
rcall do_op_push16
pop z_pch
pop z_pcl
ret
do_store_am:
mov adrh,oph
mov adrl,opl
mov temp,z_a
rcall memWriteByte
ret
; ------------ Operation phase stuff -----------------
.equ OP_NOP = (0<<10)
.equ OP_INC = (1<<10)
.equ OP_DEC = (2<<10)
.equ OP_INC16 = (3<<10)
.equ OP_DEC16 = (4<<10)
.equ OP_RLC = (5<<10)
.equ OP_RRC = (6<<10)
.equ OP_RR = (7<<10)
.equ OP_RL = (8<<10)
.equ OP_ADDA = (9<<10)
.equ OP_ADCA = (10<<10)
.equ OP_SUBFA = (11<<10)
.equ OP_SBCFA = (12<<10)
.equ OP_ANDA = (13<<10)
.equ OP_ORA = (14<<10)
.equ OP_XORA = (15<<10)
.equ OP_ADDHL = (16<<10)
.equ OP_STHL = (17<<10) ;store HL in fetched address
.equ OP_RMEM16 = (18<<10) ;read mem at fetched address
.equ OP_RMEM8 = (19<<10) ;read mem at fetched address
.equ OP_DA = (20<<10)
.equ OP_SCF = (21<<10)
.equ OP_CPL = (22<<10)
.equ OP_CCF = (23<<10)
.equ OP_POP16 = (24<<10)
.equ OP_PUSH16 = (25<<10)
.equ OP_IFNZ = (26<<10)
.equ OP_IFZ = (27<<10)
.equ OP_IFNC = (28<<10)
.equ OP_IFC = (29<<10)
.equ OP_IFPO = (30<<10)
.equ OP_IFPE = (31<<10)
.equ OP_IFP = (32<<10)
.equ OP_IFM = (33<<10)
.equ OP_OUTA = (34<<10)
.equ OP_IN = (35<<10)
.equ OP_EXHL = (36<<10)
.equ OP_DI = (37<<10)
.equ OP_EI = (38<<10)
.equ OP_INV = (39<<10)
opjumps:
.dw do_op_nop
.dw do_op_inc
.dw do_op_dec
.dw do_op_inc16
.dw do_op_dec16
.dw do_op_rlc
.dw do_op_rrc
.dw do_op_rr
.dw do_op_rl
.dw do_op_adda
.dw do_op_adca
.dw do_op_subfa
.dw do_op_sbcfa
.dw do_op_anda
.dw do_op_ora
.dw do_op_xora
.dw do_op_addhl
.dw do_op_sthl
.dw do_op_rmem16
.dw do_op_rmem8
.dw do_op_da
.dw do_op_scf
.dw do_op_cpl
.dw do_op_ccf
.dw do_op_pop16
.dw do_op_push16
.dw do_op_ifnz
.dw do_op_ifz
.dw do_op_ifnc
.dw do_op_ifc
.dw do_op_ifpo
.dw do_op_ifpe
.dw do_op_ifp
.dw do_op_ifm
.dw do_op_outa
.dw do_op_in
.dw do_op_exhl
.dw do_op_di
.dw do_op_ei
.dw do_op_inv
;How the flags are supposed to work:
;7 ZFL_S - Sign flag (=MSBit of result)
;6 ZFL_Z - Zero flag. Is 1 when the result is 0
;4 ZFL_H - Half-carry (carry from bit 3 to 4)
;2 ZFL_P - Parity/2-complement Overflow
;1 ZFL_N - Subtract - set if last op was a subtract
;0 ZFL_C - Carry
;
;I sure hope I got the mapping between flags and instructions correct...
;----------------------------------------------------------------
;| |
;| Zilog |
;| |
;| ZZZZZZZ 88888 000 |
;| Z 8 8 0 0 |
;| Z 8 8 0 0 0 |
;| Z 88888 0 0 0 |
;| Z 8 8 0 0 0 |
;| Z 8 8 0 0 |
;| ZZZZZZZ 88888 000 |
;| |
;| Z80 MICROPROCESSOR Instruction Set Summary |
;| |
;----------------------------------------------------------------
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;|----------+------+---------------------+----------------------|
;|ADC A,s |***V0*|Add with Carry |A=A+s+CY |
;|ADC HL,ss |**?V0*|Add with Carry |HL=HL+ss+CY |
;|ADD A,s |***V0*|Add |A=A+s |
;|ADD HL,ss |--?-0*|Add |HL=HL+ss |
;|ADD IX,pp |--?-0*|Add |IX=IX+pp |
;|ADD IY,rr |--?-0*|Add |IY=IY+rr |
;|AND s |**1P00|Logical AND |A=A&s |
;|BIT b,m |?*1?0-|Test Bit |m&{2^b} |
;|CALL cc,nn|------|Conditional Call |If cc CALL |
;|CALL nn |------|Unconditional Call |-[SP]=PC,PC=nn |
;|CCF |--?-0*|Complement Carry Flag|CY=~CY |
;|CP s |***V1*|Compare |A-s |
;|CPD |****1-|Compare and Decrement|A-[HL],HL=HL-1,BC=BC-1|
;|CPDR |****1-|Compare, Dec., Repeat|CPD till A=[HL]or BC=0|
;|CPI |****1-|Compare and Increment|A-[HL],HL=HL+1,BC=BC-1|
;|CPIR |****1-|Compare, Inc., Repeat|CPI till A=[HL]or BC=0|
;|CPL |--1-1-|Complement |A=~A |
;|DAA |***P-*|Decimal Adjust Acc. |A=BCD format |
;|DEC s |***V1-|Decrement |s=s-1 |
;|DEC xx |------|Decrement |xx=xx-1 |
;|DEC ss |------|Decrement |ss=ss-1 |
;|DI |------|Disable Interrupts | |
;|DJNZ e |------|Dec., Jump Non-Zero |B=B-1 till B=0 |
;|EI |------|Enable Interrupts | |
;|EX [SP],HL|------|Exchange |[SP]<->HL |
;|EX [SP],xx|------|Exchange |[SP]<->xx |
;|EX AF,AF' |------|Exchange |AF<->AF' |
;|EX DE,HL |------|Exchange |DE<->HL |
;|EXX |------|Exchange |qq<->qq' (except AF)|
;|HALT |------|Halt | |
;|IM n |------|Interrupt Mode | (n=0,1,2)|
;|IN A,[n] |------|Input |A=[n] |
;|IN r,[C] |***P0-|Input |r=[C] |
;|INC r |***V0-|Increment |r=r+1 |
;|INC [HL] |***V0-|Increment |[HL]=[HL]+1 |
;|INC xx |------|Increment |xx=xx+1 |
;|INC [xx+d]|***V0-|Increment |[xx+d]=[xx+d]+1 |
;|INC ss |------|Increment |ss=ss+1 |
;|IND |?*??1-|Input and Decrement |[HL]=[C],HL=HL-1,B=B-1|
;|INDR |?1??1-|Input, Dec., Repeat |IND till B=0 |
;|INI |?*??1-|Input and Increment |[HL]=[C],HL=HL+1,B=B-1|
;|INIR |?1??1-|Input, Inc., Repeat |INI till B=0 |
;|JP [HL] |------|Unconditional Jump |PC=[HL] |
;|JP [xx] |------|Unconditional Jump |PC=[xx] |
;|JP nn |------|Unconditional Jump |PC=nn |
;|JP cc,nn |------|Conditional Jump |If cc JP |
;|JR e |------|Unconditional Jump |PC=PC+e |
;|JR cc,e |------|Conditional Jump |If cc JR(cc=C,NC,NZ,Z)|
;|LD dst,src|------|Load |dst=src |
;|LD A,i |**0*0-|Load |A=i (i=I,R)|
;|LDD |--0*0-|Load and Decrement |[DE]=[HL],HL=HL-1,# |
;|LDDR |--000-|Load, Dec., Repeat |LDD till BC=0 |
;|LDI |--0*0-|Load and Increment |[DE]=[HL],HL=HL+1,# |
;|LDIR |--000-|Load, Inc., Repeat |LDI till BC=0 |
;|NEG |***V1*|Negate |A=-A |
;|NOP |------|No Operation | |
;|OR s |**0P00|Logical inclusive OR |A=Avs |
;|OTDR |?1??1-|Output, Dec., Repeat |OUTD till B=0 |
;|OTIR |?1??1-|Output, Inc., Repeat |OUTI till B=0 |
;|OUT [C],r |------|Output |[C]=r |
;|OUT [n],A |------|Output |[n]=A |
;|OUTD |?*??1-|Output and Decrement |[C]=[HL],HL=HL-1,B=B-1|
;|OUTI |?*??1-|Output and Increment |[C]=[HL],HL=HL+1,B=B-1|
;|POP xx |------|Pop |xx=[SP]+ |
;|POP qq |------|Pop |qq=[SP]+ |
;|PUSH xx |------|Push |-[SP]=xx |
;|PUSH qq |------|Push |-[SP]=qq |
;|RES b,m |------|Reset bit |m=m&{~2^b} |
;|RET |------|Return |PC=[SP]+ |
;|RET cc |------|Conditional Return |If cc RET |
;|RETI |------|Return from Interrupt|PC=[SP]+ |
;|RETN |------|Return from NMI |PC=[SP]+ |
;|RL m |**0P0*|Rotate Left |m={CY,m}<- |
;|RLA |--0-0*|Rotate Left Acc. |A={CY,A}<- |
;|RLC m |**0P0*|Rotate Left Circular |m=m<- |
;|RLCA |--0-0*|Rotate Left Circular |A=A<- |
;|RLD |**0P0-|Rotate Left 4 bits |{A,[HL]}={A,[HL]}<- ##|
;|RR m |**0P0*|Rotate Right |m=->{CY,m} |
;|RRA |--0-0*|Rotate Right Acc. |A=->{CY,A} |
;|RRC m |**0P0*|Rotate Right Circular|m=->m |
;|RRCA |--0-0*|Rotate Right Circular|A=->A |
;|RRD |**0P0-|Rotate Right 4 bits |{A,[HL]}=->{A,[HL]} ##|
;|RST p |------|Restart | (p=0H,8H,10H,...,38H)|
;|SBC A,s |***V1*|Subtract with Carry |A=A-s-CY |
;|SBC HL,ss |**?V1*|Subtract with Carry |HL=HL-ss-CY |
;|SCF |--0-01|Set Carry Flag |CY=1 |
;|SET b,m |------|Set bit |m=mv{2^b} |
;|SLA m |**0P0*|Shift Left Arithmetic|m=m*2 |
;|SRA m |**0P0*|Shift Right Arith. |m=m/2 |
;|SRL m |**0P0*|Shift Right Logical |m=->{0,m,CY} |
;|SUB s |***V1*|Subtract |A=A-s |
;|XOR s |**0P00|Logical Exclusive OR |A=Axs |
;|----------+------+--------------------------------------------|
.equ AVR_T = 6
.equ AVR_H = 5
.equ AVR_S = 4
.equ AVR_V = 3
.equ AVR_N = 2
.equ AVR_Z = 1
.equ AVR_C = 0
;------------------------------------------------;
; Move single bit between two registers
;
; bmov dstreg,dstbit,srcreg.srcbit
.macro bmov
bst @2,@3
bld @0,@1
.endm
;------------------------------------------------;
; Load table value from flash indexed by source reg.
;
; ldpmx dstreg,tablebase,indexreg
;
; (6 words, 8 cycles)
.macro ldpmx
ldi zl,low (@1*2)
ldi zh,high(@1*2)
add zl,@2
brcc PC+2
inc zh
lpm @0,z
.endm
.macro do_z80_flags_HP
#if EM_Z80
bmov z_flags, ZFL_P, temp, AVR_V
bmov z_flags, ZFL_H, temp, AVR_H
#endif
.endm
.macro do_z80_flags_set_N
#if EM_Z80
ori z_flags, (1<A |
;|----------|SZHP C|---------- 8080 ----------------------------|
;|RRCA |---- *|Rotate Right Circular|A=->A |
;
;
do_op_rrc:
;Rotate Right Cyclical. All bits move 1 to the
;right, the lsb becomes c and msb.
do_z80_flags_op_rotate
lsr opl
brcc do_op_rrc_noc
ori opl, 0x80
ori z_flags, (1<{CY,A} |
;|----------|SZHP C|---------- 8080 ----------------------------|
;|RRA |---- *|Rotate Right Acc. |A=->{CY,A} |
;
;
do_op_rr:
;Rotate Right. All bits move 1 to the right, the lsb
;becomes c, c becomes msb.
clc ; get z80 carry to avr carry
sbrc z_flags,ZFL_C
sec
do_z80_flags_op_rotate ; (clear ZFL_C, doesn't change AVR_C)
bmov z_flags,ZFL_C, opl,0 ; Bit 0 --> CY
ror opl
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|RLA |--0-0*|Rotate Left Acc. |A={CY,A}<- |
;|----------|SZHP C|---------- 8080 ----------------------------|
;|RLA |---- *|Rotate Left Acc. |A={CY,A}<- |
;
;
do_op_rl:
;Rotate Left. All bits move 1 to the left, the msb
;becomes c, c becomes lsb.
clc
sbrc z_flags,ZFL_C
sec
do_z80_flags_op_rotate ; (clear ZFL_C, doesn't change AVR_C)
bmov z_flags,ZFL_C, opl,7 ; Bit 7 --> CY
rol opl
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|ADD A,s |***V0*|Add |A=A+s |
;|----------|SZHP C|---------- 8080 ----------------------------|
;|ADD A,s |***P *|Add |A=A+s |
;
;
do_op_adda:
add opl,z_a
in temp,sreg
ldpmx z_flags,sz53p_tab,opl ;S,Z,P flag
bmov z_flags,ZFL_C, temp,AVR_C
do_z80_flags_HP
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|ADC A,s |***V0*|Add with Carry |A=A+s+CY |
;|----------|SZHP C|---------- 8080 ----------------------------|
;|ADC A,s |***P *|Add with Carry |A=A+s+CY |
;
;
do_op_adca:
clc
sbrc z_flags,ZFL_C
sec
adc opl,z_a
in temp,sreg
ldpmx z_flags,sz53p_tab,opl ;S,Z,P
bmov z_flags,ZFL_C, temp,AVR_C
do_z80_flags_HP
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|SUB s |***V1*|Subtract |A=A-s |
;|CP s |***V1*|Compare |A-s |
;|----------|SZHP C|---------- 8080 ----------------------------|
;|SUB s |***P *|Subtract |A=A-s |
;|CP s |***P *|Compare |A-s |
;
do_op_subfa:
mov temp,z_a
sub temp,opl
mov opl,temp
in temp,sreg
ldpmx z_flags,sz53p_tab,opl ;S,Z,P
bmov z_flags,ZFL_C, temp,AVR_C
do_z80_flags_HP
do_z80_flags_set_N
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|SBC A,s |***V1*|Subtract with Carry |A=A-s-CY |
;|----------|SZHP C|---------- 8080 ----------------------------|
;|SBC A,s |***P *|Subtract with Carry |A=A-s-CY |
;
;
do_op_sbcfa:
mov temp,z_a
clc
sbrc z_flags,ZFL_C
sec
sbc temp,opl
mov opl,temp
in temp,sreg
ldpmx z_flags,sz53p_tab,opl ;S,Z,P
bmov z_flags,ZFL_C, temp,AVR_C
do_z80_flags_HP
do_z80_flags_set_N
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|AND s |**1P00|Logical AND |A=A&s |
;|----------|SZHP C|---------- 8080 ----------------------------|
;|AND s |**-P 0|Logical AND |A=A&s |
;
; TODO H-Flag
do_op_anda:
and opl,z_a ;
ldpmx z_flags,sz53p_tab,opl ;S,Z,P,N,C
do_z80_flags_op_and
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|OR s |**0P00|Logical inclusive OR |A=Avs |
;|----------|SZHP C|---------- 8080 ----------------------------|
;|OR s |**-P00|Logical inclusive OR |A=Avs |
;
; TODO: H-Flag
do_op_ora:
or opl,z_a
ldpmx z_flags,sz53p_tab,opl ;S,Z,H,P,N,C
do_z80_flags_op_or
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|XOR s |**0P00|Logical Exclusive OR |A=Axs |
;|----------|SZHP C|---------- 8080 ----------------------------|
;|XOR s |**-P 0|Logical Exclusive OR |A=Axs |
;
; TODO: H-Flag
do_op_xora:
eor opl,z_a
ldpmx z_flags,sz53p_tab,opl ;S,Z,H,P,N,C
do_z80_flags_op_or
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|ADD HL,ss |--?-0*|Add |HL=HL+ss |
;|----------|SZHP C|---------- 8080 ----------------------------|
;|ADD HL,ss |---- *|Add |HL=HL+ss |
;
;
do_op_addhl:
add opl,z_l
adc oph,z_h
in temp,sreg
bmov z_flags,ZFL_H, temp,AVR_H
bmov z_flags,ZFL_C, temp,AVR_C
do_z80_flags_clear_N
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|LD dst,src|------|Load |dst=src |
;
;
do_op_sthl: ;store hl to mem loc in opl:h
mov adrl,opl
mov adrh,oph
mov temp,z_l
rcall memWriteByte
inc opl
brne op_sthlx
inc oph
op_sthlx:
mov adrl,opl
mov adrh,oph
mov temp,z_h
rcall memWriteByte
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|LD dst,src|------|Load |dst=src |
;
;
do_op_rmem16:
mov adrl,opl
mov adrh,oph
rcall memReadByte
mov opl,temp
ldi temp,1
add adrl,temp
ldi temp,0
adc adrh,temp
rcall memReadByte
mov oph,temp
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|LD dst,src|------|Load |dst=src |
;
;
do_op_rmem8:
mov adrl,opl
mov adrh,oph
rcall memReadByte
mov opl,temp
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|DAA |***P-*|Decimal Adjust Acc. | |
;|----------|SZHP C|---------- 8080 ----------------------------|
;
; Not yet checked
; Description (http://www.z80.info/z80syntx.htm#DAA):
; This instruction conditionally adjusts the accumulator for BCD addition
; and subtraction operations. For addition (ADD, ADC, INC) or subtraction
; (SUB, SBC, DEC, NEC), the following table indicates the operation performed:
;
; -------------------------------------------------------------------------------
; | | C Flag | HEX value in | H Flag | HEX value in | Number | C flag|
; | Operation| Before | upper digit | Before | lower digit | added | After |
; | | DAA | (bit 7-4) | DAA | (bit 3-0) | to byte | DAA |
; |-----------------------------------------------------------------------------|
; | | 0 | 0-9 | 0 | 0-9 | 00 | 0 |
; | ADD | 0 | 0-8 | 0 | A-F | 06 | 0 |
; | | 0 | 0-9 | 1 | 0-3 | 06 | 0 |
; | ADC | 0 | A-F | 0 | 0-9 | 60 | 1 |
; | | 0 | 9-F | 0 | A-F | 66 | 1 |
; | INC | 0 | A-F | 1 | 0-3 | 66 | 1 |
; | | 1 | 0-2 | 0 | 0-9 | 60 | 1 |
; | | 1 | 0-2 | 0 | A-F | 66 | 1 |
; | | 1 | 0-3 | 1 | 0-3 | 66 | 1 |
; |-----------------------------------------------------------------------------|
; | SUB | 0 | 0-9 | 0 | 0-9 | 00 | 0 |
; | SBC | 0 | 0-8 | 1 | 6-F | FA | 0 |
; | DEC | 1 | 7-F | 0 | 0-9 | A0 | 1 |
; | NEG | 1 | 6-F | 1 | 6-F | 9A | 1 |
; |-----------------------------------------------------------------------------|
;
; Flags:
; C: See instruction.
; N: Unaffected.
; P/V: Set if Acc. is even parity after operation, reset otherwise.
; H: See instruction.
; Z: Set if Acc. is Zero after operation, reset otherwise.
; S: Set if most significant bit of Acc. is 1 after operation, reset otherwise.
#if 1
do_op_da:
ldi oph,0 ; what to add
sbrc z_flags,ZFL_H ; if H-Flag
rjmp op_da_06
mov temp,opl
andi temp,0x0f ; ... or lower digit > 9
cpi temp,0x0a
brlo op_da_06n
op_da_06:
ori oph,0x06
op_da_06n:
sbrc z_flags,(1< 9
brlo do_op_da_h ;
ori temp2,0x06 ; add 6 to lower digit
do_op_da_h: ;
sbrc z_flags,ZFL_H ; ... or H-Flag
ori temp2,0x06 ;
add opl,temp2 ;
ldi temp2,0 ;
mov temp,opl ;
andi temp,0xf0 ;
cpi temp,0xa0 ;
brlo do_op_da_c ;
ori temp2,0x60 ;
do_op_da_c: ; else sub-op
sbrc z_flags,ZFL_C ;
ori temp2,0x60 ;
andi z_flags, ~( (1<HL |
;|EX DE,HL |------|Exchange |DE<->HL |
;
;
do_op_exhl:
mov temp,z_h
mov z_h,oph
mov oph,temp
mov temp,z_l
mov z_l,opl
mov opl,temp
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;
; TODO: Implement IFF1, IFF2
do_op_di:
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;
; TODO: Implement IFF1, IFF2
do_op_ei:
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|CALL cc,nn|------|Conditional Call |If cc CALL |
;|JP cc,nn |------|Conditional Jump |If cc JP |
;|RET cc |------|Conditional Return |If cc RET |
;
;
do_op_ifnz:
sbrs z_flags, ZFL_Z
ret
ldi insdech, 0
ldi insdecl, 0
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|CALL cc,nn|------|Conditional Call |If cc CALL |
;|JP cc,nn |------|Conditional Jump |If cc JP |
;|RET cc |------|Conditional Return |If cc RET |
;
;
do_op_ifz:
sbrc z_flags, ZFL_Z
ret
ldi insdech, 0
ldi insdecl, 0
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|CALL cc,nn|------|Conditional Call |If cc CALL |
;|JP cc,nn |------|Conditional Jump |If cc JP |
;|RET cc |------|Conditional Return |If cc RET |
;
;
do_op_ifnc:
sbrs z_flags, ZFL_C
ret
ldi insdech, 0
ldi insdecl, 0
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|CALL cc,nn|------|Conditional Call |If cc CALL |
;|JP cc,nn |------|Conditional Jump |If cc JP |
;|RET cc |------|Conditional Return |If cc RET |
;
;
do_op_ifc:
sbrc z_flags, ZFL_C
ret
ldi insdech, 0
ldi insdecl, 0
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|CALL cc,nn|------|Conditional Call |If cc CALL |
;|JP cc,nn |------|Conditional Jump |If cc JP |
;|RET cc |------|Conditional Return |If cc RET |
;
;
do_op_ifpo:
sbrs z_flags, ZFL_P
ret
ldi insdech, 0
ldi insdecl, 0
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|CALL cc,nn|------|Conditional Call |If cc CALL |
;|JP cc,nn |------|Conditional Jump |If cc JP |
;|RET cc |------|Conditional Return |If cc RET |
;
;
do_op_ifpe:
sbrc z_flags, ZFL_P
ret
ldi insdech, 0
ldi insdecl, 0
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|CALL cc,nn|------|Conditional Call |If cc CALL |
;|JP cc,nn |------|Conditional Jump |If cc JP |
;|RET cc |------|Conditional Return |If cc RET |
;
;
do_op_ifp: ;sign positive, aka s=0
sbrs z_flags, ZFL_S
ret
ldi insdech,0
ldi insdecl,0
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|CALL cc,nn|------|Conditional Call |If cc CALL |
;|JP cc,nn |------|Conditional Jump |If cc JP |
;|RET cc |------|Conditional Return |If cc RET |
;
;
do_op_ifm: ;sign negative, aka s=1
sbrc z_flags, ZFL_S
ret
ldi insdech, 0
ldi insdecl, 0
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|OUT [n],A |------|Output |[n]=A |
;
;
;Interface with peripherials goes here :)
do_op_outa: ; out (opl),a
.if PORT_DEBUG
rcall printstr
.db 13,"Port write: ",0
mov temp,z_a
rcall printhex
rcall printstr
.db " -> (",0
mov temp,opl
rcall printhex
rcall printstr
.db ")",13,0
.endif
mov temp,z_a
mov temp2,opl
rcall portWrite
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|IN A,[n] |------|Input |A=[n] |
;
;
do_op_in: ; in a,(opl)
.if PORT_DEBUG
rcall printstr
.db 13,"Port read: (",0
mov temp,opl
rcall printhex
rcall printstr
.db ") -> ",0
.endif
mov temp2,opl
rcall portRead
mov opl,temp
.if PORT_DEBUG
rcall printhex
rcall printstr
.db 13,0
.endif
ret
;----------------------------------------------------------------
#if 0
do_op_calcparity:
ldi temp2,1
sbrc parityb,0
inc temp2
sbrc parityb,1
inc temp2
sbrc parityb,2
inc temp2
sbrc parityb,3
inc temp2
sbrc parityb,4
inc temp2
sbrc parityb,5
inc temp2
sbrc parityb,6
inc temp2
sbrc parityb,7
inc temp2
andi temp2,1
ret
#endif
;----------------------------------------------------------------
do_op_inv:
rcall printstr
.db "Invalid opcode @ PC=",0,0
mov temp,z_pch
rcall printhex
mov temp,z_pcl
rcall printhex
;----------------------------------------------------------------
haltinv:
rjmp haltinv
;----------------------------------------------------------------
; Lookup table, stolen from z80ex, Z80 emulation library.
; http://z80ex.sourceforge.net/
; The S, Z, 5 and 3 bits and the parity of the lookup value
sz53p_tab:
.db 0x44,0x00,0x00,0x04,0x00,0x04,0x04,0x00
.db 0x08,0x0c,0x0c,0x08,0x0c,0x08,0x08,0x0c
.db 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04
.db 0x0c,0x08,0x08,0x0c,0x08,0x0c,0x0c,0x08
.db 0x20,0x24,0x24,0x20,0x24,0x20,0x20,0x24
.db 0x2c,0x28,0x28,0x2c,0x28,0x2c,0x2c,0x28
.db 0x24,0x20,0x20,0x24,0x20,0x24,0x24,0x20
.db 0x28,0x2c,0x2c,0x28,0x2c,0x28,0x28,0x2c
.db 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04
.db 0x0c,0x08,0x08,0x0c,0x08,0x0c,0x0c,0x08
.db 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00
.db 0x08,0x0c,0x0c,0x08,0x0c,0x08,0x08,0x0c
.db 0x24,0x20,0x20,0x24,0x20,0x24,0x24,0x20
.db 0x28,0x2c,0x2c,0x28,0x2c,0x28,0x28,0x2c
.db 0x20,0x24,0x24,0x20,0x24,0x20,0x20,0x24
.db 0x2c,0x28,0x28,0x2c,0x28,0x2c,0x2c,0x28
.db 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84
.db 0x8c,0x88,0x88,0x8c,0x88,0x8c,0x8c,0x88
.db 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80
.db 0x88,0x8c,0x8c,0x88,0x8c,0x88,0x88,0x8c
.db 0xa4,0xa0,0xa0,0xa4,0xa0,0xa4,0xa4,0xa0
.db 0xa8,0xac,0xac,0xa8,0xac,0xa8,0xa8,0xac
.db 0xa0,0xa4,0xa4,0xa0,0xa4,0xa0,0xa0,0xa4
.db 0xac,0xa8,0xa8,0xac,0xa8,0xac,0xac,0xa8
.db 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80
.db 0x88,0x8c,0x8c,0x88,0x8c,0x88,0x88,0x8c
.db 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84
.db 0x8c,0x88,0x88,0x8c,0x88,0x8c,0x8c,0x88
.db 0xa0,0xa4,0xa4,0xa0,0xa4,0xa0,0xa0,0xa4
.db 0xac,0xa8,0xa8,0xac,0xa8,0xac,0xac,0xa8
.db 0xa4,0xa0,0xa0,0xa4,0xa0,0xa4,0xa4,0xa0
.db 0xa8,0xac,0xac,0xa8,0xac,0xa8,0xa8,0xac
; ----------------------- Opcode decoding -------------------------
; Lookup table for Z80 opcodes. Translates the first byte of the instruction word into three
; operations: fetch, do something, store.
; The table is made of 256 words. These 16-bit words consist of
; the fetch operation (bit 0-4), the processing operation (bit 10-16) and the store
; operation (bit 5-9).
inst_table:
.dw (FETCH_NOP | OP_NOP | STORE_NOP) ; 00 NOP
.dw (FETCH_DIR16| OP_NOP | STORE_BC ) ; 01 nn nn LD BC,nn
.dw (FETCH_A | OP_NOP | STORE_MBC ) ; 02 LD (BC),A
.dw (FETCH_BC | OP_INC16 | STORE_BC ) ; 03 INC BC
.dw (FETCH_B | OP_INC | STORE_B ) ; 04 INC B
.dw (FETCH_B | OP_DEC | STORE_B ) ; 05 DEC B
.dw (FETCH_DIR8 | OP_NOP | STORE_B ) ; 06 nn LD B,n
.dw (FETCH_A | OP_RLC | STORE_A ) ; 07 RLCA
.dw (FETCH_NOP | OP_INV | STORE_NOP) ; 08 EX AF,AF' (Z80)
.dw (FETCH_BC | OP_ADDHL | STORE_HL ) ; 09 ADD HL,BC
.dw (FETCH_MBC | OP_NOP | STORE_A ) ; 0A LD A,(BC)
.dw (FETCH_BC | OP_DEC16 | STORE_BC ) ; 0B DEC BC
.dw (FETCH_C | OP_INC | STORE_C ) ; 0C INC C
.dw (FETCH_C | OP_DEC | STORE_C ) ; 0D DEC C
.dw (FETCH_DIR8 | OP_NOP | STORE_C ) ; 0E nn LD C,n
.dw (FETCH_A | OP_RRC | STORE_A ) ; 0F RRCA
.dw (FETCH_NOP | OP_INV | STORE_NOP) ; 10 oo DJNZ o (Z80)
.dw (FETCH_DIR16| OP_NOP | STORE_DE ) ; 11 nn nn LD DE,nn
.dw (FETCH_A | OP_NOP | STORE_MDE) ; 12 LD (DE),A
.dw (FETCH_DE | OP_INC16 | STORE_DE ) ; 13 INC DE
.dw (FETCH_D | OP_INC | STORE_D ) ; 14 INC D
.dw (FETCH_D | OP_DEC | STORE_D ) ; 15 DEC D
.dw (FETCH_DIR8 | OP_NOP | STORE_D ) ; 16 nn LD D,n
.dw (FETCH_A | OP_RL | STORE_A ) ; 17 RLA
.dw (FETCH_NOP | OP_INV | STORE_NOP) ; 18 oo JR o (Z80)
.dw (FETCH_DE | OP_ADDHL | STORE_HL ) ; 19 ADD HL,DE
.dw (FETCH_MDE | OP_NOP | STORE_A ) ; 1A LD A,(DE)
.dw (FETCH_DE | OP_DEC16 | STORE_DE ) ; 1B DEC DE
.dw (FETCH_E | OP_INC | STORE_E ) ; 1C INC E
.dw (FETCH_E | OP_DEC | STORE_E ) ; 1D DEC E
.dw (FETCH_DIR8 | OP_NOP | STORE_E ) ; 1E nn LD E,n
.dw (FETCH_A | OP_RR | STORE_A ) ; 1F RRA
.dw (FETCH_NOP | OP_INV | STORE_NOP) ; 20 oo JR NZ,o (Z80)
.dw (FETCH_DIR16| OP_NOP | STORE_HL ) ; 21 nn nn LD HL,nn
.dw (FETCH_DIR16| OP_STHL | STORE_NOP) ; 22 nn nn LD (nn),HL
.dw (FETCH_HL | OP_INC16 | STORE_HL ) ; 23 INC HL
.dw (FETCH_H | OP_INC | STORE_H ) ; 24 INC H
.dw (FETCH_H | OP_DEC | STORE_H ) ; 25 DEC H
.dw (FETCH_DIR8 | OP_NOP | STORE_H ) ; 26 nn LD H,n
.dw (FETCH_A | OP_DA | STORE_A ) ; 27 DAA
.dw (FETCH_NOP | OP_INV | STORE_NOP) ; 28 oo JR Z,o (Z80)
.dw (FETCH_HL | OP_ADDHL | STORE_HL ) ; 29 ADD HL,HL
.dw (FETCH_DIR16| OP_RMEM16 | STORE_HL ) ; 2A nn nn LD HL,(nn)
.dw (FETCH_HL | OP_DEC16 | STORE_HL ) ; 2B DEC HL
.dw (FETCH_L | OP_INC | STORE_L ) ; 2C INC L
.dw (FETCH_L | OP_DEC | STORE_L ) ; 2D DEC L
.dw (FETCH_DIR8 | OP_NOP | STORE_L ) ; 2E nn LD L,n
.dw (FETCH_A | OP_CPL | STORE_A ) ; 2F CPL
.dw (FETCH_NOP | OP_INV | STORE_NOP) ; 30 oo JR NC,o (Z80)
.dw (FETCH_DIR16| OP_NOP | STORE_SP ) ; 31 nn nn LD SP,nn
.dw (FETCH_DIR16| OP_NOP | STORE_AM ) ; 32 nn nn LD (nn),A
.dw (FETCH_SP | OP_INC16 | STORE_SP ) ; 33 INC SP
.dw (FETCH_MHL | OP_INC | STORE_MHL) ; 34 INC (HL)
.dw (FETCH_MHL | OP_DEC | STORE_MHL) ; 35 DEC (HL)
.dw (FETCH_DIR8 | OP_NOP | STORE_MHL) ; 36 nn LD (HL),n
.dw (FETCH_NOP | OP_SCF | STORE_NOP) ; 37 SCF
.dw (FETCH_NOP | OP_INV | STORE_NOP) ; 38 oo JR C,o (Z80)
.dw (FETCH_SP | OP_ADDHL | STORE_HL ) ; 39 ADD HL,SP
.dw (FETCH_DIR16| OP_RMEM8 | STORE_A ) ; 3A nn nn LD A,(nn)
.dw (FETCH_SP | OP_DEC16 | STORE_SP ) ; 3B DEC SP
.dw (FETCH_A | OP_INC | STORE_A ) ; 3C INC A
.dw (FETCH_A | OP_DEC | STORE_A ) ; 3D DEC A
.dw (FETCH_DIR8 | OP_NOP | STORE_A ) ; 3E nn LD A,n
.dw (FETCH_NOP | OP_CCF | STORE_NOP) ; 3F CCF (Complement Carry Flag, gvd)
.dw (FETCH_B | OP_NOP | STORE_B ) ; 40 LD B,r
.dw (FETCH_C | OP_NOP | STORE_B ) ; 41 LD B,r
.dw (FETCH_D | OP_NOP | STORE_B ) ; 42 LD B,r
.dw (FETCH_E | OP_NOP | STORE_B ) ; 43 LD B,r
.dw (FETCH_H | OP_NOP | STORE_B ) ; 44 LD B,r
.dw (FETCH_L | OP_NOP | STORE_B ) ; 45 LD B,r
.dw (FETCH_MHL | OP_NOP | STORE_B ) ; 46 LD B,r
.dw (FETCH_A | OP_NOP | STORE_B ) ; 47 LD B,r
.dw (FETCH_B | OP_NOP | STORE_C ) ; 48 LD C,r
.dw (FETCH_C | OP_NOP | STORE_C ) ; 49 LD C,r
.dw (FETCH_D | OP_NOP | STORE_C ) ; 4A LD C,r
.dw (FETCH_E | OP_NOP | STORE_C ) ; 4B LD C,r
.dw (FETCH_H | OP_NOP | STORE_C ) ; 4C LD C,r
.dw (FETCH_L | OP_NOP | STORE_C ) ; 4D LD C,r
.dw (FETCH_MHL | OP_NOP | STORE_C ) ; 4E LD C,r
.dw (FETCH_A | OP_NOP | STORE_C ) ; 4F LD C,r
.dw (FETCH_B | OP_NOP | STORE_D ) ; 50 LD D,r
.dw (FETCH_C | OP_NOP | STORE_D ) ; 51 LD D,r
.dw (FETCH_D | OP_NOP | STORE_D ) ; 52 LD D,r
.dw (FETCH_E | OP_NOP | STORE_D ) ; 53 LD D,r
.dw (FETCH_H | OP_NOP | STORE_D ) ; 54 LD D,r
.dw (FETCH_L | OP_NOP | STORE_D ) ; 55 LD D,r
.dw (FETCH_MHL | OP_NOP | STORE_D ) ; 56 LD D,r
.dw (FETCH_A | OP_NOP | STORE_D ) ; 57 LD D,r
.dw (FETCH_B | OP_NOP | STORE_E ) ; 58 LD E,r
.dw (FETCH_C | OP_NOP | STORE_E ) ; 59 LD E,r
.dw (FETCH_D | OP_NOP | STORE_E ) ; 5A LD E,r
.dw (FETCH_E | OP_NOP | STORE_E ) ; 5B LD E,r
.dw (FETCH_H | OP_NOP | STORE_E ) ; 5C LD E,r
.dw (FETCH_L | OP_NOP | STORE_E ) ; 5D LD E,r
.dw (FETCH_MHL | OP_NOP | STORE_E ) ; 5E LD E,r
.dw (FETCH_A | OP_NOP | STORE_E ) ; 5F LD E,r
.dw (FETCH_B | OP_NOP | STORE_H ) ; 60 LD H,r
.dw (FETCH_C | OP_NOP | STORE_H ) ; 61 LD H,r
.dw (FETCH_D | OP_NOP | STORE_H ) ; 62 LD H,r
.dw (FETCH_E | OP_NOP | STORE_H ) ; 63 LD H,r
.dw (FETCH_H | OP_NOP | STORE_H ) ; 64 LD H,r
.dw (FETCH_L | OP_NOP | STORE_H ) ; 65 LD H,r
.dw (FETCH_MHL | OP_NOP | STORE_H ) ; 66 LD H,r
.dw (FETCH_A | OP_NOP | STORE_H ) ; 67 LD H,r
.dw (FETCH_B | OP_NOP | STORE_L ) ; 68 LD L,r
.dw (FETCH_C | OP_NOP | STORE_L ) ; 69 LD L,r
.dw (FETCH_D | OP_NOP | STORE_L ) ; 6A LD L,r
.dw (FETCH_E | OP_NOP | STORE_L ) ; 6B LD L,r
.dw (FETCH_H | OP_NOP | STORE_L ) ; 6C LD L,r
.dw (FETCH_L | OP_NOP | STORE_L ) ; 6D LD L,r
.dw (FETCH_MHL | OP_NOP | STORE_L ) ; 6E LD L,r
.dw (FETCH_A | OP_NOP | STORE_L ) ; 6F LD L,r
.dw (FETCH_B | OP_NOP | STORE_MHL) ; 70 LD (HL),r
.dw (FETCH_C | OP_NOP | STORE_MHL) ; 71 LD (HL),r
.dw (FETCH_D | OP_NOP | STORE_MHL) ; 72 LD (HL),r
.dw (FETCH_E | OP_NOP | STORE_MHL) ; 73 LD (HL),r
.dw (FETCH_H | OP_NOP | STORE_MHL) ; 74 LD (HL),r
.dw (FETCH_L | OP_NOP | STORE_MHL) ; 75 LD (HL),r
.dw (FETCH_NOP | OP_NOP | STORE_NOP) ; 76 HALT
.dw (FETCH_A | OP_NOP | STORE_MHL) ; 77 LD (HL),r
.dw (FETCH_B | OP_NOP | STORE_A ) ; 78 LD A,r
.dw (FETCH_C | OP_NOP | STORE_A ) ; 79 LD A,r
.dw (FETCH_D | OP_NOP | STORE_A ) ; 7A LD A,r
.dw (FETCH_E | OP_NOP | STORE_A ) ; 7B LD A,r
.dw (FETCH_H | OP_NOP | STORE_A ) ; 7C LD A,r
.dw (FETCH_L | OP_NOP | STORE_A ) ; 7D LD A,r
.dw (FETCH_MHL | OP_NOP | STORE_A ) ; 7E LD A,r
.dw (FETCH_A | OP_NOP | STORE_A ) ; 7F LD A,r
.dw (FETCH_B | OP_ADDA | STORE_A ) ; 80 ADD A,r
.dw (FETCH_C | OP_ADDA | STORE_A ) ; 81 ADD A,r
.dw (FETCH_D | OP_ADDA | STORE_A ) ; 82 ADD A,r
.dw (FETCH_E | OP_ADDA | STORE_A ) ; 83 ADD A,r
.dw (FETCH_H | OP_ADDA | STORE_A ) ; 84 ADD A,r
.dw (FETCH_L | OP_ADDA | STORE_A ) ; 85 ADD A,r
.dw (FETCH_MHL | OP_ADDA | STORE_A ) ; 86 ADD A,r
.dw (FETCH_A | OP_ADDA | STORE_A ) ; 87 ADD A,r
.dw (FETCH_B | OP_ADCA | STORE_A ) ; 88 ADC A,r
.dw (FETCH_C | OP_ADCA | STORE_A ) ; 89 ADC A,r
.dw (FETCH_D | OP_ADCA | STORE_A ) ; 8A ADC A,r
.dw (FETCH_E | OP_ADCA | STORE_A ) ; 8B ADC A,r
.dw (FETCH_H | OP_ADCA | STORE_A ) ; 8C ADC A,r
.dw (FETCH_L | OP_ADCA | STORE_A ) ; 8D ADC A,r
.dw (FETCH_MHL | OP_ADCA | STORE_A ) ; 8E ADC A,r
.dw (FETCH_A | OP_ADCA | STORE_A ) ; 8F ADC A,r
.dw (FETCH_B | OP_SUBFA | STORE_A ) ; 90 SUB A,r
.dw (FETCH_C | OP_SUBFA | STORE_A ) ; 91 SUB A,r
.dw (FETCH_D | OP_SUBFA | STORE_A ) ; 92 SUB A,r
.dw (FETCH_E | OP_SUBFA | STORE_A ) ; 93 SUB A,r
.dw (FETCH_H | OP_SUBFA | STORE_A ) ; 94 SUB A,r
.dw (FETCH_L | OP_SUBFA | STORE_A ) ; 95 SUB A,r
.dw (FETCH_MHL | OP_SUBFA | STORE_A ) ; 96 SUB A,r
.dw (FETCH_A | OP_SUBFA | STORE_A ) ; 97 SUB A,r
.dw (FETCH_B | OP_SBCFA | STORE_A ) ; 98 SBC A,r
.dw (FETCH_C | OP_SBCFA | STORE_A ) ; 99 SBC A,r
.dw (FETCH_D | OP_SBCFA | STORE_A ) ; 9A SBC A,r
.dw (FETCH_E | OP_SBCFA | STORE_A ) ; 9B SBC A,r
.dw (FETCH_H | OP_SBCFA | STORE_A ) ; 9C SBC A,r
.dw (FETCH_L | OP_SBCFA | STORE_A ) ; 9D SBC A,r
.dw (FETCH_MHL | OP_SBCFA | STORE_A ) ; 9E SBC A,r
.dw (FETCH_A | OP_SBCFA | STORE_A ) ; 9F SBC A,r
.dw (FETCH_B | OP_ANDA | STORE_A ) ; A0 AND A,r
.dw (FETCH_C | OP_ANDA | STORE_A ) ; A1 AND A,r
.dw (FETCH_D | OP_ANDA | STORE_A ) ; A2 AND A,r
.dw (FETCH_E | OP_ANDA | STORE_A ) ; A3 AND A,r
.dw (FETCH_H | OP_ANDA | STORE_A ) ; A4 AND A,r
.dw (FETCH_L | OP_ANDA | STORE_A ) ; A5 AND A,r
.dw (FETCH_MHL | OP_ANDA | STORE_A ) ; A6 AND A,r
.dw (FETCH_A | OP_ANDA | STORE_A ) ; A7 AND A,r
.dw (FETCH_B | OP_XORA | STORE_A ) ; A8 XOR A,r
.dw (FETCH_C | OP_XORA | STORE_A ) ; A9 XOR A,r
.dw (FETCH_D | OP_XORA | STORE_A ) ; AA XOR A,r
.dw (FETCH_E | OP_XORA | STORE_A ) ; AB XOR A,r
.dw (FETCH_H | OP_XORA | STORE_A ) ; AC XOR A,r
.dw (FETCH_L | OP_XORA | STORE_A ) ; AD XOR A,r
.dw (FETCH_MHL | OP_XORA | STORE_A ) ; AE XOR A,r
.dw (FETCH_A | OP_XORA | STORE_A ) ; AF XOR A,r
.dw (FETCH_B | OP_ORA | STORE_A ) ; B0 OR A,r
.dw (FETCH_C | OP_ORA | STORE_A ) ; B1 OR A,r
.dw (FETCH_D | OP_ORA | STORE_A ) ; B2 OR A,r
.dw (FETCH_E | OP_ORA | STORE_A ) ; B3 OR A,r
.dw (FETCH_H | OP_ORA | STORE_A ) ; B4 OR A,r
.dw (FETCH_L | OP_ORA | STORE_A ) ; B5 OR A,r
.dw (FETCH_MHL | OP_ORA | STORE_A ) ; B6 OR A,r
.dw (FETCH_A | OP_ORA | STORE_A ) ; B7 OR A,r
.dw (FETCH_B | OP_SUBFA | STORE_NOP) ; B8 CP A,r
.dw (FETCH_C | OP_SUBFA | STORE_NOP) ; B9 CP A,r
.dw (FETCH_D | OP_SUBFA | STORE_NOP) ; BA CP A,r
.dw (FETCH_E | OP_SUBFA | STORE_NOP) ; BB CP A,r
.dw (FETCH_H | OP_SUBFA | STORE_NOP) ; BC CP A,r
.dw (FETCH_L | OP_SUBFA | STORE_NOP) ; BD CP A,r
.dw (FETCH_MHL | OP_SUBFA | STORE_NOP) ; BE CP A,r
.dw (FETCH_A | OP_SUBFA | STORE_NOP) ; BF CP A,r
.dw (FETCH_NOP | OP_IFNZ | STORE_RET) ; C0 RET NZ
.dw (FETCH_NOP | OP_POP16 | STORE_BC ) ; C1 POP BC
.dw (FETCH_DIR16| OP_IFNZ | STORE_PC ) ; C2 nn nn JP NZ,nn
.dw (FETCH_DIR16| OP_NOP | STORE_PC ) ; C3 nn nn JP nn
.dw (FETCH_DIR16| OP_IFNZ | STORE_CALL) ; C4 nn nn CALL NZ,nn
.dw (FETCH_BC | OP_PUSH16 | STORE_NOP) ; C5 PUSH BC
.dw (FETCH_DIR8 | OP_ADDA | STORE_A ) ; C6 nn ADD A,n
.dw (FETCH_RST | OP_NOP | STORE_CALL) ; C7 RST 0
.dw (FETCH_NOP | OP_IFZ | STORE_RET) ; C8 RET Z
.dw (FETCH_NOP | OP_NOP | STORE_RET) ; C9 RET
.dw (FETCH_DIR16| OP_IFZ | STORE_PC ) ; CA nn nn JP Z,nn
.dw (FETCH_NOP | OP_INV | STORE_NOP) ; CB (Z80 specific)
.dw (FETCH_DIR16| OP_IFZ | STORE_CALL) ; CC nn nn CALL Z,nn
.dw (FETCH_DIR16| OP_NOP | STORE_CALL) ; CD nn nn CALL nn
.dw (FETCH_DIR8 | OP_ADCA | STORE_A ) ; CE nn ADC A,n
.dw (FETCH_RST | OP_NOP | STORE_CALL) ; CF RST 8H
.dw (FETCH_NOP | OP_IFNC | STORE_RET) ; D0 RET NC
.dw (FETCH_NOP | OP_POP16 | STORE_DE ) ; D1 POP DE
.dw (FETCH_DIR16| OP_IFNC | STORE_PC ) ; D2 nn nn JP NC,nn
.dw (FETCH_DIR8 | OP_OUTA | STORE_NOP) ; D3 nn OUT (n),A
.dw (FETCH_DIR16| OP_IFNC | STORE_CALL) ; D4 nn nn CALL NC,nn
.dw (FETCH_DE | OP_PUSH16 | STORE_NOP) ; D5 PUSH DE
.dw (FETCH_DIR8 | OP_SUBFA | STORE_A ) ; D6 nn SUB n
.dw (FETCH_RST | OP_NOP | STORE_CALL) ; D7 RST 10H
.dw (FETCH_NOP | OP_IFC | STORE_RET) ; D8 RET C
.dw (FETCH_NOP | OP_INV | STORE_NOP) ; D9 EXX (Z80)
.dw (FETCH_DIR16| OP_IFC | STORE_PC ) ; DA nn nn JP C,nn
.dw (FETCH_DIR8 | OP_IN | STORE_A ) ; DB nn IN A,(n)
.dw (FETCH_DIR16| OP_IFC | STORE_CALL) ; DC nn nn CALL C,nn
.dw (FETCH_NOP | OP_INV | STORE_NOP) ; DD (Z80)
.dw (FETCH_DIR8 | OP_SBCFA | STORE_A ) ; DE nn SBC A,n
.dw (FETCH_RST | OP_NOP | STORE_CALL) ; DF RST 18H
.dw (FETCH_NOP | OP_IFPO | STORE_RET) ; E0 RET PO
.dw (FETCH_NOP | OP_POP16 | STORE_HL ) ; E1 POP HL
.dw (FETCH_DIR16| OP_IFPO | STORE_PC ) ; E2 nn nn JP PO,nn
.dw (FETCH_MSP | OP_EXHL | STORE_MSP) ; E3 EX (SP),HL
.dw (FETCH_DIR16| OP_IFPO | STORE_CALL) ; E4 nn nn CALL PO,nn
.dw (FETCH_HL | OP_PUSH16 | STORE_NOP) ; E5 PUSH HL
.dw (FETCH_DIR8 | OP_ANDA | STORE_A ) ; E6 nn AND n
.dw (FETCH_RST | OP_NOP | STORE_CALL) ; E7 RST 20H
.dw (FETCH_NOP | OP_IFPE | STORE_RET) ; E8 RET PE
.dw (FETCH_HL | OP_NOP | STORE_PC ) ; E9 JP (HL)
.dw (FETCH_DIR16| OP_IFPE | STORE_PC ) ; EA nn nn JP PE,nn
.dw (FETCH_DE | OP_EXHL | STORE_DE ) ; EB EX DE,HL
.dw (FETCH_DIR16| OP_IFPE | STORE_CALL) ; EC nn nn CALL PE,nn
.dw (FETCH_NOP | OP_INV | STORE_NOP) ; ED (Z80 specific)
.dw (FETCH_DIR8 | OP_XORA | STORE_A ) ; EE nn XOR n
.dw (FETCH_RST | OP_NOP | STORE_CALL) ; EF RST 28H
.dw (FETCH_NOP | OP_IFP | STORE_RET) ; F0 RET P
.dw (FETCH_NOP | OP_POP16 | STORE_AF ) ; F1 POP AF
.dw (FETCH_DIR16| OP_IFP | STORE_PC ) ; F2 nn nn JP P,nn
.dw (FETCH_NOP | OP_DI | STORE_NOP) ; F3 DI
.dw (FETCH_DIR16| OP_IFP | STORE_CALL) ; F4 nn nn CALL P,nn
.dw (FETCH_AF | OP_PUSH16 | STORE_NOP) ; F5 PUSH AF
.dw (FETCH_DIR8 | OP_ORA | STORE_A ) ; F6 nn OR n
.dw (FETCH_RST | OP_NOP | STORE_CALL) ; F7 RST 30H
.dw (FETCH_NOP | OP_IFM | STORE_RET) ; F8 RET M
.dw (FETCH_HL | OP_NOP | STORE_SP ) ; F9 LD SP,HL
.dw (FETCH_DIR16| OP_IFM | STORE_PC ) ; FA nn nn JP M,nn
.dw (FETCH_NOP | OP_EI | STORE_NOP) ; FB EI
.dw (FETCH_DIR16| OP_IFM | STORE_CALL) ; FC nn nn CALL M,nn
.dw (FETCH_NOP | OP_INV | STORE_NOP) ; FD (Z80 specific)
.dw (FETCH_DIR8 | OP_SUBFA | STORE_NOP) ; FE nn CP n
.dw (FETCH_RST | OP_NOP | STORE_CALL) ; FF RST 38H
; vim:set ts=8 noet nowrap