1 ; Z80 emulator with CP/M support. The Z80-specific instructions themselves actually aren't
2 ; implemented yet, making this more of an i8080 emulator.
4 ; Copyright (C) 2010 Sprite_tm
6 ; This program is free software: you can redistribute it and/or modify
7 ; it under the terms of the GNU General Public License as published by
8 ; the Free Software Foundation, either version 3 of the License, or
9 ; (at your option) any later version.
11 ; This program is distributed in the hope that it will be useful,
12 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ; GNU General Public License for more details.
16 ; You should have received a copy of the GNU General Public License
17 ; along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #elif defined atmega168
23 .include "m168def.inc"
24 #elif defined atmega328P
25 .include "m328Pdef.inc"
34 #ifndef DRAM_DQ_ORDER /* If this is set to 1, the portbits */
35 #define DRAM_DQ_ORDER 0 /* for DRAM D1 and WE are swapped. */
40 #define F_CPU 20000000 /* system clock in Hz; defaults to 20MHz */
43 #define BAUD 38400 /* console baud rate */
47 #define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) /* clever rounding */
49 #define RXBUFSIZE 64 /* USART recieve buffer size. Must be power of 2 */
51 #define REFR_RATE 64000 /* dram refresh rate in cycles/s. */
52 /* Most drams need 1/15.6µs. */
53 #define REFR_PRE 8 /* timer prescale factor */
54 #define REFR_CS 0x02 /* timer clock select for 1/8 */
55 #define REFR_CNT F_CPU / REFR_RATE / REFR_PRE
58 #if defined __ATmega8__
59 .equ refr_vect = OC2addr
61 .equ refr_vect = OC2Aaddr
64 #define DRAM_WORD_ACCESS 0 /* experimental */
66 #define EM_Z80 0 /* we don't have any z80 instructions yet */
95 .equ RAM_AH_MASK = (1<<ram_a8)|(1<<ram_a7)|(1<<ram_a6)|(1<<ram_a5)
96 .equ PD_OUTPUT_MASK = (1<<mmc_cs) | (1<<ram_oe) | RAM_AH_MASK
114 .equ RAM_AL_MASK = (1<<ram_a4)|(1<<ram_a3)|(1<<ram_a2)|(1<<ram_a1)|(1<<ram_a0)
115 .equ PB_OUTPUT_MASK = (1<<ram_ras) | RAM_AL_MASK
118 #if DRAM_DQ_ORDER == 1
133 .equ RAM_DQ_MASK = (1<<ram_d3)|(1<<ram_d2)|(1<<ram_d1)|(1<<ram_d0)
134 .equ PC_OUTPUT_MASK = (1<<ram_cas)|(1<<ram_w)
137 ;Flag bits in z_flags
145 ;Register definitions
183 ;Register definitions
222 #if defined __ATmega8__
228 .equ hostact = 7 ;host active flag
229 .equ hostwrt = 6 ;host written flag
230 .equ rsflag = 5 ;read sector flag
231 .equ readop = 4 ;1 if read operation
234 ; This is the base z80 port address for clock access
235 #define TIMERPORT 0x40
236 #define TIMER_CTL TIMERPORT
237 #define TIMER_MSECS TIMERPORT+1
238 #define TIMER_SECS TIMER_MSECS+2
240 #define starttimercmd 1
241 #define quitTimerCmd 2
242 #define printTimerCmd 15
249 rjmp start ; reset vector
251 rjmp refrint ; tim2cmpa
252 .org OC1Aaddr ; Timer/Counter1 Compare Match A
253 rjmp sysclockint ; 1ms system timer
255 rjmp rxint ; USART receive int.
259 .org INT_VECTORS_SIZE
262 ldi temp,low(RAMEND) ; top of memory
263 out SPL,temp ; init stack pointer
264 ldi temp,high(RAMEND) ; top of memory
265 out SPH,temp ; init stack pointer
269 #if defined __ATmega8__
272 ldi temp,(1<<WDCE) | (1<<WDE)
276 ldi temp,(1<<PUD) ;disable pullups
281 ldi temp,(1<<WDCE) | (1<<WDE)
285 ldi temp,(1<<PUD) ;disable pullups
290 ldi temp,PB_OUTPUT_MASK
292 ldi temp,PD_OUTPUT_MASK
294 ldi temp,PC_OUTPUT_MASK
306 sts rxcount,_0 ; reset receive buffer
311 #if defined __ATmega8__
312 ldi temp, (1<<TXEN) | (1<<RXEN) | (1<<RXCIE)
314 ldi temp, (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0)
316 ldi temp, HIGH(UBRR_VAL)
318 ldi temp, LOW(UBRR_VAL)
321 ldi temp, (1<<TXEN0) | (1<<RXEN0) | (1<<RXCIE0)
323 ldi temp, (1<<UCSZ01) | (1<<UCSZ00)
325 ldi temp, HIGH(UBRR_VAL)
327 ldi temp, LOW(UBRR_VAL)
331 ;Init timer2. Refresh-call should happen every (8ms/512)=312 cycles.
334 ldi temp,REFR_CNT*2 ; 2 cycles per int
336 ldi temp,(1<<WGM21) | REFR_CS ;CTC, clk/REFR_PRE
341 ldi temp,REFR_CNT ;=312 cycles
345 ldi temp, REFR_CS ;clk/REFR_PRE
352 ; Init clock/timer system
354 ldi zl,low(timer_base)
355 ldi zh,high(timer_base)
362 ; Init timer 1 as 1 ms system clock tick.
365 ldi temp,high(F_CPU/1000)
367 ldi temp,low(F_CPU/1000)
369 ldi temp,(1<<WGM12) | (1<<CS10) ;CTC, clk/1
375 ldi temp,high(F_CPU/1000)
377 ldi temp,low(F_CPU/1000)
379 ldi temp,(1<<WGM12) | (1<<CS10) ;CTC, clk/1
395 .db "CPM on an AVR, v1.0",13,0,0
399 .db "Initing mmc...",13,0
405 .db "Testing RAM: fill...",0,0
427 .db "reread...",13,0,0
459 ;Fill ram with cbs, which (for now) will trigger an invalid opcode error.
471 ;Load initial sector from MMC (512 bytes)
476 ;Save to Z80 RAM (only 128 bytes because that's retro)
489 cpi zl,low(hostbuf+128)
491 cpi zh,high(hostbuf+128)
493 rcall dsk_boot ;init (de)blocking buffer
504 .db 13,"Ok, CPU is live!",13,0,0
533 ; *** Stage 1: Fetch next opcode
556 ; *** Stage 2: Decode it using the ins_table.
557 ldi zh,high(inst_table*2)
578 ; *** Stage 3: Fetch operand. Use the fetch jumptable for this.
582 ldi zl,low(fetchjumps)
583 ldi zh,high(fetchjumps)
603 ; *** Stage 4: Execute operation :) Use the op jumptable for this.
628 ; *** Stage 5: Store operand. Use the store jumptable for this.
637 ldi zl,low(storejumps)
638 ldi zh,high(storejumps)
665 ; ----------------Virtual peripherial interface ------
667 ;The hw is modelled to make writing a CPM BIOS easier.
669 ;0 - Con status. Returns 0xFF if the UART has a byte, 0 otherwise.
670 ;1 - Console input, aka UDR.
673 ;16,17 - Track select
677 ;22 - Trigger - write 1 to read, 2 to write a sector using the above info;
678 ; 3 - 5, write to allocated/dirctory/unallocated
687 ;*****************************************************
688 ;* CP/M to host disk constants *
689 ;*****************************************************
690 .equ blksize = 1024 ;CP/M allocation size
691 .equ hostsize = 512 ;host disk sector size
692 ; .equ hostspt = 20 ;host disk sectors/trk
693 .equ hostblk = hostsize/128 ;CP/M sects/host buff
694 ; .equ CPMSPT = hostblk*hostspt;CP/M sectors/track
696 .equ SECMSK = hostblk-1 ;sector mask
697 .equ SECSHF = log2(hostblk) ;sector shift
699 ;*****************************************************
700 ;* BDOS constants on entry to write *
701 ;*****************************************************
702 .equ WRALL = 0 ;write to allocated
703 .equ WRDIR = 1 ;write to directory
704 .equ WRUAL = 2 ;write to unallocated
705 .equ WRTMSK= 3 ;write type mask
710 seekdsk: .byte 1 ;seek disk number
711 seektrk: .byte 2 ;seek track number
712 seeksec: .byte 1 ;seek sector number
714 hostdsk: .byte 1 ;host disk number
715 hostlba: .byte 2 ;host track number
717 unacnt: .byte 1 ;unalloc rec cnt
718 unadsk: .byte 1 ;last unalloc disk
719 unatrk: .byte 2 ;last unalloc track
720 unasec: .byte 1 ;last unalloc sector
722 erflag: .byte 1 ;error reporting
723 wrtype: .byte 1 ;write operation type
724 dmaadr: .byte 2 ;last dma address
725 hostbuf: .byte hostsize;host buffer (from/to SD-card)
730 ;Called with port in temp2. Should return value in temp.
737 cpi temp2,TIMER_MSECS
739 cpi temp2,TIMER_MSECS+6
747 ;Called with port in temp2 and value in temp.
769 cpi temp2,TIMER_MSECS+6
825 ;See what has to be done.
836 .db "DISK I/O: Invalid Function code: ",0
841 cbi flags,hostact ;host buffer inactive
842 sts unacnt,_0 ;clear unalloc count
846 sbis flags,hostwrt ;check for pending write
847 cbi flags,hostact ;clear host active flag
864 .db "Disk read: track ",0
884 sbi flags,readop ;read operation
885 sbi flags,rsflag ;must read data
886 ldi temp,WRUAL ;write type
887 sts wrtype,temp ;treat as unalloc
888 rjmp dsk_rwoper ;to perform the read
892 ;write the selected CP/M sector
895 sts wrtype,temp ;save write type
896 cbi flags,readop ;not a read operation
903 .db "Disk write: track ",0,0
927 cpi temp,WRUAL ;write unallocated?
928 brne dsk_chkuna ;check for unalloc
930 ; write to unallocated, set parameters
931 ldi temp,blksize/128 ;next unalloc recs
933 lds temp,seekdsk ;disk to seek
934 sts unadsk,temp ;unadsk = sekdsk
936 sts unatrk,temp ;unatrk = sectrk
938 sts unatrk+1,temp ;unatrk = sectrk
940 sts unasec,temp ;unasec = seksec
943 ;check for write to unallocated sector
944 lds temp,unacnt ;any unalloc remain?
946 breq dsk_alloc ;skip if not
948 ; more unallocated records remain
949 dec temp ;unacnt = unacnt-1
951 lds temp,seekdsk ;same disk?
953 cp temp,temp2 ;seekdsk = unadsk?
954 brne dsk_alloc ;skip if not
961 cp temp,temp3 ;seektrk = unatrk?
963 brne dsk_alloc ;skip if not
965 ; tracks are the same
966 lds temp,seeksec ;same sector?
968 cp temp,temp2 ;seeksec = unasec?
969 brne dsk_alloc ;skip if not
971 ; match, move to next sector for future ref
972 inc temp2 ;unasec = unasec+1
974 cpi temp2,CPMSPT ;end of track? (count CP/M sectors)
975 brlo dsk_noovf ;skip if no overflow
977 ; overflow to next track
978 sts unasec,_0 ;unasec = 0
981 subi temp, low(-1) ;unatrk = unatrk+1
987 cbi flags,rsflag ;rsflag = 0
988 rjmp dsk_rwoper ;to perform the write
991 ;not an unallocated record, requires pre-read
992 sts unacnt,_0 ;unacnt = 0
993 sbi flags,rsflag ;rsflag = 1
995 ;*****************************************************
996 ;* Common code for READ and WRITE follows *
997 ;*****************************************************
1000 ;enter here to perform the read/write
1001 sts erflag,_0 ;no errors (yet)
1003 ;Convert track/sector to an LBA address (in 128byte blocks)
1008 lds temp4,seektrk+1 ;
1014 add adrh,r0 ;adrh:adrl := sec + trk * SectorsPerTrack
1018 andi temp,SECMSK ;mask buffer number
1019 push temp ;save for later
1026 ;Convert from CP/M LBA blocks to host LBA blocks
1033 ;adrh:adrl = host block to seek
1034 ; active host sector?
1035 sbis flags,hostact ;host active?
1036 rjmp dsk_filhst ;fill host if not
1038 ; host buffer active, same as seek buffer?
1040 lds temp3,hostdsk ;same disk?
1041 cp temp,temp3 ;seekdsk = hostdsk?
1044 ; same disk, same block?
1052 ;proper disk, but not correct sector
1053 sbic flags,hostwrt ;host written?
1054 rcall dsk_writehost ;clear host buff
1057 ;may have to fill the host buffer
1063 sbic flags,rsflag ;need to read?
1064 rcall dsk_readhost ;yes, if 1
1065 cbi flags,hostwrt ;no pending write
1068 sbi flags,hostact ;host buffer active now
1070 ;copy data to or from buffer
1072 ldi zh,high(hostbuf)
1074 pop temp2 ;get buffer number (which part of hostbuf)
1076 add zl,r0 ;offset in hostbuf
1083 .db "; host buf adr: ",0,0
1094 ldi yl,128 ;length of move
1095 sbic flags,readop ;which way?
1096 rjmp dsk_rmove ;skip if read
1098 ; mark write operation
1099 sbi flags,hostwrt ;hostwrt = 1
1116 ; data has been moved to/from host buffer
1117 lds temp,wrtype ;write type
1118 cpi temp,WRDIR ;to directory?
1126 ret ;no further processing
1128 ; clear host buffer for directory write
1134 rcall dsk_writehost ;clear host buff
1135 cbi flags,hostwrt ;buffer written
1140 ;*****************************************************
1141 ;* WRITEhost performs the physical write to *
1142 ;* the host disk, READhost reads the physical *
1144 ;*****************************************************
1147 ;hostdsk = host disk #, hostlba = host block #.
1148 ;Write "hostsize" bytes from hostbuf and return
1149 ;error flag in erflag.
1150 ;Return erflag non-zero if error
1163 ;hostdsk = host disk #, hostlba = host block #.
1164 ;Read "hostsiz" bytes into hostbuf and return
1165 ;error flag in erflag.
1178 ;***************************************************************************
1180 ; ----------------- MMC/SD routines ------------------
1215 ;Wait till the mmc answers with the response in temp2, or till a timeout happens.
1222 brne mmcWaitResploopEnd
1226 rjmp mmcWaitResploop
1235 .db ": Error: MMC resp timeout!",13,0
1242 ;Init start: send 80 clocks with cs disabled
1246 ldi temp2,10 ; exactly 80 clocks
1268 ldi temp,0xff ;dummy
1270 ldi temp,0xff ;dummy
1284 ldi temp,0xff ;return byte
1287 ldi temp2,0 ;Error Code 0
1288 rcall mmcWaitResp ;Test on CMD0 is OK
1290 sbi P_MMC_CS,mmc_cs ;disable /CS
1294 ;Read OCR till card is ready
1295 ldi temp2,20 ;repeat counter
1299 cbi P_MMC_CS,mmc_cs ;enable /CS
1300 ldi temp,0xff ;dummy
1312 ; ldi temp,0x95 ;crc
1318 rcall mmcWaitResp ;wait until mmc-card send a byte <> 0xFF
1319 ;the first answer must be 0x01 (Idle-Mode)
1321 breq mmcInitOcrLoopDone ;second answer is 0x00 (Idle-Mode leave) CMD1 is OK
1323 sbi P_MMC_CS,mmc_cs ;disable /CS
1325 ; rcall mmcByteNoSend ;unnecessary
1333 brne mmcInitOcrLoop ;repeat
1340 sbi P_MMC_CS,mmc_cs ;disable /CS
1347 ;Call this with adrh:adrl = sector number
1348 ;16bit lba address means a max reach of 32M.
1355 ldi temp,0x51 ;cmd (read sector)
1370 ldi temp,0xff ;return byte
1381 ;Read sector to AVR RAM
1383 ldi zh,high(hostbuf)
1387 cpi zl,low(hostbuf+512)
1389 cpi zh,high(hostbuf+512)
1403 ;Call this with adrh:adrl = sector number
1404 ;16bit lba address means a max reach of 32M.
1412 ldi temp,0x58 ;cmd (write sector)
1427 ldi temp,0xff ;return byte
1438 ;Write sector from AVR RAM
1440 ldi zh,high(hostbuf)
1444 cpi zl,low(hostbuf+512)
1446 cpi zh,high(hostbuf+512)
1453 ;Status. Ignored for now.
1456 ;Wait till the mmc has written everything
1469 ;Set up wdt to time out after 1 sec.
1472 #if defined __ATmega8__
1475 ldi temp,(1<<WDCE) | (1<<WDE) | (110<<WDP0)
1480 ldi temp,(1<<WDCE) | (1<<WDE) | (110<<WDP0)
1486 ; ------------------ DRAM routines -------------
1488 ; DRAM_SETADDR val, low_and_mask, low_or_mask, high_and_mask, high_or_mask
1503 ori temp, @4 | (1<<mmc_cs)
1507 ;Loads the byte on address adrh:adrl into temp.
1508 ;must not alter adrh:adrl
1512 DRAM_SETADDR adrh, ~0,(1<<ram_ras), ~(1<<ram_a8), (1<<ram_oe)
1514 DRAM_SETADDR adrl, ~(1<<ram_ras),0, ~((1<<ram_oe)), (1<<ram_a8)
1517 in temp,P_DQ-2 ; PIN
1523 in temp2,P_DQ-2 ; PIN
1533 #if DRAM_WORD_ACCESS
1548 DRAM_SETADDR adrh, ~0,(1<<ram_ras), ~(1<<ram_a8),(1<<ram_oe)
1550 DRAM_SETADDR adrl, ~(1<<ram_ras),0, ~((1<<ram_oe)), (1<<ram_a8)
1553 in temp,P_DQ-2 ; PIN
1558 in temp2,P_DQ-2 ; PIN
1566 DRAM_SETADDR adrl, ~(1<<ram_ras),0, ~((1<<ram_oe)), (1<<ram_a8)
1569 in temp,P_DQ-2 ; PIN
1574 in temp2,P_DQ-2 ; PIN
1587 ;Writes the byte in temp to adrh:adrl
1588 ;must not alter adrh:adrl
1592 ldi temp2,RAM_DQ_MASK | (1<<ram_w) | (1<<ram_cas)
1596 andi temp,RAM_DQ_MASK & ~(1<<ram_w)
1597 ori temp,(1<<ram_cas)
1599 DRAM_SETADDR adrh, ~0,(1<<ram_ras), ~(1<<ram_a8),(1<<ram_oe)
1601 DRAM_SETADDR adrl, ~(1<<ram_ras),0, ~((1<<ram_a8)),(1<<ram_oe)
1608 andi temp2,RAM_DQ_MASK & ~(1<<ram_w)
1609 ori temp2,(1<<ram_cas)
1615 ldi temp,~RAM_DQ_MASK | (1<<ram_w) | (1<<ram_cas)
1621 #if DRAM_WORD_ACCESS
1636 ldi temp2,RAM_DQ_MASK | (1<<ram_w) | (1<<ram_cas)
1640 andi temp,RAM_DQ_MASK & ~(1<<ram_w)
1641 ori temp,(1<<ram_cas)
1644 DRAM_SETADDR adrh, ~0,(1<<ram_ras), ~(1<<ram_a8),(1<<ram_oe)
1646 DRAM_SETADDR adrl, ~(1<<ram_ras),0, ~((1<<ram_a8)),(1<<ram_oe)
1653 andi temp2,RAM_DQ_MASK & ~(1<<ram_w)
1654 ori temp2,(1<<ram_cas)
1663 andi temp,RAM_DQ_MASK & ~(1<<ram_w)
1664 ori temp,(1<<ram_cas)
1667 DRAM_SETADDR adrl, ~(1<<ram_ras),0, ~((1<<ram_a8)),(1<<ram_oe)
1674 andi temp2,RAM_DQ_MASK & ~(1<<ram_w)
1675 ori temp2,(1<<ram_cas)
1681 ldi temp,~RAM_DQ_MASK | (1<<ram_w) | (1<<ram_cas)
1688 ; ****************************************************************************
1690 ; refresh interupt; exec 2 cbr cycles
1693 cbi P_CAS,ram_cas ;2 1| 1|
1695 cbi P_RAS,ram_ras ;2 |0 1|
1699 sbi P_RAS,ram_ras ;2 |0 |0
1702 cbi P_RAS,ram_ras ;2 |0 1|
1704 sbi P_CAS,ram_cas ;2 |0 |0
1706 sbi P_RAS,ram_ras ;2 1| |0
1708 reti ;4 --> 21 cycles
1710 ; ****************************************************************************
1712 ; ------------- system timer 10ms ---------------
1722 ; don't change order here, clock put/get depends on it.
1723 cntms_out: ; register for ms
1725 utime_io: ; register for uptime.
1732 .equ timer_size = timer_top - timer_base
1734 .equ clkofs = cnt_1ms-cntms_out
1735 .equ timerofs = cnt_1ms-timer_ms
1756 ldi zl,high(1000) ;doesn't change flags
1789 sts delay_timer,temp
1791 lds temp,delay_timer
1800 subi temp2,TIMER_MSECS
1801 brcs clkget_end ;Port number in range?
1802 ldi zl,low(cntms_out)
1803 ldi zh,high(cntms_out)
1804 breq clkget_copy ;lowest byte requestet, latch clock
1806 brsh clkget_end ;Port number to high?
1831 subi temp2,TIMERPORT
1832 brcs clkput_end ;Port number in range?
1837 cpi temp,starttimercmd
1839 cpi temp,quitTimerCmd
1841 cpi temp,printTimerCmd
1855 ldi zl,low(cntms_out)
1856 ldi zh,high(cntms_out)
1857 breq clkput_copy ;lowest byte requestet, latch clock
1859 brsh clkput_end ;Port number to high?
1884 ldi zl,low(timer_ms)
1885 ldi zh,high(timer_ms)
1903 ldi zl,low(timer_ms)
1904 ldi zh,high(timer_ms)
1906 ; put ms on stack (16 bit)
1928 ldd temp2,z+timerofs
1932 ldd temp3,z+timerofs
1937 ldd temp4,z+timerofs
1942 .db 13,"Timer running. Elapsed: ",0
1962 ldi zh,high(cnt_1ms)
1995 ; --------------- Debugging stuff ---------------
1997 ;Print a unsigned lonng value to the uart
1998 ; temp4:temp3:temp2:temp = value
2005 clr yl ;yl = stack level
2007 ultoa1: ldi z_flags, 32 ;yh = temp4:temp % 10
2008 clr yh ;temp4:temp /= 10
2020 cpi yh, 10 ;yh is a numeral digit '0'-'9'
2024 cp temp,_0 ;Repeat until temp4:temp gets zero
2031 ultoa5: cpi yl,3 ; at least 3 digits (ms)
2037 ultoa6: pop temp ;Flush stacked digits
2048 ;Prints the lower nibble of temp in hex to the uart
2064 ;Prints temp in hex to the uart
2072 ;Prints the zero-terminated string following the call statement.
2112 ; --------------- AVR HW <-> Z80 periph stuff ------------------
2114 .equ memReadByte = dram_read
2115 .equ memWriteByte = dram_write
2116 #if DRAM_WORD_ACCESS
2117 .equ memReadWord = dram_read_w
2118 .equ memWriteWord = dram_write_w
2121 ; --------------------------------------------------------------
2125 #define RXBUFMASK RXBUFSIZE-1
2139 ; Save received character in a circular buffer. Do nothing if buffer overflows.
2152 lds zh,rxcount ;if rxcount < RXBUFSIZE
2153 cpi zh,RXBUFSIZE ; (room for at least 1 char?)
2156 sts rxcount,zh ; rxcount++
2158 ldi zl,low(rxfifo) ;
2163 sts rxidx_w,zh ; rxidx_w = ++rxidx_w % RXBUFSIZE
2164 ldi zh,high(rxfifo) ;
2167 st z,temp ; rxfifo[rxidx_w] = char
2177 ;Fetches a char from the buffer to temp. If none available, waits till one is.
2180 lds temp,rxcount ; Number of characters in buffer
2200 ld temp,z ;don't forget to get the char
2207 ;Sends a char from temp to the uart.
2209 #if defined __ATmega8__
2225 ; ------------ Fetch phase stuff -----------------
2227 .equ FETCH_NOP = (0<<0)
2228 .equ FETCH_A = (1<<0)
2229 .equ FETCH_B = (2<<0)
2230 .equ FETCH_C = (3<<0)
2231 .equ FETCH_D = (4<<0)
2232 .equ FETCH_E = (5<<0)
2233 .equ FETCH_H = (6<<0)
2234 .equ FETCH_L = (7<<0)
2235 .equ FETCH_AF = (8<<0)
2236 .equ FETCH_BC = (9<<0)
2237 .equ FETCH_DE = (10<<0)
2238 .equ FETCH_HL = (11<<0)
2239 .equ FETCH_SP = (12<<0)
2240 .equ FETCH_MBC = (13<<0)
2241 .equ FETCH_MDE = (14<<0)
2242 .equ FETCH_MHL = (15<<0)
2243 .equ FETCH_MSP = (16<<0)
2244 .equ FETCH_DIR8 = (17<<0)
2245 .equ FETCH_DIR16= (18<<0)
2246 .equ FETCH_RST = (19<<0)
2249 ;Jump table for fetch routines. Make sure to keep this in sync with the .equs!
2344 #if DRAM_WORD_ACCESS
2365 #if DRAM_WORD_ACCESS
2390 ; ------------ Store phase stuff -----------------
2392 .equ STORE_NOP = (0<<5)
2393 .equ STORE_A = (1<<5)
2394 .equ STORE_B = (2<<5)
2395 .equ STORE_C = (3<<5)
2396 .equ STORE_D = (4<<5)
2397 .equ STORE_E = (5<<5)
2398 .equ STORE_H = (6<<5)
2399 .equ STORE_L = (7<<5)
2400 .equ STORE_AF = (8<<5)
2401 .equ STORE_BC = (9<<5)
2402 .equ STORE_DE = (10<<5)
2403 .equ STORE_HL = (11<<5)
2404 .equ STORE_SP = (12<<5)
2405 .equ STORE_PC = (13<<5)
2406 .equ STORE_MBC = (14<<5)
2407 .equ STORE_MDE = (15<<5)
2408 .equ STORE_MHL = (16<<5)
2409 .equ STORE_MSP = (17<<5)
2410 .equ STORE_RET = (18<<5)
2411 .equ STORE_CALL = (19<<5)
2412 .equ STORE_AM = (20<<5)
2414 ;Jump table for store routines. Make sure to keep this in sync with the .equs!
2510 #if DRAM_WORD_ACCESS
2551 ; ------------ Operation phase stuff -----------------
2554 .equ OP_NOP = (0<<10)
2555 .equ OP_INC = (1<<10)
2556 .equ OP_DEC = (2<<10)
2557 .equ OP_INC16 = (3<<10)
2558 .equ OP_DEC16 = (4<<10)
2559 .equ OP_RLC = (5<<10)
2560 .equ OP_RRC = (6<<10)
2561 .equ OP_RR = (7<<10)
2562 .equ OP_RL = (8<<10)
2563 .equ OP_ADDA = (9<<10)
2564 .equ OP_ADCA = (10<<10)
2565 .equ OP_SUBFA = (11<<10)
2566 .equ OP_SBCFA = (12<<10)
2567 .equ OP_ANDA = (13<<10)
2568 .equ OP_ORA = (14<<10)
2569 .equ OP_XORA = (15<<10)
2570 .equ OP_ADDHL = (16<<10)
2571 .equ OP_STHL = (17<<10) ;store HL in fetched address
2572 .equ OP_RMEM16 = (18<<10) ;read mem at fetched address
2573 .equ OP_RMEM8 = (19<<10) ;read mem at fetched address
2574 .equ OP_DA = (20<<10)
2575 .equ OP_SCF = (21<<10)
2576 .equ OP_CPL = (22<<10)
2577 .equ OP_CCF = (23<<10)
2578 .equ OP_POP16 = (24<<10)
2579 .equ OP_PUSH16 = (25<<10)
2580 .equ OP_IFNZ = (26<<10)
2581 .equ OP_IFZ = (27<<10)
2582 .equ OP_IFNC = (28<<10)
2583 .equ OP_IFC = (29<<10)
2584 .equ OP_IFPO = (30<<10)
2585 .equ OP_IFPE = (31<<10)
2586 .equ OP_IFP = (32<<10)
2587 .equ OP_IFM = (33<<10)
2588 .equ OP_OUTA = (34<<10)
2589 .equ OP_IN = (35<<10)
2590 .equ OP_EXHL = (36<<10)
2591 .equ OP_DI = (37<<10)
2592 .equ OP_EI = (38<<10)
2593 .equ OP_INV = (39<<10)
2638 ;How the flags are supposed to work:
2639 ;7 ZFL_S - Sign flag (=MSBit of result)
2640 ;6 ZFL_Z - Zero flag. Is 1 when the result is 0
2641 ;4 ZFL_H - Half-carry (carry from bit 3 to 4)
2642 ;2 ZFL_P - Parity/2-complement Overflow
2643 ;1 ZFL_N - Subtract - set if last op was a subtract
2646 ;I sure hope I got the mapping between flags and instructions correct...
2648 ;----------------------------------------------------------------
2652 ;| ZZZZZZZ 88888 000 |
2658 ;| ZZZZZZZ 88888 000 |
2660 ;| Z80 MICROPROCESSOR Instruction Set Summary |
2662 ;----------------------------------------------------------------
2663 ;----------------------------------------------------------------
2664 ;|Mnemonic |SZHPNC|Description |Notes |
2665 ;|----------+------+---------------------+----------------------|
2666 ;|ADC A,s |***V0*|Add with Carry |A=A+s+CY |
2667 ;|ADC HL,ss |**?V0*|Add with Carry |HL=HL+ss+CY |
2668 ;|ADD A,s |***V0*|Add |A=A+s |
2669 ;|ADD HL,ss |--?-0*|Add |HL=HL+ss |
2670 ;|ADD IX,pp |--?-0*|Add |IX=IX+pp |
2671 ;|ADD IY,rr |--?-0*|Add |IY=IY+rr |
2672 ;|AND s |**1P00|Logical AND |A=A&s |
2673 ;|BIT b,m |?*1?0-|Test Bit |m&{2^b} |
2674 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
2675 ;|CALL nn |------|Unconditional Call |-[SP]=PC,PC=nn |
2676 ;|CCF |--?-0*|Complement Carry Flag|CY=~CY |
2677 ;|CP s |***V1*|Compare |A-s |
2678 ;|CPD |****1-|Compare and Decrement|A-[HL],HL=HL-1,BC=BC-1|
2679 ;|CPDR |****1-|Compare, Dec., Repeat|CPD till A=[HL]or BC=0|
2680 ;|CPI |****1-|Compare and Increment|A-[HL],HL=HL+1,BC=BC-1|
2681 ;|CPIR |****1-|Compare, Inc., Repeat|CPI till A=[HL]or BC=0|
2682 ;|CPL |--1-1-|Complement |A=~A |
2683 ;|DAA |***P-*|Decimal Adjust Acc. |A=BCD format |
2684 ;|DEC s |***V1-|Decrement |s=s-1 |
2685 ;|DEC xx |------|Decrement |xx=xx-1 |
2686 ;|DEC ss |------|Decrement |ss=ss-1 |
2687 ;|DI |------|Disable Interrupts | |
2688 ;|DJNZ e |------|Dec., Jump Non-Zero |B=B-1 till B=0 |
2689 ;|EI |------|Enable Interrupts | |
2690 ;|EX [SP],HL|------|Exchange |[SP]<->HL |
2691 ;|EX [SP],xx|------|Exchange |[SP]<->xx |
2692 ;|EX AF,AF' |------|Exchange |AF<->AF' |
2693 ;|EX DE,HL |------|Exchange |DE<->HL |
2694 ;|EXX |------|Exchange |qq<->qq' (except AF)|
2695 ;|HALT |------|Halt | |
2696 ;|IM n |------|Interrupt Mode | (n=0,1,2)|
2697 ;|IN A,[n] |------|Input |A=[n] |
2698 ;|IN r,[C] |***P0-|Input |r=[C] |
2699 ;|INC r |***V0-|Increment |r=r+1 |
2700 ;|INC [HL] |***V0-|Increment |[HL]=[HL]+1 |
2701 ;|INC xx |------|Increment |xx=xx+1 |
2702 ;|INC [xx+d]|***V0-|Increment |[xx+d]=[xx+d]+1 |
2703 ;|INC ss |------|Increment |ss=ss+1 |
2704 ;|IND |?*??1-|Input and Decrement |[HL]=[C],HL=HL-1,B=B-1|
2705 ;|INDR |?1??1-|Input, Dec., Repeat |IND till B=0 |
2706 ;|INI |?*??1-|Input and Increment |[HL]=[C],HL=HL+1,B=B-1|
2707 ;|INIR |?1??1-|Input, Inc., Repeat |INI till B=0 |
2708 ;|JP [HL] |------|Unconditional Jump |PC=[HL] |
2709 ;|JP [xx] |------|Unconditional Jump |PC=[xx] |
2710 ;|JP nn |------|Unconditional Jump |PC=nn |
2711 ;|JP cc,nn |------|Conditional Jump |If cc JP |
2712 ;|JR e |------|Unconditional Jump |PC=PC+e |
2713 ;|JR cc,e |------|Conditional Jump |If cc JR(cc=C,NC,NZ,Z)|
2714 ;|LD dst,src|------|Load |dst=src |
2715 ;|LD A,i |**0*0-|Load |A=i (i=I,R)|
2716 ;|LDD |--0*0-|Load and Decrement |[DE]=[HL],HL=HL-1,# |
2717 ;|LDDR |--000-|Load, Dec., Repeat |LDD till BC=0 |
2718 ;|LDI |--0*0-|Load and Increment |[DE]=[HL],HL=HL+1,# |
2719 ;|LDIR |--000-|Load, Inc., Repeat |LDI till BC=0 |
2720 ;|NEG |***V1*|Negate |A=-A |
2721 ;|NOP |------|No Operation | |
2722 ;|OR s |**0P00|Logical inclusive OR |A=Avs |
2723 ;|OTDR |?1??1-|Output, Dec., Repeat |OUTD till B=0 |
2724 ;|OTIR |?1??1-|Output, Inc., Repeat |OUTI till B=0 |
2725 ;|OUT [C],r |------|Output |[C]=r |
2726 ;|OUT [n],A |------|Output |[n]=A |
2727 ;|OUTD |?*??1-|Output and Decrement |[C]=[HL],HL=HL-1,B=B-1|
2728 ;|OUTI |?*??1-|Output and Increment |[C]=[HL],HL=HL+1,B=B-1|
2729 ;|POP xx |------|Pop |xx=[SP]+ |
2730 ;|POP qq |------|Pop |qq=[SP]+ |
2731 ;|PUSH xx |------|Push |-[SP]=xx |
2732 ;|PUSH qq |------|Push |-[SP]=qq |
2733 ;|RES b,m |------|Reset bit |m=m&{~2^b} |
2734 ;|RET |------|Return |PC=[SP]+ |
2735 ;|RET cc |------|Conditional Return |If cc RET |
2736 ;|RETI |------|Return from Interrupt|PC=[SP]+ |
2737 ;|RETN |------|Return from NMI |PC=[SP]+ |
2738 ;|RL m |**0P0*|Rotate Left |m={CY,m}<- |
2739 ;|RLA |--0-0*|Rotate Left Acc. |A={CY,A}<- |
2740 ;|RLC m |**0P0*|Rotate Left Circular |m=m<- |
2741 ;|RLCA |--0-0*|Rotate Left Circular |A=A<- |
2742 ;|RLD |**0P0-|Rotate Left 4 bits |{A,[HL]}={A,[HL]}<- ##|
2743 ;|RR m |**0P0*|Rotate Right |m=->{CY,m} |
2744 ;|RRA |--0-0*|Rotate Right Acc. |A=->{CY,A} |
2745 ;|RRC m |**0P0*|Rotate Right Circular|m=->m |
2746 ;|RRCA |--0-0*|Rotate Right Circular|A=->A |
2747 ;|RRD |**0P0-|Rotate Right 4 bits |{A,[HL]}=->{A,[HL]} ##|
2748 ;|RST p |------|Restart | (p=0H,8H,10H,...,38H)|
2749 ;|SBC A,s |***V1*|Subtract with Carry |A=A-s-CY |
2750 ;|SBC HL,ss |**?V1*|Subtract with Carry |HL=HL-ss-CY |
2751 ;|SCF |--0-01|Set Carry Flag |CY=1 |
2752 ;|SET b,m |------|Set bit |m=mv{2^b} |
2753 ;|SLA m |**0P0*|Shift Left Arithmetic|m=m*2 |
2754 ;|SRA m |**0P0*|Shift Right Arith. |m=m/2 |
2755 ;|SRL m |**0P0*|Shift Right Logical |m=->{0,m,CY} |
2756 ;|SUB s |***V1*|Subtract |A=A-s |
2757 ;|XOR s |**0P00|Logical Exclusive OR |A=Axs |
2758 ;|----------+------+--------------------------------------------|
2759 ;| F |-*01? |Flag unaffected/affected/reset/set/unknown |
2760 ;| S |S |Sign flag (Bit 7) |
2761 ;| Z | Z |Zero flag (Bit 6) |
2762 ;| HC | H |Half Carry flag (Bit 4) |
2763 ;| P/V | P |Parity/Overflow flag (Bit 2, V=overflow) |
2764 ;| N | N |Add/Subtract flag (Bit 1) |
2765 ;| CY | C|Carry flag (Bit 0) |
2766 ;|-----------------+--------------------------------------------|
2767 ;| n |Immediate addressing |
2768 ;| nn |Immediate extended addressing |
2769 ;| e |Relative addressing (PC=PC+2+offset) |
2770 ;| [nn] |Extended addressing |
2771 ;| [xx+d] |Indexed addressing |
2772 ;| r |Register addressing |
2773 ;| [rr] |Register indirect addressing |
2774 ;| |Implied addressing |
2775 ;| b |Bit addressing |
2776 ;| p |Modified page zero addressing (see RST) |
2777 ;|-----------------+--------------------------------------------|
2778 ;|DEFB n(,...) |Define Byte(s) |
2779 ;|DEFB 'str'(,...) |Define Byte ASCII string(s) |
2780 ;|DEFS nn |Define Storage Block |
2781 ;|DEFW nn(,...) |Define Word(s) |
2782 ;|-----------------+--------------------------------------------|
2783 ;| A B C D E |Registers (8-bit) |
2784 ;| AF BC DE HL |Register pairs (16-bit) |
2785 ;| F |Flag register (8-bit) |
2786 ;| I |Interrupt page address register (8-bit) |
2787 ;| IX IY |Index registers (16-bit) |
2788 ;| PC |Program Counter register (16-bit) |
2789 ;| R |Memory Refresh register |
2790 ;| SP |Stack Pointer register (16-bit) |
2791 ;|-----------------+--------------------------------------------|
2792 ;| b |One bit (0 to 7) |
2793 ;| cc |Condition (C,M,NC,NZ,P,PE,PO,Z) |
2794 ;| d |One-byte expression (-128 to +127) |
2795 ;| dst |Destination s, ss, [BC], [DE], [HL], [nn] |
2796 ;| e |One-byte expression (-126 to +129) |
2797 ;| m |Any register r, [HL] or [xx+d] |
2798 ;| n |One-byte expression (0 to 255) |
2799 ;| nn |Two-byte expression (0 to 65535) |
2800 ;| pp |Register pair BC, DE, IX or SP |
2801 ;| qq |Register pair AF, BC, DE or HL |
2802 ;| qq' |Alternative register pair AF, BC, DE or HL |
2803 ;| r |Register A, B, C, D, E, H or L |
2804 ;| rr |Register pair BC, DE, IY or SP |
2805 ;| s |Any register r, value n, [HL] or [xx+d] |
2806 ;| src |Source s, ss, [BC], [DE], [HL], nn, [nn] |
2807 ;| ss |Register pair BC, DE, HL or SP |
2808 ;| xx |Index register IX or IY |
2809 ;|-----------------+--------------------------------------------|
2810 ;| + - * / ^ |Add/subtract/multiply/divide/exponent |
2811 ;| & ~ v x |Logical AND/NOT/inclusive OR/exclusive OR |
2812 ;| <- -> |Rotate left/right |
2813 ;| [ ] |Indirect addressing |
2814 ;| [ ]+ -[ ] |Indirect addressing auto-increment/decrement|
2815 ;| { } |Combination of operands |
2816 ;| # |Also BC=BC-1,DE=DE-1 |
2817 ;| ## |Only lower 4 bits of accumulator A used |
2818 ;----------------------------------------------------------------
2829 ;------------------------------------------------;
2830 ; Move single bit between two registers
2832 ; bmov dstreg,dstbit,srcreg.srcbit
2840 ;------------------------------------------------;
2841 ; Load table value from flash indexed by source reg.
2843 ; ldpmx dstreg,tablebase,indexreg
2845 ; (6 words, 8 cycles)
2848 ldi zh,high(@1*2) ; table must be page aligned
2852 .macro do_z80_flags_HP
2854 bmov z_flags, ZFL_P, temp, AVR_V
2855 bmov z_flags, ZFL_H, temp, AVR_H
2859 .macro do_z80_flags_set_N
2861 ori z_flags, (1<<ZFL_N) ; Negation auf 1
2865 .macro do_z80_flags_set_HN
2867 ori z_flags,(1<<ZFL_N)|(1<<ZFL_H)
2871 .macro do_z80_flags_clear_N
2873 andi z_flags,~(1<<ZFL_N)
2877 .macro do_z80_flags_op_rotate
2878 ; must not change avr carry flag!
2880 andi z_flags, ~( (1<<ZFL_H) | (1<<ZFL_N) | (1<<ZFL_C) )
2882 andi z_flags, ~( (1<<ZFL_C) )
2886 .macro do_z80_flags_op_and
2888 ori z_flags,(1<<ZFL_H)
2890 ori z_flags,(1<<ZFL_H)
2894 .macro do_z80_flags_op_or
2903 ;----------------------------------------------------------------
2904 ;|Mnemonic |SZHPNC|Description |Notes |
2905 ;----------------------------------------------------------------
2906 ;|INC r |***V0-|Increment |r=r+1 |
2907 ;|INC [HL] |***V0-|Increment |[HL]=[HL]+1 |
2908 ;|INC [xx+d]|***V0-|Increment |[xx+d]=[xx+d]+1 |
2909 ;|----------|SZHP C|---------- 8080 ----------------------------|
2910 ;|INC r |**-P0-|Increment |r=r+1 |
2911 ;|INC [HL] |**-P0-|Increment |[HL]=[HL]+1 |
2918 andi z_flags,(1<<ZFL_H)|(1<<ZFL_C) ; preserve C-, and H-flag
2919 ldpmx temp2, sz53p_tab, opl
2924 ;----------------------------------------------------------------
2925 ;|Mnemonic |SZHPNC|Description |Notes |
2926 ;----------------------------------------------------------------
2927 ;|DEC r |***V1-|Decrement |s=s-1 |
2928 ;|INC [HL] |***V0-|Increment |[HL]=[HL]+1 |
2929 ;|INC [xx+d]|***V0-|Increment |[xx+d]=[xx+d]+1 |
2930 ;|----------|SZHP C|---------- 8080 ----------------------------|
2931 ;|DEC r |**-P -|Increment |r=r+1 |
2932 ;|DEC [HL] |**-P -|Increment |[HL]=[HL]+1 |
2938 andi z_flags,(1<<ZFL_H)|(1<<ZFL_C) ; preserve C-, and H-flag
2939 ldpmx temp2, sz53p_tab, opl
2946 ;----------------------------------------------------------------
2947 ;|Mnemonic |SZHPNC|Description |Notes |
2948 ;----------------------------------------------------------------
2949 ;|INC xx |------|Increment |xx=xx+1 |
2950 ;|INC ss |------|Increment |ss=ss+1 |
2958 ;----------------------------------------------------------------
2959 ;|Mnemonic |SZHPNC|Description |Notes |
2960 ;----------------------------------------------------------------
2961 ;|DEC xx |------|Decrement |xx=xx-1 |
2962 ;|DEC ss |------|Decrement |ss=ss-1 |
2970 ;----------------------------------------------------------------
2971 ;|Mnemonic |SZHPNC|Description |Notes |
2972 ;----------------------------------------------------------------
2973 ;|RLCA |--0-0*|Rotate Left Circular |A=A<- |
2974 ;|----------|SZHP C|---------- 8080 ----------------------------|
2975 ;|RLCA |---- *|Rotate Left Circular |A=A<- |
2979 ;Rotate Left Cyclical. All bits move 1 to the
2980 ;left, the msb becomes c and lsb.
2981 do_z80_flags_op_rotate
2985 ori z_flags, (1<<ZFL_C)
2989 ;----------------------------------------------------------------
2990 ;|Mnemonic |SZHPNC|Description |Notes |
2991 ;----------------------------------------------------------------
2992 ;|RRCA |--0-0*|Rotate Right Circular|A=->A |
2993 ;|----------|SZHP C|---------- 8080 ----------------------------|
2994 ;|RRCA |---- *|Rotate Right Circular|A=->A |
2998 ;Rotate Right Cyclical. All bits move 1 to the
2999 ;right, the lsb becomes c and msb.
3000 do_z80_flags_op_rotate
3004 ori z_flags, (1<<ZFL_C)
3008 ;----------------------------------------------------------------
3009 ;|Mnemonic |SZHPNC|Description |Notes |
3010 ;----------------------------------------------------------------
3011 ;|RRA |--0-0*|Rotate Right Acc. |A=->{CY,A} |
3012 ;|----------|SZHP C|---------- 8080 ----------------------------|
3013 ;|RRA |---- *|Rotate Right Acc. |A=->{CY,A} |
3017 ;Rotate Right. All bits move 1 to the right, the lsb
3018 ;becomes c, c becomes msb.
3019 clc ; get z80 carry to avr carry
3022 do_z80_flags_op_rotate ; (clear ZFL_C, doesn't change AVR_C)
3023 bmov z_flags,ZFL_C, opl,0 ; Bit 0 --> CY
3027 ;----------------------------------------------------------------
3028 ;|Mnemonic |SZHPNC|Description |Notes |
3029 ;----------------------------------------------------------------
3030 ;|RLA |--0-0*|Rotate Left Acc. |A={CY,A}<- |
3031 ;|----------|SZHP C|---------- 8080 ----------------------------|
3032 ;|RLA |---- *|Rotate Left Acc. |A={CY,A}<- |
3036 ;Rotate Left. All bits move 1 to the left, the msb
3037 ;becomes c, c becomes lsb.
3041 do_z80_flags_op_rotate ; (clear ZFL_C, doesn't change AVR_C)
3042 bmov z_flags,ZFL_C, opl,7 ; Bit 7 --> CY
3046 ;----------------------------------------------------------------
3047 ;|Mnemonic |SZHPNC|Description |Notes |
3048 ;----------------------------------------------------------------
3049 ;|ADD A,s |***V0*|Add |A=A+s |
3050 ;|----------|SZHP C|---------- 8080 ----------------------------|
3051 ;|ADD A,s |***P *|Add |A=A+s |
3057 ldpmx z_flags,sz53p_tab,opl ;S,Z,P flag
3058 bmov z_flags,ZFL_C, temp,AVR_C
3062 ;----------------------------------------------------------------
3063 ;|Mnemonic |SZHPNC|Description |Notes |
3064 ;----------------------------------------------------------------
3065 ;|ADC A,s |***V0*|Add with Carry |A=A+s+CY |
3066 ;|----------|SZHP C|---------- 8080 ----------------------------|
3067 ;|ADC A,s |***P *|Add with Carry |A=A+s+CY |
3076 ldpmx z_flags,sz53p_tab,opl ;S,Z,P
3077 bmov z_flags,ZFL_C, temp,AVR_C
3081 ;----------------------------------------------------------------
3082 ;|Mnemonic |SZHPNC|Description |Notes |
3083 ;----------------------------------------------------------------
3084 ;|SUB s |***V1*|Subtract |A=A-s |
3085 ;|CP s |***V1*|Compare |A-s |
3086 ;|----------|SZHP C|---------- 8080 ----------------------------|
3087 ;|SUB s |***P *|Subtract |A=A-s |
3088 ;|CP s |***P *|Compare |A-s |
3096 ldpmx z_flags,sz53p_tab,opl ;S,Z,P
3097 bmov z_flags,ZFL_C, temp,AVR_C
3102 ;----------------------------------------------------------------
3103 ;|Mnemonic |SZHPNC|Description |Notes |
3104 ;----------------------------------------------------------------
3105 ;|SBC A,s |***V1*|Subtract with Carry |A=A-s-CY |
3106 ;|----------|SZHP C|---------- 8080 ----------------------------|
3107 ;|SBC A,s |***P *|Subtract with Carry |A=A-s-CY |
3118 ldpmx z_flags,sz53p_tab,opl ;S,Z,P
3119 bmov z_flags,ZFL_C, temp,AVR_C
3124 ;----------------------------------------------------------------
3125 ;|Mnemonic |SZHPNC|Description |Notes |
3126 ;----------------------------------------------------------------
3127 ;|AND s |**1P00|Logical AND |A=A&s |
3128 ;|----------|SZHP C|---------- 8080 ----------------------------|
3129 ;|AND s |**-P 0|Logical AND |A=A&s |
3134 ldpmx z_flags,sz53p_tab,opl ;S,Z,P,N,C
3139 ;----------------------------------------------------------------
3140 ;|Mnemonic |SZHPNC|Description |Notes |
3141 ;----------------------------------------------------------------
3142 ;|OR s |**0P00|Logical inclusive OR |A=Avs |
3143 ;|----------|SZHP C|---------- 8080 ----------------------------|
3144 ;|OR s |**-P00|Logical inclusive OR |A=Avs |
3149 ldpmx z_flags,sz53p_tab,opl ;S,Z,H,P,N,C
3153 ;----------------------------------------------------------------
3154 ;|Mnemonic |SZHPNC|Description |Notes |
3155 ;----------------------------------------------------------------
3156 ;|XOR s |**0P00|Logical Exclusive OR |A=Axs |
3157 ;|----------|SZHP C|---------- 8080 ----------------------------|
3158 ;|XOR s |**-P 0|Logical Exclusive OR |A=Axs |
3163 ldpmx z_flags,sz53p_tab,opl ;S,Z,H,P,N,C
3167 ;----------------------------------------------------------------
3168 ;|Mnemonic |SZHPNC|Description |Notes |
3169 ;----------------------------------------------------------------
3170 ;|ADD HL,ss |--?-0*|Add |HL=HL+ss |
3171 ;|----------|SZHP C|---------- 8080 ----------------------------|
3172 ;|ADD HL,ss |---- *|Add |HL=HL+ss |
3179 bmov z_flags,ZFL_H, temp,AVR_H
3180 bmov z_flags,ZFL_C, temp,AVR_C
3181 do_z80_flags_clear_N
3184 ;----------------------------------------------------------------
3185 ;|Mnemonic |SZHPNC|Description |Notes |
3186 ;----------------------------------------------------------------
3187 ;|LD dst,src|------|Load |dst=src |
3190 do_op_sthl: ;store hl to mem loc in opl:h
3192 #if DRAM_WORD_ACCESS
3204 ;----------------------------------------------------------------
3205 ;|Mnemonic |SZHPNC|Description |Notes |
3206 ;----------------------------------------------------------------
3207 ;|LD dst,src|------|Load |dst=src |
3212 #if DRAM_WORD_ACCESS
3224 ;----------------------------------------------------------------
3225 ;|Mnemonic |SZHPNC|Description |Notes |
3226 ;----------------------------------------------------------------
3227 ;|LD dst,src|------|Load |dst=src |
3236 ;----------------------------------------------------------------
3237 ;|Mnemonic |SZHPNC|Description |Notes |
3238 ;----------------------------------------------------------------
3239 ;|DAA |***P-*|Decimal Adjust Acc. | |
3240 ;|----------|SZHP C|---------- 8080 ----------------------------|
3244 ; Description (http://www.z80.info/z80syntx.htm#DAA):
3245 ; This instruction conditionally adjusts the accumulator for BCD addition
3246 ; and subtraction operations. For addition (ADD, ADC, INC) or subtraction
3247 ; (SUB, SBC, DEC, NEC), the following table indicates the operation performed:
3249 ; -------------------------------------------------------------------------------
3250 ; | | C Flag | HEX value in | H Flag | HEX value in | Number | C flag|
3251 ; | Operation| Before | upper digit | Before | lower digit | added | After |
3252 ; | | DAA | (bit 7-4) | DAA | (bit 3-0) | to byte | DAA |
3253 ; |-----------------------------------------------------------------------------|
3254 ; | | 0 | 0-9 | 0 | 0-9 | 00 | 0 |
3255 ; | ADD | 0 | 0-8 | 0 | A-F | 06 | 0 |
3256 ; | | 0 | 0-9 | 1 | 0-3 | 06 | 0 |
3257 ; | ADC | 0 | A-F | 0 | 0-9 | 60 | 1 |
3258 ; | | 0 | 9-F | 0 | A-F | 66 | 1 |
3259 ; | INC | 0 | A-F | 1 | 0-3 | 66 | 1 |
3260 ; | | 1 | 0-2 | 0 | 0-9 | 60 | 1 |
3261 ; | | 1 | 0-2 | 0 | A-F | 66 | 1 |
3262 ; | | 1 | 0-3 | 1 | 0-3 | 66 | 1 |
3263 ; |-----------------------------------------------------------------------------|
3264 ; | SUB | 0 | 0-9 | 0 | 0-9 | 00 | 0 |
3265 ; | SBC | 0 | 0-8 | 1 | 6-F | FA | 0 |
3266 ; | DEC | 1 | 7-F | 0 | 0-9 | A0 | 1 |
3267 ; | NEG | 1 | 6-F | 1 | 6-F | 9A | 1 |
3268 ; |-----------------------------------------------------------------------------|
3271 ; C: See instruction.
3273 ; P/V: Set if Acc. is even parity after operation, reset otherwise.
3274 ; H: See instruction.
3275 ; Z: Set if Acc. is Zero after operation, reset otherwise.
3276 ; S: Set if most significant bit of Acc. is 1 after operation, reset otherwise.
3282 ldi oph,0 ; what to add
3283 sbrc z_flags,ZFL_H ; if H-Flag
3286 andi temp,0x0f ; ... or lower digit > 9
3292 sbrc z_flags,(1<<ZFL_C)
3301 ori z_flags,(1<<ZFL_C); set C
3303 sbrs z_flags,ZFL_N ; if sub-op
3304 rjmp op_da_add ; then
3307 op_da_add: ; else add-op
3320 ori z_flags,(1<<ZFL_C)
3321 andi z_flags,(1<<ZFL_N)|(1<<ZFL_C) ; preserve C,N
3322 ldpmx temp2, sz53p_tab, opl ; get S,Z,P
3324 bmov z_flags,ZFL_H, temp,AVR_H ; H (?)
3329 sbrc z_flags,ZFL_N ; if add-op
3330 rjmp do_op_da_sub ; then
3334 cpi temp,0x0a ; if lower digit > 9
3336 ori temp2,0x06 ; add 6 to lower digit
3338 sbrc z_flags,ZFL_H ; ... or H-Flag
3348 do_op_da_c: ; else sub-op
3349 sbrc z_flags,ZFL_C ;
3351 andi z_flags, ~( (1<<ZFL_S) | (1<<ZFL_Z) | (1<<ZFL_H) )
3354 bst temp,AVR_Z ;Z-Flag
3356 bst temp,AVR_N ;S-Flag
3358 sbrc temp2,5 ;C-Flag, set if 0x06 added
3359 ori z_flags,(1<<ZFL_C) ;
3363 do_op_da_sub: ;TODO:
3368 ;----------------------------------------------------------------
3369 ;|Mnemonic |SZHPNC|Description |Notes |
3370 ;----------------------------------------------------------------
3371 ;|SCF |--0-01|Set Carry Flag |CY=1 |
3372 ;|----------|SZHP C|---------- 8080 ----------------------------|
3376 andi z_flags,~((1<<ZFL_H)|(1<<ZFL_N))
3377 ori z_flags,(1<<ZFL_C)
3380 ;----------------------------------------------------------------
3381 ;|Mnemonic |SZHPNC|Description |Notes |
3382 ;----------------------------------------------------------------
3383 ;|CCF |--?-0*|Complement Carry Flag|CY=~CY |
3384 ;|----------|SZHP C|---------- 8080 ----------------------------|
3385 ;|SCF |---- 1|Set Carry Flag |CY=1 |
3389 do_z80_flags_clear_N
3394 ;----------------------------------------------------------------
3395 ;|Mnemonic |SZHPNC|Description |Notes |
3396 ;----------------------------------------------------------------
3397 ;|CPL |--1-1-|Complement |A=~A |
3398 ;|----------|SZHP C|---------- 8080 ----------------------------|
3399 ;|CPL |---- -|Complement |A=~A |
3408 ;----------------------------------------------------------------
3409 ;|Mnemonic |SZHPNC|Description |Notes |
3410 ;----------------------------------------------------------------
3411 ;|PUSH xx |------|Push |-[SP]=xx |
3412 ;|PUSH qq |------|Push |-[SP]=qq |
3420 #if DRAM_WORD_ACCESS
3439 .db ", SP is now ",0
3450 ;----------------------------------------------------------------
3451 ;|Mnemonic |SZHPNC|Description |Notes |
3452 ;----------------------------------------------------------------
3453 ;|POP xx |------|Pop |xx=[SP]+ |
3454 ;|POP qq |------|Pop |qq=[SP]+ |
3459 #if DRAM_WORD_ACCESS
3477 .db "Stack pop: val ",0
3493 ;----------------------------------------------------------------
3494 ;|Mnemonic |SZHPNC|Description |Notes |
3495 ;----------------------------------------------------------------
3496 ;|EX [SP],HL|------|Exchange |[SP]<->HL |
3497 ;|EX DE,HL |------|Exchange |DE<->HL |
3509 ;----------------------------------------------------------------
3510 ;|Mnemonic |SZHPNC|Description |Notes |
3511 ;----------------------------------------------------------------
3513 ; TODO: Implement IFF1, IFF2
3517 ;----------------------------------------------------------------
3518 ;|Mnemonic |SZHPNC|Description |Notes |
3519 ;----------------------------------------------------------------
3521 ; TODO: Implement IFF1, IFF2
3525 ;----------------------------------------------------------------
3526 ;|Mnemonic |SZHPNC|Description |Notes |
3527 ;----------------------------------------------------------------
3528 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3529 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3530 ;|RET cc |------|Conditional Return |If cc RET |
3540 ;----------------------------------------------------------------
3541 ;|Mnemonic |SZHPNC|Description |Notes |
3542 ;----------------------------------------------------------------
3543 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3544 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3545 ;|RET cc |------|Conditional Return |If cc RET |
3555 ;----------------------------------------------------------------
3556 ;|Mnemonic |SZHPNC|Description |Notes |
3557 ;----------------------------------------------------------------
3558 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3559 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3560 ;|RET cc |------|Conditional Return |If cc RET |
3570 ;----------------------------------------------------------------
3571 ;|Mnemonic |SZHPNC|Description |Notes |
3572 ;----------------------------------------------------------------
3573 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3574 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3575 ;|RET cc |------|Conditional Return |If cc RET |
3585 ;----------------------------------------------------------------
3586 ;|Mnemonic |SZHPNC|Description |Notes |
3587 ;----------------------------------------------------------------
3588 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3589 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3590 ;|RET cc |------|Conditional Return |If cc RET |
3600 ;----------------------------------------------------------------
3601 ;|Mnemonic |SZHPNC|Description |Notes |
3602 ;----------------------------------------------------------------
3603 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3604 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3605 ;|RET cc |------|Conditional Return |If cc RET |
3615 ;----------------------------------------------------------------
3616 ;|Mnemonic |SZHPNC|Description |Notes |
3617 ;----------------------------------------------------------------
3618 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3619 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3620 ;|RET cc |------|Conditional Return |If cc RET |
3623 do_op_ifp: ;sign positive, aka s=0
3630 ;----------------------------------------------------------------
3631 ;|Mnemonic |SZHPNC|Description |Notes |
3632 ;----------------------------------------------------------------
3633 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3634 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3635 ;|RET cc |------|Conditional Return |If cc RET |
3638 do_op_ifm: ;sign negative, aka s=1
3645 ;----------------------------------------------------------------
3646 ;|Mnemonic |SZHPNC|Description |Notes |
3647 ;----------------------------------------------------------------
3648 ;|OUT [n],A |------|Output |[n]=A |
3651 ;Interface with peripherials goes here :)
3652 do_op_outa: ; out (opl),a
3655 .db 13,"Port write: ",0
3670 ;----------------------------------------------------------------
3671 ;|Mnemonic |SZHPNC|Description |Notes |
3672 ;----------------------------------------------------------------
3673 ;|IN A,[n] |------|Input |A=[n] |
3676 do_op_in: ; in a,(opl)
3679 .db 13,"Port read: (",0
3698 ;----------------------------------------------------------------
3701 .db "Invalid opcode @ PC=",0,0
3707 ;----------------------------------------------------------------
3711 ;----------------------------------------------------------------
3712 ; Lookup table, stolen from z80ex, Z80 emulation library.
3713 ; http://z80ex.sourceforge.net/
3715 ; The S, Z, 5 and 3 bits and the parity of the lookup value
3716 .org (PC+255) & 0xff00
3718 .db 0x44,0x00,0x00,0x04,0x00,0x04,0x04,0x00
3719 .db 0x08,0x0c,0x0c,0x08,0x0c,0x08,0x08,0x0c
3720 .db 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04
3721 .db 0x0c,0x08,0x08,0x0c,0x08,0x0c,0x0c,0x08
3722 .db 0x20,0x24,0x24,0x20,0x24,0x20,0x20,0x24
3723 .db 0x2c,0x28,0x28,0x2c,0x28,0x2c,0x2c,0x28
3724 .db 0x24,0x20,0x20,0x24,0x20,0x24,0x24,0x20
3725 .db 0x28,0x2c,0x2c,0x28,0x2c,0x28,0x28,0x2c
3726 .db 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04
3727 .db 0x0c,0x08,0x08,0x0c,0x08,0x0c,0x0c,0x08
3728 .db 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00
3729 .db 0x08,0x0c,0x0c,0x08,0x0c,0x08,0x08,0x0c
3730 .db 0x24,0x20,0x20,0x24,0x20,0x24,0x24,0x20
3731 .db 0x28,0x2c,0x2c,0x28,0x2c,0x28,0x28,0x2c
3732 .db 0x20,0x24,0x24,0x20,0x24,0x20,0x20,0x24
3733 .db 0x2c,0x28,0x28,0x2c,0x28,0x2c,0x2c,0x28
3734 .db 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84
3735 .db 0x8c,0x88,0x88,0x8c,0x88,0x8c,0x8c,0x88
3736 .db 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80
3737 .db 0x88,0x8c,0x8c,0x88,0x8c,0x88,0x88,0x8c
3738 .db 0xa4,0xa0,0xa0,0xa4,0xa0,0xa4,0xa4,0xa0
3739 .db 0xa8,0xac,0xac,0xa8,0xac,0xa8,0xa8,0xac
3740 .db 0xa0,0xa4,0xa4,0xa0,0xa4,0xa0,0xa0,0xa4
3741 .db 0xac,0xa8,0xa8,0xac,0xa8,0xac,0xac,0xa8
3742 .db 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80
3743 .db 0x88,0x8c,0x8c,0x88,0x8c,0x88,0x88,0x8c
3744 .db 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84
3745 .db 0x8c,0x88,0x88,0x8c,0x88,0x8c,0x8c,0x88
3746 .db 0xa0,0xa4,0xa4,0xa0,0xa4,0xa0,0xa0,0xa4
3747 .db 0xac,0xa8,0xa8,0xac,0xa8,0xac,0xac,0xa8
3748 .db 0xa4,0xa0,0xa0,0xa4,0xa0,0xa4,0xa4,0xa0
3749 .db 0xa8,0xac,0xac,0xa8,0xac,0xa8,0xa8,0xac
3752 ; ----------------------- Opcode decoding -------------------------
3754 ; Lookup table for Z80 opcodes. Translates the first byte of the instruction word into three
3755 ; operations: fetch, do something, store.
3756 ; The table is made of 256 words. These 16-bit words consist of
3757 ; the fetch operation (bit 0-4), the processing operation (bit 10-16) and the store
3758 ; operation (bit 5-9).
3759 .org (PC+255) & 0xff00
3761 .dw (FETCH_NOP | OP_NOP | STORE_NOP) ; 00 NOP
3762 .dw (FETCH_DIR16| OP_NOP | STORE_BC ) ; 01 nn nn LD BC,nn
3763 .dw (FETCH_A | OP_NOP | STORE_MBC) ; 02 LD (BC),A
3764 .dw (FETCH_BC | OP_INC16 | STORE_BC ) ; 03 INC BC
3765 .dw (FETCH_B | OP_INC | STORE_B ) ; 04 INC B
3766 .dw (FETCH_B | OP_DEC | STORE_B ) ; 05 DEC B
3767 .dw (FETCH_DIR8 | OP_NOP | STORE_B ) ; 06 nn LD B,n
3768 .dw (FETCH_A | OP_RLC | STORE_A ) ; 07 RLCA
3769 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 08 EX AF,AF' (Z80)
3770 .dw (FETCH_BC | OP_ADDHL | STORE_HL ) ; 09 ADD HL,BC
3771 .dw (FETCH_MBC | OP_NOP | STORE_A ) ; 0A LD A,(BC)
3772 .dw (FETCH_BC | OP_DEC16 | STORE_BC ) ; 0B DEC BC
3773 .dw (FETCH_C | OP_INC | STORE_C ) ; 0C INC C
3774 .dw (FETCH_C | OP_DEC | STORE_C ) ; 0D DEC C
3775 .dw (FETCH_DIR8 | OP_NOP | STORE_C ) ; 0E nn LD C,n
3776 .dw (FETCH_A | OP_RRC | STORE_A ) ; 0F RRCA
3777 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 10 oo DJNZ o (Z80)
3778 .dw (FETCH_DIR16| OP_NOP | STORE_DE ) ; 11 nn nn LD DE,nn
3779 .dw (FETCH_A | OP_NOP | STORE_MDE) ; 12 LD (DE),A
3780 .dw (FETCH_DE | OP_INC16 | STORE_DE ) ; 13 INC DE
3781 .dw (FETCH_D | OP_INC | STORE_D ) ; 14 INC D
3782 .dw (FETCH_D | OP_DEC | STORE_D ) ; 15 DEC D
3783 .dw (FETCH_DIR8 | OP_NOP | STORE_D ) ; 16 nn LD D,n
3784 .dw (FETCH_A | OP_RL | STORE_A ) ; 17 RLA
3785 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 18 oo JR o (Z80)
3786 .dw (FETCH_DE | OP_ADDHL | STORE_HL ) ; 19 ADD HL,DE
3787 .dw (FETCH_MDE | OP_NOP | STORE_A ) ; 1A LD A,(DE)
3788 .dw (FETCH_DE | OP_DEC16 | STORE_DE ) ; 1B DEC DE
3789 .dw (FETCH_E | OP_INC | STORE_E ) ; 1C INC E
3790 .dw (FETCH_E | OP_DEC | STORE_E ) ; 1D DEC E
3791 .dw (FETCH_DIR8 | OP_NOP | STORE_E ) ; 1E nn LD E,n
3792 .dw (FETCH_A | OP_RR | STORE_A ) ; 1F RRA
3793 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 20 oo JR NZ,o (Z80)
3794 .dw (FETCH_DIR16| OP_NOP | STORE_HL ) ; 21 nn nn LD HL,nn
3795 .dw (FETCH_DIR16| OP_STHL | STORE_NOP) ; 22 nn nn LD (nn),HL
3796 .dw (FETCH_HL | OP_INC16 | STORE_HL ) ; 23 INC HL
3797 .dw (FETCH_H | OP_INC | STORE_H ) ; 24 INC H
3798 .dw (FETCH_H | OP_DEC | STORE_H ) ; 25 DEC H
3799 .dw (FETCH_DIR8 | OP_NOP | STORE_H ) ; 26 nn LD H,n
3800 .dw (FETCH_A | OP_DA | STORE_A ) ; 27 DAA
3801 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 28 oo JR Z,o (Z80)
3802 .dw (FETCH_HL | OP_ADDHL | STORE_HL ) ; 29 ADD HL,HL
3803 .dw (FETCH_DIR16| OP_RMEM16 | STORE_HL ) ; 2A nn nn LD HL,(nn)
3804 .dw (FETCH_HL | OP_DEC16 | STORE_HL ) ; 2B DEC HL
3805 .dw (FETCH_L | OP_INC | STORE_L ) ; 2C INC L
3806 .dw (FETCH_L | OP_DEC | STORE_L ) ; 2D DEC L
3807 .dw (FETCH_DIR8 | OP_NOP | STORE_L ) ; 2E nn LD L,n
3808 .dw (FETCH_A | OP_CPL | STORE_A ) ; 2F CPL
3809 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 30 oo JR NC,o (Z80)
3810 .dw (FETCH_DIR16| OP_NOP | STORE_SP ) ; 31 nn nn LD SP,nn
3811 .dw (FETCH_DIR16| OP_NOP | STORE_AM ) ; 32 nn nn LD (nn),A
3812 .dw (FETCH_SP | OP_INC16 | STORE_SP ) ; 33 INC SP
3813 .dw (FETCH_MHL | OP_INC | STORE_MHL) ; 34 INC (HL)
3814 .dw (FETCH_MHL | OP_DEC | STORE_MHL) ; 35 DEC (HL)
3815 .dw (FETCH_DIR8 | OP_NOP | STORE_MHL) ; 36 nn LD (HL),n
3816 .dw (FETCH_NOP | OP_SCF | STORE_NOP) ; 37 SCF
3817 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 38 oo JR C,o (Z80)
3818 .dw (FETCH_SP | OP_ADDHL | STORE_HL ) ; 39 ADD HL,SP
3819 .dw (FETCH_DIR16| OP_RMEM8 | STORE_A ) ; 3A nn nn LD A,(nn)
3820 .dw (FETCH_SP | OP_DEC16 | STORE_SP ) ; 3B DEC SP
3821 .dw (FETCH_A | OP_INC | STORE_A ) ; 3C INC A
3822 .dw (FETCH_A | OP_DEC | STORE_A ) ; 3D DEC A
3823 .dw (FETCH_DIR8 | OP_NOP | STORE_A ) ; 3E nn LD A,n
3824 .dw (FETCH_NOP | OP_CCF | STORE_NOP) ; 3F CCF (Complement Carry Flag, gvd)
3825 .dw (FETCH_B | OP_NOP | STORE_B ) ; 40 LD B,r
3826 .dw (FETCH_C | OP_NOP | STORE_B ) ; 41 LD B,r
3827 .dw (FETCH_D | OP_NOP | STORE_B ) ; 42 LD B,r
3828 .dw (FETCH_E | OP_NOP | STORE_B ) ; 43 LD B,r
3829 .dw (FETCH_H | OP_NOP | STORE_B ) ; 44 LD B,r
3830 .dw (FETCH_L | OP_NOP | STORE_B ) ; 45 LD B,r
3831 .dw (FETCH_MHL | OP_NOP | STORE_B ) ; 46 LD B,r
3832 .dw (FETCH_A | OP_NOP | STORE_B ) ; 47 LD B,r
3833 .dw (FETCH_B | OP_NOP | STORE_C ) ; 48 LD C,r
3834 .dw (FETCH_C | OP_NOP | STORE_C ) ; 49 LD C,r
3835 .dw (FETCH_D | OP_NOP | STORE_C ) ; 4A LD C,r
3836 .dw (FETCH_E | OP_NOP | STORE_C ) ; 4B LD C,r
3837 .dw (FETCH_H | OP_NOP | STORE_C ) ; 4C LD C,r
3838 .dw (FETCH_L | OP_NOP | STORE_C ) ; 4D LD C,r
3839 .dw (FETCH_MHL | OP_NOP | STORE_C ) ; 4E LD C,r
3840 .dw (FETCH_A | OP_NOP | STORE_C ) ; 4F LD C,r
3841 .dw (FETCH_B | OP_NOP | STORE_D ) ; 50 LD D,r
3842 .dw (FETCH_C | OP_NOP | STORE_D ) ; 51 LD D,r
3843 .dw (FETCH_D | OP_NOP | STORE_D ) ; 52 LD D,r
3844 .dw (FETCH_E | OP_NOP | STORE_D ) ; 53 LD D,r
3845 .dw (FETCH_H | OP_NOP | STORE_D ) ; 54 LD D,r
3846 .dw (FETCH_L | OP_NOP | STORE_D ) ; 55 LD D,r
3847 .dw (FETCH_MHL | OP_NOP | STORE_D ) ; 56 LD D,r
3848 .dw (FETCH_A | OP_NOP | STORE_D ) ; 57 LD D,r
3849 .dw (FETCH_B | OP_NOP | STORE_E ) ; 58 LD E,r
3850 .dw (FETCH_C | OP_NOP | STORE_E ) ; 59 LD E,r
3851 .dw (FETCH_D | OP_NOP | STORE_E ) ; 5A LD E,r
3852 .dw (FETCH_E | OP_NOP | STORE_E ) ; 5B LD E,r
3853 .dw (FETCH_H | OP_NOP | STORE_E ) ; 5C LD E,r
3854 .dw (FETCH_L | OP_NOP | STORE_E ) ; 5D LD E,r
3855 .dw (FETCH_MHL | OP_NOP | STORE_E ) ; 5E LD E,r
3856 .dw (FETCH_A | OP_NOP | STORE_E ) ; 5F LD E,r
3857 .dw (FETCH_B | OP_NOP | STORE_H ) ; 60 LD H,r
3858 .dw (FETCH_C | OP_NOP | STORE_H ) ; 61 LD H,r
3859 .dw (FETCH_D | OP_NOP | STORE_H ) ; 62 LD H,r
3860 .dw (FETCH_E | OP_NOP | STORE_H ) ; 63 LD H,r
3861 .dw (FETCH_H | OP_NOP | STORE_H ) ; 64 LD H,r
3862 .dw (FETCH_L | OP_NOP | STORE_H ) ; 65 LD H,r
3863 .dw (FETCH_MHL | OP_NOP | STORE_H ) ; 66 LD H,r
3864 .dw (FETCH_A | OP_NOP | STORE_H ) ; 67 LD H,r
3865 .dw (FETCH_B | OP_NOP | STORE_L ) ; 68 LD L,r
3866 .dw (FETCH_C | OP_NOP | STORE_L ) ; 69 LD L,r
3867 .dw (FETCH_D | OP_NOP | STORE_L ) ; 6A LD L,r
3868 .dw (FETCH_E | OP_NOP | STORE_L ) ; 6B LD L,r
3869 .dw (FETCH_H | OP_NOP | STORE_L ) ; 6C LD L,r
3870 .dw (FETCH_L | OP_NOP | STORE_L ) ; 6D LD L,r
3871 .dw (FETCH_MHL | OP_NOP | STORE_L ) ; 6E LD L,r
3872 .dw (FETCH_A | OP_NOP | STORE_L ) ; 6F LD L,r
3873 .dw (FETCH_B | OP_NOP | STORE_MHL) ; 70 LD (HL),r
3874 .dw (FETCH_C | OP_NOP | STORE_MHL) ; 71 LD (HL),r
3875 .dw (FETCH_D | OP_NOP | STORE_MHL) ; 72 LD (HL),r
3876 .dw (FETCH_E | OP_NOP | STORE_MHL) ; 73 LD (HL),r
3877 .dw (FETCH_H | OP_NOP | STORE_MHL) ; 74 LD (HL),r
3878 .dw (FETCH_L | OP_NOP | STORE_MHL) ; 75 LD (HL),r
3879 .dw (FETCH_NOP | OP_NOP | STORE_NOP) ; 76 HALT
3880 .dw (FETCH_A | OP_NOP | STORE_MHL) ; 77 LD (HL),r
3881 .dw (FETCH_B | OP_NOP | STORE_A ) ; 78 LD A,r
3882 .dw (FETCH_C | OP_NOP | STORE_A ) ; 79 LD A,r
3883 .dw (FETCH_D | OP_NOP | STORE_A ) ; 7A LD A,r
3884 .dw (FETCH_E | OP_NOP | STORE_A ) ; 7B LD A,r
3885 .dw (FETCH_H | OP_NOP | STORE_A ) ; 7C LD A,r
3886 .dw (FETCH_L | OP_NOP | STORE_A ) ; 7D LD A,r
3887 .dw (FETCH_MHL | OP_NOP | STORE_A ) ; 7E LD A,r
3888 .dw (FETCH_A | OP_NOP | STORE_A ) ; 7F LD A,r
3889 .dw (FETCH_B | OP_ADDA | STORE_A ) ; 80 ADD A,r
3890 .dw (FETCH_C | OP_ADDA | STORE_A ) ; 81 ADD A,r
3891 .dw (FETCH_D | OP_ADDA | STORE_A ) ; 82 ADD A,r
3892 .dw (FETCH_E | OP_ADDA | STORE_A ) ; 83 ADD A,r
3893 .dw (FETCH_H | OP_ADDA | STORE_A ) ; 84 ADD A,r
3894 .dw (FETCH_L | OP_ADDA | STORE_A ) ; 85 ADD A,r
3895 .dw (FETCH_MHL | OP_ADDA | STORE_A ) ; 86 ADD A,r
3896 .dw (FETCH_A | OP_ADDA | STORE_A ) ; 87 ADD A,r
3897 .dw (FETCH_B | OP_ADCA | STORE_A ) ; 88 ADC A,r
3898 .dw (FETCH_C | OP_ADCA | STORE_A ) ; 89 ADC A,r
3899 .dw (FETCH_D | OP_ADCA | STORE_A ) ; 8A ADC A,r
3900 .dw (FETCH_E | OP_ADCA | STORE_A ) ; 8B ADC A,r
3901 .dw (FETCH_H | OP_ADCA | STORE_A ) ; 8C ADC A,r
3902 .dw (FETCH_L | OP_ADCA | STORE_A ) ; 8D ADC A,r
3903 .dw (FETCH_MHL | OP_ADCA | STORE_A ) ; 8E ADC A,r
3904 .dw (FETCH_A | OP_ADCA | STORE_A ) ; 8F ADC A,r
3905 .dw (FETCH_B | OP_SUBFA | STORE_A ) ; 90 SUB A,r
3906 .dw (FETCH_C | OP_SUBFA | STORE_A ) ; 91 SUB A,r
3907 .dw (FETCH_D | OP_SUBFA | STORE_A ) ; 92 SUB A,r
3908 .dw (FETCH_E | OP_SUBFA | STORE_A ) ; 93 SUB A,r
3909 .dw (FETCH_H | OP_SUBFA | STORE_A ) ; 94 SUB A,r
3910 .dw (FETCH_L | OP_SUBFA | STORE_A ) ; 95 SUB A,r
3911 .dw (FETCH_MHL | OP_SUBFA | STORE_A ) ; 96 SUB A,r
3912 .dw (FETCH_A | OP_SUBFA | STORE_A ) ; 97 SUB A,r
3913 .dw (FETCH_B | OP_SBCFA | STORE_A ) ; 98 SBC A,r
3914 .dw (FETCH_C | OP_SBCFA | STORE_A ) ; 99 SBC A,r
3915 .dw (FETCH_D | OP_SBCFA | STORE_A ) ; 9A SBC A,r
3916 .dw (FETCH_E | OP_SBCFA | STORE_A ) ; 9B SBC A,r
3917 .dw (FETCH_H | OP_SBCFA | STORE_A ) ; 9C SBC A,r
3918 .dw (FETCH_L | OP_SBCFA | STORE_A ) ; 9D SBC A,r
3919 .dw (FETCH_MHL | OP_SBCFA | STORE_A ) ; 9E SBC A,r
3920 .dw (FETCH_A | OP_SBCFA | STORE_A ) ; 9F SBC A,r
3921 .dw (FETCH_B | OP_ANDA | STORE_A ) ; A0 AND A,r
3922 .dw (FETCH_C | OP_ANDA | STORE_A ) ; A1 AND A,r
3923 .dw (FETCH_D | OP_ANDA | STORE_A ) ; A2 AND A,r
3924 .dw (FETCH_E | OP_ANDA | STORE_A ) ; A3 AND A,r
3925 .dw (FETCH_H | OP_ANDA | STORE_A ) ; A4 AND A,r
3926 .dw (FETCH_L | OP_ANDA | STORE_A ) ; A5 AND A,r
3927 .dw (FETCH_MHL | OP_ANDA | STORE_A ) ; A6 AND A,r
3928 .dw (FETCH_A | OP_ANDA | STORE_A ) ; A7 AND A,r
3929 .dw (FETCH_B | OP_XORA | STORE_A ) ; A8 XOR A,r
3930 .dw (FETCH_C | OP_XORA | STORE_A ) ; A9 XOR A,r
3931 .dw (FETCH_D | OP_XORA | STORE_A ) ; AA XOR A,r
3932 .dw (FETCH_E | OP_XORA | STORE_A ) ; AB XOR A,r
3933 .dw (FETCH_H | OP_XORA | STORE_A ) ; AC XOR A,r
3934 .dw (FETCH_L | OP_XORA | STORE_A ) ; AD XOR A,r
3935 .dw (FETCH_MHL | OP_XORA | STORE_A ) ; AE XOR A,r
3936 .dw (FETCH_A | OP_XORA | STORE_A ) ; AF XOR A,r
3937 .dw (FETCH_B | OP_ORA | STORE_A ) ; B0 OR A,r
3938 .dw (FETCH_C | OP_ORA | STORE_A ) ; B1 OR A,r
3939 .dw (FETCH_D | OP_ORA | STORE_A ) ; B2 OR A,r
3940 .dw (FETCH_E | OP_ORA | STORE_A ) ; B3 OR A,r
3941 .dw (FETCH_H | OP_ORA | STORE_A ) ; B4 OR A,r
3942 .dw (FETCH_L | OP_ORA | STORE_A ) ; B5 OR A,r
3943 .dw (FETCH_MHL | OP_ORA | STORE_A ) ; B6 OR A,r
3944 .dw (FETCH_A | OP_ORA | STORE_A ) ; B7 OR A,r
3945 .dw (FETCH_B | OP_SUBFA | STORE_NOP) ; B8 CP A,r
3946 .dw (FETCH_C | OP_SUBFA | STORE_NOP) ; B9 CP A,r
3947 .dw (FETCH_D | OP_SUBFA | STORE_NOP) ; BA CP A,r
3948 .dw (FETCH_E | OP_SUBFA | STORE_NOP) ; BB CP A,r
3949 .dw (FETCH_H | OP_SUBFA | STORE_NOP) ; BC CP A,r
3950 .dw (FETCH_L | OP_SUBFA | STORE_NOP) ; BD CP A,r
3951 .dw (FETCH_MHL | OP_SUBFA | STORE_NOP) ; BE CP A,r
3952 .dw (FETCH_A | OP_SUBFA | STORE_NOP) ; BF CP A,r
3953 .dw (FETCH_NOP | OP_IFNZ | STORE_RET) ; C0 RET NZ
3954 .dw (FETCH_NOP | OP_POP16 | STORE_BC ) ; C1 POP BC
3955 .dw (FETCH_DIR16| OP_IFNZ | STORE_PC ) ; C2 nn nn JP NZ,nn
3956 .dw (FETCH_DIR16| OP_NOP | STORE_PC ) ; C3 nn nn JP nn
3957 .dw (FETCH_DIR16| OP_IFNZ | STORE_CALL) ; C4 nn nn CALL NZ,nn
3958 .dw (FETCH_BC | OP_PUSH16 | STORE_NOP) ; C5 PUSH BC
3959 .dw (FETCH_DIR8 | OP_ADDA | STORE_A ) ; C6 nn ADD A,n
3960 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; C7 RST 0
3961 .dw (FETCH_NOP | OP_IFZ | STORE_RET) ; C8 RET Z
3962 .dw (FETCH_NOP | OP_NOP | STORE_RET) ; C9 RET
3963 .dw (FETCH_DIR16| OP_IFZ | STORE_PC ) ; CA nn nn JP Z,nn
3964 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; CB (Z80 specific)
3965 .dw (FETCH_DIR16| OP_IFZ | STORE_CALL) ; CC nn nn CALL Z,nn
3966 .dw (FETCH_DIR16| OP_NOP | STORE_CALL) ; CD nn nn CALL nn
3967 .dw (FETCH_DIR8 | OP_ADCA | STORE_A ) ; CE nn ADC A,n
3968 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; CF RST 8H
3969 .dw (FETCH_NOP | OP_IFNC | STORE_RET) ; D0 RET NC
3970 .dw (FETCH_NOP | OP_POP16 | STORE_DE ) ; D1 POP DE
3971 .dw (FETCH_DIR16| OP_IFNC | STORE_PC ) ; D2 nn nn JP NC,nn
3972 .dw (FETCH_DIR8 | OP_OUTA | STORE_NOP) ; D3 nn OUT (n),A
3973 .dw (FETCH_DIR16| OP_IFNC | STORE_CALL) ; D4 nn nn CALL NC,nn
3974 .dw (FETCH_DE | OP_PUSH16 | STORE_NOP) ; D5 PUSH DE
3975 .dw (FETCH_DIR8 | OP_SUBFA | STORE_A ) ; D6 nn SUB n
3976 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; D7 RST 10H
3977 .dw (FETCH_NOP | OP_IFC | STORE_RET) ; D8 RET C
3978 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; D9 EXX (Z80)
3979 .dw (FETCH_DIR16| OP_IFC | STORE_PC ) ; DA nn nn JP C,nn
3980 .dw (FETCH_DIR8 | OP_IN | STORE_A ) ; DB nn IN A,(n)
3981 .dw (FETCH_DIR16| OP_IFC | STORE_CALL) ; DC nn nn CALL C,nn
3982 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; DD (Z80)
3983 .dw (FETCH_DIR8 | OP_SBCFA | STORE_A ) ; DE nn SBC A,n
3984 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; DF RST 18H
3985 .dw (FETCH_NOP | OP_IFPO | STORE_RET) ; E0 RET PO
3986 .dw (FETCH_NOP | OP_POP16 | STORE_HL ) ; E1 POP HL
3987 .dw (FETCH_DIR16| OP_IFPO | STORE_PC ) ; E2 nn nn JP PO,nn
3988 .dw (FETCH_MSP | OP_EXHL | STORE_MSP) ; E3 EX (SP),HL
3989 .dw (FETCH_DIR16| OP_IFPO | STORE_CALL) ; E4 nn nn CALL PO,nn
3990 .dw (FETCH_HL | OP_PUSH16 | STORE_NOP) ; E5 PUSH HL
3991 .dw (FETCH_DIR8 | OP_ANDA | STORE_A ) ; E6 nn AND n
3992 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; E7 RST 20H
3993 .dw (FETCH_NOP | OP_IFPE | STORE_RET) ; E8 RET PE
3994 .dw (FETCH_HL | OP_NOP | STORE_PC ) ; E9 JP (HL)
3995 .dw (FETCH_DIR16| OP_IFPE | STORE_PC ) ; EA nn nn JP PE,nn
3996 .dw (FETCH_DE | OP_EXHL | STORE_DE ) ; EB EX DE,HL
3997 .dw (FETCH_DIR16| OP_IFPE | STORE_CALL) ; EC nn nn CALL PE,nn
3998 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; ED (Z80 specific)
3999 .dw (FETCH_DIR8 | OP_XORA | STORE_A ) ; EE nn XOR n
4000 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; EF RST 28H
4001 .dw (FETCH_NOP | OP_IFP | STORE_RET) ; F0 RET P
4002 .dw (FETCH_NOP | OP_POP16 | STORE_AF ) ; F1 POP AF
4003 .dw (FETCH_DIR16| OP_IFP | STORE_PC ) ; F2 nn nn JP P,nn
4004 .dw (FETCH_NOP | OP_DI | STORE_NOP) ; F3 DI
4005 .dw (FETCH_DIR16| OP_IFP | STORE_CALL) ; F4 nn nn CALL P,nn
4006 .dw (FETCH_AF | OP_PUSH16 | STORE_NOP) ; F5 PUSH AF
4007 .dw (FETCH_DIR8 | OP_ORA | STORE_A ) ; F6 nn OR n
4008 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; F7 RST 30H
4009 .dw (FETCH_NOP | OP_IFM | STORE_RET) ; F8 RET M
4010 .dw (FETCH_HL | OP_NOP | STORE_SP ) ; F9 LD SP,HL
4011 .dw (FETCH_DIR16| OP_IFM | STORE_PC ) ; FA nn nn JP M,nn
4012 .dw (FETCH_NOP | OP_EI | STORE_NOP) ; FB EI
4013 .dw (FETCH_DIR16| OP_IFM | STORE_CALL) ; FC nn nn CALL M,nn
4014 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; FD (Z80 specific)
4015 .dw (FETCH_DIR8 | OP_SUBFA | STORE_NOP) ; FE nn CP n
4016 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; FF RST 38H
4018 ; vim:set ts=8 noet nowrap