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