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