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