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