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