]> cloudbase.mooo.com Git - avrcpm.git/blob - avrcpm/avr/z80.asm
Initial import of the original source from Sprite_tm:
[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
20 ;FUSE_H=0xDF
21 ;FUSE_L=0xF7
22 .include "m88def.inc"
23 ;device ATmega88
24
25 .equ MMC_DEBUG = 0
26 .equ INS_DEBUG = 0
27 .equ MEMTEST = 0
28 .equ BOOTWAIT = 0
29 .equ PORT_DEBUG = 0
30 .equ DISK_DEBUG = 0
31 .equ MEMFILL_CB = 1
32 .equ STACK_DBG = 0
33 .equ PRINT_PC = 0
34
35 ;Port declarations
36
37 ; Port D
38 .equ rxd = 0
39 .equ txd = 1
40 .equ ram_oe = 2
41 .equ ram_a8 = 3
42 .equ mmc_cs = 4
43 .equ ram_a5 = 5
44 .equ ram_a6 = 6
45 .equ ram_a7 = 7
46
47 ;Port B
48 .equ ram_a4 = 0
49 .equ ram_a3 = 1
50 .equ ram_a2 = 2
51 .equ ram_a1 = 3
52 .equ mmc_mosi= 3
53 .equ ram_a0 = 4
54 .equ mmc_miso= 4
55 .equ ram_ras= 5
56 .equ mmc_sck= 5
57
58 ;Port C
59 .equ ram_d1 = 0
60 .equ ram_w = 1
61 .equ ram_d2 = 2
62 .equ ram_d4 = 3
63 .equ ram_d3 = 4
64 .equ ram_cas= 5
65
66
67 ;Flag bits in z_flags
68 .equ ZFL_S = 7
69 .equ ZFL_Z = 6
70 .equ ZFL_H = 4
71 .equ ZFL_P = 2
72 .equ ZFL_N = 1
73 .equ ZFL_C = 0
74
75 ;Register definitions
76 .def z_a = r2
77 .def z_b = r3
78 .def z_c = r4
79 .def z_d = r5
80 .def z_e = r6
81 .def z_l = r7
82 .def z_h = r8
83 .def z_spl = r9
84 .def z_sph = r10
85
86 .def dsk_trk= r11
87 .def dsk_sec= r12
88 .def dsk_dmah= r13
89 .def dsk_dmal= r14
90
91 .def parityb= r15
92
93 .def temp = R16 ;The temp register
94 .def temp2 = R17 ;Second temp register
95 .def trace = r18
96 .def opl = r19
97 .def oph = r20
98 .def adrl = r21
99 .def adrh = r22
100 .def insdecl= r23
101 .def z_pcl = r24
102 .def z_pch = r25
103 .def insdech= r26
104 .def z_flags= r27
105
106
107 ;SRAM
108 ;Sector buffer for 512 byte reads/writes from/to SD-card
109 .equ sectbuff = 0x200
110
111 .org 0
112 rjmp start ; reset vector
113 nop ; ext int 0
114 nop ; ext int 1
115 nop ; pcint0
116 nop ; pcint1
117 nop ; pcint2
118 nop ; wdt
119 rjmp refrint ; tim2cmpa
120 nop ; tim2cmpb
121 nop ; tim2ovf
122
123 start:
124 ldi temp,low(RAMEND) ; top of memory
125 out SPL,temp ; init stack pointer
126 ldi temp,high(RAMEND) ; top of memory
127 out SPH,temp ; init stack pointer
128
129 ; - Kill wdt
130 wdr
131 ldi temp,0
132 out MCUSR,temp
133 ldi temp,0x18
134 sts WDTCSR,temp
135 ldi temp,0x10
136 sts WDTCSR,temp
137
138
139 ; - Setup Ports
140 ldi temp,$3F
141 out DDRB,temp
142 ldi temp,$FE
143 out DDRD,temp
144 ldi temp,$22
145 out DDRC,temp
146
147 sbi portc,ram_w
148 sbi portc,ram_cas
149 sbi portb,ram_ras
150 sbi portd,ram_oe
151 sbi portd,mmc_cs
152
153
154 ; - Init serial port
155 ldi temp,$18
156 sts ucsr0b,temp
157 ldi temp,$6
158 sts ucsr0c,temp
159 ldi temp,32
160 sts ubrr0l,temp
161 ldi temp,0
162 sts ubrr0h,temp
163
164 ;Init timer2. Refresh-call should happen every (8ms/512)=312 cycles.
165 ldi temp,2
166 sts tccr2a,temp
167 ldi temp,2 ;clk/8
168 sts tccr2b,temp
169 ldi temp,39 ;=312 cycles
170 sts ocr2a,temp
171 ldi temp,2
172 sts timsk2,temp
173 sei
174
175 .if BOOTWAIT
176 push temp
177 ldi temp,0
178 bootwait1:
179 push temp
180 ldi temp,0
181 bootwait2:
182 dec temp
183 brne bootwait2
184 pop temp
185 dec temp
186 brne bootwait1
187
188 .endif
189
190 rcall printstr
191 .db "CPM on an AVR, v1.0",13,0
192
193
194 rcall printstr
195 .db "Initing mmc...",13,0
196 rcall mmcInit
197
198
199 .if MEMTEST
200 rcall printstr
201 .db "Testing RAM...",13,0
202
203 ;Fill RAM
204 ldi adrl,0
205 ldi adrh,0
206 ramtestw:
207 mov temp,adrh
208 eor temp,adrl
209 rcall memwritebyte
210 ldi temp,1
211 ldi temp2,0
212 add adrl,temp
213 adc adrh,temp2
214 brcc ramtestw
215
216 ;re-read RAM
217 ldi adrl,0
218 ldi adrh,0
219 ramtestr:
220 rcall memreadbyte
221 mov temp2,adrh
222 eor temp2,adrl
223 cp temp,temp2
224 breq ramtestrok
225 rcall printhex
226 ldi temp,'<'
227 rcall uartPutc
228 mov temp,adrh
229 eor temp,adrl
230 rcall printhex
231 ldi temp,'@'
232 rcall uartPutc
233 mov temp,adrh
234 rcall printhex
235 mov temp,adrl
236 rcall printhex
237 ldi temp,13
238 rcall uartPutc
239 ramtestrok:
240 ldi temp,1
241 ldi temp2,0
242 add adrl,temp
243 adc adrh,temp2
244 brcc ramtestr
245
246 .endif
247
248 .if MEMFILL_CB
249 ;Fill ram with cbs, which (for now) will trigger an invalid opcode error.
250 ldi adrl,0
251 ldi adrh,0
252 ramfillw:
253 ldi temp,0xcb
254 rcall memwritebyte
255 ldi temp,1
256 ldi temp2,0
257 add adrl,temp
258 adc adrh,temp2
259 brcc ramfillw
260 .endif
261
262
263
264 ;Load initial sector from MMC (512 bytes)
265 ldi adrh,0
266 ldi adrl,0
267 rcall mmcReadSect
268
269 ;Save to Z80 RAM (only 128 bytes because that's retro)
270 ldi zl,low(sectbuff)
271 ldi zh,high(sectbuff)
272 ldi adrh,0x20
273 ldi adrl,0x00
274 iplwriteloop:
275 ld temp,z+
276 push zh
277 push zl
278 rcall memWriteByte
279 pop zl
280 pop zh
281 ldi temp,1
282 ldi temp2,0
283 add adrl,temp
284 adc adrh,temp2
285 cpi zl,low(sectbuff+128)
286 brne iplwriteloop
287 cpi zh,high(sectbuff+128)
288 brne iplwriteloop
289
290
291
292 ;Init z80
293 ldi temp,0x00
294 mov z_pcl,temp
295 ldi temp,0x20
296 mov z_pch,temp
297
298 ldi trace,0
299 rcall printstr
300 .db 13,"Ok, CPU is live!",13,0
301
302 main:
303 ldi trace,0
304 cpi z_pch,1
305 brlo notraceon
306 cpi z_pch,$dc
307 brsh notraceon
308 ldi trace,1
309 notraceon:
310
311
312 .if PRINT_PC
313 cpi z_pch,1
314 brlo noprintpc
315 cpi z_pch,0xdc
316 brsh noprintpc
317
318 rcall printstr
319 .db "PC=",0
320 mov temp,z_pch
321 rcall printhex
322 mov temp,z_pcl
323 rcall printhex
324 ldi temp,10
325 rcall uartputc
326 noprintpc:
327 .endif
328
329 ; *** Stage 1: Fetch next opcode
330 mov adrl,z_pcl
331 mov adrh,z_pch
332 rcall memReadByte
333 adiw z_pcl,1
334
335
336 .if INS_DEBUG
337 cpi trace,0
338 breq notrace1
339 rcall printstr
340 .db "PC=",0
341 push temp
342 mov temp,adrh
343 rcall printhex
344 mov temp,adrl
345 rcall printhex
346 pop temp
347 rcall printstr
348 .db ", opcode=",0
349 rcall printhex
350 notrace1:
351 .endif
352
353 ; *** Stage 2: Decode it using the ins_table.
354 ldi temp2,0
355 ldi zl,low(inst_table*2)
356 ldi zh,high(inst_table*2)
357 add zl,temp
358 adc zh,temp2
359 add zl,temp
360 adc zh,temp2
361 lpm insdecl,Z+
362 lpm insdech,Z
363
364 .if INS_DEBUG
365 cpi trace,0
366 breq notrace2
367 rcall printstr
368 .db ", decoded=",0
369 mov temp,insdech
370 rcall printhex
371 mov temp,insdecl
372 rcall printhex
373 rcall printstr
374 .db ".",13,0
375 notrace2:
376 .endif
377
378 ; *** Stage 3: Fetch operand. Use the fetch jumptable for this.
379 mov temp,insdecl
380 andi temp,0x1F
381 cpi temp,0
382 breq nofetch
383 ldi temp2,0
384 lsl temp
385 ldi zl,low(fetchjumps*2)
386 ldi zh,high(fetchjumps*2)
387 add zl,temp
388 adc zh,temp2
389
390 lpm temp,Z+
391 lpm temp2,Z
392 mov zl,temp
393 mov zh,temp2
394 icall
395
396 .if INS_DEBUG
397 cpi trace,0
398 breq notrace3
399 rcall printstr
400 .db "pre: oph:l=",0
401 mov temp,oph
402 rcall printhex
403 mov temp,opl
404 rcall printhex
405 rcall printstr
406 .db " -- ",0
407 notrace3:
408 .endif
409
410 nofetch:
411 ; *** Stage 4: Execute operation :) Use the op jumptable for this.
412 mov temp,insdech
413 andi temp,0xFC
414 lsr temp
415 cpi temp,0
416 breq nooper
417 ldi zl,low(opjumps*2)
418 ldi zh,high(opjumps*2)
419 ldi temp2,0
420 add zl,temp
421 adc zh,temp2
422 lpm temp,Z+
423 lpm temp2,Z
424 mov zl,temp
425 mov zh,temp2
426 icall
427
428 .if INS_DEBUG
429 cpi trace,0
430 breq notrace4
431 rcall printstr
432 .db ",post:oph:l=",0
433 mov temp,oph
434 rcall printhex
435 mov temp,opl
436 rcall printhex
437 notrace4:
438 .endif
439
440 nooper:
441 ; *** Stage 5: Store operand. Use the store jumptable for this.
442 swap insdecl
443 swap insdech
444 mov temp,insdecl
445 andi temp,0x0E
446 andi insdech,0x30
447 or temp,insdech
448 cpi temp,0
449 breq nostore
450 ldi zl,low(storejumps*2)
451 ldi zh,high(storejumps*2)
452 ldi temp2,0
453 add zl,temp
454 adc zh,temp2
455 lpm temp,Z+
456 lpm temp2,Z
457 mov zl,temp
458 mov zh,temp2
459 icall
460
461 .if INS_DEBUG
462 cpi trace,0
463 breq notrace5
464 rcall printstr
465 .db ", stored.",0
466 notrace5:
467 .endif
468
469 nostore:
470
471 .if INS_DEBUG
472 cpi trace,0
473 breq notrace6
474 rcall printstr
475 .db 13,0
476 notrace6:
477 .endif
478
479 ;All done. Neeeext!
480 rjmp main
481
482
483 ; ----------------Virtual peripherial interface ------
484
485 ;The hw is modelled to make writing a CPM BIOS easier.
486 ;Ports:
487 ;0 - Con status. Returns 0xFF if the UART has a byte, 0 otherwise.
488 ;1 - Console input, aka UDR.
489 ;2 - Console output
490 ;16 - Track select
491 ;18 - Sector select
492 ;20 - Write addr l
493 ;21 - Write addr h
494 ;22 - Trigger - write 1 to read, 2 to write a sector using the above info.
495 ; This will automatically move track, sector and dma addr to the next sector.
496
497 ;Called with port in temp2. Should return value in temp.
498 portRead:
499 cpi temp2,0
500 breq conStatus
501 cpi temp2,1
502 breq conInp
503 ret
504
505 ;Called with port in temp2 and value in temp.
506 portWrite:
507 cpi temp2,0
508 breq dbgOut
509 cpi temp2,2
510 breq conOut
511 cpi temp2,16
512 breq dskTrackSel
513 cpi temp2,18
514 breq dskSecSel
515 cpi temp2,20
516 breq dskDmaL
517 cpi temp2,21
518 breq dskDmaH
519 cpi temp2,22
520 breq dskDoIt
521 ret
522
523
524 conStatus:
525 lds temp2,UCSR0A
526 ldi temp,0
527 sbrc temp2,7
528 ldi temp,0xff
529 ret
530
531 conInp:
532 rcall uartGetc
533 ret
534
535 dbgOut:
536 rcall printstr
537 .db "Debug: ",0
538 rcall printhex
539 rcall printstr
540 .db 13,0
541 ret
542
543 conOut:
544 rcall uartputc
545 ret
546
547 dskTrackSel:
548 mov dsk_trk,temp
549 ret
550
551 dskSecSel:
552 mov dsk_sec,temp
553 ret
554
555 dskDmal:
556 mov dsk_dmal,temp
557 ret
558
559 dskDmah:
560 mov dsk_dmah,temp
561 ret
562
563 dskDoIt:
564 .if DISK_DEBUG
565 push temp
566 rcall printstr
567 .db "Disk read: track ",0
568 mov temp,dsk_trk
569 rcall printhex
570 rcall printstr
571 .db " sector ",0
572 mov temp,dsk_sec
573 rcall printhex
574 rcall printstr
575 .db " dma-addr ",0
576 mov temp,dsk_dmah
577 rcall printhex
578 mov temp,dsk_dmal
579 rcall printhex
580 rcall printstr
581 .db ".",13,0
582 pop temp
583 .endif
584
585 ;First, convert track/sector to an LBA address (in 128byte blocks)
586 push temp
587 mov adrl,dsk_sec
588 ldi adrh,0
589 mov temp2,dsk_trk
590 dskXlateLoop:
591 cpi temp2,0
592 breq dskXlateLoopEnd
593 ldi temp,26
594 add adrl,temp
595 ldi temp,0
596 adc adrh,temp
597 dec temp2
598 rjmp dskXlateLoop
599 dskXlateLoopEnd:
600 pop temp
601
602 ;Now, see what has to be done.
603 cpi temp,1
604 breq dskDoItRead
605 cpi temp,2
606 breq dskDoItWrite
607
608 dskDoItRead:
609 push adrl
610 ;Convert from 128-byte LBA blocks to 512-byte LBA blocks
611 lsr adrh
612 ror adrl
613 lsr adrh
614 ror adrl
615 ;Read 512-byte sector
616 rcall mmcReadSect
617 pop adrl
618
619 ;Now, move the correct portion of the sector from AVR ram to Z80 ram
620 ldi zl,low(sectbuff)
621 ldi zh,high(sectbuff)
622 ldi temp,128
623 ldi temp2,0
624 sbrc adrl,0
625 add zl,temp
626 sbrc adrl,0
627 adc zh,temp2
628 sbrc adrl,1
629 inc zh
630
631 mov adrh,dsk_dmah
632 mov adrl,dsk_dmal
633
634 ldi temp2,128
635 dskDoItReadMemLoop:
636 push temp2
637 ld temp,z+
638 push zh
639 push zl
640 rcall memWriteByte
641 pop zl
642 pop zh
643 ldi temp,1
644 ldi temp2,0
645 add adrl,temp
646 adc adrh,temp2
647 pop temp2
648 dec temp2
649 brne dskDoItReadMemLoop
650 ret
651
652 dskDoItWrite:
653 ;The write routines is a bit naive: it'll read the 512-byte sector the 128byte CPM-sector
654 ;resides in into memory, will overwrite the needed 128 byte with the Z80s memory buffer
655 ;and will then write it back to disk. In theory, this would mean that every 512 bytes
656 ;written will take 4 write cycles, while theoretically the writes could be deferred so we
657 ;would only have to do one write cycle.
658
659 .if DISK_DEBUG
660 push temp
661 rcall printstr
662 .db "Disk write: track ",0
663 mov temp,dsk_trk
664 rcall printhex
665 rcall printstr
666 .db " sector ",0
667 mov temp,dsk_sec
668 rcall printhex
669 rcall printstr
670 .db " dma-addr ",0
671 mov temp,dsk_dmah
672 rcall printhex
673 mov temp,dsk_dmal
674 rcall printhex
675 rcall printstr
676 .db ".",13,0
677 pop temp
678 .endif
679
680
681 push adrl
682 push adrh
683 ;Convert from 128-byte LBA blocks to 512-byte LBA blocks
684 lsr adrh
685 ror adrl
686 lsr adrh
687 ror adrl
688 ;Read 512-byte sector
689 rcall mmcReadSect
690 pop adrh
691 pop adrl
692
693 push adrl
694 push adrh
695
696 ;Copy the data from the Z80 DMA buffer in external memory to the right place in the
697 ;sector buffer.
698 ;Now, move the correct portion of the sector from AVR ram to Z80 ram
699 ldi zl,low(sectbuff)
700 ldi zh,high(sectbuff)
701 ldi temp,128
702 ldi temp2,0
703 sbrc adrl,0
704 add zl,temp
705 sbrc adrl,0
706 adc zh,temp2
707 sbrc adrl,1
708 inc zh
709 mov adrh,dsk_dmah
710 mov adrl,dsk_dmal
711 ldi temp2,128
712 dskDoItWriteMemLoop:
713 push temp2
714
715 push zh
716 push zl
717 rcall memReadByte
718 pop zl
719 pop zh
720 st z+,temp
721 ldi temp,1
722 ldi temp2,0
723 add adrl,temp
724 adc adrh,temp2
725
726 pop temp2
727 dec temp2
728 brne dskDoItWriteMemLoop
729
730 pop adrh
731 pop adrl
732
733 ;Convert from 128-byte LBA blocks to 512-byte LBA blocks
734 lsr adrh
735 ror adrl
736 lsr adrh
737 ror adrl
738 ;Write the sector back.
739 rcall mmcWriteSect
740
741 ;All done :)
742 ret
743
744 ; ----------------- MMC/SD routines ------------------
745
746 mmcByteNoSend:
747 ldi temp,0xff
748 mmcByte:
749
750 .if MMC_DEBUG
751 push zl
752 push zh
753 rcall printstr
754 .db "MMC: <--",0
755 rcall printhex
756 .endif
757
758 out SPDR,temp
759 mmcWrByteW:
760 in temp,SPSR
761 sbrs temp,7
762 rjmp mmcWrByteW
763 in temp,SPDR
764
765 .if MMC_DEBUG
766 push temp
767 rcall printstr
768 .db ", -->",0
769 rcall printhex
770 rcall printstr
771 .db ".",13,0
772 pop temp
773 pop zh
774 pop zl
775 .endif
776 ret
777
778
779 ;Wait till the mmc answers with the response in temp2, or till a timeout happens.
780 mmcWaitResp:
781 ldi zl,0
782 ldi zh,0
783 mmcWaitResploop:
784 rcall mmcByteNoSend
785 cpi temp,0xff
786 brne mmcWaitResploopEnd
787 adiw zl,1
788 cpi zh,255
789 breq mmcWaitErr
790 rjmp mmcWaitResploop
791 mmcWaitResploopEnd:
792 ret
793
794
795 mmcWaitErr:
796 mov temp,temp2
797 rcall printhex
798 rcall printstr
799 .db ": Error: MMC resp timeout!",13,0
800 rjmp resetAVR
801
802 mmcInit:
803 ldi temp,0x53
804 out SPCR,temp
805
806 ;Init start: send 80 clocks with cs disabled
807 sbi portd,mmc_cs
808
809 ldi temp2,20
810 mmcInitLoop:
811 mov temp,temp2
812 rcall mmcByte
813 dec temp2
814 brne mmcInitLoop
815
816 cbi portd,mmc_cs
817 rcall mmcByteNoSend
818 rcall mmcByteNoSend
819 rcall mmcByteNoSend
820 rcall mmcByteNoSend
821 rcall mmcByteNoSend
822 rcall mmcByteNoSend
823 sbi portd,mmc_cs
824 rcall mmcByteNoSend
825 rcall mmcByteNoSend
826 rcall mmcByteNoSend
827 rcall mmcByteNoSend
828
829 ;Send init command
830 cbi portd,mmc_cs
831 ldi temp,0xff ;dummy
832 rcall mmcByte
833 ldi temp,0xff ;dummy
834 rcall mmcByte
835 ldi temp,0x40 ;cmd
836 rcall mmcByte
837 ldi temp,0 ;pxh
838 rcall mmcByte
839 ldi temp,0 ;pxl
840 rcall mmcByte
841 ldi temp,0 ;pyh
842 rcall mmcByte
843 ldi temp,0 ;pyl
844 rcall mmcByte
845 ldi temp,0x95 ;crc
846 rcall mmcByte
847 ldi temp,0xff ;return byte
848 rcall mmcByte
849
850 ldi temp2,0
851 rcall mmcWaitResp
852
853 sbi portd,mmc_cs
854 rcall mmcByteNoSend
855
856
857 ;Read OCR till card is ready
858 ldi temp2,150
859 mmcInitOcrLoop:
860 push temp2
861
862 cbi portd,mmc_cs
863 ldi temp,0xff ;dummy
864 rcall mmcByte
865 ldi temp,0x41 ;cmd
866 rcall mmcByte
867 ldi temp,0 ;pxh
868 rcall mmcByte
869 ldi temp,0 ;pxl
870 rcall mmcByte
871 ldi temp,0 ;pyh
872 rcall mmcByte
873 ldi temp,0 ;pyl
874 rcall mmcByte
875 ldi temp,0x95 ;crc
876 rcall mmcByte
877 rcall mmcByteNoSend
878
879 ldi temp2,1
880 rcall mmcWaitResp
881 cpi temp,0
882 breq mmcInitOcrLoopDone
883
884 sbi portd,mmc_cs
885 rcall mmcByteNoSend
886
887 pop temp2
888 dec temp2
889 cpi temp2,0
890 brne mmcInitOcrLoop
891
892 ldi temp,4
893 rjmp mmcWaitErr
894
895 mmcInitOcrLoopDone:
896 pop temp2
897 sbi portd,mmc_cs
898 rcall mmcByteNoSend
899
900 ldi temp,0
901 out SPCR,temp
902 ret
903
904
905 ;Call this with adrh:adrl = sector number
906 ;16bit lba address means a max reach of 32M.
907 mmcReadSect:
908 ldi temp,0x50
909 out SPCR,temp
910
911 cbi portd,mmc_cs
912 rcall mmcByteNoSend
913 ldi temp,0x51 ;cmd (read sector)
914 rcall mmcByte
915 ldi temp,0
916 lsl adrl
917 rol adrh
918 rol temp
919 rcall mmcByte
920 mov temp,adrh ;pxl
921 rcall mmcByte
922 mov temp,adrl ;pyh
923 rcall mmcByte
924 ldi temp,0 ;pyl
925 rcall mmcByte
926 ldi temp,0x95 ;crc
927 rcall mmcByte
928 ldi temp,0xff ;return byte
929 rcall mmcByte
930
931 ;resp
932 ldi temp2,2
933 rcall mmcWaitResp
934
935 ;data token
936 ldi temp2,3
937 rcall mmcWaitResp
938
939 ;Read sector to AVR RAM
940 ldi zl,low(sectbuff)
941 ldi zh,high(sectbuff)
942 mmcreadloop:
943 rcall mmcByteNoSend
944 st z+,temp
945 cpi zl,low(sectbuff+512)
946 brne mmcreadloop
947 cpi zh,high(sectbuff+512)
948 brne mmcreadloop
949
950 ;CRC
951 rcall mmcByteNoSend
952 rcall mmcByteNoSend
953
954 sbi portd,mmc_cs
955 rcall mmcByteNoSend
956
957 ldi temp,0
958 out SPCR,temp
959 ret
960
961
962 ;Call this with adrh:adrl = sector number
963 ;16bit lba address means a max reach of 32M.
964 mmcWriteSect:
965 ldi temp,0x50
966 out SPCR,temp
967
968 cbi portd,mmc_cs
969 rcall mmcByteNoSend
970
971 ldi temp,0x58 ;cmd (write sector)
972 rcall mmcByte
973 ldi temp,0
974 lsl adrl
975 rol adrh
976 rol temp
977 rcall mmcByte
978 mov temp,adrh ;pxl
979 rcall mmcByte
980 mov temp,adrl ;pyh
981 rcall mmcByte
982 ldi temp,0 ;pyl
983 rcall mmcByte
984 ldi temp,0x95 ;crc
985 rcall mmcByte
986 ldi temp,0xff ;return byte
987 rcall mmcByte
988
989 ;resp
990 ldi temp2,1
991 rcall mmcWaitResp
992
993 ;Send data token
994 ldi temp,0xfe
995 rcall mmcByte
996
997 ;Write sector from AVR RAM
998 ldi zl,low(sectbuff)
999 ldi zh,high(sectbuff)
1000 mmcwriteloop:
1001 ld temp,z+
1002 rcall mmcByte
1003 cpi zl,low(sectbuff+512)
1004 brne mmcwriteloop
1005 cpi zh,high(sectbuff+512)
1006 brne mmcwriteloop
1007
1008 ;CRC
1009 rcall mmcByteNoSend
1010 rcall mmcByteNoSend
1011
1012 ;Status. Ignored for now.
1013 rcall mmcByteNoSend
1014
1015 ;Wait till the mmc has written everything
1016 mmcwaitwritten:
1017 rcall mmcByteNoSend
1018 cpi temp,0xff
1019 brne mmcwaitwritten
1020
1021 sbi portd,mmc_cs
1022 rcall mmcByteNoSend
1023
1024 ldi temp,0
1025 out SPCR,temp
1026 ret
1027
1028
1029 ;Set up wdt to time out after 1 sec.
1030 resetAVR:
1031 cli
1032 ldi temp,0x10
1033 sts WDTCSR,temp
1034 ldi temp,0x1f
1035 sts WDTCSR,temp
1036 resetwait:
1037 rjmp resetwait
1038
1039 ; ------------------ DRAM routines -------------
1040
1041 ;Sends the address in zh:zl to the ram
1042 dram_setaddr:
1043 push temp
1044 in temp,portd
1045 andi temp,0x17
1046 out portd,temp
1047 in temp,portb
1048 andi temp,0xE0
1049 out portb,temp
1050 sbrc zl,0
1051 sbi portb,ram_a0
1052 sbrc zl,1
1053 sbi portb,ram_a1
1054 sbrc zl,2
1055 sbi portb,ram_a2
1056 sbrc zl,3
1057 sbi portb,ram_a3
1058 sbrc zl,4
1059 sbi portb,ram_a4
1060 sbrc zl,5
1061 sbi portd,ram_a5
1062 sbrc zl,6
1063 sbi portd,ram_a6
1064 sbrc zl,7
1065 sbi portd,ram_a7
1066 sbrc zh,0
1067 sbi portd,ram_a8
1068 pop temp
1069 ret
1070
1071 dram_getnibble:
1072 andi temp,0xf0
1073 sbic pinc,ram_d1
1074 ori temp,0x1
1075 sbic pinc,ram_d2
1076 ori temp,0x2
1077 sbic pinc,ram_d3
1078 ori temp,0x4
1079 sbic pinc,ram_d4
1080 ori temp,0x8
1081 ret
1082
1083 dram_sendnibble:
1084 push temp2
1085 in temp2,portc
1086 andi temp2,0xE2
1087
1088 sbrc temp,0
1089 ori temp2,(1<<ram_d1)
1090 sbrc temp,1
1091 ori temp2,(1<<ram_d2)
1092 sbrc temp,2
1093 ori temp2,(1<<ram_d3)
1094 sbrc temp,3
1095 ori temp2,(1<<ram_d4)
1096
1097 out portc,temp2
1098 pop temp2
1099 ret
1100
1101
1102 ;Loads the byte on address adrh:adrl into temp.
1103 dram_read:
1104 cli
1105 mov zl,adrh
1106 ldi zh,0
1107 mov temp2,adrl
1108 lsl temp2
1109 rol zl
1110 rol zh
1111 ;z=addr[15-7]
1112 rcall dram_setaddr
1113 cbi portb,ram_ras
1114
1115 ldi zh,0
1116 mov zl,adrl
1117 andi zl,0x7F
1118 rcall dram_setaddr
1119 nop
1120 cbi portc,ram_cas
1121 nop
1122 nop
1123 cbi portd,ram_oe
1124 nop
1125 rcall dram_getnibble
1126 sbi portd,ram_oe
1127 swap temp
1128 sbi portc,ram_cas
1129
1130 ldi zh,0
1131 mov zl,adrl
1132 ori zl,0x80
1133 rcall dram_setaddr
1134 nop
1135 cbi portc,ram_cas
1136 nop
1137 cbi portd,ram_oe
1138 nop
1139 nop
1140 rcall dram_getnibble
1141
1142 sbi portd,ram_oe
1143 sbi portc,ram_cas
1144 sbi portb,ram_ras
1145 sei
1146 ret
1147
1148 ;Writes the byte in temp to adrh:adrl
1149 dram_write:
1150 cli
1151
1152 in temp2,ddrc
1153 ori temp2,0x1d
1154 out ddrc,temp2
1155
1156 rcall dram_sendnibble
1157
1158 mov zl,adrh
1159 ldi zh,0
1160 mov temp2,adrl
1161 lsl temp2
1162 rol zl
1163 rol zh
1164 ;z=addr[15-7]
1165 rcall dram_setaddr
1166 nop
1167 nop
1168 cbi portb,ram_ras
1169
1170 ldi zh,0
1171 mov zl,adrl
1172 ori zl,0x80
1173 rcall dram_setaddr
1174 nop
1175 nop
1176 cbi portc,ram_cas
1177 nop
1178 nop
1179 cbi portc,ram_w
1180 nop
1181 nop
1182 nop
1183 sbi portc,ram_w
1184 sbi portc,ram_cas
1185
1186
1187 ldi zh,0
1188 mov zl,adrl
1189 andi zl,0x7F
1190 rcall dram_setaddr
1191 swap temp
1192 rcall dram_sendnibble
1193 cbi portc,ram_cas
1194 nop
1195 nop
1196 cbi portc,ram_w
1197 nop
1198 nop
1199 sbi portc,ram_w
1200 nop
1201 nop
1202 sbi portc,ram_cas
1203 sbi portb,ram_ras
1204
1205 in temp,ddrc
1206 andi temp,0xE2
1207 out ddrc,temp
1208 in temp,portc
1209 andi temp,0xE2
1210 out portc,temp
1211 sei
1212 ret
1213
1214 refrint:
1215 nop
1216 nop
1217 nop
1218 cbi portc,ram_cas
1219 nop
1220 nop
1221 nop
1222 nop
1223 cbi portb,ram_ras
1224 nop
1225 nop
1226 nop
1227 nop
1228 sbi portc,ram_cas
1229 nop
1230 nop
1231 nop
1232 nop
1233 sbi portb,ram_ras
1234 nop
1235 nop
1236 nop
1237 nop
1238 nop
1239 reti
1240
1241
1242
1243
1244 ; --------------- Debugging stuff ---------------
1245
1246 ;Prints the lower nibble of temp in hex to the uart
1247 printhexn:
1248 push temp
1249 andi temp,0xf
1250 cpi temp,0xA
1251 brlo printhexn_isno
1252 subi temp,-('A'-10)
1253 rcall uartputc
1254 pop temp
1255 ret
1256 printhexn_isno:
1257 subi temp,-'0'
1258 rcall uartputc
1259 pop temp
1260 ret
1261
1262 ;Prints temp in hex to the uart
1263 printhex:
1264 swap temp
1265 rcall printhexn
1266 swap temp
1267 rcall printhexn
1268 ret
1269
1270 ;Prints the zero-terminated string following the call statement. WARNING: Destroys temp.
1271 printstr:
1272 pop zh
1273 pop zl
1274 push temp
1275
1276 lsl zl
1277 rol zh
1278
1279 printstr_loop:
1280 lpm temp,z+
1281 cpi temp,0
1282 breq printstr_end
1283 rcall uartputc
1284 cpi temp,13
1285 brne printstr_loop
1286 ldi temp,10
1287 rcall uartputc
1288 rjmp printstr_loop
1289
1290 printstr_end:
1291 adiw zl,1
1292 lsr zh
1293 ror zl
1294
1295 pop temp
1296 push zl
1297 push zh
1298 ret
1299
1300
1301 ; --------------- AVR HW <-> Z80 periph stuff ------------------
1302
1303 .equ memReadByte = dram_read
1304 .equ memWriteByte = dram_write
1305
1306
1307
1308 ;Fetches a char from the uart to temp. If none available, waits till one is.
1309 uartgetc:
1310 lds temp,ucsr0a
1311 sbrs temp,7
1312 rjmp uartgetc
1313 lds temp,udr0
1314 ret
1315
1316 ;Sends a char from temp to the uart.
1317 uartputc:
1318 push temp
1319 uartputc_l:
1320 lds temp,ucsr0a
1321 sbrs temp,5
1322 rjmp uartputc_l
1323 pop temp
1324 sts udr0,temp
1325 ret
1326
1327 ; ------------ Fetch phase stuff -----------------
1328
1329 .equ FETCH_NOP = (0<<0)
1330 .equ FETCH_A = (1<<0)
1331 .equ FETCH_B = (2<<0)
1332 .equ FETCH_C = (3<<0)
1333 .equ FETCH_D = (4<<0)
1334 .equ FETCH_E = (5<<0)
1335 .equ FETCH_H = (6<<0)
1336 .equ FETCH_L = (7<<0)
1337 .equ FETCH_AF = (8<<0)
1338 .equ FETCH_BC = (9<<0)
1339 .equ FETCH_DE = (10<<0)
1340 .equ FETCH_HL = (11<<0)
1341 .equ FETCH_SP = (12<<0)
1342 .equ FETCH_MBC = (13<<0)
1343 .equ FETCH_MDE = (14<<0)
1344 .equ FETCH_MHL = (15<<0)
1345 .equ FETCH_MSP = (16<<0)
1346 .equ FETCH_DIR8 = (17<<0)
1347 .equ FETCH_DIR16= (18<<0)
1348 .equ FETCH_RST = (19<<0)
1349
1350
1351 ;Jump table for fetch routines. Make sure to keep this in sync with the .equs!
1352 fetchjumps:
1353 .dw do_fetch_nop
1354 .dw do_fetch_a
1355 .dw do_fetch_b
1356 .dw do_fetch_c
1357 .dw do_fetch_d
1358 .dw do_fetch_e
1359 .dw do_fetch_h
1360 .dw do_fetch_l
1361 .dw do_fetch_af
1362 .dw do_fetch_bc
1363 .dw do_fetch_de
1364 .dw do_fetch_hl
1365 .dw do_fetch_sp
1366 .dw do_fetch_mbc
1367 .dw do_fetch_mde
1368 .dw do_fetch_mhl
1369 .dw do_fetch_msp
1370 .dw do_fetch_dir8
1371 .dw do_fetch_dir16
1372 .dw do_fetch_rst
1373
1374 do_fetch_nop:
1375 ret
1376
1377 do_fetch_a:
1378 mov opl,z_a
1379 ret
1380
1381 do_fetch_b:
1382 mov opl,z_b
1383 ret
1384
1385 do_fetch_c:
1386 mov opl,z_c
1387 ret
1388
1389 do_fetch_d:
1390 mov opl,z_d
1391 ret
1392
1393 do_fetch_e:
1394 mov opl,z_e
1395 ret
1396
1397 do_fetch_h:
1398 mov opl,z_h
1399 ret
1400
1401 do_fetch_l:
1402 mov opl,z_l
1403 ret
1404
1405 do_fetch_af:
1406 mov opl,z_flags
1407 mov oph,z_a
1408 rcall do_op_calcparity
1409 andi opl,~(1<<ZFL_P)
1410 sbrs temp2,0
1411 ori opl,(1<<ZFL_P)
1412 ret
1413
1414 do_fetch_bc:
1415 mov opl,z_c
1416 mov oph,z_b
1417 ret
1418
1419 do_fetch_de:
1420 mov opl,z_e
1421 mov oph,z_d
1422 ret
1423
1424 do_fetch_hl:
1425 mov opl,z_l
1426 mov oph,z_h
1427 ret
1428
1429 do_fetch_sp:
1430 mov opl,z_spl
1431 mov oph,z_sph
1432 ret
1433
1434 do_fetch_mbc:
1435 mov adrh,z_b
1436 mov adrl,z_c
1437 rcall memReadByte
1438 mov opl,temp
1439 ret
1440
1441 do_fetch_mde:
1442 mov adrh,z_d
1443 mov adrl,z_e
1444 rcall memReadByte
1445 mov opl,temp
1446 ret
1447
1448 do_fetch_mhl:
1449 mov adrh,z_h
1450 mov adrl,z_l
1451 rcall memReadByte
1452 mov opl,temp
1453 ret
1454
1455 do_fetch_msp:
1456 mov adrh,z_sph
1457 mov adrl,z_spl
1458 rcall memReadByte
1459 mov opl,temp
1460
1461 mov adrh,z_sph
1462 mov adrl,z_spl
1463 ldi temp,1
1464 ldi temp2,0
1465 add adrl,temp
1466 adc adrh,temp2
1467 rcall memReadByte
1468 mov oph,temp
1469 ret
1470
1471 do_fetch_dir8:
1472 mov adrl,z_pcl
1473 mov adrh,z_pch
1474 rcall memReadByte
1475 adiw z_pcl,1
1476 mov opl,temp
1477 ret
1478
1479 do_fetch_dir16:
1480 mov adrl,z_pcl
1481 mov adrh,z_pch
1482 rcall memReadByte
1483 mov opl,temp
1484 adiw z_pcl,1
1485 mov adrl,z_pcl
1486 mov adrh,z_pch
1487 rcall memReadByte
1488 adiw z_pcl,1
1489 mov oph,temp
1490 ret
1491
1492 do_fetch_rst:
1493 mov adrl,z_pcl
1494 mov adrh,z_pch
1495 rcall memReadByte
1496 andi temp,0x38
1497 ldi oph,0
1498 mov opl,temp
1499 ret
1500
1501
1502
1503 ; ------------ Store phase stuff -----------------
1504
1505 .equ STORE_NOP = (0<<5)
1506 .equ STORE_A = (1<<5)
1507 .equ STORE_B = (2<<5)
1508 .equ STORE_C = (3<<5)
1509 .equ STORE_D = (4<<5)
1510 .equ STORE_E = (5<<5)
1511 .equ STORE_H = (6<<5)
1512 .equ STORE_L = (7<<5)
1513 .equ STORE_AF = (8<<5)
1514 .equ STORE_BC = (9<<5)
1515 .equ STORE_DE = (10<<5)
1516 .equ STORE_HL = (11<<5)
1517 .equ STORE_SP = (12<<5)
1518 .equ STORE_PC = (13<<5)
1519 .equ STORE_MBC = (14<<5)
1520 .equ STORE_MDE = (15<<5)
1521 .equ STORE_MHL = (16<<5)
1522 .equ STORE_MSP = (17<<5)
1523 .equ STORE_RET = (18<<5)
1524 .equ STORE_CALL = (19<<5)
1525 .equ STORE_AM = (20<<5)
1526
1527 ;Jump table for store routines. Make sure to keep this in sync with the .equs!
1528 storejumps:
1529 .dw do_store_nop
1530 .dw do_store_a
1531 .dw do_store_b
1532 .dw do_store_c
1533 .dw do_store_d
1534 .dw do_store_e
1535 .dw do_store_h
1536 .dw do_store_l
1537 .dw do_store_af
1538 .dw do_store_bc
1539 .dw do_store_de
1540 .dw do_store_hl
1541 .dw do_store_sp
1542 .dw do_store_pc
1543 .dw do_store_mbc
1544 .dw do_store_mde
1545 .dw do_store_mhl
1546 .dw do_store_msp
1547 .dw do_store_ret
1548 .dw do_store_call
1549 .dw do_store_am
1550
1551
1552 do_store_nop:
1553 ret
1554
1555 do_store_a:
1556 mov z_a,opl
1557 ret
1558
1559 do_store_b:
1560 mov z_b,opl
1561 ret
1562
1563 do_store_c:
1564 mov z_c,opl
1565 ret
1566
1567 do_store_d:
1568 mov z_d,opl
1569 ret
1570
1571 do_store_e:
1572 mov z_e,opl
1573 ret
1574
1575 do_store_h:
1576 mov z_h,opl
1577 ret
1578
1579 do_store_l:
1580 mov z_l,opl
1581 ret
1582
1583 do_store_af:
1584 mov z_a,oph
1585 mov z_flags,opl
1586 ldi temp,0
1587 mov parityb,temp
1588 sbrs z_flags,ZFL_P
1589 inc parityb
1590 ret
1591
1592 do_store_bc:
1593 mov z_b,oph
1594 mov z_c,opl
1595 ret
1596
1597 do_store_de:
1598 mov z_d,oph
1599 mov z_e,opl
1600 ret
1601
1602 do_store_hl:
1603 mov z_h,oph
1604 mov z_l,opl
1605 ret
1606
1607 do_store_mbc:
1608 mov adrh,z_b
1609 mov adrl,z_c
1610 mov temp,opl
1611 rcall memWriteByte
1612 ret
1613
1614 do_store_mde:
1615 mov adrh,z_d
1616 mov adrl,z_e
1617 mov temp,opl
1618 rcall memWriteByte
1619 ret
1620
1621 do_store_mhl:
1622 mov adrh,z_h
1623 mov adrl,z_l
1624 mov temp,opl
1625 rcall memWriteByte
1626 ret
1627
1628 do_store_msp:
1629 mov adrh,z_sph
1630 mov adrl,z_spl
1631 mov temp,opl
1632 rcall memWriteByte
1633
1634 mov adrh,z_sph
1635 mov adrl,z_spl
1636 ldi temp,1
1637 ldi temp2,0
1638 add adrl,temp
1639 adc adrh,temp2
1640 mov temp,oph
1641 rcall memWriteByte
1642
1643 ret
1644
1645 do_store_sp:
1646 mov z_sph,oph
1647 mov z_spl,opl
1648 ret
1649
1650 do_store_pc:
1651 mov z_pch,oph
1652 mov z_pcl,opl
1653 ret
1654
1655 do_store_ret:
1656 rcall do_op_pop16
1657 mov z_pcl,opl
1658 mov z_pch,oph
1659 ret
1660
1661 do_store_call:
1662 push opl
1663 push oph
1664 mov opl,z_pcl
1665 mov oph,z_pch
1666 rcall do_op_push16
1667 pop z_pch
1668 pop z_pcl
1669 ret
1670
1671 do_store_am:
1672 mov adrh,oph
1673 mov adrl,opl
1674 mov temp,z_a
1675 rcall memWriteByte
1676 ret
1677
1678
1679 ; ------------ Operation phase stuff -----------------
1680
1681
1682 .equ OP_NOP = (0<<10)
1683 .equ OP_INC = (1<<10)
1684 .equ OP_DEC = (2<<10)
1685 .equ OP_INC16 = (3<<10)
1686 .equ OP_DEC16 = (4<<10)
1687 .equ OP_RLC = (5<<10)
1688 .equ OP_RRC = (6<<10)
1689 .equ OP_RR = (7<<10)
1690 .equ OP_RL = (8<<10)
1691 .equ OP_ADDA = (9<<10)
1692 .equ OP_ADCA = (10<<10)
1693 .equ OP_SUBFA = (11<<10)
1694 .equ OP_SBCFA = (12<<10)
1695 .equ OP_ANDA = (13<<10)
1696 .equ OP_ORA = (14<<10)
1697 .equ OP_XORA = (15<<10)
1698 .equ OP_ADDHL = (16<<10)
1699 .equ OP_STHL = (17<<10) ;store HL in fetched address
1700 .equ OP_RMEM16 = (18<<10) ;read mem at fetched address
1701 .equ OP_RMEM8 = (19<<10) ;read mem at fetched address
1702 .equ OP_DA = (20<<10)
1703 .equ OP_SCF = (21<<10)
1704 .equ OP_CPL = (22<<10)
1705 .equ OP_CCF = (23<<10)
1706 .equ OP_POP16 = (24<<10)
1707 .equ OP_PUSH16 = (25<<10)
1708 .equ OP_IFNZ = (26<<10)
1709 .equ OP_IFZ = (27<<10)
1710 .equ OP_IFNC = (28<<10)
1711 .equ OP_IFC = (29<<10)
1712 .equ OP_IFPO = (30<<10)
1713 .equ OP_IFPE = (31<<10)
1714 .equ OP_IFP = (32<<10)
1715 .equ OP_IFM = (33<<10)
1716 .equ OP_OUTA = (34<<10)
1717 .equ OP_IN = (35<<10)
1718 .equ OP_EXHL = (36<<10)
1719 .equ OP_DI = (37<<10)
1720 .equ OP_EI = (38<<10)
1721 .equ OP_INV = (39<<10)
1722
1723 opjumps:
1724 .dw do_op_nop
1725 .dw do_op_inc
1726 .dw do_op_dec
1727 .dw do_op_inc16
1728 .dw do_op_dec16
1729 .dw do_op_rlc
1730 .dw do_op_rrc
1731 .dw do_op_rr
1732 .dw do_op_rl
1733 .dw do_op_adda
1734 .dw do_op_adca
1735 .dw do_op_subfa
1736 .dw do_op_sbcfa
1737 .dw do_op_anda
1738 .dw do_op_ora
1739 .dw do_op_xora
1740 .dw do_op_addhl
1741 .dw do_op_sthl
1742 .dw do_op_rmem16
1743 .dw do_op_rmem8
1744 .dw do_op_da
1745 .dw do_op_scf
1746 .dw do_op_cpl
1747 .dw do_op_ccf
1748 .dw do_op_pop16
1749 .dw do_op_push16
1750 .dw do_op_ifnz
1751 .dw do_op_ifz
1752 .dw do_op_ifnc
1753 .dw do_op_ifc
1754 .dw do_op_ifpo
1755 .dw do_op_ifpe
1756 .dw do_op_ifp
1757 .dw do_op_ifm
1758 .dw do_op_outa
1759 .dw do_op_in
1760 .dw do_op_exhl
1761 .dw do_op_di
1762 .dw do_op_ei
1763 .dw do_op_inv
1764
1765
1766 ;How the flags are supposed to work:
1767 ;7 ZFL_S - Sign flag (=MSBit of result)
1768 ;6 ZFL_Z - Zero flag. Is 1 when the result is 0
1769 ;4 ZFL_H - Half-carry (carry from bit 3 to 4)
1770 ;2 ZFL_P - Parity/2-complement Overflow
1771 ;1 ZFL_N - Subtract - set if last op was a subtract
1772 ;0 ZFL_C - Carry
1773 ;
1774 ;I sure hope I got the mapping between flags and instructions correct...
1775
1776
1777 ;ToDo: Parity at more instructions...
1778
1779 .equ AVR_H = 5
1780 .equ AVR_S = 4
1781 .equ AVR_V = 3
1782 .equ AVR_N = 2
1783 .equ AVR_Z = 1
1784 .equ AVR_C = 0
1785
1786 do_op_nop:
1787 ret
1788
1789 do_op_inc:
1790 andi z_flags,1
1791 ldi temp,1
1792 add opl,temp
1793 in temp,sreg
1794 mov parityb,opl
1795 bst temp,AVR_Z
1796 bld z_flags,ZFL_Z
1797 sbrc opl,7
1798 ori z_flags,(1<<ZFL_S)
1799 bst temp,AVR_H
1800 bld z_flags,ZFL_H
1801 ret
1802
1803 do_op_dec:
1804 andi z_flags,1
1805 ori z_flags,(1<<ZFL_N)
1806 ldi temp,1
1807 sub opl,temp
1808 in temp,sreg
1809 mov parityb,opl
1810 bst temp,AVR_Z
1811 bld z_flags,ZFL_Z
1812 bst temp,AVR_S
1813 bld z_flags,ZFL_S
1814 bst temp,AVR_H
1815 bld z_flags,ZFL_H
1816 ret
1817
1818 do_op_inc16:
1819 ldi temp,1
1820 ldi temp2,0
1821 add opl,temp
1822 adc oph,temp2
1823 ret
1824
1825 do_op_dec16:
1826 ldi temp,1
1827 ldi temp2,0
1828 sub opl,temp
1829 sbc oph,temp2
1830 ret
1831
1832 do_op_rlc:
1833 ;Rotate Left Cyclical. All bits move 1 to the
1834 ;left, the msb becomes c and lsb.
1835 andi z_flags,0b11101100
1836 lsl opl
1837 brcc do_op_rlc_noc
1838 ori opl,1
1839 ori z_flags,(1<<ZFL_C)
1840 do_op_rlc_noc:
1841 ret
1842
1843 do_op_rrc:
1844 ;Rotate Right Cyclical. All bits move 1 to the
1845 ;right, the lsb becomes c and msb.
1846 andi z_flags,0b11101100
1847 lsr opl
1848 brcc do_op_rrc_noc
1849 ori opl,0x80
1850 ori z_flags,(1<<ZFL_C)
1851 do_op_rrc_noc:
1852 ret
1853
1854 do_op_rr:
1855 ;Rotate Right. All bits move 1 to the right, the lsb
1856 ;becomes c, c becomes msb.
1857 clc
1858 sbrc z_flags,ZFL_C
1859 sec
1860 ror opl
1861 in temp,sreg
1862 andi z_flags,0b11101100
1863 bst temp,AVR_C
1864 bld z_flags,ZFL_C
1865 ret
1866
1867 do_op_rl:
1868 ;Rotate Left. All bits move 1 to the left, the msb
1869 ;becomes c, c becomes lsb.
1870 clc
1871 sbrc z_flags,ZFL_C
1872 sec
1873 rol opl
1874 in temp,sreg
1875 andi z_flags,0b11101100
1876 bst temp,AVR_C
1877 bld z_flags,ZFL_C
1878 ret
1879
1880 do_op_adda:
1881 ldi z_flags,0
1882 add opl,z_a
1883 in temp,sreg
1884 bst temp,AVR_Z
1885 bld z_flags,ZFL_Z
1886 bst temp,AVR_S
1887 cpi opl,$80
1888 brne adda_no_s
1889 ori z_flags,(1<<ZFL_S)
1890 adda_no_s:
1891 bst temp,AVR_H
1892 bld z_flags,ZFL_H
1893 bst temp,AVR_V
1894 bld z_flags,ZFL_P
1895 bst temp,AVR_C
1896 bld z_flags,ZFL_C
1897 ret
1898
1899 do_op_adca:
1900 clc
1901 sbrc z_flags,ZFL_C
1902 sec
1903 adc opl,z_a
1904 in temp,sreg
1905 ldi z_flags,0
1906 bst temp,AVR_Z
1907 bld z_flags,ZFL_Z
1908 sbrc opl,7
1909 ori z_flags,(1<<ZFL_S)
1910 bst temp,AVR_H
1911 bld z_flags,ZFL_H
1912 bst temp,AVR_V
1913 bld z_flags,ZFL_P
1914 bst temp,AVR_C
1915 bld z_flags,ZFL_C
1916 andi z_flags,~(1<<ZFL_N)
1917 ret
1918
1919 do_op_subfa:
1920 mov temp,z_a
1921 sub temp,opl
1922 mov opl,temp
1923 in temp,sreg
1924 bst temp,AVR_Z
1925 bld z_flags,ZFL_Z
1926 bst temp,AVR_S
1927 bld z_flags,ZFL_S
1928 bst temp,AVR_H
1929 bld z_flags,ZFL_H
1930 bst temp,AVR_V
1931 bld z_flags,ZFL_P
1932 bst temp,AVR_C
1933 bld z_flags,ZFL_C
1934 ori z_flags,(1<<ZFL_N)
1935 ret
1936
1937 do_op_sbcfa:
1938 mov temp,z_a
1939 clc
1940 sbrc z_flags,ZFL_C
1941 sec
1942 sbc temp,opl
1943 mov opl,temp
1944 in temp,sreg
1945 bst temp,AVR_S
1946 bld z_flags,ZFL_S
1947 bst temp,AVR_H
1948 bld z_flags,ZFL_H
1949 bst temp,AVR_V
1950 bld z_flags,ZFL_P
1951 bst temp,AVR_C
1952 bld z_flags,ZFL_C
1953 cpi opl,0 ;AVR doesn't set Z?
1954 in temp,sreg
1955 bst temp,AVR_Z
1956 bld z_flags,ZFL_Z
1957 ori z_flags,(1<<ZFL_N)
1958 ret
1959
1960 do_op_anda:
1961 ldi z_flags,0
1962 and opl,z_a
1963 in temp,sreg
1964 bst temp,AVR_Z
1965 bld z_flags,ZFL_Z
1966 bst temp,AVR_S
1967 bld z_flags,ZFL_S
1968 bst temp,AVR_H
1969 bld z_flags,ZFL_H
1970 mov temp,opl
1971 ret
1972
1973 do_op_ora:
1974 ldi z_flags,0
1975 or opl,z_a
1976 in temp,sreg
1977 bst temp,AVR_Z
1978 bld z_flags,ZFL_Z
1979 bst temp,AVR_S
1980 bld z_flags,ZFL_S
1981 bst temp,AVR_H
1982 bld z_flags,ZFL_H
1983 mov temp,opl
1984 ret
1985
1986 do_op_xora:
1987 ldi z_flags,0
1988 eor opl,z_a
1989 in temp,sreg
1990 bst temp,AVR_Z
1991 bld z_flags,ZFL_Z
1992 bst temp,AVR_S
1993 bld z_flags,ZFL_S
1994 bst temp,AVR_H
1995 bld z_flags,ZFL_H
1996 mov temp,opl
1997 ret
1998
1999 do_op_addhl:
2000 add opl,z_l
2001 adc oph,z_h
2002 in temp,sreg
2003 bst temp,AVR_C
2004 bld z_flags,ZFL_C
2005 andi z_flags,~(1<<ZFL_N)
2006 ret
2007
2008 do_op_sthl: ;store hl to mem loc in opl
2009 ;ToDo: check flags
2010 mov adrl,opl
2011 mov adrh,oph
2012 mov temp,z_l
2013 rcall memWriteByte
2014
2015 ldi temp,1
2016 ldi temp2,0
2017 add opl,temp
2018 adc oph,temp2
2019
2020 mov adrl,opl
2021 mov adrh,oph
2022 mov temp,z_h
2023 rcall memWriteByte
2024
2025 ret
2026
2027 do_op_rmem16:
2028 mov adrl,opl
2029 mov adrh,oph
2030 rcall memReadByte
2031 mov opl,temp
2032 ldi temp,1
2033 add adrl,temp
2034 ldi temp,0
2035 adc adrh,temp
2036 rcall memReadByte
2037 mov oph,temp
2038 ret
2039
2040 do_op_rmem8:
2041 mov adrl,opl
2042 mov adrh,oph
2043 rcall memReadByte
2044 mov opl,temp
2045 ret
2046
2047 do_op_da:
2048 ;DAA -> todo
2049 rcall do_op_inv
2050 mov temp,opl
2051 ret
2052
2053
2054 do_op_scf:
2055 ori z_flags,(1<<ZFL_C)
2056 ret
2057
2058 do_op_ccf:
2059 ldi temp,(1<<ZFL_C)
2060 eor z_flags,temp
2061 ret
2062
2063 do_op_cpl:
2064 com opl
2065 ori z_flags,(1<<ZFL_N)|(1<<ZFL_H)
2066 ret
2067
2068 do_op_push16:
2069 ldi temp,1
2070 ldi temp2,0
2071 sub z_spl,temp
2072 sbc z_sph,temp2
2073
2074 mov adrl,z_spl
2075 mov adrh,z_sph
2076 mov temp,oph
2077 rcall memWriteByte
2078
2079 ldi temp,1
2080 ldi temp2,0
2081 sub z_spl,temp
2082 sbc z_sph,temp2
2083
2084 mov adrl,z_spl
2085 mov adrh,z_sph
2086 mov temp,opl
2087 rcall memWriteByte
2088
2089 .if STACK_DBG
2090 rcall printstr
2091 .db "Stack push ",0
2092 mov temp,oph
2093 rcall printhex
2094 mov temp,opl
2095 rcall printhex
2096 rcall printstr
2097 .db ", SP is now ",0
2098 mov temp,z_sph
2099 rcall printhex
2100 mov temp,z_spl
2101 rcall printhex
2102 rcall printstr
2103 .db ".",13,0
2104 .endif
2105
2106 ret
2107
2108 do_op_pop16:
2109 mov adrl,z_spl
2110 mov adrh,z_sph
2111 rcall memReadByte
2112 mov opl,temp
2113
2114 ldi temp,1
2115 ldi temp2,0
2116 add z_spl,temp
2117 adc z_sph,temp2
2118
2119 mov adrl,z_spl
2120 mov adrh,z_sph
2121 rcall memReadByte
2122 mov oph,temp
2123
2124 ldi temp,1
2125 ldi temp2,0
2126 add z_spl,temp
2127 adc z_sph,temp2
2128
2129 .if STACK_DBG
2130 rcall printstr
2131 .db "Stack pop: val ",0
2132 mov temp,oph
2133 rcall printhex
2134 mov temp,opl
2135 rcall printhex
2136 rcall printstr
2137 .db ", SP is now",0
2138 mov temp,z_sph
2139 rcall printhex
2140 mov temp,z_spl
2141 rcall printhex
2142 rcall printstr
2143 .db ".",13,0
2144 .endif
2145 ret
2146
2147 do_op_exhl:
2148 mov temp,z_h
2149 mov z_h,oph
2150 mov oph,temp
2151 mov temp,z_l
2152 mov z_l,opl
2153 mov opl,temp
2154 ret
2155
2156 do_op_di:
2157 ret
2158
2159 do_op_ei:
2160 ret
2161
2162 do_op_ifnz:
2163 sbrs z_flags,ZFL_Z
2164 ret
2165 ldi insdech,0
2166 ldi insdecl,0
2167 ret
2168
2169 do_op_ifz:
2170 sbrc z_flags,ZFL_Z
2171 ret
2172 ldi insdech,0
2173 ldi insdecl,0
2174 ret
2175
2176 do_op_ifnc:
2177 sbrs z_flags,ZFL_C
2178 ret
2179 ldi insdech,0
2180 ldi insdecl,0
2181 ret
2182
2183 do_op_ifc:
2184 sbrc z_flags,ZFL_C
2185 ret
2186 ldi insdech,0
2187 ldi insdecl,0
2188 ret
2189
2190 do_op_ifpo:
2191 rcall do_op_calcparity
2192 sbrs temp2,0
2193 ret
2194 ldi insdech,0
2195 ldi insdecl,0
2196 ret
2197
2198 do_op_ifpe:
2199 rcall do_op_calcparity
2200 sbrc temp2,0
2201 ret
2202 ldi insdech,0
2203 ldi insdecl,0
2204 ret
2205
2206 do_op_ifp: ;sign positive, aka s=0
2207 sbrs z_flags,ZFL_S
2208 ret
2209 ldi insdech,0
2210 ldi insdecl,0
2211 ret
2212
2213 do_op_ifm: ;sign negative, aka s=1
2214 sbrc z_flags,ZFL_S
2215 ret
2216 ldi insdech,0
2217 ldi insdecl,0
2218 ret
2219
2220 ;Interface with peripherials goes here :)
2221 do_op_outa: ; out (opl),a
2222 .if PORT_DEBUG
2223 rcall printstr
2224 .db 13,"Port write: ",0
2225 mov temp,z_a
2226 rcall printhex
2227 rcall printstr
2228 .db " -> (",0
2229 mov temp,opl
2230 rcall printhex
2231 rcall printstr
2232 .db ")",13,0
2233 .endif
2234 mov temp,z_a
2235 mov temp2,opl
2236 rcall portWrite
2237 ret
2238
2239 do_op_in: ; in a,(opl)
2240 .if PORT_DEBUG
2241 rcall printstr
2242 .db 13,"Port read: (",0
2243 mov temp,opl
2244 rcall printhex
2245 rcall printstr
2246 .db ") -> ",0
2247 .endif
2248
2249 mov temp2,opl
2250 rcall portRead
2251 mov opl,temp
2252
2253 .if PORT_DEBUG
2254 rcall printhex
2255 rcall printstr
2256 .db 13,0
2257 .endif
2258 ret
2259
2260 do_op_calcparity:
2261 ldi temp2,1
2262 sbrc parityb,0
2263 inc temp2
2264 sbrc parityb,1
2265 inc temp2
2266 sbrc parityb,2
2267 inc temp2
2268 sbrc parityb,3
2269 inc temp2
2270 sbrc parityb,4
2271 inc temp2
2272 sbrc parityb,5
2273 inc temp2
2274 sbrc parityb,6
2275 inc temp2
2276 sbrc parityb,7
2277 inc temp2
2278 andi temp2,1
2279 ret
2280
2281 do_op_inv:
2282 rcall printstr
2283 .db "Invalid opcode @ PC=",0
2284 mov temp,z_pch
2285 rcall printhex
2286 mov temp,z_pcl
2287 rcall printhex
2288 haltinv:
2289 rjmp haltinv
2290
2291
2292 ; ----------------------- Opcode decoding -------------------------
2293
2294 ; Lookup table for Z80 opcodes. Translates the first byte of the instruction word into three
2295 ; operations: fetch, do something, store.
2296 ; The table is made of 256 words. These 16-bit words consist of
2297 ; the fetch operation (bit 0-4), the processing operation (bit 10-16) and the store
2298 ; operation (bit 5-9).
2299
2300 inst_table:
2301 .dw (FETCH_NOP | OP_NOP | STORE_NOP) ; 00 NOP
2302 .dw (FETCH_DIR16| OP_NOP | STORE_BC ) ; 01 nn nn LD BC,nn
2303 .dw (FETCH_A | OP_NOP | STORE_MBC ) ; 02 LD (BC),A
2304 .dw (FETCH_BC | OP_INC16 | STORE_BC ) ; 03 INC BC
2305 .dw (FETCH_B | OP_INC | STORE_B ) ; 04 INC B
2306 .dw (FETCH_B | OP_DEC | STORE_B ) ; 05 DEC B
2307 .dw (FETCH_DIR8 | OP_NOP | STORE_B ) ; 06 nn LD B,n
2308 .dw (FETCH_A | OP_RLC | STORE_A ) ; 07 RLCA
2309 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 08 EX AF,AF' (Z80)
2310 .dw (FETCH_BC | OP_ADDHL | STORE_HL ) ; 09 ADD HL,BC
2311 .dw (FETCH_MBC | OP_NOP | STORE_A ) ; 0A LD A,(BC)
2312 .dw (FETCH_BC | OP_DEC16 | STORE_BC ) ; 0B DEC BC
2313 .dw (FETCH_C | OP_INC | STORE_C ) ; 0C INC C
2314 .dw (FETCH_C | OP_DEC | STORE_C ) ; 0D DEC C
2315 .dw (FETCH_DIR8 | OP_NOP | STORE_C ) ; 0E nn LD C,n
2316 .dw (FETCH_A | OP_RRC | STORE_A ) ; 0F RRCA
2317 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 10 oo DJNZ o (Z80)
2318 .dw (FETCH_DIR16| OP_NOP | STORE_DE ) ; 11 nn nn LD DE,nn
2319 .dw (FETCH_A | OP_NOP | STORE_MDE) ; 12 LD (DE),A
2320 .dw (FETCH_DE | OP_INC16 | STORE_DE ) ; 13 INC DE
2321 .dw (FETCH_D | OP_INC | STORE_D ) ; 14 INC D
2322 .dw (FETCH_D | OP_DEC | STORE_D ) ; 15 DEC D
2323 .dw (FETCH_DIR8 | OP_NOP | STORE_D ) ; 16 nn LD D,n
2324 .dw (FETCH_A | OP_RL | STORE_A ) ; 17 RLA
2325 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 18 oo JR o (Z80)
2326 .dw (FETCH_DE | OP_ADDHL | STORE_HL ) ; 19 ADD HL,DE
2327 .dw (FETCH_MDE | OP_NOP | STORE_A ) ; 1A LD A,(DE)
2328 .dw (FETCH_DE | OP_DEC16 | STORE_DE ) ; 1B DEC DE
2329 .dw (FETCH_E | OP_INC | STORE_E ) ; 1C INC E
2330 .dw (FETCH_E | OP_DEC | STORE_E ) ; 1D DEC E
2331 .dw (FETCH_DIR8 | OP_NOP | STORE_E ) ; 1E nn LD E,n
2332 .dw (FETCH_A | OP_RR | STORE_A ) ; 1F RRA
2333 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 20 oo JR NZ,o (Z80)
2334 .dw (FETCH_DIR16| OP_NOP | STORE_HL ) ; 21 nn nn LD HL,nn
2335 .dw (FETCH_DIR16| OP_STHL | STORE_NOP) ; 22 nn nn LD (nn),HL
2336 .dw (FETCH_HL | OP_INC16 | STORE_HL ) ; 23 INC HL
2337 .dw (FETCH_H | OP_INC | STORE_H ) ; 24 INC H
2338 .dw (FETCH_H | OP_DEC | STORE_H ) ; 25 DEC H
2339 .dw (FETCH_DIR8 | OP_NOP | STORE_H ) ; 26 nn LD H,n
2340 .dw (FETCH_A | OP_DA | STORE_A ) ; 27 DAA
2341 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 28 oo JR Z,o (Z80)
2342 .dw (FETCH_HL | OP_ADDHL | STORE_HL ) ; 29 ADD HL,HL
2343 .dw (FETCH_DIR16| OP_RMEM16 | STORE_HL ) ; 2A nn nn LD HL,(nn)
2344 .dw (FETCH_HL | OP_DEC16 | STORE_HL ) ; 2B DEC HL
2345 .dw (FETCH_L | OP_INC | STORE_L ) ; 2C INC L
2346 .dw (FETCH_L | OP_DEC | STORE_L ) ; 2D DEC L
2347 .dw (FETCH_DIR8 | OP_NOP | STORE_L ) ; 2E nn LD L,n
2348 .dw (FETCH_A | OP_CPL | STORE_A ) ; 2F CPL
2349 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 30 oo JR NC,o (Z80)
2350 .dw (FETCH_DIR16| OP_NOP | STORE_SP ) ; 31 nn nn LD SP,nn
2351 .dw (FETCH_DIR16| OP_NOP | STORE_AM ) ; 32 nn nn LD (nn),A
2352 .dw (FETCH_SP | OP_INC16 | STORE_SP ) ; 33 INC SP
2353 .dw (FETCH_MHL | OP_INC | STORE_MHL) ; 34 INC (HL)
2354 .dw (FETCH_MHL | OP_DEC | STORE_MHL) ; 35 DEC (HL)
2355 .dw (FETCH_DIR8 | OP_NOP | STORE_MHL) ; 36 nn LD (HL),n
2356 .dw (FETCH_NOP | OP_SCF | STORE_NOP) ; 37 SCF
2357 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 38 oo JR C,o (Z80)
2358 .dw (FETCH_SP | OP_ADDHL | STORE_HL ) ; 39 ADD HL,SP
2359 .dw (FETCH_DIR16| OP_RMEM8 | STORE_A ) ; 3A nn nn LD A,(nn)
2360 .dw (FETCH_SP | OP_DEC16 | STORE_SP ) ; 3B DEC SP
2361 .dw (FETCH_A | OP_INC | STORE_A ) ; 3C INC A
2362 .dw (FETCH_A | OP_DEC | STORE_A ) ; 3D DEC A
2363 .dw (FETCH_DIR8 | OP_NOP | STORE_A ) ; 3E nn LD A,n
2364 .dw (FETCH_NOP | OP_CCF | STORE_NOP) ; 3F CCF (Complement Carry Flag, gvd)
2365 .dw (FETCH_B | OP_NOP | STORE_B ) ; 40 LD B,r
2366 .dw (FETCH_C | OP_NOP | STORE_B ) ; 41 LD B,r
2367 .dw (FETCH_D | OP_NOP | STORE_B ) ; 42 LD B,r
2368 .dw (FETCH_E | OP_NOP | STORE_B ) ; 43 LD B,r
2369 .dw (FETCH_H | OP_NOP | STORE_B ) ; 44 LD B,r
2370 .dw (FETCH_L | OP_NOP | STORE_B ) ; 45 LD B,r
2371 .dw (FETCH_MHL | OP_NOP | STORE_B ) ; 46 LD B,r
2372 .dw (FETCH_A | OP_NOP | STORE_B ) ; 47 LD B,r
2373 .dw (FETCH_B | OP_NOP | STORE_C ) ; 48 LD C,r
2374 .dw (FETCH_C | OP_NOP | STORE_C ) ; 49 LD C,r
2375 .dw (FETCH_D | OP_NOP | STORE_C ) ; 4A LD C,r
2376 .dw (FETCH_E | OP_NOP | STORE_C ) ; 4B LD C,r
2377 .dw (FETCH_H | OP_NOP | STORE_C ) ; 4C LD C,r
2378 .dw (FETCH_L | OP_NOP | STORE_C ) ; 4D LD C,r
2379 .dw (FETCH_MHL | OP_NOP | STORE_C ) ; 4E LD C,r
2380 .dw (FETCH_A | OP_NOP | STORE_C ) ; 4F LD C,r
2381 .dw (FETCH_B | OP_NOP | STORE_D ) ; 50 LD D,r
2382 .dw (FETCH_C | OP_NOP | STORE_D ) ; 51 LD D,r
2383 .dw (FETCH_D | OP_NOP | STORE_D ) ; 52 LD D,r
2384 .dw (FETCH_E | OP_NOP | STORE_D ) ; 53 LD D,r
2385 .dw (FETCH_H | OP_NOP | STORE_D ) ; 54 LD D,r
2386 .dw (FETCH_L | OP_NOP | STORE_D ) ; 55 LD D,r
2387 .dw (FETCH_MHL | OP_NOP | STORE_D ) ; 56 LD D,r
2388 .dw (FETCH_A | OP_NOP | STORE_D ) ; 57 LD D,r
2389 .dw (FETCH_B | OP_NOP | STORE_E ) ; 58 LD E,r
2390 .dw (FETCH_C | OP_NOP | STORE_E ) ; 59 LD E,r
2391 .dw (FETCH_D | OP_NOP | STORE_E ) ; 5A LD E,r
2392 .dw (FETCH_E | OP_NOP | STORE_E ) ; 5B LD E,r
2393 .dw (FETCH_H | OP_NOP | STORE_E ) ; 5C LD E,r
2394 .dw (FETCH_L | OP_NOP | STORE_E ) ; 5D LD E,r
2395 .dw (FETCH_MHL | OP_NOP | STORE_E ) ; 5E LD E,r
2396 .dw (FETCH_A | OP_NOP | STORE_E ) ; 5F LD E,r
2397 .dw (FETCH_B | OP_NOP | STORE_H ) ; 60 LD H,r
2398 .dw (FETCH_C | OP_NOP | STORE_H ) ; 61 LD H,r
2399 .dw (FETCH_D | OP_NOP | STORE_H ) ; 62 LD H,r
2400 .dw (FETCH_E | OP_NOP | STORE_H ) ; 63 LD H,r
2401 .dw (FETCH_H | OP_NOP | STORE_H ) ; 64 LD H,r
2402 .dw (FETCH_L | OP_NOP | STORE_H ) ; 65 LD H,r
2403 .dw (FETCH_MHL | OP_NOP | STORE_H ) ; 66 LD H,r
2404 .dw (FETCH_A | OP_NOP | STORE_H ) ; 67 LD H,r
2405 .dw (FETCH_B | OP_NOP | STORE_L ) ; 68 LD L,r
2406 .dw (FETCH_C | OP_NOP | STORE_L ) ; 69 LD L,r
2407 .dw (FETCH_D | OP_NOP | STORE_L ) ; 6A LD L,r
2408 .dw (FETCH_E | OP_NOP | STORE_L ) ; 6B LD L,r
2409 .dw (FETCH_H | OP_NOP | STORE_L ) ; 6C LD L,r
2410 .dw (FETCH_L | OP_NOP | STORE_L ) ; 6D LD L,r
2411 .dw (FETCH_MHL | OP_NOP | STORE_L ) ; 6E LD L,r
2412 .dw (FETCH_A | OP_NOP | STORE_L ) ; 6F LD L,r
2413 .dw (FETCH_B | OP_NOP | STORE_MHL) ; 70 LD (HL),r
2414 .dw (FETCH_C | OP_NOP | STORE_MHL) ; 71 LD (HL),r
2415 .dw (FETCH_D | OP_NOP | STORE_MHL) ; 72 LD (HL),r
2416 .dw (FETCH_E | OP_NOP | STORE_MHL) ; 73 LD (HL),r
2417 .dw (FETCH_H | OP_NOP | STORE_MHL) ; 74 LD (HL),r
2418 .dw (FETCH_L | OP_NOP | STORE_MHL) ; 75 LD (HL),r
2419 .dw (FETCH_NOP | OP_NOP | STORE_NOP) ; 76 HALT
2420 .dw (FETCH_A | OP_NOP | STORE_MHL) ; 77 LD (HL),r
2421 .dw (FETCH_B | OP_NOP | STORE_A ) ; 78 LD A,r
2422 .dw (FETCH_C | OP_NOP | STORE_A ) ; 79 LD A,r
2423 .dw (FETCH_D | OP_NOP | STORE_A ) ; 7A LD A,r
2424 .dw (FETCH_E | OP_NOP | STORE_A ) ; 7B LD A,r
2425 .dw (FETCH_H | OP_NOP | STORE_A ) ; 7C LD A,r
2426 .dw (FETCH_L | OP_NOP | STORE_A ) ; 7D LD A,r
2427 .dw (FETCH_MHL | OP_NOP | STORE_A ) ; 7E LD A,r
2428 .dw (FETCH_A | OP_NOP | STORE_A ) ; 7F LD A,r
2429 .dw (FETCH_B | OP_ADDA | STORE_A ) ; 80 ADD A,r
2430 .dw (FETCH_C | OP_ADDA | STORE_A ) ; 81 ADD A,r
2431 .dw (FETCH_D | OP_ADDA | STORE_A ) ; 82 ADD A,r
2432 .dw (FETCH_E | OP_ADDA | STORE_A ) ; 83 ADD A,r
2433 .dw (FETCH_H | OP_ADDA | STORE_A ) ; 84 ADD A,r
2434 .dw (FETCH_L | OP_ADDA | STORE_A ) ; 85 ADD A,r
2435 .dw (FETCH_MHL | OP_ADDA | STORE_A ) ; 86 ADD A,r
2436 .dw (FETCH_A | OP_ADDA | STORE_A ) ; 87 ADD A,r
2437 .dw (FETCH_B | OP_ADCA | STORE_A ) ; 88 ADC A,r
2438 .dw (FETCH_C | OP_ADCA | STORE_A ) ; 89 ADC A,r
2439 .dw (FETCH_D | OP_ADCA | STORE_A ) ; 8A ADC A,r
2440 .dw (FETCH_E | OP_ADCA | STORE_A ) ; 8B ADC A,r
2441 .dw (FETCH_H | OP_ADCA | STORE_A ) ; 8C ADC A,r
2442 .dw (FETCH_L | OP_ADCA | STORE_A ) ; 8D ADC A,r
2443 .dw (FETCH_MHL | OP_ADCA | STORE_A ) ; 8E ADC A,r
2444 .dw (FETCH_A | OP_ADCA | STORE_A ) ; 8F ADC A,r
2445 .dw (FETCH_B | OP_SUBFA | STORE_A ) ; 90 SUB A,r
2446 .dw (FETCH_C | OP_SUBFA | STORE_A ) ; 91 SUB A,r
2447 .dw (FETCH_D | OP_SUBFA | STORE_A ) ; 92 SUB A,r
2448 .dw (FETCH_E | OP_SUBFA | STORE_A ) ; 93 SUB A,r
2449 .dw (FETCH_H | OP_SUBFA | STORE_A ) ; 94 SUB A,r
2450 .dw (FETCH_L | OP_SUBFA | STORE_A ) ; 95 SUB A,r
2451 .dw (FETCH_MHL | OP_SUBFA | STORE_A ) ; 96 SUB A,r
2452 .dw (FETCH_A | OP_SUBFA | STORE_A ) ; 97 SUB A,r
2453 .dw (FETCH_B | OP_SBCFA | STORE_A ) ; 98 SBC A,r
2454 .dw (FETCH_C | OP_SBCFA | STORE_A ) ; 99 SBC A,r
2455 .dw (FETCH_D | OP_SBCFA | STORE_A ) ; 9A SBC A,r
2456 .dw (FETCH_E | OP_SBCFA | STORE_A ) ; 9B SBC A,r
2457 .dw (FETCH_H | OP_SBCFA | STORE_A ) ; 9C SBC A,r
2458 .dw (FETCH_L | OP_SBCFA | STORE_A ) ; 9D SBC A,r
2459 .dw (FETCH_MHL | OP_SBCFA | STORE_A ) ; 9E SBC A,r
2460 .dw (FETCH_A | OP_SBCFA | STORE_A ) ; 9F SBC A,r
2461 .dw (FETCH_B | OP_ANDA | STORE_A ) ; A0 AND A,r
2462 .dw (FETCH_C | OP_ANDA | STORE_A ) ; A1 AND A,r
2463 .dw (FETCH_D | OP_ANDA | STORE_A ) ; A2 AND A,r
2464 .dw (FETCH_E | OP_ANDA | STORE_A ) ; A3 AND A,r
2465 .dw (FETCH_H | OP_ANDA | STORE_A ) ; A4 AND A,r
2466 .dw (FETCH_L | OP_ANDA | STORE_A ) ; A5 AND A,r
2467 .dw (FETCH_MHL | OP_ANDA | STORE_A ) ; A6 AND A,r
2468 .dw (FETCH_A | OP_ANDA | STORE_A ) ; A7 AND A,r
2469 .dw (FETCH_B | OP_XORA | STORE_A ) ; A8 XOR A,r
2470 .dw (FETCH_C | OP_XORA | STORE_A ) ; A9 XOR A,r
2471 .dw (FETCH_D | OP_XORA | STORE_A ) ; AA XOR A,r
2472 .dw (FETCH_E | OP_XORA | STORE_A ) ; AB XOR A,r
2473 .dw (FETCH_H | OP_XORA | STORE_A ) ; AC XOR A,r
2474 .dw (FETCH_L | OP_XORA | STORE_A ) ; AD XOR A,r
2475 .dw (FETCH_MHL | OP_XORA | STORE_A ) ; AE XOR A,r
2476 .dw (FETCH_A | OP_XORA | STORE_A ) ; AF XOR A,r
2477 .dw (FETCH_B | OP_ORA | STORE_A ) ; B0 OR A,r
2478 .dw (FETCH_C | OP_ORA | STORE_A ) ; B1 OR A,r
2479 .dw (FETCH_D | OP_ORA | STORE_A ) ; B2 OR A,r
2480 .dw (FETCH_E | OP_ORA | STORE_A ) ; B3 OR A,r
2481 .dw (FETCH_H | OP_ORA | STORE_A ) ; B4 OR A,r
2482 .dw (FETCH_L | OP_ORA | STORE_A ) ; B5 OR A,r
2483 .dw (FETCH_MHL | OP_ORA | STORE_A ) ; B6 OR A,r
2484 .dw (FETCH_A | OP_ORA | STORE_A ) ; B7 OR A,r
2485 .dw (FETCH_B | OP_SUBFA | STORE_NOP) ; B8 CP A,r
2486 .dw (FETCH_C | OP_SUBFA | STORE_NOP) ; B9 CP A,r
2487 .dw (FETCH_D | OP_SUBFA | STORE_NOP) ; BA CP A,r
2488 .dw (FETCH_E | OP_SUBFA | STORE_NOP) ; BB CP A,r
2489 .dw (FETCH_H | OP_SUBFA | STORE_NOP) ; BC CP A,r
2490 .dw (FETCH_L | OP_SUBFA | STORE_NOP) ; BD CP A,r
2491 .dw (FETCH_MHL | OP_SUBFA | STORE_NOP) ; BE CP A,r
2492 .dw (FETCH_A | OP_SUBFA | STORE_NOP) ; BF CP A,r
2493 .dw (FETCH_NOP | OP_IFNZ | STORE_RET) ; C0 RET NZ
2494 .dw (FETCH_NOP | OP_POP16 | STORE_BC ) ; C1 POP BC
2495 .dw (FETCH_DIR16| OP_IFNZ | STORE_PC ) ; C2 nn nn JP NZ,nn
2496 .dw (FETCH_DIR16| OP_NOP | STORE_PC ) ; C3 nn nn JP nn
2497 .dw (FETCH_DIR16| OP_IFNZ | STORE_CALL) ; C4 nn nn CALL NZ,nn
2498 .dw (FETCH_BC | OP_PUSH16 | STORE_NOP) ; C5 PUSH BC
2499 .dw (FETCH_DIR8 | OP_ADDA | STORE_A ) ; C6 nn ADD A,n
2500 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; C7 RST 0
2501 .dw (FETCH_NOP | OP_IFZ | STORE_RET) ; C8 RET Z
2502 .dw (FETCH_NOP | OP_NOP | STORE_RET) ; C9 RET
2503 .dw (FETCH_DIR16| OP_IFZ | STORE_PC ) ; CA nn nn JP Z,nn
2504 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; CB (Z80 specific)
2505 .dw (FETCH_DIR16| OP_IFZ | STORE_CALL) ; CC nn nn CALL Z,nn
2506 .dw (FETCH_DIR16| OP_NOP | STORE_CALL) ; CD nn nn CALL nn
2507 .dw (FETCH_DIR8 | OP_ADCA | STORE_A ) ; CE nn ADC A,n
2508 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; CF RST 8H
2509 .dw (FETCH_NOP | OP_IFNC | STORE_RET) ; D0 RET NC
2510 .dw (FETCH_NOP | OP_POP16 | STORE_DE ) ; D1 POP DE
2511 .dw (FETCH_DIR16| OP_IFNC | STORE_PC ) ; D2 nn nn JP NC,nn
2512 .dw (FETCH_DIR8 | OP_OUTA | STORE_NOP) ; D3 nn OUT (n),A
2513 .dw (FETCH_DIR16| OP_IFNC | STORE_CALL) ; D4 nn nn CALL NC,nn
2514 .dw (FETCH_DE | OP_PUSH16 | STORE_NOP) ; D5 PUSH DE
2515 .dw (FETCH_DIR8 | OP_SUBFA | STORE_A ) ; D6 nn SUB n
2516 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; D7 RST 10H
2517 .dw (FETCH_NOP | OP_IFC | STORE_RET) ; D8 RET C
2518 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; D9 EXX (Z80)
2519 .dw (FETCH_DIR16| OP_IFC | STORE_PC ) ; DA nn nn JP C,nn
2520 .dw (FETCH_DIR8 | OP_IN | STORE_A ) ; DB nn IN A,(n)
2521 .dw (FETCH_DIR16| OP_IFC | STORE_CALL) ; DC nn nn CALL C,nn
2522 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; DD (Z80)
2523 .dw (FETCH_DIR8 | OP_SBCFA | STORE_A ) ; DE nn SBC A,n
2524 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; DF RST 18H
2525 .dw (FETCH_NOP | OP_IFPO | STORE_RET) ; E0 RET PO
2526 .dw (FETCH_NOP | OP_POP16 | STORE_HL ) ; E1 POP HL
2527 .dw (FETCH_DIR16| OP_IFPO | STORE_PC ) ; E2 nn nn JP PO,nn
2528 .dw (FETCH_MSP | OP_EXHL | STORE_MSP) ; E3 EX (SP),HL
2529 .dw (FETCH_DIR16| OP_IFPO | STORE_CALL) ; E4 nn nn CALL PO,nn
2530 .dw (FETCH_HL | OP_PUSH16 | STORE_NOP) ; E5 PUSH HL
2531 .dw (FETCH_DIR8 | OP_ANDA | STORE_A ) ; E6 nn AND n
2532 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; E7 RST 20H
2533 .dw (FETCH_NOP | OP_IFPE | STORE_RET) ; E8 RET PE
2534 .dw (FETCH_HL | OP_NOP | STORE_PC ) ; E9 JP (HL)
2535 .dw (FETCH_DIR16| OP_IFPE | STORE_PC ) ; EA nn nn JP PE,nn
2536 .dw (FETCH_DE | OP_EXHL | STORE_DE ) ; EB EX DE,HL
2537 .dw (FETCH_DIR16| OP_IFPE | STORE_CALL) ; EC nn nn CALL PE,nn
2538 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; ED (Z80 specific)
2539 .dw (FETCH_DIR8 | OP_XORA | STORE_A ) ; EE nn XOR n
2540 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; EF RST 28H
2541 .dw (FETCH_NOP | OP_IFP | STORE_RET) ; F0 RET P
2542 .dw (FETCH_NOP | OP_POP16 | STORE_AF ) ; F1 POP AF
2543 .dw (FETCH_DIR16| OP_IFP | STORE_PC ) ; F2 nn nn JP P,nn
2544 .dw (FETCH_NOP | OP_DI | STORE_NOP) ; F3 DI
2545 .dw (FETCH_DIR16| OP_IFP | STORE_CALL) ; F4 nn nn CALL P,nn
2546 .dw (FETCH_AF | OP_PUSH16 | STORE_NOP) ; F5 PUSH AF
2547 .dw (FETCH_DIR8 | OP_ORA | STORE_A ) ; F6 nn OR n
2548 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; F7 RST 30H
2549 .dw (FETCH_NOP | OP_IFM | STORE_RET) ; F8 RET M
2550 .dw (FETCH_HL | OP_NOP | STORE_SP ) ; F9 LD SP,HL
2551 .dw (FETCH_DIR16| OP_IFM | STORE_PC ) ; FA nn nn JP M,nn
2552 .dw (FETCH_NOP | OP_EI | STORE_NOP) ; FB EI
2553 .dw (FETCH_DIR16| OP_IFM | STORE_CALL) ; FC nn nn CALL M,nn
2554 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; FD (Z80 specific)
2555 .dw (FETCH_DIR8 | OP_SUBFA | STORE_NOP) ; FE nn CP n
2556 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; FF RST 38H