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