]> 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 1 /* 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 ; DRAM_SETADDR val, low_and_mask, low_or_mask, high_and_mask, high_or_mask
1216 .macro DRAM_SETADDR
1217 mov temp,@0
1218 .if low(@1) != 0xff
1219 andi temp,@1
1220 .endif
1221 .if low(@2) != 0
1222 ori temp, @2
1223 .endif
1224 out P_AL,temp
1225
1226 mov temp,@0
1227 .if low(@3) != 0xff
1228 andi temp,@3
1229 .endif
1230 ori temp, @4 | (1<<mmc_cs)
1231 out P_AH,temp
1232 .endm
1233
1234
1235 ;Loads the byte on address adrh:adrl into temp.
1236 ;must not alter adrh:adrl
1237
1238 dram_read:
1239 cli
1240 DRAM_SETADDR adrh, ~0,(1<<ram_ras), ~(1<<ram_a8), (1<<ram_oe)
1241 cbi P_RAS,ram_ras
1242 DRAM_SETADDR adrl, ~(1<<ram_ras),0, ~((1<<ram_oe)), (1<<ram_a8)
1243 cbi P_CAS,ram_cas
1244 cbi P_A8,ram_a8
1245 in temp,P_DQ-2 ; PIN
1246 sbi P_CAS,ram_cas
1247
1248 cbi P_CAS,ram_cas
1249 andi temp,0x0f
1250 swap temp
1251 in temp2,P_DQ-2 ; PIN
1252 andi temp2,0x0f
1253 or temp,temp2
1254
1255 sbi P_OE,ram_oe
1256 sbi P_CAS,ram_cas
1257 sbi P_RAS,ram_ras
1258 sei
1259 ret
1260
1261 #if DRAM_WORD_ACCESS
1262 dram_read_w:
1263 cpi adrl,255
1264 brne dram_read_w1
1265
1266 rcall dram_read
1267 push temp
1268 adiw adrl,1
1269 rcall dram_read
1270 mov temp2,temp
1271 pop temp
1272 ret
1273
1274 dram_read_w1:
1275 cli
1276 DRAM_SETADDR adrh, ~0,(1<<ram_ras), ~(1<<ram_a8),(1<<ram_oe)
1277 cbi P_RAS,ram_ras
1278 DRAM_SETADDR adrl, ~(1<<ram_ras),0, ~((1<<ram_oe)), (1<<ram_a8)
1279 cbi P_CAS,ram_cas
1280 cbi P_A8,ram_a8
1281 in temp,P_DQ-2 ; PIN
1282 sbi P_CAS,ram_cas
1283 cbi P_CAS,ram_cas
1284 andi temp,0x0f
1285 swap temp
1286 in temp2,P_DQ-2 ; PIN
1287 sbi P_CAS,ram_cas
1288 andi temp2,0x0f
1289 or temp,temp2
1290
1291 ; push temp
1292 mov _wl,temp
1293 inc adrl
1294 DRAM_SETADDR adrl, ~(1<<ram_ras),0, ~((1<<ram_oe)), (1<<ram_a8)
1295 cbi P_CAS,ram_cas
1296 cbi P_A8,ram_a8
1297 in temp,P_DQ-2 ; PIN
1298 sbi P_CAS,ram_cas
1299 cbi P_CAS,ram_cas
1300 andi temp,0x0f
1301 swap temp
1302 in temp2,P_DQ-2 ; PIN
1303 sbi P_CAS,ram_cas
1304 andi temp2,0x0f
1305 or temp2,temp
1306 ; pop temp
1307 mov temp,_wl
1308
1309 sbi P_OE,ram_oe
1310 sbi P_RAS,ram_ras
1311 sei
1312 ret
1313 #endif
1314
1315 ;Writes the byte in temp to adrh:adrl
1316 ;must not alter adrh:adrl
1317
1318 dram_write:
1319 cli
1320 ldi temp2,RAM_DQ_MASK | (1<<ram_w) | (1<<ram_cas)
1321 out DDRC,temp2
1322
1323 mov temp2,temp
1324 andi temp,RAM_DQ_MASK & ~(1<<ram_w)
1325 ori temp,(1<<ram_cas)
1326 out PORTC,temp
1327
1328 DRAM_SETADDR adrh, ~0,(1<<ram_ras), ~(1<<ram_a8),(1<<ram_oe)
1329 cbi P_RAS,ram_ras
1330 DRAM_SETADDR adrl, ~(1<<ram_ras),0, ~((1<<ram_a8)),(1<<ram_oe)
1331 cbi PORTC,ram_cas
1332 sbi PORTC,ram_cas
1333
1334 sbi PORTD,ram_a8
1335 swap temp2
1336
1337 andi temp2,RAM_DQ_MASK & ~(1<<ram_w)
1338 ori temp2,(1<<ram_cas)
1339 out PORTC,temp2
1340
1341 cbi PORTC,ram_cas
1342 sbi P_RAS,ram_ras
1343
1344 ldi temp,~RAM_DQ_MASK | (1<<ram_w) | (1<<ram_cas)
1345 out DDRC,temp
1346 out PORTC,temp
1347 sei
1348 ret
1349
1350 #if DRAM_WORD_ACCESS
1351 dram_write_w:
1352 cpi adrl,255
1353 brne dram_write_w1
1354
1355 push temp2
1356 rcall dram_write
1357 pop temp
1358 adiw adrl,1
1359 rcall dram_write
1360 ret
1361
1362 dram_write_w1:
1363 cli
1364 push temp2
1365 ldi temp2,RAM_DQ_MASK | (1<<ram_w) | (1<<ram_cas)
1366 out DDRC,temp2
1367
1368 mov temp2,temp
1369 andi temp,RAM_DQ_MASK & ~(1<<ram_w)
1370 ori temp,(1<<ram_cas)
1371 out PORTC,temp
1372
1373 DRAM_SETADDR adrh, ~0,(1<<ram_ras), ~(1<<ram_a8),(1<<ram_oe)
1374 cbi P_RAS,ram_ras
1375 DRAM_SETADDR adrl, ~(1<<ram_ras),0, ~((1<<ram_a8)),(1<<ram_oe)
1376 cbi PORTC,ram_cas
1377 sbi PORTC,ram_cas
1378
1379 sbi PORTD,ram_a8
1380 swap temp2
1381
1382 andi temp2,RAM_DQ_MASK & ~(1<<ram_w)
1383 ori temp2,(1<<ram_cas)
1384 out PORTC,temp2
1385
1386 cbi PORTC,ram_cas
1387 sbi PORTC,ram_cas
1388
1389 pop temp
1390 inc adrl
1391 mov temp2,temp
1392 andi temp,RAM_DQ_MASK & ~(1<<ram_w)
1393 ori temp,(1<<ram_cas)
1394 out PORTC,temp
1395
1396 DRAM_SETADDR adrl, ~(1<<ram_ras),0, ~((1<<ram_a8)),(1<<ram_oe)
1397 cbi PORTC,ram_cas
1398 sbi PORTC,ram_cas
1399
1400 sbi PORTD,ram_a8
1401 swap temp2
1402
1403 andi temp2,RAM_DQ_MASK & ~(1<<ram_w)
1404 ori temp2,(1<<ram_cas)
1405 out PORTC,temp2
1406 cbi PORTC,ram_cas
1407
1408 sbi P_RAS,ram_ras
1409
1410 ldi temp,~RAM_DQ_MASK | (1<<ram_w) | (1<<ram_cas)
1411 out DDRC,temp
1412 out PORTC,temp
1413 sei
1414 ret
1415 #endif
1416
1417 ; ****************************************************************************
1418
1419 ; refresh interupt; exec 2 cbr cycles
1420 refrint:
1421 ;4 CAS RAS
1422 cbi P_CAS,ram_cas ;2 1| 1|
1423 ; 1| 1|
1424 cbi P_RAS,ram_ras ;2 |0 1|
1425 ; |0 1|
1426 nop ;1 |0 |0
1427 ; nop ;1 |0 |0
1428 sbi P_RAS,ram_ras ;2 |0 |0
1429 ; |0 |0
1430 ; nop ;1 |0 |0
1431 cbi P_RAS,ram_ras ;2 |0 1|
1432 ; |0 1|
1433 sbi P_CAS,ram_cas ;2 |0 |0
1434 ; |0 |0
1435 sbi P_RAS,ram_ras ;2 1| |0
1436 ; 1| 1|
1437 reti ;4 --> 21 cycles
1438
1439 ; ****************************************************************************
1440
1441 ; ------------- system timer 10ms ---------------
1442 .dseg
1443
1444 delay_timer:
1445 .byte 1
1446 timer_base:
1447 timer_ms:
1448 .byte 2
1449 timer_s:
1450 .byte 4
1451 ; don't change order here, clock put/get depends on it.
1452 cntms_out: ; register for ms
1453 .byte 2
1454 utime_io: ; register for uptime.
1455 .byte 4
1456 cnt_1ms:
1457 .byte 2
1458 uptime:
1459 .byte 4
1460 timer_top:
1461 .equ timer_size = timer_top - timer_base
1462
1463 .equ clkofs = cnt_1ms-cntms_out
1464 .equ timerofs = cnt_1ms-timer_ms
1465
1466 .cseg
1467 sysclockint:
1468 push zl
1469 in zl,SREG
1470 push zl
1471 push zh
1472
1473 lds zl,delay_timer
1474 subi zl,1
1475 brcs syscl1
1476 sts delay_timer,zl
1477 syscl1:
1478 lds zl,cnt_1ms
1479 lds zh,cnt_1ms+1
1480 adiw z,1
1481
1482 sts cnt_1ms,zl
1483 sts cnt_1ms+1,zh
1484 cpi zl,low(1000)
1485 ldi zl,high(1000) ;doesn't change flags
1486 cpc zh,zl
1487 brlo syscl_end
1488
1489 sts cnt_1ms,_0
1490 sts cnt_1ms+1,_0
1491
1492 lds zl,uptime+0
1493 inc zl
1494 sts uptime+0,zl
1495 brne syscl_end
1496 lds zl,uptime+1
1497 inc zl
1498 sts uptime+1,zl
1499 brne syscl_end
1500 lds zl,uptime+2
1501 inc zl
1502 sts uptime+2,zl
1503 brne syscl_end
1504 lds zl,uptime+3
1505 inc zl
1506 sts uptime+3,zl
1507
1508 syscl_end:
1509 pop zh
1510 pop zl
1511 out SREG,zl
1512 pop zl
1513 reti
1514
1515 ; wait for temp ms
1516
1517 delay_ms:
1518 sts delay_timer,temp
1519 dly_loop:
1520 lds temp,delay_timer
1521 cpi temp,0
1522 brne dly_loop
1523 ret
1524
1525 ;
1526
1527 clockget:
1528 ldi temp,0xFF
1529 subi temp2,TIMER_MSECS
1530 brcs clkget_end ;Port number in range?
1531 ldi zl,low(cntms_out)
1532 ldi zh,high(cntms_out)
1533 breq clkget_copy ;lowest byte requestet, latch clock
1534 cpi temp2,6
1535 brsh clkget_end ;Port number to high?
1536
1537 add zl,temp2
1538 brcc PC+2
1539 inc zh
1540 ld temp,z
1541 clkget_end:
1542 ret
1543
1544
1545
1546 clkget_copy:
1547 ldi temp2,6
1548 cli
1549 clkget_l:
1550 ldd temp,z+clkofs
1551 st z+,temp
1552 dec temp2
1553 brne clkget_l
1554 sei
1555 lds temp,cntms_out
1556 ;req. byte in temp
1557 ret
1558
1559 clockput:
1560 subi temp2,TIMERPORT
1561 brcs clkput_end ;Port number in range?
1562 brne clkput_1
1563
1564 ; clock control
1565
1566 cpi temp,starttimercmd
1567 breq timer_start
1568 cpi temp,quitTimerCmd
1569 breq timer_quit
1570 cpi temp,printTimerCmd
1571 breq timer_print
1572 cpi temp,uptimeCmd
1573 brne cp_ex
1574 rjmp uptime_print
1575 cp_ex:
1576 ret
1577
1578 timer_quit:
1579 rcall timer_print
1580 rjmp timer_start
1581
1582 clkput_1:
1583 dec temp2
1584 ldi zl,low(cntms_out)
1585 ldi zh,high(cntms_out)
1586 breq clkput_copy ;lowest byte requestet, latch clock
1587 cpi temp2,6
1588 brsh clkput_end ;Port number to high?
1589
1590 add zl,temp2
1591 brcc PC+2
1592 inc zh
1593 st z,temp
1594 clkput_end:
1595 ret
1596
1597 clkput_copy:
1598 st z,temp
1599 adiw z,5
1600 ldi temp2,6
1601 cli
1602 clkput_l:
1603 ldd temp,z+clkofs
1604 st z+,temp
1605 dec temp2
1606 brne clkput_l
1607 sei
1608 ret
1609
1610 ; start/reset timer
1611 ;
1612 timer_start:
1613 ldi zl,low(timer_ms)
1614 ldi zh,high(timer_ms)
1615 ldi temp2,6
1616 cli
1617 ts_loop:
1618 ldd temp,z+timerofs
1619 st z+,temp
1620 dec temp2
1621 brne ts_loop
1622 sei
1623 ret
1624
1625
1626 ; print timer
1627 ;
1628
1629 timer_print:
1630 push adrh
1631 push adrl
1632 push oph
1633 push opl
1634 ldi zl,low(timer_ms)
1635 ldi zh,high(timer_ms)
1636
1637 ; put ms on stack (16 bit)
1638
1639 cli
1640 ldd adrl,z+timerofs
1641 ld temp2,z+
1642 sub adrl,temp2
1643 ldd adrh,z+timerofs
1644 ld temp2,z+
1645 sbc adrh,temp2
1646 brsh tp_s
1647
1648 subi adrl,low(-1000)
1649 sbci adrh,high(-1000)
1650 sec
1651 tp_s:
1652 push adrh
1653 push adrl
1654
1655 ;
1656
1657 ldd temp,z+timerofs
1658 ld adrl,z+
1659 sbc temp,adrl
1660
1661 ldd temp2,z+timerofs
1662 ld adrh,z+
1663 sbc temp2,adrh
1664
1665 ldd opl,z+timerofs
1666 ld adrl,z+
1667 sbc opl,adrl
1668
1669 sei
1670 ldd oph,z+timerofs
1671 ld adrh,z+
1672 sbc oph,adrh
1673
1674 rcall printstr
1675 .db 13,"Timer running. Elapsed: ",0
1676 rcall print_ultoa
1677
1678 rcall printstr
1679 .db ",",0
1680 ldi opl,0
1681 ldi oph,0
1682 pop temp
1683 pop temp2
1684 rcall print_ultoa
1685 rcall printstr
1686 .db "s.",0,0
1687
1688 pop opl
1689 pop oph
1690 pop adrl
1691 pop adrh
1692 ret
1693
1694 uptime_print:
1695
1696 push oph
1697 push opl
1698 ldi zl,low(cnt_1ms)
1699 ldi zh,high(cnt_1ms)
1700
1701 cli
1702 ld temp,z+
1703 push temp
1704 ld temp,z+
1705 push temp
1706
1707 ld temp,z+
1708 ld temp2,z+
1709 ld opl,z+
1710 sei
1711 ld oph,z+
1712
1713 rcall printstr
1714 .db 13,"Uptime: ",0
1715
1716 rcall print_ultoa
1717 rcall printstr
1718 .db ",",0
1719
1720 ldi opl,0
1721 ldi oph,0
1722 pop temp2
1723 pop temp
1724 rcall print_ultoa
1725 rcall printstr
1726 .db "s.",0,0
1727
1728 pop opl
1729 pop oph
1730 ret
1731
1732
1733
1734 ; --------------- Debugging stuff ---------------
1735
1736 ;Print a unsigned lonng value to the uart
1737 ; oph:opl:temp2:temp = value
1738
1739 print_ultoa:
1740 push adrh
1741 push adrl
1742 push insdech
1743
1744 clr adrl ;adrl = stack level
1745
1746 ultoa1: ldi insdech, 32 ;adrh = oph:temp % 10
1747 clr adrh ;oph:temp /= 10
1748 ultoa2: lsl temp
1749 rol temp2
1750 rol opl
1751 rol oph
1752 rol adrh
1753 cpi adrh,10
1754 brcs ultoa3
1755 subi adrh,10
1756 inc temp
1757 ultoa3: dec insdech
1758 brne ultoa2
1759 cpi adrh, 10 ;adrh is a numeral digit '0'-'9'
1760 subi adrh, -'0'
1761 push adrh ;Stack it
1762 inc adrl
1763 cp temp,_0 ;Repeat until oph:temp gets zero
1764 cpc temp2,_0
1765 cpc opl,_0
1766 cpc oph,_0
1767 brne ultoa1
1768
1769 ldi temp, '0'
1770 ultoa5: cpi adrl,3 ; at least 3 digits (ms)
1771 brge ultoa6
1772 push temp
1773 inc adrl
1774 rjmp ultoa5
1775
1776 ultoa6: pop temp ;Flush stacked digits
1777 rcall uartputc
1778 dec adrl
1779 brne ultoa6
1780
1781 pop insdech
1782 pop adrl
1783 pop adrh
1784 ret
1785
1786
1787 ;Prints the lower nibble of temp in hex to the uart
1788 printhexn:
1789 push temp
1790 andi temp,0xf
1791 cpi temp,0xA
1792 brlo printhexn_isno
1793 subi temp,-('A'-10)
1794 rcall uartputc
1795 pop temp
1796 ret
1797 printhexn_isno:
1798 subi temp,-'0'
1799 rcall uartputc
1800 pop temp
1801 ret
1802
1803 ;Prints temp in hex to the uart
1804 printhex:
1805 swap temp
1806 rcall printhexn
1807 swap temp
1808 rcall printhexn
1809 ret
1810
1811 ;Prints the zero-terminated string following the call statement. WARNING: Destroys temp.
1812 printstr:
1813 pop zh
1814 pop zl
1815 push temp
1816
1817 lsl zl
1818 rol zh
1819
1820 printstr_loop:
1821 lpm temp,z+
1822 cpi temp,0
1823 breq printstr_end
1824 rcall uartputc
1825 cpi temp,13
1826 brne printstr_loop
1827 ldi temp,10
1828 rcall uartputc
1829 rjmp printstr_loop
1830
1831 printstr_end:
1832 adiw zl,1
1833 lsr zh
1834 ror zl
1835
1836 pop temp
1837 push zl
1838 push zh
1839 ret
1840
1841
1842 ; --------------- AVR HW <-> Z80 periph stuff ------------------
1843
1844 .equ memReadByte = dram_read
1845 .equ memWriteByte = dram_write
1846 #if DRAM_WORD_ACCESS
1847 .equ memReadWord = dram_read_w
1848 .equ memWriteWord = dram_write_w
1849 #endif
1850
1851 ; --------------------------------------------------------------
1852
1853 .dseg
1854
1855 #define RXBUFMASK RXBUFSIZE-1
1856
1857 rxcount:
1858 .byte 1
1859 rxidx_w:
1860 .byte 1
1861 rxidx_r:
1862 .byte 1
1863 rxfifo:
1864 .byte RXBUFSIZE
1865 .byte 0
1866
1867 .cseg
1868
1869 ; Save received character in a circular buffer. Do nothing if buffer overflows.
1870
1871 rxint:
1872 push temp
1873 in temp,sreg
1874 push temp
1875 push zh
1876 push zl
1877 #ifdef __ATmega8__
1878 in temp,UDR
1879 #else
1880 lds temp,UDR0
1881 #endif
1882 lds zh,rxcount ;if rxcount < RXBUFSIZE
1883 cpi zh,RXBUFSIZE ; (room for at least 1 char?)
1884 brsh rxi_ov ;
1885 inc zh ;
1886 sts rxcount,zh ; rxcount++
1887
1888 ldi zl,low(rxfifo) ;
1889 lds zh,rxidx_w ;
1890 add zl,zh ;
1891 inc zh ;
1892 andi zh,RXBUFMASK ;
1893 sts rxidx_w,zh ; rxidx_w = ++rxidx_w % RXBUFSIZE
1894 ldi zh,high(rxfifo) ;
1895 brcc PC+2 ;
1896 inc zh ;
1897 st z,temp ; rxfifo[rxidx_w] = char
1898 rxi_ov: ;endif
1899 pop zl
1900 pop zh
1901 pop temp
1902 out sreg,temp
1903 pop temp
1904 reti
1905
1906
1907 ;Fetches a char from the buffer to temp. If none available, waits till one is.
1908
1909 uartgetc:
1910 lds temp,rxcount ; Number of characters in buffer
1911 tst temp
1912 breq uartgetc
1913
1914 push zh
1915 push zl
1916 ldi zl,low(rxfifo)
1917 ldi zh,high(rxfifo)
1918 lds temp,rxidx_r
1919 add zl,temp
1920 brcc PC+2
1921 inc zh
1922 inc temp
1923 andi temp,RXBUFMASK
1924 sts rxidx_r,temp
1925 cli
1926 lds temp,rxcount
1927 dec temp
1928 sts rxcount,temp
1929 sei
1930 ld temp,z ;don't forget to get the char
1931 pop zl
1932 pop zh
1933 ret
1934
1935
1936
1937 ;Sends a char from temp to the uart.
1938 uartputc:
1939 #if defined __ATmega8__
1940 uartputc_l:
1941 sbis UCSRA,UDRE
1942 rjmp uartputc_l
1943 out UDR,temp
1944 #else
1945 push temp
1946 uartputc_l:
1947 lds temp,UCSR0A
1948 sbrs temp,UDRE0
1949 rjmp uartputc_l
1950 pop temp
1951 sts UDR0,temp
1952 #endif
1953 ret
1954
1955 ; ------------ Fetch phase stuff -----------------
1956
1957 .equ FETCH_NOP = (0<<0)
1958 .equ FETCH_A = (1<<0)
1959 .equ FETCH_B = (2<<0)
1960 .equ FETCH_C = (3<<0)
1961 .equ FETCH_D = (4<<0)
1962 .equ FETCH_E = (5<<0)
1963 .equ FETCH_H = (6<<0)
1964 .equ FETCH_L = (7<<0)
1965 .equ FETCH_AF = (8<<0)
1966 .equ FETCH_BC = (9<<0)
1967 .equ FETCH_DE = (10<<0)
1968 .equ FETCH_HL = (11<<0)
1969 .equ FETCH_SP = (12<<0)
1970 .equ FETCH_MBC = (13<<0)
1971 .equ FETCH_MDE = (14<<0)
1972 .equ FETCH_MHL = (15<<0)
1973 .equ FETCH_MSP = (16<<0)
1974 .equ FETCH_DIR8 = (17<<0)
1975 .equ FETCH_DIR16= (18<<0)
1976 .equ FETCH_RST = (19<<0)
1977
1978
1979 ;Jump table for fetch routines. Make sure to keep this in sync with the .equs!
1980 fetchjumps:
1981 rjmp do_fetch_nop
1982 rjmp do_fetch_a
1983 rjmp do_fetch_b
1984 rjmp do_fetch_c
1985 rjmp do_fetch_d
1986 rjmp do_fetch_e
1987 rjmp do_fetch_h
1988 rjmp do_fetch_l
1989 rjmp do_fetch_af
1990 rjmp do_fetch_bc
1991 rjmp do_fetch_de
1992 rjmp do_fetch_hl
1993 rjmp do_fetch_sp
1994 rjmp do_fetch_mbc
1995 rjmp do_fetch_mde
1996 rjmp do_fetch_mhl
1997 rjmp do_fetch_msp
1998 rjmp do_fetch_dir8
1999 rjmp do_fetch_dir16
2000 rjmp do_fetch_rst
2001
2002 do_fetch_nop:
2003 ret
2004
2005 do_fetch_a:
2006 mov opl,z_a
2007 ret
2008
2009 do_fetch_b:
2010 mov opl,z_b
2011 ret
2012
2013 do_fetch_c:
2014 mov opl,z_c
2015 ret
2016
2017 do_fetch_d:
2018 mov opl,z_d
2019 ret
2020
2021 do_fetch_e:
2022 mov opl,z_e
2023 ret
2024
2025 do_fetch_h:
2026 mov opl,z_h
2027 ret
2028
2029 do_fetch_l:
2030 mov opl,z_l
2031 ret
2032
2033 do_fetch_af:
2034 mov opl,z_flags
2035 mov oph,z_a
2036 ret
2037
2038 do_fetch_bc:
2039 mov opl,z_c
2040 mov oph,z_b
2041 ret
2042
2043 do_fetch_de:
2044 mov opl,z_e
2045 mov oph,z_d
2046 ret
2047
2048 do_fetch_hl:
2049 mov opl,z_l
2050 mov oph,z_h
2051 ret
2052
2053 do_fetch_sp:
2054 movw opl,z_spl
2055 ret
2056
2057 do_fetch_mbc:
2058 mov adrh,z_b
2059 mov adrl,z_c
2060 rcall memReadByte
2061 mov opl,temp
2062 ret
2063
2064 do_fetch_mde:
2065 mov adrh,z_d
2066 mov adrl,z_e
2067 rcall memReadByte
2068 mov opl,temp
2069 ret
2070
2071 do_fetch_mhl:
2072 mov adrh,z_h
2073 mov adrl,z_l
2074 rcall memReadByte
2075 mov opl,temp
2076 ret
2077
2078 do_fetch_msp:
2079 movw adrl,z_spl
2080 #if DRAM_WORD_ACCESS
2081 rcall memReadWord
2082 movw opl,temp
2083 #else
2084 rcall memReadByte
2085 mov opl,temp
2086
2087 adiw adrl,1
2088 rcall memReadByte
2089 mov oph,temp
2090 #endif
2091 ret
2092
2093 do_fetch_dir8:
2094 movw adrl,z_pcl
2095 rcall memReadByte
2096 adiw z_pcl,1
2097 mov opl,temp
2098 ret
2099
2100 do_fetch_dir16:
2101 movw adrl,z_pcl
2102 #if DRAM_WORD_ACCESS
2103 rcall memReadWord
2104 movw opl,temp
2105 #else
2106 rcall memReadByte
2107 mov opl,temp
2108 adiw adrl,1
2109 rcall memReadByte
2110 mov oph,temp
2111 #endif
2112 adiw z_pcl,2
2113 ret
2114
2115 do_fetch_rst:
2116 movw adrl,z_pcl
2117 subi adrl,1
2118 sbci adrh,0
2119 rcall memReadByte
2120 andi temp,0x38
2121 ldi oph,0
2122 mov opl,temp
2123 ret
2124
2125
2126
2127 ; ------------ Store phase stuff -----------------
2128
2129 .equ STORE_NOP = (0<<5)
2130 .equ STORE_A = (1<<5)
2131 .equ STORE_B = (2<<5)
2132 .equ STORE_C = (3<<5)
2133 .equ STORE_D = (4<<5)
2134 .equ STORE_E = (5<<5)
2135 .equ STORE_H = (6<<5)
2136 .equ STORE_L = (7<<5)
2137 .equ STORE_AF = (8<<5)
2138 .equ STORE_BC = (9<<5)
2139 .equ STORE_DE = (10<<5)
2140 .equ STORE_HL = (11<<5)
2141 .equ STORE_SP = (12<<5)
2142 .equ STORE_PC = (13<<5)
2143 .equ STORE_MBC = (14<<5)
2144 .equ STORE_MDE = (15<<5)
2145 .equ STORE_MHL = (16<<5)
2146 .equ STORE_MSP = (17<<5)
2147 .equ STORE_RET = (18<<5)
2148 .equ STORE_CALL = (19<<5)
2149 .equ STORE_AM = (20<<5)
2150
2151 ;Jump table for store routines. Make sure to keep this in sync with the .equs!
2152 storejumps:
2153 rjmp do_store_nop
2154 rjmp do_store_a
2155 rjmp do_store_b
2156 rjmp do_store_c
2157 rjmp do_store_d
2158 rjmp do_store_e
2159 rjmp do_store_h
2160 rjmp do_store_l
2161 rjmp do_store_af
2162 rjmp do_store_bc
2163 rjmp do_store_de
2164 rjmp do_store_hl
2165 rjmp do_store_sp
2166 rjmp do_store_pc
2167 rjmp do_store_mbc
2168 rjmp do_store_mde
2169 rjmp do_store_mhl
2170 rjmp do_store_msp
2171 rjmp do_store_ret
2172 rjmp do_store_call
2173 rjmp do_store_am
2174
2175
2176 do_store_nop:
2177 ret
2178
2179 do_store_a:
2180 mov z_a,opl
2181 ret
2182
2183 do_store_b:
2184 mov z_b,opl
2185 ret
2186
2187 do_store_c:
2188 mov z_c,opl
2189 ret
2190
2191 do_store_d:
2192 mov z_d,opl
2193 ret
2194
2195 do_store_e:
2196 mov z_e,opl
2197 ret
2198
2199 do_store_h:
2200 mov z_h,opl
2201 ret
2202
2203 do_store_l:
2204 mov z_l,opl
2205 ret
2206
2207 do_store_af:
2208 mov z_a,oph
2209 mov z_flags,opl
2210 ret
2211
2212 do_store_bc:
2213 mov z_b,oph
2214 mov z_c,opl
2215 ret
2216
2217 do_store_de:
2218 mov z_d,oph
2219 mov z_e,opl
2220 ret
2221
2222 do_store_hl:
2223 mov z_h,oph
2224 mov z_l,opl
2225 ret
2226
2227 do_store_mbc:
2228 mov adrh,z_b
2229 mov adrl,z_c
2230 mov temp,opl
2231 rcall memWriteByte
2232 ret
2233
2234 do_store_mde:
2235 mov adrh,z_d
2236 mov adrl,z_e
2237 mov temp,opl
2238 rcall memWriteByte
2239 ret
2240
2241 do_store_mhl:
2242 mov adrh,z_h
2243 mov adrl,z_l
2244 mov temp,opl
2245 rcall memWriteByte
2246 ret
2247
2248 do_store_msp:
2249 movw adrl,z_spl
2250 #if DRAM_WORD_ACCESS
2251 movw temp,opl
2252 rcall memWriteWord
2253 #else
2254 mov temp,opl
2255 rcall memWriteByte
2256 adiw adrl,1
2257 mov temp,oph
2258 rcall memWriteByte
2259 #endif
2260 ret
2261
2262 do_store_sp:
2263 movw z_spl,opl
2264 ret
2265
2266 do_store_pc:
2267 movw z_pcl,opl
2268 ret
2269
2270 do_store_ret:
2271 rcall do_op_pop16
2272 movw z_pcl,opl
2273 ret
2274
2275 do_store_call:
2276 push opl
2277 push oph
2278 movw opl,z_pcl
2279 rcall do_op_push16
2280 pop z_pch
2281 pop z_pcl
2282 ret
2283
2284 do_store_am:
2285 movw adrl,opl
2286 mov temp,z_a
2287 rcall memWriteByte
2288 ret
2289
2290
2291 ; ------------ Operation phase stuff -----------------
2292
2293
2294 .equ OP_NOP = (0<<10)
2295 .equ OP_INC = (1<<10)
2296 .equ OP_DEC = (2<<10)
2297 .equ OP_INC16 = (3<<10)
2298 .equ OP_DEC16 = (4<<10)
2299 .equ OP_RLC = (5<<10)
2300 .equ OP_RRC = (6<<10)
2301 .equ OP_RR = (7<<10)
2302 .equ OP_RL = (8<<10)
2303 .equ OP_ADDA = (9<<10)
2304 .equ OP_ADCA = (10<<10)
2305 .equ OP_SUBFA = (11<<10)
2306 .equ OP_SBCFA = (12<<10)
2307 .equ OP_ANDA = (13<<10)
2308 .equ OP_ORA = (14<<10)
2309 .equ OP_XORA = (15<<10)
2310 .equ OP_ADDHL = (16<<10)
2311 .equ OP_STHL = (17<<10) ;store HL in fetched address
2312 .equ OP_RMEM16 = (18<<10) ;read mem at fetched address
2313 .equ OP_RMEM8 = (19<<10) ;read mem at fetched address
2314 .equ OP_DA = (20<<10)
2315 .equ OP_SCF = (21<<10)
2316 .equ OP_CPL = (22<<10)
2317 .equ OP_CCF = (23<<10)
2318 .equ OP_POP16 = (24<<10)
2319 .equ OP_PUSH16 = (25<<10)
2320 .equ OP_IFNZ = (26<<10)
2321 .equ OP_IFZ = (27<<10)
2322 .equ OP_IFNC = (28<<10)
2323 .equ OP_IFC = (29<<10)
2324 .equ OP_IFPO = (30<<10)
2325 .equ OP_IFPE = (31<<10)
2326 .equ OP_IFP = (32<<10)
2327 .equ OP_IFM = (33<<10)
2328 .equ OP_OUTA = (34<<10)
2329 .equ OP_IN = (35<<10)
2330 .equ OP_EXHL = (36<<10)
2331 .equ OP_DI = (37<<10)
2332 .equ OP_EI = (38<<10)
2333 .equ OP_INV = (39<<10)
2334
2335 opjumps:
2336 rjmp do_op_nop
2337 rjmp do_op_inc
2338 rjmp do_op_dec
2339 rjmp do_op_inc16
2340 rjmp do_op_dec16
2341 rjmp do_op_rlc
2342 rjmp do_op_rrc
2343 rjmp do_op_rr
2344 rjmp do_op_rl
2345 rjmp do_op_adda
2346 rjmp do_op_adca
2347 rjmp do_op_subfa
2348 rjmp do_op_sbcfa
2349 rjmp do_op_anda
2350 rjmp do_op_ora
2351 rjmp do_op_xora
2352 rjmp do_op_addhl
2353 rjmp do_op_sthl
2354 rjmp do_op_rmem16
2355 rjmp do_op_rmem8
2356 rjmp do_op_da
2357 rjmp do_op_scf
2358 rjmp do_op_cpl
2359 rjmp do_op_ccf
2360 rjmp do_op_pop16
2361 rjmp do_op_push16
2362 rjmp do_op_ifnz
2363 rjmp do_op_ifz
2364 rjmp do_op_ifnc
2365 rjmp do_op_ifc
2366 rjmp do_op_ifpo
2367 rjmp do_op_ifpe
2368 rjmp do_op_ifp
2369 rjmp do_op_ifm
2370 rjmp do_op_outa
2371 rjmp do_op_in
2372 rjmp do_op_exhl
2373 rjmp do_op_di
2374 rjmp do_op_ei
2375 rjmp do_op_inv
2376
2377
2378 ;How the flags are supposed to work:
2379 ;7 ZFL_S - Sign flag (=MSBit of result)
2380 ;6 ZFL_Z - Zero flag. Is 1 when the result is 0
2381 ;4 ZFL_H - Half-carry (carry from bit 3 to 4)
2382 ;2 ZFL_P - Parity/2-complement Overflow
2383 ;1 ZFL_N - Subtract - set if last op was a subtract
2384 ;0 ZFL_C - Carry
2385 ;
2386 ;I sure hope I got the mapping between flags and instructions correct...
2387
2388 ;----------------------------------------------------------------
2389 ;| |
2390 ;| Zilog |
2391 ;| |
2392 ;| ZZZZZZZ 88888 000 |
2393 ;| Z 8 8 0 0 |
2394 ;| Z 8 8 0 0 0 |
2395 ;| Z 88888 0 0 0 |
2396 ;| Z 8 8 0 0 0 |
2397 ;| Z 8 8 0 0 |
2398 ;| ZZZZZZZ 88888 000 |
2399 ;| |
2400 ;| Z80 MICROPROCESSOR Instruction Set Summary |
2401 ;| |
2402 ;----------------------------------------------------------------
2403 ;----------------------------------------------------------------
2404 ;|Mnemonic |SZHPNC|Description |Notes |
2405 ;|----------+------+---------------------+----------------------|
2406 ;|ADC A,s |***V0*|Add with Carry |A=A+s+CY |
2407 ;|ADC HL,ss |**?V0*|Add with Carry |HL=HL+ss+CY |
2408 ;|ADD A,s |***V0*|Add |A=A+s |
2409 ;|ADD HL,ss |--?-0*|Add |HL=HL+ss |
2410 ;|ADD IX,pp |--?-0*|Add |IX=IX+pp |
2411 ;|ADD IY,rr |--?-0*|Add |IY=IY+rr |
2412 ;|AND s |**1P00|Logical AND |A=A&s |
2413 ;|BIT b,m |?*1?0-|Test Bit |m&{2^b} |
2414 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
2415 ;|CALL nn |------|Unconditional Call |-[SP]=PC,PC=nn |
2416 ;|CCF |--?-0*|Complement Carry Flag|CY=~CY |
2417 ;|CP s |***V1*|Compare |A-s |
2418 ;|CPD |****1-|Compare and Decrement|A-[HL],HL=HL-1,BC=BC-1|
2419 ;|CPDR |****1-|Compare, Dec., Repeat|CPD till A=[HL]or BC=0|
2420 ;|CPI |****1-|Compare and Increment|A-[HL],HL=HL+1,BC=BC-1|
2421 ;|CPIR |****1-|Compare, Inc., Repeat|CPI till A=[HL]or BC=0|
2422 ;|CPL |--1-1-|Complement |A=~A |
2423 ;|DAA |***P-*|Decimal Adjust Acc. |A=BCD format |
2424 ;|DEC s |***V1-|Decrement |s=s-1 |
2425 ;|DEC xx |------|Decrement |xx=xx-1 |
2426 ;|DEC ss |------|Decrement |ss=ss-1 |
2427 ;|DI |------|Disable Interrupts | |
2428 ;|DJNZ e |------|Dec., Jump Non-Zero |B=B-1 till B=0 |
2429 ;|EI |------|Enable Interrupts | |
2430 ;|EX [SP],HL|------|Exchange |[SP]<->HL |
2431 ;|EX [SP],xx|------|Exchange |[SP]<->xx |
2432 ;|EX AF,AF' |------|Exchange |AF<->AF' |
2433 ;|EX DE,HL |------|Exchange |DE<->HL |
2434 ;|EXX |------|Exchange |qq<->qq' (except AF)|
2435 ;|HALT |------|Halt | |
2436 ;|IM n |------|Interrupt Mode | (n=0,1,2)|
2437 ;|IN A,[n] |------|Input |A=[n] |
2438 ;|IN r,[C] |***P0-|Input |r=[C] |
2439 ;|INC r |***V0-|Increment |r=r+1 |
2440 ;|INC [HL] |***V0-|Increment |[HL]=[HL]+1 |
2441 ;|INC xx |------|Increment |xx=xx+1 |
2442 ;|INC [xx+d]|***V0-|Increment |[xx+d]=[xx+d]+1 |
2443 ;|INC ss |------|Increment |ss=ss+1 |
2444 ;|IND |?*??1-|Input and Decrement |[HL]=[C],HL=HL-1,B=B-1|
2445 ;|INDR |?1??1-|Input, Dec., Repeat |IND till B=0 |
2446 ;|INI |?*??1-|Input and Increment |[HL]=[C],HL=HL+1,B=B-1|
2447 ;|INIR |?1??1-|Input, Inc., Repeat |INI till B=0 |
2448 ;|JP [HL] |------|Unconditional Jump |PC=[HL] |
2449 ;|JP [xx] |------|Unconditional Jump |PC=[xx] |
2450 ;|JP nn |------|Unconditional Jump |PC=nn |
2451 ;|JP cc,nn |------|Conditional Jump |If cc JP |
2452 ;|JR e |------|Unconditional Jump |PC=PC+e |
2453 ;|JR cc,e |------|Conditional Jump |If cc JR(cc=C,NC,NZ,Z)|
2454 ;|LD dst,src|------|Load |dst=src |
2455 ;|LD A,i |**0*0-|Load |A=i (i=I,R)|
2456 ;|LDD |--0*0-|Load and Decrement |[DE]=[HL],HL=HL-1,# |
2457 ;|LDDR |--000-|Load, Dec., Repeat |LDD till BC=0 |
2458 ;|LDI |--0*0-|Load and Increment |[DE]=[HL],HL=HL+1,# |
2459 ;|LDIR |--000-|Load, Inc., Repeat |LDI till BC=0 |
2460 ;|NEG |***V1*|Negate |A=-A |
2461 ;|NOP |------|No Operation | |
2462 ;|OR s |**0P00|Logical inclusive OR |A=Avs |
2463 ;|OTDR |?1??1-|Output, Dec., Repeat |OUTD till B=0 |
2464 ;|OTIR |?1??1-|Output, Inc., Repeat |OUTI till B=0 |
2465 ;|OUT [C],r |------|Output |[C]=r |
2466 ;|OUT [n],A |------|Output |[n]=A |
2467 ;|OUTD |?*??1-|Output and Decrement |[C]=[HL],HL=HL-1,B=B-1|
2468 ;|OUTI |?*??1-|Output and Increment |[C]=[HL],HL=HL+1,B=B-1|
2469 ;|POP xx |------|Pop |xx=[SP]+ |
2470 ;|POP qq |------|Pop |qq=[SP]+ |
2471 ;|PUSH xx |------|Push |-[SP]=xx |
2472 ;|PUSH qq |------|Push |-[SP]=qq |
2473 ;|RES b,m |------|Reset bit |m=m&{~2^b} |
2474 ;|RET |------|Return |PC=[SP]+ |
2475 ;|RET cc |------|Conditional Return |If cc RET |
2476 ;|RETI |------|Return from Interrupt|PC=[SP]+ |
2477 ;|RETN |------|Return from NMI |PC=[SP]+ |
2478 ;|RL m |**0P0*|Rotate Left |m={CY,m}<- |
2479 ;|RLA |--0-0*|Rotate Left Acc. |A={CY,A}<- |
2480 ;|RLC m |**0P0*|Rotate Left Circular |m=m<- |
2481 ;|RLCA |--0-0*|Rotate Left Circular |A=A<- |
2482 ;|RLD |**0P0-|Rotate Left 4 bits |{A,[HL]}={A,[HL]}<- ##|
2483 ;|RR m |**0P0*|Rotate Right |m=->{CY,m} |
2484 ;|RRA |--0-0*|Rotate Right Acc. |A=->{CY,A} |
2485 ;|RRC m |**0P0*|Rotate Right Circular|m=->m |
2486 ;|RRCA |--0-0*|Rotate Right Circular|A=->A |
2487 ;|RRD |**0P0-|Rotate Right 4 bits |{A,[HL]}=->{A,[HL]} ##|
2488 ;|RST p |------|Restart | (p=0H,8H,10H,...,38H)|
2489 ;|SBC A,s |***V1*|Subtract with Carry |A=A-s-CY |
2490 ;|SBC HL,ss |**?V1*|Subtract with Carry |HL=HL-ss-CY |
2491 ;|SCF |--0-01|Set Carry Flag |CY=1 |
2492 ;|SET b,m |------|Set bit |m=mv{2^b} |
2493 ;|SLA m |**0P0*|Shift Left Arithmetic|m=m*2 |
2494 ;|SRA m |**0P0*|Shift Right Arith. |m=m/2 |
2495 ;|SRL m |**0P0*|Shift Right Logical |m=->{0,m,CY} |
2496 ;|SUB s |***V1*|Subtract |A=A-s |
2497 ;|XOR s |**0P00|Logical Exclusive OR |A=Axs |
2498 ;|----------+------+--------------------------------------------|
2499 ;| F |-*01? |Flag unaffected/affected/reset/set/unknown |
2500 ;| S |S |Sign flag (Bit 7) |
2501 ;| Z | Z |Zero flag (Bit 6) |
2502 ;| HC | H |Half Carry flag (Bit 4) |
2503 ;| P/V | P |Parity/Overflow flag (Bit 2, V=overflow) |
2504 ;| N | N |Add/Subtract flag (Bit 1) |
2505 ;| CY | C|Carry flag (Bit 0) |
2506 ;|-----------------+--------------------------------------------|
2507 ;| n |Immediate addressing |
2508 ;| nn |Immediate extended addressing |
2509 ;| e |Relative addressing (PC=PC+2+offset) |
2510 ;| [nn] |Extended addressing |
2511 ;| [xx+d] |Indexed addressing |
2512 ;| r |Register addressing |
2513 ;| [rr] |Register indirect addressing |
2514 ;| |Implied addressing |
2515 ;| b |Bit addressing |
2516 ;| p |Modified page zero addressing (see RST) |
2517 ;|-----------------+--------------------------------------------|
2518 ;|DEFB n(,...) |Define Byte(s) |
2519 ;|DEFB 'str'(,...) |Define Byte ASCII string(s) |
2520 ;|DEFS nn |Define Storage Block |
2521 ;|DEFW nn(,...) |Define Word(s) |
2522 ;|-----------------+--------------------------------------------|
2523 ;| A B C D E |Registers (8-bit) |
2524 ;| AF BC DE HL |Register pairs (16-bit) |
2525 ;| F |Flag register (8-bit) |
2526 ;| I |Interrupt page address register (8-bit) |
2527 ;| IX IY |Index registers (16-bit) |
2528 ;| PC |Program Counter register (16-bit) |
2529 ;| R |Memory Refresh register |
2530 ;| SP |Stack Pointer register (16-bit) |
2531 ;|-----------------+--------------------------------------------|
2532 ;| b |One bit (0 to 7) |
2533 ;| cc |Condition (C,M,NC,NZ,P,PE,PO,Z) |
2534 ;| d |One-byte expression (-128 to +127) |
2535 ;| dst |Destination s, ss, [BC], [DE], [HL], [nn] |
2536 ;| e |One-byte expression (-126 to +129) |
2537 ;| m |Any register r, [HL] or [xx+d] |
2538 ;| n |One-byte expression (0 to 255) |
2539 ;| nn |Two-byte expression (0 to 65535) |
2540 ;| pp |Register pair BC, DE, IX or SP |
2541 ;| qq |Register pair AF, BC, DE or HL |
2542 ;| qq' |Alternative register pair AF, BC, DE or HL |
2543 ;| r |Register A, B, C, D, E, H or L |
2544 ;| rr |Register pair BC, DE, IY or SP |
2545 ;| s |Any register r, value n, [HL] or [xx+d] |
2546 ;| src |Source s, ss, [BC], [DE], [HL], nn, [nn] |
2547 ;| ss |Register pair BC, DE, HL or SP |
2548 ;| xx |Index register IX or IY |
2549 ;|-----------------+--------------------------------------------|
2550 ;| + - * / ^ |Add/subtract/multiply/divide/exponent |
2551 ;| & ~ v x |Logical AND/NOT/inclusive OR/exclusive OR |
2552 ;| <- -> |Rotate left/right |
2553 ;| [ ] |Indirect addressing |
2554 ;| [ ]+ -[ ] |Indirect addressing auto-increment/decrement|
2555 ;| { } |Combination of operands |
2556 ;| # |Also BC=BC-1,DE=DE-1 |
2557 ;| ## |Only lower 4 bits of accumulator A used |
2558 ;----------------------------------------------------------------
2559
2560
2561 .equ AVR_T = 6
2562 .equ AVR_H = 5
2563 .equ AVR_S = 4
2564 .equ AVR_V = 3
2565 .equ AVR_N = 2
2566 .equ AVR_Z = 1
2567 .equ AVR_C = 0
2568
2569 ;------------------------------------------------;
2570 ; Move single bit between two registers
2571 ;
2572 ; bmov dstreg,dstbit,srcreg.srcbit
2573
2574 .macro bmov
2575 bst @2,@3
2576 bld @0,@1
2577 .endm
2578
2579
2580 ;------------------------------------------------;
2581 ; Load table value from flash indexed by source reg.
2582 ;
2583 ; ldpmx dstreg,tablebase,indexreg
2584 ;
2585 ; (6 words, 8 cycles)
2586
2587 .macro ldpmx
2588 ldi zh,high(@1*2) ; table must be page aligned
2589 mov zl,@2
2590 lpm @0,z
2591 .endm
2592
2593 .macro do_z80_flags_HP
2594 #if EM_Z80
2595 bmov z_flags, ZFL_P, temp, AVR_V
2596 bmov z_flags, ZFL_H, temp, AVR_H
2597 #endif
2598 .endm
2599
2600 .macro do_z80_flags_set_N
2601 #if EM_Z80
2602 ori z_flags, (1<<ZFL_N) ; Negation auf 1
2603 #endif
2604 .endm
2605
2606 .macro do_z80_flags_set_HN
2607 #if EM_Z80
2608 ori z_flags,(1<<ZFL_N)|(1<<ZFL_H)
2609 #endif
2610 .endm
2611
2612 .macro do_z80_flags_clear_N
2613 #if EM_Z80
2614 andi z_flags,~(1<<ZFL_N)
2615 #endif
2616 .endm
2617
2618 .macro do_z80_flags_op_rotate
2619 ; must not change avr carry flag!
2620 #if EM_Z80
2621 andi z_flags, ~( (1<<ZFL_H) | (1<<ZFL_N) | (1<<ZFL_C) )
2622 #else
2623 andi z_flags, ~( (1<<ZFL_C) )
2624 #endif
2625 .endm
2626
2627 .macro do_z80_flags_op_and
2628 #if EM_Z80
2629 ori z_flags,(1<<ZFL_H)
2630 #else
2631 ori z_flags,(1<<ZFL_H)
2632 #endif
2633 .endm
2634
2635 .macro do_z80_flags_op_or
2636 #if EM_Z80
2637 #endif
2638 .endm
2639
2640
2641 do_op_nop:
2642 ret
2643
2644 ;----------------------------------------------------------------
2645 ;|Mnemonic |SZHPNC|Description |Notes |
2646 ;----------------------------------------------------------------
2647 ;|INC r |***V0-|Increment |r=r+1 |
2648 ;|INC [HL] |***V0-|Increment |[HL]=[HL]+1 |
2649 ;|INC [xx+d]|***V0-|Increment |[xx+d]=[xx+d]+1 |
2650 ;|----------|SZHP C|---------- 8080 ----------------------------|
2651 ;|INC r |**-P0-|Increment |r=r+1 |
2652 ;|INC [HL] |**-P0-|Increment |[HL]=[HL]+1 |
2653 ;
2654 ;
2655 do_op_inc:
2656 ldi temp,1
2657 add opl,temp
2658 in temp, sreg
2659 andi z_flags,(1<<ZFL_H)|(1<<ZFL_C) ; preserve C-, and H-flag
2660 ldpmx temp2, sz53p_tab, opl
2661 or z_flags,temp2 ;
2662 do_z80_flags_HP
2663 ret
2664
2665 ;----------------------------------------------------------------
2666 ;|Mnemonic |SZHPNC|Description |Notes |
2667 ;----------------------------------------------------------------
2668 ;|DEC r |***V1-|Decrement |s=s-1 |
2669 ;|INC [HL] |***V0-|Increment |[HL]=[HL]+1 |
2670 ;|INC [xx+d]|***V0-|Increment |[xx+d]=[xx+d]+1 |
2671 ;|----------|SZHP C|---------- 8080 ----------------------------|
2672 ;|DEC r |**-P -|Increment |r=r+1 |
2673 ;|DEC [HL] |**-P -|Increment |[HL]=[HL]+1 |
2674 ;
2675 ;
2676 do_op_dec:
2677 subi opl,1
2678 in temp, sreg
2679 andi z_flags,(1<<ZFL_H)|(1<<ZFL_C) ; preserve C-, and H-flag
2680 ldpmx temp2, sz53p_tab, opl
2681 or z_flags,temp2 ;
2682 do_z80_flags_HP
2683 do_z80_flags_set_N
2684 ret
2685
2686
2687 ;----------------------------------------------------------------
2688 ;|Mnemonic |SZHPNC|Description |Notes |
2689 ;----------------------------------------------------------------
2690 ;|INC xx |------|Increment |xx=xx+1 |
2691 ;|INC ss |------|Increment |ss=ss+1 |
2692 ;
2693 ;
2694 do_op_inc16:
2695 adiw opl,1
2696 ret
2697
2698 ;----------------------------------------------------------------
2699 ;|Mnemonic |SZHPNC|Description |Notes |
2700 ;----------------------------------------------------------------
2701 ;|DEC xx |------|Decrement |xx=xx-1 |
2702 ;|DEC ss |------|Decrement |ss=ss-1 |
2703 ;
2704 ;
2705 do_op_dec16:
2706 subi opl, 1
2707 sbci oph, 0
2708 ret
2709
2710 ;----------------------------------------------------------------
2711 ;|Mnemonic |SZHPNC|Description |Notes |
2712 ;----------------------------------------------------------------
2713 ;|RLCA |--0-0*|Rotate Left Circular |A=A<- |
2714 ;|----------|SZHP C|---------- 8080 ----------------------------|
2715 ;|RLCA |---- *|Rotate Left Circular |A=A<- |
2716 ;
2717 ;
2718 do_op_rlc:
2719 ;Rotate Left Cyclical. All bits move 1 to the
2720 ;left, the msb becomes c and lsb.
2721 do_z80_flags_op_rotate
2722 lsl opl
2723 brcc do_op_rlc_noc
2724 ori opl, 1
2725 ori z_flags, (1<<ZFL_C)
2726 do_op_rlc_noc:
2727 ret
2728
2729 ;----------------------------------------------------------------
2730 ;|Mnemonic |SZHPNC|Description |Notes |
2731 ;----------------------------------------------------------------
2732 ;|RRCA |--0-0*|Rotate Right Circular|A=->A |
2733 ;|----------|SZHP C|---------- 8080 ----------------------------|
2734 ;|RRCA |---- *|Rotate Right Circular|A=->A |
2735 ;
2736 ;
2737 do_op_rrc:
2738 ;Rotate Right Cyclical. All bits move 1 to the
2739 ;right, the lsb becomes c and msb.
2740 do_z80_flags_op_rotate
2741 lsr opl
2742 brcc do_op_rrc_noc
2743 ori opl, 0x80
2744 ori z_flags, (1<<ZFL_C)
2745 do_op_rrc_noc:
2746 ret
2747
2748 ;----------------------------------------------------------------
2749 ;|Mnemonic |SZHPNC|Description |Notes |
2750 ;----------------------------------------------------------------
2751 ;|RRA |--0-0*|Rotate Right Acc. |A=->{CY,A} |
2752 ;|----------|SZHP C|---------- 8080 ----------------------------|
2753 ;|RRA |---- *|Rotate Right Acc. |A=->{CY,A} |
2754 ;
2755 ;
2756 do_op_rr:
2757 ;Rotate Right. All bits move 1 to the right, the lsb
2758 ;becomes c, c becomes msb.
2759 clc ; get z80 carry to avr carry
2760 sbrc z_flags,ZFL_C
2761 sec
2762 do_z80_flags_op_rotate ; (clear ZFL_C, doesn't change AVR_C)
2763 bmov z_flags,ZFL_C, opl,0 ; Bit 0 --> CY
2764 ror opl
2765 ret
2766
2767 ;----------------------------------------------------------------
2768 ;|Mnemonic |SZHPNC|Description |Notes |
2769 ;----------------------------------------------------------------
2770 ;|RLA |--0-0*|Rotate Left Acc. |A={CY,A}<- |
2771 ;|----------|SZHP C|---------- 8080 ----------------------------|
2772 ;|RLA |---- *|Rotate Left Acc. |A={CY,A}<- |
2773 ;
2774 ;
2775 do_op_rl:
2776 ;Rotate Left. All bits move 1 to the left, the msb
2777 ;becomes c, c becomes lsb.
2778 clc
2779 sbrc z_flags,ZFL_C
2780 sec
2781 do_z80_flags_op_rotate ; (clear ZFL_C, doesn't change AVR_C)
2782 bmov z_flags,ZFL_C, opl,7 ; Bit 7 --> CY
2783 rol opl
2784 ret
2785
2786 ;----------------------------------------------------------------
2787 ;|Mnemonic |SZHPNC|Description |Notes |
2788 ;----------------------------------------------------------------
2789 ;|ADD A,s |***V0*|Add |A=A+s |
2790 ;|----------|SZHP C|---------- 8080 ----------------------------|
2791 ;|ADD A,s |***P *|Add |A=A+s |
2792 ;
2793 ;
2794 do_op_adda:
2795 add opl,z_a
2796 in temp,sreg
2797 ldpmx z_flags,sz53p_tab,opl ;S,Z,P flag
2798 bmov z_flags,ZFL_C, temp,AVR_C
2799 do_z80_flags_HP
2800 ret
2801
2802 ;----------------------------------------------------------------
2803 ;|Mnemonic |SZHPNC|Description |Notes |
2804 ;----------------------------------------------------------------
2805 ;|ADC A,s |***V0*|Add with Carry |A=A+s+CY |
2806 ;|----------|SZHP C|---------- 8080 ----------------------------|
2807 ;|ADC A,s |***P *|Add with Carry |A=A+s+CY |
2808 ;
2809 ;
2810 do_op_adca:
2811 clc
2812 sbrc z_flags,ZFL_C
2813 sec
2814 adc opl,z_a
2815 in temp,sreg
2816 ldpmx z_flags,sz53p_tab,opl ;S,Z,P
2817 bmov z_flags,ZFL_C, temp,AVR_C
2818 do_z80_flags_HP
2819 ret
2820
2821 ;----------------------------------------------------------------
2822 ;|Mnemonic |SZHPNC|Description |Notes |
2823 ;----------------------------------------------------------------
2824 ;|SUB s |***V1*|Subtract |A=A-s |
2825 ;|CP s |***V1*|Compare |A-s |
2826 ;|----------|SZHP C|---------- 8080 ----------------------------|
2827 ;|SUB s |***P *|Subtract |A=A-s |
2828 ;|CP s |***P *|Compare |A-s |
2829
2830 ;
2831 do_op_subfa:
2832 mov temp,z_a
2833 sub temp,opl
2834 mov opl,temp
2835 in temp,sreg
2836 ldpmx z_flags,sz53p_tab,opl ;S,Z,P
2837 bmov z_flags,ZFL_C, temp,AVR_C
2838 do_z80_flags_HP
2839 do_z80_flags_set_N
2840 ret
2841
2842 ;----------------------------------------------------------------
2843 ;|Mnemonic |SZHPNC|Description |Notes |
2844 ;----------------------------------------------------------------
2845 ;|SBC A,s |***V1*|Subtract with Carry |A=A-s-CY |
2846 ;|----------|SZHP C|---------- 8080 ----------------------------|
2847 ;|SBC A,s |***P *|Subtract with Carry |A=A-s-CY |
2848 ;
2849 ;
2850 do_op_sbcfa:
2851 mov temp,z_a
2852 clc
2853 sbrc z_flags,ZFL_C
2854 sec
2855 sbc temp,opl
2856 mov opl,temp
2857 in temp,sreg
2858 ldpmx z_flags,sz53p_tab,opl ;S,Z,P
2859 bmov z_flags,ZFL_C, temp,AVR_C
2860 do_z80_flags_HP
2861 do_z80_flags_set_N
2862 ret
2863
2864 ;----------------------------------------------------------------
2865 ;|Mnemonic |SZHPNC|Description |Notes |
2866 ;----------------------------------------------------------------
2867 ;|AND s |**1P00|Logical AND |A=A&s |
2868 ;|----------|SZHP C|---------- 8080 ----------------------------|
2869 ;|AND s |**-P 0|Logical AND |A=A&s |
2870 ;
2871 ; TODO H-Flag
2872 do_op_anda:
2873 and opl,z_a ;
2874 ldpmx z_flags,sz53p_tab,opl ;S,Z,P,N,C
2875 do_z80_flags_op_and
2876 ret
2877
2878
2879 ;----------------------------------------------------------------
2880 ;|Mnemonic |SZHPNC|Description |Notes |
2881 ;----------------------------------------------------------------
2882 ;|OR s |**0P00|Logical inclusive OR |A=Avs |
2883 ;|----------|SZHP C|---------- 8080 ----------------------------|
2884 ;|OR s |**-P00|Logical inclusive OR |A=Avs |
2885 ;
2886 ; TODO: H-Flag
2887 do_op_ora:
2888 or opl,z_a
2889 ldpmx z_flags,sz53p_tab,opl ;S,Z,H,P,N,C
2890 do_z80_flags_op_or
2891 ret
2892
2893 ;----------------------------------------------------------------
2894 ;|Mnemonic |SZHPNC|Description |Notes |
2895 ;----------------------------------------------------------------
2896 ;|XOR s |**0P00|Logical Exclusive OR |A=Axs |
2897 ;|----------|SZHP C|---------- 8080 ----------------------------|
2898 ;|XOR s |**-P 0|Logical Exclusive OR |A=Axs |
2899 ;
2900 ; TODO: H-Flag
2901 do_op_xora:
2902 eor opl,z_a
2903 ldpmx z_flags,sz53p_tab,opl ;S,Z,H,P,N,C
2904 do_z80_flags_op_or
2905 ret
2906
2907 ;----------------------------------------------------------------
2908 ;|Mnemonic |SZHPNC|Description |Notes |
2909 ;----------------------------------------------------------------
2910 ;|ADD HL,ss |--?-0*|Add |HL=HL+ss |
2911 ;|----------|SZHP C|---------- 8080 ----------------------------|
2912 ;|ADD HL,ss |---- *|Add |HL=HL+ss |
2913 ;
2914 ;
2915 do_op_addhl:
2916 add opl,z_l
2917 adc oph,z_h
2918 in temp,sreg
2919 bmov z_flags,ZFL_H, temp,AVR_H
2920 bmov z_flags,ZFL_C, temp,AVR_C
2921 do_z80_flags_clear_N
2922 ret
2923
2924 ;----------------------------------------------------------------
2925 ;|Mnemonic |SZHPNC|Description |Notes |
2926 ;----------------------------------------------------------------
2927 ;|LD dst,src|------|Load |dst=src |
2928 ;
2929 ;
2930 do_op_sthl: ;store hl to mem loc in opl:h
2931 movw adrl,opl
2932 #if DRAM_WORD_ACCESS
2933 mov temp,z_l
2934 mov temp2,z_h
2935 rcall memWriteWord
2936 #else
2937 mov temp,z_l
2938 rcall memWriteByte
2939 adiw adrl,1
2940 mov temp,z_h
2941 rcall memWriteByte
2942 #endif
2943 ret
2944
2945 ;----------------------------------------------------------------
2946 ;|Mnemonic |SZHPNC|Description |Notes |
2947 ;----------------------------------------------------------------
2948 ;|LD dst,src|------|Load |dst=src |
2949 ;
2950 ;
2951 do_op_rmem16:
2952 movw adrl,opl
2953 #if DRAM_WORD_ACCESS
2954 rcall memReadWord
2955 movw opl,temp
2956 #else
2957 rcall memReadByte
2958 mov opl,temp
2959 adiw adrl,1
2960 rcall memReadByte
2961 mov oph,temp
2962 #endif
2963 ret
2964
2965 ;----------------------------------------------------------------
2966 ;|Mnemonic |SZHPNC|Description |Notes |
2967 ;----------------------------------------------------------------
2968 ;|LD dst,src|------|Load |dst=src |
2969 ;
2970 ;
2971 do_op_rmem8:
2972 movw adrl,opl
2973 rcall memReadByte
2974 mov opl,temp
2975 ret
2976
2977 ;----------------------------------------------------------------
2978 ;|Mnemonic |SZHPNC|Description |Notes |
2979 ;----------------------------------------------------------------
2980 ;|DAA |***P-*|Decimal Adjust Acc. | |
2981 ;|----------|SZHP C|---------- 8080 ----------------------------|
2982 ;
2983 ; Not yet checked
2984
2985 ; Description (http://www.z80.info/z80syntx.htm#DAA):
2986 ; This instruction conditionally adjusts the accumulator for BCD addition
2987 ; and subtraction operations. For addition (ADD, ADC, INC) or subtraction
2988 ; (SUB, SBC, DEC, NEC), the following table indicates the operation performed:
2989 ;
2990 ; -------------------------------------------------------------------------------
2991 ; | | C Flag | HEX value in | H Flag | HEX value in | Number | C flag|
2992 ; | Operation| Before | upper digit | Before | lower digit | added | After |
2993 ; | | DAA | (bit 7-4) | DAA | (bit 3-0) | to byte | DAA |
2994 ; |-----------------------------------------------------------------------------|
2995 ; | | 0 | 0-9 | 0 | 0-9 | 00 | 0 |
2996 ; | ADD | 0 | 0-8 | 0 | A-F | 06 | 0 |
2997 ; | | 0 | 0-9 | 1 | 0-3 | 06 | 0 |
2998 ; | ADC | 0 | A-F | 0 | 0-9 | 60 | 1 |
2999 ; | | 0 | 9-F | 0 | A-F | 66 | 1 |
3000 ; | INC | 0 | A-F | 1 | 0-3 | 66 | 1 |
3001 ; | | 1 | 0-2 | 0 | 0-9 | 60 | 1 |
3002 ; | | 1 | 0-2 | 0 | A-F | 66 | 1 |
3003 ; | | 1 | 0-3 | 1 | 0-3 | 66 | 1 |
3004 ; |-----------------------------------------------------------------------------|
3005 ; | SUB | 0 | 0-9 | 0 | 0-9 | 00 | 0 |
3006 ; | SBC | 0 | 0-8 | 1 | 6-F | FA | 0 |
3007 ; | DEC | 1 | 7-F | 0 | 0-9 | A0 | 1 |
3008 ; | NEG | 1 | 6-F | 1 | 6-F | 9A | 1 |
3009 ; |-----------------------------------------------------------------------------|
3010 ;
3011 ; Flags:
3012 ; C: See instruction.
3013 ; N: Unaffected.
3014 ; P/V: Set if Acc. is even parity after operation, reset otherwise.
3015 ; H: See instruction.
3016 ; Z: Set if Acc. is Zero after operation, reset otherwise.
3017 ; S: Set if most significant bit of Acc. is 1 after operation, reset otherwise.
3018
3019
3020
3021 #if 1
3022 do_op_da:
3023 ldi oph,0 ; what to add
3024 sbrc z_flags,ZFL_H ; if H-Flag
3025 rjmp op_da_06
3026 mov temp,opl
3027 andi temp,0x0f ; ... or lower digit > 9
3028 cpi temp,0x0a
3029 brlo op_da_06n
3030 op_da_06:
3031 ori oph,0x06
3032 op_da_06n:
3033 sbrc z_flags,(1<<ZFL_C)
3034 rjmp op_da_60
3035 cpi opl,0xa0
3036 brlo op_da_60n
3037 op_da_60:
3038 ori oph,0x60
3039 op_da_60n:
3040 cpi opl,0x9a
3041 brlo op_da_99n
3042 ori z_flags,(1<<ZFL_C); set C
3043 op_da_99n:
3044 sbrs z_flags,ZFL_N ; if sub-op
3045 rjmp op_da_add ; then
3046 sub opl,oph
3047 rjmp op_da_ex
3048 op_da_add: ; else add-op
3049 cpi opl,0x91
3050 brlo op_da_60n2
3051 mov temp,opl
3052 andi temp,0x0f
3053 cpi temp,0x0a
3054 brlo op_da_60n2
3055 ori oph,0x60
3056 op_da_60n2:
3057 add opl,oph
3058 op_da_ex:
3059 in temp,SREG
3060 sbrc temp,AVR_H
3061 ori z_flags,(1<<ZFL_C)
3062 andi z_flags,(1<<ZFL_N)|(1<<ZFL_C) ; preserve C,N
3063 ldpmx temp2, sz53p_tab, opl ; get S,Z,P
3064 or z_flags,temp2
3065 bmov z_flags,ZFL_H, temp,AVR_H ; H (?)
3066 ret
3067 #else
3068
3069 do_op_da:
3070 sbrc z_flags,ZFL_N ; if add-op
3071 rjmp do_op_da_sub ; then
3072 ldi temp2,0 ;
3073 mov temp,opl ;
3074 andi temp,0x0f ;
3075 cpi temp,0x0a ; if lower digit > 9
3076 brlo do_op_da_h ;
3077 ori temp2,0x06 ; add 6 to lower digit
3078 do_op_da_h: ;
3079 sbrc z_flags,ZFL_H ; ... or H-Flag
3080 ori temp2,0x06 ;
3081 add opl,temp2 ;
3082
3083 ldi temp2,0 ;
3084 mov temp,opl ;
3085 andi temp,0xf0 ;
3086 cpi temp,0xa0 ;
3087 brlo do_op_da_c ;
3088 ori temp2,0x60 ;
3089 do_op_da_c: ; else sub-op
3090 sbrc z_flags,ZFL_C ;
3091 ori temp2,0x60 ;
3092 andi z_flags, ~( (1<<ZFL_S) | (1<<ZFL_Z) | (1<<ZFL_H) )
3093 add opl,temp2 ;
3094 in temp,SREG ;
3095 bst temp,AVR_Z ;Z-Flag
3096 bld z_flags,ZFL_Z ;
3097 bst temp,AVR_N ;S-Flag
3098 bst z_flags,ZFL_S ;
3099 sbrc temp2,5 ;C-Flag, set if 0x06 added
3100 ori z_flags,(1<<ZFL_C) ;
3101 ;H-Flag?
3102 ret
3103
3104 do_op_da_sub: ;TODO:
3105 rcall do_op_inv
3106 ret
3107 #endif
3108
3109 ;----------------------------------------------------------------
3110 ;|Mnemonic |SZHPNC|Description |Notes |
3111 ;----------------------------------------------------------------
3112 ;|SCF |--0-01|Set Carry Flag |CY=1 |
3113 ;|----------|SZHP C|---------- 8080 ----------------------------|
3114 ;
3115 ;
3116 do_op_scf:
3117 andi z_flags,~((1<<ZFL_H)|(1<<ZFL_N))
3118 ori z_flags,(1<<ZFL_C)
3119 ret
3120
3121 ;----------------------------------------------------------------
3122 ;|Mnemonic |SZHPNC|Description |Notes |
3123 ;----------------------------------------------------------------
3124 ;|CCF |--?-0*|Complement Carry Flag|CY=~CY |
3125 ;|----------|SZHP C|---------- 8080 ----------------------------|
3126 ;|SCF |---- 1|Set Carry Flag |CY=1 |
3127 ;
3128 ;TODO: H-Flag
3129 do_op_ccf:
3130 do_z80_flags_clear_N
3131 ldi temp,(1<<ZFL_C)
3132 eor z_flags,temp
3133 ret
3134
3135 ;----------------------------------------------------------------
3136 ;|Mnemonic |SZHPNC|Description |Notes |
3137 ;----------------------------------------------------------------
3138 ;|CPL |--1-1-|Complement |A=~A |
3139 ;|----------|SZHP C|---------- 8080 ----------------------------|
3140 ;|CPL |---- -|Complement |A=~A |
3141 ;
3142 ;
3143 do_op_cpl:
3144 com opl
3145 do_z80_flags_set_HN
3146 ret
3147
3148
3149 ;----------------------------------------------------------------
3150 ;|Mnemonic |SZHPNC|Description |Notes |
3151 ;----------------------------------------------------------------
3152 ;|PUSH xx |------|Push |-[SP]=xx |
3153 ;|PUSH qq |------|Push |-[SP]=qq |
3154 ;
3155 ;
3156 do_op_push16:
3157 movw adrl,z_spl
3158 subi adrl,2
3159 sbci adrh,0
3160 movw z_spl,adrl
3161 #if DRAM_WORD_ACCESS
3162 movw temp,opl
3163 rcall memWriteWord
3164 #else
3165 mov temp,opl
3166 rcall memWriteByte
3167 adiw adrl,1
3168 mov temp,oph
3169 rcall memWriteByte
3170 #endif
3171
3172 .if STACK_DBG
3173 rcall printstr
3174 .db "Stack push ",0
3175 mov temp,oph
3176 rcall printhex
3177 mov temp,opl
3178 rcall printhex
3179 rcall printstr
3180 .db ", SP is now ",0
3181 mov temp,z_sph
3182 rcall printhex
3183 mov temp,z_spl
3184 rcall printhex
3185 rcall printstr
3186 .db ".",13,0
3187 .endif
3188
3189 ret
3190
3191 ;----------------------------------------------------------------
3192 ;|Mnemonic |SZHPNC|Description |Notes |
3193 ;----------------------------------------------------------------
3194 ;|POP xx |------|Pop |xx=[SP]+ |
3195 ;|POP qq |------|Pop |qq=[SP]+ |
3196 ;
3197 ;
3198 do_op_pop16:
3199 movw adrl,z_spl
3200 #if DRAM_WORD_ACCESS
3201 rcall memReadWord
3202 movw opl,temp
3203 #else
3204 rcall memReadByte
3205 mov opl,temp
3206 adiw adrl,1
3207 rcall memReadByte
3208 mov oph,temp
3209 #endif
3210
3211 ldi temp,2
3212 add z_spl,temp
3213 adc z_sph,_0
3214
3215 .if STACK_DBG
3216 rcall printstr
3217 .db "Stack pop: val ",0
3218 mov temp,oph
3219 rcall printhex
3220 mov temp,opl
3221 rcall printhex
3222 rcall printstr
3223 .db ", SP is now",0
3224 mov temp,z_sph
3225 rcall printhex
3226 mov temp,z_spl
3227 rcall printhex
3228 rcall printstr
3229 .db ".",13,0
3230 .endif
3231 ret
3232
3233 ;----------------------------------------------------------------
3234 ;|Mnemonic |SZHPNC|Description |Notes |
3235 ;----------------------------------------------------------------
3236 ;|EX [SP],HL|------|Exchange |[SP]<->HL |
3237 ;|EX DE,HL |------|Exchange |DE<->HL |
3238 ;
3239 ;
3240 do_op_exhl:
3241 mov temp,z_h
3242 mov z_h,oph
3243 mov oph,temp
3244 mov temp,z_l
3245 mov z_l,opl
3246 mov opl,temp
3247 ret
3248
3249 ;----------------------------------------------------------------
3250 ;|Mnemonic |SZHPNC|Description |Notes |
3251 ;----------------------------------------------------------------
3252 ;
3253 ; TODO: Implement IFF1, IFF2
3254 do_op_di:
3255 ret
3256
3257 ;----------------------------------------------------------------
3258 ;|Mnemonic |SZHPNC|Description |Notes |
3259 ;----------------------------------------------------------------
3260 ;
3261 ; TODO: Implement IFF1, IFF2
3262 do_op_ei:
3263 ret
3264
3265 ;----------------------------------------------------------------
3266 ;|Mnemonic |SZHPNC|Description |Notes |
3267 ;----------------------------------------------------------------
3268 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3269 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3270 ;|RET cc |------|Conditional Return |If cc RET |
3271 ;
3272 ;
3273 do_op_ifnz:
3274 sbrs z_flags, ZFL_Z
3275 ret
3276 ldi insdech, 0
3277 ldi insdecl, 0
3278 ret
3279
3280 ;----------------------------------------------------------------
3281 ;|Mnemonic |SZHPNC|Description |Notes |
3282 ;----------------------------------------------------------------
3283 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3284 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3285 ;|RET cc |------|Conditional Return |If cc RET |
3286 ;
3287 ;
3288 do_op_ifz:
3289 sbrc z_flags, ZFL_Z
3290 ret
3291 ldi insdech, 0
3292 ldi insdecl, 0
3293 ret
3294
3295 ;----------------------------------------------------------------
3296 ;|Mnemonic |SZHPNC|Description |Notes |
3297 ;----------------------------------------------------------------
3298 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3299 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3300 ;|RET cc |------|Conditional Return |If cc RET |
3301 ;
3302 ;
3303 do_op_ifnc:
3304 sbrs z_flags, ZFL_C
3305 ret
3306 ldi insdech, 0
3307 ldi insdecl, 0
3308 ret
3309
3310 ;----------------------------------------------------------------
3311 ;|Mnemonic |SZHPNC|Description |Notes |
3312 ;----------------------------------------------------------------
3313 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3314 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3315 ;|RET cc |------|Conditional Return |If cc RET |
3316 ;
3317 ;
3318 do_op_ifc:
3319 sbrc z_flags, ZFL_C
3320 ret
3321 ldi insdech, 0
3322 ldi insdecl, 0
3323 ret
3324
3325 ;----------------------------------------------------------------
3326 ;|Mnemonic |SZHPNC|Description |Notes |
3327 ;----------------------------------------------------------------
3328 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3329 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3330 ;|RET cc |------|Conditional Return |If cc RET |
3331 ;
3332 ;
3333 do_op_ifpo:
3334 sbrs z_flags, ZFL_P
3335 ret
3336 ldi insdech, 0
3337 ldi insdecl, 0
3338 ret
3339
3340 ;----------------------------------------------------------------
3341 ;|Mnemonic |SZHPNC|Description |Notes |
3342 ;----------------------------------------------------------------
3343 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3344 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3345 ;|RET cc |------|Conditional Return |If cc RET |
3346 ;
3347 ;
3348 do_op_ifpe:
3349 sbrc z_flags, ZFL_P
3350 ret
3351 ldi insdech, 0
3352 ldi insdecl, 0
3353 ret
3354
3355 ;----------------------------------------------------------------
3356 ;|Mnemonic |SZHPNC|Description |Notes |
3357 ;----------------------------------------------------------------
3358 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3359 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3360 ;|RET cc |------|Conditional Return |If cc RET |
3361 ;
3362 ;
3363 do_op_ifp: ;sign positive, aka s=0
3364 sbrs z_flags, ZFL_S
3365 ret
3366 ldi insdech,0
3367 ldi insdecl,0
3368 ret
3369
3370 ;----------------------------------------------------------------
3371 ;|Mnemonic |SZHPNC|Description |Notes |
3372 ;----------------------------------------------------------------
3373 ;|CALL cc,nn|------|Conditional Call |If cc CALL |
3374 ;|JP cc,nn |------|Conditional Jump |If cc JP |
3375 ;|RET cc |------|Conditional Return |If cc RET |
3376 ;
3377 ;
3378 do_op_ifm: ;sign negative, aka s=1
3379 sbrc z_flags, ZFL_S
3380 ret
3381 ldi insdech, 0
3382 ldi insdecl, 0
3383 ret
3384
3385 ;----------------------------------------------------------------
3386 ;|Mnemonic |SZHPNC|Description |Notes |
3387 ;----------------------------------------------------------------
3388 ;|OUT [n],A |------|Output |[n]=A |
3389 ;
3390 ;
3391 ;Interface with peripherials goes here :)
3392 do_op_outa: ; out (opl),a
3393 .if PORT_DEBUG
3394 rcall printstr
3395 .db 13,"Port write: ",0
3396 mov temp,z_a
3397 rcall printhex
3398 rcall printstr
3399 .db " -> (",0
3400 mov temp,opl
3401 rcall printhex
3402 rcall printstr
3403 .db ")",13,0
3404 .endif
3405 mov temp,z_a
3406 mov temp2,opl
3407 rcall portWrite
3408 ret
3409
3410 ;----------------------------------------------------------------
3411 ;|Mnemonic |SZHPNC|Description |Notes |
3412 ;----------------------------------------------------------------
3413 ;|IN A,[n] |------|Input |A=[n] |
3414 ;
3415 ;
3416 do_op_in: ; in a,(opl)
3417 .if PORT_DEBUG
3418 rcall printstr
3419 .db 13,"Port read: (",0
3420 mov temp,opl
3421 rcall printhex
3422 rcall printstr
3423 .db ") -> ",0
3424 .endif
3425
3426 mov temp2,opl
3427 rcall portRead
3428 mov opl,temp
3429
3430 .if PORT_DEBUG
3431 rcall printhex
3432 rcall printstr
3433 .db 13,0
3434 .endif
3435 ret
3436
3437
3438 ;----------------------------------------------------------------
3439 do_op_inv:
3440 rcall printstr
3441 .db "Invalid opcode @ PC=",0,0
3442 mov temp,z_pch
3443 rcall printhex
3444 mov temp,z_pcl
3445 rcall printhex
3446
3447 ;----------------------------------------------------------------
3448 haltinv:
3449 rjmp haltinv
3450
3451 ;----------------------------------------------------------------
3452 ; Lookup table, stolen from z80ex, Z80 emulation library.
3453 ; http://z80ex.sourceforge.net/
3454
3455 ; The S, Z, 5 and 3 bits and the parity of the lookup value
3456 .org (PC+255) & 0xff00
3457 sz53p_tab:
3458 .db 0x44,0x00,0x00,0x04,0x00,0x04,0x04,0x00
3459 .db 0x08,0x0c,0x0c,0x08,0x0c,0x08,0x08,0x0c
3460 .db 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04
3461 .db 0x0c,0x08,0x08,0x0c,0x08,0x0c,0x0c,0x08
3462 .db 0x20,0x24,0x24,0x20,0x24,0x20,0x20,0x24
3463 .db 0x2c,0x28,0x28,0x2c,0x28,0x2c,0x2c,0x28
3464 .db 0x24,0x20,0x20,0x24,0x20,0x24,0x24,0x20
3465 .db 0x28,0x2c,0x2c,0x28,0x2c,0x28,0x28,0x2c
3466 .db 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04
3467 .db 0x0c,0x08,0x08,0x0c,0x08,0x0c,0x0c,0x08
3468 .db 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00
3469 .db 0x08,0x0c,0x0c,0x08,0x0c,0x08,0x08,0x0c
3470 .db 0x24,0x20,0x20,0x24,0x20,0x24,0x24,0x20
3471 .db 0x28,0x2c,0x2c,0x28,0x2c,0x28,0x28,0x2c
3472 .db 0x20,0x24,0x24,0x20,0x24,0x20,0x20,0x24
3473 .db 0x2c,0x28,0x28,0x2c,0x28,0x2c,0x2c,0x28
3474 .db 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84
3475 .db 0x8c,0x88,0x88,0x8c,0x88,0x8c,0x8c,0x88
3476 .db 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80
3477 .db 0x88,0x8c,0x8c,0x88,0x8c,0x88,0x88,0x8c
3478 .db 0xa4,0xa0,0xa0,0xa4,0xa0,0xa4,0xa4,0xa0
3479 .db 0xa8,0xac,0xac,0xa8,0xac,0xa8,0xa8,0xac
3480 .db 0xa0,0xa4,0xa4,0xa0,0xa4,0xa0,0xa0,0xa4
3481 .db 0xac,0xa8,0xa8,0xac,0xa8,0xac,0xac,0xa8
3482 .db 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80
3483 .db 0x88,0x8c,0x8c,0x88,0x8c,0x88,0x88,0x8c
3484 .db 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84
3485 .db 0x8c,0x88,0x88,0x8c,0x88,0x8c,0x8c,0x88
3486 .db 0xa0,0xa4,0xa4,0xa0,0xa4,0xa0,0xa0,0xa4
3487 .db 0xac,0xa8,0xa8,0xac,0xa8,0xac,0xac,0xa8
3488 .db 0xa4,0xa0,0xa0,0xa4,0xa0,0xa4,0xa4,0xa0
3489 .db 0xa8,0xac,0xac,0xa8,0xac,0xa8,0xa8,0xac
3490
3491
3492 ; ----------------------- Opcode decoding -------------------------
3493
3494 ; Lookup table for Z80 opcodes. Translates the first byte of the instruction word into three
3495 ; operations: fetch, do something, store.
3496 ; The table is made of 256 words. These 16-bit words consist of
3497 ; the fetch operation (bit 0-4), the processing operation (bit 10-16) and the store
3498 ; operation (bit 5-9).
3499
3500 .org (PC+255) & 0xff00
3501 inst_table:
3502 .dw (FETCH_NOP | OP_NOP | STORE_NOP) ; 00 NOP
3503 .dw (FETCH_DIR16| OP_NOP | STORE_BC ) ; 01 nn nn LD BC,nn
3504 .dw (FETCH_A | OP_NOP | STORE_MBC) ; 02 LD (BC),A
3505 .dw (FETCH_BC | OP_INC16 | STORE_BC ) ; 03 INC BC
3506 .dw (FETCH_B | OP_INC | STORE_B ) ; 04 INC B
3507 .dw (FETCH_B | OP_DEC | STORE_B ) ; 05 DEC B
3508 .dw (FETCH_DIR8 | OP_NOP | STORE_B ) ; 06 nn LD B,n
3509 .dw (FETCH_A | OP_RLC | STORE_A ) ; 07 RLCA
3510 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 08 EX AF,AF' (Z80)
3511 .dw (FETCH_BC | OP_ADDHL | STORE_HL ) ; 09 ADD HL,BC
3512 .dw (FETCH_MBC | OP_NOP | STORE_A ) ; 0A LD A,(BC)
3513 .dw (FETCH_BC | OP_DEC16 | STORE_BC ) ; 0B DEC BC
3514 .dw (FETCH_C | OP_INC | STORE_C ) ; 0C INC C
3515 .dw (FETCH_C | OP_DEC | STORE_C ) ; 0D DEC C
3516 .dw (FETCH_DIR8 | OP_NOP | STORE_C ) ; 0E nn LD C,n
3517 .dw (FETCH_A | OP_RRC | STORE_A ) ; 0F RRCA
3518 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 10 oo DJNZ o (Z80)
3519 .dw (FETCH_DIR16| OP_NOP | STORE_DE ) ; 11 nn nn LD DE,nn
3520 .dw (FETCH_A | OP_NOP | STORE_MDE) ; 12 LD (DE),A
3521 .dw (FETCH_DE | OP_INC16 | STORE_DE ) ; 13 INC DE
3522 .dw (FETCH_D | OP_INC | STORE_D ) ; 14 INC D
3523 .dw (FETCH_D | OP_DEC | STORE_D ) ; 15 DEC D
3524 .dw (FETCH_DIR8 | OP_NOP | STORE_D ) ; 16 nn LD D,n
3525 .dw (FETCH_A | OP_RL | STORE_A ) ; 17 RLA
3526 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 18 oo JR o (Z80)
3527 .dw (FETCH_DE | OP_ADDHL | STORE_HL ) ; 19 ADD HL,DE
3528 .dw (FETCH_MDE | OP_NOP | STORE_A ) ; 1A LD A,(DE)
3529 .dw (FETCH_DE | OP_DEC16 | STORE_DE ) ; 1B DEC DE
3530 .dw (FETCH_E | OP_INC | STORE_E ) ; 1C INC E
3531 .dw (FETCH_E | OP_DEC | STORE_E ) ; 1D DEC E
3532 .dw (FETCH_DIR8 | OP_NOP | STORE_E ) ; 1E nn LD E,n
3533 .dw (FETCH_A | OP_RR | STORE_A ) ; 1F RRA
3534 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 20 oo JR NZ,o (Z80)
3535 .dw (FETCH_DIR16| OP_NOP | STORE_HL ) ; 21 nn nn LD HL,nn
3536 .dw (FETCH_DIR16| OP_STHL | STORE_NOP) ; 22 nn nn LD (nn),HL
3537 .dw (FETCH_HL | OP_INC16 | STORE_HL ) ; 23 INC HL
3538 .dw (FETCH_H | OP_INC | STORE_H ) ; 24 INC H
3539 .dw (FETCH_H | OP_DEC | STORE_H ) ; 25 DEC H
3540 .dw (FETCH_DIR8 | OP_NOP | STORE_H ) ; 26 nn LD H,n
3541 .dw (FETCH_A | OP_DA | STORE_A ) ; 27 DAA
3542 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 28 oo JR Z,o (Z80)
3543 .dw (FETCH_HL | OP_ADDHL | STORE_HL ) ; 29 ADD HL,HL
3544 .dw (FETCH_DIR16| OP_RMEM16 | STORE_HL ) ; 2A nn nn LD HL,(nn)
3545 .dw (FETCH_HL | OP_DEC16 | STORE_HL ) ; 2B DEC HL
3546 .dw (FETCH_L | OP_INC | STORE_L ) ; 2C INC L
3547 .dw (FETCH_L | OP_DEC | STORE_L ) ; 2D DEC L
3548 .dw (FETCH_DIR8 | OP_NOP | STORE_L ) ; 2E nn LD L,n
3549 .dw (FETCH_A | OP_CPL | STORE_A ) ; 2F CPL
3550 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 30 oo JR NC,o (Z80)
3551 .dw (FETCH_DIR16| OP_NOP | STORE_SP ) ; 31 nn nn LD SP,nn
3552 .dw (FETCH_DIR16| OP_NOP | STORE_AM ) ; 32 nn nn LD (nn),A
3553 .dw (FETCH_SP | OP_INC16 | STORE_SP ) ; 33 INC SP
3554 .dw (FETCH_MHL | OP_INC | STORE_MHL) ; 34 INC (HL)
3555 .dw (FETCH_MHL | OP_DEC | STORE_MHL) ; 35 DEC (HL)
3556 .dw (FETCH_DIR8 | OP_NOP | STORE_MHL) ; 36 nn LD (HL),n
3557 .dw (FETCH_NOP | OP_SCF | STORE_NOP) ; 37 SCF
3558 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; 38 oo JR C,o (Z80)
3559 .dw (FETCH_SP | OP_ADDHL | STORE_HL ) ; 39 ADD HL,SP
3560 .dw (FETCH_DIR16| OP_RMEM8 | STORE_A ) ; 3A nn nn LD A,(nn)
3561 .dw (FETCH_SP | OP_DEC16 | STORE_SP ) ; 3B DEC SP
3562 .dw (FETCH_A | OP_INC | STORE_A ) ; 3C INC A
3563 .dw (FETCH_A | OP_DEC | STORE_A ) ; 3D DEC A
3564 .dw (FETCH_DIR8 | OP_NOP | STORE_A ) ; 3E nn LD A,n
3565 .dw (FETCH_NOP | OP_CCF | STORE_NOP) ; 3F CCF (Complement Carry Flag, gvd)
3566 .dw (FETCH_B | OP_NOP | STORE_B ) ; 40 LD B,r
3567 .dw (FETCH_C | OP_NOP | STORE_B ) ; 41 LD B,r
3568 .dw (FETCH_D | OP_NOP | STORE_B ) ; 42 LD B,r
3569 .dw (FETCH_E | OP_NOP | STORE_B ) ; 43 LD B,r
3570 .dw (FETCH_H | OP_NOP | STORE_B ) ; 44 LD B,r
3571 .dw (FETCH_L | OP_NOP | STORE_B ) ; 45 LD B,r
3572 .dw (FETCH_MHL | OP_NOP | STORE_B ) ; 46 LD B,r
3573 .dw (FETCH_A | OP_NOP | STORE_B ) ; 47 LD B,r
3574 .dw (FETCH_B | OP_NOP | STORE_C ) ; 48 LD C,r
3575 .dw (FETCH_C | OP_NOP | STORE_C ) ; 49 LD C,r
3576 .dw (FETCH_D | OP_NOP | STORE_C ) ; 4A LD C,r
3577 .dw (FETCH_E | OP_NOP | STORE_C ) ; 4B LD C,r
3578 .dw (FETCH_H | OP_NOP | STORE_C ) ; 4C LD C,r
3579 .dw (FETCH_L | OP_NOP | STORE_C ) ; 4D LD C,r
3580 .dw (FETCH_MHL | OP_NOP | STORE_C ) ; 4E LD C,r
3581 .dw (FETCH_A | OP_NOP | STORE_C ) ; 4F LD C,r
3582 .dw (FETCH_B | OP_NOP | STORE_D ) ; 50 LD D,r
3583 .dw (FETCH_C | OP_NOP | STORE_D ) ; 51 LD D,r
3584 .dw (FETCH_D | OP_NOP | STORE_D ) ; 52 LD D,r
3585 .dw (FETCH_E | OP_NOP | STORE_D ) ; 53 LD D,r
3586 .dw (FETCH_H | OP_NOP | STORE_D ) ; 54 LD D,r
3587 .dw (FETCH_L | OP_NOP | STORE_D ) ; 55 LD D,r
3588 .dw (FETCH_MHL | OP_NOP | STORE_D ) ; 56 LD D,r
3589 .dw (FETCH_A | OP_NOP | STORE_D ) ; 57 LD D,r
3590 .dw (FETCH_B | OP_NOP | STORE_E ) ; 58 LD E,r
3591 .dw (FETCH_C | OP_NOP | STORE_E ) ; 59 LD E,r
3592 .dw (FETCH_D | OP_NOP | STORE_E ) ; 5A LD E,r
3593 .dw (FETCH_E | OP_NOP | STORE_E ) ; 5B LD E,r
3594 .dw (FETCH_H | OP_NOP | STORE_E ) ; 5C LD E,r
3595 .dw (FETCH_L | OP_NOP | STORE_E ) ; 5D LD E,r
3596 .dw (FETCH_MHL | OP_NOP | STORE_E ) ; 5E LD E,r
3597 .dw (FETCH_A | OP_NOP | STORE_E ) ; 5F LD E,r
3598 .dw (FETCH_B | OP_NOP | STORE_H ) ; 60 LD H,r
3599 .dw (FETCH_C | OP_NOP | STORE_H ) ; 61 LD H,r
3600 .dw (FETCH_D | OP_NOP | STORE_H ) ; 62 LD H,r
3601 .dw (FETCH_E | OP_NOP | STORE_H ) ; 63 LD H,r
3602 .dw (FETCH_H | OP_NOP | STORE_H ) ; 64 LD H,r
3603 .dw (FETCH_L | OP_NOP | STORE_H ) ; 65 LD H,r
3604 .dw (FETCH_MHL | OP_NOP | STORE_H ) ; 66 LD H,r
3605 .dw (FETCH_A | OP_NOP | STORE_H ) ; 67 LD H,r
3606 .dw (FETCH_B | OP_NOP | STORE_L ) ; 68 LD L,r
3607 .dw (FETCH_C | OP_NOP | STORE_L ) ; 69 LD L,r
3608 .dw (FETCH_D | OP_NOP | STORE_L ) ; 6A LD L,r
3609 .dw (FETCH_E | OP_NOP | STORE_L ) ; 6B LD L,r
3610 .dw (FETCH_H | OP_NOP | STORE_L ) ; 6C LD L,r
3611 .dw (FETCH_L | OP_NOP | STORE_L ) ; 6D LD L,r
3612 .dw (FETCH_MHL | OP_NOP | STORE_L ) ; 6E LD L,r
3613 .dw (FETCH_A | OP_NOP | STORE_L ) ; 6F LD L,r
3614 .dw (FETCH_B | OP_NOP | STORE_MHL) ; 70 LD (HL),r
3615 .dw (FETCH_C | OP_NOP | STORE_MHL) ; 71 LD (HL),r
3616 .dw (FETCH_D | OP_NOP | STORE_MHL) ; 72 LD (HL),r
3617 .dw (FETCH_E | OP_NOP | STORE_MHL) ; 73 LD (HL),r
3618 .dw (FETCH_H | OP_NOP | STORE_MHL) ; 74 LD (HL),r
3619 .dw (FETCH_L | OP_NOP | STORE_MHL) ; 75 LD (HL),r
3620 .dw (FETCH_NOP | OP_NOP | STORE_NOP) ; 76 HALT
3621 .dw (FETCH_A | OP_NOP | STORE_MHL) ; 77 LD (HL),r
3622 .dw (FETCH_B | OP_NOP | STORE_A ) ; 78 LD A,r
3623 .dw (FETCH_C | OP_NOP | STORE_A ) ; 79 LD A,r
3624 .dw (FETCH_D | OP_NOP | STORE_A ) ; 7A LD A,r
3625 .dw (FETCH_E | OP_NOP | STORE_A ) ; 7B LD A,r
3626 .dw (FETCH_H | OP_NOP | STORE_A ) ; 7C LD A,r
3627 .dw (FETCH_L | OP_NOP | STORE_A ) ; 7D LD A,r
3628 .dw (FETCH_MHL | OP_NOP | STORE_A ) ; 7E LD A,r
3629 .dw (FETCH_A | OP_NOP | STORE_A ) ; 7F LD A,r
3630 .dw (FETCH_B | OP_ADDA | STORE_A ) ; 80 ADD A,r
3631 .dw (FETCH_C | OP_ADDA | STORE_A ) ; 81 ADD A,r
3632 .dw (FETCH_D | OP_ADDA | STORE_A ) ; 82 ADD A,r
3633 .dw (FETCH_E | OP_ADDA | STORE_A ) ; 83 ADD A,r
3634 .dw (FETCH_H | OP_ADDA | STORE_A ) ; 84 ADD A,r
3635 .dw (FETCH_L | OP_ADDA | STORE_A ) ; 85 ADD A,r
3636 .dw (FETCH_MHL | OP_ADDA | STORE_A ) ; 86 ADD A,r
3637 .dw (FETCH_A | OP_ADDA | STORE_A ) ; 87 ADD A,r
3638 .dw (FETCH_B | OP_ADCA | STORE_A ) ; 88 ADC A,r
3639 .dw (FETCH_C | OP_ADCA | STORE_A ) ; 89 ADC A,r
3640 .dw (FETCH_D | OP_ADCA | STORE_A ) ; 8A ADC A,r
3641 .dw (FETCH_E | OP_ADCA | STORE_A ) ; 8B ADC A,r
3642 .dw (FETCH_H | OP_ADCA | STORE_A ) ; 8C ADC A,r
3643 .dw (FETCH_L | OP_ADCA | STORE_A ) ; 8D ADC A,r
3644 .dw (FETCH_MHL | OP_ADCA | STORE_A ) ; 8E ADC A,r
3645 .dw (FETCH_A | OP_ADCA | STORE_A ) ; 8F ADC A,r
3646 .dw (FETCH_B | OP_SUBFA | STORE_A ) ; 90 SUB A,r
3647 .dw (FETCH_C | OP_SUBFA | STORE_A ) ; 91 SUB A,r
3648 .dw (FETCH_D | OP_SUBFA | STORE_A ) ; 92 SUB A,r
3649 .dw (FETCH_E | OP_SUBFA | STORE_A ) ; 93 SUB A,r
3650 .dw (FETCH_H | OP_SUBFA | STORE_A ) ; 94 SUB A,r
3651 .dw (FETCH_L | OP_SUBFA | STORE_A ) ; 95 SUB A,r
3652 .dw (FETCH_MHL | OP_SUBFA | STORE_A ) ; 96 SUB A,r
3653 .dw (FETCH_A | OP_SUBFA | STORE_A ) ; 97 SUB A,r
3654 .dw (FETCH_B | OP_SBCFA | STORE_A ) ; 98 SBC A,r
3655 .dw (FETCH_C | OP_SBCFA | STORE_A ) ; 99 SBC A,r
3656 .dw (FETCH_D | OP_SBCFA | STORE_A ) ; 9A SBC A,r
3657 .dw (FETCH_E | OP_SBCFA | STORE_A ) ; 9B SBC A,r
3658 .dw (FETCH_H | OP_SBCFA | STORE_A ) ; 9C SBC A,r
3659 .dw (FETCH_L | OP_SBCFA | STORE_A ) ; 9D SBC A,r
3660 .dw (FETCH_MHL | OP_SBCFA | STORE_A ) ; 9E SBC A,r
3661 .dw (FETCH_A | OP_SBCFA | STORE_A ) ; 9F SBC A,r
3662 .dw (FETCH_B | OP_ANDA | STORE_A ) ; A0 AND A,r
3663 .dw (FETCH_C | OP_ANDA | STORE_A ) ; A1 AND A,r
3664 .dw (FETCH_D | OP_ANDA | STORE_A ) ; A2 AND A,r
3665 .dw (FETCH_E | OP_ANDA | STORE_A ) ; A3 AND A,r
3666 .dw (FETCH_H | OP_ANDA | STORE_A ) ; A4 AND A,r
3667 .dw (FETCH_L | OP_ANDA | STORE_A ) ; A5 AND A,r
3668 .dw (FETCH_MHL | OP_ANDA | STORE_A ) ; A6 AND A,r
3669 .dw (FETCH_A | OP_ANDA | STORE_A ) ; A7 AND A,r
3670 .dw (FETCH_B | OP_XORA | STORE_A ) ; A8 XOR A,r
3671 .dw (FETCH_C | OP_XORA | STORE_A ) ; A9 XOR A,r
3672 .dw (FETCH_D | OP_XORA | STORE_A ) ; AA XOR A,r
3673 .dw (FETCH_E | OP_XORA | STORE_A ) ; AB XOR A,r
3674 .dw (FETCH_H | OP_XORA | STORE_A ) ; AC XOR A,r
3675 .dw (FETCH_L | OP_XORA | STORE_A ) ; AD XOR A,r
3676 .dw (FETCH_MHL | OP_XORA | STORE_A ) ; AE XOR A,r
3677 .dw (FETCH_A | OP_XORA | STORE_A ) ; AF XOR A,r
3678 .dw (FETCH_B | OP_ORA | STORE_A ) ; B0 OR A,r
3679 .dw (FETCH_C | OP_ORA | STORE_A ) ; B1 OR A,r
3680 .dw (FETCH_D | OP_ORA | STORE_A ) ; B2 OR A,r
3681 .dw (FETCH_E | OP_ORA | STORE_A ) ; B3 OR A,r
3682 .dw (FETCH_H | OP_ORA | STORE_A ) ; B4 OR A,r
3683 .dw (FETCH_L | OP_ORA | STORE_A ) ; B5 OR A,r
3684 .dw (FETCH_MHL | OP_ORA | STORE_A ) ; B6 OR A,r
3685 .dw (FETCH_A | OP_ORA | STORE_A ) ; B7 OR A,r
3686 .dw (FETCH_B | OP_SUBFA | STORE_NOP) ; B8 CP A,r
3687 .dw (FETCH_C | OP_SUBFA | STORE_NOP) ; B9 CP A,r
3688 .dw (FETCH_D | OP_SUBFA | STORE_NOP) ; BA CP A,r
3689 .dw (FETCH_E | OP_SUBFA | STORE_NOP) ; BB CP A,r
3690 .dw (FETCH_H | OP_SUBFA | STORE_NOP) ; BC CP A,r
3691 .dw (FETCH_L | OP_SUBFA | STORE_NOP) ; BD CP A,r
3692 .dw (FETCH_MHL | OP_SUBFA | STORE_NOP) ; BE CP A,r
3693 .dw (FETCH_A | OP_SUBFA | STORE_NOP) ; BF CP A,r
3694 .dw (FETCH_NOP | OP_IFNZ | STORE_RET) ; C0 RET NZ
3695 .dw (FETCH_NOP | OP_POP16 | STORE_BC ) ; C1 POP BC
3696 .dw (FETCH_DIR16| OP_IFNZ | STORE_PC ) ; C2 nn nn JP NZ,nn
3697 .dw (FETCH_DIR16| OP_NOP | STORE_PC ) ; C3 nn nn JP nn
3698 .dw (FETCH_DIR16| OP_IFNZ | STORE_CALL) ; C4 nn nn CALL NZ,nn
3699 .dw (FETCH_BC | OP_PUSH16 | STORE_NOP) ; C5 PUSH BC
3700 .dw (FETCH_DIR8 | OP_ADDA | STORE_A ) ; C6 nn ADD A,n
3701 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; C7 RST 0
3702 .dw (FETCH_NOP | OP_IFZ | STORE_RET) ; C8 RET Z
3703 .dw (FETCH_NOP | OP_NOP | STORE_RET) ; C9 RET
3704 .dw (FETCH_DIR16| OP_IFZ | STORE_PC ) ; CA nn nn JP Z,nn
3705 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; CB (Z80 specific)
3706 .dw (FETCH_DIR16| OP_IFZ | STORE_CALL) ; CC nn nn CALL Z,nn
3707 .dw (FETCH_DIR16| OP_NOP | STORE_CALL) ; CD nn nn CALL nn
3708 .dw (FETCH_DIR8 | OP_ADCA | STORE_A ) ; CE nn ADC A,n
3709 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; CF RST 8H
3710 .dw (FETCH_NOP | OP_IFNC | STORE_RET) ; D0 RET NC
3711 .dw (FETCH_NOP | OP_POP16 | STORE_DE ) ; D1 POP DE
3712 .dw (FETCH_DIR16| OP_IFNC | STORE_PC ) ; D2 nn nn JP NC,nn
3713 .dw (FETCH_DIR8 | OP_OUTA | STORE_NOP) ; D3 nn OUT (n),A
3714 .dw (FETCH_DIR16| OP_IFNC | STORE_CALL) ; D4 nn nn CALL NC,nn
3715 .dw (FETCH_DE | OP_PUSH16 | STORE_NOP) ; D5 PUSH DE
3716 .dw (FETCH_DIR8 | OP_SUBFA | STORE_A ) ; D6 nn SUB n
3717 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; D7 RST 10H
3718 .dw (FETCH_NOP | OP_IFC | STORE_RET) ; D8 RET C
3719 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; D9 EXX (Z80)
3720 .dw (FETCH_DIR16| OP_IFC | STORE_PC ) ; DA nn nn JP C,nn
3721 .dw (FETCH_DIR8 | OP_IN | STORE_A ) ; DB nn IN A,(n)
3722 .dw (FETCH_DIR16| OP_IFC | STORE_CALL) ; DC nn nn CALL C,nn
3723 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; DD (Z80)
3724 .dw (FETCH_DIR8 | OP_SBCFA | STORE_A ) ; DE nn SBC A,n
3725 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; DF RST 18H
3726 .dw (FETCH_NOP | OP_IFPO | STORE_RET) ; E0 RET PO
3727 .dw (FETCH_NOP | OP_POP16 | STORE_HL ) ; E1 POP HL
3728 .dw (FETCH_DIR16| OP_IFPO | STORE_PC ) ; E2 nn nn JP PO,nn
3729 .dw (FETCH_MSP | OP_EXHL | STORE_MSP) ; E3 EX (SP),HL
3730 .dw (FETCH_DIR16| OP_IFPO | STORE_CALL) ; E4 nn nn CALL PO,nn
3731 .dw (FETCH_HL | OP_PUSH16 | STORE_NOP) ; E5 PUSH HL
3732 .dw (FETCH_DIR8 | OP_ANDA | STORE_A ) ; E6 nn AND n
3733 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; E7 RST 20H
3734 .dw (FETCH_NOP | OP_IFPE | STORE_RET) ; E8 RET PE
3735 .dw (FETCH_HL | OP_NOP | STORE_PC ) ; E9 JP (HL)
3736 .dw (FETCH_DIR16| OP_IFPE | STORE_PC ) ; EA nn nn JP PE,nn
3737 .dw (FETCH_DE | OP_EXHL | STORE_DE ) ; EB EX DE,HL
3738 .dw (FETCH_DIR16| OP_IFPE | STORE_CALL) ; EC nn nn CALL PE,nn
3739 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; ED (Z80 specific)
3740 .dw (FETCH_DIR8 | OP_XORA | STORE_A ) ; EE nn XOR n
3741 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; EF RST 28H
3742 .dw (FETCH_NOP | OP_IFP | STORE_RET) ; F0 RET P
3743 .dw (FETCH_NOP | OP_POP16 | STORE_AF ) ; F1 POP AF
3744 .dw (FETCH_DIR16| OP_IFP | STORE_PC ) ; F2 nn nn JP P,nn
3745 .dw (FETCH_NOP | OP_DI | STORE_NOP) ; F3 DI
3746 .dw (FETCH_DIR16| OP_IFP | STORE_CALL) ; F4 nn nn CALL P,nn
3747 .dw (FETCH_AF | OP_PUSH16 | STORE_NOP) ; F5 PUSH AF
3748 .dw (FETCH_DIR8 | OP_ORA | STORE_A ) ; F6 nn OR n
3749 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; F7 RST 30H
3750 .dw (FETCH_NOP | OP_IFM | STORE_RET) ; F8 RET M
3751 .dw (FETCH_HL | OP_NOP | STORE_SP ) ; F9 LD SP,HL
3752 .dw (FETCH_DIR16| OP_IFM | STORE_PC ) ; FA nn nn JP M,nn
3753 .dw (FETCH_NOP | OP_EI | STORE_NOP) ; FB EI
3754 .dw (FETCH_DIR16| OP_IFM | STORE_CALL) ; FC nn nn CALL M,nn
3755 .dw (FETCH_NOP | OP_INV | STORE_NOP) ; FD (Z80 specific)
3756 .dw (FETCH_DIR8 | OP_SUBFA | STORE_NOP) ; FE nn CP n
3757 .dw (FETCH_RST | OP_NOP | STORE_CALL) ; FF RST 38H
3758
3759 ; vim:set ts=8 noet nowrap
3760