]> cloudbase.mooo.com Git - avrcpm.git/blob - avrcpm/avr/z80.asm
z80.asm: added interrupt driven delay timer; used in BOOTWAIT and RAMTEST.
[avrcpm.git] / avrcpm / avr / z80.asm
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.
3 ;
4 ; Copyright (C) 2010 Sprite_tm
5 ;
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.
10 ;
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.
15 ;
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/>.
18
19 .nolist
20 #if defined atmega8
21 .include "m8def.inc"
22 #elif defined atmega168
23 .include "m168def.inc"
24 #else /* default */
25 .include "m88def.inc"
26 ;FUSE_H=0xDF
27 ;FUSE_L=0xF7
28 #endif
29 .list
30
31 .listmac
32
33 #ifndef DRAM_DQ_ORDER /* If this is set to 1, the portbits */
34 #define DRAM_DQ_ORDER 0 /* for DRAM D1 and WE are swapped. */
35 #endif
36
37
38 #ifndef F_CPU
39 #define F_CPU 20000000 /* system clock in Hz; defaults to 20MHz */
40 #endif
41 #ifndef BAUD
42 #define BAUD 38400 /* console baud rate */
43 #endif
44
45
46 #define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) /* clever rounding */
47
48 #define RXBUFSIZE 64 /* USART recieve buffer size. Must be power of 2 */
49
50 #define REFR_RATE 64000 /* dram refresh rate in cycles/s. */
51 /* Most drams need 1/15.6µs. */
52 #define REFR_PRE 8 /* timer prescale factor */
53 #define REFR_CS 0x02 /* timer clock select for 1/8 */
54 #define REFR_CNT F_CPU / REFR_RATE / REFR_PRE
55
56
57 #if defined __ATmega8__
58 .equ refr_vect = OC2addr
59 #else
60 .equ refr_vect = OC2Aaddr
61 #endif
62
63
64 #define EM_Z80 0 /* we don't have any z80 instructions yet */
65
66 .equ MMC_DEBUG = 0
67 .equ INS_DEBUG = 0
68 .equ MEMTEST = 1
69 .equ BOOTWAIT = 1
70 .equ PORT_DEBUG = 0
71 .equ DISK_DEBUG = 0
72 .equ MEMFILL_CB = 1
73 .equ STACK_DBG = 0
74 .equ PRINT_PC = 0
75
76 ;Port declarations
77
78 ; Port D
79 .equ rxd = 0
80 .equ txd = 1
81 .equ ram_oe = 2
82 .equ ram_a8 = 3
83 .equ mmc_cs = 4
84 .equ ram_a5 = 5
85 .equ ram_a6 = 6
86 .equ ram_a7 = 7
87 .equ P_OE = PORTD
88
89 .equ RAM_AH_MASK = 0xE0 ; ram_a[7..5]
90 .equ PD_OUTPUT_MASK = 0xFE
91
92
93 ;Port B
94 .equ ram_a4 = 0
95 .equ ram_a3 = 1
96 .equ ram_a2 = 2
97 .equ ram_a1 = 3
98 .equ mmc_mosi = 3
99 .equ ram_a0 = 4
100 .equ mmc_miso = 4
101 .equ ram_ras = 5
102 .equ mmc_sck = 5
103 .equ P_RAS = PORTB
104
105 .equ RAM_AL_MASK = 0x1F ; ram_a[4..0]
106 .equ PB_OUTPUT_MASK = 0x3F
107
108 ;Port C
109 #if DRAM_DQ_ORDER == 1
110 .equ ram_d1 = 1
111 .equ ram_w = 4
112 #else /* original */
113 .equ ram_d1 = 4
114 .equ ram_w = 1
115 #endif
116 .equ ram_d0 = 0
117 .equ ram_d2 = 2
118 .equ ram_d3 = 3
119 .equ ram_cas= 5
120 .equ P_W = PORTC
121 .equ P_CAS = PORTC
122
123 .equ RAM_DQ_MASK = (1<<ram_d3)|(1<<ram_d2)|(1<<ram_d1)|(1<<ram_d0)
124 .equ PC_OUTPUT_MASK = (1<<ram_cas)|(1<<ram_w)
125
126
127 ;Flag bits in z_flags
128 .equ ZFL_S = 7
129 .equ ZFL_Z = 6
130 .equ ZFL_H = 4
131 .equ ZFL_P = 2
132 .equ ZFL_N = 1
133 .equ ZFL_C = 0
134
135 ;Register definitions
136 .def z_a = r2
137 .def z_b = r3
138 .def z_c = r4
139 .def z_d = r5
140 .def z_e = r6
141 .def z_l = r7
142 .def z_h = r8
143 .def z_spl = r9
144 .def z_sph = r10
145
146 .def dsk_trk = r11
147 .def dsk_sec = r12
148 .def dsk_dmah = r13
149 .def dsk_dmal = r14
150
151 ;.def parityb = r15
152
153 .def temp = R16 ;The temp register
154 .def temp2 = R17 ;Second temp register
155 .def trace = r18
156 .def opl = r19
157 .def oph = r20
158 .def adrl = r21
159 .def adrh = r22
160 .def insdecl = r23
161 .def z_pcl = r24
162 .def z_pch = r25
163 .undef xl
164 .undef xh
165 .def insdech = r26
166 .def z_flags = r27
167
168
169 ; This is the base z80 port address for clock access
170 #define TIMERPORT 0x40
171 #define TIMER_CTL TIMERPORT
172 #define TIMER_MSECS TIMERPORT+1
173 #define TIMER_SECS TIMER_MSECS+2
174
175 #define starttimercmd 1
176 #define quitTimerCmd 2
177 #define printTimerCmd 15
178 #define uptimeCmd 16
179
180
181
182 ;SRAM
183 .dseg
184
185 ;Sector buffer for 512 byte reads/writes from/to SD-card
186
187 sectbuff:
188 .byte 512
189
190
191 .cseg
192 .org 0
193 rjmp start ; reset vector
194 .org refr_vect
195 rjmp refrint ; tim2cmpa
196 .org OC1Aaddr ; Timer/Counter1 Compare Match A
197 rjmp sysclockint ; 1ms system timer
198 .org URXCaddr
199 rjmp rxint ; USART receive int.
200 ;.org UDREaddr
201 ; rjmp txint
202
203 .org INT_VECTORS_SIZE
204
205 start:
206 ldi temp,low(RAMEND) ; top of memory
207 out SPL,temp ; init stack pointer
208 ldi temp,high(RAMEND) ; top of memory
209 out SPH,temp ; init stack pointer
210
211 ; - Kill wdt
212 wdr
213 #if defined __ATmega8__
214 ldi temp,0
215 out MCUCSR,temp
216
217 ldi temp,(1<<WDCE) | (1<<WDE)
218 out WDTCSR,temp
219 ldi temp,(1<<WDCE)
220 out WDTCSR,temp
221 #else
222 ldi temp,0
223 out MCUSR,temp
224
225 ldi temp,(1<<WDCE) | (1<<WDE)
226 sts WDTCSR,temp
227 ldi temp,(1<<WDCE)
228 sts WDTCSR,temp
229 #endif
230
231 ; - Setup Ports
232 ldi temp,PB_OUTPUT_MASK
233 out DDRB,temp
234 ldi temp,PD_OUTPUT_MASK
235 out DDRD,temp
236 ldi temp,PC_OUTPUT_MASK
237 out DDRC,temp
238
239 sbi PORTC,ram_w
240 sbi PORTC,ram_cas
241 sbi PORTB,ram_ras
242 sbi PORTD,ram_oe
243 sbi PORTD,mmc_cs
244
245
246 ; - Init serial port
247
248 ldi temp,0 ; reset receive buffer
249 sts rxcount,temp
250 sts rxidx_r,temp
251 sts rxidx_w,temp
252
253
254 #if defined __ATmega8__
255 ldi temp, (1<<TXEN) | (1<<RXEN) | (1<<RXCIE)
256 out UCSRB,temp
257 ldi temp, (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0)
258 out UCSRC,temp
259 ldi temp, HIGH(UBRR_VAL)
260 out UBRRH,temp
261 ldi temp, LOW(UBRR_VAL)
262 out UBRRL,temp
263 #else
264 ldi temp, (1<<TXEN0) | (1<<RXEN0) | (1<<RXCIE0)
265 sts UCSR0B,temp
266 ldi temp, (1<<UCSZ01) | (1<<UCSZ00)
267 sts UCSR0C,temp
268 ldi temp, HIGH(UBRR_VAL)
269 sts UBRR0H,temp
270 ldi temp, LOW(UBRR_VAL)
271 sts UBRR0L,temp
272 #endif
273
274 ;Init timer2. Refresh-call should happen every (8ms/512)=312 cycles.
275
276 #ifdef __ATmega8__
277 ldi temp,REFR_CNT*2 ; 2 cycles per int
278 out OCR2,temp
279 ldi temp,(1<<WGM21) | REFR_CS ;CTC, clk/REFR_PRE
280 out TCCR2,temp
281 ldi temp, (1<<OCIE2)
282 out TIMSK,temp
283 #else
284 ldi temp,REFR_CNT ;=312 cycles
285 sts OCR2A,temp
286 ldi temp, (1<<WGM21)
287 sts TCCR2A,temp
288 ldi temp, REFR_CS ;clk/REFR_PRE
289 sts TCCR2B,temp
290 ldi temp,(1<<OCIE2A)
291 sts TIMSK2,temp
292 #endif
293
294
295 ; Init clock/timer system
296
297 ldi zl,low(timer_base)
298 ldi zh,high(timer_base)
299 ldi temp,0
300 ldi temp2,timer_size
301 ti_loop:
302 st z+,temp
303 dec temp2
304 brne ti_loop
305
306 ; Init timer 1 as 1 ms system clock tick.
307
308 #ifdef __ATmega8__
309 ldi temp,high(F_CPU/1000)
310 out OCR1AH,temp
311 ldi temp,low(F_CPU/1000)
312 out OCR1AL,temp
313 ldi temp,(1<<WGM12) | (1<<CS10) ;CTC, clk/1
314 out TCCR1B,temp
315 in temp,TIMSK
316 ori temp,(1<<OCIE1A)
317 out TIMSK,temp
318 #else
319 ldi temp,high(F_CPU/1000)
320 sts OCR1AH,temp
321 ldi temp,low(F_CPU/1000)
322 sts OCR1AL,temp
323 ldi temp,(1<<WGM12) | (1<<CS10) ;CTC, clk/1
324 sts TCCR1B,temp
325 lds temp,TIMSK1
326 ori temp,(1<<OCIE1A)
327 sts TIMSK1,temp
328 #endif
329 sei
330
331
332 .if BOOTWAIT
333 ldi temp,10
334 rcall delay_ms
335
336 .endif
337
338 rcall printstr
339 .db "CPM on an AVR, v1.0",13,0,0
340
341
342 rcall printstr
343 .db "Initing mmc...",13,0
344 rcall mmcInit
345
346
347 .if MEMTEST
348 rcall printstr
349 .db "Testing RAM: fill...",0,0
350
351 ;Fill RAM
352 ldi adrl,0
353 ldi adrh,0
354 ramtestw:
355 mov temp,adrh
356 eor temp,adrl
357 rcall memwritebyte
358 ldi temp,1
359 ldi temp2,0
360 add adrl,temp
361 adc adrh,temp2
362 brcc ramtestw
363 rcall printstr
364 .db "wait...",0
365
366 ldi temp2,8
367 ramtestwl:
368 ldi temp,255
369 rcall delay_ms
370 dec temp2
371 brne ramtestwl
372
373 rcall printstr
374 .db "reread...",13,0,0
375
376 ;re-read RAM
377 ldi adrl,0
378 ldi adrh,0
379 ramtestr:
380 rcall memreadbyte
381 mov temp2,adrh
382 eor temp2,adrl
383 cp temp,temp2
384 breq ramtestrok
385 rcall printhex
386 ldi temp,'<'
387 rcall uartPutc
388 mov temp,adrh
389 eor temp,adrl
390 rcall printhex
391 ldi temp,'@'
392 rcall uartPutc
393 mov temp,adrh
394 rcall printhex
395 mov temp,adrl
396 rcall printhex
397 ldi temp,13
398 rcall uartPutc
399 ramtestrok:
400 ldi temp,1
401 ldi temp2,0
402 add adrl,temp
403 adc adrh,temp2
404 brcc ramtestr
405
406 .endif
407
408 .if MEMFILL_CB
409 ;Fill ram with cbs, which (for now) will trigger an invalid opcode error.
410 ldi adrl,0
411 ldi adrh,0
412 ramfillw:
413 ldi temp,0xcb
414 rcall memwritebyte
415 ldi temp,1
416 ldi temp2,0
417 add adrl,temp
418 adc adrh,temp2
419 brcc ramfillw
420 .endif
421
422
423
424 ;Load initial sector from MMC (512 bytes)
425 ldi adrh,0
426 ldi adrl,0
427 rcall mmcReadSect
428
429 ;Save to Z80 RAM (only 128 bytes because that's retro)
430 ldi zl,low(sectbuff)
431 ldi zh,high(sectbuff)
432 ldi adrh,0x20
433 ldi adrl,0x00
434 iplwriteloop:
435 ld temp,z+
436 push zh
437 push zl
438 rcall memWriteByte
439 pop zl
440 pop zh
441 ldi temp,1
442 ldi temp2,0
443 add adrl,temp
444 adc adrh,temp2
445 cpi zl,low(sectbuff+128)
446 brne iplwriteloop
447 cpi zh,high(sectbuff+128)
448 brne iplwriteloop
449
450
451
452 ;Init z80
453 ldi temp,0x00
454 mov z_pcl,temp
455 ldi temp,0x20
456 mov z_pch,temp
457
458 ldi trace,0
459 rcall printstr
460 .db 13,"Ok, CPU is live!",13,0,0
461
462 main:
463 ldi trace,0
464 cpi z_pch,1
465 brlo notraceon
466 cpi z_pch,$dc
467 brsh notraceon
468 ldi trace,1
469 notraceon:
470
471
472 .if PRINT_PC
473 cpi z_pch,1
474 brlo noprintpc
475 cpi z_pch,0xdc
476 brsh noprintpc
477
478 rcall printstr
479 .db "PC=",0
480 mov temp,z_pch
481 rcall printhex
482 mov temp,z_pcl
483 rcall printhex
484 ldi temp,10
485 rcall uartputc
486 noprintpc:
487 .endif
488
489 ; *** Stage 1: Fetch next opcode
490 mov adrl,z_pcl
491 mov adrh,z_pch
492 rcall memReadByte
493 adiw z_pcl,1
494
495
496 .if INS_DEBUG
497 cpi trace,0
498 breq notrace1
499 rcall printstr
500 .db "PC=",0
501 push temp
502 mov temp,adrh
503 rcall printhex
504 mov temp,adrl
505 rcall printhex
506 pop temp
507 rcall printstr
508 .db ", opcode=",0
509 rcall printhex
510 notrace1:
511 .endif
512
513 ; *** Stage 2: Decode it using the ins_table.
514 ldi temp2,0
515 ldi zl,low(inst_table*2)
516 ldi zh,high(inst_table*2)
517 add zl,temp
518 adc zh,temp2
519 add zl,temp
520 adc zh,temp2
521 lpm insdecl,Z+
522 lpm insdech,Z
523
524 .if INS_DEBUG
525 cpi trace,0
526 breq notrace2
527 rcall printstr
528 .db ", decoded=",0
529 mov temp,insdech
530 rcall printhex
531 mov temp,insdecl
532 rcall printhex
533 rcall printstr
534 .db ".",13,0
535 notrace2:
536 .endif
537
538 ; *** Stage 3: Fetch operand. Use the fetch jumptable for this.
539 mov temp,insdecl
540 andi temp,0x1F
541 cpi temp,0
542 breq nofetch
543 ldi temp2,0
544 lsl temp
545 ldi zl,low(fetchjumps*2)
546 ldi zh,high(fetchjumps*2)
547 add zl,temp
548 adc zh,temp2
549 lpm temp,Z+
550 lpm temp2,Z
551 mov zl,temp
552 mov zh,temp2
553 icall
554
555 .if INS_DEBUG
556 cpi trace,0
557 breq notrace3
558 rcall printstr
559 .db "pre: oph:l=",0
560 mov temp,oph
561 rcall printhex
562 mov temp,opl
563 rcall printhex
564 rcall printstr
565 .db " -- ",0
566 notrace3:
567 .endif
568
569 nofetch:
570 ; *** Stage 4: Execute operation :) Use the op jumptable for this.
571 mov temp,insdech
572 andi temp,0xFC
573 lsr temp
574 cpi temp,0
575 breq nooper
576 ldi zl,low(opjumps*2)
577 ldi zh,high(opjumps*2)
578 ldi temp2,0
579 add zl,temp
580 adc zh,temp2
581 lpm temp,Z+
582 lpm temp2,Z
583 mov zl,temp
584 mov zh,temp2
585 icall
586
587 .if INS_DEBUG
588 cpi trace,0
589 breq notrace4
590 rcall printstr
591 .db ",post:oph:l=",0
592 mov temp,oph
593 rcall printhex
594 mov temp,opl
595 rcall printhex
596 notrace4:
597 .endif
598
599 nooper:
600 ; *** Stage 5: Store operand. Use the store jumptable for this.
601 swap insdecl
602 swap insdech
603 mov temp,insdecl
604 andi temp,0x0E
605 andi insdech,0x30
606 or temp,insdech
607 breq nostore
608 ldi zl,low(storejumps*2)
609 ldi zh,high(storejumps*2)
610 ldi temp2,0
611 add zl,temp
612 adc zh,temp2
613 lpm temp,Z+
614 lpm temp2,Z
615 mov zl,temp
616 mov zh,temp2
617 icall
618
619 .if INS_DEBUG
620 cpi trace,0
621 breq notrace5
622 rcall printstr
623 .db ", stored.",0
624 notrace5:
625 .endif
626
627 nostore:
628
629 .if INS_DEBUG
630 cpi trace,0
631 breq notrace6
632 rcall printstr
633 .db 13,0
634 notrace6:
635 .endif
636
637 ;All done. Neeeext!
638 rjmp main
639
640
641 ; ----------------Virtual peripherial interface ------
642
643 ;The hw is modelled to make writing a CPM BIOS easier.
644 ;Ports:
645 ;0 - Con status. Returns 0xFF if the UART has a byte, 0 otherwise.
646 ;1 - Console input, aka UDR.
647 ;2 - Console output
648 ;16 - Track select
649 ;18 - Sector select
650 ;20 - Write addr l
651 ;21 - Write addr h
652 ;22 - Trigger - write 1 to read, 2 to write a sector using the above info.
653 ; This will automatically move track, sector and dma addr to the next sector.
654
655 ;Called with port in temp2. Should return value in temp.
656 portRead:
657 cpi temp2,0
658 breq conStatus
659 cpi temp2,1
660 breq conInp
661
662 cpi temp2,TIMER_MSECS
663 brlo pr_noclock
664 cpi temp2,TIMER_MSECS+6
665 brsh pr_noclock
666 rjmp clockget
667
668 pr_noclock:
669 ldi temp,0xFF
670 ret
671
672 ;Called with port in temp2 and value in temp.
673 portWrite:
674 cpi temp2,0
675 breq dbgOut
676 cpi temp2,2
677 breq conOut
678 cpi temp2,16
679 breq dskTrackSel
680 cpi temp2,18
681 breq dskSecSel
682 cpi temp2,20
683 breq dskDmaL
684 cpi temp2,21
685 breq dskDmaH
686 cpi temp2,22
687 breq dskDoIt
688
689 cpi temp2,TIMERPORT
690 brlo pw_noclock
691 cpi temp2,TIMER_MSECS+6
692 brsh pw_noclock
693 rjmp clockput
694
695 pw_noclock:
696 ret
697
698
699 conStatus:
700
701 lds temp,rxcount
702 tst temp
703 breq PC+2
704 ldi temp,0xff
705 ret
706
707 conInp:
708 rcall uartGetc
709 ret
710
711 dbgOut:
712 rcall printstr
713 .db "Debug: ",0
714 rcall printhex
715 rcall printstr
716 .db 13,0
717 ret
718
719 conOut:
720 rcall uartputc
721 ret
722
723
724
725 dskTrackSel:
726 mov dsk_trk,temp
727 ret
728
729 dskSecSel:
730 mov dsk_sec,temp
731 ret
732
733 dskDmal:
734 mov dsk_dmal,temp
735 ret
736
737 dskDmah:
738 mov dsk_dmah,temp
739 ret
740
741 dskDoIt:
742 .if DISK_DEBUG
743 push temp
744 rcall printstr
745 .db "Disk read: track ",0
746 mov temp,dsk_trk
747 rcall printhex
748 rcall printstr
749 .db " sector ",0
750 mov temp,dsk_sec
751 rcall printhex
752 rcall printstr
753 .db " dma-addr ",0
754 mov temp,dsk_dmah
755 rcall printhex
756 mov temp,dsk_dmal
757 rcall printhex
758 rcall printstr
759 .db ".",13,0
760 pop temp
761 .endif
762
763 ;First, convert track/sector to an LBA address (in 128byte blocks)
764 push temp
765 mov adrl,dsk_sec
766 ldi adrh,0
767 mov temp2,dsk_trk
768 dskXlateLoop:
769 cpi temp2,0
770 breq dskXlateLoopEnd
771 ldi temp,26
772 add adrl,temp
773 ldi temp,0
774 adc adrh,temp
775 dec temp2
776 rjmp dskXlateLoop
777 dskXlateLoopEnd:
778 pop temp
779
780 ;Now, see what has to be done.
781 cpi temp,1
782 breq dskDoItRead
783 cpi temp,2
784 breq dskDoItWrite
785
786 dskDoItRead:
787 push adrl
788 ;Convert from 128-byte LBA blocks to 512-byte LBA blocks
789 lsr adrh
790 ror adrl
791 lsr adrh
792 ror adrl
793 ;Read 512-byte sector
794 rcall mmcReadSect
795 pop adrl
796
797 ;Now, move the correct portion of the sector from AVR ram to Z80 ram
798 ldi zl,low(sectbuff)
799 ldi zh,high(sectbuff)
800 ldi temp,128
801 ldi temp2,0
802 sbrc adrl,0
803 add zl,temp
804 sbrc adrl,0
805 adc zh,temp2
806 sbrc adrl,1
807 inc zh
808
809 mov adrh,dsk_dmah
810 mov adrl,dsk_dmal
811
812 ldi temp2,128
813 dskDoItReadMemLoop:
814 push temp2
815 ld temp,z+
816 push zh
817 push zl
818 rcall memWriteByte
819 pop zl
820 pop zh
821 ldi temp,1
822 ldi temp2,0
823 add adrl,temp
824 adc adrh,temp2
825 pop temp2
826 dec temp2
827 brne dskDoItReadMemLoop
828 ret
829
830 dskDoItWrite:
831 ;The write routines is a bit naive: it'll read the 512-byte sector the 128byte CPM-sector
832 ;resides in into memory, will overwrite the needed 128 byte with the Z80s memory buffer
833 ;and will then write it back to disk. In theory, this would mean that every 512 bytes
834 ;written will take 4 write cycles, while theoretically the writes could be deferred so we
835 ;would only have to do one write cycle.
836
837 .if DISK_DEBUG
838 push temp
839 rcall printstr
840 .db "Disk write: track ",0
841 mov temp,dsk_trk
842 rcall printhex
843 rcall printstr
844 .db " sector ",0
845 mov temp,dsk_sec
846 rcall printhex
847 rcall printstr
848 .db " dma-addr ",0
849 mov temp,dsk_dmah
850 rcall printhex
851 mov temp,dsk_dmal
852 rcall printhex
853 rcall printstr
854 .db ".",13,0
855 pop temp
856 .endif
857
858
859 push adrl
860 push adrh
861 ;Convert from 128-byte LBA blocks to 512-byte LBA blocks
862 lsr adrh
863 ror adrl
864 lsr adrh
865 ror adrl
866 ;Read 512-byte sector
867 rcall mmcReadSect
868 pop adrh
869 pop adrl
870
871 push adrl
872 push adrh
873
874 ;Copy the data from the Z80 DMA buffer in external memory to the right place in the
875 ;sector buffer.
876 ;Now, move the correct portion of the sector from AVR ram to Z80 ram
877 ldi zl,low(sectbuff)
878 ldi zh,high(sectbuff)
879 ldi temp,128
880 ldi temp2,0
881 sbrc adrl,0
882 add zl,temp
883 sbrc adrl,0
884 adc zh,temp2
885 sbrc adrl,1
886 inc zh
887 mov adrh,dsk_dmah
888 mov adrl,dsk_dmal
889 ldi temp2,128
890 dskDoItWriteMemLoop:
891 push temp2
892
893 push zh
894 push zl
895 rcall memReadByte
896 pop zl
897 pop zh
898 st z+,temp
899 ldi temp,1
900 ldi temp2,0
901 add adrl,temp
902 adc adrh,temp2
903
904 pop temp2
905 dec temp2
906 brne dskDoItWriteMemLoop
907
908 pop adrh
909 pop adrl
910
911 ;Convert from 128-byte LBA blocks to 512-byte LBA blocks
912 lsr adrh
913 ror adrl
914 lsr adrh
915 ror adrl
916 ;Write the sector back.
917 rcall mmcWriteSect
918
919 ;All done :)
920 ret
921
922
923 ; ----------------- MMC/SD routines ------------------
924
925 mmcByteNoSend:
926 ldi temp,0xff
927 mmcByte:
928
929 .if MMC_DEBUG
930 push zl
931 push zh
932 rcall printstr
933 .db "MMC: <--",0
934 rcall printhex
935 .endif
936
937 out SPDR,temp
938 mmcWrByteW:
939 in temp,SPSR
940 sbrs temp,7
941 rjmp mmcWrByteW
942 in temp,SPDR
943
944 .if MMC_DEBUG
945 push temp
946 rcall printstr
947 .db ", -->",0
948 rcall printhex
949 rcall printstr
950 .db ".",13,0
951 pop temp
952 pop zh
953 pop zl
954 .endif
955 ret
956
957
958 ;Wait till the mmc answers with the response in temp2, or till a timeout happens.
959 mmcWaitResp:
960 ldi zl,0
961 ldi zh,0
962 mmcWaitResploop:
963 rcall mmcByteNoSend
964 cpi temp,0xff
965 brne mmcWaitResploopEnd
966 adiw zl,1
967 cpi zh,255
968 breq mmcWaitErr
969 rjmp mmcWaitResploop
970 mmcWaitResploopEnd:
971 ret
972
973
974 mmcWaitErr:
975 mov temp,temp2
976 rcall printhex
977 rcall printstr
978 .db ": Error: MMC resp timeout!",13,0
979 rjmp resetAVR
980
981 mmcInit:
982 ldi temp,0x53
983 out SPCR,temp
984
985 ;Init start: send 80 clocks with cs disabled
986 sbi PORTD,mmc_cs
987
988 ldi temp2,20
989 mmcInitLoop:
990 mov temp,temp2
991 rcall mmcByte
992 dec temp2
993 brne mmcInitLoop
994
995 cbi PORTD,mmc_cs
996 rcall mmcByteNoSend
997 rcall mmcByteNoSend
998 rcall mmcByteNoSend
999 rcall mmcByteNoSend
1000 rcall mmcByteNoSend
1001 rcall mmcByteNoSend
1002 sbi PORTD,mmc_cs
1003 rcall mmcByteNoSend
1004 rcall mmcByteNoSend
1005 rcall mmcByteNoSend
1006 rcall mmcByteNoSend
1007
1008 ;Send init command
1009 cbi PORTD,mmc_cs
1010 ldi temp,0xff ;dummy
1011 rcall mmcByte
1012 ldi temp,0xff ;dummy
1013 rcall mmcByte
1014 ldi temp,0x40 ;cmd
1015 rcall mmcByte
1016 ldi temp,0 ;pxh
1017 rcall mmcByte
1018 ldi temp,0 ;pxl
1019 rcall mmcByte
1020 ldi temp,0 ;pyh
1021 rcall mmcByte
1022 ldi temp,0 ;pyl
1023 rcall mmcByte
1024 ldi temp,0x95 ;crc
1025 rcall mmcByte
1026 ldi temp,0xff ;return byte
1027 rcall mmcByte
1028
1029 ldi temp2,0
1030 rcall mmcWaitResp
1031
1032 sbi PORTD,mmc_cs
1033 rcall mmcByteNoSend
1034
1035
1036 ;Read OCR till card is ready
1037 ldi temp2,150
1038 mmcInitOcrLoop:
1039 push temp2
1040
1041 cbi PORTD,mmc_cs
1042 ldi temp,0xff ;dummy
1043 rcall mmcByte
1044 ldi temp,0x41 ;cmd
1045 rcall mmcByte
1046 ldi temp,0 ;pxh
1047 rcall mmcByte
1048 ldi temp,0 ;pxl
1049 rcall mmcByte
1050 ldi temp,0 ;pyh
1051 rcall mmcByte
1052 ldi temp,0 ;pyl
1053 rcall mmcByte
1054 ldi temp,0x95 ;crc
1055 rcall mmcByte
1056 rcall mmcByteNoSend
1057
1058 ldi temp2,1
1059 rcall mmcWaitResp
1060 cpi temp,0
1061 breq mmcInitOcrLoopDone
1062
1063 sbi PORTD,mmc_cs
1064 rcall mmcByteNoSend
1065
1066 pop temp2
1067 dec temp2
1068 cpi temp2,0
1069 brne mmcInitOcrLoop
1070
1071 ldi temp,4
1072 rjmp mmcWaitErr
1073
1074 mmcInitOcrLoopDone:
1075 pop temp2
1076 sbi PORTD,mmc_cs
1077 rcall mmcByteNoSend
1078
1079 ldi temp,0
1080 out SPCR,temp
1081 ret
1082
1083
1084 ;Call this with adrh:adrl = sector number
1085 ;16bit lba address means a max reach of 32M.
1086 mmcReadSect:
1087 ldi temp,0x50
1088 out SPCR,temp
1089
1090 cbi PORTD,mmc_cs
1091 rcall mmcByteNoSend
1092 ldi temp,0x51 ;cmd (read sector)
1093 rcall mmcByte
1094 ldi temp,0
1095 lsl adrl
1096 rol adrh
1097 rol temp
1098 rcall mmcByte
1099 mov temp,adrh ;pxl
1100 rcall mmcByte
1101 mov temp,adrl ;pyh
1102 rcall mmcByte
1103 ldi temp,0 ;pyl
1104 rcall mmcByte
1105 ldi temp,0x95 ;crc
1106 rcall mmcByte
1107 ldi temp,0xff ;return byte
1108 rcall mmcByte
1109
1110 ;resp
1111 ldi temp2,2
1112 rcall mmcWaitResp
1113
1114 ;data token
1115 ldi temp2,3
1116 rcall mmcWaitResp
1117
1118 ;Read sector to AVR RAM
1119 ldi zl,low(sectbuff)
1120 ldi zh,high(sectbuff)
1121 mmcreadloop:
1122 rcall mmcByteNoSend
1123 st z+,temp
1124 cpi zl,low(sectbuff+512)
1125 brne mmcreadloop
1126 cpi zh,high(sectbuff+512)
1127 brne mmcreadloop
1128
1129 ;CRC
1130 rcall mmcByteNoSend
1131 rcall mmcByteNoSend
1132
1133 sbi PORTD,mmc_cs
1134 rcall mmcByteNoSend
1135
1136 ldi temp,0
1137 out SPCR,temp
1138 ret
1139
1140
1141 ;Call this with adrh:adrl = sector number
1142 ;16bit lba address means a max reach of 32M.
1143 mmcWriteSect:
1144 ldi temp,0x50
1145 out SPCR,temp
1146
1147 cbi PORTD,mmc_cs
1148 rcall mmcByteNoSend
1149
1150 ldi temp,0x58 ;cmd (write sector)
1151 rcall mmcByte
1152 ldi temp,0
1153 lsl adrl
1154 rol adrh
1155 rol temp
1156 rcall mmcByte
1157 mov temp,adrh ;pxl
1158 rcall mmcByte
1159 mov temp,adrl ;pyh
1160 rcall mmcByte
1161 ldi temp,0 ;pyl
1162 rcall mmcByte
1163 ldi temp,0x95 ;crc
1164 rcall mmcByte
1165 ldi temp,0xff ;return byte
1166 rcall mmcByte
1167
1168 ;resp
1169 ldi temp2,1
1170 rcall mmcWaitResp
1171
1172 ;Send data token
1173 ldi temp,0xfe
1174 rcall mmcByte
1175
1176 ;Write sector from AVR RAM
1177 ldi zl,low(sectbuff)
1178 ldi zh,high(sectbuff)
1179 mmcwriteloop:
1180 ld temp,z+
1181 rcall mmcByte
1182 cpi zl,low(sectbuff+512)
1183 brne mmcwriteloop
1184 cpi zh,high(sectbuff+512)
1185 brne mmcwriteloop
1186
1187 ;CRC
1188 rcall mmcByteNoSend
1189 rcall mmcByteNoSend
1190
1191 ;Status. Ignored for now.
1192 rcall mmcByteNoSend
1193
1194 ;Wait till the mmc has written everything
1195 mmcwaitwritten:
1196 rcall mmcByteNoSend
1197 cpi temp,0xff
1198 brne mmcwaitwritten
1199
1200 sbi PORTD,mmc_cs
1201 rcall mmcByteNoSend
1202
1203 ldi temp,0
1204 out SPCR,temp
1205 ret
1206
1207
1208 ;Set up wdt to time out after 1 sec.
1209 resetAVR:
1210 cli
1211 #if defined __ATmega8__
1212 ldi temp,(1<<WDCE)
1213 out WDTCSR,temp
1214 ldi temp,(1<<WDCE) | (1<<WDE) | (110<<WDP0)
1215 out WDTCSR,temp
1216 #else
1217 ldi temp,(1<<WDCE)
1218 sts WDTCSR,temp
1219 ldi temp,(1<<WDCE) | (1<<WDE) | (110<<WDP0)
1220 sts WDTCSR,temp
1221 #endif
1222 resetwait:
1223 rjmp resetwait
1224
1225
1226 ; ------------------ DRAM routines -------------
1227
1228 ; TODO:
1229
1230 #if DRAM_DQ_ORDER == 1
1231 #define CLASSIC_DRAM 0
1232 #else
1233 #define CLASSIC_DRAM 1 /* Change manualy, if you want new hw w/ old sw */
1234 #endif
1235
1236
1237 #if DRAM_DQ_ORDER == 0
1238 #if CLASSIC_DRAM == 1
1239 #error "Old harware can not work with new software!"
1240 #endif
1241 #endif
1242
1243 ; ****************************************************************************
1244
1245 #if CLASSIC_DRAM
1246
1247 ; ********************** DRAM routines from Sprite_tm ************************
1248
1249 ;Sends the address in zh:zl to the ram
1250 dram_setaddr:
1251 push temp
1252 in temp,portd
1253 andi temp,0x17
1254 out portd,temp
1255 in temp,portb
1256 andi temp,0xE0
1257 out portb,temp
1258 sbrc zl,0
1259 sbi portb,ram_a0
1260 sbrc zl,1
1261 sbi portb,ram_a1
1262 sbrc zl,2
1263 sbi portb,ram_a2
1264 sbrc zl,3
1265 sbi portb,ram_a3
1266 sbrc zl,4
1267 sbi portb,ram_a4
1268 sbrc zl,5
1269 sbi portd,ram_a5
1270 sbrc zl,6
1271 sbi portd,ram_a6
1272 sbrc zl,7
1273 sbi portd,ram_a7
1274 sbrc zh,0
1275 sbi portd,ram_a8
1276 pop temp
1277 ret
1278
1279 dram_getnibble:
1280 andi temp,0xf0
1281 sbic pinc,ram_d0
1282 ori temp,0x1
1283 sbic pinc,ram_d1
1284 ori temp,0x2
1285 sbic pinc,ram_d2
1286 ori temp,0x4
1287 sbic pinc,ram_d3
1288 ori temp,0x8
1289 ret
1290
1291 dram_sendnibble:
1292 push temp2
1293 in temp2,portc
1294 andi temp2,~RAM_DQ_MASK
1295
1296 sbrc temp,0
1297 ori temp2,(1<<ram_d0)
1298 sbrc temp,1
1299 ori temp2,(1<<ram_d1)
1300 sbrc temp,2
1301 ori temp2,(1<<ram_d2)
1302 sbrc temp,3
1303 ori temp2,(1<<ram_d3)
1304
1305 out portc,temp2
1306 pop temp2
1307 ret
1308
1309
1310 ;Loads the byte on address adrh:adrl into temp.
1311 dram_read:
1312 cli
1313 mov zl,adrh
1314 ldi zh,0
1315 mov temp2,adrl
1316 lsl temp2
1317 rol zl
1318 rol zh
1319 ;z=addr[15-7]
1320 rcall dram_setaddr
1321 cbi portb,ram_ras
1322
1323 ldi zh,0
1324 mov zl,adrl
1325 andi zl,0x7F
1326 rcall dram_setaddr
1327 nop
1328 cbi portc,ram_cas
1329 nop
1330 nop
1331 cbi portd,ram_oe
1332 nop
1333 rcall dram_getnibble
1334 sbi portd,ram_oe
1335 swap temp
1336 sbi portc,ram_cas
1337
1338 ldi zh,0
1339 mov zl,adrl
1340 ori zl,0x80
1341 rcall dram_setaddr
1342 nop
1343 cbi portc,ram_cas
1344 nop
1345 cbi portd,ram_oe
1346 nop
1347 nop
1348 rcall dram_getnibble
1349
1350 sbi portd,ram_oe
1351 sbi portc,ram_cas
1352 sbi portb,ram_ras
1353 sei
1354 ret
1355
1356 ;Writes the byte in temp to adrh:adrl
1357 dram_write:
1358 cli
1359
1360 in temp2,ddrc
1361 ori temp2,RAM_DQ_MASK
1362 out ddrc,temp2
1363
1364 rcall dram_sendnibble
1365
1366 mov zl,adrh
1367 ldi zh,0
1368 mov temp2,adrl
1369 lsl temp2
1370 rol zl
1371 rol zh
1372 ;z=addr[15-7]
1373 rcall dram_setaddr
1374 nop
1375 nop
1376 cbi portb,ram_ras
1377
1378 ldi zh,0
1379 mov zl,adrl
1380 ori zl,0x80
1381 rcall dram_setaddr
1382 nop
1383 nop
1384 cbi portc,ram_cas
1385 nop
1386 nop
1387 cbi portc,ram_w
1388 nop
1389 nop
1390 nop
1391 sbi portc,ram_w
1392 sbi portc,ram_cas
1393
1394
1395 ldi zh,0
1396 mov zl,adrl
1397 andi zl,0x7F
1398 rcall dram_setaddr
1399 swap temp
1400 rcall dram_sendnibble
1401 cbi portc,ram_cas
1402 nop
1403 nop
1404 cbi portc,ram_w
1405 nop
1406 nop
1407 sbi portc,ram_w
1408 nop
1409 nop
1410 sbi portc,ram_cas
1411 sbi portb,ram_ras
1412
1413 in temp,ddrc
1414 andi temp,~RAM_DQ_MASK
1415 out ddrc,temp
1416 in temp,portc
1417 andi temp,~RAM_DQ_MASK
1418 out portc,temp
1419 sei
1420 ret
1421 #endif /* CLASSIC_DRAM == 1 */
1422
1423 ; ****************************************************************************
1424
1425 #if ! CLASSIC_DRAM
1426
1427 ; ***************************** New DRAM routines ****************************
1428
1429 ; Defines how the dram nibbles are arganized.
1430 ; RAMORG == 0 : A7 == 0: low nibble, A7 == 1: high nibble (Original Sprite_tm design)
1431 ; RAMORG == 1 : A8 == 0: low nibble, A8 == 1: high nibble (faster)
1432 ;
1433 #define RAMORG 1
1434
1435 #if RAMORG == 0
1436 ;Sends the address in zh:zl to the ram
1437 dram_setaddr:
1438 push temp
1439 in temp,PORTB
1440 andi temp,~RAM_AL_MASK
1441 sbrc zl,0
1442 ori temp,(1<<ram_a0)
1443 sbrc zl,1
1444 ori temp,(1<<ram_a1)
1445 sbrc zl,2
1446 ori temp,(1<<ram_a2)
1447 sbrc zl,3
1448 ori temp,(1<<ram_a3)
1449 sbrc zl,4
1450 ori temp,(1<<ram_a4)
1451 out PORTB,temp
1452
1453 in temp,PORTD
1454 andi temp,~RAM_AH_MASK
1455 sbrc zl,5
1456 ori temp,(1<<ram_a5)
1457 sbrc zl,6
1458 ori temp,(1<<ram_a6)
1459 sbrc zl,7
1460 ori temp,(1<<ram_a7)
1461 sbrc zh,0
1462 ori temp,(1<<ram_a8)
1463 out PORTD,temp
1464 pop temp
1465 #else /* RAMORG == 1 */
1466 .macro DRAM_SETADDR
1467 push temp
1468 in temp,PORTB
1469 andi temp,~RAM_AL_MASK
1470 sbrc @0,0
1471 ori temp,(1<<ram_a0)
1472 sbrc @0,1
1473 ori temp,(1<<ram_a1)
1474 sbrc @0,2
1475 ori temp,(1<<ram_a2)
1476 sbrc @0,3
1477 ori temp,(1<<ram_a3)
1478 sbrc @0,4
1479 ori temp,(1<<ram_a4)
1480 out PORTB,temp
1481
1482 in temp,PORTD
1483 andi temp,~RAM_AH_MASK
1484 sbrc @0,5
1485 ori temp,(1<<ram_a5)
1486 sbrc @0,6
1487 ori temp,(1<<ram_a6)
1488 sbrc @0,7
1489 ori temp,(1<<ram_a7)
1490 out PORTD,temp
1491 pop temp
1492 .endm
1493 ret
1494 #endif /* RAMORG */
1495
1496 .macro DRAM_SENDNIBBLE
1497 in temp2,PORTC
1498 andi temp2,~RAM_DQ_MASK
1499 andi temp,RAM_DQ_MASK
1500 or temp2,temp
1501 out PORTC,temp2
1502 .endm
1503
1504
1505 ;Loads the byte on address adrh:adrl into temp.
1506 ;must not alter adrh:adrl
1507
1508 dram_read:
1509 cli
1510 #if RAMORG == 0
1511 mov zl,adrh
1512 ldi zh,0
1513 mov temp2,adrl
1514 lsl temp2
1515 rol zl
1516 rol zh
1517 ;z=addr[15-7]
1518 rcall dram_setaddr
1519 cbi PORTB,ram_ras
1520
1521 ldi zh,0
1522 mov zl,adrl
1523 andi zl,0x7F
1524 rcall dram_setaddr
1525 cbi PORTC,ram_cas
1526 cbi PORTD,ram_oe
1527 ldi zh,0
1528 in temp,PINC
1529 andi temp,0x0f
1530 swap temp
1531 sbi PORTC,ram_cas
1532
1533 mov zl,adrl
1534 ori zl,0x80
1535 rcall dram_setaddr
1536 cbi PORTC,ram_cas
1537 nop
1538 in temp2,PINC
1539 andi temp2,0x0f
1540 or temp,temp2
1541
1542 sbi PORTD,ram_oe
1543 sbi PORTC,ram_cas
1544 sbi PORTB,ram_ras
1545 #else
1546 cbi PORTD,ram_a8
1547 DRAM_SETADDR adrh
1548 cbi PORTB,ram_ras
1549
1550 DRAM_SETADDR adrl
1551 cbi PORTC,ram_cas
1552 cbi PORTD,ram_oe
1553 nop ;1 |0 |0
1554 nop
1555 in temp,PINC
1556 andi temp,0x0f
1557 swap temp
1558 nop ;1 |0 |0
1559 sbi PORTC,ram_cas
1560
1561 sbi PORTD,ram_a8
1562 ; nop ;1 |0 |0
1563 cbi PORTC,ram_cas
1564 nop
1565 nop ;1 |0 |0
1566 in temp2,PINC
1567 andi temp2,0x0f
1568 or temp,temp2
1569 swap temp
1570
1571 sbi PORTD,ram_oe
1572 sbi PORTC,ram_cas
1573 sbi PORTB,ram_ras
1574 #endif
1575 sei
1576 ret
1577
1578
1579 ;Writes the byte in temp to adrh:adrl
1580 ;must not alter adrh:adrl
1581
1582 dram_write:
1583 cli
1584 #if RAMORG == 0
1585 in temp2,DDRC ;DRAM data ports as outputs
1586 ori temp2,RAM_DQ_MASK
1587 out DDRC,temp2
1588
1589 push temp
1590 DRAM_SENDNIBBLE
1591 pop temp
1592
1593 mov zl,adrh
1594 ldi zh,0
1595 mov temp2,adrl
1596 lsl temp2
1597 rol zl
1598 rol zh
1599 ;z=addr[15-7]
1600 rcall dram_setaddr
1601 cbi PORTB,ram_ras
1602
1603 ldi zh,0
1604 mov zl,adrl
1605 ori zl,0x80
1606 cbi PORTC,ram_w ;early write
1607 rcall dram_setaddr
1608 cbi PORTC,ram_cas
1609 sbi PORTC,ram_cas
1610
1611 ldi zh,0
1612 mov zl,adrl
1613 andi zl,0x7F
1614 rcall dram_setaddr
1615 swap temp
1616
1617 DRAM_SENDNIBBLE
1618
1619 cbi PORTC,ram_cas
1620 sbi PORTC,ram_cas
1621 sbi PORTC,ram_w
1622 sbi PORTB,ram_ras
1623
1624 in temp,DDRC
1625 andi temp,~RAM_DQ_MASK
1626 out DDRC,temp
1627 in temp,PORTC
1628 andi temp,~RAM_DQ_MASK
1629 out PORTC,temp
1630 #else /* RAMORG == 1 */
1631 in temp2,DDRC ;DRAM data ports as outputs
1632 ori temp2,RAM_DQ_MASK
1633 out DDRC,temp2
1634
1635 push temp
1636 DRAM_SENDNIBBLE
1637 pop temp
1638
1639 cbi PORTD,ram_a8
1640 DRAM_SETADDR adrh
1641 cbi PORTB,ram_ras
1642
1643 cbi PORTC,ram_w ;early write
1644 DRAM_SETADDR adrl
1645 cbi PORTC,ram_cas
1646 sbi PORTC,ram_cas
1647
1648 sbi PORTD,ram_a8
1649 swap temp
1650
1651 DRAM_SENDNIBBLE
1652
1653 nop ;1 |0 |0
1654 cbi PORTC,ram_cas
1655 nop
1656 sbi PORTC,ram_cas
1657 sbi PORTC,ram_w
1658 sbi PORTB,ram_ras
1659
1660 in temp,DDRC
1661 andi temp,~RAM_DQ_MASK
1662 out DDRC,temp
1663 in temp,PORTC
1664 andi temp,~RAM_DQ_MASK
1665 out PORTC,temp
1666 #endif /* RAMORG */
1667 sei
1668 ret
1669
1670 #endif /* CLASSIC_DRAM == 0 */
1671
1672 ; ****************************************************************************
1673
1674 ; refresh interupt; exec 2 cbr cycles
1675 refrint:
1676 ;4 CAS RAS
1677 cbi P_CAS,ram_cas ;2 1| 1|
1678 ; 1| 1|
1679 cbi P_RAS,ram_ras ;2 |0 1|
1680 ; |0 1|
1681 nop ;1 |0 |0
1682 ; nop ;1 |0 |0
1683 sbi P_RAS,ram_ras ;2 |0 |0
1684 ; |0 |0
1685 ; nop ;1 |0 |0
1686 cbi P_RAS,ram_ras ;2 |0 1|
1687 ; |0 1|
1688 sbi P_CAS,ram_cas ;2 |0 |0
1689 ; |0 |0
1690 sbi P_RAS,ram_ras ;2 1| |0
1691 ; 1| 1|
1692 reti ;4 --> 21 cycles
1693
1694 ; ****************************************************************************
1695
1696 ; ------------- system timer 10ms ---------------
1697 .dseg
1698
1699 delay_timer:
1700 .byte 1
1701 timer_base:
1702 timer_ms:
1703 .byte 2
1704 timer_s:
1705 .byte 4
1706 ; don't change order here, clock put/get depends on it.
1707 cntms_out: ; register for ms
1708 .byte 2
1709 utime_io: ; register for uptime.
1710 .byte 4
1711 cnt_1ms:
1712 .byte 2
1713 uptime:
1714 .byte 4
1715 timer_top:
1716 .equ timer_size = timer_top - timer_base
1717
1718 .equ clkofs = cnt_1ms-cntms_out
1719 .equ timerofs = cnt_1ms-timer_ms
1720
1721 .cseg
1722 sysclockint:
1723 push zl
1724 in zl,SREG
1725 push zl
1726 push zh
1727
1728 lds zl,delay_timer
1729 subi zl,1
1730 brcs syscl1
1731 sts delay_timer,zl
1732 syscl1:
1733 lds zl,cnt_1ms
1734 lds zh,cnt_1ms+1
1735 adiw z,1
1736
1737 sts cnt_1ms,zl
1738 sts cnt_1ms+1,zh
1739 cpi zl,low(1000)
1740 ldi zl,high(1000) ;doesn't change flags
1741 cpc zh,zl
1742 brlo syscl_end
1743
1744 ldi zl,0
1745 sts cnt_1ms,zl
1746 sts cnt_1ms+1,zl
1747
1748 lds zl,uptime+0
1749 inc zl
1750 sts uptime+0,zl
1751 brne syscl_end
1752 lds zl,uptime+1
1753 inc zl
1754 sts uptime+1,zl
1755 brne syscl_end
1756 lds zl,uptime+2
1757 inc zl
1758 sts uptime+2,zl
1759 brne syscl_end
1760 lds zl,uptime+3
1761 inc zl
1762 sts uptime+3,zl
1763
1764 syscl_end:
1765 pop zh
1766 pop zl
1767 out SREG,zl
1768 pop zl
1769 reti
1770
1771 ; wait for temp ms
1772
1773 delay_ms:
1774 sts delay_timer,temp
1775 dly_loop:
1776 lds temp,delay_timer
1777 cpi temp,0
1778 brne dly_loop
1779 ret
1780
1781 ;
1782
1783 clockget:
1784 ldi temp,0xFF
1785 subi temp2,TIMER_MSECS
1786 brcs clkget_end ;Port number in range?
1787 ldi zl,low(cntms_out)
1788 ldi zh,high(cntms_out)
1789 breq clkget_copy ;lowest byte requestet, latch clock
1790 cpi temp2,6
1791 brsh clkget_end ;Port number to high?
1792
1793 add zl,temp2
1794 brcc PC+2
1795 inc zh
1796 ld temp,z
1797 clkget_end:
1798 ret
1799
1800
1801
1802 clkget_copy:
1803 ldi temp2,6
1804 cli
1805 clkget_l:
1806 ldd temp,z+clkofs
1807 st z+,temp
1808 dec temp2
1809 brne clkget_l
1810 sei
1811 lds temp,cntms_out
1812 ;req. byte in temp
1813 ret
1814
1815 clockput:
1816 subi temp2,TIMERPORT
1817 brcs clkput_end ;Port number in range?
1818 brne clkput_1
1819
1820 ; clock control
1821
1822 cpi temp,starttimercmd
1823 breq timer_start
1824 cpi temp,quitTimerCmd
1825 breq timer_quit
1826 cpi temp,printTimerCmd
1827 breq timer_print
1828 cpi temp,uptimeCmd
1829 brne cp_ex
1830 rjmp uptime_print
1831 cp_ex:
1832 ret
1833
1834 timer_quit:
1835 rcall timer_print
1836 rjmp timer_start
1837
1838 clkput_1:
1839 dec temp2
1840 ldi zl,low(cntms_out)
1841 ldi zh,high(cntms_out)
1842 breq clkput_copy ;lowest byte requestet, latch clock
1843 cpi temp2,6
1844 brsh clkput_end ;Port number to high?
1845
1846 add zl,temp2
1847 brcc PC+2
1848 inc zh
1849 st z,temp
1850 clkput_end:
1851 ret
1852
1853 clkput_copy:
1854 st z,temp
1855 adiw z,5
1856 ldi temp2,6
1857 cli
1858 clkput_l:
1859 ldd temp,z+clkofs
1860 st z+,temp
1861 dec temp2
1862 brne clkput_l
1863 sei
1864 ret
1865
1866 ; start/reset timer
1867 ;
1868 timer_start:
1869 ldi zl,low(timer_ms)
1870 ldi zh,high(timer_ms)
1871 ldi temp2,6
1872 cli
1873 ts_loop:
1874 ldd temp,z+timerofs
1875 st z+,temp
1876 dec temp2
1877 brne ts_loop
1878 sei
1879 ret
1880
1881
1882 ; print timer
1883 ;
1884
1885 timer_print:
1886 push adrh
1887 push adrl
1888 push oph
1889 push opl
1890 ldi zl,low(timer_ms)
1891 ldi zh,high(timer_ms)
1892
1893 ; put ms on stack (16 bit)
1894
1895 cli
1896 ldd adrl,z+timerofs
1897 ld temp2,z+
1898 sub adrl,temp2
1899 ldd adrh,z+timerofs
1900 ld temp2,z+
1901 sbc adrh,temp2
1902 brsh tp_s
1903
1904 subi adrl,low(-1000)
1905 sbci adrh,high(-1000)
1906 sec
1907 tp_s:
1908 push adrh
1909 push adrl
1910
1911 ;
1912
1913 ldd temp,z+timerofs
1914 ld adrl,z+
1915 sbc temp,adrl
1916
1917 ldd temp2,z+timerofs
1918 ld adrh,z+
1919 sbc temp2,adrh
1920
1921 ldd opl,z+timerofs
1922 ld adrl,z+
1923 sbc opl,adrl
1924
1925 sei
1926 ldd oph,z+timerofs
1927 ld adrh,z+
1928 sbc oph,adrh
1929
1930 rcall printstr
1931 .db 13,"Timer running. Elapsed: ",0
1932 rcall print_ultoa
1933
1934 rcall printstr
1935 .db ",",0
1936 ldi opl,0
1937 ldi oph,0
1938 pop temp
1939 pop temp2
1940 rcall print_ultoa
1941 rcall printstr
1942 .db "s.",0
1943
1944 pop opl
1945 pop oph
1946 pop adrl
1947 pop adrh
1948 ret
1949
1950 uptime_print:
1951
1952 push oph
1953 push opl
1954 ldi zl,low(cnt_1ms)
1955 ldi zh,high(cnt_1ms)
1956
1957 cli
1958 ld temp,z+
1959 push temp
1960 ld temp,z+
1961 push temp
1962
1963 ld temp,z+
1964 ld temp2,z+
1965 ld opl,z+
1966 sei
1967 ld oph,z+
1968
1969 rcall printstr
1970 .db 13,"Uptime: ",0
1971
1972 rcall print_ultoa
1973 rcall printstr
1974 .db ",",0
1975
1976 ldi opl,0
1977 ldi oph,0
1978 pop temp2
1979 pop temp
1980 rcall print_ultoa
1981 rcall printstr
1982 .db "s.",0,0
1983
1984 pop opl
1985 pop oph
1986 ret
1987
1988
1989
1990 ; --------------- Debugging stuff ---------------
1991
1992 ;Print a unsigned lonng value to the uart
1993 ; oph:opl:temp2:temp = value
1994
1995 print_ultoa:
1996 push adrh
1997 push adrl
1998 push insdech
1999
2000 clr adrl ;adrl = stack level
2001
2002 ultoa1: ldi insdech, 32 ;adrh = oph:temp % 10
2003 clr adrh ;oph:temp /= 10
2004 ultoa2: lsl temp
2005 rol temp2
2006 rol opl
2007 rol oph
2008 rol adrh
2009 cpi adrh,10
2010 brcs ultoa3
2011 subi adrh,10
2012 inc temp
2013 ultoa3: dec insdech
2014 brne ultoa2
2015 cpi adrh, 10 ;adrh is a numeral digit '0'-'9'
2016 subi adrh, -'0'
2017 push adrh ;Stack it
2018 inc adrl
2019 ldi insdech,0
2020 cp temp,insdech ;Repeat until oph:temp gets zero
2021 cpc temp2,insdech
2022 cpc opl,insdech
2023 cpc oph,insdech
2024 brne ultoa1
2025
2026 ldi temp, '0'
2027 ultoa5: cpi adrl,3 ; at least 3 digits (ms)
2028 brge ultoa6
2029 push temp
2030 inc adrl
2031 rjmp ultoa5
2032
2033 ultoa6: pop temp ;Flush stacked digits
2034 rcall uartputc
2035 dec adrl
2036 brne ultoa6
2037
2038 pop insdech
2039 pop adrl
2040 pop adrh
2041 ret
2042
2043
2044 ;Prints the lower nibble of temp in hex to the uart
2045 printhexn:
2046 push temp
2047 andi temp,0xf
2048 cpi temp,0xA
2049 brlo printhexn_isno
2050 subi temp,-('A'-10)
2051 rcall uartputc
2052 pop temp
2053 ret
2054 printhexn_isno:
2055 subi temp,-'0'
2056 rcall uartputc
2057 pop temp
2058 ret
2059
2060 ;Prints temp in hex to the uart
2061 printhex:
2062 swap temp
2063 rcall printhexn
2064 swap temp
2065 rcall printhexn
2066 ret
2067
2068 ;Prints the zero-terminated string following the call statement. WARNING: Destroys temp.
2069 printstr:
2070 pop zh
2071 pop zl
2072 push temp
2073
2074 lsl zl
2075 rol zh
2076
2077 printstr_loop:
2078 lpm temp,z+
2079 cpi temp,0
2080 breq printstr_end
2081 rcall uartputc
2082 cpi temp,13
2083 brne printstr_loop
2084 ldi temp,10
2085 rcall uartputc
2086 rjmp printstr_loop
2087
2088 printstr_end:
2089 adiw zl,1
2090 lsr zh
2091 ror zl
2092
2093 pop temp
2094 push zl
2095 push zh
2096 ret
2097
2098
2099 ; --------------- AVR HW <-> Z80 periph stuff ------------------
2100
2101 .equ memReadByte = dram_read
2102 .equ memWriteByte = dram_write
2103
2104 ; --------------------------------------------------------------
2105
2106 .dseg
2107
2108 #define RXBUFMASK RXBUFSIZE-1
2109
2110 rxcount:
2111 .byte 1
2112 rxidx_w:
2113 .byte 1
2114 rxidx_r:
2115 .byte 1
2116 rxfifo:
2117 .byte RXBUFSIZE
2118 .byte 0
2119
2120 .cseg
2121
2122 ; Save received character in a circular buffer. Do nothing if buffer overflows.
2123
2124 rxint:
2125 push temp
2126 in temp,sreg
2127 push temp
2128 push zh
2129 push zl
2130 #ifdef __ATmega8__
2131 in temp,UDR
2132 #else
2133 lds temp,UDR0
2134 #endif
2135 lds zh,rxcount ;if rxcount < RXBUFSIZE
2136 cpi zh,RXBUFSIZE ; (room for at least 1 char?)
2137 brsh rxi_ov ;
2138 inc zh ;
2139 sts rxcount,zh ; rxcount++
2140
2141 ldi zl,low(rxfifo) ;
2142 lds zh,rxidx_w ;
2143 add zl,zh ;
2144 inc zh ;
2145 andi zh,RXBUFMASK ;
2146 sts rxidx_w,zh ; rxidx_w = ++rxidx_w % RXBUFSIZE
2147 ldi zh,high(rxfifo) ;
2148 brcc PC+2 ;
2149 inc zh ;
2150 st z,temp ; rxfifo[rxidx_w] = char
2151 rxi_ov: ;endif
2152 pop zl
2153 pop zh
2154 pop temp
2155 out sreg,temp
2156 pop temp
2157 reti
2158
2159
2160 ;Fetches a char from the buffer to temp. If none available, waits till one is.
2161
2162 uartgetc:
2163 lds temp,rxcount ; Number of characters in buffer
2164 tst temp
2165 breq uartgetc
2166
2167 push zh
2168 push zl
2169 ldi zl,low(rxfifo)
2170 ldi zh,high(rxfifo)
2171 lds temp,rxidx_r
2172 add zl,temp
2173 brcc PC+2
2174 inc zh
2175 inc temp
2176 andi temp,RXBUFMASK
2177 sts rxidx_r,temp
2178 cli
2179 lds temp,rxcount
2180 dec temp
2181 sts rxcount,temp
2182 sei
2183 ld temp,z ;don't forget to get the char
2184 pop zl
2185 pop zh
2186 ret
2187
2188
2189
2190 ;Sends a char from temp to the uart.
2191 uartputc:
2192 #if defined __ATmega8__
2193 uartputc_l:
2194 sbis UCSRA,UDRE
2195 rjmp uartputc_l
2196 out UDR,temp
2197 #else
2198 push temp
2199 uartputc_l:
2200 lds temp,UCSR0A
2201 sbrs temp,UDRE0
2202 rjmp uartputc_l
2203 pop temp
2204 sts UDR0,temp
2205 #endif
2206 ret
2207
2208 ; ------------ Fetch phase stuff -----------------
2209
2210 .equ FETCH_NOP = (0<<0)
2211 .equ FETCH_A = (1<<0)
2212 .equ FETCH_B = (2<<0)
2213 .equ FETCH_C = (3<<0)
2214 .equ FETCH_D = (4<<0)
2215 .equ FETCH_E = (5<<0)
2216 .equ FETCH_H = (6<<0)
2217 .equ FETCH_L = (7<<0)
2218 .equ FETCH_AF = (8<<0)
2219 .equ FETCH_BC = (9<<0)
2220 .equ FETCH_DE = (10<<0)
2221 .equ FETCH_HL = (11<<0)
2222 .equ FETCH_SP = (12<<0)
2223 .equ FETCH_MBC = (13<<0)
2224 .equ FETCH_MDE = (14<<0)
2225 .equ FETCH_MHL = (15<<0)
2226 .equ FETCH_MSP = (16<<0)
2227 .equ FETCH_DIR8 = (17<<0)
2228 .equ FETCH_DIR16= (18<<0)
2229 .equ FETCH_RST = (19<<0)
2230
2231
2232 ;Jump table for fetch routines. Make sure to keep this in sync with the .equs!
2233 fetchjumps:
2234 .dw do_fetch_nop
2235 .dw do_fetch_a
2236 .dw do_fetch_b
2237 .dw do_fetch_c
2238 .dw do_fetch_d
2239 .dw do_fetch_e
2240 .dw do_fetch_h
2241 .dw do_fetch_l
2242 .dw do_fetch_af
2243 .dw do_fetch_bc
2244 .dw do_fetch_de
2245 .dw do_fetch_hl
2246 .dw do_fetch_sp
2247 .dw do_fetch_mbc
2248 .dw do_fetch_mde
2249 .dw do_fetch_mhl
2250 .dw do_fetch_msp
2251 .dw do_fetch_dir8
2252 .dw do_fetch_dir16
2253 .dw do_fetch_rst
2254
2255 do_fetch_nop:
2256 ret
2257
2258 do_fetch_a:
2259 mov opl,z_a
2260 ret
2261
2262 do_fetch_b:
2263 mov opl,z_b
2264 ret
2265
2266 do_fetch_c:
2267 mov opl,z_c
2268 ret
2269
2270 do_fetch_d:
2271 mov opl,z_d
2272 ret
2273
2274 do_fetch_e:
2275 mov opl,z_e
2276 ret
2277
2278 do_fetch_h:
2279 mov opl,z_h
2280 ret
2281
2282 do_fetch_l:
2283 mov opl,z_l
2284 ret
2285
2286 do_fetch_af:
2287 mov opl,z_flags
2288 mov oph,z_a
2289 ret
2290
2291 do_fetch_bc:
2292 mov opl,z_c
2293 mov oph,z_b
2294 ret
2295
2296 do_fetch_de:
2297 mov opl,z_e
2298 mov oph,z_d
2299 ret
2300
2301 do_fetch_hl:
2302 mov opl,z_l
2303 mov oph,z_h
2304 ret
2305
2306 do_fetch_sp:
2307 mov opl,z_spl
2308 mov oph,z_sph
2309 ret
2310
2311 do_fetch_mbc:
2312 mov adrh,z_b
2313 mov adrl,z_c
2314 rcall memReadByte
2315 mov opl,temp
2316 ret
2317
2318 do_fetch_mde:
2319 mov adrh,z_d
2320 mov adrl,z_e
2321 rcall memReadByte
2322 mov opl,temp
2323 ret
2324
2325 do_fetch_mhl:
2326 mov adrh,z_h
2327 mov adrl,z_l
2328 rcall memReadByte
2329 mov opl,temp
2330 ret
2331
2332 do_fetch_msp:
2333 mov adrh,z_sph
2334 mov adrl,z_spl
2335 rcall memReadByte
2336 mov opl,temp
2337
2338 ldi temp,1
2339 ldi temp2,0
2340 add adrl,temp
2341 adc adrh,temp2
2342 rcall memReadByte
2343 mov oph,temp
2344 ret
2345
2346 do_fetch_dir8:
2347 mov adrl,z_pcl
2348 mov adrh,z_pch
2349 rcall memReadByte
2350 adiw z_pcl,1
2351 mov opl,temp
2352 ret
2353
2354 do_fetch_dir16:
2355 mov adrl,z_pcl
2356 mov adrh,z_pch
2357 rcall memReadByte
2358 mov opl,temp
2359 adiw z_pcl,1
2360 mov adrl,z_pcl
2361 mov adrh,z_pch
2362 rcall memReadByte
2363 adiw z_pcl,1
2364 mov oph,temp
2365 ret
2366
2367 do_fetch_rst:
2368 mov adrl,z_pcl
2369 mov adrh,z_pch
2370 subi adrl,1
2371 sbci adrh,0
2372 rcall memReadByte
2373 andi temp,0x38
2374 ldi oph,0
2375 mov opl,temp
2376 ret
2377
2378
2379
2380 ; ------------ Store phase stuff -----------------
2381
2382 .equ STORE_NOP = (0<<5)
2383 .equ STORE_A = (1<<5)
2384 .equ STORE_B = (2<<5)
2385 .equ STORE_C = (3<<5)
2386 .equ STORE_D = (4<<5)
2387 .equ STORE_E = (5<<5)
2388 .equ STORE_H = (6<<5)
2389 .equ STORE_L = (7<<5)
2390 .equ STORE_AF = (8<<5)
2391 .equ STORE_BC = (9<<5)
2392 .equ STORE_DE = (10<<5)
2393 .equ STORE_HL = (11<<5)
2394 .equ STORE_SP = (12<<5)
2395 .equ STORE_PC = (13<<5)
2396 .equ STORE_MBC = (14<<5)
2397 .equ STORE_MDE = (15<<5)
2398 .equ STORE_MHL = (16<<5)
2399 .equ STORE_MSP = (17<<5)
2400 .equ STORE_RET = (18<<5)
2401 .equ STORE_CALL = (19<<5)
2402 .equ STORE_AM = (20<<5)
2403
2404 ;Jump table for store routines. Make sure to keep this in sync with the .equs!
2405 storejumps:
2406 .dw do_store_nop
2407 .dw do_store_a
2408 .dw do_store_b
2409 .dw do_store_c
2410 .dw do_store_d
2411 .dw do_store_e
2412 .dw do_store_h
2413 .dw do_store_l
2414 .dw do_store_af
2415 .dw do_store_bc
2416 .dw do_store_de
2417 .dw do_store_hl
2418 .dw do_store_sp
2419 .dw do_store_pc
2420 .dw do_store_mbc
2421 .dw do_store_mde
2422 .dw do_store_mhl
2423 .dw do_store_msp
2424 .dw do_store_ret
2425 .dw do_store_call
2426 .dw do_store_am
2427
2428
2429 do_store_nop:
2430 ret
2431
2432 do_store_a:
2433 mov z_a,opl
2434 ret
2435
2436 do_store_b:
2437 mov z_b,opl
2438 ret
2439
2440 do_store_c:
2441 mov z_c,opl
2442 ret
2443
2444 do_store_d:
2445 mov z_d,opl
2446 ret
2447
2448 do_store_e:
2449 mov z_e,opl
2450 ret
2451
2452 do_store_h:
2453 mov z_h,opl
2454 ret
2455
2456 do_store_l:
2457 mov z_l,opl
2458 ret
2459
2460 do_store_af:
2461 mov z_a,oph
2462 mov z_flags,opl
2463 ret
2464
2465 do_store_bc:
2466 mov z_b,oph
2467 mov z_c,opl
2468 ret
2469
2470 do_store_de:
2471 mov z_d,oph
2472 mov z_e,opl
2473 ret
2474
2475 do_store_hl:
2476 mov z_h,oph
2477 mov z_l,opl
2478 ret
2479
2480 do_store_mbc:
2481 mov adrh,z_b
2482 mov adrl,z_c
2483 mov temp,opl
2484 rcall memWriteByte
2485 ret
2486
2487 do_store_mde:
2488 mov adrh,z_d
2489 mov adrl,z_e
2490 mov temp,opl
2491 rcall memWriteByte
2492 ret
2493
2494 do_store_mhl:
2495 mov adrh,z_h
2496 mov adrl,z_l
2497 mov temp,opl
2498 rcall memWriteByte
2499 ret
2500
2501 do_store_msp:
2502 mov adrh,z_sph
2503 mov adrl,z_spl
2504 mov temp,opl
2505 rcall memWriteByte
2506
2507 ldi temp,1
2508 ldi temp2,0
2509 add adrl,temp
2510 adc adrh,temp2
2511 mov temp,oph
2512 rcall memWriteByte
2513
2514 ret
2515
2516 do_store_sp:
2517 mov z_sph,oph
2518 mov z_spl,opl
2519 ret
2520
2521 do_store_pc:
2522 mov z_pch,oph
2523 mov z_pcl,opl
2524 ret
2525
2526 do_store_ret:
2527 rcall do_op_pop16
2528 mov z_pcl,opl
2529 mov z_pch,oph
2530 ret
2531
2532 do_store_call:
2533 push opl
2534 push oph
2535 mov opl,z_pcl
2536 mov oph,z_pch
2537 rcall do_op_push16
2538 pop z_pch
2539 pop z_pcl
2540 ret
2541
2542 do_store_am:
2543 mov adrh,oph
2544 mov adrl,opl
2545 mov temp,z_a
2546 rcall memWriteByte
2547 ret
2548
2549
2550 ; ------------ Operation phase stuff -----------------
2551
2552
2553 .equ OP_NOP = (0<<10)
2554 .equ OP_INC = (1<<10)
2555 .equ OP_DEC = (2<<10)
2556 .equ OP_INC16 = (3<<10)
2557 .equ OP_DEC16 = (4<<10)
2558 .equ OP_RLC = (5<<10)
2559 .equ OP_RRC = (6<<10)
2560 .equ OP_RR = (7<<10)
2561 .equ OP_RL = (8<<10)
2562 .equ OP_ADDA = (9<<10)
2563 .equ OP_ADCA = (10<<10)
2564 .equ OP_SUBFA = (11<<10)
2565 .equ OP_SBCFA = (12<<10)
2566 .equ OP_ANDA = (13<<10)
2567 .equ OP_ORA = (14<<10)
2568 .equ OP_XORA = (15<<10)
2569 .equ OP_ADDHL = (16<<10)
2570 .equ OP_STHL = (17<<10) ;store HL in fetched address
2571 .equ OP_RMEM16 = (18<<10) ;read mem at fetched address
2572 .equ OP_RMEM8 = (19<<10) ;read mem at fetched address
2573 .equ OP_DA = (20<<10)
2574 .equ OP_SCF = (21<<10)
2575 .equ OP_CPL = (22<<10)
2576 .equ OP_CCF = (23<<10)
2577 .equ OP_POP16 = (24<<10)
2578 .equ OP_PUSH16 = (25<<10)
2579 .equ OP_IFNZ = (26<<10)
2580 .equ OP_IFZ = (27<<10)
2581 .equ OP_IFNC = (28<<10)
2582 .equ OP_IFC = (29<<10)
2583 .equ OP_IFPO = (30<<10)
2584 .equ OP_IFPE = (31<<10)
2585 .equ OP_IFP = (32<<10)
2586 .equ OP_IFM = (33<<10)
2587 .equ OP_OUTA = (34<<10)
2588 .equ OP_IN = (35<<10)
2589 .equ OP_EXHL = (36<<10)
2590 .equ OP_DI = (37<<10)
2591 .equ OP_EI = (38<<10)
2592 .equ OP_INV = (39<<10)
2593
2594 opjumps:
2595 .dw do_op_nop
2596 .dw do_op_inc
2597 .dw do_op_dec
2598 .dw do_op_inc16
2599 .dw do_op_dec16
2600 .dw do_op_rlc
2601 .dw do_op_rrc
2602 .dw do_op_rr
2603 .dw do_op_rl
2604 .dw do_op_adda
2605 .dw do_op_adca
2606 .dw do_op_subfa
2607 .dw do_op_sbcfa
2608 .dw do_op_anda
2609 .dw do_op_ora
2610 .dw do_op_xora
2611 .dw do_op_addhl
2612 .dw do_op_sthl
2613 .dw do_op_rmem16
2614 .dw do_op_rmem8
2615 .dw do_op_da
2616 .dw do_op_scf
2617 .dw do_op_cpl
2618 .dw do_op_ccf
2619 .dw do_op_pop16
2620 .dw do_op_push16
2621 .dw do_op_ifnz
2622 .dw do_op_ifz
2623 .dw do_op_ifnc
2624 .dw do_op_ifc
2625 .dw do_op_ifpo
2626 .dw do_op_ifpe
2627 .dw do_op_ifp
2628 .dw do_op_ifm
2629 .dw do_op_outa
2630 .dw do_op_in
2631 .dw do_op_exhl
2632 .dw do_op_di
2633 .dw do_op_ei
2634 .dw do_op_inv
2635
2636
2637 ;How the flags are supposed to work:
2638 ;7 ZFL_S - Sign flag (=MSBit of result)
2639 ;6 ZFL_Z - Zero flag. Is 1 when the result is 0
2640 ;4 ZFL_H - Half-carry (carry from bit 3 to 4)
2641 ;2 ZFL_P - Parity/2-complement Overflow
2642 ;1 ZFL_N - Subtract - set if last op was a subtract
2643 ;0 ZFL_C - Carry
2644 ;
2645 ;I sure hope I got the mapping between flags and instructions correct...
2646
2647 ;----------------------------------------------------------------
2648 ;| |
2649 ;| Zilog |
2650 ;| |
2651 ;| ZZZZZZZ 88888 000 |
2652 ;| Z 8 8 0 0 |
2653 ;| Z 8 8 0 0 0 |
2654 ;| Z 88888 0 0 0 |
2655 ;| Z 8 8 0 0 0 |
2656 ;| Z 8 8 0 0 |
2657 ;| ZZZZZZZ 88888 000 |
2658 ;| |
2659 ;| Z80 MICROPROCESSOR Instruction Set Summary |
2660 ;| |
2661 ;----------------------------------------------------------------
2662 ;----------------------------------------------------------------
2663 ;|Mnemonic |SZHPNC|Description |Notes |
2664 ;|----------+------+---------------------+----------------------|
2665 ;|ADC A,s |***V0*|Add with Carry |A=A+s+CY |
2666 ;|ADC HL,ss |**?V0*|Add with Carry |HL=HL+ss+CY |
2667 ;|ADD A,s |***V0*|Add |A=A+s |
2668 ;|ADD HL,ss |--?-0*|Add |HL=HL+ss |
2669 ;|ADD IX,pp |--?-0*|Add |IX=IX+pp |
2670 ;|ADD IY,rr |--?-0*|Add |IY=IY+rr |
2671 ;|AND s |**1P00|Logical AND |A=A&s |
2672 ;|BIT b,m |?*1?0-|Test Bit |m&{2^b} |
2673 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
2674 ;|CALL nn |------|Unconditional Call |-[SP]=PC,PC=nn |
2675 ;|CCF |--?-0*|Complement Carry Flag|CY=~CY |
2676 ;|CP s |***V1*|Compare |A-s |
2677 ;|CPD |****1-|Compare and Decrement|A-[HL],HL=HL-1,BC=BC-1|
2678 ;|CPDR |****1-|Compare, Dec., Repeat|CPD till A=[HL]or BC=0|
2679 ;|CPI |****1-|Compare and Increment|A-[HL],HL=HL+1,BC=BC-1|
2680 ;|CPIR |****1-|Compare, Inc., Repeat|CPI till A=[HL]or BC=0|
2681 ;|CPL |--1-1-|Complement |A=~A |
2682 ;|DAA |***P-*|Decimal Adjust Acc. |A=BCD format |
2683 ;|DEC s |***V1-|Decrement |s=s-1 |
2684 ;|DEC xx |------|Decrement |xx=xx-1 |
2685 ;|DEC ss |------|Decrement |ss=ss-1 |
2686 ;|DI |------|Disable Interrupts | |
2687 ;|DJNZ e |------|Dec., Jump Non-Zero |B=B-1 till B=0 |
2688 ;|EI |------|Enable Interrupts | |
2689 ;|EX [SP],HL|------|Exchange |[SP]<->HL |
2690 ;|EX [SP],xx|------|Exchange |[SP]<->xx |
2691 ;|EX AF,AF' |------|Exchange |AF<->AF' |
2692 ;|EX DE,HL |------|Exchange |DE<->HL |
2693 ;|EXX |------|Exchange |qq<->qq' (except AF)|
2694 ;|HALT |------|Halt | |
2695 ;|IM n |------|Interrupt Mode | (n=0,1,2)|
2696 ;|IN A,[n] |------|Input |A=[n] |
2697 ;|IN r,[C] |***P0-|Input |r=[C] |
2698 ;|INC r |***V0-|Increment |r=r+1 |
2699 ;|INC [HL] |***V0-|Increment |[HL]=[HL]+1 |
2700 ;|INC xx |------|Increment |xx=xx+1 |
2701 ;|INC [xx+d]|***V0-|Increment |[xx+d]=[xx+d]+1 |
2702 ;|INC ss |------|Increment |ss=ss+1 |
2703 ;|IND |?*??1-|Input and Decrement |[HL]=[C],HL=HL-1,B=B-1|
2704 ;|INDR |?1??1-|Input, Dec., Repeat |IND till B=0 |
2705 ;|INI |?*??1-|Input and Increment |[HL]=[C],HL=HL+1,B=B-1|
2706 ;|INIR |?1??1-|Input, Inc., Repeat |INI till B=0 |
2707 ;|JP [HL] |------|Unconditional Jump |PC=[HL] |
2708 ;|JP [xx] |------|Unconditional Jump |PC=[xx] |
2709 ;|JP nn |------|Unconditional Jump |PC=nn |
2710 ;|JP cc,nn |------|Conditional Jump |If cc JP |
2711 ;|JR e |------|Unconditional Jump |PC=PC+e |
2712 ;|JR cc,e |------|Conditional Jump |If cc JR(cc=C,NC,NZ,Z)|
2713 ;|LD dst,src|------|Load |dst=src |
2714 ;|LD A,i |**0*0-|Load |A=i (i=I,R)|
2715 ;|LDD |--0*0-|Load and Decrement |[DE]=[HL],HL=HL-1,# |
2716 ;|LDDR |--000-|Load, Dec., Repeat |LDD till BC=0 |
2717 ;|LDI |--0*0-|Load and Increment |[DE]=[HL],HL=HL+1,# |
2718 ;|LDIR |--000-|Load, Inc., Repeat |LDI till BC=0 |
2719 ;|NEG |***V1*|Negate |A=-A |
2720 ;|NOP |------|No Operation | |
2721 ;|OR s |**0P00|Logical inclusive OR |A=Avs |
2722 ;|OTDR |?1??1-|Output, Dec., Repeat |OUTD till B=0 |
2723 ;|OTIR |?1??1-|Output, Inc., Repeat |OUTI till B=0 |
2724 ;|OUT [C],r |------|Output |[C]=r |
2725 ;|OUT [n],A |------|Output |[n]=A |
2726 ;|OUTD |?*??1-|Output and Decrement |[C]=[HL],HL=HL-1,B=B-1|
2727 ;|OUTI |?*??1-|Output and Increment |[C]=[HL],HL=HL+1,B=B-1|
2728 ;|POP xx |------|Pop |xx=[SP]+ |
2729 ;|POP qq |------|Pop |qq=[SP]+ |
2730 ;|PUSH xx |------|Push |-[SP]=xx |
2731 ;|PUSH qq |------|Push |-[SP]=qq |
2732 ;|RES b,m |------|Reset bit |m=m&{~2^b} |
2733 ;|RET |------|Return |PC=[SP]+ |
2734 ;|RET cc |------|Conditional Return |If cc RET |
2735 ;|RETI |------|Return from Interrupt|PC=[SP]+ |
2736 ;|RETN |------|Return from NMI |PC=[SP]+ |
2737 ;|RL m |**0P0*|Rotate Left |m={CY,m}<- |
2738 ;|RLA |--0-0*|Rotate Left Acc. |A={CY,A}<- |
2739 ;|RLC m |**0P0*|Rotate Left Circular |m=m<- |
2740 ;|RLCA |--0-0*|Rotate Left Circular |A=A<- |
2741 ;|RLD |**0P0-|Rotate Left 4 bits |{A,[HL]}={A,[HL]}<- ##|
2742 ;|RR m |**0P0*|Rotate Right |m=->{CY,m} |
2743 ;|RRA |--0-0*|Rotate Right Acc. |A=->{CY,A} |
2744 ;|RRC m |**0P0*|Rotate Right Circular|m=->m |
2745 ;|RRCA |--0-0*|Rotate Right Circular|A=->A |
2746 ;|RRD |**0P0-|Rotate Right 4 bits |{A,[HL]}=->{A,[HL]} ##|
2747 ;|RST p |------|Restart | (p=0H,8H,10H,...,38H)|
2748 ;|SBC A,s |***V1*|Subtract with Carry |A=A-s-CY |
2749 ;|SBC HL,ss |**?V1*|Subtract with Carry |HL=HL-ss-CY |
2750 ;|SCF |--0-01|Set Carry Flag |CY=1 |
2751 ;|SET b,m |------|Set bit |m=mv{2^b} |
2752 ;|SLA m |**0P0*|Shift Left Arithmetic|m=m*2 |
2753 ;|SRA m |**0P0*|Shift Right Arith. |m=m/2 |
2754 ;|SRL m |**0P0*|Shift Right Logical |m=->{0,m,CY} |
2755 ;|SUB s |***V1*|Subtract |A=A-s |
2756 ;|XOR s |**0P00|Logical Exclusive OR |A=Axs |
2757 ;|----------+------+--------------------------------------------|
2758
2759
2760 .equ AVR_T = 6
2761 .equ AVR_H = 5
2762 .equ AVR_S = 4
2763 .equ AVR_V = 3
2764 .equ AVR_N = 2
2765 .equ AVR_Z = 1
2766 .equ AVR_C = 0
2767
2768 ;------------------------------------------------;
2769 ; Move single bit between two registers
2770 ;
2771 ; bmov dstreg,dstbit,srcreg.srcbit
2772
2773 .macro bmov
2774 bst @2,@3
2775 bld @0,@1
2776 .endm
2777
2778
2779 ;------------------------------------------------;
2780 ; Load table value from flash indexed by source reg.
2781 ;
2782 ; ldpmx dstreg,tablebase,indexreg
2783 ;
2784 ; (6 words, 8 cycles)
2785
2786 .macro ldpmx
2787 ldi zl,low (@1*2)
2788 ldi zh,high(@1*2)
2789 add zl,@2
2790 brcc PC+2
2791 inc zh
2792 lpm @0,z
2793 .endm
2794
2795 .macro do_z80_flags_HP
2796 #if EM_Z80
2797 bmov z_flags, ZFL_P, temp, AVR_V
2798 bmov z_flags, ZFL_H, temp, AVR_H
2799 #endif
2800 .endm
2801
2802 .macro do_z80_flags_set_N
2803 #if EM_Z80
2804 ori z_flags, (1<<ZFL_N) ; Negation auf 1
2805 #endif
2806 .endm
2807
2808 .macro do_z80_flags_set_HN
2809 #if EM_Z80
2810 ori z_flags,(1<<ZFL_N)|(1<<ZFL_H)
2811 #endif
2812 .endm
2813
2814 .macro do_z80_flags_clear_N
2815 #if EM_Z80
2816 andi z_flags,~(1<<ZFL_N)
2817 #endif
2818 .endm
2819
2820 .macro do_z80_flags_op_rotate
2821 ; must not change avr carry flag!
2822 #if EM_Z80
2823 andi z_flags, ~( (1<<ZFL_H) | (1<<ZFL_N) | (1<<ZFL_C) )
2824 #else
2825 andi z_flags, ~( (1<<ZFL_C) )
2826 #endif
2827 .endm
2828
2829 .macro do_z80_flags_op_and
2830 #if EM_Z80
2831 ori z_flags,(1<<ZFL_H)
2832 #else
2833 ori z_flags,(1<<ZFL_H)
2834 #endif
2835 .endm
2836
2837 .macro do_z80_flags_op_or
2838 #if EM_Z80
2839 #endif
2840 .endm
2841
2842
2843 do_op_nop:
2844 ret
2845
2846 ;----------------------------------------------------------------
2847 ;|Mnemonic |SZHPNC|Description |Notes |
2848 ;----------------------------------------------------------------
2849 ;|INC r |***V0-|Increment |r=r+1 |
2850 ;|INC [HL] |***V0-|Increment |[HL]=[HL]+1 |
2851 ;|INC [xx+d]|***V0-|Increment |[xx+d]=[xx+d]+1 |
2852 ;|----------|SZHP C|---------- 8080 ----------------------------|
2853 ;|INC r |**-P0-|Increment |r=r+1 |
2854 ;|INC [HL] |**-P0-|Increment |[HL]=[HL]+1 |
2855 ;
2856 ;
2857 do_op_inc:
2858 ldi temp,1
2859 add opl,temp
2860 in temp, sreg
2861 andi z_flags,(1<<ZFL_H)|(1<<ZFL_C) ; preserve C-, and H-flag
2862 ldpmx temp2, sz53p_tab, opl
2863 or z_flags,temp2 ;
2864 do_z80_flags_HP
2865 ret
2866
2867 ;----------------------------------------------------------------
2868 ;|Mnemonic |SZHPNC|Description |Notes |
2869 ;----------------------------------------------------------------
2870 ;|DEC r |***V1-|Decrement |s=s-1 |
2871 ;|INC [HL] |***V0-|Increment |[HL]=[HL]+1 |
2872 ;|INC [xx+d]|***V0-|Increment |[xx+d]=[xx+d]+1 |
2873 ;|----------|SZHP C|---------- 8080 ----------------------------|
2874 ;|DEC r |**-P -|Increment |r=r+1 |
2875 ;|DEC [HL] |**-P -|Increment |[HL]=[HL]+1 |
2876 ;
2877 ;
2878 do_op_dec:
2879 subi opl,1
2880 in temp, sreg
2881 andi z_flags,(1<<ZFL_H)|(1<<ZFL_C) ; preserve C-, and H-flag
2882 ldpmx temp2, sz53p_tab, opl
2883 or z_flags,temp2 ;
2884 do_z80_flags_HP
2885 do_z80_flags_set_N
2886 ret
2887
2888
2889 ;----------------------------------------------------------------
2890 ;|Mnemonic |SZHPNC|Description |Notes |
2891 ;----------------------------------------------------------------
2892 ;|INC xx |------|Increment |xx=xx+1 |
2893 ;|INC ss |------|Increment |ss=ss+1 |
2894 ;
2895 ;
2896 do_op_inc16:
2897 inc opl
2898 brne op_i16x
2899 inc oph
2900 op_i16x:
2901 ret
2902
2903 ;----------------------------------------------------------------
2904 ;|Mnemonic |SZHPNC|Description |Notes |
2905 ;----------------------------------------------------------------
2906 ;|DEC xx |------|Decrement |xx=xx-1 |
2907 ;|DEC ss |------|Decrement |ss=ss-1 |
2908 ;
2909 ;
2910 do_op_dec16:
2911 subi opl, 1
2912 sbci oph, 0
2913 ret
2914
2915 ;----------------------------------------------------------------
2916 ;|Mnemonic |SZHPNC|Description |Notes |
2917 ;----------------------------------------------------------------
2918 ;|RLCA |--0-0*|Rotate Left Circular |A=A<- |
2919 ;|----------|SZHP C|---------- 8080 ----------------------------|
2920 ;|RLCA |---- *|Rotate Left Circular |A=A<- |
2921 ;
2922 ;
2923 do_op_rlc:
2924 ;Rotate Left Cyclical. All bits move 1 to the
2925 ;left, the msb becomes c and lsb.
2926 do_z80_flags_op_rotate
2927 lsl opl
2928 brcc do_op_rlc_noc
2929 ori opl, 1
2930 ori z_flags, (1<<ZFL_C)
2931 do_op_rlc_noc:
2932 ret
2933
2934 ;----------------------------------------------------------------
2935 ;|Mnemonic |SZHPNC|Description |Notes |
2936 ;----------------------------------------------------------------
2937 ;|RRCA |--0-0*|Rotate Right Circular|A=->A |
2938 ;|----------|SZHP C|---------- 8080 ----------------------------|
2939 ;|RRCA |---- *|Rotate Right Circular|A=->A |
2940 ;
2941 ;
2942 do_op_rrc:
2943 ;Rotate Right Cyclical. All bits move 1 to the
2944 ;right, the lsb becomes c and msb.
2945 do_z80_flags_op_rotate
2946 lsr opl
2947 brcc do_op_rrc_noc
2948 ori opl, 0x80
2949 ori z_flags, (1<<ZFL_C)
2950 do_op_rrc_noc:
2951 ret
2952
2953 ;----------------------------------------------------------------
2954 ;|Mnemonic |SZHPNC|Description |Notes |
2955 ;----------------------------------------------------------------
2956 ;|RRA |--0-0*|Rotate Right Acc. |A=->{CY,A} |
2957 ;|----------|SZHP C|---------- 8080 ----------------------------|
2958 ;|RRA |---- *|Rotate Right Acc. |A=->{CY,A} |
2959 ;
2960 ;
2961 do_op_rr:
2962 ;Rotate Right. All bits move 1 to the right, the lsb
2963 ;becomes c, c becomes msb.
2964 clc ; get z80 carry to avr carry
2965 sbrc z_flags,ZFL_C
2966 sec
2967 do_z80_flags_op_rotate ; (clear ZFL_C, doesn't change AVR_C)
2968 bmov z_flags,ZFL_C, opl,0 ; Bit 0 --> CY
2969 ror opl
2970 ret
2971
2972 ;----------------------------------------------------------------
2973 ;|Mnemonic |SZHPNC|Description |Notes |
2974 ;----------------------------------------------------------------
2975 ;|RLA |--0-0*|Rotate Left Acc. |A={CY,A}<- |
2976 ;|----------|SZHP C|---------- 8080 ----------------------------|
2977 ;|RLA |---- *|Rotate Left Acc. |A={CY,A}<- |
2978 ;
2979 ;
2980 do_op_rl:
2981 ;Rotate Left. All bits move 1 to the left, the msb
2982 ;becomes c, c becomes lsb.
2983 clc
2984 sbrc z_flags,ZFL_C
2985 sec
2986 do_z80_flags_op_rotate ; (clear ZFL_C, doesn't change AVR_C)
2987 bmov z_flags,ZFL_C, opl,7 ; Bit 7 --> CY
2988 rol opl
2989 ret
2990
2991 ;----------------------------------------------------------------
2992 ;|Mnemonic |SZHPNC|Description |Notes |
2993 ;----------------------------------------------------------------
2994 ;|ADD A,s |***V0*|Add |A=A+s |
2995 ;|----------|SZHP C|---------- 8080 ----------------------------|
2996 ;|ADD A,s |***P *|Add |A=A+s |
2997 ;
2998 ;
2999 do_op_adda:
3000 add opl,z_a
3001 in temp,sreg
3002 ldpmx z_flags,sz53p_tab,opl ;S,Z,P flag
3003 bmov z_flags,ZFL_C, temp,AVR_C
3004 do_z80_flags_HP
3005 ret
3006
3007 ;----------------------------------------------------------------
3008 ;|Mnemonic |SZHPNC|Description |Notes |
3009 ;----------------------------------------------------------------
3010 ;|ADC A,s |***V0*|Add with Carry |A=A+s+CY |
3011 ;|----------|SZHP C|---------- 8080 ----------------------------|
3012 ;|ADC A,s |***P *|Add with Carry |A=A+s+CY |
3013 ;
3014 ;
3015 do_op_adca:
3016 clc
3017 sbrc z_flags,ZFL_C
3018 sec
3019 adc opl,z_a
3020 in temp,sreg
3021 ldpmx z_flags,sz53p_tab,opl ;S,Z,P
3022 bmov z_flags,ZFL_C, temp,AVR_C
3023 do_z80_flags_HP
3024 ret
3025
3026 ;----------------------------------------------------------------
3027 ;|Mnemonic |SZHPNC|Description |Notes |
3028 ;----------------------------------------------------------------
3029 ;|SUB s |***V1*|Subtract |A=A-s |
3030 ;|CP s |***V1*|Compare |A-s |
3031 ;|----------|SZHP C|---------- 8080 ----------------------------|
3032 ;|SUB s |***P *|Subtract |A=A-s |
3033 ;|CP s |***P *|Compare |A-s |
3034
3035 ;
3036 do_op_subfa:
3037 mov temp,z_a
3038 sub temp,opl
3039 mov opl,temp
3040 in temp,sreg
3041 ldpmx z_flags,sz53p_tab,opl ;S,Z,P
3042 bmov z_flags,ZFL_C, temp,AVR_C
3043 do_z80_flags_HP
3044 do_z80_flags_set_N
3045 ret
3046
3047 ;----------------------------------------------------------------
3048 ;|Mnemonic |SZHPNC|Description |Notes |
3049 ;----------------------------------------------------------------
3050 ;|SBC A,s |***V1*|Subtract with Carry |A=A-s-CY |
3051 ;|----------|SZHP C|---------- 8080 ----------------------------|
3052 ;|SBC A,s |***P *|Subtract with Carry |A=A-s-CY |
3053 ;
3054 ;
3055 do_op_sbcfa:
3056 mov temp,z_a
3057 clc
3058 sbrc z_flags,ZFL_C
3059 sec
3060 sbc temp,opl
3061 mov opl,temp
3062 in temp,sreg
3063 ldpmx z_flags,sz53p_tab,opl ;S,Z,P
3064 bmov z_flags,ZFL_C, temp,AVR_C
3065 do_z80_flags_HP
3066 do_z80_flags_set_N
3067 ret
3068
3069 ;----------------------------------------------------------------
3070 ;|Mnemonic |SZHPNC|Description |Notes |
3071 ;----------------------------------------------------------------
3072 ;|AND s |**1P00|Logical AND |A=A&s |
3073 ;|----------|SZHP C|---------- 8080 ----------------------------|
3074 ;|AND s |**-P 0|Logical AND |A=A&s |
3075 ;
3076 ; TODO H-Flag
3077 do_op_anda:
3078 and opl,z_a ;
3079 ldpmx z_flags,sz53p_tab,opl ;S,Z,P,N,C
3080 do_z80_flags_op_and
3081 ret
3082
3083
3084 ;----------------------------------------------------------------
3085 ;|Mnemonic |SZHPNC|Description |Notes |
3086 ;----------------------------------------------------------------
3087 ;|OR s |**0P00|Logical inclusive OR |A=Avs |
3088 ;|----------|SZHP C|---------- 8080 ----------------------------|
3089 ;|OR s |**-P00|Logical inclusive OR |A=Avs |
3090 ;
3091 ; TODO: H-Flag
3092 do_op_ora:
3093 or opl,z_a
3094 ldpmx z_flags,sz53p_tab,opl ;S,Z,H,P,N,C
3095 do_z80_flags_op_or
3096 ret
3097
3098 ;----------------------------------------------------------------
3099 ;|Mnemonic |SZHPNC|Description |Notes |
3100 ;----------------------------------------------------------------
3101 ;|XOR s |**0P00|Logical Exclusive OR |A=Axs |
3102 ;|----------|SZHP C|---------- 8080 ----------------------------|
3103 ;|XOR s |**-P 0|Logical Exclusive OR |A=Axs |
3104 ;
3105 ; TODO: H-Flag
3106 do_op_xora:
3107 eor opl,z_a
3108 ldpmx z_flags,sz53p_tab,opl ;S,Z,H,P,N,C
3109 do_z80_flags_op_or
3110 ret
3111
3112 ;----------------------------------------------------------------
3113 ;|Mnemonic |SZHPNC|Description |Notes |
3114 ;----------------------------------------------------------------
3115 ;|ADD HL,ss |--?-0*|Add |HL=HL+ss |
3116 ;|----------|SZHP C|---------- 8080 ----------------------------|
3117 ;|ADD HL,ss |---- *|Add |HL=HL+ss |
3118 ;
3119 ;
3120 do_op_addhl:
3121 add opl,z_l
3122 adc oph,z_h
3123 in temp,sreg
3124 bmov z_flags,ZFL_H, temp,AVR_H
3125 bmov z_flags,ZFL_C, temp,AVR_C
3126 do_z80_flags_clear_N
3127 ret
3128
3129 ;----------------------------------------------------------------
3130 ;|Mnemonic |SZHPNC|Description |Notes |
3131 ;----------------------------------------------------------------
3132 ;|LD dst,src|------|Load |dst=src |
3133 ;
3134 ;
3135 do_op_sthl: ;store hl to mem loc in opl:h
3136 mov adrl,opl
3137 mov adrh,oph
3138 mov temp,z_l
3139 rcall memWriteByte
3140
3141 inc opl
3142 brne op_sthlx
3143 inc oph
3144 op_sthlx:
3145 mov adrl,opl
3146 mov adrh,oph
3147 mov temp,z_h
3148 rcall memWriteByte
3149
3150 ret
3151
3152 ;----------------------------------------------------------------
3153 ;|Mnemonic |SZHPNC|Description |Notes |
3154 ;----------------------------------------------------------------
3155 ;|LD dst,src|------|Load |dst=src |
3156 ;
3157 ;
3158 do_op_rmem16:
3159 mov adrl,opl
3160 mov adrh,oph
3161 rcall memReadByte
3162 mov opl,temp
3163 ldi temp,1
3164 add adrl,temp
3165 ldi temp,0
3166 adc adrh,temp
3167 rcall memReadByte
3168 mov oph,temp
3169 ret
3170
3171 ;----------------------------------------------------------------
3172 ;|Mnemonic |SZHPNC|Description |Notes |
3173 ;----------------------------------------------------------------
3174 ;|LD dst,src|------|Load |dst=src |
3175 ;
3176 ;
3177 do_op_rmem8:
3178 mov adrl,opl
3179 mov adrh,oph
3180 rcall memReadByte
3181 mov opl,temp
3182 ret
3183
3184 ;----------------------------------------------------------------
3185 ;|Mnemonic |SZHPNC|Description |Notes |
3186 ;----------------------------------------------------------------
3187 ;|DAA |***P-*|Decimal Adjust Acc. | |
3188 ;|----------|SZHP C|---------- 8080 ----------------------------|
3189 ;
3190 ; Not yet checked
3191
3192 ; Description (http://www.z80.info/z80syntx.htm#DAA):
3193 ; This instruction conditionally adjusts the accumulator for BCD addition
3194 ; and subtraction operations. For addition (ADD, ADC, INC) or subtraction
3195 ; (SUB, SBC, DEC, NEC), the following table indicates the operation performed:
3196 ;
3197 ; -------------------------------------------------------------------------------
3198 ; | | C Flag | HEX value in | H Flag | HEX value in | Number | C flag|
3199 ; | Operation| Before | upper digit | Before | lower digit | added | After |
3200 ; | | DAA | (bit 7-4) | DAA | (bit 3-0) | to byte | DAA |
3201 ; |-----------------------------------------------------------------------------|
3202 ; | | 0 | 0-9 | 0 | 0-9 | 00 | 0 |
3203 ; | ADD | 0 | 0-8 | 0 | A-F | 06 | 0 |
3204 ; | | 0 | 0-9 | 1 | 0-3 | 06 | 0 |
3205 ; | ADC | 0 | A-F | 0 | 0-9 | 60 | 1 |
3206 ; | | 0 | 9-F | 0 | A-F | 66 | 1 |
3207 ; | INC | 0 | A-F | 1 | 0-3 | 66 | 1 |
3208 ; | | 1 | 0-2 | 0 | 0-9 | 60 | 1 |
3209 ; | | 1 | 0-2 | 0 | A-F | 66 | 1 |
3210 ; | | 1 | 0-3 | 1 | 0-3 | 66 | 1 |
3211 ; |-----------------------------------------------------------------------------|
3212 ; | SUB | 0 | 0-9 | 0 | 0-9 | 00 | 0 |
3213 ; | SBC | 0 | 0-8 | 1 | 6-F | FA | 0 |
3214 ; | DEC | 1 | 7-F | 0 | 0-9 | A0 | 1 |
3215 ; | NEG | 1 | 6-F | 1 | 6-F | 9A | 1 |
3216 ; |-----------------------------------------------------------------------------|
3217 ;
3218 ; Flags:
3219 ; C: See instruction.
3220 ; N: Unaffected.
3221 ; P/V: Set if Acc. is even parity after operation, reset otherwise.
3222 ; H: See instruction.
3223 ; Z: Set if Acc. is Zero after operation, reset otherwise.
3224 ; S: Set if most significant bit of Acc. is 1 after operation, reset otherwise.
3225
3226
3227
3228 #if 1
3229 do_op_da:
3230 ldi oph,0 ; what to add
3231 sbrc z_flags,ZFL_H ; if H-Flag
3232 rjmp op_da_06
3233 mov temp,opl
3234 andi temp,0x0f ; ... or lower digit > 9
3235 cpi temp,0x0a
3236 brlo op_da_06n
3237 op_da_06:
3238 ori oph,0x06
3239 op_da_06n:
3240 sbrc z_flags,(1<<ZFL_C)
3241 rjmp op_da_60
3242 cpi opl,0xa0
3243 brlo op_da_60n
3244 op_da_60:
3245 ori oph,0x60
3246 op_da_60n:
3247 cpi opl,0x9a
3248 brlo op_da_99n
3249 ori z_flags,(1<<ZFL_C); set C
3250 op_da_99n:
3251 sbrs z_flags,ZFL_N ; if sub-op
3252 rjmp op_da_add ; then
3253 sub opl,oph
3254 rjmp op_da_ex
3255 op_da_add: ; else add-op
3256 cpi opl,0x91
3257 brlo op_da_60n2
3258 mov temp,opl
3259 andi temp,0x0f
3260 cpi temp,0x0a
3261 brlo op_da_60n2
3262 ori oph,0x60
3263 op_da_60n2:
3264 add opl,oph
3265 op_da_ex:
3266 in temp,SREG
3267 sbrc temp,AVR_H
3268 ori z_flags,(1<<ZFL_C)
3269 andi z_flags,(1<<ZFL_N)|(1<<ZFL_C) ; preserve C,N
3270 ldpmx temp2, sz53p_tab, opl ; get S,Z,P
3271 or z_flags,temp2
3272 bmov z_flags,ZFL_H, temp,AVR_H ; H (?)
3273 ret
3274 #else
3275
3276 do_op_da:
3277 sbrc z_flags,ZFL_N ; if add-op
3278 rjmp do_op_da_sub ; then
3279 ldi temp2,0 ;
3280 mov temp,opl ;
3281 andi temp,0x0f ;
3282 cpi temp,0x0a ; if lower digit > 9
3283 brlo do_op_da_h ;
3284 ori temp2,0x06 ; add 6 to lower digit
3285 do_op_da_h: ;
3286 sbrc z_flags,ZFL_H ; ... or H-Flag
3287 ori temp2,0x06 ;
3288 add opl,temp2 ;
3289
3290 ldi temp2,0 ;
3291 mov temp,opl ;
3292 andi temp,0xf0 ;
3293 cpi temp,0xa0 ;
3294 brlo do_op_da_c ;
3295 ori temp2,0x60 ;
3296 do_op_da_c: ; else sub-op
3297 sbrc z_flags,ZFL_C ;
3298 ori temp2,0x60 ;
3299 andi z_flags, ~( (1<<ZFL_S) | (1<<ZFL_Z) | (1<<ZFL_H) )
3300 add opl,temp2 ;
3301 in temp,SREG ;
3302 bst temp,AVR_Z ;Z-Flag
3303 bld z_flags,ZFL_Z ;
3304 bst temp,AVR_N ;S-Flag
3305 bst z_flags,ZFL_S ;
3306 sbrc temp2,5 ;C-Flag, set if 0x06 added
3307 ori z_flags,(1<<ZFL_C) ;
3308 ;H-Flag?
3309 ret
3310
3311 do_op_da_sub: ;TODO:
3312 rcall do_op_inv
3313 ret
3314 #endif
3315
3316 ;----------------------------------------------------------------
3317 ;|Mnemonic |SZHPNC|Description |Notes |
3318 ;----------------------------------------------------------------
3319 ;|SCF |--0-01|Set Carry Flag |CY=1 |
3320 ;|----------|SZHP C|---------- 8080 ----------------------------|
3321 ;
3322 ;
3323 do_op_scf:
3324 andi z_flags,~((1<<ZFL_H)|(1<<ZFL_N))
3325 ori z_flags,(1<<ZFL_C)
3326 ret
3327
3328 ;----------------------------------------------------------------
3329 ;|Mnemonic |SZHPNC|Description |Notes |
3330 ;----------------------------------------------------------------
3331 ;|CCF |--?-0*|Complement Carry Flag|CY=~CY |
3332 ;|----------|SZHP C|---------- 8080 ----------------------------|
3333 ;|SCF |---- 1|Set Carry Flag |CY=1 |
3334 ;
3335 ;TODO: H-Flag
3336 do_op_ccf:
3337 do_z80_flags_clear_N
3338 ldi temp,(1<<ZFL_C)
3339 eor z_flags,temp
3340 ret
3341
3342 ;----------------------------------------------------------------
3343 ;|Mnemonic |SZHPNC|Description |Notes |
3344 ;----------------------------------------------------------------
3345 ;|CPL |--1-1-|Complement |A=~A |
3346 ;|----------|SZHP C|---------- 8080 ----------------------------|
3347 ;|CPL |---- -|Complement |A=~A |
3348 ;
3349 ;
3350 do_op_cpl:
3351 com opl
3352 do_z80_flags_set_HN
3353 ret
3354
3355
3356 ;----------------------------------------------------------------
3357 ;|Mnemonic |SZHPNC|Description |Notes |
3358 ;----------------------------------------------------------------
3359 ;|PUSH xx |------|Push |-[SP]=xx |
3360 ;|PUSH qq |------|Push |-[SP]=qq |
3361 ;
3362 ;
3363 do_op_push16:
3364 #if 1
3365 ldi temp,1
3366 ldi temp2,0
3367 sub z_spl,temp
3368 sbc z_sph,temp2
3369
3370 mov adrl,z_spl
3371 mov adrh,z_sph
3372 mov temp,oph
3373 rcall memWriteByte
3374
3375 ldi temp,1
3376 ldi temp2,0
3377 sub z_spl,temp
3378 sbc z_sph,temp2
3379
3380 mov adrl,z_spl
3381 mov adrh,z_sph
3382 mov temp,opl
3383 rcall memWriteByte
3384 #else
3385 subi z_spl,1
3386 sbci z_sph,0
3387
3388 mov adrl,z_spl
3389 mov adrh,z_sph
3390 mov temp,oph
3391 rcall memWriteByte
3392
3393 subi z_spl,1
3394 sbci z_sph,0
3395
3396 mov adrl,z_spl
3397 mov adrh,z_sph
3398 mov temp,opl
3399 rcall memWriteByte
3400 #endif
3401
3402 .if STACK_DBG
3403 rcall printstr
3404 .db "Stack push ",0
3405 mov temp,oph
3406 rcall printhex
3407 mov temp,opl
3408 rcall printhex
3409 rcall printstr
3410 .db ", SP is now ",0
3411 mov temp,z_sph
3412 rcall printhex
3413 mov temp,z_spl
3414 rcall printhex
3415 rcall printstr
3416 .db ".",13,0
3417 .endif
3418
3419 ret
3420
3421 ;----------------------------------------------------------------
3422 ;|Mnemonic |SZHPNC|Description |Notes |
3423 ;----------------------------------------------------------------
3424 ;|POP xx |------|Pop |xx=[SP]+ |
3425 ;|POP qq |------|Pop |qq=[SP]+ |
3426 ;
3427 ;
3428 do_op_pop16:
3429 mov adrl,z_spl
3430 mov adrh,z_sph
3431 rcall memReadByte
3432 mov opl,temp
3433
3434 ldi temp,1
3435 ldi temp2,0
3436 add z_spl,temp
3437 adc z_sph,temp2
3438
3439 mov adrl,z_spl
3440 mov adrh,z_sph
3441 rcall memReadByte
3442 mov oph,temp
3443
3444 ldi temp,1
3445 ldi temp2,0
3446 add z_spl,temp
3447 adc z_sph,temp2
3448
3449 .if STACK_DBG
3450 rcall printstr
3451 .db "Stack pop: val ",0
3452 mov temp,oph
3453 rcall printhex
3454 mov temp,opl
3455 rcall printhex
3456 rcall printstr
3457 .db ", SP is now",0
3458 mov temp,z_sph
3459 rcall printhex
3460 mov temp,z_spl
3461 rcall printhex
3462 rcall printstr
3463 .db ".",13,0
3464 .endif
3465 ret
3466
3467 ;----------------------------------------------------------------
3468 ;|Mnemonic |SZHPNC|Description |Notes |
3469 ;----------------------------------------------------------------
3470 ;|EX [SP],HL|------|Exchange |[SP]<->HL |
3471 ;|EX DE,HL |------|Exchange |DE<->HL |
3472 ;
3473 ;
3474 do_op_exhl:
3475 mov temp,z_h
3476 mov z_h,oph
3477 mov oph,temp
3478 mov temp,z_l
3479 mov z_l,opl
3480 mov opl,temp
3481 ret
3482
3483 ;----------------------------------------------------------------
3484 ;|Mnemonic |SZHPNC|Description |Notes |
3485 ;----------------------------------------------------------------
3486 ;
3487 ; TODO: Implement IFF1, IFF2
3488 do_op_di:
3489 ret
3490
3491 ;----------------------------------------------------------------
3492 ;|Mnemonic |SZHPNC|Description |Notes |
3493 ;----------------------------------------------------------------
3494 ;
3495 ; TODO: Implement IFF1, IFF2
3496 do_op_ei:
3497 ret
3498
3499 ;----------------------------------------------------------------
3500 ;|Mnemonic |SZHPNC|Description |Notes |
3501 ;----------------------------------------------------------------
3502 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3503 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3504 ;|RET cc |------|Conditional Return |If cc RET |
3505 ;
3506 ;
3507 do_op_ifnz:
3508 sbrs z_flags, ZFL_Z
3509 ret
3510 ldi insdech, 0
3511 ldi insdecl, 0
3512 ret
3513
3514 ;----------------------------------------------------------------
3515 ;|Mnemonic |SZHPNC|Description |Notes |
3516 ;----------------------------------------------------------------
3517 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3518 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3519 ;|RET cc |------|Conditional Return |If cc RET |
3520 ;
3521 ;
3522 do_op_ifz:
3523 sbrc z_flags, ZFL_Z
3524 ret
3525 ldi insdech, 0
3526 ldi insdecl, 0
3527 ret
3528
3529 ;----------------------------------------------------------------
3530 ;|Mnemonic |SZHPNC|Description |Notes |
3531 ;----------------------------------------------------------------
3532 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3533 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3534 ;|RET cc |------|Conditional Return |If cc RET |
3535 ;
3536 ;
3537 do_op_ifnc:
3538 sbrs z_flags, ZFL_C
3539 ret
3540 ldi insdech, 0
3541 ldi insdecl, 0
3542 ret
3543
3544 ;----------------------------------------------------------------
3545 ;|Mnemonic |SZHPNC|Description |Notes |
3546 ;----------------------------------------------------------------
3547 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3548 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3549 ;|RET cc |------|Conditional Return |If cc RET |
3550 ;
3551 ;
3552 do_op_ifc:
3553 sbrc z_flags, ZFL_C
3554 ret
3555 ldi insdech, 0
3556 ldi insdecl, 0
3557 ret
3558
3559 ;----------------------------------------------------------------
3560 ;|Mnemonic |SZHPNC|Description |Notes |
3561 ;----------------------------------------------------------------
3562 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3563 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3564 ;|RET cc |------|Conditional Return |If cc RET |
3565 ;
3566 ;
3567 do_op_ifpo:
3568 sbrs z_flags, ZFL_P
3569 ret
3570 ldi insdech, 0
3571 ldi insdecl, 0
3572 ret
3573
3574 ;----------------------------------------------------------------
3575 ;|Mnemonic |SZHPNC|Description |Notes |
3576 ;----------------------------------------------------------------
3577 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3578 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3579 ;|RET cc |------|Conditional Return |If cc RET |
3580 ;
3581 ;
3582 do_op_ifpe:
3583 sbrc z_flags, ZFL_P
3584 ret
3585 ldi insdech, 0
3586 ldi insdecl, 0
3587 ret
3588
3589 ;----------------------------------------------------------------
3590 ;|Mnemonic |SZHPNC|Description |Notes |
3591 ;----------------------------------------------------------------
3592 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3593 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3594 ;|RET cc |------|Conditional Return |If cc RET |
3595 ;
3596 ;
3597 do_op_ifp: ;sign positive, aka s=0
3598 sbrs z_flags, ZFL_S
3599 ret
3600 ldi insdech,0
3601 ldi insdecl,0
3602 ret
3603
3604 ;----------------------------------------------------------------
3605 ;|Mnemonic |SZHPNC|Description |Notes |
3606 ;----------------------------------------------------------------
3607 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3608 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3609 ;|RET cc |------|Conditional Return |If cc RET |
3610 ;
3611 ;
3612 do_op_ifm: ;sign negative, aka s=1
3613 sbrc z_flags, ZFL_S
3614 ret
3615 ldi insdech, 0
3616 ldi insdecl, 0
3617 ret
3618
3619 ;----------------------------------------------------------------
3620 ;|Mnemonic |SZHPNC|Description |Notes |
3621 ;----------------------------------------------------------------
3622 ;|OUT [n],A |------|Output |[n]=A |
3623 ;
3624 ;
3625 ;Interface with peripherials goes here :)
3626 do_op_outa: ; out (opl),a
3627 .if PORT_DEBUG
3628 rcall printstr
3629 .db 13,"Port write: ",0
3630 mov temp,z_a
3631 rcall printhex
3632 rcall printstr
3633 .db " -> (",0
3634 mov temp,opl
3635 rcall printhex
3636 rcall printstr
3637 .db ")",13,0
3638 .endif
3639 mov temp,z_a
3640 mov temp2,opl
3641 rcall portWrite
3642 ret
3643
3644 ;----------------------------------------------------------------
3645 ;|Mnemonic |SZHPNC|Description |Notes |
3646 ;----------------------------------------------------------------
3647 ;|IN A,[n] |------|Input |A=[n] |
3648 ;
3649 ;
3650 do_op_in: ; in a,(opl)
3651 .if PORT_DEBUG
3652 rcall printstr
3653 .db 13,"Port read: (",0
3654 mov temp,opl
3655 rcall printhex
3656 rcall printstr
3657 .db ") -> ",0
3658 .endif
3659
3660 mov temp2,opl
3661 rcall portRead
3662 mov opl,temp
3663
3664 .if PORT_DEBUG
3665 rcall printhex
3666 rcall printstr
3667 .db 13,0
3668 .endif
3669 ret
3670
3671 ;----------------------------------------------------------------
3672
3673 #if 0
3674 do_op_calcparity:
3675 ldi temp2,1
3676 sbrc parityb,0
3677 inc temp2
3678 sbrc parityb,1
3679 inc temp2
3680 sbrc parityb,2
3681 inc temp2
3682 sbrc parityb,3
3683 inc temp2
3684 sbrc parityb,4
3685 inc temp2
3686 sbrc parityb,5
3687 inc temp2
3688 sbrc parityb,6
3689 inc temp2
3690 sbrc parityb,7
3691 inc temp2
3692 andi temp2,1
3693 ret
3694 #endif
3695
3696 ;----------------------------------------------------------------
3697 do_op_inv:
3698 rcall printstr
3699 .db "Invalid opcode @ PC=",0,0
3700 mov temp,z_pch
3701 rcall printhex
3702 mov temp,z_pcl
3703 rcall printhex
3704
3705 ;----------------------------------------------------------------
3706 haltinv:
3707 rjmp haltinv
3708
3709 ;----------------------------------------------------------------
3710 ; Lookup table, stolen from z80ex, Z80 emulation library.
3711 ; http://z80ex.sourceforge.net/
3712
3713 ; The S, Z, 5 and 3 bits and the parity of the lookup value
3714 sz53p_tab:
3715 .db 0x44,0x00,0x00,0x04,0x00,0x04,0x04,0x00
3716 .db 0x08,0x0c,0x0c,0x08,0x0c,0x08,0x08,0x0c
3717 .db 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04
3718 .db 0x0c,0x08,0x08,0x0c,0x08,0x0c,0x0c,0x08
3719 .db 0x20,0x24,0x24,0x20,0x24,0x20,0x20,0x24
3720 .db 0x2c,0x28,0x28,0x2c,0x28,0x2c,0x2c,0x28
3721 .db 0x24,0x20,0x20,0x24,0x20,0x24,0x24,0x20
3722 .db 0x28,0x2c,0x2c,0x28,0x2c,0x28,0x28,0x2c
3723 .db 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04
3724 .db 0x0c,0x08,0x08,0x0c,0x08,0x0c,0x0c,0x08
3725 .db 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00
3726 .db 0x08,0x0c,0x0c,0x08,0x0c,0x08,0x08,0x0c
3727 .db 0x24,0x20,0x20,0x24,0x20,0x24,0x24,0x20
3728 .db 0x28,0x2c,0x2c,0x28,0x2c,0x28,0x28,0x2c
3729 .db 0x20,0x24,0x24,0x20,0x24,0x20,0x20,0x24
3730 .db 0x2c,0x28,0x28,0x2c,0x28,0x2c,0x2c,0x28
3731 .db 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84
3732 .db 0x8c,0x88,0x88,0x8c,0x88,0x8c,0x8c,0x88
3733 .db 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80
3734 .db 0x88,0x8c,0x8c,0x88,0x8c,0x88,0x88,0x8c
3735 .db 0xa4,0xa0,0xa0,0xa4,0xa0,0xa4,0xa4,0xa0
3736 .db 0xa8,0xac,0xac,0xa8,0xac,0xa8,0xa8,0xac
3737 .db 0xa0,0xa4,0xa4,0xa0,0xa4,0xa0,0xa0,0xa4
3738 .db 0xac,0xa8,0xa8,0xac,0xa8,0xac,0xac,0xa8
3739 .db 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80
3740 .db 0x88,0x8c,0x8c,0x88,0x8c,0x88,0x88,0x8c
3741 .db 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84
3742 .db 0x8c,0x88,0x88,0x8c,0x88,0x8c,0x8c,0x88
3743 .db 0xa0,0xa4,0xa4,0xa0,0xa4,0xa0,0xa0,0xa4
3744 .db 0xac,0xa8,0xa8,0xac,0xa8,0xac,0xac,0xa8
3745 .db 0xa4,0xa0,0xa0,0xa4,0xa0,0xa4,0xa4,0xa0
3746 .db 0xa8,0xac,0xac,0xa8,0xac,0xa8,0xa8,0xac
3747
3748
3749 ; ----------------------- Opcode decoding -------------------------
3750
3751 ; Lookup table for Z80 opcodes. Translates the first byte of the instruction word into three
3752 ; operations: fetch, do something, store.
3753 ; The table is made of 256 words. These 16-bit words consist of
3754 ; the fetch operation (bit 0-4), the processing operation (bit 10-16) and the store
3755 ; operation (bit 5-9).
3756
3757 inst_table:
3758 .dw (FETCH_NOP | OP_NOP | STORE_NOP) ; 00 NOP
3759 .dw (FETCH_DIR16| OP_NOP | STORE_BC ) ; 01 nn nn LD BC,nn
3760 .dw (FETCH_A | OP_NOP | STORE_MBC ) ; 02 LD (BC),A
3761 .dw (FETCH_BC | OP_INC16 | STORE_BC ) ; 03 INC BC
3762 .dw (FETCH_B | OP_INC | STORE_B ) ; 04 INC B
3763 .dw (FETCH_B | OP_DEC | STORE_B ) ; 05 DEC B
3764 .dw (FETCH_DIR8 | OP_NOP | STORE_B ) ; 06 nn LD B,n
3765 .dw (FETCH_A | OP_RLC | STORE_A ) ; 07 RLCA
3766 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 08 EX AF,AF' (Z80)
3767 .dw (FETCH_BC | OP_ADDHL | STORE_HL ) ; 09 ADD HL,BC
3768 .dw (FETCH_MBC | OP_NOP | STORE_A ) ; 0A LD A,(BC)
3769 .dw (FETCH_BC | OP_DEC16 | STORE_BC ) ; 0B DEC BC
3770 .dw (FETCH_C | OP_INC | STORE_C ) ; 0C INC C
3771 .dw (FETCH_C | OP_DEC | STORE_C ) ; 0D DEC C
3772 .dw (FETCH_DIR8 | OP_NOP | STORE_C ) ; 0E nn LD C,n
3773 .dw (FETCH_A | OP_RRC | STORE_A ) ; 0F RRCA
3774 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 10 oo DJNZ o (Z80)
3775 .dw (FETCH_DIR16| OP_NOP | STORE_DE ) ; 11 nn nn LD DE,nn
3776 .dw (FETCH_A | OP_NOP | STORE_MDE) ; 12 LD (DE),A
3777 .dw (FETCH_DE | OP_INC16 | STORE_DE ) ; 13 INC DE
3778 .dw (FETCH_D | OP_INC | STORE_D ) ; 14 INC D
3779 .dw (FETCH_D | OP_DEC | STORE_D ) ; 15 DEC D
3780 .dw (FETCH_DIR8 | OP_NOP | STORE_D ) ; 16 nn LD D,n
3781 .dw (FETCH_A | OP_RL | STORE_A ) ; 17 RLA
3782 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 18 oo JR o (Z80)
3783 .dw (FETCH_DE | OP_ADDHL | STORE_HL ) ; 19 ADD HL,DE
3784 .dw (FETCH_MDE | OP_NOP | STORE_A ) ; 1A LD A,(DE)
3785 .dw (FETCH_DE | OP_DEC16 | STORE_DE ) ; 1B DEC DE
3786 .dw (FETCH_E | OP_INC | STORE_E ) ; 1C INC E
3787 .dw (FETCH_E | OP_DEC | STORE_E ) ; 1D DEC E
3788 .dw (FETCH_DIR8 | OP_NOP | STORE_E ) ; 1E nn LD E,n
3789 .dw (FETCH_A | OP_RR | STORE_A ) ; 1F RRA
3790 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 20 oo JR NZ,o (Z80)
3791 .dw (FETCH_DIR16| OP_NOP | STORE_HL ) ; 21 nn nn LD HL,nn
3792 .dw (FETCH_DIR16| OP_STHL | STORE_NOP) ; 22 nn nn LD (nn),HL
3793 .dw (FETCH_HL | OP_INC16 | STORE_HL ) ; 23 INC HL
3794 .dw (FETCH_H | OP_INC | STORE_H ) ; 24 INC H
3795 .dw (FETCH_H | OP_DEC | STORE_H ) ; 25 DEC H
3796 .dw (FETCH_DIR8 | OP_NOP | STORE_H ) ; 26 nn LD H,n
3797 .dw (FETCH_A | OP_DA | STORE_A ) ; 27 DAA
3798 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 28 oo JR Z,o (Z80)
3799 .dw (FETCH_HL | OP_ADDHL | STORE_HL ) ; 29 ADD HL,HL
3800 .dw (FETCH_DIR16| OP_RMEM16 | STORE_HL ) ; 2A nn nn LD HL,(nn)
3801 .dw (FETCH_HL | OP_DEC16 | STORE_HL ) ; 2B DEC HL
3802 .dw (FETCH_L | OP_INC | STORE_L ) ; 2C INC L
3803 .dw (FETCH_L | OP_DEC | STORE_L ) ; 2D DEC L
3804 .dw (FETCH_DIR8 | OP_NOP | STORE_L ) ; 2E nn LD L,n
3805 .dw (FETCH_A | OP_CPL | STORE_A ) ; 2F CPL
3806 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 30 oo JR NC,o (Z80)
3807 .dw (FETCH_DIR16| OP_NOP | STORE_SP ) ; 31 nn nn LD SP,nn
3808 .dw (FETCH_DIR16| OP_NOP | STORE_AM ) ; 32 nn nn LD (nn),A
3809 .dw (FETCH_SP | OP_INC16 | STORE_SP ) ; 33 INC SP
3810 .dw (FETCH_MHL | OP_INC | STORE_MHL) ; 34 INC (HL)
3811 .dw (FETCH_MHL | OP_DEC | STORE_MHL) ; 35 DEC (HL)
3812 .dw (FETCH_DIR8 | OP_NOP | STORE_MHL) ; 36 nn LD (HL),n
3813 .dw (FETCH_NOP | OP_SCF | STORE_NOP) ; 37 SCF
3814 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 38 oo JR C,o (Z80)
3815 .dw (FETCH_SP | OP_ADDHL | STORE_HL ) ; 39 ADD HL,SP
3816 .dw (FETCH_DIR16| OP_RMEM8 | STORE_A ) ; 3A nn nn LD A,(nn)
3817 .dw (FETCH_SP | OP_DEC16 | STORE_SP ) ; 3B DEC SP
3818 .dw (FETCH_A | OP_INC | STORE_A ) ; 3C INC A
3819 .dw (FETCH_A | OP_DEC | STORE_A ) ; 3D DEC A
3820 .dw (FETCH_DIR8 | OP_NOP | STORE_A ) ; 3E nn LD A,n
3821 .dw (FETCH_NOP | OP_CCF | STORE_NOP) ; 3F CCF (Complement Carry Flag, gvd)
3822 .dw (FETCH_B | OP_NOP | STORE_B ) ; 40 LD B,r
3823 .dw (FETCH_C | OP_NOP | STORE_B ) ; 41 LD B,r
3824 .dw (FETCH_D | OP_NOP | STORE_B ) ; 42 LD B,r
3825 .dw (FETCH_E | OP_NOP | STORE_B ) ; 43 LD B,r
3826 .dw (FETCH_H | OP_NOP | STORE_B ) ; 44 LD B,r
3827 .dw (FETCH_L | OP_NOP | STORE_B ) ; 45 LD B,r
3828 .dw (FETCH_MHL | OP_NOP | STORE_B ) ; 46 LD B,r
3829 .dw (FETCH_A | OP_NOP | STORE_B ) ; 47 LD B,r
3830 .dw (FETCH_B | OP_NOP | STORE_C ) ; 48 LD C,r
3831 .dw (FETCH_C | OP_NOP | STORE_C ) ; 49 LD C,r
3832 .dw (FETCH_D | OP_NOP | STORE_C ) ; 4A LD C,r
3833 .dw (FETCH_E | OP_NOP | STORE_C ) ; 4B LD C,r
3834 .dw (FETCH_H | OP_NOP | STORE_C ) ; 4C LD C,r
3835 .dw (FETCH_L | OP_NOP | STORE_C ) ; 4D LD C,r
3836 .dw (FETCH_MHL | OP_NOP | STORE_C ) ; 4E LD C,r
3837 .dw (FETCH_A | OP_NOP | STORE_C ) ; 4F LD C,r
3838 .dw (FETCH_B | OP_NOP | STORE_D ) ; 50 LD D,r
3839 .dw (FETCH_C | OP_NOP | STORE_D ) ; 51 LD D,r
3840 .dw (FETCH_D | OP_NOP | STORE_D ) ; 52 LD D,r
3841 .dw (FETCH_E | OP_NOP | STORE_D ) ; 53 LD D,r
3842 .dw (FETCH_H | OP_NOP | STORE_D ) ; 54 LD D,r
3843 .dw (FETCH_L | OP_NOP | STORE_D ) ; 55 LD D,r
3844 .dw (FETCH_MHL | OP_NOP | STORE_D ) ; 56 LD D,r
3845 .dw (FETCH_A | OP_NOP | STORE_D ) ; 57 LD D,r
3846 .dw (FETCH_B | OP_NOP | STORE_E ) ; 58 LD E,r
3847 .dw (FETCH_C | OP_NOP | STORE_E ) ; 59 LD E,r
3848 .dw (FETCH_D | OP_NOP | STORE_E ) ; 5A LD E,r
3849 .dw (FETCH_E | OP_NOP | STORE_E ) ; 5B LD E,r
3850 .dw (FETCH_H | OP_NOP | STORE_E ) ; 5C LD E,r
3851 .dw (FETCH_L | OP_NOP | STORE_E ) ; 5D LD E,r
3852 .dw (FETCH_MHL | OP_NOP | STORE_E ) ; 5E LD E,r
3853 .dw (FETCH_A | OP_NOP | STORE_E ) ; 5F LD E,r
3854 .dw (FETCH_B | OP_NOP | STORE_H ) ; 60 LD H,r
3855 .dw (FETCH_C | OP_NOP | STORE_H ) ; 61 LD H,r
3856 .dw (FETCH_D | OP_NOP | STORE_H ) ; 62 LD H,r
3857 .dw (FETCH_E | OP_NOP | STORE_H ) ; 63 LD H,r
3858 .dw (FETCH_H | OP_NOP | STORE_H ) ; 64 LD H,r
3859 .dw (FETCH_L | OP_NOP | STORE_H ) ; 65 LD H,r
3860 .dw (FETCH_MHL | OP_NOP | STORE_H ) ; 66 LD H,r
3861 .dw (FETCH_A | OP_NOP | STORE_H ) ; 67 LD H,r
3862 .dw (FETCH_B | OP_NOP | STORE_L ) ; 68 LD L,r
3863 .dw (FETCH_C | OP_NOP | STORE_L ) ; 69 LD L,r
3864 .dw (FETCH_D | OP_NOP | STORE_L ) ; 6A LD L,r
3865 .dw (FETCH_E | OP_NOP | STORE_L ) ; 6B LD L,r
3866 .dw (FETCH_H | OP_NOP | STORE_L ) ; 6C LD L,r
3867 .dw (FETCH_L | OP_NOP | STORE_L ) ; 6D LD L,r
3868 .dw (FETCH_MHL | OP_NOP | STORE_L ) ; 6E LD L,r
3869 .dw (FETCH_A | OP_NOP | STORE_L ) ; 6F LD L,r
3870 .dw (FETCH_B | OP_NOP | STORE_MHL) ; 70 LD (HL),r
3871 .dw (FETCH_C | OP_NOP | STORE_MHL) ; 71 LD (HL),r
3872 .dw (FETCH_D | OP_NOP | STORE_MHL) ; 72 LD (HL),r
3873 .dw (FETCH_E | OP_NOP | STORE_MHL) ; 73 LD (HL),r
3874 .dw (FETCH_H | OP_NOP | STORE_MHL) ; 74 LD (HL),r
3875 .dw (FETCH_L | OP_NOP | STORE_MHL) ; 75 LD (HL),r
3876 .dw (FETCH_NOP | OP_NOP | STORE_NOP) ; 76 HALT
3877 .dw (FETCH_A | OP_NOP | STORE_MHL) ; 77 LD (HL),r
3878 .dw (FETCH_B | OP_NOP | STORE_A ) ; 78 LD A,r
3879 .dw (FETCH_C | OP_NOP | STORE_A ) ; 79 LD A,r
3880 .dw (FETCH_D | OP_NOP | STORE_A ) ; 7A LD A,r
3881 .dw (FETCH_E | OP_NOP | STORE_A ) ; 7B LD A,r
3882 .dw (FETCH_H | OP_NOP | STORE_A ) ; 7C LD A,r
3883 .dw (FETCH_L | OP_NOP | STORE_A ) ; 7D LD A,r
3884 .dw (FETCH_MHL | OP_NOP | STORE_A ) ; 7E LD A,r
3885 .dw (FETCH_A | OP_NOP | STORE_A ) ; 7F LD A,r
3886 .dw (FETCH_B | OP_ADDA | STORE_A ) ; 80 ADD A,r
3887 .dw (FETCH_C | OP_ADDA | STORE_A ) ; 81 ADD A,r
3888 .dw (FETCH_D | OP_ADDA | STORE_A ) ; 82 ADD A,r
3889 .dw (FETCH_E | OP_ADDA | STORE_A ) ; 83 ADD A,r
3890 .dw (FETCH_H | OP_ADDA | STORE_A ) ; 84 ADD A,r
3891 .dw (FETCH_L | OP_ADDA | STORE_A ) ; 85 ADD A,r
3892 .dw (FETCH_MHL | OP_ADDA | STORE_A ) ; 86 ADD A,r
3893 .dw (FETCH_A | OP_ADDA | STORE_A ) ; 87 ADD A,r
3894 .dw (FETCH_B | OP_ADCA | STORE_A ) ; 88 ADC A,r
3895 .dw (FETCH_C | OP_ADCA | STORE_A ) ; 89 ADC A,r
3896 .dw (FETCH_D | OP_ADCA | STORE_A ) ; 8A ADC A,r
3897 .dw (FETCH_E | OP_ADCA | STORE_A ) ; 8B ADC A,r
3898 .dw (FETCH_H | OP_ADCA | STORE_A ) ; 8C ADC A,r
3899 .dw (FETCH_L | OP_ADCA | STORE_A ) ; 8D ADC A,r
3900 .dw (FETCH_MHL | OP_ADCA | STORE_A ) ; 8E ADC A,r
3901 .dw (FETCH_A | OP_ADCA | STORE_A ) ; 8F ADC A,r
3902 .dw (FETCH_B | OP_SUBFA | STORE_A ) ; 90 SUB A,r
3903 .dw (FETCH_C | OP_SUBFA | STORE_A ) ; 91 SUB A,r
3904 .dw (FETCH_D | OP_SUBFA | STORE_A ) ; 92 SUB A,r
3905 .dw (FETCH_E | OP_SUBFA | STORE_A ) ; 93 SUB A,r
3906 .dw (FETCH_H | OP_SUBFA | STORE_A ) ; 94 SUB A,r
3907 .dw (FETCH_L | OP_SUBFA | STORE_A ) ; 95 SUB A,r
3908 .dw (FETCH_MHL | OP_SUBFA | STORE_A ) ; 96 SUB A,r
3909 .dw (FETCH_A | OP_SUBFA | STORE_A ) ; 97 SUB A,r
3910 .dw (FETCH_B | OP_SBCFA | STORE_A ) ; 98 SBC A,r
3911 .dw (FETCH_C | OP_SBCFA | STORE_A ) ; 99 SBC A,r
3912 .dw (FETCH_D | OP_SBCFA | STORE_A ) ; 9A SBC A,r
3913 .dw (FETCH_E | OP_SBCFA | STORE_A ) ; 9B SBC A,r
3914 .dw (FETCH_H | OP_SBCFA | STORE_A ) ; 9C SBC A,r
3915 .dw (FETCH_L | OP_SBCFA | STORE_A ) ; 9D SBC A,r
3916 .dw (FETCH_MHL | OP_SBCFA | STORE_A ) ; 9E SBC A,r
3917 .dw (FETCH_A | OP_SBCFA | STORE_A ) ; 9F SBC A,r
3918 .dw (FETCH_B | OP_ANDA | STORE_A ) ; A0 AND A,r
3919 .dw (FETCH_C | OP_ANDA | STORE_A ) ; A1 AND A,r
3920 .dw (FETCH_D | OP_ANDA | STORE_A ) ; A2 AND A,r
3921 .dw (FETCH_E | OP_ANDA | STORE_A ) ; A3 AND A,r
3922 .dw (FETCH_H | OP_ANDA | STORE_A ) ; A4 AND A,r
3923 .dw (FETCH_L | OP_ANDA | STORE_A ) ; A5 AND A,r
3924 .dw (FETCH_MHL | OP_ANDA | STORE_A ) ; A6 AND A,r
3925 .dw (FETCH_A | OP_ANDA | STORE_A ) ; A7 AND A,r
3926 .dw (FETCH_B | OP_XORA | STORE_A ) ; A8 XOR A,r
3927 .dw (FETCH_C | OP_XORA | STORE_A ) ; A9 XOR A,r
3928 .dw (FETCH_D | OP_XORA | STORE_A ) ; AA XOR A,r
3929 .dw (FETCH_E | OP_XORA | STORE_A ) ; AB XOR A,r
3930 .dw (FETCH_H | OP_XORA | STORE_A ) ; AC XOR A,r
3931 .dw (FETCH_L | OP_XORA | STORE_A ) ; AD XOR A,r
3932 .dw (FETCH_MHL | OP_XORA | STORE_A ) ; AE XOR A,r
3933 .dw (FETCH_A | OP_XORA | STORE_A ) ; AF XOR A,r
3934 .dw (FETCH_B | OP_ORA | STORE_A ) ; B0 OR A,r
3935 .dw (FETCH_C | OP_ORA | STORE_A ) ; B1 OR A,r
3936 .dw (FETCH_D | OP_ORA | STORE_A ) ; B2 OR A,r
3937 .dw (FETCH_E | OP_ORA | STORE_A ) ; B3 OR A,r
3938 .dw (FETCH_H | OP_ORA | STORE_A ) ; B4 OR A,r
3939 .dw (FETCH_L | OP_ORA | STORE_A ) ; B5 OR A,r
3940 .dw (FETCH_MHL | OP_ORA | STORE_A ) ; B6 OR A,r
3941 .dw (FETCH_A | OP_ORA | STORE_A ) ; B7 OR A,r
3942 .dw (FETCH_B | OP_SUBFA | STORE_NOP) ; B8 CP A,r
3943 .dw (FETCH_C | OP_SUBFA | STORE_NOP) ; B9 CP A,r
3944 .dw (FETCH_D | OP_SUBFA | STORE_NOP) ; BA CP A,r
3945 .dw (FETCH_E | OP_SUBFA | STORE_NOP) ; BB CP A,r
3946 .dw (FETCH_H | OP_SUBFA | STORE_NOP) ; BC CP A,r
3947 .dw (FETCH_L | OP_SUBFA | STORE_NOP) ; BD CP A,r
3948 .dw (FETCH_MHL | OP_SUBFA | STORE_NOP) ; BE CP A,r
3949 .dw (FETCH_A | OP_SUBFA | STORE_NOP) ; BF CP A,r
3950 .dw (FETCH_NOP | OP_IFNZ | STORE_RET) ; C0 RET NZ
3951 .dw (FETCH_NOP | OP_POP16 | STORE_BC ) ; C1 POP BC
3952 .dw (FETCH_DIR16| OP_IFNZ | STORE_PC ) ; C2 nn nn JP NZ,nn
3953 .dw (FETCH_DIR16| OP_NOP | STORE_PC ) ; C3 nn nn JP nn
3954 .dw (FETCH_DIR16| OP_IFNZ | STORE_CALL) ; C4 nn nn CALL NZ,nn
3955 .dw (FETCH_BC | OP_PUSH16 | STORE_NOP) ; C5 PUSH BC
3956 .dw (FETCH_DIR8 | OP_ADDA | STORE_A ) ; C6 nn ADD A,n
3957 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; C7 RST 0
3958 .dw (FETCH_NOP | OP_IFZ | STORE_RET) ; C8 RET Z
3959 .dw (FETCH_NOP | OP_NOP | STORE_RET) ; C9 RET
3960 .dw (FETCH_DIR16| OP_IFZ | STORE_PC ) ; CA nn nn JP Z,nn
3961 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; CB (Z80 specific)
3962 .dw (FETCH_DIR16| OP_IFZ | STORE_CALL) ; CC nn nn CALL Z,nn
3963 .dw (FETCH_DIR16| OP_NOP | STORE_CALL) ; CD nn nn CALL nn
3964 .dw (FETCH_DIR8 | OP_ADCA | STORE_A ) ; CE nn ADC A,n
3965 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; CF RST 8H
3966 .dw (FETCH_NOP | OP_IFNC | STORE_RET) ; D0 RET NC
3967 .dw (FETCH_NOP | OP_POP16 | STORE_DE ) ; D1 POP DE
3968 .dw (FETCH_DIR16| OP_IFNC | STORE_PC ) ; D2 nn nn JP NC,nn
3969 .dw (FETCH_DIR8 | OP_OUTA | STORE_NOP) ; D3 nn OUT (n),A
3970 .dw (FETCH_DIR16| OP_IFNC | STORE_CALL) ; D4 nn nn CALL NC,nn
3971 .dw (FETCH_DE | OP_PUSH16 | STORE_NOP) ; D5 PUSH DE
3972 .dw (FETCH_DIR8 | OP_SUBFA | STORE_A ) ; D6 nn SUB n
3973 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; D7 RST 10H
3974 .dw (FETCH_NOP | OP_IFC | STORE_RET) ; D8 RET C
3975 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; D9 EXX (Z80)
3976 .dw (FETCH_DIR16| OP_IFC | STORE_PC ) ; DA nn nn JP C,nn
3977 .dw (FETCH_DIR8 | OP_IN | STORE_A ) ; DB nn IN A,(n)
3978 .dw (FETCH_DIR16| OP_IFC | STORE_CALL) ; DC nn nn CALL C,nn
3979 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; DD (Z80)
3980 .dw (FETCH_DIR8 | OP_SBCFA | STORE_A ) ; DE nn SBC A,n
3981 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; DF RST 18H
3982 .dw (FETCH_NOP | OP_IFPO | STORE_RET) ; E0 RET PO
3983 .dw (FETCH_NOP | OP_POP16 | STORE_HL ) ; E1 POP HL
3984 .dw (FETCH_DIR16| OP_IFPO | STORE_PC ) ; E2 nn nn JP PO,nn
3985 .dw (FETCH_MSP | OP_EXHL | STORE_MSP) ; E3 EX (SP),HL
3986 .dw (FETCH_DIR16| OP_IFPO | STORE_CALL) ; E4 nn nn CALL PO,nn
3987 .dw (FETCH_HL | OP_PUSH16 | STORE_NOP) ; E5 PUSH HL
3988 .dw (FETCH_DIR8 | OP_ANDA | STORE_A ) ; E6 nn AND n
3989 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; E7 RST 20H
3990 .dw (FETCH_NOP | OP_IFPE | STORE_RET) ; E8 RET PE
3991 .dw (FETCH_HL | OP_NOP | STORE_PC ) ; E9 JP (HL)
3992 .dw (FETCH_DIR16| OP_IFPE | STORE_PC ) ; EA nn nn JP PE,nn
3993 .dw (FETCH_DE | OP_EXHL | STORE_DE ) ; EB EX DE,HL
3994 .dw (FETCH_DIR16| OP_IFPE | STORE_CALL) ; EC nn nn CALL PE,nn
3995 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; ED (Z80 specific)
3996 .dw (FETCH_DIR8 | OP_XORA | STORE_A ) ; EE nn XOR n
3997 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; EF RST 28H
3998 .dw (FETCH_NOP | OP_IFP | STORE_RET) ; F0 RET P
3999 .dw (FETCH_NOP | OP_POP16 | STORE_AF ) ; F1 POP AF
4000 .dw (FETCH_DIR16| OP_IFP | STORE_PC ) ; F2 nn nn JP P,nn
4001 .dw (FETCH_NOP | OP_DI | STORE_NOP) ; F3 DI
4002 .dw (FETCH_DIR16| OP_IFP | STORE_CALL) ; F4 nn nn CALL P,nn
4003 .dw (FETCH_AF | OP_PUSH16 | STORE_NOP) ; F5 PUSH AF
4004 .dw (FETCH_DIR8 | OP_ORA | STORE_A ) ; F6 nn OR n
4005 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; F7 RST 30H
4006 .dw (FETCH_NOP | OP_IFM | STORE_RET) ; F8 RET M
4007 .dw (FETCH_HL | OP_NOP | STORE_SP ) ; F9 LD SP,HL
4008 .dw (FETCH_DIR16| OP_IFM | STORE_PC ) ; FA nn nn JP M,nn
4009 .dw (FETCH_NOP | OP_EI | STORE_NOP) ; FB EI
4010 .dw (FETCH_DIR16| OP_IFM | STORE_CALL) ; FC nn nn CALL M,nn
4011 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; FD (Z80 specific)
4012 .dw (FETCH_DIR8 | OP_SUBFA | STORE_NOP) ; FE nn CP n
4013 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; FF RST 38H
4014
4015 ; vim:set ts=8 noet nowrap
4016