; 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 P_AH = PORTD .equ P_A8 = PORTD .equ P_MMC_CS = PORTD ; ram_a[7..5] .equ RAM_AH_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 P_MMC_CS,mmc_cs ldi temp2,20 mmcInitLoop: mov temp,temp2 rcall mmcByte dec temp2 brne mmcInitLoop cbi P_MMC_CS,mmc_cs rcall mmcByteNoSend rcall mmcByteNoSend rcall mmcByteNoSend rcall mmcByteNoSend rcall mmcByteNoSend rcall mmcByteNoSend sbi P_MMC_CS,mmc_cs rcall mmcByteNoSend rcall mmcByteNoSend rcall mmcByteNoSend rcall mmcByteNoSend ;Send init command cbi P_MMC_CS,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 P_MMC_CS,mmc_cs rcall mmcByteNoSend ;Read OCR till card is ready ldi temp2,150 mmcInitOcrLoop: push temp2 cbi P_MMC_CS,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 P_MMC_CS,mmc_cs rcall mmcByteNoSend pop temp2 dec temp2 cpi temp2,0 brne mmcInitOcrLoop ldi temp,4 rjmp mmcWaitErr mmcInitOcrLoopDone: pop temp2 sbi P_MMC_CS,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 P_MMC_CS,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 P_MMC_CS,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 P_MMC_CS,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 P_MMC_CS,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,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