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/>.
25 #elif defined atmega168
26 .include "m168def.inc"
27 #elif defined atmega328P
28 .include "m328Pdef.inc"
40 #define F_CPU 20000000 /* system clock in Hz; defaults to 20MHz */
43 #define BAUD 38400 /* console baud rate */
46 #define PARTID 0x52 /* Partition table id */
47 /* http://www.win.tue.nl/~aeb/partitions/partition_types-1.html */
49 #define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) /* clever rounding */
51 #define RXBUFSIZE 64 /* USART recieve buffer size. Must be power of 2 */
52 #define TXBUFSIZE 64 /* USART transmit buffer size. Must be power of 2 */
54 #define DRAM_WAITSTATES 1 /* Number of additional clock cycles for dram read access */
55 #define REFR_RATE 64000 /* dram refresh rate in cycles/s. */
56 /* Most drams need 1/15.6µs. */
57 #define REFR_PRE 8 /* timer prescale factor */
58 #define REFR_CS 0x02 /* timer clock select for 1/8 */
59 #define REFR_CNT F_CPU / REFR_RATE / REFR_PRE
63 #define DRAM_WORD_ACCESS 0 /* experimental */
65 #define EM_Z80 0 /* we don't have any z80 instructions yet */
94 .equ RAM_AH_MASK = (1<<ram_a8)|(1<<ram_a7)|(1<<ram_a6)|(1<<ram_a5)
95 .equ PD_OUTPUT_MASK = (1<<mmc_cs) | (1<<ram_oe) | RAM_AH_MASK
113 .equ RAM_AL_MASK = (1<<ram_a4)|(1<<ram_a3)|(1<<ram_a2)|(1<<ram_a1)|(1<<ram_a0)
114 .equ PB_OUTPUT_MASK = (1<<ram_ras) | RAM_AL_MASK
127 .equ RAM_DQ_MASK = (1<<ram_d3)|(1<<ram_d2)|(1<<ram_d1)|(1<<ram_d0)
128 .equ PC_OUTPUT_MASK = (1<<ram_cas)|(1<<ram_w)
131 ;Flag bits in z_flags
139 ;Register definitions
175 #if defined __ATmega8__
184 .equ hostact = 7 ;host active flag
185 .equ hostwrt = 6 ;host written flag
186 .equ rsflag = 5 ;read sector flag
187 .equ readop = 4 ;1 if read operation
190 ; This is the base z80 port address for clock access
191 #define TIMERPORT 0x40
192 #define TIMER_CTL TIMERPORT
193 #define TIMER_MSECS TIMERPORT+1
194 #define TIMER_SECS TIMER_MSECS+2
196 #define starttimercmd 1
197 #define quitTimerCmd 2
198 #define printTimerCmd 15
201 #if defined __ATmega8__
216 .equ OC2Aaddr= OC2addr
229 ;----------------------------------------
239 ;----------------------------------------
251 ;----------------------------------------
253 ; dram_wait number_of_cycles
268 rjmp start ; reset vector
270 rjmp refrint ; tim2cmpa
271 .org OC1Aaddr ; Timer/Counter1 Compare Match A
272 rjmp sysclockint ; 1ms system timer
274 rjmp rxint ; USART receive int.
276 rjmp txint ; USART transmit int.
278 .org INT_VECTORS_SIZE
281 ldi temp,low(RAMEND) ; top of memory
282 out SPL,temp ; init stack pointer
283 ldi temp,high(RAMEND) ; top of memory
284 out SPH,temp ; init stack pointer
292 ldi temp,(1<<WDCE) | (1<<WDE)
299 ldi zl,low(SRAM_START)
300 ldi zh,high(SRAM_START)
301 ldi temp2,high(ramtop)
309 ldi temp,(1<<PUD) ;disable pullups
312 out PORTD,temp ;all pins high
315 out DDRD,temp ; all outputs
327 ldi temp, (1<<TXEN0) | (1<<RXEN0) | (1<<RXCIE0)
330 ldi temp, (1<<URSEL) | (1<<UCSZ01) | (1<<UCSZ00)
332 ldi temp, (1<<UCSZ01) | (1<<UCSZ00)
335 ldi temp, HIGH(UBRR_VAL)
337 ldi temp, LOW(UBRR_VAL)
340 ; Init clock/timer system
342 ; Init timer 1 as 1 ms system clock tick.
344 ldi temp,high(F_CPU/1000)
346 ldi temp,low(F_CPU/1000)
348 ldi temp,(1<<WGM12) | (1<<CS10) ;CTC, clk/1
354 ;Init timer2. Refresh-call should happen every (8ms/512)=312 cycles.
356 ldi temp,REFR_CNT*2 ; 2 cycles per int
359 ori temp,(1<<WGM21) ;CTC mode
362 ori temp,REFR_CS ;clk/REFR_PRE
365 ori temp, (1<<OCIE2A)
378 .db "CPM on an AVR, v1.0",13,0,0
383 .db "Testing RAM: fill...",0,0
405 .db "reread...",13,0,0
437 ;Fill ram with cbs, which (for now) will trigger an invalid opcode error.
449 .db "Initing mmc...",13,0
452 ;----------------------------------------------------------------------------
454 ; Partition table offsets:
459 ;Load first sector from MMC (boot sector)
468 ;Test, if it has a valid MBR
470 lds temp,hostbuf+510 ;MBR signature (0xAA55) at and of sector?
471 lds temp2,hostbuf+511
477 ;No MBR, no partition table ...
482 ;Search Partition Table for CP/M partitions
484 ldi zl,low(hostbuf+510-64)
485 ldi zh,high(hostbuf+510-64)
486 ldi yl,low(hostdstart)
487 ldi yh,high(hostdstart)
489 ldi oph,high(hostbuf+510)
495 ldd temp,z+PART_START
497 ldd temp2,z+PART_START+1
499 ldd temp3,z+PART_START+2
501 ldd temp4,z+PART_START+3
505 .db "CP/M partition at: ",0
510 ldd temp2,z+PART_SIZE+1
511 ldd temp3,z+PART_SIZE+2
512 ldd temp4,z+PART_SIZE+3
526 cpi zl,low(hostbuf+510)
533 ; Read first sector of first CP/M partition
546 .db "No bootable CP/M disk found! Please change MMC/SD-Card",13,0
558 ;First sector of disk or first CP/M partition is in hostbuf.
560 ;Save to Z80 RAM (only 128 bytes because that's retro)
569 cpi zl,low(hostbuf+128)
571 cpi zh,high(hostbuf+128)
573 rcall dsk_boot ;init (de)blocking buffer
584 .db 13,"Ok, CPU is live!",13,0,0
613 ; *** Stage 1: Fetch next opcode
636 ; *** Stage 2: Decode it using the ins_table.
637 ldi zh,high(inst_table*2)
658 ; *** Stage 3: Fetch operand. Use the fetch jumptable for this.
662 ldi zl,low(fetchjumps)
663 ldi zh,high(fetchjumps)
683 ; *** Stage 4: Execute operation :) Use the op jumptable for this.
699 .db ",post:oph:l=",0,0
708 ; *** Stage 5: Store operand. Use the store jumptable for this.
717 ldi zl,low(storejumps)
718 ldi zh,high(storejumps)
745 ; ----------------Virtual peripherial interface ------
747 ;The hw is modelled to make writing a CPM BIOS easier.
749 ;0 - Con status. Returns 0xFF if the UART has a byte, 0 otherwise.
750 ;1 - Console input, aka UDR.
753 ;16,17 - Track select
757 ;22 - Trigger - write to read, to write a sector using the above info;
758 ; , write to allocated/dirctory/unallocated
767 ;*****************************************************
768 ;* CP/M to host disk constants *
769 ;*****************************************************
770 .equ MAXDISKS = 4 ;Max number of Disks (partitions)
771 .equ blksize = 1024 ;CP/M allocation size
772 .equ hostsize = 512 ;host disk sector size
773 ; .equ hostspt = 20 ;host disk sectors/trk
774 .equ hostblk = hostsize/128 ;CP/M sects/host buff
775 ; .equ CPMSPT = hostblk*hostspt;CP/M sectors/track
777 .equ SECMSK = hostblk-1 ;sector mask
778 .equ SECSHF = log2(hostblk) ;sector shift
780 ;*****************************************************
781 ;* BDOS constants on entry to write *
782 ;*****************************************************
783 .equ WRALL = 0 ;write to allocated
784 .equ WRDIR = 1 ;write to directory
785 .equ WRUAL = 2 ;write to unallocated
786 .equ WRTMSK= 3 ;write type mask
790 ndisks: .byte 1 ;Number of CP/M disks
792 seekdsk: .byte 1 ;seek disk number
793 seektrk: .byte 2 ;seek track number
794 seeksec: .byte 1 ;seek sector number
796 hostdsk: .byte 1 ;host disk number
797 hostlba: .byte 3 ;host sector number (relative to partition start)
798 hostdstart: .byte 4*MAXDISKS ; host disks start sector (partition)
800 unacnt: .byte 1 ;unalloc rec cnt
801 unadsk: .byte 1 ;last unalloc disk
802 unatrk: .byte 2 ;last unalloc track
803 unasec: .byte 1 ;last unalloc sector
805 erflag: .byte 1 ;error reporting
806 wrtype: .byte 1 ;write operation type
807 dmaadr: .byte 2 ;last dma address
808 hostbuf: .byte hostsize;host buffer (from/to SD-card)
813 ;Called with port in temp2. Should return value in temp.
823 cpi temp2,TIMER_MSECS
825 cpi temp2,TIMER_MSECS+6
833 ;Called with port in temp2 and value in temp.
858 cpi temp2,TIMER_MSECS+6
891 lds temp2,ndisks ;check if selected disk # is less then # of disks
895 ldi temp,0xff ;error return
924 ;See what has to be done.
935 .db "DISK I/O: Invalid Function code: ",0
940 cbi flags,hostact ;host buffer inactive
941 sts unacnt,_0 ;clear unalloc count
945 sbis flags,hostwrt ;check for pending write
946 cbi flags,hostact ;clear host active flag
963 .db "Disk read: track ",0
983 sbi flags,readop ;read operation
984 sbi flags,rsflag ;must read data
985 ldi temp,WRUAL ;write type
986 sts wrtype,temp ;treat as unalloc
987 rjmp dsk_rwoper ;to perform the read
991 ;write the selected CP/M sector
994 sts wrtype,temp ;save write type
995 cbi flags,readop ;not a read operation
1002 .db "Disk write: track ",0,0
1012 .db " dma-addr ",0,0
1026 cpi temp,WRUAL ;write unallocated?
1027 brne dsk_chkuna ;check for unalloc
1029 ; write to unallocated, set parameters
1030 ldi temp,blksize/128 ;next unalloc recs
1032 lds temp,seekdsk ;disk to seek
1033 sts unadsk,temp ;unadsk = sekdsk
1035 sts unatrk,temp ;unatrk = sectrk
1037 sts unatrk+1,temp ;unatrk = sectrk
1039 sts unasec,temp ;unasec = seksec
1042 ;check for write to unallocated sector
1043 lds temp,unacnt ;any unalloc remain?
1045 breq dsk_alloc ;skip if not
1047 ; more unallocated records remain
1048 dec temp ;unacnt = unacnt-1
1050 lds temp,seekdsk ;same disk?
1052 cp temp,temp2 ;seekdsk = unadsk?
1053 brne dsk_alloc ;skip if not
1055 ; disks are the same
1060 cp temp,temp3 ;seektrk = unatrk?
1062 brne dsk_alloc ;skip if not
1064 ; tracks are the same
1065 lds temp,seeksec ;same sector?
1067 cp temp,temp2 ;seeksec = unasec?
1068 brne dsk_alloc ;skip if not
1070 ; match, move to next sector for future ref
1071 inc temp2 ;unasec = unasec+1
1073 cpi temp2,CPMSPT ;end of track? (count CP/M sectors)
1074 brlo dsk_noovf ;skip if no overflow
1076 ; overflow to next track
1077 sts unasec,_0 ;unasec = 0
1080 subi temp, low(-1) ;unatrk = unatrk+1
1086 cbi flags,rsflag ;rsflag = 0
1087 rjmp dsk_rwoper ;to perform the write
1090 ;not an unallocated record, requires pre-read
1091 sts unacnt,_0 ;unacnt = 0
1092 sbi flags,rsflag ;rsflag = 1
1094 ;*****************************************************
1095 ;* Common code for READ and WRITE follows *
1096 ;*****************************************************
1099 ;enter here to perform the read/write
1100 sts erflag,_0 ;no errors (yet)
1102 ;Convert track/sector to an LBA address (in 128byte blocks)
1108 lds temp4,seektrk+1 ;
1114 add xh,r0 ;xh:xl := sec + trk * SectorsPerTrack
1119 andi temp,SECMSK ;mask buffer number
1120 push temp ;save for later
1122 ;Convert from CP/M LBA blocks to host LBA blocks
1130 ;yl:xh:xl = host block to seek
1131 ; active host sector?
1132 sbis flags,hostact ;host active?
1133 rjmp dsk_filhst ;fill host if not
1135 ; host buffer active, same as seek buffer?
1137 lds temp2,hostdsk ;same disk?
1138 cp temp,temp2 ;seekdsk = hostdsk?
1141 ; same disk, same block?
1151 ;proper disk, but not correct sector
1152 sbic flags,hostwrt ;host written?
1153 rcall dsk_writehost ;clear host buff
1156 ;may have to fill the host buffer
1163 sbic flags,rsflag ;need to read?
1164 rcall dsk_readhost ;yes, if 1
1165 cbi flags,hostwrt ;no pending write
1168 sbi flags,hostact ;host buffer active now
1170 ;copy data to or from buffer
1172 ldi zh,high(hostbuf)
1174 pop temp2 ;get buffer number (which part of hostbuf)
1176 add zl,r0 ;offset in hostbuf
1183 .db "; host buf adr: ",0,0
1193 ldi temp3,128 ;length of move
1194 sbic flags,readop ;which way?
1195 rjmp dsk_rmove ;skip if read
1197 ; mark write operation
1198 sbi flags,hostwrt ;hostwrt = 1
1214 ; data has been moved to/from host buffer
1215 lds temp,wrtype ;write type
1216 cpi temp,WRDIR ;to directory?
1224 ret ;no further processing
1226 ; clear host buffer for directory write
1232 rcall dsk_writehost ;clear host buff
1233 cbi flags,hostwrt ;buffer written
1238 ;*****************************************************
1239 ;* WRITEhost performs the physical write to *
1240 ;* the host disk, READhost reads the physical *
1242 ;*****************************************************
1245 ;hostdsk = host disk #, hostlba = host block #.
1246 ;Write "hostsize" bytes from hostbuf and return
1247 ;error flag in erflag.
1248 ;Return erflag non-zero if error
1254 ldi zl,low(hostdstart)
1255 ldi zh,high(hostdstart)
1282 ;hostdsk = host disk #, hostlba = host block #.
1283 ;Read "hostsiz" bytes into hostbuf and return
1284 ;error flag in erflag.
1290 ldi zl,low(hostdstart)
1291 ldi zh,high(hostdstart)
1318 ;***************************************************************************
1320 ; ----------------- MMC/SD routines ------------------
1349 ;Wait till the mmc answers with the response in temp2, or till a timeout happens.
1356 brne mmcWaitResploopEnd
1360 rjmp mmcWaitResploop
1369 .db ": Error: MMC resp timeout!",13,0
1376 ;Init start: send 80 clocks with cs disabled
1380 ldi temp2,10 ; exactly 80 clocks
1402 ldi temp,0xff ;dummy
1404 ldi temp,0xff ;dummy
1418 ldi temp,0xff ;return byte
1421 ldi temp2,0 ;Error Code 0
1422 rcall mmcWaitResp ;Test on CMD0 is OK
1424 sbi P_MMC_CS,mmc_cs ;disable /CS
1428 ;Read OCR till card is ready
1429 ldi temp2,20 ;repeat counter
1433 cbi P_MMC_CS,mmc_cs ;enable /CS
1434 ldi temp,0xff ;dummy
1446 ; ldi temp,0x95 ;crc
1452 rcall mmcWaitResp ;wait until mmc-card send a byte <> 0xFF
1453 ;the first answer must be 0x01 (Idle-Mode)
1455 breq mmcInitOcrLoopDone ;second answer is 0x00 (Idle-Mode leave) CMD1 is OK
1457 sbi P_MMC_CS,mmc_cs ;disable /CS
1459 ; rcall mmcByteNoSend ;unnecessary
1467 brne mmcInitOcrLoop ;repeat
1474 sbi P_MMC_CS,mmc_cs ;disable /CS
1481 ;Call this with yh:yl:xh:xl = sector number
1489 ldi temp,0x51 ;cmd (read sector)
1491 lsl xl ;convert to byte address (*512)
1504 ldi temp,0xff ;return byte
1515 ;Read sector to AVR RAM
1517 ldi zh,high(hostbuf)
1521 cpi zl,low(hostbuf+512)
1523 cpi zh,high(hostbuf+512)
1537 ;Call this with yh:yl:xh:xl = sector number
1546 ldi temp,0x58 ;cmd (write sector)
1548 lsl xl ;convert to byte address (*512)
1561 ldi temp,0xff ;return byte
1572 ;Write sector from AVR RAM
1574 ldi zh,high(hostbuf)
1578 cpi zl,low(hostbuf+512)
1580 cpi zh,high(hostbuf+512)
1587 ;Status. Ignored for now.
1590 ;Wait till the mmc has written everything
1603 ;Set up wdt to time out after 1 sec.
1608 ldi temp,(1<<WDCE) | (1<<WDE) | (110<<WDP0)
1613 ; ------------------ DRAM routines -------------
1615 ; DRAM_SETADDR val, low_and_mask, low_or_mask, high_and_mask, high_or_mask
1630 ori temp, @4 | (1<<mmc_cs)
1634 ;Loads the byte on address xh:xl into temp.
1635 ;must not alter xh:xl
1639 DRAM_SETADDR xh, ~0,(1<<ram_ras), ~(1<<ram_a8), (1<<ram_oe)
1641 DRAM_SETADDR xl, ~(1<<ram_ras),0, ~((1<<ram_oe)), (1<<ram_a8)
1644 dram_wait DRAM_WAITSTATES ;
1645 in temp,P_DQ-2 ; PIN
1651 dram_wait DRAM_WAITSTATES ;
1652 in temp2,P_DQ-2 ; PIN
1662 #if DRAM_WORD_ACCESS
1677 DRAM_SETADDR xh, ~0,(1<<ram_ras), ~(1<<ram_a8),(1<<ram_oe)
1679 DRAM_SETADDR xl, ~(1<<ram_ras),0, ~((1<<ram_oe)), (1<<ram_a8)
1683 in temp,P_DQ-2 ; PIN
1689 in temp2,P_DQ-2 ; PIN
1697 DRAM_SETADDR xl, ~(1<<ram_ras),0, ~((1<<ram_oe)), (1<<ram_a8)
1701 in temp,P_DQ-2 ; PIN
1707 in temp2,P_DQ-2 ; PIN
1720 ;Writes the byte in temp to xh:xl
1721 ;must not alter xh:xl
1725 ldi temp2,RAM_DQ_MASK | (1<<ram_w) | (1<<ram_cas)
1729 andi temp,RAM_DQ_MASK & ~(1<<ram_w)
1730 ori temp,(1<<ram_cas)
1732 DRAM_SETADDR xh, ~0,(1<<ram_ras), ~(1<<ram_a8),(1<<ram_oe)
1734 DRAM_SETADDR xl, ~(1<<ram_ras),0, ~((1<<ram_a8)),(1<<ram_oe)
1741 andi temp2,RAM_DQ_MASK & ~(1<<ram_w)
1742 ori temp2,(1<<ram_cas)
1748 ldi temp,~RAM_DQ_MASK | (1<<ram_w) | (1<<ram_cas)
1754 #if DRAM_WORD_ACCESS
1769 ldi temp2,RAM_DQ_MASK | (1<<ram_w) | (1<<ram_cas)
1773 andi temp,RAM_DQ_MASK & ~(1<<ram_w)
1774 ori temp,(1<<ram_cas)
1777 DRAM_SETADDR xh, ~0,(1<<ram_ras), ~(1<<ram_a8),(1<<ram_oe)
1779 DRAM_SETADDR xl, ~(1<<ram_ras),0, ~((1<<ram_a8)),(1<<ram_oe)
1786 andi temp2,RAM_DQ_MASK & ~(1<<ram_w)
1787 ori temp2,(1<<ram_cas)
1796 andi temp,RAM_DQ_MASK & ~(1<<ram_w)
1797 ori temp,(1<<ram_cas)
1800 DRAM_SETADDR xl, ~(1<<ram_ras),0, ~((1<<ram_a8)),(1<<ram_oe)
1807 andi temp2,RAM_DQ_MASK & ~(1<<ram_w)
1808 ori temp2,(1<<ram_cas)
1814 ldi temp,~RAM_DQ_MASK | (1<<ram_w) | (1<<ram_cas)
1821 ; ****************************************************************************
1823 ; refresh interupt; exec 2 cbr cycles
1826 cbi P_CAS,ram_cas ;2 1| 1|
1828 cbi P_RAS,ram_ras ;2 |0 1|
1832 sbi P_RAS,ram_ras ;2 |0 |0
1834 dram_wait DRAM_WAITSTATES-1 ;
1836 cbi P_RAS,ram_ras ;2 |0 1|
1838 sbi P_CAS,ram_cas ;2 |0 |0
1840 sbi P_RAS,ram_ras ;2 1| |0
1842 reti ;4 --> 21 cycles
1845 ; ------------- system timer 1ms ---------------
1855 ; don't change order here, clock put/get depends on it.
1856 cntms_out: ; register for ms
1858 utime_io: ; register for uptime.
1865 .equ timer_size = timer_top - timer_base
1867 .equ clkofs = cnt_1ms-cntms_out
1868 .equ timerofs = cnt_1ms-timer_ms
1889 ldi zl,high(1000) ;doesn't change flags
1922 sts delay_timer,temp
1924 lds temp,delay_timer
1933 subi temp2,TIMER_MSECS
1934 brcs clkget_end ;Port number in range?
1935 ldi zl,low(cntms_out)
1936 ldi zh,high(cntms_out)
1937 breq clkget_copy ;lowest byte requestet, latch clock
1939 brsh clkget_end ;Port number to high?
1964 subi temp2,TIMERPORT
1965 brcs clkput_end ;Port number in range?
1970 cpi temp,starttimercmd
1972 cpi temp,quitTimerCmd
1974 cpi temp,printTimerCmd
1988 ldi zl,low(cntms_out)
1989 ldi zh,high(cntms_out)
1990 breq clkput_copy ;lowest byte requestet, latch clock
1992 brsh clkput_end ;Port number to high?
2017 ldi zl,low(timer_ms)
2018 ldi zh,high(timer_ms)
2036 ldi zl,low(timer_ms)
2037 ldi zh,high(timer_ms)
2039 ; put ms on stack (16 bit)
2061 ldd temp2,z+timerofs
2065 ldd temp3,z+timerofs
2070 ldd temp4,z+timerofs
2075 .db 13,"Timer running. Elapsed: ",0
2095 ldi zh,high(cnt_1ms)
2128 ; --------------- Debugging stuff ---------------
2130 ;Print a unsigned lonng value to the uart
2131 ; temp4:temp3:temp2:temp = value
2138 clr yl ;yl = stack level
2140 ultoa1: ldi z_flags, 32 ;yh = temp4:temp % 10
2141 clr yh ;temp4:temp /= 10
2153 cpi yh, 10 ;yh is a numeral digit '0'-'9'
2157 cp temp,_0 ;Repeat until temp4:temp gets zero
2164 ultoa5: cpi yl,3 ; at least 3 digits (ms)
2170 ultoa6: pop temp ;Flush stacked digits
2181 ;Prints the lower nibble of temp in hex to the uart
2197 ;Prints temp in hex to the uart
2205 ;Prints the zero-terminated string following the call statement.
2245 ; --------------- AVR HW <-> Z80 periph stuff ------------------
2247 .equ memReadByte = dram_read
2248 .equ memWriteByte = dram_write
2249 #if DRAM_WORD_ACCESS
2250 .equ memReadWord = dram_read_w
2251 .equ memWriteWord = dram_write_w
2254 ; --------------------------------------------------------------
2258 #define RXBUFMASK RXBUFSIZE-1
2259 #define TXBUFMASK TXBUFSIZE-1
2281 ; Save received character in a circular buffer. Do nothing if buffer overflows.
2290 lds zh,rxcount ;if rxcount < RXBUFSIZE
2291 cpi zh,RXBUFSIZE ; (room for at least 1 char?)
2294 sts rxcount,zh ; rxcount++
2296 ldi zl,low(rxfifo) ;
2301 sts rxidx_w,zh ; rxidx_w = ++rxidx_w % RXBUFSIZE
2302 ldi zh,high(rxfifo) ;
2305 st z,temp ; rxfifo[rxidx_w] = char
2315 ;Fetches a char from the buffer to temp. If none available, waits till one is.
2318 lds temp,rxcount ; Number of characters in buffer
2338 ld temp,z ;don't forget to get the char
2347 lds temp,txcount ;if txcount != 0
2352 sts txcount,temp ; --txcount
2355 ldi zl,low(txfifo) ;
2356 ldi zh,high(txfifo) ;
2362 andi temp,TXBUFMASK ;
2372 ldi temp, (1<<TXEN0) | (1<<RXEN0) | (1<<RXCIE0)
2381 ;Sends a char from temp to the uart.
2387 lds temp,txcount ;do {
2388 cpi temp,TXBUFSIZE ;
2389 brsh putc_l ;} while (txcount >= TXBUFSIZE)
2391 ldi zl,low(txfifo) ;
2392 ldi zh,high(txfifo) ;
2398 andi temp,TXBUFMASK ;
2399 sts txidx_w,temp ; txidx_w = ++txidx_w % TXBUFSIZE
2401 st z,temp ; txfifo[txidx_w] = char
2406 ldi zl, (1<<UDRIE0) | (1<<TXEN0) | (1<<RXEN0) | (1<<RXCIE0)
2413 ; ------------ Fetch phase stuff -----------------
2415 .equ FETCH_NOP = (0<<0)
2416 .equ FETCH_A = (1<<0)
2417 .equ FETCH_B = (2<<0)
2418 .equ FETCH_C = (3<<0)
2419 .equ FETCH_D = (4<<0)
2420 .equ FETCH_E = (5<<0)
2421 .equ FETCH_H = (6<<0)
2422 .equ FETCH_L = (7<<0)
2423 .equ FETCH_AF = (8<<0)
2424 .equ FETCH_BC = (9<<0)
2425 .equ FETCH_DE = (10<<0)
2426 .equ FETCH_HL = (11<<0)
2427 .equ FETCH_SP = (12<<0)
2428 .equ FETCH_MBC = (13<<0)
2429 .equ FETCH_MDE = (14<<0)
2430 .equ FETCH_MHL = (15<<0)
2431 .equ FETCH_MSP = (16<<0)
2432 .equ FETCH_DIR8 = (17<<0)
2433 .equ FETCH_DIR16= (18<<0)
2434 .equ FETCH_RST = (19<<0)
2437 ;Jump table for fetch routines. Make sure to keep this in sync with the .equs!
2532 #if DRAM_WORD_ACCESS
2553 #if DRAM_WORD_ACCESS
2578 ; ------------ Store phase stuff -----------------
2580 .equ STORE_NOP = (0<<5)
2581 .equ STORE_A = (1<<5)
2582 .equ STORE_B = (2<<5)
2583 .equ STORE_C = (3<<5)
2584 .equ STORE_D = (4<<5)
2585 .equ STORE_E = (5<<5)
2586 .equ STORE_H = (6<<5)
2587 .equ STORE_L = (7<<5)
2588 .equ STORE_AF = (8<<5)
2589 .equ STORE_BC = (9<<5)
2590 .equ STORE_DE = (10<<5)
2591 .equ STORE_HL = (11<<5)
2592 .equ STORE_SP = (12<<5)
2593 .equ STORE_PC = (13<<5)
2594 .equ STORE_MBC = (14<<5)
2595 .equ STORE_MDE = (15<<5)
2596 .equ STORE_MHL = (16<<5)
2597 .equ STORE_MSP = (17<<5)
2598 .equ STORE_RET = (18<<5)
2599 .equ STORE_CALL = (19<<5)
2600 .equ STORE_AM = (20<<5)
2602 ;Jump table for store routines. Make sure to keep this in sync with the .equs!
2698 #if DRAM_WORD_ACCESS
2739 ; ------------ Operation phase stuff -----------------
2742 .equ OP_NOP = (0<<10)
2743 .equ OP_INC = (1<<10)
2744 .equ OP_DEC = (2<<10)
2745 .equ OP_INC16 = (3<<10)
2746 .equ OP_DEC16 = (4<<10)
2747 .equ OP_RLC = (5<<10)
2748 .equ OP_RRC = (6<<10)
2749 .equ OP_RR = (7<<10)
2750 .equ OP_RL = (8<<10)
2751 .equ OP_ADDA = (9<<10)
2752 .equ OP_ADCA = (10<<10)
2753 .equ OP_SUBFA = (11<<10)
2754 .equ OP_SBCFA = (12<<10)
2755 .equ OP_ANDA = (13<<10)
2756 .equ OP_ORA = (14<<10)
2757 .equ OP_XORA = (15<<10)
2758 .equ OP_ADDHL = (16<<10)
2759 .equ OP_STHL = (17<<10) ;store HL in fetched address
2760 .equ OP_RMEM16 = (18<<10) ;read mem at fetched address
2761 .equ OP_RMEM8 = (19<<10) ;read mem at fetched address
2762 .equ OP_DA = (20<<10)
2763 .equ OP_SCF = (21<<10)
2764 .equ OP_CPL = (22<<10)
2765 .equ OP_CCF = (23<<10)
2766 .equ OP_POP16 = (24<<10)
2767 .equ OP_PUSH16 = (25<<10)
2768 .equ OP_IFNZ = (26<<10)
2769 .equ OP_IFZ = (27<<10)
2770 .equ OP_IFNC = (28<<10)
2771 .equ OP_IFC = (29<<10)
2772 .equ OP_IFPO = (30<<10)
2773 .equ OP_IFPE = (31<<10)
2774 .equ OP_IFP = (32<<10)
2775 .equ OP_IFM = (33<<10)
2776 .equ OP_OUTA = (34<<10)
2777 .equ OP_IN = (35<<10)
2778 .equ OP_EXHL = (36<<10)
2779 .equ OP_DI = (37<<10)
2780 .equ OP_EI = (38<<10)
2781 .equ OP_INV = (39<<10)
2782 .equ OP_CPFA = (40<<10)
2783 .equ OP_INCA = (41<<10)
2784 .equ OP_DECA = (42<<10)
2832 ;How the flags are supposed to work:
2833 ;7 ZFL_S - Sign flag (=MSBit of result)
2834 ;6 ZFL_Z - Zero flag. Is 1 when the result is 0
2835 ;4 ZFL_H - Half-carry (carry from bit 3 to 4)
2836 ;2 ZFL_P - Parity/2-complement Overflow
2837 ;1 ZFL_N - Subtract - set if last op was a subtract
2840 ;I sure hope I got the mapping between flags and instructions correct...
2842 ;----------------------------------------------------------------
2846 ;| ZZZZZZZ 88888 000 |
2852 ;| ZZZZZZZ 88888 000 |
2854 ;| Z80 MICROPROCESSOR Instruction Set Summary |
2856 ;----------------------------------------------------------------
2857 ;----------------------------------------------------------------
2858 ;|Mnemonic |SZHPNC|Description |Notes |
2859 ;|----------+------+---------------------+----------------------|
2860 ;|ADC A,s |***V0*|Add with Carry |A=A+s+CY |
2861 ;|ADC HL,ss |**?V0*|Add with Carry |HL=HL+ss+CY |
2862 ;|ADD A,s |***V0*|Add |A=A+s |
2863 ;|ADD HL,ss |--?-0*|Add |HL=HL+ss |
2864 ;|ADD IX,pp |--?-0*|Add |IX=IX+pp |
2865 ;|ADD IY,rr |--?-0*|Add |IY=IY+rr |
2866 ;|AND s |**1P00|Logical AND |A=A&s |
2867 ;|BIT b,m |?*1?0-|Test Bit |m&{2^b} |
2868 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
2869 ;|CALL nn |------|Unconditional Call |-[SP]=PC,PC=nn |
2870 ;|CCF |--?-0*|Complement Carry Flag|CY=~CY |
2871 ;|CP s |***V1*|Compare |A-s |
2872 ;|CPD |****1-|Compare and Decrement|A-[HL],HL=HL-1,BC=BC-1|
2873 ;|CPDR |****1-|Compare, Dec., Repeat|CPD till A=[HL]or BC=0|
2874 ;|CPI |****1-|Compare and Increment|A-[HL],HL=HL+1,BC=BC-1|
2875 ;|CPIR |****1-|Compare, Inc., Repeat|CPI till A=[HL]or BC=0|
2876 ;|CPL |--1-1-|Complement |A=~A |
2877 ;|DAA |***P-*|Decimal Adjust Acc. |A=BCD format |
2878 ;|DEC s |***V1-|Decrement |s=s-1 |
2879 ;|DEC xx |------|Decrement |xx=xx-1 |
2880 ;|DEC ss |------|Decrement |ss=ss-1 |
2881 ;|DI |------|Disable Interrupts | |
2882 ;|DJNZ e |------|Dec., Jump Non-Zero |B=B-1 till B=0 |
2883 ;|EI |------|Enable Interrupts | |
2884 ;|EX [SP],HL|------|Exchange |[SP]<->HL |
2885 ;|EX [SP],xx|------|Exchange |[SP]<->xx |
2886 ;|EX AF,AF' |------|Exchange |AF<->AF' |
2887 ;|EX DE,HL |------|Exchange |DE<->HL |
2888 ;|EXX |------|Exchange |qq<->qq' (except AF)|
2889 ;|HALT |------|Halt | |
2890 ;|IM n |------|Interrupt Mode | (n=0,1,2)|
2891 ;|IN A,[n] |------|Input |A=[n] |
2892 ;|IN r,[C] |***P0-|Input |r=[C] |
2893 ;|INC r |***V0-|Increment |r=r+1 |
2894 ;|INC [HL] |***V0-|Increment |[HL]=[HL]+1 |
2895 ;|INC xx |------|Increment |xx=xx+1 |
2896 ;|INC [xx+d]|***V0-|Increment |[xx+d]=[xx+d]+1 |
2897 ;|INC ss |------|Increment |ss=ss+1 |
2898 ;|IND |?*??1-|Input and Decrement |[HL]=[C],HL=HL-1,B=B-1|
2899 ;|INDR |?1??1-|Input, Dec., Repeat |IND till B=0 |
2900 ;|INI |?*??1-|Input and Increment |[HL]=[C],HL=HL+1,B=B-1|
2901 ;|INIR |?1??1-|Input, Inc., Repeat |INI till B=0 |
2902 ;|JP [HL] |------|Unconditional Jump |PC=[HL] |
2903 ;|JP [xx] |------|Unconditional Jump |PC=[xx] |
2904 ;|JP nn |------|Unconditional Jump |PC=nn |
2905 ;|JP cc,nn |------|Conditional Jump |If cc JP |
2906 ;|JR e |------|Unconditional Jump |PC=PC+e |
2907 ;|JR cc,e |------|Conditional Jump |If cc JR(cc=C,NC,NZ,Z)|
2908 ;|LD dst,src|------|Load |dst=src |
2909 ;|LD A,i |**0*0-|Load |A=i (i=I,R)|
2910 ;|LDD |--0*0-|Load and Decrement |[DE]=[HL],HL=HL-1,# |
2911 ;|LDDR |--000-|Load, Dec., Repeat |LDD till BC=0 |
2912 ;|LDI |--0*0-|Load and Increment |[DE]=[HL],HL=HL+1,# |
2913 ;|LDIR |--000-|Load, Inc., Repeat |LDI till BC=0 |
2914 ;|NEG |***V1*|Negate |A=-A |
2915 ;|NOP |------|No Operation | |
2916 ;|OR s |**0P00|Logical inclusive OR |A=Avs |
2917 ;|OTDR |?1??1-|Output, Dec., Repeat |OUTD till B=0 |
2918 ;|OTIR |?1??1-|Output, Inc., Repeat |OUTI till B=0 |
2919 ;|OUT [C],r |------|Output |[C]=r |
2920 ;|OUT [n],A |------|Output |[n]=A |
2921 ;|OUTD |?*??1-|Output and Decrement |[C]=[HL],HL=HL-1,B=B-1|
2922 ;|OUTI |?*??1-|Output and Increment |[C]=[HL],HL=HL+1,B=B-1|
2923 ;|POP xx |------|Pop |xx=[SP]+ |
2924 ;|POP qq |------|Pop |qq=[SP]+ |
2925 ;|PUSH xx |------|Push |-[SP]=xx |
2926 ;|PUSH qq |------|Push |-[SP]=qq |
2927 ;|RES b,m |------|Reset bit |m=m&{~2^b} |
2928 ;|RET |------|Return |PC=[SP]+ |
2929 ;|RET cc |------|Conditional Return |If cc RET |
2930 ;|RETI |------|Return from Interrupt|PC=[SP]+ |
2931 ;|RETN |------|Return from NMI |PC=[SP]+ |
2932 ;|RL m |**0P0*|Rotate Left |m={CY,m}<- |
2933 ;|RLA |--0-0*|Rotate Left Acc. |A={CY,A}<- |
2934 ;|RLC m |**0P0*|Rotate Left Circular |m=m<- |
2935 ;|RLCA |--0-0*|Rotate Left Circular |A=A<- |
2936 ;|RLD |**0P0-|Rotate Left 4 bits |{A,[HL]}={A,[HL]}<- ##|
2937 ;|RR m |**0P0*|Rotate Right |m=->{CY,m} |
2938 ;|RRA |--0-0*|Rotate Right Acc. |A=->{CY,A} |
2939 ;|RRC m |**0P0*|Rotate Right Circular|m=->m |
2940 ;|RRCA |--0-0*|Rotate Right Circular|A=->A |
2941 ;|RRD |**0P0-|Rotate Right 4 bits |{A,[HL]}=->{A,[HL]} ##|
2942 ;|RST p |------|Restart | (p=0H,8H,10H,...,38H)|
2943 ;|SBC A,s |***V1*|Subtract with Carry |A=A-s-CY |
2944 ;|SBC HL,ss |**?V1*|Subtract with Carry |HL=HL-ss-CY |
2945 ;|SCF |--0-01|Set Carry Flag |CY=1 |
2946 ;|SET b,m |------|Set bit |m=mv{2^b} |
2947 ;|SLA m |**0P0*|Shift Left Arithmetic|m=m*2 |
2948 ;|SRA m |**0P0*|Shift Right Arith. |m=m/2 |
2949 ;|SRL m |**0P0*|Shift Right Logical |m=->{0,m,CY} |
2950 ;|SUB s |***V1*|Subtract |A=A-s |
2951 ;|XOR s |**0P00|Logical Exclusive OR |A=Axs |
2952 ;|----------+------+--------------------------------------------|
2953 ;| F |-*01? |Flag unaffected/affected/reset/set/unknown |
2954 ;| S |S |Sign flag (Bit 7) |
2955 ;| Z | Z |Zero flag (Bit 6) |
2956 ;| HC | H |Half Carry flag (Bit 4) |
2957 ;| P/V | P |Parity/Overflow flag (Bit 2, V=overflow) |
2958 ;| N | N |Add/Subtract flag (Bit 1) |
2959 ;| CY | C|Carry flag (Bit 0) |
2960 ;|-----------------+--------------------------------------------|
2961 ;| n |Immediate addressing |
2962 ;| nn |Immediate extended addressing |
2963 ;| e |Relative addressing (PC=PC+2+offset) |
2964 ;| [nn] |Extended addressing |
2965 ;| [xx+d] |Indexed addressing |
2966 ;| r |Register addressing |
2967 ;| [rr] |Register indirect addressing |
2968 ;| |Implied addressing |
2969 ;| b |Bit addressing |
2970 ;| p |Modified page zero addressing (see RST) |
2971 ;|-----------------+--------------------------------------------|
2972 ;|DEFB n(,...) |Define Byte(s) |
2973 ;|DEFB 'str'(,...) |Define Byte ASCII string(s) |
2974 ;|DEFS nn |Define Storage Block |
2975 ;|DEFW nn(,...) |Define Word(s) |
2976 ;|-----------------+--------------------------------------------|
2977 ;| A B C D E |Registers (8-bit) |
2978 ;| AF BC DE HL |Register pairs (16-bit) |
2979 ;| F |Flag register (8-bit) |
2980 ;| I |Interrupt page address register (8-bit) |
2981 ;| IX IY |Index registers (16-bit) |
2982 ;| PC |Program Counter register (16-bit) |
2983 ;| R |Memory Refresh register |
2984 ;| SP |Stack Pointer register (16-bit) |
2985 ;|-----------------+--------------------------------------------|
2986 ;| b |One bit (0 to 7) |
2987 ;| cc |Condition (C,M,NC,NZ,P,PE,PO,Z) |
2988 ;| d |One-byte expression (-128 to +127) |
2989 ;| dst |Destination s, ss, [BC], [DE], [HL], [nn] |
2990 ;| e |One-byte expression (-126 to +129) |
2991 ;| m |Any register r, [HL] or [xx+d] |
2992 ;| n |One-byte expression (0 to 255) |
2993 ;| nn |Two-byte expression (0 to 65535) |
2994 ;| pp |Register pair BC, DE, IX or SP |
2995 ;| qq |Register pair AF, BC, DE or HL |
2996 ;| qq' |Alternative register pair AF, BC, DE or HL |
2997 ;| r |Register A, B, C, D, E, H or L |
2998 ;| rr |Register pair BC, DE, IY or SP |
2999 ;| s |Any register r, value n, [HL] or [xx+d] |
3000 ;| src |Source s, ss, [BC], [DE], [HL], nn, [nn] |
3001 ;| ss |Register pair BC, DE, HL or SP |
3002 ;| xx |Index register IX or IY |
3003 ;|-----------------+--------------------------------------------|
3004 ;| + - * / ^ |Add/subtract/multiply/divide/exponent |
3005 ;| & ~ v x |Logical AND/NOT/inclusive OR/exclusive OR |
3006 ;| <- -> |Rotate left/right |
3007 ;| [ ] |Indirect addressing |
3008 ;| [ ]+ -[ ] |Indirect addressing auto-increment/decrement|
3009 ;| { } |Combination of operands |
3010 ;| # |Also BC=BC-1,DE=DE-1 |
3011 ;| ## |Only lower 4 bits of accumulator A used |
3012 ;----------------------------------------------------------------
3023 ;------------------------------------------------;
3024 ; Move single bit between two registers
3026 ; bmov dstreg,dstbit,srcreg.srcbit
3034 ;------------------------------------------------;
3035 ; Load table value from flash indexed by source reg.
3037 ; ldpmx dstreg,tablebase,indexreg
3039 ; (6 words, 8 cycles)
3042 ldi zh,high(@1*2) ; table must be page aligned
3046 .macro do_z80_flags_HP
3048 bmov z_flags, ZFL_P, temp, AVR_V
3049 bmov z_flags, ZFL_H, temp, AVR_H
3053 .macro do_z80_flags_set_N
3055 ori z_flags, (1<<ZFL_N) ; Negation auf 1
3059 .macro do_z80_flags_set_HN
3061 ori z_flags,(1<<ZFL_N)|(1<<ZFL_H)
3065 .macro do_z80_flags_clear_N
3067 andi z_flags,~(1<<ZFL_N)
3071 .macro do_z80_flags_op_rotate
3072 ; must not change avr carry flag!
3074 andi z_flags, ~( (1<<ZFL_H) | (1<<ZFL_N) | (1<<ZFL_C) )
3076 andi z_flags, ~( (1<<ZFL_C) )
3080 .macro do_z80_flags_op_and
3082 ori z_flags,(1<<ZFL_H)
3084 ori z_flags,(1<<ZFL_H)
3088 .macro do_z80_flags_op_or
3097 ;----------------------------------------------------------------
3098 ;|Mnemonic |SZHPNC|Description |Notes |
3099 ;----------------------------------------------------------------
3100 ;|INC r |***V0-|Increment |r=r+1 |
3101 ;|INC [HL] |***V0-|Increment |[HL]=[HL]+1 |
3102 ;|INC [xx+d]|***V0-|Increment |[xx+d]=[xx+d]+1 |
3103 ;|----------|SZHP C|---------- 8080 ----------------------------|
3104 ;|INC r |**-P0-|Increment |r=r+1 |
3105 ;|INC [HL] |**-P0-|Increment |[HL]=[HL]+1 |
3113 andi z_flags,(1<<ZFL_H)|(1<<ZFL_C) ; preserve C-, and H-flag
3114 ldpmx temp2, sz53p_tab, opl
3124 andi z_flags,(1<<ZFL_H)|(1<<ZFL_C) ; preserve C-, and H-flag
3125 ldpmx temp2, sz53p_tab, z_a
3130 ;----------------------------------------------------------------
3131 ;|Mnemonic |SZHPNC|Description |Notes |
3132 ;----------------------------------------------------------------
3133 ;|DEC r |***V1-|Decrement |s=s-1 |
3134 ;|INC [HL] |***V0-|Increment |[HL]=[HL]+1 |
3135 ;|INC [xx+d]|***V0-|Increment |[xx+d]=[xx+d]+1 |
3136 ;|----------|SZHP C|---------- 8080 ----------------------------|
3137 ;|DEC r |**-P -|Increment |r=r+1 |
3138 ;|DEC [HL] |**-P -|Increment |[HL]=[HL]+1 |
3146 andi z_flags,(1<<ZFL_H)|(1<<ZFL_C) ; preserve C-, and H-flag
3147 ldpmx temp2, sz53p_tab, opl
3158 andi z_flags,(1<<ZFL_H)|(1<<ZFL_C) ; preserve C-, and H-flag
3159 ldpmx temp2, sz53p_tab, z_a
3165 ;----------------------------------------------------------------
3166 ;|Mnemonic |SZHPNC|Description |Notes |
3167 ;----------------------------------------------------------------
3168 ;|INC xx |------|Increment |xx=xx+1 |
3169 ;|INC ss |------|Increment |ss=ss+1 |
3177 ;----------------------------------------------------------------
3178 ;|Mnemonic |SZHPNC|Description |Notes |
3179 ;----------------------------------------------------------------
3180 ;|DEC xx |------|Decrement |xx=xx-1 |
3181 ;|DEC ss |------|Decrement |ss=ss-1 |
3189 ;----------------------------------------------------------------
3190 ;|Mnemonic |SZHPNC|Description |Notes |
3191 ;----------------------------------------------------------------
3192 ;|RLCA |--0-0*|Rotate Left Circular |A=A<- |
3193 ;|----------|SZHP C|---------- 8080 ----------------------------|
3194 ;|RLCA |---- *|Rotate Left Circular |A=A<- |
3198 ;Rotate Left Cyclical. All bits move 1 to the
3199 ;left, the msb becomes c and lsb.
3200 do_z80_flags_op_rotate
3204 ori z_flags, (1<<ZFL_C)
3208 ;----------------------------------------------------------------
3209 ;|Mnemonic |SZHPNC|Description |Notes |
3210 ;----------------------------------------------------------------
3211 ;|RRCA |--0-0*|Rotate Right Circular|A=->A |
3212 ;|----------|SZHP C|---------- 8080 ----------------------------|
3213 ;|RRCA |---- *|Rotate Right Circular|A=->A |
3217 ;Rotate Right Cyclical. All bits move 1 to the
3218 ;right, the lsb becomes c and msb.
3219 do_z80_flags_op_rotate
3223 ori z_flags, (1<<ZFL_C)
3227 ;----------------------------------------------------------------
3228 ;|Mnemonic |SZHPNC|Description |Notes |
3229 ;----------------------------------------------------------------
3230 ;|RRA |--0-0*|Rotate Right Acc. |A=->{CY,A} |
3231 ;|----------|SZHP C|---------- 8080 ----------------------------|
3232 ;|RRA |---- *|Rotate Right Acc. |A=->{CY,A} |
3236 ;Rotate Right. All bits move 1 to the right, the lsb
3237 ;becomes c, c becomes msb.
3238 clc ; get z80 carry to avr carry
3241 do_z80_flags_op_rotate ; (clear ZFL_C, doesn't change AVR_C)
3242 bmov z_flags,ZFL_C, opl,0 ; Bit 0 --> CY
3246 ;----------------------------------------------------------------
3247 ;|Mnemonic |SZHPNC|Description |Notes |
3248 ;----------------------------------------------------------------
3249 ;|RLA |--0-0*|Rotate Left Acc. |A={CY,A}<- |
3250 ;|----------|SZHP C|---------- 8080 ----------------------------|
3251 ;|RLA |---- *|Rotate Left Acc. |A={CY,A}<- |
3255 ;Rotate Left. All bits move 1 to the left, the msb
3256 ;becomes c, c becomes lsb.
3260 do_z80_flags_op_rotate ; (clear ZFL_C, doesn't change AVR_C)
3261 bmov z_flags,ZFL_C, opl,7 ; Bit 7 --> CY
3265 ;----------------------------------------------------------------
3266 ;|Mnemonic |SZHPNC|Description |Notes |
3267 ;----------------------------------------------------------------
3268 ;|ADD A,s |***V0*|Add |A=A+s |
3269 ;|----------|SZHP C|---------- 8080 ----------------------------|
3270 ;|ADD A,s |***P *|Add |A=A+s |
3276 ldpmx z_flags,sz53p_tab,z_a ;S,Z,P flag
3277 bmov z_flags,ZFL_C, temp,AVR_C
3281 ;----------------------------------------------------------------
3282 ;|Mnemonic |SZHPNC|Description |Notes |
3283 ;----------------------------------------------------------------
3284 ;|ADC A,s |***V0*|Add with Carry |A=A+s+CY |
3285 ;|----------|SZHP C|---------- 8080 ----------------------------|
3286 ;|ADC A,s |***P *|Add with Carry |A=A+s+CY |
3295 ldpmx z_flags,sz53p_tab,z_a ;S,Z,P
3296 bmov z_flags,ZFL_C, temp,AVR_C
3300 ;----------------------------------------------------------------
3301 ;|Mnemonic |SZHPNC|Description |Notes |
3302 ;----------------------------------------------------------------
3303 ;|SUB s |***V1*|Subtract |A=A-s |
3304 ;|----------|SZHP C|---------- 8080 ----------------------------|
3305 ;|SUB s |***P *|Subtract |A=A-s |
3311 ldpmx z_flags,sz53p_tab,z_a ;S,Z,P
3312 bmov z_flags,ZFL_C, temp,AVR_C
3317 ;----------------------------------------------------------------
3318 ;|Mnemonic |SZHPNC|Description |Notes |
3319 ;----------------------------------------------------------------
3320 ;|CP s |***V1*|Compare |A-s |
3321 ;|----------|SZHP C|---------- 8080 ----------------------------|
3322 ;|CP s |***P *|Compare |A-s |
3330 ldpmx z_flags,sz53p_tab,opl ;S,Z,P
3331 bmov z_flags,ZFL_C, temp,AVR_C
3336 ;----------------------------------------------------------------
3337 ;|Mnemonic |SZHPNC|Description |Notes |
3338 ;----------------------------------------------------------------
3339 ;|SBC A,s |***V1*|Subtract with Carry |A=A-s-CY |
3340 ;|----------|SZHP C|---------- 8080 ----------------------------|
3341 ;|SBC A,s |***P *|Subtract with Carry |A=A-s-CY |
3350 ldpmx z_flags,sz53p_tab,z_a ;S,Z,P
3351 bmov z_flags,ZFL_C, temp,AVR_C
3356 ;----------------------------------------------------------------
3357 ;|Mnemonic |SZHPNC|Description |Notes |
3358 ;----------------------------------------------------------------
3359 ;|AND s |**1P00|Logical AND |A=A&s |
3360 ;|----------|SZHP C|---------- 8080 ----------------------------|
3361 ;|AND s |**-P 0|Logical AND |A=A&s |
3366 ldpmx z_flags,sz53p_tab,z_a ;S,Z,P,N,C
3371 ;----------------------------------------------------------------
3372 ;|Mnemonic |SZHPNC|Description |Notes |
3373 ;----------------------------------------------------------------
3374 ;|OR s |**0P00|Logical inclusive OR |A=Avs |
3375 ;|----------|SZHP C|---------- 8080 ----------------------------|
3376 ;|OR s |**-P00|Logical inclusive OR |A=Avs |
3381 ldpmx z_flags,sz53p_tab,z_a ;S,Z,H,P,N,C
3385 ;----------------------------------------------------------------
3386 ;|Mnemonic |SZHPNC|Description |Notes |
3387 ;----------------------------------------------------------------
3388 ;|XOR s |**0P00|Logical Exclusive OR |A=Axs |
3389 ;|----------|SZHP C|---------- 8080 ----------------------------|
3390 ;|XOR s |**-P 0|Logical Exclusive OR |A=Axs |
3395 ldpmx z_flags,sz53p_tab,z_a ;S,Z,H,P,N,C
3399 ;----------------------------------------------------------------
3400 ;|Mnemonic |SZHPNC|Description |Notes |
3401 ;----------------------------------------------------------------
3402 ;|ADD HL,ss |--?-0*|Add |HL=HL+ss |
3403 ;|----------|SZHP C|---------- 8080 ----------------------------|
3404 ;|ADD HL,ss |---- *|Add |HL=HL+ss |
3411 bmov z_flags,ZFL_H, temp,AVR_H
3412 bmov z_flags,ZFL_C, temp,AVR_C
3413 do_z80_flags_clear_N
3416 ;----------------------------------------------------------------
3417 ;|Mnemonic |SZHPNC|Description |Notes |
3418 ;----------------------------------------------------------------
3419 ;|LD dst,src|------|Load |dst=src |
3422 do_op_sthl: ;store hl to mem loc in opl:h
3424 #if DRAM_WORD_ACCESS
3436 ;----------------------------------------------------------------
3437 ;|Mnemonic |SZHPNC|Description |Notes |
3438 ;----------------------------------------------------------------
3439 ;|LD dst,src|------|Load |dst=src |
3444 #if DRAM_WORD_ACCESS
3456 ;----------------------------------------------------------------
3457 ;|Mnemonic |SZHPNC|Description |Notes |
3458 ;----------------------------------------------------------------
3459 ;|LD dst,src|------|Load |dst=src |
3468 ;----------------------------------------------------------------
3469 ;|Mnemonic |SZHPNC|Description |Notes |
3470 ;----------------------------------------------------------------
3471 ;|DAA |***P-*|Decimal Adjust Acc. | |
3472 ;|----------|SZHP C|---------- 8080 ----------------------------|
3476 ; Description (http://www.z80.info/z80syntx.htm#DAA):
3477 ; This instruction conditionally adjusts the accumulator for BCD addition
3478 ; and subtraction operations. For addition (ADD, ADC, INC) or subtraction
3479 ; (SUB, SBC, DEC, NEC), the following table indicates the operation performed:
3481 ; -------------------------------------------------------------------------------
3482 ; | | C Flag | HEX value in | H Flag | HEX value in | Number | C flag|
3483 ; | Operation| Before | upper digit | Before | lower digit | added | After |
3484 ; | | DAA | (bit 7-4) | DAA | (bit 3-0) | to byte | DAA |
3485 ; |-----------------------------------------------------------------------------|
3486 ; | | 0 | 0-9 | 0 | 0-9 | 00 | 0 |
3487 ; | ADD | 0 | 0-8 | 0 | A-F | 06 | 0 |
3488 ; | | 0 | 0-9 | 1 | 0-3 | 06 | 0 |
3489 ; | ADC | 0 | A-F | 0 | 0-9 | 60 | 1 |
3490 ; | | 0 | 9-F | 0 | A-F | 66 | 1 |
3491 ; | INC | 0 | A-F | 1 | 0-3 | 66 | 1 |
3492 ; | | 1 | 0-2 | 0 | 0-9 | 60 | 1 |
3493 ; | | 1 | 0-2 | 0 | A-F | 66 | 1 |
3494 ; | | 1 | 0-3 | 1 | 0-3 | 66 | 1 |
3495 ; |-----------------------------------------------------------------------------|
3496 ; | SUB | 0 | 0-9 | 0 | 0-9 | 00 | 0 |
3497 ; | SBC | 0 | 0-8 | 1 | 6-F | FA | 0 |
3498 ; | DEC | 1 | 7-F | 0 | 0-9 | A0 | 1 |
3499 ; | NEG | 1 | 6-F | 1 | 6-F | 9A | 1 |
3500 ; |-----------------------------------------------------------------------------|
3503 ; C: See instruction.
3505 ; P/V: Set if Acc. is even parity after operation, reset otherwise.
3506 ; H: See instruction.
3507 ; Z: Set if Acc. is Zero after operation, reset otherwise.
3508 ; S: Set if most significant bit of Acc. is 1 after operation, reset otherwise.
3514 ldi oph,0 ; what to add
3515 sbrc z_flags,ZFL_H ; if H-Flag
3518 andi temp,0x0f ; ... or lower digit > 9
3524 sbrc z_flags,(1<<ZFL_C)
3533 ori z_flags,(1<<ZFL_C); set C
3535 sbrs z_flags,ZFL_N ; if sub-op
3536 rjmp op_da_add ; then
3539 op_da_add: ; else add-op
3552 ori z_flags,(1<<ZFL_C)
3553 andi z_flags,(1<<ZFL_N)|(1<<ZFL_C) ; preserve C,N
3554 ldpmx temp2, sz53p_tab, opl ; get S,Z,P
3556 bmov z_flags,ZFL_H, temp,AVR_H ; H (?)
3561 sbrc z_flags,ZFL_N ; if add-op
3562 rjmp do_op_da_sub ; then
3566 cpi temp,0x0a ; if lower digit > 9
3568 ori temp2,0x06 ; add 6 to lower digit
3570 sbrc z_flags,ZFL_H ; ... or H-Flag
3580 do_op_da_c: ; else sub-op
3581 sbrc z_flags,ZFL_C ;
3583 andi z_flags, ~( (1<<ZFL_S) | (1<<ZFL_Z) | (1<<ZFL_H) )
3586 bst temp,AVR_Z ;Z-Flag
3588 bst temp,AVR_N ;S-Flag
3590 sbrc temp2,5 ;C-Flag, set if 0x06 added
3591 ori z_flags,(1<<ZFL_C) ;
3595 do_op_da_sub: ;TODO:
3600 ;----------------------------------------------------------------
3601 ;|Mnemonic |SZHPNC|Description |Notes |
3602 ;----------------------------------------------------------------
3603 ;|SCF |--0-01|Set Carry Flag |CY=1 |
3604 ;|----------|SZHP C|---------- 8080 ----------------------------|
3608 andi z_flags,~((1<<ZFL_H)|(1<<ZFL_N))
3609 ori z_flags,(1<<ZFL_C)
3612 ;----------------------------------------------------------------
3613 ;|Mnemonic |SZHPNC|Description |Notes |
3614 ;----------------------------------------------------------------
3615 ;|CCF |--?-0*|Complement Carry Flag|CY=~CY |
3616 ;|----------|SZHP C|---------- 8080 ----------------------------|
3617 ;|SCF |---- 1|Set Carry Flag |CY=1 |
3621 do_z80_flags_clear_N
3626 ;----------------------------------------------------------------
3627 ;|Mnemonic |SZHPNC|Description |Notes |
3628 ;----------------------------------------------------------------
3629 ;|CPL |--1-1-|Complement |A=~A |
3630 ;|----------|SZHP C|---------- 8080 ----------------------------|
3631 ;|CPL |---- -|Complement |A=~A |
3640 ;----------------------------------------------------------------
3641 ;|Mnemonic |SZHPNC|Description |Notes |
3642 ;----------------------------------------------------------------
3643 ;|PUSH xx |------|Push |-[SP]=xx |
3644 ;|PUSH qq |------|Push |-[SP]=qq |
3652 #if DRAM_WORD_ACCESS
3671 .db ", SP is now ",0
3682 ;----------------------------------------------------------------
3683 ;|Mnemonic |SZHPNC|Description |Notes |
3684 ;----------------------------------------------------------------
3685 ;|POP xx |------|Pop |xx=[SP]+ |
3686 ;|POP qq |------|Pop |qq=[SP]+ |
3691 #if DRAM_WORD_ACCESS
3709 .db "Stack pop: val ",0
3725 ;----------------------------------------------------------------
3726 ;|Mnemonic |SZHPNC|Description |Notes |
3727 ;----------------------------------------------------------------
3728 ;|EX [SP],HL|------|Exchange |[SP]<->HL |
3729 ;|EX DE,HL |------|Exchange |DE<->HL |
3741 ;----------------------------------------------------------------
3742 ;|Mnemonic |SZHPNC|Description |Notes |
3743 ;----------------------------------------------------------------
3745 ; TODO: Implement IFF1, IFF2
3749 ;----------------------------------------------------------------
3750 ;|Mnemonic |SZHPNC|Description |Notes |
3751 ;----------------------------------------------------------------
3753 ; TODO: Implement IFF1, IFF2
3757 ;----------------------------------------------------------------
3758 ;|Mnemonic |SZHPNC|Description |Notes |
3759 ;----------------------------------------------------------------
3760 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3761 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3762 ;|RET cc |------|Conditional Return |If cc RET |
3772 ;----------------------------------------------------------------
3773 ;|Mnemonic |SZHPNC|Description |Notes |
3774 ;----------------------------------------------------------------
3775 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3776 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3777 ;|RET cc |------|Conditional Return |If cc RET |
3787 ;----------------------------------------------------------------
3788 ;|Mnemonic |SZHPNC|Description |Notes |
3789 ;----------------------------------------------------------------
3790 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3791 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3792 ;|RET cc |------|Conditional Return |If cc RET |
3802 ;----------------------------------------------------------------
3803 ;|Mnemonic |SZHPNC|Description |Notes |
3804 ;----------------------------------------------------------------
3805 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3806 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3807 ;|RET cc |------|Conditional Return |If cc RET |
3817 ;----------------------------------------------------------------
3818 ;|Mnemonic |SZHPNC|Description |Notes |
3819 ;----------------------------------------------------------------
3820 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3821 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3822 ;|RET cc |------|Conditional Return |If cc RET |
3832 ;----------------------------------------------------------------
3833 ;|Mnemonic |SZHPNC|Description |Notes |
3834 ;----------------------------------------------------------------
3835 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3836 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3837 ;|RET cc |------|Conditional Return |If cc RET |
3847 ;----------------------------------------------------------------
3848 ;|Mnemonic |SZHPNC|Description |Notes |
3849 ;----------------------------------------------------------------
3850 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3851 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3852 ;|RET cc |------|Conditional Return |If cc RET |
3855 do_op_ifp: ;sign positive, aka s=0
3862 ;----------------------------------------------------------------
3863 ;|Mnemonic |SZHPNC|Description |Notes |
3864 ;----------------------------------------------------------------
3865 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3866 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3867 ;|RET cc |------|Conditional Return |If cc RET |
3870 do_op_ifm: ;sign negative, aka s=1
3877 ;----------------------------------------------------------------
3878 ;|Mnemonic |SZHPNC|Description |Notes |
3879 ;----------------------------------------------------------------
3880 ;|OUT [n],A |------|Output |[n]=A |
3883 ;Interface with peripherials goes here :)
3884 do_op_outa: ; out (opl),a
3887 .db 13,"Port write: ",0
3902 ;----------------------------------------------------------------
3903 ;|Mnemonic |SZHPNC|Description |Notes |
3904 ;----------------------------------------------------------------
3905 ;|IN A,[n] |------|Input |A=[n] |
3908 do_op_in: ; in a,(opl)
3911 .db 13,"Port read: (",0
3930 ;----------------------------------------------------------------
3933 .db "Invalid opcode @ PC=",0,0
3939 ;----------------------------------------------------------------
3943 ;----------------------------------------------------------------
3944 ; Lookup table, stolen from z80ex, Z80 emulation library.
3945 ; http://z80ex.sourceforge.net/
3947 ; The S, Z, 5 and 3 bits and the parity of the lookup value
3948 .org (PC+255) & 0xff00
3950 .db 0x44,0x00,0x00,0x04,0x00,0x04,0x04,0x00
3951 .db 0x08,0x0c,0x0c,0x08,0x0c,0x08,0x08,0x0c
3952 .db 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04
3953 .db 0x0c,0x08,0x08,0x0c,0x08,0x0c,0x0c,0x08
3954 .db 0x20,0x24,0x24,0x20,0x24,0x20,0x20,0x24
3955 .db 0x2c,0x28,0x28,0x2c,0x28,0x2c,0x2c,0x28
3956 .db 0x24,0x20,0x20,0x24,0x20,0x24,0x24,0x20
3957 .db 0x28,0x2c,0x2c,0x28,0x2c,0x28,0x28,0x2c
3958 .db 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04
3959 .db 0x0c,0x08,0x08,0x0c,0x08,0x0c,0x0c,0x08
3960 .db 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00
3961 .db 0x08,0x0c,0x0c,0x08,0x0c,0x08,0x08,0x0c
3962 .db 0x24,0x20,0x20,0x24,0x20,0x24,0x24,0x20
3963 .db 0x28,0x2c,0x2c,0x28,0x2c,0x28,0x28,0x2c
3964 .db 0x20,0x24,0x24,0x20,0x24,0x20,0x20,0x24
3965 .db 0x2c,0x28,0x28,0x2c,0x28,0x2c,0x2c,0x28
3966 .db 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84
3967 .db 0x8c,0x88,0x88,0x8c,0x88,0x8c,0x8c,0x88
3968 .db 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80
3969 .db 0x88,0x8c,0x8c,0x88,0x8c,0x88,0x88,0x8c
3970 .db 0xa4,0xa0,0xa0,0xa4,0xa0,0xa4,0xa4,0xa0
3971 .db 0xa8,0xac,0xac,0xa8,0xac,0xa8,0xa8,0xac
3972 .db 0xa0,0xa4,0xa4,0xa0,0xa4,0xa0,0xa0,0xa4
3973 .db 0xac,0xa8,0xa8,0xac,0xa8,0xac,0xac,0xa8
3974 .db 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80
3975 .db 0x88,0x8c,0x8c,0x88,0x8c,0x88,0x88,0x8c
3976 .db 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84
3977 .db 0x8c,0x88,0x88,0x8c,0x88,0x8c,0x8c,0x88
3978 .db 0xa0,0xa4,0xa4,0xa0,0xa4,0xa0,0xa0,0xa4
3979 .db 0xac,0xa8,0xa8,0xac,0xa8,0xac,0xac,0xa8
3980 .db 0xa4,0xa0,0xa0,0xa4,0xa0,0xa4,0xa4,0xa0
3981 .db 0xa8,0xac,0xac,0xa8,0xac,0xa8,0xa8,0xac
3984 ; ----------------------- Opcode decoding -------------------------
3986 ; Lookup table for Z80 opcodes. Translates the first byte of the instruction word into three
3987 ; operations: fetch, do something, store.
3988 ; The table is made of 256 words. These 16-bit words consist of
3989 ; the fetch operation (bit 0-4), the processing operation (bit 10-16) and the store
3990 ; operation (bit 5-9).
3991 .org (PC+255) & 0xff00
3993 .dw (FETCH_NOP | OP_NOP | STORE_NOP) ; 00 NOP
3994 .dw (FETCH_DIR16| OP_NOP | STORE_BC ) ; 01 nn nn LD BC,nn
3995 .dw (FETCH_A | OP_NOP | STORE_MBC) ; 02 LD (BC),A
3996 .dw (FETCH_BC | OP_INC16 | STORE_BC ) ; 03 INC BC
3997 .dw (FETCH_B | OP_INC | STORE_B ) ; 04 INC B
3998 .dw (FETCH_B | OP_DEC | STORE_B ) ; 05 DEC B
3999 .dw (FETCH_DIR8 | OP_NOP | STORE_B ) ; 06 nn LD B,n
4000 .dw (FETCH_A | OP_RLC | STORE_A ) ; 07 RLCA
4001 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 08 EX AF,AF' (Z80)
4002 .dw (FETCH_BC | OP_ADDHL | STORE_HL ) ; 09 ADD HL,BC
4003 .dw (FETCH_MBC | OP_NOP | STORE_A ) ; 0A LD A,(BC)
4004 .dw (FETCH_BC | OP_DEC16 | STORE_BC ) ; 0B DEC BC
4005 .dw (FETCH_C | OP_INC | STORE_C ) ; 0C INC C
4006 .dw (FETCH_C | OP_DEC | STORE_C ) ; 0D DEC C
4007 .dw (FETCH_DIR8 | OP_NOP | STORE_C ) ; 0E nn LD C,n
4008 .dw (FETCH_A | OP_RRC | STORE_A ) ; 0F RRCA
4009 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 10 oo DJNZ o (Z80)
4010 .dw (FETCH_DIR16| OP_NOP | STORE_DE ) ; 11 nn nn LD DE,nn
4011 .dw (FETCH_A | OP_NOP | STORE_MDE) ; 12 LD (DE),A
4012 .dw (FETCH_DE | OP_INC16 | STORE_DE ) ; 13 INC DE
4013 .dw (FETCH_D | OP_INC | STORE_D ) ; 14 INC D
4014 .dw (FETCH_D | OP_DEC | STORE_D ) ; 15 DEC D
4015 .dw (FETCH_DIR8 | OP_NOP | STORE_D ) ; 16 nn LD D,n
4016 .dw (FETCH_A | OP_RL | STORE_A ) ; 17 RLA
4017 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 18 oo JR o (Z80)
4018 .dw (FETCH_DE | OP_ADDHL | STORE_HL ) ; 19 ADD HL,DE
4019 .dw (FETCH_MDE | OP_NOP | STORE_A ) ; 1A LD A,(DE)
4020 .dw (FETCH_DE | OP_DEC16 | STORE_DE ) ; 1B DEC DE
4021 .dw (FETCH_E | OP_INC | STORE_E ) ; 1C INC E
4022 .dw (FETCH_E | OP_DEC | STORE_E ) ; 1D DEC E
4023 .dw (FETCH_DIR8 | OP_NOP | STORE_E ) ; 1E nn LD E,n
4024 .dw (FETCH_A | OP_RR | STORE_A ) ; 1F RRA
4025 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 20 oo JR NZ,o (Z80)
4026 .dw (FETCH_DIR16| OP_NOP | STORE_HL ) ; 21 nn nn LD HL,nn
4027 .dw (FETCH_DIR16| OP_STHL | STORE_NOP) ; 22 nn nn LD (nn),HL
4028 .dw (FETCH_HL | OP_INC16 | STORE_HL ) ; 23 INC HL
4029 .dw (FETCH_H | OP_INC | STORE_H ) ; 24 INC H
4030 .dw (FETCH_H | OP_DEC | STORE_H ) ; 25 DEC H
4031 .dw (FETCH_DIR8 | OP_NOP | STORE_H ) ; 26 nn LD H,n
4032 .dw (FETCH_A | OP_DA | STORE_A ) ; 27 DAA
4033 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 28 oo JR Z,o (Z80)
4034 .dw (FETCH_HL | OP_ADDHL | STORE_HL ) ; 29 ADD HL,HL
4035 .dw (FETCH_DIR16| OP_RMEM16 | STORE_HL ) ; 2A nn nn LD HL,(nn)
4036 .dw (FETCH_HL | OP_DEC16 | STORE_HL ) ; 2B DEC HL
4037 .dw (FETCH_L | OP_INC | STORE_L ) ; 2C INC L
4038 .dw (FETCH_L | OP_DEC | STORE_L ) ; 2D DEC L
4039 .dw (FETCH_DIR8 | OP_NOP | STORE_L ) ; 2E nn LD L,n
4040 .dw (FETCH_NOP | OP_CPL | STORE_NOP) ; 2F CPL
4041 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 30 oo JR NC,o (Z80)
4042 .dw (FETCH_DIR16| OP_NOP | STORE_SP ) ; 31 nn nn LD SP,nn
4043 .dw (FETCH_DIR16| OP_NOP | STORE_AM ) ; 32 nn nn LD (nn),A
4044 .dw (FETCH_SP | OP_INC16 | STORE_SP ) ; 33 INC SP
4045 .dw (FETCH_MHL | OP_INC | STORE_MHL) ; 34 INC (HL)
4046 .dw (FETCH_MHL | OP_DEC | STORE_MHL) ; 35 DEC (HL)
4047 .dw (FETCH_DIR8 | OP_NOP | STORE_MHL) ; 36 nn LD (HL),n
4048 .dw (FETCH_NOP | OP_SCF | STORE_NOP) ; 37 SCF
4049 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 38 oo JR C,o (Z80)
4050 .dw (FETCH_SP | OP_ADDHL | STORE_HL ) ; 39 ADD HL,SP
4051 .dw (FETCH_DIR16| OP_RMEM8 | STORE_A ) ; 3A nn nn LD A,(nn)
4052 .dw (FETCH_SP | OP_DEC16 | STORE_SP ) ; 3B DEC SP
4053 .dw (FETCH_NOP | OP_INCA | STORE_NOP) ; 3C INC A
4054 .dw (FETCH_NOP | OP_DECA | STORE_NOP) ; 3D DEC A
4055 .dw (FETCH_DIR8 | OP_NOP | STORE_A ) ; 3E nn LD A,n
4056 .dw (FETCH_NOP | OP_CCF | STORE_NOP) ; 3F CCF (Complement Carry Flag, gvd)
4057 .dw (FETCH_B | OP_NOP | STORE_B ) ; 40 LD B,r
4058 .dw (FETCH_C | OP_NOP | STORE_B ) ; 41 LD B,r
4059 .dw (FETCH_D | OP_NOP | STORE_B ) ; 42 LD B,r
4060 .dw (FETCH_E | OP_NOP | STORE_B ) ; 43 LD B,r
4061 .dw (FETCH_H | OP_NOP | STORE_B ) ; 44 LD B,r
4062 .dw (FETCH_L | OP_NOP | STORE_B ) ; 45 LD B,r
4063 .dw (FETCH_MHL | OP_NOP | STORE_B ) ; 46 LD B,r
4064 .dw (FETCH_A | OP_NOP | STORE_B ) ; 47 LD B,r
4065 .dw (FETCH_B | OP_NOP | STORE_C ) ; 48 LD C,r
4066 .dw (FETCH_C | OP_NOP | STORE_C ) ; 49 LD C,r
4067 .dw (FETCH_D | OP_NOP | STORE_C ) ; 4A LD C,r
4068 .dw (FETCH_E | OP_NOP | STORE_C ) ; 4B LD C,r
4069 .dw (FETCH_H | OP_NOP | STORE_C ) ; 4C LD C,r
4070 .dw (FETCH_L | OP_NOP | STORE_C ) ; 4D LD C,r
4071 .dw (FETCH_MHL | OP_NOP | STORE_C ) ; 4E LD C,r
4072 .dw (FETCH_A | OP_NOP | STORE_C ) ; 4F LD C,r
4073 .dw (FETCH_B | OP_NOP | STORE_D ) ; 50 LD D,r
4074 .dw (FETCH_C | OP_NOP | STORE_D ) ; 51 LD D,r
4075 .dw (FETCH_D | OP_NOP | STORE_D ) ; 52 LD D,r
4076 .dw (FETCH_E | OP_NOP | STORE_D ) ; 53 LD D,r
4077 .dw (FETCH_H | OP_NOP | STORE_D ) ; 54 LD D,r
4078 .dw (FETCH_L | OP_NOP | STORE_D ) ; 55 LD D,r
4079 .dw (FETCH_MHL | OP_NOP | STORE_D ) ; 56 LD D,r
4080 .dw (FETCH_A | OP_NOP | STORE_D ) ; 57 LD D,r
4081 .dw (FETCH_B | OP_NOP | STORE_E ) ; 58 LD E,r
4082 .dw (FETCH_C | OP_NOP | STORE_E ) ; 59 LD E,r
4083 .dw (FETCH_D | OP_NOP | STORE_E ) ; 5A LD E,r
4084 .dw (FETCH_E | OP_NOP | STORE_E ) ; 5B LD E,r
4085 .dw (FETCH_H | OP_NOP | STORE_E ) ; 5C LD E,r
4086 .dw (FETCH_L | OP_NOP | STORE_E ) ; 5D LD E,r
4087 .dw (FETCH_MHL | OP_NOP | STORE_E ) ; 5E LD E,r
4088 .dw (FETCH_A | OP_NOP | STORE_E ) ; 5F LD E,r
4089 .dw (FETCH_B | OP_NOP | STORE_H ) ; 60 LD H,r
4090 .dw (FETCH_C | OP_NOP | STORE_H ) ; 61 LD H,r
4091 .dw (FETCH_D | OP_NOP | STORE_H ) ; 62 LD H,r
4092 .dw (FETCH_E | OP_NOP | STORE_H ) ; 63 LD H,r
4093 .dw (FETCH_H | OP_NOP | STORE_H ) ; 64 LD H,r
4094 .dw (FETCH_L | OP_NOP | STORE_H ) ; 65 LD H,r
4095 .dw (FETCH_MHL | OP_NOP | STORE_H ) ; 66 LD H,r
4096 .dw (FETCH_A | OP_NOP | STORE_H ) ; 67 LD H,r
4097 .dw (FETCH_B | OP_NOP | STORE_L ) ; 68 LD L,r
4098 .dw (FETCH_C | OP_NOP | STORE_L ) ; 69 LD L,r
4099 .dw (FETCH_D | OP_NOP | STORE_L ) ; 6A LD L,r
4100 .dw (FETCH_E | OP_NOP | STORE_L ) ; 6B LD L,r
4101 .dw (FETCH_H | OP_NOP | STORE_L ) ; 6C LD L,r
4102 .dw (FETCH_L | OP_NOP | STORE_L ) ; 6D LD L,r
4103 .dw (FETCH_MHL | OP_NOP | STORE_L ) ; 6E LD L,r
4104 .dw (FETCH_A | OP_NOP | STORE_L ) ; 6F LD L,r
4105 .dw (FETCH_B | OP_NOP | STORE_MHL) ; 70 LD (HL),r
4106 .dw (FETCH_C | OP_NOP | STORE_MHL) ; 71 LD (HL),r
4107 .dw (FETCH_D | OP_NOP | STORE_MHL) ; 72 LD (HL),r
4108 .dw (FETCH_E | OP_NOP | STORE_MHL) ; 73 LD (HL),r
4109 .dw (FETCH_H | OP_NOP | STORE_MHL) ; 74 LD (HL),r
4110 .dw (FETCH_L | OP_NOP | STORE_MHL) ; 75 LD (HL),r
4111 .dw (FETCH_NOP | OP_NOP | STORE_NOP) ; 76 HALT
4112 .dw (FETCH_A | OP_NOP | STORE_MHL) ; 77 LD (HL),r
4113 .dw (FETCH_B | OP_NOP | STORE_A ) ; 78 LD A,r
4114 .dw (FETCH_C | OP_NOP | STORE_A ) ; 79 LD A,r
4115 .dw (FETCH_D | OP_NOP | STORE_A ) ; 7A LD A,r
4116 .dw (FETCH_E | OP_NOP | STORE_A ) ; 7B LD A,r
4117 .dw (FETCH_H | OP_NOP | STORE_A ) ; 7C LD A,r
4118 .dw (FETCH_L | OP_NOP | STORE_A ) ; 7D LD A,r
4119 .dw (FETCH_MHL | OP_NOP | STORE_A ) ; 7E LD A,r
4120 .dw (FETCH_A | OP_NOP | STORE_A ) ; 7F LD A,r
4121 .dw (FETCH_B | OP_ADDA | STORE_NOP) ; 80 ADD A,r
4122 .dw (FETCH_C | OP_ADDA | STORE_NOP) ; 81 ADD A,r
4123 .dw (FETCH_D | OP_ADDA | STORE_NOP) ; 82 ADD A,r
4124 .dw (FETCH_E | OP_ADDA | STORE_NOP) ; 83 ADD A,r
4125 .dw (FETCH_H | OP_ADDA | STORE_NOP) ; 84 ADD A,r
4126 .dw (FETCH_L | OP_ADDA | STORE_NOP) ; 85 ADD A,r
4127 .dw (FETCH_MHL | OP_ADDA | STORE_NOP) ; 86 ADD A,r
4128 .dw (FETCH_A | OP_ADDA | STORE_NOP) ; 87 ADD A,r
4129 .dw (FETCH_B | OP_ADCA | STORE_NOP) ; 88 ADC A,r
4130 .dw (FETCH_C | OP_ADCA | STORE_NOP) ; 89 ADC A,r
4131 .dw (FETCH_D | OP_ADCA | STORE_NOP) ; 8A ADC A,r
4132 .dw (FETCH_E | OP_ADCA | STORE_NOP) ; 8B ADC A,r
4133 .dw (FETCH_H | OP_ADCA | STORE_NOP) ; 8C ADC A,r
4134 .dw (FETCH_L | OP_ADCA | STORE_NOP) ; 8D ADC A,r
4135 .dw (FETCH_MHL | OP_ADCA | STORE_NOP) ; 8E ADC A,r
4136 .dw (FETCH_A | OP_ADCA | STORE_NOP) ; 8F ADC A,r
4137 .dw (FETCH_B | OP_SUBFA | STORE_NOP) ; 90 SUB A,r
4138 .dw (FETCH_C | OP_SUBFA | STORE_NOP) ; 91 SUB A,r
4139 .dw (FETCH_D | OP_SUBFA | STORE_NOP) ; 92 SUB A,r
4140 .dw (FETCH_E | OP_SUBFA | STORE_NOP) ; 93 SUB A,r
4141 .dw (FETCH_H | OP_SUBFA | STORE_NOP) ; 94 SUB A,r
4142 .dw (FETCH_L | OP_SUBFA | STORE_NOP) ; 95 SUB A,r
4143 .dw (FETCH_MHL | OP_SUBFA | STORE_NOP) ; 96 SUB A,r
4144 .dw (FETCH_A | OP_SUBFA | STORE_NOP) ; 97 SUB A,r
4145 .dw (FETCH_B | OP_SBCFA | STORE_NOP) ; 98 SBC A,r
4146 .dw (FETCH_C | OP_SBCFA | STORE_NOP) ; 99 SBC A,r
4147 .dw (FETCH_D | OP_SBCFA | STORE_NOP) ; 9A SBC A,r
4148 .dw (FETCH_E | OP_SBCFA | STORE_NOP) ; 9B SBC A,r
4149 .dw (FETCH_H | OP_SBCFA | STORE_NOP) ; 9C SBC A,r
4150 .dw (FETCH_L | OP_SBCFA | STORE_NOP) ; 9D SBC A,r
4151 .dw (FETCH_MHL | OP_SBCFA | STORE_NOP) ; 9E SBC A,r
4152 .dw (FETCH_A | OP_SBCFA | STORE_NOP) ; 9F SBC A,r
4153 .dw (FETCH_B | OP_ANDA | STORE_NOP) ; A0 AND A,r
4154 .dw (FETCH_C | OP_ANDA | STORE_NOP) ; A1 AND A,r
4155 .dw (FETCH_D | OP_ANDA | STORE_NOP) ; A2 AND A,r
4156 .dw (FETCH_E | OP_ANDA | STORE_NOP) ; A3 AND A,r
4157 .dw (FETCH_H | OP_ANDA | STORE_NOP) ; A4 AND A,r
4158 .dw (FETCH_L | OP_ANDA | STORE_NOP) ; A5 AND A,r
4159 .dw (FETCH_MHL | OP_ANDA | STORE_NOP) ; A6 AND A,r
4160 .dw (FETCH_A | OP_ANDA | STORE_NOP) ; A7 AND A,r
4161 .dw (FETCH_B | OP_XORA | STORE_NOP) ; A8 XOR A,r
4162 .dw (FETCH_C | OP_XORA | STORE_NOP) ; A9 XOR A,r
4163 .dw (FETCH_D | OP_XORA | STORE_NOP) ; AA XOR A,r
4164 .dw (FETCH_E | OP_XORA | STORE_NOP) ; AB XOR A,r
4165 .dw (FETCH_H | OP_XORA | STORE_NOP) ; AC XOR A,r
4166 .dw (FETCH_L | OP_XORA | STORE_NOP) ; AD XOR A,r
4167 .dw (FETCH_MHL | OP_XORA | STORE_NOP) ; AE XOR A,r
4168 .dw (FETCH_A | OP_XORA | STORE_NOP) ; AF XOR A,r
4169 .dw (FETCH_B | OP_ORA | STORE_NOP) ; B0 OR A,r
4170 .dw (FETCH_C | OP_ORA | STORE_NOP) ; B1 OR A,r
4171 .dw (FETCH_D | OP_ORA | STORE_NOP) ; B2 OR A,r
4172 .dw (FETCH_E | OP_ORA | STORE_NOP) ; B3 OR A,r
4173 .dw (FETCH_H | OP_ORA | STORE_NOP) ; B4 OR A,r
4174 .dw (FETCH_L | OP_ORA | STORE_NOP) ; B5 OR A,r
4175 .dw (FETCH_MHL | OP_ORA | STORE_NOP) ; B6 OR A,r
4176 .dw (FETCH_A | OP_ORA | STORE_NOP) ; B7 OR A,r
4177 .dw (FETCH_B | OP_CPFA | STORE_NOP) ; B8 CP A,r
4178 .dw (FETCH_C | OP_CPFA | STORE_NOP) ; B9 CP A,r
4179 .dw (FETCH_D | OP_CPFA | STORE_NOP) ; BA CP A,r
4180 .dw (FETCH_E | OP_CPFA | STORE_NOP) ; BB CP A,r
4181 .dw (FETCH_H | OP_CPFA | STORE_NOP) ; BC CP A,r
4182 .dw (FETCH_L | OP_CPFA | STORE_NOP) ; BD CP A,r
4183 .dw (FETCH_MHL | OP_CPFA | STORE_NOP) ; BE CP A,r
4184 .dw (FETCH_A | OP_CPFA | STORE_NOP) ; BF CP A,r
4185 .dw (FETCH_NOP | OP_IFNZ | STORE_RET) ; C0 RET NZ
4186 .dw (FETCH_NOP | OP_POP16 | STORE_BC ) ; C1 POP BC
4187 .dw (FETCH_DIR16| OP_IFNZ | STORE_PC ) ; C2 nn nn JP NZ,nn
4188 .dw (FETCH_DIR16| OP_NOP | STORE_PC ) ; C3 nn nn JP nn
4189 .dw (FETCH_DIR16| OP_IFNZ | STORE_CALL) ; C4 nn nn CALL NZ,nn
4190 .dw (FETCH_BC | OP_PUSH16 | STORE_NOP) ; C5 PUSH BC
4191 .dw (FETCH_DIR8 | OP_ADDA | STORE_NOP) ; C6 nn ADD A,n
4192 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; C7 RST 0
4193 .dw (FETCH_NOP | OP_IFZ | STORE_RET) ; C8 RET Z
4194 .dw (FETCH_NOP | OP_NOP | STORE_RET) ; C9 RET
4195 .dw (FETCH_DIR16| OP_IFZ | STORE_PC ) ; CA nn nn JP Z,nn
4196 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; CB (Z80 specific)
4197 .dw (FETCH_DIR16| OP_IFZ | STORE_CALL) ; CC nn nn CALL Z,nn
4198 .dw (FETCH_DIR16| OP_NOP | STORE_CALL) ; CD nn nn CALL nn
4199 .dw (FETCH_DIR8 | OP_ADCA | STORE_NOP) ; CE nn ADC A,n
4200 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; CF RST 8H
4201 .dw (FETCH_NOP | OP_IFNC | STORE_RET) ; D0 RET NC
4202 .dw (FETCH_NOP | OP_POP16 | STORE_DE ) ; D1 POP DE
4203 .dw (FETCH_DIR16| OP_IFNC | STORE_PC ) ; D2 nn nn JP NC,nn
4204 .dw (FETCH_DIR8 | OP_OUTA | STORE_NOP) ; D3 nn OUT (n),A
4205 .dw (FETCH_DIR16| OP_IFNC | STORE_CALL) ; D4 nn nn CALL NC,nn
4206 .dw (FETCH_DE | OP_PUSH16 | STORE_NOP) ; D5 PUSH DE
4207 .dw (FETCH_DIR8 | OP_SUBFA | STORE_NOP) ; D6 nn SUB n
4208 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; D7 RST 10H
4209 .dw (FETCH_NOP | OP_IFC | STORE_RET) ; D8 RET C
4210 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; D9 EXX (Z80)
4211 .dw (FETCH_DIR16| OP_IFC | STORE_PC ) ; DA nn nn JP C,nn
4212 .dw (FETCH_DIR8 | OP_IN | STORE_A ) ; DB nn IN A,(n)
4213 .dw (FETCH_DIR16| OP_IFC | STORE_CALL) ; DC nn nn CALL C,nn
4214 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; DD (Z80)
4215 .dw (FETCH_DIR8 | OP_SBCFA | STORE_NOP) ; DE nn SBC A,n
4216 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; DF RST 18H
4217 .dw (FETCH_NOP | OP_IFPO | STORE_RET) ; E0 RET PO
4218 .dw (FETCH_NOP | OP_POP16 | STORE_HL ) ; E1 POP HL
4219 .dw (FETCH_DIR16| OP_IFPO | STORE_PC ) ; E2 nn nn JP PO,nn
4220 .dw (FETCH_MSP | OP_EXHL | STORE_MSP) ; E3 EX (SP),HL
4221 .dw (FETCH_DIR16| OP_IFPO | STORE_CALL) ; E4 nn nn CALL PO,nn
4222 .dw (FETCH_HL | OP_PUSH16 | STORE_NOP) ; E5 PUSH HL
4223 .dw (FETCH_DIR8 | OP_ANDA | STORE_NOP) ; E6 nn AND n
4224 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; E7 RST 20H
4225 .dw (FETCH_NOP | OP_IFPE | STORE_RET) ; E8 RET PE
4226 .dw (FETCH_HL | OP_NOP | STORE_PC ) ; E9 JP (HL)
4227 .dw (FETCH_DIR16| OP_IFPE | STORE_PC ) ; EA nn nn JP PE,nn
4228 .dw (FETCH_DE | OP_EXHL | STORE_DE ) ; EB EX DE,HL
4229 .dw (FETCH_DIR16| OP_IFPE | STORE_CALL) ; EC nn nn CALL PE,nn
4230 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; ED (Z80 specific)
4231 .dw (FETCH_DIR8 | OP_XORA | STORE_NOP) ; EE nn XOR n
4232 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; EF RST 28H
4233 .dw (FETCH_NOP | OP_IFP | STORE_RET) ; F0 RET P
4234 .dw (FETCH_NOP | OP_POP16 | STORE_AF ) ; F1 POP AF
4235 .dw (FETCH_DIR16| OP_IFP | STORE_PC ) ; F2 nn nn JP P,nn
4236 .dw (FETCH_NOP | OP_DI | STORE_NOP) ; F3 DI
4237 .dw (FETCH_DIR16| OP_IFP | STORE_CALL) ; F4 nn nn CALL P,nn
4238 .dw (FETCH_AF | OP_PUSH16 | STORE_NOP) ; F5 PUSH AF
4239 .dw (FETCH_DIR8 | OP_ORA | STORE_NOP) ; F6 nn OR n
4240 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; F7 RST 30H
4241 .dw (FETCH_NOP | OP_IFM | STORE_RET) ; F8 RET M
4242 .dw (FETCH_HL | OP_NOP | STORE_SP ) ; F9 LD SP,HL
4243 .dw (FETCH_DIR16| OP_IFM | STORE_PC ) ; FA nn nn JP M,nn
4244 .dw (FETCH_NOP | OP_EI | STORE_NOP) ; FB EI
4245 .dw (FETCH_DIR16| OP_IFM | STORE_CALL) ; FC nn nn CALL M,nn
4246 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; FD (Z80 specific)
4247 .dw (FETCH_DIR8 | OP_CPFA | STORE_NOP) ; FE nn CP n
4248 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; FF RST 38H
4250 ; vim:set ts=8 noet nowrap