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 */
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
128 .equ RAM_DQ_MASK = (1<<ram_d3)|(1<<ram_d2)|(1<<ram_d1)|(1<<ram_d0)
129 .equ PC_OUTPUT_MASK = (1<<ram_cas)|(1<<ram_w)
132 ;Flag bits in z_flags
140 ;Register definitions
176 #if defined __ATmega8__
185 .equ hostact = 7 ;host active flag
186 .equ hostwrt = 6 ;host written flag
187 .equ rsflag = 5 ;read sector flag
188 .equ readop = 4 ;1 if read operation
191 ; This is the base z80 port address for clock access
192 #define TIMERPORT 0x40
193 #define TIMER_CTL TIMERPORT
194 #define TIMER_MSECS TIMERPORT+1
195 #define TIMER_SECS TIMER_MSECS+2
197 #define starttimercmd 1
198 #define quitTimerCmd 2
199 #define printTimerCmd 15
202 #if defined __ATmega8__
217 .equ OC2Aaddr= OC2addr
230 ;----------------------------------------
240 ;----------------------------------------
252 ;----------------------------------------
254 ; dram_wait number_of_cycles
269 rjmp start ; reset vector
271 rjmp refrint ; tim2cmpa
272 .org OC1Aaddr ; Timer/Counter1 Compare Match A
273 rjmp sysclockint ; 1ms system timer
275 rjmp rxint ; USART receive int.
277 rjmp txint ; USART transmit int.
279 .org INT_VECTORS_SIZE
282 ldi temp,low(RAMEND) ; top of memory
283 out SPL,temp ; init stack pointer
284 ldi temp,high(RAMEND) ; top of memory
285 out SPH,temp ; init stack pointer
293 ldi temp,(1<<WDCE) | (1<<WDE)
300 ldi zl,low(SRAM_START)
301 ldi zh,high(SRAM_START)
302 ldi temp2,high(ramtop)
310 ldi temp,(1<<PUD) ;disable pullups
313 out PORTD,temp ;all pins high
316 out DDRD,temp ; all outputs
328 ldi temp, (1<<TXEN0) | (1<<RXEN0) | (1<<RXCIE0)
331 ldi temp, (1<<URSEL) | (1<<UCSZ01) | (1<<UCSZ00)
333 ldi temp, (1<<UCSZ01) | (1<<UCSZ00)
336 ldi temp, HIGH(UBRR_VAL)
338 ldi temp, LOW(UBRR_VAL)
341 ; Init clock/timer system
343 ; Init timer 1 as 1 ms system clock tick.
345 ldi temp,high(F_CPU/1000)
347 ldi temp,low(F_CPU/1000)
349 ldi temp,(1<<WGM12) | (1<<CS10) ;CTC, clk/1
355 ;Init timer2. Refresh-call should happen every (8ms/512)=312 cycles.
357 ldi temp,REFR_CNT*2 ; 2 cycles per int
360 ori temp,(1<<WGM21) ;CTC mode
363 ori temp,REFR_CS ;clk/REFR_PRE
366 ori temp, (1<<OCIE2A)
379 .db "CPM on an AVR, v1.0",13,0,0
384 .db "Testing RAM: fill...",0,0
406 .db "reread...",13,0,0
438 ;Fill ram with cbs, which (for now) will trigger an invalid opcode error.
450 .db "Initing mmc...",13,0
453 ;----------------------------------------------------------------------------
455 ; Partition table offsets:
460 ;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
475 ldi opl,0 ;opl holds number of found disks (paritions)
478 ;No MBR, no partition table ...
479 inc opl ;pretend we have one.
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(hostparttbl)
487 ldi yh,high(hostparttbl)
488 ldi oph,high(hostbuf+510)
494 ; Found a CP/M partition
496 ldd temp,z+PART_START
498 ldd temp2,z+PART_START+1
500 ldd temp3,z+PART_START+2
502 ldd temp4,z+PART_START+3
506 .db "CP/M partition at: ",0
512 ldd temp2,z+PART_SIZE+1
514 ldd temp3,z+PART_SIZE+2
516 ldd temp4,z+PART_SIZE+3
531 cpi zl,low(hostbuf+510)
537 ; Read first sector of first CP/M partition
550 .db "No bootable CP/M disk found! Please change MMC/SD-Card",13,0
562 ;First sector of disk or first CP/M partition is in hostbuf.
564 ;Save to Z80 RAM (only 128 bytes because that's retro)
573 cpi zl,low(hostbuf+128)
575 cpi zh,high(hostbuf+128)
577 rcall dsk_boot ;init (de)blocking buffer
588 .db 13,"Ok, CPU is live!",13,0,0
618 ; *** Stage 1: Fetch next opcode
641 ; *** Stage 2: Decode it using the ins_table.
642 ldi zh,high(inst_table*2)
663 ; *** Stage 3: Fetch operand. Use the fetch jumptable for this.
667 ldi zl,low(fetchjumps)
668 ldi zh,high(fetchjumps)
688 ; *** Stage 4: Execute operation :) Use the op jumptable for this.
704 .db ",post:oph:l=",0,0
713 ; *** Stage 5: Store operand. Use the store jumptable for this.
722 ldi zl,low(storejumps)
723 ldi zh,high(storejumps)
750 ; ----------------Virtual peripherial interface ------
752 ;The hw is modelled to make writing a CPM BIOS easier.
754 ;0 - Con status. Returns 0xFF if the UART has a byte, 0 otherwise.
755 ;1 - Console input, aka UDR.
758 ;16,17 - Track select
762 ;22 - Trigger - write to read, to write a sector using the above info;
763 ; , write to allocated/dirctory/unallocated
772 ;*****************************************************
773 ;* CP/M to host disk constants *
774 ;*****************************************************
775 .equ MAXDISKS = 4 ;Max number of Disks (partitions)
776 .equ blksize = 1024 ;CP/M allocation size
777 .equ hostsize = 512 ;host disk sector size
778 ; .equ hostspt = 20 ;host disk sectors/trk
779 .equ hostblk = hostsize/128 ;CP/M sects/host buff
780 ; .equ CPMSPT = hostblk*hostspt;CP/M sectors/track
782 .equ SECMSK = hostblk-1 ;sector mask
783 .equ SECSHF = log2(hostblk) ;sector shift
785 ;*****************************************************
786 ;* BDOS constants on entry to write *
787 ;*****************************************************
788 .equ WRALL = 0 ;write to allocated
789 .equ WRDIR = 1 ;write to directory
790 .equ WRUAL = 2 ;write to unallocated
791 .equ WRTMSK= 3 ;write type mask
795 ndisks: .byte 1 ;Number of CP/M disks
797 seekdsk: .byte 1 ;seek disk number
798 seektrk: .byte 2 ;seek track number
799 seeksec: .byte 1 ;seek sector number
801 hostparttbl: .byte 8*MAXDISKS ; host partition table (start sector, sector count)
802 hostdsk: .byte 1 ;host disk number
803 hostlba: .byte 3 ;host sector number (relative to partition start)
805 unacnt: .byte 1 ;unalloc rec cnt
806 unadsk: .byte 1 ;last unalloc disk
807 unatrk: .byte 2 ;last unalloc track
808 unasec: .byte 1 ;last unalloc sector
810 erflag: .byte 1 ;error reporting
811 wrtype: .byte 1 ;write operation type
812 dmaadr: .byte 2 ;last dma address
813 hostbuf: .byte hostsize;host buffer (from/to SD-card)
818 ;Called with port in temp2. Should return value in temp.
830 cpi temp2,TIMER_MSECS
832 cpi temp2,TIMER_MSECS+6
840 ;Called with port in temp2 and value in temp.
865 cpi temp2,TIMER_MSECS+6
898 lds temp2,ndisks ;check if selected disk # is less then # of disks
902 ldi temp,0xff ;error return
949 .db 13,"Disk read: ",0
953 .db 13,"Disk write: ",0
985 ;See what has to be done.
996 .db "DISK I/O: Invalid Function code: ",0
1001 cbi flags,hostact ;host buffer inactive
1002 sts unacnt,_0 ;clear unalloc count
1006 sbis flags,hostwrt ;check for pending write
1007 cbi flags,hostact ;clear host active flag
1013 sbi flags,readop ;read operation
1016 ; cpi temp2,RAMDISKNR
1021 sbi flags,rsflag ;must read data
1022 ldi temp,WRUAL ;write type
1023 sts wrtype,temp ;treat as unalloc
1024 rjmp dsk_rwoper ;to perform the read
1028 ;write the selected CP/M sector
1030 cbi flags,readop ;not a read operation
1034 ; cpi temp2,RAMDISKNR
1038 sts wrtype,temp ;save write type
1040 cpi temp,WRUAL ;write unallocated?
1041 brne dsk_chkuna ;check for unalloc
1043 ; write to unallocated, set parameters
1044 ldi temp,blksize/128 ;next unalloc recs
1046 lds temp,seekdsk ;disk to seek
1047 sts unadsk,temp ;unadsk = sekdsk
1049 sts unatrk,temp ;unatrk = sectrk
1051 sts unatrk+1,temp ;unatrk = sectrk
1053 sts unasec,temp ;unasec = seksec
1056 ;check for write to unallocated sector
1057 lds temp,unacnt ;any unalloc remain?
1059 breq dsk_alloc ;skip if not
1061 ; more unallocated records remain
1062 dec temp ;unacnt = unacnt-1
1064 lds temp,seekdsk ;same disk?
1066 cp temp,temp2 ;seekdsk = unadsk?
1067 brne dsk_alloc ;skip if not
1069 ; disks are the same
1074 cp temp,temp3 ;seektrk = unatrk?
1076 brne dsk_alloc ;skip if not
1078 ; tracks are the same
1079 lds temp,seeksec ;same sector?
1081 cp temp,temp2 ;seeksec = unasec?
1082 brne dsk_alloc ;skip if not
1084 ; match, move to next sector for future ref
1085 inc temp2 ;unasec = unasec+1
1087 cpi temp2,CPMSPT ;end of track? (count CP/M sectors)
1088 brlo dsk_noovf ;skip if no overflow
1090 ; overflow to next track
1091 sts unasec,_0 ;unasec = 0
1094 subi temp, low(-1) ;unatrk = unatrk+1
1100 cbi flags,rsflag ;rsflag = 0
1101 rjmp dsk_rwoper ;to perform the write
1104 ;not an unallocated record, requires pre-read
1105 sts unacnt,_0 ;unacnt = 0
1106 sbi flags,rsflag ;rsflag = 1
1108 ;*****************************************************
1109 ;* Common code for READ and WRITE follows *
1110 ;*****************************************************
1113 ;enter here to perform the read/write
1120 sts erflag,_0 ;no errors (yet)
1122 ;Convert track/sector to an LBA address (in 128byte blocks)
1128 lds temp4,seektrk+1 ;
1134 add xh,r0 ;yl:xh:xl := sec + trk * SectorsPerTrack
1139 andi temp,SECMSK ;mask buffer number
1140 push temp ;save for later
1142 ;Convert from CP/M LBA blocks to host LBA blocks
1150 ;yl:xh:xl = host block to seek
1151 ; active host sector?
1152 in _tmp,flags ;host active flag
1153 sbi flags,hostact ;always becomes 1
1154 sbrs _tmp,hostact ;was it already?
1155 rjmp dsk_filhst ;fill host if not
1157 ; host buffer active, same as seek buffer?
1159 lds temp2,hostdsk ;same disk?
1160 cp temp,temp2 ;seekdsk = hostdsk?
1163 ; same disk, same block?
1173 ;proper disk, but not correct sector
1174 sbis flags,hostwrt ;host written?
1179 rcall dsk_writehost ;clear host buff
1185 ;may have to fill the host buffer
1192 sbic flags,rsflag ;need to read?
1193 rcall dsk_readhost ;yes, if 1
1194 cbi flags,hostwrt ;no pending write
1198 ;copy data to or from buffer
1200 ldi zh,high(hostbuf)
1202 pop temp2 ;get buffer number (which part of hostbuf)
1204 add zl,r0 ;offset in hostbuf
1211 .db "; host buf adr: ",0,0
1221 ldi temp3,128 ;length of move
1222 sbic flags,readop ;which way?
1223 rjmp dsk_rmove ;skip if read
1225 ; mark write operation
1226 sbi flags,hostwrt ;hostwrt = 1
1242 ; data has been moved to/from host buffer
1243 lds temp,wrtype ;write type
1244 cpi temp,WRDIR ;to directory?
1246 ret ;no further processing
1248 ; clear host buffer for directory write
1254 rcall dsk_writehost ;clear host buff
1255 cbi flags,hostwrt ;buffer written
1258 ;*****************************************************
1260 ; hostdsk = host disk #, (partition #)
1261 ; hostlba = host block #, relative to partition start
1262 ; Read/Write "hostsize" bytes to/from hostbuf
1266 ldi zl,low(hostparttbl)
1267 ldi zh,high(hostparttbl)
1357 ;*****************************************************
1358 ;* WRITEhost performs the physical write to *
1359 ;* the host disk, READhost reads the physical *
1361 ;*****************************************************
1366 .db 13,"host write ",0,0
1382 .db 13,"host read ",0,0
1396 ;***************************************************************************
1398 ; ----------------- MMC/SD routines ------------------
1427 ;Wait till the mmc answers with the response in temp2, or till a timeout happens.
1434 brne mmcWaitResploopEnd
1438 rjmp mmcWaitResploop
1447 .db ": Error: MMC resp timeout!",13,0
1454 ;Init start: send 80 clocks with cs disabled
1458 ldi temp2,10 ; exactly 80 clocks
1480 ldi temp,0xff ;dummy
1482 ldi temp,0xff ;dummy
1496 ldi temp,0xff ;return byte
1499 ldi temp2,0 ;Error Code 0
1500 rcall mmcWaitResp ;Test on CMD0 is OK
1502 sbi P_MMC_CS,mmc_cs ;disable /CS
1506 ;Read OCR till card is ready
1507 ldi temp2,20 ;repeat counter
1511 cbi P_MMC_CS,mmc_cs ;enable /CS
1512 ldi temp,0xff ;dummy
1524 ; ldi temp,0x95 ;crc
1530 rcall mmcWaitResp ;wait until mmc-card send a byte <> 0xFF
1531 ;the first answer must be 0x01 (Idle-Mode)
1533 breq mmcInitOcrLoopDone ;second answer is 0x00 (Idle-Mode leave) CMD1 is OK
1535 sbi P_MMC_CS,mmc_cs ;disable /CS
1537 ; rcall mmcByteNoSend ;unnecessary
1545 brne mmcInitOcrLoop ;repeat
1552 sbi P_MMC_CS,mmc_cs ;disable /CS
1559 ;Call this with yh:yl:xh:xl = sector number
1567 ldi temp,0x51 ;cmd (read sector)
1569 lsl xl ;convert to byte address (*512)
1582 ldi temp,0xff ;return byte
1593 ;Read sector to AVR RAM
1595 ldi zh,high(hostbuf)
1599 cpi zl,low(hostbuf+512)
1601 cpi zh,high(hostbuf+512)
1615 ;Call this with yh:yl:xh:xl = sector number
1624 ldi temp,0x58 ;cmd (write sector)
1626 lsl xl ;convert to byte address (*512)
1639 ldi temp,0xff ;return byte
1650 ;Write sector from AVR RAM
1652 ldi zh,high(hostbuf)
1656 cpi zl,low(hostbuf+512)
1658 cpi zh,high(hostbuf+512)
1665 ;Status. Ignored for now.
1668 ;Wait till the mmc has written everything
1681 ;Set up wdt to time out after 1 sec.
1686 ldi temp,(1<<WDCE) | (1<<WDE) | (110<<WDP0)
1691 ; ------------------ DRAM routines -------------
1693 ; DRAM_SETADDR val, low_and_mask, low_or_mask, high_and_mask, high_or_mask
1708 ori temp, @4 | (1<<mmc_cs)
1712 ;Loads the byte on address xh:xl into temp.
1713 ;must not alter xh:xl
1717 DRAM_SETADDR xh, ~0,(1<<ram_ras), ~(1<<ram_a8), (1<<ram_oe)
1719 DRAM_SETADDR xl, ~(1<<ram_ras),0, ~((1<<ram_oe)), (1<<ram_a8)
1722 dram_wait DRAM_WAITSTATES ;
1723 in temp,P_DQ-2 ; PIN
1729 dram_wait DRAM_WAITSTATES ;
1730 in temp2,P_DQ-2 ; PIN
1740 #if DRAM_WORD_ACCESS
1755 DRAM_SETADDR xh, ~0,(1<<ram_ras), ~(1<<ram_a8),(1<<ram_oe)
1757 DRAM_SETADDR xl, ~(1<<ram_ras),0, ~((1<<ram_oe)), (1<<ram_a8)
1761 in temp,P_DQ-2 ; PIN
1767 in temp2,P_DQ-2 ; PIN
1775 DRAM_SETADDR xl, ~(1<<ram_ras),0, ~((1<<ram_oe)), (1<<ram_a8)
1779 in temp,P_DQ-2 ; PIN
1785 in temp2,P_DQ-2 ; PIN
1798 ;Writes the byte in temp to xh:xl
1799 ;must not alter xh:xl
1803 ldi temp2,RAM_DQ_MASK | (1<<ram_w) | (1<<ram_cas)
1807 andi temp,RAM_DQ_MASK & ~(1<<ram_w)
1808 ori temp,(1<<ram_cas)
1810 DRAM_SETADDR xh, ~0,(1<<ram_ras), ~(1<<ram_a8),(1<<ram_oe)
1812 DRAM_SETADDR xl, ~(1<<ram_ras),0, ~((1<<ram_a8)),(1<<ram_oe)
1819 andi temp2,RAM_DQ_MASK & ~(1<<ram_w)
1820 ori temp2,(1<<ram_cas)
1826 ldi temp,~RAM_DQ_MASK | (1<<ram_w) | (1<<ram_cas)
1832 #if DRAM_WORD_ACCESS
1847 ldi temp2,RAM_DQ_MASK | (1<<ram_w) | (1<<ram_cas)
1851 andi temp,RAM_DQ_MASK & ~(1<<ram_w)
1852 ori temp,(1<<ram_cas)
1855 DRAM_SETADDR xh, ~0,(1<<ram_ras), ~(1<<ram_a8),(1<<ram_oe)
1857 DRAM_SETADDR xl, ~(1<<ram_ras),0, ~((1<<ram_a8)),(1<<ram_oe)
1864 andi temp2,RAM_DQ_MASK & ~(1<<ram_w)
1865 ori temp2,(1<<ram_cas)
1874 andi temp,RAM_DQ_MASK & ~(1<<ram_w)
1875 ori temp,(1<<ram_cas)
1878 DRAM_SETADDR xl, ~(1<<ram_ras),0, ~((1<<ram_a8)),(1<<ram_oe)
1885 andi temp2,RAM_DQ_MASK & ~(1<<ram_w)
1886 ori temp2,(1<<ram_cas)
1892 ldi temp,~RAM_DQ_MASK | (1<<ram_w) | (1<<ram_cas)
1899 ; ****************************************************************************
1901 ; refresh interupt; exec 2 cbr cycles
1904 sbis P_RAS,ram_ras ;2
1907 cbi P_CAS,ram_cas ;2 1| 1|
1909 cbi P_RAS,ram_ras ;2 |0 1|
1913 sbi P_RAS,ram_ras ;2 |0 |0
1915 dram_wait DRAM_WAITSTATES-1 ;
1917 cbi P_RAS,ram_ras ;2 |0 1|
1919 sbi P_CAS,ram_cas ;2 |0 |0
1921 sbi P_RAS,ram_ras ;2 1| |0
1923 reti ;4 --> 21 cycles
1926 ; ------------- system timer 1ms ---------------
1936 ; don't change order here, clock put/get depends on it.
1937 cntms_out: ; register for ms
1939 utime_io: ; register for uptime.
1946 .equ timer_size = timer_top - timer_base
1948 .equ clkofs = cnt_1ms-cntms_out
1949 .equ timerofs = cnt_1ms-timer_ms
1970 ldi zl,high(1000) ;doesn't change flags
2003 sts delay_timer,temp
2005 lds temp,delay_timer
2014 subi temp2,TIMER_MSECS
2015 brcs clkget_end ;Port number in range?
2016 ldi zl,low(cntms_out)
2017 ldi zh,high(cntms_out)
2018 breq clkget_copy ;lowest byte requestet, latch clock
2020 brsh clkget_end ;Port number to high?
2045 subi temp2,TIMERPORT
2046 brcs clkput_end ;Port number in range?
2051 cpi temp,starttimercmd
2053 cpi temp,quitTimerCmd
2055 cpi temp,printTimerCmd
2069 ldi zl,low(cntms_out)
2070 ldi zh,high(cntms_out)
2071 breq clkput_copy ;lowest byte requestet, latch clock
2073 brsh clkput_end ;Port number to high?
2098 ldi zl,low(timer_ms)
2099 ldi zh,high(timer_ms)
2117 ldi zl,low(timer_ms)
2118 ldi zh,high(timer_ms)
2120 ; put ms on stack (16 bit)
2142 ldd temp2,z+timerofs
2146 ldd temp3,z+timerofs
2151 ldd temp4,z+timerofs
2156 .db 13,"Timer running. Elapsed: ",0
2176 ldi zh,high(cnt_1ms)
2209 ; --------------- Debugging stuff ---------------
2211 ;Print a unsigned lonng value to the uart
2212 ; temp4:temp3:temp2:temp = value
2223 clr yl ;yl = stack level
2225 ultoa1: ldi z_flags, 32 ;yh = temp4:temp % 10
2226 clr yh ;temp4:temp /= 10
2238 cpi yh, 10 ;yh is a numeral digit '0'-'9'
2242 cp temp,_0 ;Repeat until temp4:temp gets zero
2249 ultoa5: cpi yl,3 ; at least 3 digits (ms)
2255 ultoa6: pop temp ;Flush stacked digits
2270 ;Prints the lower nibble of temp in hex to the uart
2286 ;Prints temp in hex to the uart
2294 ;Prints the zero-terminated string following the call statement.
2334 ; --------------- AVR HW <-> Z80 periph stuff ------------------
2336 .equ memReadByte = dram_read
2337 .equ memWriteByte = dram_write
2338 #if DRAM_WORD_ACCESS
2339 .equ memReadWord = dram_read_w
2340 .equ memWriteWord = dram_write_w
2343 ; --------------------------------------------------------------
2347 #define RXBUFMASK RXBUFSIZE-1
2348 #define TXBUFMASK TXBUFSIZE-1
2370 ; Save received character in a circular buffer. Do nothing if buffer overflows.
2379 lds zh,rxcount ;if rxcount < RXBUFSIZE
2380 cpi zh,RXBUFSIZE ; (room for at least 1 char?)
2383 sts rxcount,zh ; rxcount++
2385 ldi zl,low(rxfifo) ;
2390 sts rxidx_w,zh ; rxidx_w = ++rxidx_w % RXBUFSIZE
2391 ldi zh,high(rxfifo) ;
2394 st z,temp ; rxfifo[rxidx_w] = char
2404 ;Fetches a char from the buffer to temp. If none available, waits till one is.
2407 lds temp,rxcount ; Number of characters in buffer
2409 breq uartgetc ;Wait for char
2427 ld temp,z ;don't forget to get the char
2436 lds temp,txcount ;if txcount != 0
2441 sts txcount,temp ; --txcount
2444 ldi zl,low(txfifo) ;
2445 ldi zh,high(txfifo) ;
2451 andi temp,TXBUFMASK ;
2461 ldi temp, (1<<TXEN0) | (1<<RXEN0) | (1<<RXCIE0)
2470 ;Sends a char from temp to the uart.
2476 lds temp,txcount ;do {
2477 cpi temp,TXBUFSIZE ;
2478 brsh putc_l ;} while (txcount >= TXBUFSIZE)
2480 ldi zl,low(txfifo) ;
2481 ldi zh,high(txfifo) ;
2487 andi temp,TXBUFMASK ;
2488 sts txidx_w,temp ; txidx_w = ++txidx_w % TXBUFSIZE
2490 st z,temp ; txfifo[txidx_w] = char
2495 ldi zl, (1<<UDRIE0) | (1<<TXEN0) | (1<<RXEN0) | (1<<RXCIE0)
2502 ; ------------ Fetch phase stuff -----------------
2504 .equ FETCH_NOP = (0<<0)
2505 .equ FETCH_A = (1<<0)
2506 .equ FETCH_B = (2<<0)
2507 .equ FETCH_C = (3<<0)
2508 .equ FETCH_D = (4<<0)
2509 .equ FETCH_E = (5<<0)
2510 .equ FETCH_H = (6<<0)
2511 .equ FETCH_L = (7<<0)
2512 .equ FETCH_AF = (8<<0)
2513 .equ FETCH_BC = (9<<0)
2514 .equ FETCH_DE = (10<<0)
2515 .equ FETCH_HL = (11<<0)
2516 .equ FETCH_SP = (12<<0)
2517 .equ FETCH_MBC = (13<<0)
2518 .equ FETCH_MDE = (14<<0)
2519 .equ FETCH_MHL = (15<<0)
2520 .equ FETCH_MSP = (16<<0)
2521 .equ FETCH_DIR8 = (17<<0)
2522 .equ FETCH_DIR16= (18<<0)
2523 .equ FETCH_RST = (19<<0)
2526 ;Jump table for fetch routines. Make sure to keep this in sync with the .equs!
2621 #if DRAM_WORD_ACCESS
2642 #if DRAM_WORD_ACCESS
2667 ; ------------ Store phase stuff -----------------
2669 .equ STORE_NOP = (0<<5)
2670 .equ STORE_A = (1<<5)
2671 .equ STORE_B = (2<<5)
2672 .equ STORE_C = (3<<5)
2673 .equ STORE_D = (4<<5)
2674 .equ STORE_E = (5<<5)
2675 .equ STORE_H = (6<<5)
2676 .equ STORE_L = (7<<5)
2677 .equ STORE_AF = (8<<5)
2678 .equ STORE_BC = (9<<5)
2679 .equ STORE_DE = (10<<5)
2680 .equ STORE_HL = (11<<5)
2681 .equ STORE_SP = (12<<5)
2682 .equ STORE_PC = (13<<5)
2683 .equ STORE_MBC = (14<<5)
2684 .equ STORE_MDE = (15<<5)
2685 .equ STORE_MHL = (16<<5)
2686 .equ STORE_MSP = (17<<5)
2687 .equ STORE_RET = (18<<5)
2688 .equ STORE_CALL = (19<<5)
2689 .equ STORE_AM = (20<<5)
2691 ;Jump table for store routines. Make sure to keep this in sync with the .equs!
2787 #if DRAM_WORD_ACCESS
2828 ; ------------ Operation phase stuff -----------------
2831 .equ OP_NOP = (0<<10)
2832 .equ OP_INC = (1<<10)
2833 .equ OP_DEC = (2<<10)
2834 .equ OP_INC16 = (3<<10)
2835 .equ OP_DEC16 = (4<<10)
2836 .equ OP_RLC = (5<<10)
2837 .equ OP_RRC = (6<<10)
2838 .equ OP_RR = (7<<10)
2839 .equ OP_RL = (8<<10)
2840 .equ OP_ADDA = (9<<10)
2841 .equ OP_ADCA = (10<<10)
2842 .equ OP_SUBFA = (11<<10)
2843 .equ OP_SBCFA = (12<<10)
2844 .equ OP_ANDA = (13<<10)
2845 .equ OP_ORA = (14<<10)
2846 .equ OP_XORA = (15<<10)
2847 .equ OP_ADDHL = (16<<10)
2848 .equ OP_STHL = (17<<10) ;store HL in fetched address
2849 .equ OP_RMEM16 = (18<<10) ;read mem at fetched address
2850 .equ OP_RMEM8 = (19<<10) ;read mem at fetched address
2851 .equ OP_DA = (20<<10)
2852 .equ OP_SCF = (21<<10)
2853 .equ OP_CPL = (22<<10)
2854 .equ OP_CCF = (23<<10)
2855 .equ OP_POP16 = (24<<10)
2856 .equ OP_PUSH16 = (25<<10)
2857 .equ OP_IFNZ = (26<<10)
2858 .equ OP_IFZ = (27<<10)
2859 .equ OP_IFNC = (28<<10)
2860 .equ OP_IFC = (29<<10)
2861 .equ OP_IFPO = (30<<10)
2862 .equ OP_IFPE = (31<<10)
2863 .equ OP_IFP = (32<<10)
2864 .equ OP_IFM = (33<<10)
2865 .equ OP_OUTA = (34<<10)
2866 .equ OP_IN = (35<<10)
2867 .equ OP_EXHL = (36<<10)
2868 .equ OP_DI = (37<<10)
2869 .equ OP_EI = (38<<10)
2870 .equ OP_INV = (39<<10)
2871 .equ OP_CPFA = (40<<10)
2872 .equ OP_INCA = (41<<10)
2873 .equ OP_DECA = (42<<10)
2921 ;How the flags are supposed to work:
2922 ;7 ZFL_S - Sign flag (=MSBit of result)
2923 ;6 ZFL_Z - Zero flag. Is 1 when the result is 0
2924 ;4 ZFL_H - Half-carry (carry from bit 3 to 4)
2925 ;2 ZFL_P - Parity/2-complement Overflow
2926 ;1 ZFL_N - Subtract - set if last op was a subtract
2929 ;I sure hope I got the mapping between flags and instructions correct...
2931 ;----------------------------------------------------------------
2935 ;| ZZZZZZZ 88888 000 |
2941 ;| ZZZZZZZ 88888 000 |
2943 ;| Z80 MICROPROCESSOR Instruction Set Summary |
2945 ;----------------------------------------------------------------
2946 ;----------------------------------------------------------------
2947 ;|Mnemonic |SZHPNC|Description |Notes |
2948 ;|----------+------+---------------------+----------------------|
2949 ;|ADC A,s |***V0*|Add with Carry |A=A+s+CY |
2950 ;|ADC HL,ss |**?V0*|Add with Carry |HL=HL+ss+CY |
2951 ;|ADD A,s |***V0*|Add |A=A+s |
2952 ;|ADD HL,ss |--?-0*|Add |HL=HL+ss |
2953 ;|ADD IX,pp |--?-0*|Add |IX=IX+pp |
2954 ;|ADD IY,rr |--?-0*|Add |IY=IY+rr |
2955 ;|AND s |**1P00|Logical AND |A=A&s |
2956 ;|BIT b,m |?*1?0-|Test Bit |m&{2^b} |
2957 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
2958 ;|CALL nn |------|Unconditional Call |-[SP]=PC,PC=nn |
2959 ;|CCF |--?-0*|Complement Carry Flag|CY=~CY |
2960 ;|CP s |***V1*|Compare |A-s |
2961 ;|CPD |****1-|Compare and Decrement|A-[HL],HL=HL-1,BC=BC-1|
2962 ;|CPDR |****1-|Compare, Dec., Repeat|CPD till A=[HL]or BC=0|
2963 ;|CPI |****1-|Compare and Increment|A-[HL],HL=HL+1,BC=BC-1|
2964 ;|CPIR |****1-|Compare, Inc., Repeat|CPI till A=[HL]or BC=0|
2965 ;|CPL |--1-1-|Complement |A=~A |
2966 ;|DAA |***P-*|Decimal Adjust Acc. |A=BCD format |
2967 ;|DEC s |***V1-|Decrement |s=s-1 |
2968 ;|DEC xx |------|Decrement |xx=xx-1 |
2969 ;|DEC ss |------|Decrement |ss=ss-1 |
2970 ;|DI |------|Disable Interrupts | |
2971 ;|DJNZ e |------|Dec., Jump Non-Zero |B=B-1 till B=0 |
2972 ;|EI |------|Enable Interrupts | |
2973 ;|EX [SP],HL|------|Exchange |[SP]<->HL |
2974 ;|EX [SP],xx|------|Exchange |[SP]<->xx |
2975 ;|EX AF,AF' |------|Exchange |AF<->AF' |
2976 ;|EX DE,HL |------|Exchange |DE<->HL |
2977 ;|EXX |------|Exchange |qq<->qq' (except AF)|
2978 ;|HALT |------|Halt | |
2979 ;|IM n |------|Interrupt Mode | (n=0,1,2)|
2980 ;|IN A,[n] |------|Input |A=[n] |
2981 ;|IN r,[C] |***P0-|Input |r=[C] |
2982 ;|INC r |***V0-|Increment |r=r+1 |
2983 ;|INC [HL] |***V0-|Increment |[HL]=[HL]+1 |
2984 ;|INC xx |------|Increment |xx=xx+1 |
2985 ;|INC [xx+d]|***V0-|Increment |[xx+d]=[xx+d]+1 |
2986 ;|INC ss |------|Increment |ss=ss+1 |
2987 ;|IND |?*??1-|Input and Decrement |[HL]=[C],HL=HL-1,B=B-1|
2988 ;|INDR |?1??1-|Input, Dec., Repeat |IND till B=0 |
2989 ;|INI |?*??1-|Input and Increment |[HL]=[C],HL=HL+1,B=B-1|
2990 ;|INIR |?1??1-|Input, Inc., Repeat |INI till B=0 |
2991 ;|JP [HL] |------|Unconditional Jump |PC=[HL] |
2992 ;|JP [xx] |------|Unconditional Jump |PC=[xx] |
2993 ;|JP nn |------|Unconditional Jump |PC=nn |
2994 ;|JP cc,nn |------|Conditional Jump |If cc JP |
2995 ;|JR e |------|Unconditional Jump |PC=PC+e |
2996 ;|JR cc,e |------|Conditional Jump |If cc JR(cc=C,NC,NZ,Z)|
2997 ;|LD dst,src|------|Load |dst=src |
2998 ;|LD A,i |**0*0-|Load |A=i (i=I,R)|
2999 ;|LDD |--0*0-|Load and Decrement |[DE]=[HL],HL=HL-1,# |
3000 ;|LDDR |--000-|Load, Dec., Repeat |LDD till BC=0 |
3001 ;|LDI |--0*0-|Load and Increment |[DE]=[HL],HL=HL+1,# |
3002 ;|LDIR |--000-|Load, Inc., Repeat |LDI till BC=0 |
3003 ;|NEG |***V1*|Negate |A=-A |
3004 ;|NOP |------|No Operation | |
3005 ;|OR s |**0P00|Logical inclusive OR |A=Avs |
3006 ;|OTDR |?1??1-|Output, Dec., Repeat |OUTD till B=0 |
3007 ;|OTIR |?1??1-|Output, Inc., Repeat |OUTI till B=0 |
3008 ;|OUT [C],r |------|Output |[C]=r |
3009 ;|OUT [n],A |------|Output |[n]=A |
3010 ;|OUTD |?*??1-|Output and Decrement |[C]=[HL],HL=HL-1,B=B-1|
3011 ;|OUTI |?*??1-|Output and Increment |[C]=[HL],HL=HL+1,B=B-1|
3012 ;|POP xx |------|Pop |xx=[SP]+ |
3013 ;|POP qq |------|Pop |qq=[SP]+ |
3014 ;|PUSH xx |------|Push |-[SP]=xx |
3015 ;|PUSH qq |------|Push |-[SP]=qq |
3016 ;|RES b,m |------|Reset bit |m=m&{~2^b} |
3017 ;|RET |------|Return |PC=[SP]+ |
3018 ;|RET cc |------|Conditional Return |If cc RET |
3019 ;|RETI |------|Return from Interrupt|PC=[SP]+ |
3020 ;|RETN |------|Return from NMI |PC=[SP]+ |
3021 ;|RL m |**0P0*|Rotate Left |m={CY,m}<- |
3022 ;|RLA |--0-0*|Rotate Left Acc. |A={CY,A}<- |
3023 ;|RLC m |**0P0*|Rotate Left Circular |m=m<- |
3024 ;|RLCA |--0-0*|Rotate Left Circular |A=A<- |
3025 ;|RLD |**0P0-|Rotate Left 4 bits |{A,[HL]}={A,[HL]}<- ##|
3026 ;|RR m |**0P0*|Rotate Right |m=->{CY,m} |
3027 ;|RRA |--0-0*|Rotate Right Acc. |A=->{CY,A} |
3028 ;|RRC m |**0P0*|Rotate Right Circular|m=->m |
3029 ;|RRCA |--0-0*|Rotate Right Circular|A=->A |
3030 ;|RRD |**0P0-|Rotate Right 4 bits |{A,[HL]}=->{A,[HL]} ##|
3031 ;|RST p |------|Restart | (p=0H,8H,10H,...,38H)|
3032 ;|SBC A,s |***V1*|Subtract with Carry |A=A-s-CY |
3033 ;|SBC HL,ss |**?V1*|Subtract with Carry |HL=HL-ss-CY |
3034 ;|SCF |--0-01|Set Carry Flag |CY=1 |
3035 ;|SET b,m |------|Set bit |m=mv{2^b} |
3036 ;|SLA m |**0P0*|Shift Left Arithmetic|m=m*2 |
3037 ;|SRA m |**0P0*|Shift Right Arith. |m=m/2 |
3038 ;|SRL m |**0P0*|Shift Right Logical |m=->{0,m,CY} |
3039 ;|SUB s |***V1*|Subtract |A=A-s |
3040 ;|XOR s |**0P00|Logical Exclusive OR |A=Axs |
3041 ;|----------+------+--------------------------------------------|
3042 ;| F |-*01? |Flag unaffected/affected/reset/set/unknown |
3043 ;| S |S |Sign flag (Bit 7) |
3044 ;| Z | Z |Zero flag (Bit 6) |
3045 ;| HC | H |Half Carry flag (Bit 4) |
3046 ;| P/V | P |Parity/Overflow flag (Bit 2, V=overflow) |
3047 ;| N | N |Add/Subtract flag (Bit 1) |
3048 ;| CY | C|Carry flag (Bit 0) |
3049 ;|-----------------+--------------------------------------------|
3050 ;| n |Immediate addressing |
3051 ;| nn |Immediate extended addressing |
3052 ;| e |Relative addressing (PC=PC+2+offset) |
3053 ;| [nn] |Extended addressing |
3054 ;| [xx+d] |Indexed addressing |
3055 ;| r |Register addressing |
3056 ;| [rr] |Register indirect addressing |
3057 ;| |Implied addressing |
3058 ;| b |Bit addressing |
3059 ;| p |Modified page zero addressing (see RST) |
3060 ;|-----------------+--------------------------------------------|
3061 ;|DEFB n(,...) |Define Byte(s) |
3062 ;|DEFB 'str'(,...) |Define Byte ASCII string(s) |
3063 ;|DEFS nn |Define Storage Block |
3064 ;|DEFW nn(,...) |Define Word(s) |
3065 ;|-----------------+--------------------------------------------|
3066 ;| A B C D E |Registers (8-bit) |
3067 ;| AF BC DE HL |Register pairs (16-bit) |
3068 ;| F |Flag register (8-bit) |
3069 ;| I |Interrupt page address register (8-bit) |
3070 ;| IX IY |Index registers (16-bit) |
3071 ;| PC |Program Counter register (16-bit) |
3072 ;| R |Memory Refresh register |
3073 ;| SP |Stack Pointer register (16-bit) |
3074 ;|-----------------+--------------------------------------------|
3075 ;| b |One bit (0 to 7) |
3076 ;| cc |Condition (C,M,NC,NZ,P,PE,PO,Z) |
3077 ;| d |One-byte expression (-128 to +127) |
3078 ;| dst |Destination s, ss, [BC], [DE], [HL], [nn] |
3079 ;| e |One-byte expression (-126 to +129) |
3080 ;| m |Any register r, [HL] or [xx+d] |
3081 ;| n |One-byte expression (0 to 255) |
3082 ;| nn |Two-byte expression (0 to 65535) |
3083 ;| pp |Register pair BC, DE, IX or SP |
3084 ;| qq |Register pair AF, BC, DE or HL |
3085 ;| qq' |Alternative register pair AF, BC, DE or HL |
3086 ;| r |Register A, B, C, D, E, H or L |
3087 ;| rr |Register pair BC, DE, IY or SP |
3088 ;| s |Any register r, value n, [HL] or [xx+d] |
3089 ;| src |Source s, ss, [BC], [DE], [HL], nn, [nn] |
3090 ;| ss |Register pair BC, DE, HL or SP |
3091 ;| xx |Index register IX or IY |
3092 ;|-----------------+--------------------------------------------|
3093 ;| + - * / ^ |Add/subtract/multiply/divide/exponent |
3094 ;| & ~ v x |Logical AND/NOT/inclusive OR/exclusive OR |
3095 ;| <- -> |Rotate left/right |
3096 ;| [ ] |Indirect addressing |
3097 ;| [ ]+ -[ ] |Indirect addressing auto-increment/decrement|
3098 ;| { } |Combination of operands |
3099 ;| # |Also BC=BC-1,DE=DE-1 |
3100 ;| ## |Only lower 4 bits of accumulator A used |
3101 ;----------------------------------------------------------------
3112 ;------------------------------------------------;
3113 ; Move single bit between two registers
3115 ; bmov dstreg,dstbit,srcreg.srcbit
3123 ;------------------------------------------------;
3124 ; Load table value from flash indexed by source reg.
3126 ; ldpmx dstreg,tablebase,indexreg
3128 ; (6 words, 8 cycles)
3131 ldi zh,high(@1*2) ; table must be page aligned
3135 .macro do_z80_flags_HP
3137 bmov z_flags, ZFL_P, temp, AVR_V
3138 bmov z_flags, ZFL_H, temp, AVR_H
3142 .macro do_z80_flags_set_N
3144 ori z_flags, (1<<ZFL_N) ; Negation auf 1
3148 .macro do_z80_flags_set_HN
3150 ori z_flags,(1<<ZFL_N)|(1<<ZFL_H)
3154 .macro do_z80_flags_clear_N
3156 andi z_flags,~(1<<ZFL_N)
3160 .macro do_z80_flags_op_rotate
3161 ; must not change avr carry flag!
3163 andi z_flags, ~( (1<<ZFL_H) | (1<<ZFL_N) | (1<<ZFL_C) )
3165 andi z_flags, ~( (1<<ZFL_C) )
3169 .macro do_z80_flags_op_and
3171 ori z_flags,(1<<ZFL_H)
3173 ori z_flags,(1<<ZFL_H)
3177 .macro do_z80_flags_op_or
3186 ;----------------------------------------------------------------
3187 ;|Mnemonic |SZHPNC|Description |Notes |
3188 ;----------------------------------------------------------------
3189 ;|INC r |***V0-|Increment |r=r+1 |
3190 ;|INC [HL] |***V0-|Increment |[HL]=[HL]+1 |
3191 ;|INC [xx+d]|***V0-|Increment |[xx+d]=[xx+d]+1 |
3192 ;|----------|SZHP C|---------- 8080 ----------------------------|
3193 ;|INC r |**-P0-|Increment |r=r+1 |
3194 ;|INC [HL] |**-P0-|Increment |[HL]=[HL]+1 |
3202 andi z_flags,(1<<ZFL_H)|(1<<ZFL_C) ; preserve C-, and H-flag
3203 ldpmx temp2, sz53p_tab, opl
3213 andi z_flags,(1<<ZFL_H)|(1<<ZFL_C) ; preserve C-, and H-flag
3214 ldpmx temp2, sz53p_tab, z_a
3219 ;----------------------------------------------------------------
3220 ;|Mnemonic |SZHPNC|Description |Notes |
3221 ;----------------------------------------------------------------
3222 ;|DEC r |***V1-|Decrement |s=s-1 |
3223 ;|INC [HL] |***V0-|Increment |[HL]=[HL]+1 |
3224 ;|INC [xx+d]|***V0-|Increment |[xx+d]=[xx+d]+1 |
3225 ;|----------|SZHP C|---------- 8080 ----------------------------|
3226 ;|DEC r |**-P -|Increment |r=r+1 |
3227 ;|DEC [HL] |**-P -|Increment |[HL]=[HL]+1 |
3235 andi z_flags,(1<<ZFL_H)|(1<<ZFL_C) ; preserve C-, and H-flag
3236 ldpmx temp2, sz53p_tab, opl
3247 andi z_flags,(1<<ZFL_H)|(1<<ZFL_C) ; preserve C-, and H-flag
3248 ldpmx temp2, sz53p_tab, z_a
3254 ;----------------------------------------------------------------
3255 ;|Mnemonic |SZHPNC|Description |Notes |
3256 ;----------------------------------------------------------------
3257 ;|INC xx |------|Increment |xx=xx+1 |
3258 ;|INC ss |------|Increment |ss=ss+1 |
3266 ;----------------------------------------------------------------
3267 ;|Mnemonic |SZHPNC|Description |Notes |
3268 ;----------------------------------------------------------------
3269 ;|DEC xx |------|Decrement |xx=xx-1 |
3270 ;|DEC ss |------|Decrement |ss=ss-1 |
3278 ;----------------------------------------------------------------
3279 ;|Mnemonic |SZHPNC|Description |Notes |
3280 ;----------------------------------------------------------------
3281 ;|RLCA |--0-0*|Rotate Left Circular |A=A<- |
3282 ;|----------|SZHP C|---------- 8080 ----------------------------|
3283 ;|RLCA |---- *|Rotate Left Circular |A=A<- |
3287 ;Rotate Left Cyclical. All bits move 1 to the
3288 ;left, the msb becomes c and lsb.
3289 do_z80_flags_op_rotate
3293 ori z_flags, (1<<ZFL_C)
3297 ;----------------------------------------------------------------
3298 ;|Mnemonic |SZHPNC|Description |Notes |
3299 ;----------------------------------------------------------------
3300 ;|RRCA |--0-0*|Rotate Right Circular|A=->A |
3301 ;|----------|SZHP C|---------- 8080 ----------------------------|
3302 ;|RRCA |---- *|Rotate Right Circular|A=->A |
3306 ;Rotate Right Cyclical. All bits move 1 to the
3307 ;right, the lsb becomes c and msb.
3308 do_z80_flags_op_rotate
3312 ori z_flags, (1<<ZFL_C)
3316 ;----------------------------------------------------------------
3317 ;|Mnemonic |SZHPNC|Description |Notes |
3318 ;----------------------------------------------------------------
3319 ;|RRA |--0-0*|Rotate Right Acc. |A=->{CY,A} |
3320 ;|----------|SZHP C|---------- 8080 ----------------------------|
3321 ;|RRA |---- *|Rotate Right Acc. |A=->{CY,A} |
3325 ;Rotate Right. All bits move 1 to the right, the lsb
3326 ;becomes c, c becomes msb.
3327 clc ; get z80 carry to avr carry
3330 do_z80_flags_op_rotate ; (clear ZFL_C, doesn't change AVR_C)
3331 bmov z_flags,ZFL_C, opl,0 ; Bit 0 --> CY
3335 ;----------------------------------------------------------------
3336 ;|Mnemonic |SZHPNC|Description |Notes |
3337 ;----------------------------------------------------------------
3338 ;|RLA |--0-0*|Rotate Left Acc. |A={CY,A}<- |
3339 ;|----------|SZHP C|---------- 8080 ----------------------------|
3340 ;|RLA |---- *|Rotate Left Acc. |A={CY,A}<- |
3344 ;Rotate Left. All bits move 1 to the left, the msb
3345 ;becomes c, c becomes lsb.
3349 do_z80_flags_op_rotate ; (clear ZFL_C, doesn't change AVR_C)
3350 bmov z_flags,ZFL_C, opl,7 ; Bit 7 --> CY
3354 ;----------------------------------------------------------------
3355 ;|Mnemonic |SZHPNC|Description |Notes |
3356 ;----------------------------------------------------------------
3357 ;|ADD A,s |***V0*|Add |A=A+s |
3358 ;|----------|SZHP C|---------- 8080 ----------------------------|
3359 ;|ADD A,s |***P *|Add |A=A+s |
3365 ldpmx z_flags,sz53p_tab,z_a ;S,Z,P flag
3366 bmov z_flags,ZFL_C, temp,AVR_C
3370 ;----------------------------------------------------------------
3371 ;|Mnemonic |SZHPNC|Description |Notes |
3372 ;----------------------------------------------------------------
3373 ;|ADC A,s |***V0*|Add with Carry |A=A+s+CY |
3374 ;|----------|SZHP C|---------- 8080 ----------------------------|
3375 ;|ADC A,s |***P *|Add with Carry |A=A+s+CY |
3384 ldpmx z_flags,sz53p_tab,z_a ;S,Z,P
3385 bmov z_flags,ZFL_C, temp,AVR_C
3389 ;----------------------------------------------------------------
3390 ;|Mnemonic |SZHPNC|Description |Notes |
3391 ;----------------------------------------------------------------
3392 ;|SUB s |***V1*|Subtract |A=A-s |
3393 ;|----------|SZHP C|---------- 8080 ----------------------------|
3394 ;|SUB s |***P *|Subtract |A=A-s |
3400 ldpmx z_flags,sz53p_tab,z_a ;S,Z,P
3401 bmov z_flags,ZFL_C, temp,AVR_C
3406 ;----------------------------------------------------------------
3407 ;|Mnemonic |SZHPNC|Description |Notes |
3408 ;----------------------------------------------------------------
3409 ;|CP s |***V1*|Compare |A-s |
3410 ;|----------|SZHP C|---------- 8080 ----------------------------|
3411 ;|CP s |***P *|Compare |A-s |
3419 ldpmx z_flags,sz53p_tab,opl ;S,Z,P
3420 bmov z_flags,ZFL_C, temp,AVR_C
3425 ;----------------------------------------------------------------
3426 ;|Mnemonic |SZHPNC|Description |Notes |
3427 ;----------------------------------------------------------------
3428 ;|SBC A,s |***V1*|Subtract with Carry |A=A-s-CY |
3429 ;|----------|SZHP C|---------- 8080 ----------------------------|
3430 ;|SBC A,s |***P *|Subtract with Carry |A=A-s-CY |
3439 ldpmx z_flags,sz53p_tab,z_a ;S,Z,P
3440 bmov z_flags,ZFL_C, temp,AVR_C
3445 ;----------------------------------------------------------------
3446 ;|Mnemonic |SZHPNC|Description |Notes |
3447 ;----------------------------------------------------------------
3448 ;|AND s |**1P00|Logical AND |A=A&s |
3449 ;|----------|SZHP C|---------- 8080 ----------------------------|
3450 ;|AND s |**-P 0|Logical AND |A=A&s |
3455 ldpmx z_flags,sz53p_tab,z_a ;S,Z,P,N,C
3460 ;----------------------------------------------------------------
3461 ;|Mnemonic |SZHPNC|Description |Notes |
3462 ;----------------------------------------------------------------
3463 ;|OR s |**0P00|Logical inclusive OR |A=Avs |
3464 ;|----------|SZHP C|---------- 8080 ----------------------------|
3465 ;|OR s |**-P00|Logical inclusive OR |A=Avs |
3470 ldpmx z_flags,sz53p_tab,z_a ;S,Z,H,P,N,C
3474 ;----------------------------------------------------------------
3475 ;|Mnemonic |SZHPNC|Description |Notes |
3476 ;----------------------------------------------------------------
3477 ;|XOR s |**0P00|Logical Exclusive OR |A=Axs |
3478 ;|----------|SZHP C|---------- 8080 ----------------------------|
3479 ;|XOR s |**-P 0|Logical Exclusive OR |A=Axs |
3484 ldpmx z_flags,sz53p_tab,z_a ;S,Z,H,P,N,C
3488 ;----------------------------------------------------------------
3489 ;|Mnemonic |SZHPNC|Description |Notes |
3490 ;----------------------------------------------------------------
3491 ;|ADD HL,ss |--?-0*|Add |HL=HL+ss |
3492 ;|----------|SZHP C|---------- 8080 ----------------------------|
3493 ;|ADD HL,ss |---- *|Add |HL=HL+ss |
3500 bmov z_flags,ZFL_H, temp,AVR_H
3501 bmov z_flags,ZFL_C, temp,AVR_C
3502 do_z80_flags_clear_N
3505 ;----------------------------------------------------------------
3506 ;|Mnemonic |SZHPNC|Description |Notes |
3507 ;----------------------------------------------------------------
3508 ;|LD dst,src|------|Load |dst=src |
3511 do_op_sthl: ;store hl to mem loc in opl:h
3513 #if DRAM_WORD_ACCESS
3525 ;----------------------------------------------------------------
3526 ;|Mnemonic |SZHPNC|Description |Notes |
3527 ;----------------------------------------------------------------
3528 ;|LD dst,src|------|Load |dst=src |
3533 #if DRAM_WORD_ACCESS
3545 ;----------------------------------------------------------------
3546 ;|Mnemonic |SZHPNC|Description |Notes |
3547 ;----------------------------------------------------------------
3548 ;|LD dst,src|------|Load |dst=src |
3557 ;----------------------------------------------------------------
3558 ;|Mnemonic |SZHPNC|Description |Notes |
3559 ;----------------------------------------------------------------
3560 ;|DAA |***P-*|Decimal Adjust Acc. | |
3561 ;|----------|SZHP C|---------- 8080 ----------------------------|
3565 ; Description (http://www.z80.info/z80syntx.htm#DAA):
3566 ; This instruction conditionally adjusts the accumulator for BCD addition
3567 ; and subtraction operations. For addition (ADD, ADC, INC) or subtraction
3568 ; (SUB, SBC, DEC, NEC), the following table indicates the operation performed:
3570 ; -------------------------------------------------------------------------------
3571 ; | | C Flag | HEX value in | H Flag | HEX value in | Number | C flag|
3572 ; | Operation| Before | upper digit | Before | lower digit | added | After |
3573 ; | | DAA | (bit 7-4) | DAA | (bit 3-0) | to byte | DAA |
3574 ; |-----------------------------------------------------------------------------|
3575 ; | | 0 | 0-9 | 0 | 0-9 | 00 | 0 |
3576 ; | ADD | 0 | 0-8 | 0 | A-F | 06 | 0 |
3577 ; | | 0 | 0-9 | 1 | 0-3 | 06 | 0 |
3578 ; | ADC | 0 | A-F | 0 | 0-9 | 60 | 1 |
3579 ; | | 0 | 9-F | 0 | A-F | 66 | 1 |
3580 ; | INC | 0 | A-F | 1 | 0-3 | 66 | 1 |
3581 ; | | 1 | 0-2 | 0 | 0-9 | 60 | 1 |
3582 ; | | 1 | 0-2 | 0 | A-F | 66 | 1 |
3583 ; | | 1 | 0-3 | 1 | 0-3 | 66 | 1 |
3584 ; |-----------------------------------------------------------------------------|
3585 ; | SUB | 0 | 0-9 | 0 | 0-9 | 00 | 0 |
3586 ; | SBC | 0 | 0-8 | 1 | 6-F | FA | 0 |
3587 ; | DEC | 1 | 7-F | 0 | 0-9 | A0 | 1 |
3588 ; | NEG | 1 | 6-F | 1 | 6-F | 9A | 1 |
3589 ; |-----------------------------------------------------------------------------|
3592 ; C: See instruction.
3594 ; P/V: Set if Acc. is even parity after operation, reset otherwise.
3595 ; H: See instruction.
3596 ; Z: Set if Acc. is Zero after operation, reset otherwise.
3597 ; S: Set if most significant bit of Acc. is 1 after operation, reset otherwise.
3603 ldi oph,0 ; what to add
3604 sbrc z_flags,ZFL_H ; if H-Flag
3607 andi temp,0x0f ; ... or lower digit > 9
3613 sbrc z_flags,(1<<ZFL_C)
3622 ori z_flags,(1<<ZFL_C); set C
3624 sbrs z_flags,ZFL_N ; if sub-op
3625 rjmp op_da_add ; then
3628 op_da_add: ; else add-op
3641 ori z_flags,(1<<ZFL_C)
3642 andi z_flags,(1<<ZFL_N)|(1<<ZFL_C) ; preserve C,N
3643 ldpmx temp2, sz53p_tab, opl ; get S,Z,P
3645 bmov z_flags,ZFL_H, temp,AVR_H ; H (?)
3650 sbrc z_flags,ZFL_N ; if add-op
3651 rjmp do_op_da_sub ; then
3655 cpi temp,0x0a ; if lower digit > 9
3657 ori temp2,0x06 ; add 6 to lower digit
3659 sbrc z_flags,ZFL_H ; ... or H-Flag
3669 do_op_da_c: ; else sub-op
3670 sbrc z_flags,ZFL_C ;
3672 andi z_flags, ~( (1<<ZFL_S) | (1<<ZFL_Z) | (1<<ZFL_H) )
3675 bst temp,AVR_Z ;Z-Flag
3677 bst temp,AVR_N ;S-Flag
3679 sbrc temp2,5 ;C-Flag, set if 0x06 added
3680 ori z_flags,(1<<ZFL_C) ;
3684 do_op_da_sub: ;TODO:
3689 ;----------------------------------------------------------------
3690 ;|Mnemonic |SZHPNC|Description |Notes |
3691 ;----------------------------------------------------------------
3692 ;|SCF |--0-01|Set Carry Flag |CY=1 |
3693 ;|----------|SZHP C|---------- 8080 ----------------------------|
3697 andi z_flags,~((1<<ZFL_H)|(1<<ZFL_N))
3698 ori z_flags,(1<<ZFL_C)
3701 ;----------------------------------------------------------------
3702 ;|Mnemonic |SZHPNC|Description |Notes |
3703 ;----------------------------------------------------------------
3704 ;|CCF |--?-0*|Complement Carry Flag|CY=~CY |
3705 ;|----------|SZHP C|---------- 8080 ----------------------------|
3706 ;|SCF |---- 1|Set Carry Flag |CY=1 |
3710 do_z80_flags_clear_N
3715 ;----------------------------------------------------------------
3716 ;|Mnemonic |SZHPNC|Description |Notes |
3717 ;----------------------------------------------------------------
3718 ;|CPL |--1-1-|Complement |A=~A |
3719 ;|----------|SZHP C|---------- 8080 ----------------------------|
3720 ;|CPL |---- -|Complement |A=~A |
3729 ;----------------------------------------------------------------
3730 ;|Mnemonic |SZHPNC|Description |Notes |
3731 ;----------------------------------------------------------------
3732 ;|PUSH xx |------|Push |-[SP]=xx |
3733 ;|PUSH qq |------|Push |-[SP]=qq |
3741 #if DRAM_WORD_ACCESS
3760 .db ", SP is now ",0
3771 ;----------------------------------------------------------------
3772 ;|Mnemonic |SZHPNC|Description |Notes |
3773 ;----------------------------------------------------------------
3774 ;|POP xx |------|Pop |xx=[SP]+ |
3775 ;|POP qq |------|Pop |qq=[SP]+ |
3780 #if DRAM_WORD_ACCESS
3798 .db "Stack pop: val ",0
3814 ;----------------------------------------------------------------
3815 ;|Mnemonic |SZHPNC|Description |Notes |
3816 ;----------------------------------------------------------------
3817 ;|EX [SP],HL|------|Exchange |[SP]<->HL |
3818 ;|EX DE,HL |------|Exchange |DE<->HL |
3830 ;----------------------------------------------------------------
3831 ;|Mnemonic |SZHPNC|Description |Notes |
3832 ;----------------------------------------------------------------
3834 ; TODO: Implement IFF1, IFF2
3838 ;----------------------------------------------------------------
3839 ;|Mnemonic |SZHPNC|Description |Notes |
3840 ;----------------------------------------------------------------
3842 ; TODO: Implement IFF1, IFF2
3846 ;----------------------------------------------------------------
3847 ;|Mnemonic |SZHPNC|Description |Notes |
3848 ;----------------------------------------------------------------
3849 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3850 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3851 ;|RET cc |------|Conditional Return |If cc RET |
3861 ;----------------------------------------------------------------
3862 ;|Mnemonic |SZHPNC|Description |Notes |
3863 ;----------------------------------------------------------------
3864 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3865 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3866 ;|RET cc |------|Conditional Return |If cc RET |
3876 ;----------------------------------------------------------------
3877 ;|Mnemonic |SZHPNC|Description |Notes |
3878 ;----------------------------------------------------------------
3879 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3880 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3881 ;|RET cc |------|Conditional Return |If cc RET |
3891 ;----------------------------------------------------------------
3892 ;|Mnemonic |SZHPNC|Description |Notes |
3893 ;----------------------------------------------------------------
3894 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3895 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3896 ;|RET cc |------|Conditional Return |If cc RET |
3906 ;----------------------------------------------------------------
3907 ;|Mnemonic |SZHPNC|Description |Notes |
3908 ;----------------------------------------------------------------
3909 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3910 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3911 ;|RET cc |------|Conditional Return |If cc RET |
3921 ;----------------------------------------------------------------
3922 ;|Mnemonic |SZHPNC|Description |Notes |
3923 ;----------------------------------------------------------------
3924 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3925 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3926 ;|RET cc |------|Conditional Return |If cc RET |
3936 ;----------------------------------------------------------------
3937 ;|Mnemonic |SZHPNC|Description |Notes |
3938 ;----------------------------------------------------------------
3939 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3940 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3941 ;|RET cc |------|Conditional Return |If cc RET |
3944 do_op_ifp: ;sign positive, aka s=0
3951 ;----------------------------------------------------------------
3952 ;|Mnemonic |SZHPNC|Description |Notes |
3953 ;----------------------------------------------------------------
3954 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3955 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3956 ;|RET cc |------|Conditional Return |If cc RET |
3959 do_op_ifm: ;sign negative, aka s=1
3966 ;----------------------------------------------------------------
3967 ;|Mnemonic |SZHPNC|Description |Notes |
3968 ;----------------------------------------------------------------
3969 ;|OUT [n],A |------|Output |[n]=A |
3972 ;Interface with peripherials goes here :)
3973 do_op_outa: ; out (opl),a
3976 .db 13,"Port write: ",0
3991 ;----------------------------------------------------------------
3992 ;|Mnemonic |SZHPNC|Description |Notes |
3993 ;----------------------------------------------------------------
3994 ;|IN A,[n] |------|Input |A=[n] |
3997 do_op_in: ; in a,(opl)
4000 .db 13,"Port read: (",0
4019 ;----------------------------------------------------------------
4022 .db "Invalid opcode @ PC=",0,0
4028 ;----------------------------------------------------------------
4032 ;----------------------------------------------------------------
4033 ; Lookup table, stolen from z80ex, Z80 emulation library.
4034 ; http://z80ex.sourceforge.net/
4036 ; The S, Z, 5 and 3 bits and the parity of the lookup value
4037 .org (PC+255) & 0xff00
4039 .db 0x44,0x00,0x00,0x04,0x00,0x04,0x04,0x00
4040 .db 0x08,0x0c,0x0c,0x08,0x0c,0x08,0x08,0x0c
4041 .db 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04
4042 .db 0x0c,0x08,0x08,0x0c,0x08,0x0c,0x0c,0x08
4043 .db 0x20,0x24,0x24,0x20,0x24,0x20,0x20,0x24
4044 .db 0x2c,0x28,0x28,0x2c,0x28,0x2c,0x2c,0x28
4045 .db 0x24,0x20,0x20,0x24,0x20,0x24,0x24,0x20
4046 .db 0x28,0x2c,0x2c,0x28,0x2c,0x28,0x28,0x2c
4047 .db 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04
4048 .db 0x0c,0x08,0x08,0x0c,0x08,0x0c,0x0c,0x08
4049 .db 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00
4050 .db 0x08,0x0c,0x0c,0x08,0x0c,0x08,0x08,0x0c
4051 .db 0x24,0x20,0x20,0x24,0x20,0x24,0x24,0x20
4052 .db 0x28,0x2c,0x2c,0x28,0x2c,0x28,0x28,0x2c
4053 .db 0x20,0x24,0x24,0x20,0x24,0x20,0x20,0x24
4054 .db 0x2c,0x28,0x28,0x2c,0x28,0x2c,0x2c,0x28
4055 .db 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84
4056 .db 0x8c,0x88,0x88,0x8c,0x88,0x8c,0x8c,0x88
4057 .db 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80
4058 .db 0x88,0x8c,0x8c,0x88,0x8c,0x88,0x88,0x8c
4059 .db 0xa4,0xa0,0xa0,0xa4,0xa0,0xa4,0xa4,0xa0
4060 .db 0xa8,0xac,0xac,0xa8,0xac,0xa8,0xa8,0xac
4061 .db 0xa0,0xa4,0xa4,0xa0,0xa4,0xa0,0xa0,0xa4
4062 .db 0xac,0xa8,0xa8,0xac,0xa8,0xac,0xac,0xa8
4063 .db 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80
4064 .db 0x88,0x8c,0x8c,0x88,0x8c,0x88,0x88,0x8c
4065 .db 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84
4066 .db 0x8c,0x88,0x88,0x8c,0x88,0x8c,0x8c,0x88
4067 .db 0xa0,0xa4,0xa4,0xa0,0xa4,0xa0,0xa0,0xa4
4068 .db 0xac,0xa8,0xa8,0xac,0xa8,0xac,0xac,0xa8
4069 .db 0xa4,0xa0,0xa0,0xa4,0xa0,0xa4,0xa4,0xa0
4070 .db 0xa8,0xac,0xac,0xa8,0xac,0xa8,0xa8,0xac
4073 ; ----------------------- Opcode decoding -------------------------
4075 ; Lookup table for Z80 opcodes. Translates the first byte of the instruction word into three
4076 ; operations: fetch, do something, store.
4077 ; The table is made of 256 words. These 16-bit words consist of
4078 ; the fetch operation (bit 0-4), the processing operation (bit 10-16) and the store
4079 ; operation (bit 5-9).
4080 .org (PC+255) & 0xff00
4082 .dw (FETCH_NOP | OP_NOP | STORE_NOP) ; 00 NOP
4083 .dw (FETCH_DIR16| OP_NOP | STORE_BC ) ; 01 nn nn LD BC,nn
4084 .dw (FETCH_A | OP_NOP | STORE_MBC) ; 02 LD (BC),A
4085 .dw (FETCH_BC | OP_INC16 | STORE_BC ) ; 03 INC BC
4086 .dw (FETCH_B | OP_INC | STORE_B ) ; 04 INC B
4087 .dw (FETCH_B | OP_DEC | STORE_B ) ; 05 DEC B
4088 .dw (FETCH_DIR8 | OP_NOP | STORE_B ) ; 06 nn LD B,n
4089 .dw (FETCH_A | OP_RLC | STORE_A ) ; 07 RLCA
4090 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 08 EX AF,AF' (Z80)
4091 .dw (FETCH_BC | OP_ADDHL | STORE_HL ) ; 09 ADD HL,BC
4092 .dw (FETCH_MBC | OP_NOP | STORE_A ) ; 0A LD A,(BC)
4093 .dw (FETCH_BC | OP_DEC16 | STORE_BC ) ; 0B DEC BC
4094 .dw (FETCH_C | OP_INC | STORE_C ) ; 0C INC C
4095 .dw (FETCH_C | OP_DEC | STORE_C ) ; 0D DEC C
4096 .dw (FETCH_DIR8 | OP_NOP | STORE_C ) ; 0E nn LD C,n
4097 .dw (FETCH_A | OP_RRC | STORE_A ) ; 0F RRCA
4098 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 10 oo DJNZ o (Z80)
4099 .dw (FETCH_DIR16| OP_NOP | STORE_DE ) ; 11 nn nn LD DE,nn
4100 .dw (FETCH_A | OP_NOP | STORE_MDE) ; 12 LD (DE),A
4101 .dw (FETCH_DE | OP_INC16 | STORE_DE ) ; 13 INC DE
4102 .dw (FETCH_D | OP_INC | STORE_D ) ; 14 INC D
4103 .dw (FETCH_D | OP_DEC | STORE_D ) ; 15 DEC D
4104 .dw (FETCH_DIR8 | OP_NOP | STORE_D ) ; 16 nn LD D,n
4105 .dw (FETCH_A | OP_RL | STORE_A ) ; 17 RLA
4106 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 18 oo JR o (Z80)
4107 .dw (FETCH_DE | OP_ADDHL | STORE_HL ) ; 19 ADD HL,DE
4108 .dw (FETCH_MDE | OP_NOP | STORE_A ) ; 1A LD A,(DE)
4109 .dw (FETCH_DE | OP_DEC16 | STORE_DE ) ; 1B DEC DE
4110 .dw (FETCH_E | OP_INC | STORE_E ) ; 1C INC E
4111 .dw (FETCH_E | OP_DEC | STORE_E ) ; 1D DEC E
4112 .dw (FETCH_DIR8 | OP_NOP | STORE_E ) ; 1E nn LD E,n
4113 .dw (FETCH_A | OP_RR | STORE_A ) ; 1F RRA
4114 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 20 oo JR NZ,o (Z80)
4115 .dw (FETCH_DIR16| OP_NOP | STORE_HL ) ; 21 nn nn LD HL,nn
4116 .dw (FETCH_DIR16| OP_STHL | STORE_NOP) ; 22 nn nn LD (nn),HL
4117 .dw (FETCH_HL | OP_INC16 | STORE_HL ) ; 23 INC HL
4118 .dw (FETCH_H | OP_INC | STORE_H ) ; 24 INC H
4119 .dw (FETCH_H | OP_DEC | STORE_H ) ; 25 DEC H
4120 .dw (FETCH_DIR8 | OP_NOP | STORE_H ) ; 26 nn LD H,n
4121 .dw (FETCH_A | OP_DA | STORE_A ) ; 27 DAA
4122 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 28 oo JR Z,o (Z80)
4123 .dw (FETCH_HL | OP_ADDHL | STORE_HL ) ; 29 ADD HL,HL
4124 .dw (FETCH_DIR16| OP_RMEM16 | STORE_HL ) ; 2A nn nn LD HL,(nn)
4125 .dw (FETCH_HL | OP_DEC16 | STORE_HL ) ; 2B DEC HL
4126 .dw (FETCH_L | OP_INC | STORE_L ) ; 2C INC L
4127 .dw (FETCH_L | OP_DEC | STORE_L ) ; 2D DEC L
4128 .dw (FETCH_DIR8 | OP_NOP | STORE_L ) ; 2E nn LD L,n
4129 .dw (FETCH_NOP | OP_CPL | STORE_NOP) ; 2F CPL
4130 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 30 oo JR NC,o (Z80)
4131 .dw (FETCH_DIR16| OP_NOP | STORE_SP ) ; 31 nn nn LD SP,nn
4132 .dw (FETCH_DIR16| OP_NOP | STORE_AM ) ; 32 nn nn LD (nn),A
4133 .dw (FETCH_SP | OP_INC16 | STORE_SP ) ; 33 INC SP
4134 .dw (FETCH_MHL | OP_INC | STORE_MHL) ; 34 INC (HL)
4135 .dw (FETCH_MHL | OP_DEC | STORE_MHL) ; 35 DEC (HL)
4136 .dw (FETCH_DIR8 | OP_NOP | STORE_MHL) ; 36 nn LD (HL),n
4137 .dw (FETCH_NOP | OP_SCF | STORE_NOP) ; 37 SCF
4138 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 38 oo JR C,o (Z80)
4139 .dw (FETCH_SP | OP_ADDHL | STORE_HL ) ; 39 ADD HL,SP
4140 .dw (FETCH_DIR16| OP_RMEM8 | STORE_A ) ; 3A nn nn LD A,(nn)
4141 .dw (FETCH_SP | OP_DEC16 | STORE_SP ) ; 3B DEC SP
4142 .dw (FETCH_NOP | OP_INCA | STORE_NOP) ; 3C INC A
4143 .dw (FETCH_NOP | OP_DECA | STORE_NOP) ; 3D DEC A
4144 .dw (FETCH_DIR8 | OP_NOP | STORE_A ) ; 3E nn LD A,n
4145 .dw (FETCH_NOP | OP_CCF | STORE_NOP) ; 3F CCF (Complement Carry Flag, gvd)
4146 .dw (FETCH_B | OP_NOP | STORE_B ) ; 40 LD B,r
4147 .dw (FETCH_C | OP_NOP | STORE_B ) ; 41 LD B,r
4148 .dw (FETCH_D | OP_NOP | STORE_B ) ; 42 LD B,r
4149 .dw (FETCH_E | OP_NOP | STORE_B ) ; 43 LD B,r
4150 .dw (FETCH_H | OP_NOP | STORE_B ) ; 44 LD B,r
4151 .dw (FETCH_L | OP_NOP | STORE_B ) ; 45 LD B,r
4152 .dw (FETCH_MHL | OP_NOP | STORE_B ) ; 46 LD B,r
4153 .dw (FETCH_A | OP_NOP | STORE_B ) ; 47 LD B,r
4154 .dw (FETCH_B | OP_NOP | STORE_C ) ; 48 LD C,r
4155 .dw (FETCH_C | OP_NOP | STORE_C ) ; 49 LD C,r
4156 .dw (FETCH_D | OP_NOP | STORE_C ) ; 4A LD C,r
4157 .dw (FETCH_E | OP_NOP | STORE_C ) ; 4B LD C,r
4158 .dw (FETCH_H | OP_NOP | STORE_C ) ; 4C LD C,r
4159 .dw (FETCH_L | OP_NOP | STORE_C ) ; 4D LD C,r
4160 .dw (FETCH_MHL | OP_NOP | STORE_C ) ; 4E LD C,r
4161 .dw (FETCH_A | OP_NOP | STORE_C ) ; 4F LD C,r
4162 .dw (FETCH_B | OP_NOP | STORE_D ) ; 50 LD D,r
4163 .dw (FETCH_C | OP_NOP | STORE_D ) ; 51 LD D,r
4164 .dw (FETCH_D | OP_NOP | STORE_D ) ; 52 LD D,r
4165 .dw (FETCH_E | OP_NOP | STORE_D ) ; 53 LD D,r
4166 .dw (FETCH_H | OP_NOP | STORE_D ) ; 54 LD D,r
4167 .dw (FETCH_L | OP_NOP | STORE_D ) ; 55 LD D,r
4168 .dw (FETCH_MHL | OP_NOP | STORE_D ) ; 56 LD D,r
4169 .dw (FETCH_A | OP_NOP | STORE_D ) ; 57 LD D,r
4170 .dw (FETCH_B | OP_NOP | STORE_E ) ; 58 LD E,r
4171 .dw (FETCH_C | OP_NOP | STORE_E ) ; 59 LD E,r
4172 .dw (FETCH_D | OP_NOP | STORE_E ) ; 5A LD E,r
4173 .dw (FETCH_E | OP_NOP | STORE_E ) ; 5B LD E,r
4174 .dw (FETCH_H | OP_NOP | STORE_E ) ; 5C LD E,r
4175 .dw (FETCH_L | OP_NOP | STORE_E ) ; 5D LD E,r
4176 .dw (FETCH_MHL | OP_NOP | STORE_E ) ; 5E LD E,r
4177 .dw (FETCH_A | OP_NOP | STORE_E ) ; 5F LD E,r
4178 .dw (FETCH_B | OP_NOP | STORE_H ) ; 60 LD H,r
4179 .dw (FETCH_C | OP_NOP | STORE_H ) ; 61 LD H,r
4180 .dw (FETCH_D | OP_NOP | STORE_H ) ; 62 LD H,r
4181 .dw (FETCH_E | OP_NOP | STORE_H ) ; 63 LD H,r
4182 .dw (FETCH_H | OP_NOP | STORE_H ) ; 64 LD H,r
4183 .dw (FETCH_L | OP_NOP | STORE_H ) ; 65 LD H,r
4184 .dw (FETCH_MHL | OP_NOP | STORE_H ) ; 66 LD H,r
4185 .dw (FETCH_A | OP_NOP | STORE_H ) ; 67 LD H,r
4186 .dw (FETCH_B | OP_NOP | STORE_L ) ; 68 LD L,r
4187 .dw (FETCH_C | OP_NOP | STORE_L ) ; 69 LD L,r
4188 .dw (FETCH_D | OP_NOP | STORE_L ) ; 6A LD L,r
4189 .dw (FETCH_E | OP_NOP | STORE_L ) ; 6B LD L,r
4190 .dw (FETCH_H | OP_NOP | STORE_L ) ; 6C LD L,r
4191 .dw (FETCH_L | OP_NOP | STORE_L ) ; 6D LD L,r
4192 .dw (FETCH_MHL | OP_NOP | STORE_L ) ; 6E LD L,r
4193 .dw (FETCH_A | OP_NOP | STORE_L ) ; 6F LD L,r
4194 .dw (FETCH_B | OP_NOP | STORE_MHL) ; 70 LD (HL),r
4195 .dw (FETCH_C | OP_NOP | STORE_MHL) ; 71 LD (HL),r
4196 .dw (FETCH_D | OP_NOP | STORE_MHL) ; 72 LD (HL),r
4197 .dw (FETCH_E | OP_NOP | STORE_MHL) ; 73 LD (HL),r
4198 .dw (FETCH_H | OP_NOP | STORE_MHL) ; 74 LD (HL),r
4199 .dw (FETCH_L | OP_NOP | STORE_MHL) ; 75 LD (HL),r
4200 .dw (FETCH_NOP | OP_NOP | STORE_NOP) ; 76 HALT
4201 .dw (FETCH_A | OP_NOP | STORE_MHL) ; 77 LD (HL),r
4202 .dw (FETCH_B | OP_NOP | STORE_A ) ; 78 LD A,r
4203 .dw (FETCH_C | OP_NOP | STORE_A ) ; 79 LD A,r
4204 .dw (FETCH_D | OP_NOP | STORE_A ) ; 7A LD A,r
4205 .dw (FETCH_E | OP_NOP | STORE_A ) ; 7B LD A,r
4206 .dw (FETCH_H | OP_NOP | STORE_A ) ; 7C LD A,r
4207 .dw (FETCH_L | OP_NOP | STORE_A ) ; 7D LD A,r
4208 .dw (FETCH_MHL | OP_NOP | STORE_A ) ; 7E LD A,r
4209 .dw (FETCH_A | OP_NOP | STORE_A ) ; 7F LD A,r
4210 .dw (FETCH_B | OP_ADDA | STORE_NOP) ; 80 ADD A,r
4211 .dw (FETCH_C | OP_ADDA | STORE_NOP) ; 81 ADD A,r
4212 .dw (FETCH_D | OP_ADDA | STORE_NOP) ; 82 ADD A,r
4213 .dw (FETCH_E | OP_ADDA | STORE_NOP) ; 83 ADD A,r
4214 .dw (FETCH_H | OP_ADDA | STORE_NOP) ; 84 ADD A,r
4215 .dw (FETCH_L | OP_ADDA | STORE_NOP) ; 85 ADD A,r
4216 .dw (FETCH_MHL | OP_ADDA | STORE_NOP) ; 86 ADD A,r
4217 .dw (FETCH_A | OP_ADDA | STORE_NOP) ; 87 ADD A,r
4218 .dw (FETCH_B | OP_ADCA | STORE_NOP) ; 88 ADC A,r
4219 .dw (FETCH_C | OP_ADCA | STORE_NOP) ; 89 ADC A,r
4220 .dw (FETCH_D | OP_ADCA | STORE_NOP) ; 8A ADC A,r
4221 .dw (FETCH_E | OP_ADCA | STORE_NOP) ; 8B ADC A,r
4222 .dw (FETCH_H | OP_ADCA | STORE_NOP) ; 8C ADC A,r
4223 .dw (FETCH_L | OP_ADCA | STORE_NOP) ; 8D ADC A,r
4224 .dw (FETCH_MHL | OP_ADCA | STORE_NOP) ; 8E ADC A,r
4225 .dw (FETCH_A | OP_ADCA | STORE_NOP) ; 8F ADC A,r
4226 .dw (FETCH_B | OP_SUBFA | STORE_NOP) ; 90 SUB A,r
4227 .dw (FETCH_C | OP_SUBFA | STORE_NOP) ; 91 SUB A,r
4228 .dw (FETCH_D | OP_SUBFA | STORE_NOP) ; 92 SUB A,r
4229 .dw (FETCH_E | OP_SUBFA | STORE_NOP) ; 93 SUB A,r
4230 .dw (FETCH_H | OP_SUBFA | STORE_NOP) ; 94 SUB A,r
4231 .dw (FETCH_L | OP_SUBFA | STORE_NOP) ; 95 SUB A,r
4232 .dw (FETCH_MHL | OP_SUBFA | STORE_NOP) ; 96 SUB A,r
4233 .dw (FETCH_A | OP_SUBFA | STORE_NOP) ; 97 SUB A,r
4234 .dw (FETCH_B | OP_SBCFA | STORE_NOP) ; 98 SBC A,r
4235 .dw (FETCH_C | OP_SBCFA | STORE_NOP) ; 99 SBC A,r
4236 .dw (FETCH_D | OP_SBCFA | STORE_NOP) ; 9A SBC A,r
4237 .dw (FETCH_E | OP_SBCFA | STORE_NOP) ; 9B SBC A,r
4238 .dw (FETCH_H | OP_SBCFA | STORE_NOP) ; 9C SBC A,r
4239 .dw (FETCH_L | OP_SBCFA | STORE_NOP) ; 9D SBC A,r
4240 .dw (FETCH_MHL | OP_SBCFA | STORE_NOP) ; 9E SBC A,r
4241 .dw (FETCH_A | OP_SBCFA | STORE_NOP) ; 9F SBC A,r
4242 .dw (FETCH_B | OP_ANDA | STORE_NOP) ; A0 AND A,r
4243 .dw (FETCH_C | OP_ANDA | STORE_NOP) ; A1 AND A,r
4244 .dw (FETCH_D | OP_ANDA | STORE_NOP) ; A2 AND A,r
4245 .dw (FETCH_E | OP_ANDA | STORE_NOP) ; A3 AND A,r
4246 .dw (FETCH_H | OP_ANDA | STORE_NOP) ; A4 AND A,r
4247 .dw (FETCH_L | OP_ANDA | STORE_NOP) ; A5 AND A,r
4248 .dw (FETCH_MHL | OP_ANDA | STORE_NOP) ; A6 AND A,r
4249 .dw (FETCH_A | OP_ANDA | STORE_NOP) ; A7 AND A,r
4250 .dw (FETCH_B | OP_XORA | STORE_NOP) ; A8 XOR A,r
4251 .dw (FETCH_C | OP_XORA | STORE_NOP) ; A9 XOR A,r
4252 .dw (FETCH_D | OP_XORA | STORE_NOP) ; AA XOR A,r
4253 .dw (FETCH_E | OP_XORA | STORE_NOP) ; AB XOR A,r
4254 .dw (FETCH_H | OP_XORA | STORE_NOP) ; AC XOR A,r
4255 .dw (FETCH_L | OP_XORA | STORE_NOP) ; AD XOR A,r
4256 .dw (FETCH_MHL | OP_XORA | STORE_NOP) ; AE XOR A,r
4257 .dw (FETCH_A | OP_XORA | STORE_NOP) ; AF XOR A,r
4258 .dw (FETCH_B | OP_ORA | STORE_NOP) ; B0 OR A,r
4259 .dw (FETCH_C | OP_ORA | STORE_NOP) ; B1 OR A,r
4260 .dw (FETCH_D | OP_ORA | STORE_NOP) ; B2 OR A,r
4261 .dw (FETCH_E | OP_ORA | STORE_NOP) ; B3 OR A,r
4262 .dw (FETCH_H | OP_ORA | STORE_NOP) ; B4 OR A,r
4263 .dw (FETCH_L | OP_ORA | STORE_NOP) ; B5 OR A,r
4264 .dw (FETCH_MHL | OP_ORA | STORE_NOP) ; B6 OR A,r
4265 .dw (FETCH_A | OP_ORA | STORE_NOP) ; B7 OR A,r
4266 .dw (FETCH_B | OP_CPFA | STORE_NOP) ; B8 CP A,r
4267 .dw (FETCH_C | OP_CPFA | STORE_NOP) ; B9 CP A,r
4268 .dw (FETCH_D | OP_CPFA | STORE_NOP) ; BA CP A,r
4269 .dw (FETCH_E | OP_CPFA | STORE_NOP) ; BB CP A,r
4270 .dw (FETCH_H | OP_CPFA | STORE_NOP) ; BC CP A,r
4271 .dw (FETCH_L | OP_CPFA | STORE_NOP) ; BD CP A,r
4272 .dw (FETCH_MHL | OP_CPFA | STORE_NOP) ; BE CP A,r
4273 .dw (FETCH_A | OP_CPFA | STORE_NOP) ; BF CP A,r
4274 .dw (FETCH_NOP | OP_IFNZ | STORE_RET) ; C0 RET NZ
4275 .dw (FETCH_NOP | OP_POP16 | STORE_BC ) ; C1 POP BC
4276 .dw (FETCH_DIR16| OP_IFNZ | STORE_PC ) ; C2 nn nn JP NZ,nn
4277 .dw (FETCH_DIR16| OP_NOP | STORE_PC ) ; C3 nn nn JP nn
4278 .dw (FETCH_DIR16| OP_IFNZ | STORE_CALL) ; C4 nn nn CALL NZ,nn
4279 .dw (FETCH_BC | OP_PUSH16 | STORE_NOP) ; C5 PUSH BC
4280 .dw (FETCH_DIR8 | OP_ADDA | STORE_NOP) ; C6 nn ADD A,n
4281 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; C7 RST 0
4282 .dw (FETCH_NOP | OP_IFZ | STORE_RET) ; C8 RET Z
4283 .dw (FETCH_NOP | OP_NOP | STORE_RET) ; C9 RET
4284 .dw (FETCH_DIR16| OP_IFZ | STORE_PC ) ; CA nn nn JP Z,nn
4285 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; CB (Z80 specific)
4286 .dw (FETCH_DIR16| OP_IFZ | STORE_CALL) ; CC nn nn CALL Z,nn
4287 .dw (FETCH_DIR16| OP_NOP | STORE_CALL) ; CD nn nn CALL nn
4288 .dw (FETCH_DIR8 | OP_ADCA | STORE_NOP) ; CE nn ADC A,n
4289 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; CF RST 8H
4290 .dw (FETCH_NOP | OP_IFNC | STORE_RET) ; D0 RET NC
4291 .dw (FETCH_NOP | OP_POP16 | STORE_DE ) ; D1 POP DE
4292 .dw (FETCH_DIR16| OP_IFNC | STORE_PC ) ; D2 nn nn JP NC,nn
4293 .dw (FETCH_DIR8 | OP_OUTA | STORE_NOP) ; D3 nn OUT (n),A
4294 .dw (FETCH_DIR16| OP_IFNC | STORE_CALL) ; D4 nn nn CALL NC,nn
4295 .dw (FETCH_DE | OP_PUSH16 | STORE_NOP) ; D5 PUSH DE
4296 .dw (FETCH_DIR8 | OP_SUBFA | STORE_NOP) ; D6 nn SUB n
4297 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; D7 RST 10H
4298 .dw (FETCH_NOP | OP_IFC | STORE_RET) ; D8 RET C
4299 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; D9 EXX (Z80)
4300 .dw (FETCH_DIR16| OP_IFC | STORE_PC ) ; DA nn nn JP C,nn
4301 .dw (FETCH_DIR8 | OP_IN | STORE_A ) ; DB nn IN A,(n)
4302 .dw (FETCH_DIR16| OP_IFC | STORE_CALL) ; DC nn nn CALL C,nn
4303 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; DD (Z80)
4304 .dw (FETCH_DIR8 | OP_SBCFA | STORE_NOP) ; DE nn SBC A,n
4305 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; DF RST 18H
4306 .dw (FETCH_NOP | OP_IFPO | STORE_RET) ; E0 RET PO
4307 .dw (FETCH_NOP | OP_POP16 | STORE_HL ) ; E1 POP HL
4308 .dw (FETCH_DIR16| OP_IFPO | STORE_PC ) ; E2 nn nn JP PO,nn
4309 .dw (FETCH_MSP | OP_EXHL | STORE_MSP) ; E3 EX (SP),HL
4310 .dw (FETCH_DIR16| OP_IFPO | STORE_CALL) ; E4 nn nn CALL PO,nn
4311 .dw (FETCH_HL | OP_PUSH16 | STORE_NOP) ; E5 PUSH HL
4312 .dw (FETCH_DIR8 | OP_ANDA | STORE_NOP) ; E6 nn AND n
4313 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; E7 RST 20H
4314 .dw (FETCH_NOP | OP_IFPE | STORE_RET) ; E8 RET PE
4315 .dw (FETCH_HL | OP_NOP | STORE_PC ) ; E9 JP (HL)
4316 .dw (FETCH_DIR16| OP_IFPE | STORE_PC ) ; EA nn nn JP PE,nn
4317 .dw (FETCH_DE | OP_EXHL | STORE_DE ) ; EB EX DE,HL
4318 .dw (FETCH_DIR16| OP_IFPE | STORE_CALL) ; EC nn nn CALL PE,nn
4319 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; ED (Z80 specific)
4320 .dw (FETCH_DIR8 | OP_XORA | STORE_NOP) ; EE nn XOR n
4321 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; EF RST 28H
4322 .dw (FETCH_NOP | OP_IFP | STORE_RET) ; F0 RET P
4323 .dw (FETCH_NOP | OP_POP16 | STORE_AF ) ; F1 POP AF
4324 .dw (FETCH_DIR16| OP_IFP | STORE_PC ) ; F2 nn nn JP P,nn
4325 .dw (FETCH_NOP | OP_DI | STORE_NOP) ; F3 DI
4326 .dw (FETCH_DIR16| OP_IFP | STORE_CALL) ; F4 nn nn CALL P,nn
4327 .dw (FETCH_AF | OP_PUSH16 | STORE_NOP) ; F5 PUSH AF
4328 .dw (FETCH_DIR8 | OP_ORA | STORE_NOP) ; F6 nn OR n
4329 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; F7 RST 30H
4330 .dw (FETCH_NOP | OP_IFM | STORE_RET) ; F8 RET M
4331 .dw (FETCH_HL | OP_NOP | STORE_SP ) ; F9 LD SP,HL
4332 .dw (FETCH_DIR16| OP_IFM | STORE_PC ) ; FA nn nn JP M,nn
4333 .dw (FETCH_NOP | OP_EI | STORE_NOP) ; FB EI
4334 .dw (FETCH_DIR16| OP_IFM | STORE_CALL) ; FC nn nn CALL M,nn
4335 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; FD (Z80 specific)
4336 .dw (FETCH_DIR8 | OP_CPFA | STORE_NOP) ; FE nn CP n
4337 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; FF RST 38H
4339 ; vim:set ts=8 noet nowrap