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