-; Z80 emulator with CP/M support. The Z80-specific instructions themselves actually aren't
-; implemented yet, making this more of an i8080 emulator.
-;
+; Z80 Interpreter.
+; This is part of the Z80-CP/M emulator written by Sprite_tm.
+; The Z80-specific instructions themselves actually aren't
+; implemented yet, making this more of an i8080 emulator.
+
; Copyright (C) 2010 Sprite_tm
+; Copyright (C) 2010 Leo C.
+
+; This file is part of avrcpm.
;
-; This program is free software: you can redistribute it and/or modify
-; it under the terms of the GNU General Public License as published by
+; avrcpm is free software: you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
-; This program is distributed in the hope that it will be useful,
+; avrcpm is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
-; along with this program. If not, see <http://www.gnu.org/licenses/>.
+; along with avrcpm. If not, see <http://www.gnu.org/licenses/>.
;
; $Id$
;
-;.nolist
-#if defined atmega8
- .include "m8def.inc"
-#elif defined atmega168
- .include "m168def.inc"
-#elif defined atmega328P
- .include "m328Pdef.inc"
-#else /* default */
- .include "m88def.inc"
- ;FUSE_H=0xDF
- ;FUSE_L=0xF7
-#endif
-.list
-.listmac
-
-
-
-#ifndef F_CPU
- #define F_CPU 20000000 /* system clock in Hz; defaults to 20MHz */
-#endif
-#ifndef BAUD
- #define BAUD 38400 /* console baud rate */
-#endif
-
-#define PARTID 0x52 /* Partition table id */
- /* http://www.win.tue.nl/~aeb/partitions/partition_types-1.html */
-#define RAMDISKNR 'I'-'A' /* Driveletter for first RAM disk */
-#define RAMDISKCNT 1 /* Number of RAM disks */
-
-#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) /* clever rounding */
-
-#define RXBUFSIZE 64 /* USART recieve buffer size. Must be power of 2 */
-#define TXBUFSIZE 64 /* USART transmit buffer size. Must be power of 2 */
-
-#define DRAM_WAITSTATES 1 /* Number of additional clock cycles for dram read access */
-#define REFR_RATE 64000 /* dram refresh rate in cycles/s. */
- /* Most drams need 1/15.6µs. */
-#define REFR_PRE 8 /* timer prescale factor */
-#define REFR_CS 0x02 /* timer clock select for 1/8 */
-#define REFR_CNT F_CPU / REFR_RATE / REFR_PRE
-
-
-
-#define DRAM_WORD_ACCESS 0 /* experimental */
-
-#define EM_Z80 0 /* we don't have any z80 instructions yet */
-
-.equ MMC_DEBUG = 0
-.equ INS_DEBUG = 0
-.equ MEMTEST = 1
-.equ BOOTWAIT = 1
-.equ PORT_DEBUG = 0
-.equ DISK_DEBUG = 0 /* Increase for more debugging */
-.equ HOSTRW_DEBUG= 0
-.equ MEMFILL_CB = 1
-.equ STACK_DBG = 0
-.equ PRINT_PC = 0
-
-;Port declarations
-
-; Port D
-.equ rxd = 0
-.equ txd = 1
-.equ ram_oe = 2
-.equ ram_a8 = 3
-.equ mmc_cs = 4
-.equ ram_a5 = 5
-.equ ram_a6 = 6
-.equ ram_a7 = 7
-
-.equ P_OE = PORTD
-.equ P_AH = PORTD
-.equ P_A8 = PORTD
-.equ P_MMC_CS = PORTD
- ; ram_a[7..5]
-.equ RAM_AH_MASK = (1<<ram_a8)|(1<<ram_a7)|(1<<ram_a6)|(1<<ram_a5)
-.equ PD_OUTPUT_MASK = (1<<mmc_cs) | (1<<ram_oe) | RAM_AH_MASK
-
-
-;Port B
-.equ ram_a4 = 0
-.equ ram_a3 = 1
-.equ ram_a2 = 2
-.equ ram_a1 = 3
-.equ mmc_mosi = 3
-.equ ram_a0 = 4
-.equ mmc_miso = 4
-.equ ram_ras = 5
-.equ mmc_sck = 5
-
-
-.equ P_RAS = PORTB
-.equ P_AL = PORTB
- ; ram_a[4..0]
-.equ RAM_AL_MASK = (1<<ram_a4)|(1<<ram_a3)|(1<<ram_a2)|(1<<ram_a1)|(1<<ram_a0)
-.equ PB_OUTPUT_MASK = (1<<ram_ras) | RAM_AL_MASK
-
-;Port C
-.equ ram_d0 = 0
-.equ ram_d1 = 1
-.equ ram_d2 = 2
-.equ ram_d3 = 3
-.equ ram_w = 4
-.equ ram_cas= 5
-
-.equ P_DQ = PORTC
-.equ P_W = PORTC
-.equ P_CAS = PORTC
-.equ RAM_DQ_MASK = (1<<ram_d3)|(1<<ram_d2)|(1<<ram_d1)|(1<<ram_d0)
-.equ PC_OUTPUT_MASK = (1<<ram_cas)|(1<<ram_w)
-
-
-;Flag bits in z_flags
-.equ ZFL_S = 7
-.equ ZFL_Z = 6
-.equ ZFL_H = 4
-.equ ZFL_P = 2
-.equ ZFL_N = 1
-.equ ZFL_C = 0
-
-;Register definitions
-
-.def _tmp = r0 ; 0
-.def _0 = r1
-
-.def z_c = r4
-.def z_b = r5
-.def z_e = r6
-.def z_d = r7
-.def z_l = r8
-.def z_h = r9
-.def z_a = r10
-
-.def insdecl = r12 ;
-.def insdech = r13 ;
-.def z_spl = r14
-.def z_sph = r15 ;
-.def temp = r16 ;
-.def temp2 = r17 ;
-.def temp3 = r18
-.def temp4 = r19
-.def z_flags = r20 ;
- ;
-.def opl = r22 ;
-.def oph = r23 ;
-.def z_pcl = r24 ;
-.def z_pch = r25 ;
-; xl ;r26
-; xh ;r27
-; yl ;r28
-; yh ;r29
-; zl ;r30 ;
-; zh ;r31 ;
-
-
-
-#if defined __ATmega8__
-.equ flags = TWBR
-.equ P_PUD = SFIOR
-#else
-.equ flags = GPIOR0
-.equ P_PUD = MCUCR
-#endif
-
-; Flags:
- .equ hostact = 7 ;host active flag
- .equ hostwrt = 6 ;host written flag
- .equ rsflag = 5 ;read sector flag
- .equ readop = 4 ;1 if read operation
- .equ trace = 0
-
-; This is the base z80 port address for clock access
-#define TIMERPORT 0x40
-#define TIMER_CTL TIMERPORT
-#define TIMER_MSECS TIMERPORT+1
-#define TIMER_SECS TIMER_MSECS+2
-
-#define starttimercmd 1
-#define quitTimerCmd 2
-#define printTimerCmd 15
-#define uptimeCmd 16
-
-#if defined __ATmega8__
-.equ RXTXDR0 = UDR
-.equ UCSR0A = UCSRA
-.equ UDRE0 = UDRE
-.equ UCSR0B = UCSRB
-.equ RXCIE0 = RXCIE
-.equ UDRIE0 = UDRIE
-.equ RXEN0 = RXEN
-.equ TXEN0 = TXEN
-.equ UCSR0C = UCSRC
-.equ UCSZ00 = UCSZ0
-.equ UCSZ01 = UCSZ1
-.equ UBRR0H = UBRRH
-.equ UBRR0L = UBRRL
-.equ OCR2A = OCR2
-.equ OC2Aaddr= OC2addr
-.equ TCCR2A = TCCR2
-.equ TCCR2B = TCCR2
-.equ TIMSK1 = TIMSK
-.equ TIMSK2 = TIMSK
-.equ OCIE2A = OCIE2
-.equ TIFR1 = TIFR
-.equ ICIE1 = TICIE1
-#else
-.equ RXTXDR0 = UDR0
-#endif
-
-
-;----------------------------------------
-;
-.macro outm8
-.if @0 > 0x3f
- sts @0,@1
-.else
- out @0,@1
-.endif
-.endm
-
-;----------------------------------------
-;
-.macro inm8
-.if @1 > 0x3f
- lds @0,@1
-.else
- in @0,@1
-.endif
-.endm
-
-
-
-; -------------------- DRAM ---------------
-
-; DRAM_SETADDR val, low_and_mask, low_or_mask, high_and_mask, high_or_mask
-.macro DRAM_SETADDR
- mov temp,@0
-.if low(@1) != 0xff
- andi temp,@1
-.endif
-.if low(@2) != 0
- ori temp, @2
-.endif
- out P_AL,temp
-
- mov temp,@0
-.if low(@3) != 0xff
- andi temp,@3
-.endif
- ori temp, @4 | (1<<mmc_cs)
- out P_AH,temp
-.endm
-
-;----------------------------------------
-; add wait states
-; dram_wait number_of_cycles
-
-.macro dram_wait
-.if @0 > 1
- rjmp PC+1
- dram_wait @0 - 2
-.elif @0 > 0
- nop
- dram_wait @0 - 1
-.endif
-.endm
-
-
-.cseg
-.org 0
- rjmp start ; reset vector
-.org OC2Aaddr
- rjmp refrint ; tim2cmpa
-.org OC1Aaddr ; Timer/Counter1 Compare Match A
- rjmp sysclockint ; 1ms system timer
-.org URXCaddr
- rjmp rxint ; USART receive int.
-.org UDREaddr
- rjmp txint ; USART transmit int.
-
-.org INT_VECTORS_SIZE
-
-start:
- ldi temp,low(RAMEND) ; top of memory
- out SPL,temp ; init stack pointer
- ldi temp,high(RAMEND) ; top of memory
- out SPH,temp ; init stack pointer
-
- clr _0
-
-; - Kill wdt
- wdr
- out MCUSR,_0
-
- ldi temp,(1<<WDCE) | (1<<WDE)
- outm8 WDTCSR,temp
- ldi temp,(1<<WDCE)
- outm8 WDTCSR,temp
-
-; - Clear RAM
-
- ldi zl,low(SRAM_START)
- ldi zh,high(SRAM_START)
- ldi temp2,high(ramtop)
-clr_l:
- st z+,_0
- cpi zl,low(ramtop)
- cpc zh,temp2
- brne clr_l
-
-; - Setup Ports
- ldi temp,(1<<PUD) ;disable pullups
- outm8 P_PUD,temp
- ldi temp,0xFF
- out PORTD,temp ;all pins high
- out PORTB,temp
- out PORTC,temp
- out DDRD,temp ; all outputs
- out DDRB,temp
- out DDRC,temp
-
- outm8 TIMSK1,_0
- outm8 TIMSK2,_0
- outm8 TCCR2A,_0
- outm8 TCCR2B,_0
-
-
-; - Init serial port
-
- ldi temp, (1<<TXEN0) | (1<<RXEN0) | (1<<RXCIE0)
- outm8 UCSR0B,temp
-.ifdef URSEL
- ldi temp, (1<<URSEL) | (1<<UCSZ01) | (1<<UCSZ00)
-.else
- ldi temp, (1<<UCSZ01) | (1<<UCSZ00)
-.endif
- outm8 UCSR0C,temp
- ldi temp, HIGH(UBRR_VAL)
- outm8 UBRR0H,temp
- ldi temp, LOW(UBRR_VAL)
- outm8 UBRR0L,temp
-
-; Init clock/timer system
-
-; Init timer 1 as 1 ms system clock tick.
-
- ldi temp,high(F_CPU/1000)
- outm8 OCR1AH,temp
- ldi temp,low(F_CPU/1000)
- outm8 OCR1AL,temp
- ldi temp,(1<<WGM12) | (1<<CS10) ;CTC, clk/1
- outm8 TCCR1B,temp
- inm8 temp,TIMSK1
- ori temp,(1<<OCIE1A)
- outm8 TIMSK1,temp
-
-;Init timer2. Refresh-call should happen every (8ms/512)=312 cycles.
-
- ldi temp,REFR_CNT*2 ; 2 cycles per int
- outm8 OCR2A,temp
- inm8 temp,TCCR2A
- ori temp,(1<<WGM21) ;CTC mode
- outm8 TCCR2A,temp
- inm8 temp,TCCR2B
- ori temp,REFR_CS ;clk/REFR_PRE
- outm8 TCCR2B,temp
- inm8 temp,TIMSK2
- ori temp, (1<<OCIE2A)
- outm8 TIMSK2,temp
-
- sei
-
-
-.if BOOTWAIT
- ldi temp,10
- rcall delay_ms
-
-.endif
-
- rcall printstr
- .db 13,"CPM on an AVR, v1.0",13,0
-
-
-.if MEMTEST
- rcall printstr
- .db 13,"Testing RAM: fill...",0
-
-;Fill RAM
- ldi xl,0
- ldi xh,0
-ramtestw:
- mov temp,xh
- eor temp,xl
- rcall memwritebyte
- adiw xl,1
- brcc ramtestw
- rcall printstr
- .db "wait...",0
-
- ldi temp2,8
-ramtestwl:
- ldi temp,255
- rcall delay_ms
- dec temp2
- brne ramtestwl
-
- rcall printstr
- .db "reread...",13,0,0
-
-;re-read RAM
- ldi xl,0
- ldi xh,0
-ramtestr:
- rcall memReadByte
- mov temp2,xh
- eor temp2,xl
- cp temp,temp2
- breq ramtestrok
- rcall printhex
- ldi temp,'<'
- rcall uartPutc
- mov temp,xh
- eor temp,xl
- rcall printhex
- ldi temp,'@'
- rcall uartPutc
- movw temp,x
- rcall printhexw
- ldi temp,13
- rcall uartPutc
-ramtestrok:
- adiw xl,1
- brcc ramtestr
-
-.endif
-
-.if MEMFILL_CB
- ;Fill ram with cbs, which (for now) will trigger an invalid opcode error.
- ldi xl,0
- ldi xh,0
-ramfillw:
- ldi temp,0xcb
- rcall memwritebyte
- adiw xl,1
- brcc ramfillw
-.endif
-
-
-;----------------------------------------------------------------------------
-
-boot_again:
- rcall printstr
- .db 13,"Initing mmc...",0
- rcall dsk_partinit
- rcall printstr
- .db 13,"Partinit done.",0
-
- lds temp,ndisks
- tst temp
- brne boot_ipl2
- rcall printstr
- .db "No bootable CP/M disk found! Please change MMC/SD-Card",13,0
- ldi temp2,18
-boot_iplwl:
- ldi temp,255
- rcall delay_ms
- dec temp2
- brne boot_iplwl
- rjmp boot_again
-
-
-boot_ipl2:
-
-; Read first sector of first CP/M partition
-
- lds xl,hostparttbl
- lds xh,hostparttbl+1
- lds yl,hostparttbl+2
- lds yh,hostparttbl+3
- rcall mmcReadSect
-
- rcall dsk_cboot ;init (de)blocking buffer
-
-;First sector of disk or first CP/M partition is in hostbuf.
+ .dseg
-;Save to Z80 RAM (only 128 bytes because that's retro)
- ldi zl,low(hostbuf)
- ldi zh,high(hostbuf)
- ldi xh,0x20
- ldi xl,0x00
-iplwriteloop:
- ld temp,z+
- rcall memWriteByte
- adiw xl,1
- cpi zl,low(hostbuf+128)
- brne iplwriteloop
- cpi zh,high(hostbuf+128)
- brne iplwriteloop
+z_b: .byte 1
+z_c: .byte 1
+z_d: .byte 1
+z_e: .byte 1
+z_h: .byte 1
+z_l: .byte 1
+ .cseg
;Init z80
- ldi temp,0x00
- mov z_pcl,temp
- ldi temp,0x20
- mov z_pch,temp
+z80_init:
+ ldi z_pcl,low (IPLADDR)
+ ldi z_pch,high(IPLADDR)
cbi flags,trace
- rcall printstr
- .db 13,"Ok, CPU is live!",13,0,0
+ printnewline
+ printstring "Ok, CPU is live!"
+ printnewline
main:
+.if INS_DEBUG
cbi flags,trace
- cpi z_pch,1
+ cpi z_pch,DBG_TRACE_BOTTOM
brlo notraceon
- cpi z_pch,$dc
+ cpi z_pch,DBG_TRACE_TOP
brsh notraceon
sbi flags,trace
notraceon:
+.endif
.if PRINT_PC
- cpi z_pch,1
+ cpi z_pch,DBG_TRACE_BOTTOM
brlo noprintpc
- cpi z_pch,0xdc
+ cpi z_pch,DBG_TRACE_TOP
brsh noprintpc
- rcall printstr
- .db 13,"PC=",0
+ printnewline
+ printstring "PC="
movw temp,z_pcl
rcall printhexw
- ldi temp,' '
-; ldi temp,10
-; rcall uartputc
+ printstring " "
noprintpc:
.endif
; *** Stage 1: Fetch next opcode
- movw xl,z_pcl
- rcall memReadByte
+ mem_read_s z_pc
.if INS_DEBUG
sbis flags,trace
rjmp notrace1
- rcall printstr
- .db "PC=",0
+ printnewline
+ printstring "PC="
push temp
movw temp,z_pcl
rcall printhexw
pop temp
- rcall printstr
- .db ", opcode=",0
+ printstring ", opcode="
rcall printhex
notrace1:
.endif
.if INS_DEBUG
sbis flags,trace
rjmp notrace2
- rcall printstr
- .db ", decoded=",0,0
- movw temp,insdecl
- rcall printhexw
- rcall printstr
- .db ".",13,0,0
+ printstring ", decoded="
+ movw temp,insdecl
+ rcall printhexw
notrace2:
.endif
.if INS_DEBUG
sbis flags,trace
rjmp notrace3
- rcall printstr
- .db "pre: oph:l=",0
- mov tempw,opl
- rcall printhexw
- rcall printstr
- .db " -- ",0,0
+ printstring " pre: op="
+ movw temp,opl
+ rcall printhexw
notrace3:
+ rjmp nonofetch
.endif
nofetch:
+.if INS_DEBUG
+ sbis flags,trace
+ rjmp nonofetch
+ printstring " "
+
+nonofetch:
+.endif
; *** Stage 4: Execute operation :) Use the op jumptable for this.
mov temp,insdech
andi temp,0xFC
.if INS_DEBUG
sbis flags,trace
rjmp notrace4
- rcall printstr
- .db ",post:oph:l=",0,0
- movw temp,opl
- rcall printhexw
+ printstring " post: op="
+ movw temp,opl
+ rcall printhexw
notrace4:
+ rjmp nonooper
.endif
nooper:
+.if INS_DEBUG
+ sbis flags,trace
+ rjmp nonooper
+ printstring " "
+
+nonooper:
+.endif
; *** Stage 5: Store operand. Use the store jumptable for this.
swap insdecl
swap insdech
.if INS_DEBUG
sbis flags,trace
rjmp notrace5
- rcall printstr
- .db ", stored.",0
+ printstring " stored "
notrace5:
.endif
nostore:
-
-.if INS_DEBUG
- sbis flags,trace
- rjmp notrace6
- rcall printstr
- .db 13,0
-notrace6:
-.endif
-
;All done. Neeeext!
rjmp main
-
-
-
-; ----------------Virtual peripherial interface ------
-
-;The hw is modelled to make writing a CPM BIOS easier.
-;Ports:
-;0 - Con status. Returns 0xFF if the UART has a byte, 0 otherwise.
-;1 - Console input, aka UDR.
-;2 - Console output
-;15 - Disk select
-;16,17 - Track select
-;18 - Sector select
-;20 - Write addr l
-;21 - Write addr h
-;22 - Trigger - write to read, to write a sector using the above info;
-; , write to allocated/dirctory/unallocated
-
- .equ READ_FUNC = 7
- .equ WRITE_FUNC = 6
- .equ BOOT_FUNC = 5
- .equ HOME_FUNC = 4
-
-
-
-;*****************************************************
-;* CP/M to host disk constants *
-;*****************************************************
- .equ MAXDISKS = 4 ;Max number of Disks (partitions)
- .equ blksize = 1024 ;CP/M allocation size
- .equ hostsize = 512 ;host disk sector size
-; .equ hostspt = 20 ;host disk sectors/trk
- .equ hostblk = hostsize/128 ;CP/M sects/host buff
-; .equ CPMSPT = hostblk*hostspt;CP/M sectors/track
- .equ CPMSPT = 26 ;
- .equ SECMSK = hostblk-1 ;sector mask
- .equ SECSHF = log2(hostblk) ;sector shift
-
-;*****************************************************
-;* BDOS constants on entry to write *
-;*****************************************************
- .equ WRALL = 0 ;write to allocated
- .equ WRDIR = 1 ;write to directory
- .equ WRUAL = 2 ;write to unallocated
- .equ WRTMSK= 3 ;write type mask
-
-
- .dseg
-ndisks: .byte 1 ;Number of CP/M disks
-
-seekdsk: .byte 1 ;seek disk number
-seektrk: .byte 2 ;seek track number
-seeksec: .byte 1 ;seek sector number
-
-hostparttbl: .byte 8*MAXDISKS ; host partition table (start sector, sector count)
-hostdsk: .byte 1 ;host disk number
-hostlba: .byte 3 ;host sector number (relative to partition start)
-
-unacnt: .byte 1 ;unalloc rec cnt
-unadsk: .byte 1 ;last unalloc disk
-unatrk: .byte 2 ;last unalloc track
-unasec: .byte 1 ;last unalloc sector
-
-erflag: .byte 1 ;error reporting
-wrtype: .byte 1 ;write operation type
-dmaadr: .byte 2 ;last dma address
-hostbuf: .byte hostsize;host buffer (from/to SD-card)
-
-
- .cseg
-
-conStatus:
-
- lds temp,rxcount
- tst temp
- breq PC+2
- ldi temp,0xff
- ret
-
-conInp:
- rjmp uartGetc
-
-dbgOut:
- rcall printstr
- .db "Debug: ",0
- rcall printhex
- rcall printstr
- .db 13,0
- ret
-
-conOut:
- rjmp uartputc
-
-
-;Called with port in temp2. Should return value in temp.
-portRead:
- cpi temp2,0
- breq conStatus
- cpi temp2,1
- breq conInp
-
- cpi temp2,15
- breq dskDiskCheck
- cpi temp2,22
- breq dskErrorRet
-
- cpi temp2,TIMER_MSECS
- brlo pr_noclock
- cpi temp2,TIMER_MSECS+6
- brsh pr_noclock
- rjmp clockget
-
-pr_noclock:
- ldi temp,0xFF
- ret
-
-;Called with port in temp2 and value in temp.
-portWrite:
- cpi temp2,0
- breq dbgOut
- cpi temp2,2
- breq conOut
-
- cpi temp2,15
- breq dskDiskSel
- cpi temp2,16
- breq dskTrackSel_l
- cpi temp2,17
- breq dskTrackSel_h
- cpi temp2,18
- breq dskSecSel
- cpi temp2,20
- breq dskDmaL
- cpi temp2,21
- breq dskDmaH
-
- cpi temp2,22
- breq dskDoIt
-
- cpi temp2,TIMERPORT
- brlo pw_noclock
- cpi temp2,TIMER_MSECS+6
- brsh pw_noclock
- rjmp clockput
-
-pw_noclock:
- ret
-
-
-dskDiskCheck:
- lds temp,seekdsk
- cpi temp,RAMDISKNR
- brsh dsk_dchrd ;maybe ramdisk
-
- lds temp2,ndisks ;check if selected disk # is less then # of disks
- tst temp2
- brne dsk_dchpart1
-
-; Need to init
-
- rcall dsk_partinit
- lds temp2,ndisks
- lds temp,seekdsk
-
-dsk_dchpart1:
- cp temp,temp2
- brsh dsk_dcher
-
-dsk_dchend:
- ldi temp,0
- ret
-
-dsk_dchrd:
- cpi temp,RAMDISKNR+RAMDISKCNT
- brlo dsk_dchend
-dsk_dcher:
- ldi temp,0xff ;error return
- ret
-
-
-
-
-dskErrorRet:
- lds temp,erflag
- ret
-
-dskDiskSel:
- sts seekdsk,temp
- ret
-
-dskTrackSel_l:
- sts seektrk,temp
- sts seektrk+1,_0
- ret
-
-dskTrackSel_h:
- sts seektrk+1,temp
- ret
-
-dskSecSel:
- sts seeksec,temp
- ret
-
-dskDmal:
- sts dmaadr,temp
- ret
-
-dskDmah:
- sts dmaadr+1,temp
- ret
-
-dskDoIt:
-.if DISK_DEBUG
- push temp
- sbrc temp,READ_FUNC
- rjmp dskdbgr
- sbrc temp,WRITE_FUNC
- rjmp dskdbgw
- rjmp dskdbge
-
-dskdbgr:
- rcall printstr
- .db 13,"Disk read: ",0
- rjmp dskdbg1
-dskdbgw:
- rcall printstr
- .db 13,"Disk write: ",0
-dskdbg1:
- lds temp,seekdsk
- subi temp,-('A')
- rcall uartputc
- rcall printstr
- .db ": track ",0,0
- lds temp2,seektrk+1
- lds temp,seektrk
- rcall printhexw
- rcall printstr
- .db ", sector ",0
- lds temp,seeksec
- rcall printhex
- rcall printstr
- .db ", dma-addr ",0
- lds temp2,dmaadr+1
- lds temp,dmaadr
- rcall printhexw
- pop temp
- push temp
- sbrs temp,WRITE_FUNC
- rjmp dskdbge
- rcall printstr
- .db " wrtype ",0,0
- andi temp,3
- rcall printhex
-dskdbge:
- pop temp
-.endif
- ;See what has to be done.
- sbrc temp,READ_FUNC
- rjmp dsk_read
- sbrc temp,WRITE_FUNC
- rjmp dsk_write
- sbrc temp,HOME_FUNC
- rjmp dsk_home
- sbrc temp,BOOT_FUNC
- rjmp dsk_boot
-
- rcall printstr
- .db "DISK I/O: Invalid Function code: ",0
- rcall printhex
- rjmp haltinv
-
-dsk_boot:
- sts ndisks,_0 ;no active partitions
-dsk_cboot:
- cbi flags,hostact ;host buffer inactive
- sts unacnt,_0 ;clear unalloc count
- ret
-
-dsk_home:
- sbis flags,hostwrt ;check for pending write
- cbi flags,hostact ;clear host active flag
- ret
-
-
-dsk_read:
-
- sbi flags,readop ;read operation
- ;RAM disk?
- lds temp2,seekdsk
- cpi temp2,RAMDISKNR
- brlt PC+2
- rjmp rdskDoIt
-
- sts unacnt,_0
- sbi flags,rsflag ;must read data
- ldi temp,WRUAL ;write type
- sts wrtype,temp ;treat as unalloc
- rjmp dsk_rwoper ;to perform the read
-
-
-dsk_write:
- ;write the selected CP/M sector
-
- cbi flags,readop ;not a read operation
-
- ;RAM disk?
- lds temp2,seekdsk
- cpi temp2,RAMDISKNR
- brlt PC+2
- rjmp rdskDoIt
- andi temp,WRTMSK
- sts wrtype,temp ;save write type
-
- cpi temp,WRUAL ;write unallocated?
- brne dsk_chkuna ;check for unalloc
-
-; write to unallocated, set parameters
- ldi temp,blksize/128 ;next unalloc recs
- sts unacnt,temp
- lds temp,seekdsk ;disk to seek
- sts unadsk,temp ;unadsk = sekdsk
- lds temp,seektrk
- sts unatrk,temp ;unatrk = sectrk
- lds temp,seektrk+1
- sts unatrk+1,temp ;unatrk = sectrk
- lds temp,seeksec
- sts unasec,temp ;unasec = seksec
-;
-dsk_chkuna:
- ;check for write to unallocated sector
- lds temp,unacnt ;any unalloc remain?
- tst temp
- breq dsk_alloc ;skip if not
-
-; more unallocated records remain
- dec temp ;unacnt = unacnt-1
- sts unacnt,temp
- lds temp,seekdsk ;same disk?
- lds temp2,unadsk
- cp temp,temp2 ;seekdsk = unadsk?
- brne dsk_alloc ;skip if not
-
-; disks are the same
- lds temp,unatrk
- lds temp2,unatrk+1
- lds temp3,seektrk
- lds temp4,seektrk+1
- cp temp,temp3 ;seektrk = unatrk?
- cpc temp2,temp4
- brne dsk_alloc ;skip if not
-
-; tracks are the same
- lds temp,seeksec ;same sector?
- lds temp2,unasec
- cp temp,temp2 ;seeksec = unasec?
- brne dsk_alloc ;skip if not
-
-; match, move to next sector for future ref
- inc temp2 ;unasec = unasec+1
- sts unasec,temp2
- cpi temp2,CPMSPT ;end of track? (count CP/M sectors)
- brlo dsk_noovf ;skip if no overflow
-
-; overflow to next track
- sts unasec,_0 ;unasec = 0
- lds temp,unatrk
- lds temp2,unatrk+1
- subi temp, low(-1) ;unatrk = unatrk+1
- sbci temp2,high(-1)
- sts unatrk,temp
- sts unatrk+1,temp2
-;
-dsk_noovf:
- cbi flags,rsflag ;rsflag = 0
- rjmp dsk_rwoper ;to perform the write
-;
-dsk_alloc:
- ;not an unallocated record, requires pre-read
- sts unacnt,_0 ;unacnt = 0
- sbi flags,rsflag ;rsflag = 1
-
-;*****************************************************
-;* Common code for READ and WRITE follows *
-;*****************************************************
-
-dsk_rwoper:
- ;enter here to perform the read/write
-.if DISK_DEBUG
- rcall printstr
- .db ", flags: ",0
- in temp,flags
- rcall printhex
-.endif
- sts erflag,_0 ;no errors (yet)
-
- ;Convert track/sector to an LBA address (in 128byte blocks)
-
- lds xl,seeksec ;
- ldi xh,0 ;
- ldi yl,0 ;
- lds temp3,seektrk ;
- lds temp4,seektrk+1 ;
- ldi temp,CPMSPT ;
- mul temp3,temp ;
- add xl,r0 ;
- adc xh,r1 ;
- mul temp4,temp ;
- add xh,r0 ;yl:xh:xl := sec + trk * SectorsPerTrack
- adc yl,r1 ;
- clr _0
-
- mov temp,xl
- andi temp,SECMSK ;mask buffer number
- push temp ;save for later
-
- ;Convert from CP/M LBA blocks to host LBA blocks
- ldi temp,SECSHF
-dsk_sh1:
- lsr yl
- ror xh
- ror xl
- dec temp
- brne dsk_sh1
- ;yl:xh:xl = host block to seek
-; active host sector?
- in _tmp,flags ;host active flag
- sbi flags,hostact ;always becomes 1
- sbrs _tmp,hostact ;was it already?
- rjmp dsk_filhst ;fill host if not
-
-; host buffer active, same as seek buffer?
- lds temp,seekdsk
- lds temp2,hostdsk ;same disk?
- cp temp,temp2 ;seekdsk = hostdsk?
- brne dsk_nomatch
-
-; same disk, same block?
- lds temp,hostlba
- lds temp2,hostlba+1
- lds temp3,hostlba+2
- cp xl,temp
- cpc xh,temp2
- cpc yl,temp3
- breq dsk_match
-;
-dsk_nomatch:
- ;proper disk, but not correct sector
- sbis flags,hostwrt ;host written?
- rjmp dsk_filhst
- push xl
- push xh
- push yl
- rcall dsk_writehost ;clear host buff
- pop yl
- pop xh
- pop xl
-
-dsk_filhst:
- ;may have to fill the host buffer
- lds temp,seekdsk
- sts hostdsk,temp
- sts hostlba,xl
- sts hostlba+1,xh
- sts hostlba+2,yl
-
- sbic flags,rsflag ;need to read?
- rcall dsk_readhost ;yes, if 1
- cbi flags,hostwrt ;no pending write
-
-dsk_match:
-
- ;copy data to or from buffer
- ldi zl,low(hostbuf)
- ldi zh,high(hostbuf)
- ldi temp,128
- pop temp2 ;get buffer number (which part of hostbuf)
- mul temp2,temp
- add zl,r0 ;offset in hostbuf
- adc zh,r1
-.if DISK_DEBUG > 2
- push r0
- push r1
- clr _0
- rcall printstr
- .db "; host buf adr: ",0,0
- pop temp2
- pop temp
- rcall printhexw
-.endif
- clr _0
-
- lds xl,dmaadr
- lds xh,dmaadr+1
- ldi temp3,128 ;length of move
- sbic flags,readop ;which way?
- rjmp dsk_rmove ;skip if read
-
-; mark write operation
- sbi flags,hostwrt ;hostwrt = 1
-dsk_wmove:
- rcall memReadByte
- st z+,temp
- adiw xl,1
- dec temp3
- brne dsk_wmove
- rjmp dsk_rwmfin
-
-dsk_rmove:
- ld temp,z+
- rcall memWriteByte
- adiw xl,1
- dec temp3
- brne dsk_rmove
-dsk_rwmfin:
-; data has been moved to/from host buffer
- lds temp,wrtype ;write type
- cpi temp,WRDIR ;to directory?
- breq dsk_wdir
- ret ;no further processing
-dsk_wdir:
-; clear host buffer for directory write
- lds temp,erflag
- tst temp ;errors?
- breq dsk_wdir1
- ret ;skip if so
-dsk_wdir1:
- rcall dsk_writehost ;clear host buff
- cbi flags,hostwrt ;buffer written
- ret
-
-;*****************************************************
-
-; hostdsk = host disk #, (partition #)
-; hostlba = host block #, relative to partition start
-; Read/Write "hostsize" bytes to/from hostbuf
-
-
-dsk_hostparam:
- ldi zl,low(hostparttbl)
- ldi zh,high(hostparttbl)
- lds temp,hostdsk
-.if HOSTRW_DEBUG
- push temp
- subi temp,-('A')
- rcall uartputc
- rcall printstr
- .db ": ",0,0
- pop temp
-.endif
-
- lsl temp
- lsl temp
- lsl temp
- add zl,temp
- adc zh,_0
-
- lds temp,hostlba
- lds temp2,hostlba+1
- lds temp3,hostlba+2
-
-.if HOSTRW_DEBUG
- rcall printstr
- .db "lba: ",0
- clr temp4
- rcall print_ultoa
-.endif
-
- ldd xl,z+4
- ldd xh,z+5
- ldd yl,z+6
-
- cp temp,xl
- cpc temp2,xh
- cpc temp3,yl
- brcs dsk_hp1
-
-.if HOSTRW_DEBUG
- rcall printstr
- .db ", max: ",0
- push temp4
- push temp3
- push temp2
- push temp
- movw temp,x
- mov temp3,yl
- clr temp4
- rcall print_ultoa
- pop temp
- pop temp2
- pop temp3
- pop temp4
- rcall printstr
- .db " ",0
-.endif
-
- clr temp
- ret
-
-dsk_hp1:
- ldd xl,z+0
- ldd xh,z+1
- ldd yl,z+2
- ldd yh,z+3
-
- add xl,temp
- adc xh,temp2
- adc zl,temp3
- adc zh,_0
-.if HOSTRW_DEBUG
- rcall printstr
- .db ", abs:",0,0
- push temp4
- push temp3
- push temp2
- push temp
- movw temp,x
- movw temp3,y
- rcall print_ultoa
- pop temp
- pop temp2
- pop temp3
- pop temp4
- rcall printstr
- .db " ",0
-.endif
- ori temp,255
-dsk_hpex:
- ret
-
-;*****************************************************
-;* WRITEhost performs the physical write to *
-;* the host disk, READhost reads the physical *
-;* disk. *
-;*****************************************************
-
-dsk_writehost:
-.if HOSTRW_DEBUG
- rcall printstr
- .db 13,"host write ",0,0
-.endif
- rcall dsk_hostparam
- brne dsk_wr1
- ldi temp,255
- sts erflag,temp
- ret
-
-dsk_wr1:
- rcall mmcWriteSect
- sts erflag,_0
- ret
-
-dsk_readhost:
-.if HOSTRW_DEBUG
- rcall printstr
- .db 13,"host read ",0,0
-.endif
- rcall dsk_hostparam
- brne dsk_rd1
- ldi temp,255
- sts erflag,temp
- ret
-
-dsk_rd1:
- rcall mmcReadSect
- sts erflag,_0
- ret
-
-
-;***************************************************************************
-; ----------------- RAM disk -----------------
-
- .dseg
-rdskbuf:
- .byte 128
-
- .cseg
-;----------------------------------------------
-
-rdsk_adr:
- ldi xl,0
- lds xh,seeksec
- lds temp2,seektrk
-
- lsr xh
- ror xl ;Col 0..7
-
- mov temp,temp2
- andi temp,0x0f
- swap temp
- or xh,temp ;Row 0..7
-
- ldi zl,low (rdskbuf)
- ldi zh,high(rdskbuf)
- ldi temp3,128
- DRAM_SETADDR xh, ~0,(1<<ram_ras), ~0,(1<<ram_a8)|(1<<ram_oe)
- cbi P_RAS,ram_ras
-
-.if DISK_DEBUG > 1
- mov temp,xh
- rcall printhex
- rcall printstr
- .db " ",0
- mov temp,xl
- rcall printhex
- rcall printstr
- .db " ",0
-.endif
- ret
-
-;----------------------------------------------
-
-rdskDoIt:
- sts erflag,_0
- sbis flags,readop
- rjmp rdsk_wr
-
-.if DISK_DEBUG > 1
- rcall printstr
- .db 13,"rd-adr: ",0
-.endif
- rcall rdsk_adr
-rdsk_rdl:
- DRAM_SETADDR xl, ~(1<<ram_ras),0, ~((1<<ram_oe)), (1<<ram_a8)
- cbi P_CAS,ram_cas
- cbi P_A8,ram_a8
- inc xl
- dram_wait DRAM_WAITSTATES ;
- in temp,P_DQ-2 ; PIN
- sbi P_CAS,ram_cas
-
- cbi P_CAS,ram_cas
- andi temp,0x0f
- swap temp
- dram_wait DRAM_WAITSTATES ;
- in temp2,P_DQ-2 ; PIN
- andi temp2,0x0f
- or temp,temp2
-
- sbi P_OE,ram_oe
- sbi P_CAS,ram_cas
- dec temp3
- st z+,temp
- brne rdsk_rdl
-
- sbi P_RAS,ram_ras
- ldi zl,low (rdskbuf)
- ldi zh,high(rdskbuf)
- lds xl,dmaadr
- lds xh,dmaadr+1
- ldi temp3,128
-rdsk_rdstl:
- ld temp,z+
- rcall dram_write
- adiw x,1
- dec temp3
- brne rdsk_rdstl
- ret
-
-
-rdsk_wr:
-.if DISK_DEBUG > 1
- rcall printstr
- .db 13,"wr-adr: ",0
-.endif
- lds xl,dmaadr
- lds xh,dmaadr+1
- ldi zl,low (rdskbuf)
- ldi zh,high(rdskbuf)
- ldi temp3,128
-rdsk_wrldl:
- rcall dram_read
- st z+,temp
- adiw x,1
- dec temp3
- brne rdsk_wrldl
-
- ldi temp2,RAM_DQ_MASK | (1<<ram_w) | (1<<ram_cas)
- out DDRC,temp2
- rcall rdsk_adr
-rdsk_wrl:
- ld temp,z+
- mov temp2,temp
- andi temp,RAM_DQ_MASK & ~(1<<ram_w)
- ori temp,(1<<ram_cas)
- out PORTC,temp
- DRAM_SETADDR xl, ~(1<<ram_ras),0, ~((1<<ram_a8)),(1<<ram_oe)
- cbi PORTC,ram_cas
- sbi PORTD,ram_a8
- sbi PORTC,ram_cas
- swap temp2
- andi temp2,RAM_DQ_MASK & ~(1<<ram_w)
- ori temp2,(1<<ram_cas)
- out PORTC,temp2
- cbi PORTC,ram_cas
- inc xl
- sbi PORTC,ram_cas
- dec temp3
- brne rdsk_wrl
-
- sbi P_RAS,ram_ras
- ldi temp,~RAM_DQ_MASK | (1<<ram_w) | (1<<ram_cas)
- out DDRC,temp
- out PORTC,temp
- ret
-
-;---------------------------------------------------------------------
-
-; Partition table offsets:
-#define PART_TYPE 4
-#define PART_START 8
-#define PART_SIZE 12
-
- .dseg
-tmp_tbl:
- .byte 8*MAXDISKS
-
- .cseg
-dsk_partinit:
-
- rcall mmcInit
-
-;Load first sector from MMC (boot sector)
-
- ldi yh,0 ; Sector 0
- ldi yl,0
- movw x,y
- rcall mmcReadSect
-
- ldi yl,low(tmp_tbl)
- ldi yh,high(tmp_tbl)
- ldi temp2,8*MAXDISKS
-dsk_picl:
- st y+,_0
- dec temp2
- brne dsk_picl
- sbiw y,8*MAXDISKS
-#if 0
- rcall printstr
- .db ", ",0,0
- movw temp,y
- rcall printhexw
-#endif
-
-;Test, if it has a valid MBR
-
- ldi zl,low(hostbuf+510-1) ;Point to last byte of partition table
- ldi zh,high(hostbuf+510-1)
-
- ldi temp3,0 ;temp3 holds number of found disks (paritions)
- ldd temp,z+1 ;MBR signature (0xAA55) at and of sector?
- ldd temp2,z+2
- ldi temp4,0xAA
- cpi temp,0x55
- cpc temp2,temp4
- breq dsk_part
-
-;No MBR, no partition table ...
- inc temp3 ;pretend we have one.
- ldi temp,high((1<<16) * 128/512)
- std y+0,_0 ;start at beginning of card
- std y+1,_0
- std y+2,_0
- std y+3,_0
- std y+4,_0 ;max CP/M 2.2 disk size
- std y+5,temp ;
- std y+6,_0
- std y+7,_0
- rjmp dsk_pend
-
-;Search Partition Table for CP/M partitions
-dsk_part:
- sbiw z,63 ;Now at first byte of partition table
- ldi temp4,high(hostbuf+510)
-dsk_ploop:
- ldd temp,z+PART_TYPE
- cpi temp,PARTID
- brne dsk_nextp
-
-; Found a CP/M partition
-
- ldd temp,z+PART_START
- st y+,temp
- ldd temp,z+PART_START+1
- st y+,temp
- ldd temp,z+PART_START+2
- st y+,temp
- ldd temp,z+PART_START+3
- st y+,temp
-
- ldd temp,z+PART_SIZE
- st y+,temp
- ldd temp,z+PART_SIZE+1
- st y+,temp
- ldd temp,z+PART_SIZE+2
- st y+,temp
- ldd temp,z+PART_SIZE+3
- st y+,temp
-
-
- inc temp3
- cpi temp3,MAXDISKS
- breq dsk_pend
-dsk_nextp:
- adiw zl,16
- cpi zl,low(hostbuf+510)
- cpc zh,temp4
- brlo dsk_ploop
-
-dsk_pend:
- sts ndisks,temp3
-
-;Store new partitions and check if the SD card has been changed.
-
- ldi yl,low(tmp_tbl)
- ldi yh,high(tmp_tbl)
- ldi zl,low(hostparttbl)
- ldi zh,high(hostparttbl)
- ldi temp3,8*MAXDISKS
- clt
-dsk_pcpl:
- ld temp,y+
- ld temp2,z
- st z+,temp
- cp temp,temp2
- cpse temp,temp2
- set
- dec temp3
- brne dsk_pcpl
-
- brtc dsk_pcpe
-
- lds temp,ndisks
- tst temp
- breq dsk_pcpe
-
-; SD card changed, print Info.
-
- sbiw z,8*MAXDISKS
-
-dsk_pprl:
- ldd temp,z+4
- ldd temp2,z+5
- or temp,temp2
- ldd temp2,z+6
- or temp,temp2
- ldd temp2,z+7
- or temp,temp2
-
- breq dsk_pcpe
-
- rcall printstr
- .db 13,"CP/M partition at: ",0,0
- ldd temp,z+0
- ldd temp2,z+1
- ldd temp3,z+2
- ldd temp4,z+3
- rcall print_ultoa
- rcall printstr
- .db ", size: ",0,0
- ldd temp,z+4
- ldd temp2,z+5
- ldd temp3,z+6
- ldd temp4,z+7
- lsr temp4
- ror temp3
- ror temp2
- ror temp
- rcall print_ultoa
- rcall printstr
- .db "KB.",0
-
- adiw z,8
- ldi temp,high(hostparttbl)
- cpi xl,low (hostparttbl)
- cpc xh,temp
- brlo dsk_pprl
-
-dsk_pcpe:
- lds temp,ndisks
- ret
-
-
-;***************************************************************************
-
-; ----------------- MMC/SD routines ------------------
-
-mmcByteNoSend:
- ldi temp,0xff
-mmcByte:
-
-.if MMC_DEBUG
- rcall printstr
- .db "MMC: <--",0
- rcall printhex
-.endif
-
- out SPDR,temp
-mmcWrByteW:
- in temp,SPSR
- sbrs temp,7
- rjmp mmcWrByteW
- in temp,SPDR
-
-.if MMC_DEBUG
- rcall printstr
- .db ", -->",0
- rcall printhex
- rcall printstr
- .db ".",13,0
-.endif
- ret
-
-
-;Wait till the mmc answers with the response in temp2, or till a timeout happens.
-mmcWaitResp:
- ldi zl,0
- ldi zh,0
-mmcWaitResploop:
- rcall mmcByteNoSend
- cpi temp,0xff
- brne mmcWaitResploopEnd
- adiw zl,1
- cpi zh,255
- breq mmcWaitErr
- rjmp mmcWaitResploop
-mmcWaitResploopEnd:
- ret
-
-
-mmcWaitErr:
- mov temp,temp2
- rcall printhex
- rcall printstr
- .db ": Error: MMC resp timeout!",13,0
- rjmp resetAVR
-
-mmcInit:
- ldi temp,0x53
- out SPCR,temp
-
- ;Init start: send 80 clocks with cs disabled
- sbi P_MMC_CS,mmc_cs
-
-; ldi temp2,20
- ldi temp2,10 ; exactly 80 clocks
-mmcInitLoop:
- mov temp,temp2
- rcall mmcByte
- dec temp2
- brne mmcInitLoop
-
- cbi P_MMC_CS,mmc_cs
- rcall mmcByteNoSend
- rcall mmcByteNoSend
- rcall mmcByteNoSend
- rcall mmcByteNoSend
- rcall mmcByteNoSend
- rcall mmcByteNoSend
- sbi P_MMC_CS,mmc_cs
- rcall mmcByteNoSend
- rcall mmcByteNoSend
- rcall mmcByteNoSend
- rcall mmcByteNoSend
-
- ;Send init command
- cbi P_MMC_CS,mmc_cs
- ldi temp,0xff ;dummy
- rcall mmcByte
- ldi temp,0xff ;dummy
- rcall mmcByte
- ldi temp,0x40 ;cmd
- rcall mmcByte
- ldi temp,0 ;pxh
- rcall mmcByte
- ldi temp,0 ;pxl
- rcall mmcByte
- ldi temp,0 ;pyh
- rcall mmcByte
- ldi temp,0 ;pyl
- rcall mmcByte
- ldi temp,0x95 ;crc
- rcall mmcByte
- ldi temp,0xff ;return byte
- rcall mmcByte
-
- ldi temp2,0 ;Error Code 0
- rcall mmcWaitResp ;Test on CMD0 is OK
-
- sbi P_MMC_CS,mmc_cs ;disable /CS
- rcall mmcByteNoSend
-
-
-;Read OCR till card is ready
- ldi temp2,100 ;repeat counter
-mmcInitOcrLoop:
- push temp2
-
- cbi P_MMC_CS,mmc_cs ;enable /CS
- ldi temp,0xff ;dummy
- rcall mmcByte
- ldi temp,0x41 ;cmd
- rcall mmcByte
- ldi temp,0 ;pxh
- rcall mmcByte
- ldi temp,0 ;pxl
- rcall mmcByte
- ldi temp,0 ;pyh
- rcall mmcByte
- ldi temp,0 ;pyl
- rcall mmcByte
-; ldi temp,0x95 ;crc
- ldi temp,0x01 ;crc
- rcall mmcByte
- rcall mmcByteNoSend
-
- ldi temp2,1
- rcall mmcWaitResp ;wait until mmc-card send a byte <> 0xFF
- ;the first answer must be 0x01 (Idle-Mode)
- cpi temp,0
- breq mmcInitOcrLoopDone ;second answer is 0x00 (Idle-Mode leave) CMD1 is OK
-
- sbi P_MMC_CS,mmc_cs ;disable /CS
-
- rcall mmcByteNoSend
-
- ldi temp,10
- rcall delay_ms
-
- pop temp2
- dec temp2
- brne mmcInitOcrLoop ;repeat
-
- ldi temp2,4
- rjmp mmcWaitErr
-
-mmcInitOcrLoopDone:
- pop temp2
- sbi P_MMC_CS,mmc_cs ;disable /CS
- rcall mmcByteNoSend
-
- out SPCR,_0
- ret
-
-
-;Call this with yh:yl:xh:xl = sector number
-;
-mmcReadSect:
- ldi temp,0x50
- out SPCR,temp
-
- cbi P_MMC_CS,mmc_cs
- rcall mmcByteNoSend
- ldi temp,0x51 ;cmd (read sector)
- rcall mmcByte
- lsl xl ;convert to byte address (*512)
- rol xh
- rol yl
- mov temp,yl
- rcall mmcByte
- mov temp,xh ;pxl
- rcall mmcByte
- mov temp,xl ;pyh
- rcall mmcByte
- ldi temp,0 ;pyl
- rcall mmcByte
- ldi temp,0x95 ;crc
- rcall mmcByte
- ldi temp,0xff ;return byte
- rcall mmcByte
-
- ;resp
- ldi temp2,2
- rcall mmcWaitResp
-
- ;data token
- ldi temp2,3
- rcall mmcWaitResp
-
- ;Read sector to AVR RAM
- ldi zl,low(hostbuf)
- ldi zh,high(hostbuf)
-mmcreadloop:
- rcall mmcByteNoSend
- st z+,temp
- cpi zl,low(hostbuf+512)
- brne mmcreadloop
- cpi zh,high(hostbuf+512)
- brne mmcreadloop
-
- ;CRC
- rcall mmcByteNoSend
- rcall mmcByteNoSend
-
- sbi P_MMC_CS,mmc_cs
- rcall mmcByteNoSend
-
- out SPCR,_0
- ret
-
-
-;Call this with yh:yl:xh:xl = sector number
-;
-mmcWriteSect:
- ldi temp,0x50
- out SPCR,temp
-
- cbi P_MMC_CS,mmc_cs
- rcall mmcByteNoSend
-
- ldi temp,0x58 ;cmd (write sector)
- rcall mmcByte
- lsl xl ;convert to byte address (*512)
- rol xh
- rol yl
- mov temp,yl
- rcall mmcByte
- mov temp,xh ;pxl
- rcall mmcByte
- mov temp,xl ;pyh
- rcall mmcByte
- ldi temp,0 ;pyl
- rcall mmcByte
- ldi temp,0x95 ;crc
- rcall mmcByte
- ldi temp,0xff ;return byte
- rcall mmcByte
-
- ;resp
- ldi temp2,1
- rcall mmcWaitResp
-
- ;Send data token
- ldi temp,0xfe
- rcall mmcByte
-
- ;Write sector from AVR RAM
- ldi zl,low(hostbuf)
- ldi zh,high(hostbuf)
-mmcwriteloop:
- ld temp,z+
- rcall mmcByte
- cpi zl,low(hostbuf+512)
- brne mmcwriteloop
- cpi zh,high(hostbuf+512)
- brne mmcwriteloop
-
- ;CRC
- rcall mmcByteNoSend
- rcall mmcByteNoSend
-
- ;Status. Ignored for now.
- rcall mmcByteNoSend
-
-;Wait till the mmc has written everything
-mmcwaitwritten:
- rcall mmcByteNoSend
- cpi temp,0xff
- brne mmcwaitwritten
-
- sbi P_MMC_CS,mmc_cs
- rcall mmcByteNoSend
-
- out SPCR,_0
- ret
-
-
-;Set up wdt to time out after 1 sec.
-resetAVR:
- lds temp,txcount ;Wait, till tx buffer is empty
- tst temp
- brne resetAVR
-
- cli
- ldi temp,(1<<WDCE)
- outm8 WDTCSR,temp
- ldi temp,(1<<WDCE) | (1<<WDE) | (110<<WDP0)
- outm8 WDTCSR,temp
-resetwait:
- rjmp resetwait
-
-; ------------------ DRAM routines -------------
-
-;Loads the byte on address xh:xl into temp.
-;must not alter xh:xl
-
-dram_read:
- cli
- DRAM_SETADDR xh, ~0,(1<<ram_ras), ~(1<<ram_a8), (1<<ram_oe)
- cbi P_RAS,ram_ras
- DRAM_SETADDR xl, ~(1<<ram_ras),0, ~((1<<ram_oe)), (1<<ram_a8)
- cbi P_CAS,ram_cas
- cbi P_A8,ram_a8
- dram_wait DRAM_WAITSTATES ;
- in temp,P_DQ-2 ; PIN
- sbi P_CAS,ram_cas
-
- cbi P_CAS,ram_cas
- andi temp,0x0f
- swap temp
- dram_wait DRAM_WAITSTATES ;
- in temp2,P_DQ-2 ; PIN
- andi temp2,0x0f
- or temp,temp2
-
- sbi P_OE,ram_oe
- sbi P_CAS,ram_cas
- sbi P_RAS,ram_ras
- sei
- ret
-
-#if DRAM_WORD_ACCESS
-dram_read_w:
- cpi xl,255
- brne dram_read_w1
-
- rcall dram_read
- push temp
- adiw xl,1
- rcall dram_read
- mov temp2,temp
- pop temp
- ret
-
-dram_read_w1:
- cli
- DRAM_SETADDR xh, ~0,(1<<ram_ras), ~(1<<ram_a8),(1<<ram_oe)
- cbi P_RAS,ram_ras
- DRAM_SETADDR xl, ~(1<<ram_ras),0, ~((1<<ram_oe)), (1<<ram_a8)
- cbi P_CAS,ram_cas
- cbi P_A8,ram_a8
- nop
- in temp,P_DQ-2 ; PIN
- sbi P_CAS,ram_cas
- cbi P_CAS,ram_cas
- andi temp,0x0f
- swap temp
- nop
- in temp2,P_DQ-2 ; PIN
- sbi P_CAS,ram_cas
- andi temp2,0x0f
- or temp,temp2
-
-; push temp
- mov _wl,temp
- inc xl
- DRAM_SETADDR xl, ~(1<<ram_ras),0, ~((1<<ram_oe)), (1<<ram_a8)
- cbi P_CAS,ram_cas
- cbi P_A8,ram_a8
- nop
- in temp,P_DQ-2 ; PIN
- sbi P_CAS,ram_cas
- cbi P_CAS,ram_cas
- andi temp,0x0f
- swap temp
- nop
- in temp2,P_DQ-2 ; PIN
- sbi P_CAS,ram_cas
- andi temp2,0x0f
- or temp2,temp
-; pop temp
- mov temp,_wl
-
- sbi P_OE,ram_oe
- sbi P_RAS,ram_ras
- sei
- ret
-#endif
-
-;Writes the byte in temp to xh:xl
-;must not alter xh:xl
-
-dram_write:
- cli
- ldi temp2,RAM_DQ_MASK | (1<<ram_w) | (1<<ram_cas)
- out DDRC,temp2
-
- mov temp2,temp
- andi temp,RAM_DQ_MASK & ~(1<<ram_w)
- ori temp,(1<<ram_cas)
- out PORTC,temp
- DRAM_SETADDR xh, ~0,(1<<ram_ras), ~(1<<ram_a8),(1<<ram_oe)
- cbi P_RAS,ram_ras
- DRAM_SETADDR xl, ~(1<<ram_ras),0, ~((1<<ram_a8)),(1<<ram_oe)
- cbi PORTC,ram_cas
- sbi PORTC,ram_cas
-
- sbi PORTD,ram_a8
- swap temp2
-
- andi temp2,RAM_DQ_MASK & ~(1<<ram_w)
- ori temp2,(1<<ram_cas)
- out PORTC,temp2
-
- cbi PORTC,ram_cas
- sbi P_RAS,ram_ras
-
- ldi temp,~RAM_DQ_MASK | (1<<ram_w) | (1<<ram_cas)
- out DDRC,temp
- out PORTC,temp
- sei
- ret
-
-#if DRAM_WORD_ACCESS
-dram_write_w:
- cpi xl,255
- brne dram_write_w1
-
- push temp2
- rcall dram_write
- pop temp
- adiw xl,1
- rcall dram_write
- ret
-
-dram_write_w1:
- cli
- push temp2
- ldi temp2,RAM_DQ_MASK | (1<<ram_w) | (1<<ram_cas)
- out DDRC,temp2
-
- mov temp2,temp
- andi temp,RAM_DQ_MASK & ~(1<<ram_w)
- ori temp,(1<<ram_cas)
- out PORTC,temp
-
- DRAM_SETADDR xh, ~0,(1<<ram_ras), ~(1<<ram_a8),(1<<ram_oe)
- cbi P_RAS,ram_ras
- DRAM_SETADDR xl, ~(1<<ram_ras),0, ~((1<<ram_a8)),(1<<ram_oe)
- cbi PORTC,ram_cas
- sbi PORTC,ram_cas
-
- sbi PORTD,ram_a8
- swap temp2
-
- andi temp2,RAM_DQ_MASK & ~(1<<ram_w)
- ori temp2,(1<<ram_cas)
- out PORTC,temp2
-
- cbi PORTC,ram_cas
- sbi PORTC,ram_cas
-
- pop temp
- inc xl
- mov temp2,temp
- andi temp,RAM_DQ_MASK & ~(1<<ram_w)
- ori temp,(1<<ram_cas)
- out PORTC,temp
-
- DRAM_SETADDR xl, ~(1<<ram_ras),0, ~((1<<ram_a8)),(1<<ram_oe)
- cbi PORTC,ram_cas
- sbi PORTC,ram_cas
-
- sbi PORTD,ram_a8
- swap temp2
-
- andi temp2,RAM_DQ_MASK & ~(1<<ram_w)
- ori temp2,(1<<ram_cas)
- out PORTC,temp2
- cbi PORTC,ram_cas
-
- sbi P_RAS,ram_ras
-
- ldi temp,~RAM_DQ_MASK | (1<<ram_w) | (1<<ram_cas)
- out DDRC,temp
- out PORTC,temp
- sei
- ret
-#endif
-
-; ****************************************************************************
-
-; refresh interupt; exec 2 cbr cycles
-refrint: ;4
-
- sbis P_RAS,ram_ras ;2
- reti
- ; CAS RAS
- cbi P_CAS,ram_cas ;2 1| 1|
- ; 1| 1|
- cbi P_RAS,ram_ras ;2 |0 1|
- ; |0 1|
- nop ;1 |0 |0
-; nop ;1 |0 |0
- sbi P_RAS,ram_ras ;2 |0 |0
- ; |0 |0
- dram_wait DRAM_WAITSTATES-1 ;
-; nop ;1 |0 |0
- cbi P_RAS,ram_ras ;2 |0 1|
- ; |0 1|
- sbi P_CAS,ram_cas ;2 |0 |0
- ; |0 |0
- sbi P_RAS,ram_ras ;2 1| |0
- ; 1| 1|
- reti ;4 --> 21 cycles
-
-
-; ------------- system timer 1ms ---------------
- .dseg
-
-delay_timer:
- .byte 1
-timer_base:
-timer_ms:
- .byte 2
-timer_s:
- .byte 4
-; don't change order here, clock put/get depends on it.
-cntms_out: ; register for ms
- .byte 2
-utime_io: ; register for uptime.
- .byte 4
-cnt_1ms:
- .byte 2
-uptime:
- .byte 4
-timer_top:
- .equ timer_size = timer_top - timer_base
-
- .equ clkofs = cnt_1ms-cntms_out
- .equ timerofs = cnt_1ms-timer_ms
-
- .cseg
-sysclockint:
- push zl
- in zl,SREG
- push zl
- push zh
-
- lds zl,delay_timer
- subi zl,1
- brcs syscl1
- sts delay_timer,zl
-syscl1:
- lds zl,cnt_1ms
- lds zh,cnt_1ms+1
- adiw z,1
-
- sts cnt_1ms,zl
- sts cnt_1ms+1,zh
- cpi zl,low(1000)
- ldi zl,high(1000) ;doesn't change flags
- cpc zh,zl
- brlo syscl_end
-
- ldi zl,0 ;can't use _0 register in int.
- sts cnt_1ms,zl
- sts cnt_1ms+1,zl
-
- lds zl,uptime+0
- inc zl
- sts uptime+0,zl
- brne syscl_end
- lds zl,uptime+1
- inc zl
- sts uptime+1,zl
- brne syscl_end
- lds zl,uptime+2
- inc zl
- sts uptime+2,zl
- brne syscl_end
- lds zl,uptime+3
- inc zl
- sts uptime+3,zl
-
-syscl_end:
- pop zh
- pop zl
- out SREG,zl
- pop zl
- reti
-
-; wait for temp ms
-
-delay_ms:
- sts delay_timer,temp
-dly_loop:
- lds temp,delay_timer
- cpi temp,0
- brne dly_loop
- ret
-
-;
-
-clockget:
- ldi temp,0xFF
- subi temp2,TIMER_MSECS
- brcs clkget_end ;Port number in range?
- ldi zl,low(cntms_out)
- ldi zh,high(cntms_out)
- breq clkget_copy ;lowest byte requestet, latch clock
- cpi temp2,6
- brsh clkget_end ;Port number to high?
-
- add zl,temp2
- brcc PC+2
- inc zh
- ld temp,z
-clkget_end:
- ret
-
-
-
-clkget_copy:
- ldi temp2,6
- cli
-clkget_l:
- ldd temp,z+clkofs
- st z+,temp
- dec temp2
- brne clkget_l
- sei
- lds temp,cntms_out
- ;req. byte in temp
- ret
-
-clockput:
- subi temp2,TIMERPORT
- brcs clkput_end ;Port number in range?
- brne clkput_1
-
- ; clock control
-
- cpi temp,starttimercmd
- breq timer_start
- cpi temp,quitTimerCmd
- breq timer_quit
- cpi temp,printTimerCmd
- breq timer_print
- cpi temp,uptimeCmd
- brne cp_ex
- rjmp uptime_print
-cp_ex:
- ret
-
-timer_quit:
- rcall timer_print
- rjmp timer_start
-
-clkput_1:
- dec temp2
- ldi zl,low(cntms_out)
- ldi zh,high(cntms_out)
- breq clkput_copy ;lowest byte requestet, latch clock
- cpi temp2,6
- brsh clkput_end ;Port number to high?
-
- add zl,temp2
- brcc PC+2
- inc zh
- st z,temp
-clkput_end:
- ret
-
-clkput_copy:
- st z,temp
- adiw z,5
- ldi temp2,6
- cli
-clkput_l:
- ldd temp,z+clkofs
- st z+,temp
- dec temp2
- brne clkput_l
- sei
- ret
-
-; start/reset timer
-;
-timer_start:
- ldi zl,low(timer_ms)
- ldi zh,high(timer_ms)
- ldi temp2,6
- cli
-ts_loop:
- ldd temp,z+timerofs
- st z+,temp
- dec temp2
- brne ts_loop
- sei
- ret
-
-
-; print timer
-;
-
-timer_print:
- push yh
- push yl
- ldi zl,low(timer_ms)
- ldi zh,high(timer_ms)
-
-; put ms on stack (16 bit)
-
- cli
- ldd yl,z+timerofs
- ld temp2,z+
- sub yl,temp2
- ldd yh,z+timerofs
- ld temp2,z+
- sbc yh,temp2
- brsh tp_s
-
- subi yl,low(-1000)
- sbci yh,high(-1000)
- sec
-tp_s:
- push yh
- push yl
-
- ldd temp,z+timerofs
- ld yl,z+
- sbc temp,yl
-
- ldd temp2,z+timerofs
- ld yh,z+
- sbc temp2,yh
-
- ldd temp3,z+timerofs
- ld yl,z+
- sbc temp3,yl
-
- sei
- ldd temp4,z+timerofs
- ld yh,z+
- sbc temp4,yh
-
- rcall printstr
- .db 13,"Timer running. Elapsed: ",0
- rcall print_ultoa
-
- rcall printstr
- .db ".",0
- pop temp
- pop temp2
- ldi temp3,0
- ldi temp4,0
- rcall print_ultoa
- rcall printstr
- .db "s.",0,0
-
- pop yl
- pop yh
- ret
-
-uptime_print:
-
- ldi zl,low(cnt_1ms)
- ldi zh,high(cnt_1ms)
-
- cli
- ld temp,z+
- push temp
- ld temp,z+
- push temp
-
- ld temp,z+
- ld temp2,z+
- ld temp3,z+
- sei
- ld temp4,z+
-
- rcall printstr
- .db 13,"Uptime: ",0
-
- rcall print_ultoa
- rcall printstr
- .db ",",0
-
- ldi temp3,0
- ldi temp4,0
- pop temp2
- pop temp
- rcall print_ultoa
- rcall printstr
- .db "s.",0,0
-
- ret
-
-
-
-; --------------- Debugging stuff ---------------
-
-;Print a unsigned lonng value to the uart
-; temp4:temp3:temp2:temp = value
-
-print_ultoa:
- push yh
- push yl
- push z_flags
- push temp4
- push temp3
- push temp2
- push temp
-
- clr yl ;yl = stack level
-
-ultoa1: ldi z_flags, 32 ;yh = temp4:temp % 10
- clr yh ;temp4:temp /= 10
-ultoa2: lsl temp
- rol temp2
- rol temp3
- rol temp4
- rol yh
- cpi yh,10
- brcs ultoa3
- subi yh,10
- inc temp
-ultoa3: dec z_flags
- brne ultoa2
- cpi yh, 10 ;yh is a numeral digit '0'-'9'
- subi yh, -'0'
- push yh ;Stack it
- inc yl
- cp temp,_0 ;Repeat until temp4:temp gets zero
- cpc temp2,_0
- cpc temp3,_0
- cpc temp4,_0
- brne ultoa1
-
- ldi temp, '0'
-ultoa5: cpi yl,3 ; at least 3 digits (ms)
- brge ultoa6
- push temp
- inc yl
- rjmp ultoa5
-
-ultoa6: pop temp ;Flush stacked digits
- rcall uartputc
- dec yl
- brne ultoa6
-
- pop temp
- pop temp2
- pop temp3
- pop temp4
- pop z_flags
- pop yl
- pop yh
- ret
-
-
-;Prints temp2:temp in hex to the uart
-printhexw:
- push temp
- mov temp,temp2
- rcall printhex
- pop temp
- ;fall thru
-
-;Prints temp in hex to the uart
-printhex:
- swap temp
- rcall printhexn
- swap temp
- ;fall thru
-
-;Prints the lower nibble
-printhexn:
- push temp
- andi temp,0xf
- cpi temp,0xA
- brlo printhexn_isno
- subi temp,-7
-printhexn_isno:
- subi temp,-'0'
- rcall uartputc
- pop temp
- ret
-
-;Prints the zero-terminated string following the call statement.
-
-printstr:
- push zh
- push zl
- push yh
- push yl
- push temp
- in yh,sph
- in yl,spl
- ldd zl,y+7
- ldd zh,y+6
-
- lsl zl
- rol zh
-printstr_loop:
- lpm temp,z+
- cpi temp,0
- breq printstr_end
- rcall uartputc
- cpi temp,13
- brne printstr_loop
- ldi temp,10
- rcall uartputc
- rjmp printstr_loop
-
-printstr_end:
- adiw zl,1
- lsr zh
- ror zl
-
- std y+7,zl
- std y+6,zh
- pop temp
- pop yl
- pop yh
- pop zl
- pop zh
- ret
-
-; --------------- AVR HW <-> Z80 periph stuff ------------------
-
-.equ memReadByte = dram_read
-.equ memWriteByte = dram_write
-#if DRAM_WORD_ACCESS
-.equ memReadWord = dram_read_w
-.equ memWriteWord = dram_write_w
-#endif
-
; --------------------------------------------------------------
- .dseg
-
-#define RXBUFMASK RXBUFSIZE-1
-#define TXBUFMASK TXBUFSIZE-1
-
-rxcount:
- .byte 1
-rxidx_w:
- .byte 1
-rxidx_r:
- .byte 1
-txcount:
- .byte 1
-txidx_w:
- .byte 1
-txidx_r:
- .byte 1
-rxfifo:
- .byte RXBUFSIZE
-txfifo:
- .byte TXBUFSIZE
-
-ramtop: .byte 0
- .cseg
-
-; Save received character in a circular buffer. Do nothing if buffer overflows.
-
-rxint:
- push temp
- in temp,sreg
- push temp
- push zh
- push zl
- inm8 temp,RXTXDR0
- lds zh,rxcount ;if rxcount < RXBUFSIZE
- cpi zh,RXBUFSIZE ; (room for at least 1 char?)
- brsh rxi_ov ;
- inc zh ;
- sts rxcount,zh ; rxcount++
-
- ldi zl,low(rxfifo) ;
- lds zh,rxidx_w ;
- add zl,zh ;
- inc zh ;
- andi zh,RXBUFMASK ;
- sts rxidx_w,zh ; rxidx_w = ++rxidx_w % RXBUFSIZE
- ldi zh,high(rxfifo) ;
- brcc PC+2 ;
- inc zh ;
- st z,temp ; rxfifo[rxidx_w] = char
-rxi_ov: ;endif
- pop zl
- pop zh
- pop temp
- out sreg,temp
- pop temp
- reti
-
-
-;Fetches a char from the buffer to temp. If none available, waits till one is.
-
-uartgetc:
- lds temp,rxcount ; Number of characters in buffer
- tst temp
- breq uartgetc ;Wait for char
-
- push zh
- push zl
- ldi zl,low(rxfifo)
- ldi zh,high(rxfifo)
- lds temp,rxidx_r
- add zl,temp
- brcc PC+2
- inc zh
- inc temp
- andi temp,RXBUFMASK
- sts rxidx_r,temp
- cli
- lds temp,rxcount
- dec temp
- sts rxcount,temp
- sei
- ld temp,z ;don't forget to get the char
- pop zl
- pop zh
- ret
-
-txint:
- push temp
- in temp,sreg
- push temp
- lds temp,txcount ;if txcount != 0
- tst temp ;
- breq txi_e ;
-
- dec temp ;
- sts txcount,temp ; --txcount
- push zh ;
- push zl ;
- ldi zl,low(txfifo) ;
- ldi zh,high(txfifo) ;
- lds temp,txidx_r ;
- add zl,temp ;
- brcc PC+2 ;
- inc zh ;
- inc temp ;
- andi temp,TXBUFMASK ;
- sts txidx_r,temp ;
- ld temp,z
- outm8 RXTXDR0,temp
- pop zl
- pop zh
-txi_e: ;endif
- lds temp,txcount
- tst temp
- brne txi_x
- ldi temp, (1<<TXEN0) | (1<<RXEN0) | (1<<RXCIE0)
- outm8 UCSR0B,temp
-txi_x:
- pop temp
- out sreg,temp
- pop temp
- reti
-
-
-;Sends a char from temp to the uart.
-uartputc:
- push zh
- push zl
- push temp
-putc_l:
- lds temp,txcount ;do {
- cpi temp,TXBUFSIZE ;
- brsh putc_l ;} while (txcount >= TXBUFSIZE)
-
- ldi zl,low(txfifo) ;
- ldi zh,high(txfifo) ;
- lds temp,txidx_w ;
- add zl,temp ;
- brcc PC+2 ;
- inc zh ;
- inc temp ;
- andi temp,TXBUFMASK ;
- sts txidx_w,temp ; txidx_w = ++txidx_w % TXBUFSIZE
- pop temp ;
- st z,temp ; txfifo[txidx_w] = char
- cli
- lds zl,txcount
- inc zl
- sts txcount,zl
- ldi zl, (1<<UDRIE0) | (1<<TXEN0) | (1<<RXEN0) | (1<<RXCIE0)
- outm8 UCSR0B,zl
- sei
- pop zl
- pop zh
- ret
-
; ------------ Fetch phase stuff -----------------
.equ FETCH_NOP = (0<<0)
ret
do_fetch_b:
- mov opl,z_b
+ lds opl,z_b
ret
do_fetch_c:
- mov opl,z_c
+ lds opl,z_c
ret
do_fetch_d:
- mov opl,z_d
+ lds opl,z_d
ret
do_fetch_e:
- mov opl,z_e
+ lds opl,z_e
ret
do_fetch_h:
- mov opl,z_h
+ lds opl,z_h
ret
do_fetch_l:
- mov opl,z_l
+ lds opl,z_l
ret
do_fetch_af:
ret
do_fetch_bc:
- movw opl,z_c
+ lds opl,z_c
+ lds oph,z_b
ret
do_fetch_de:
- movw opl,z_e
+ lds opl,z_e
+ lds oph,z_d
ret
do_fetch_hl:
- movw opl,z_l
+ lds opl,z_l
+ lds oph,z_h
ret
do_fetch_sp:
ret
do_fetch_mbc:
- movw xl,z_c
- rcall memReadByte
- mov opl,temp
+ lds xh,z_b
+ lds xl,z_c
+ mem_read_d opl
ret
do_fetch_mde:
- movw xl,z_e
- rcall memReadByte
- mov opl,temp
+ lds xh,z_d
+ lds xl,z_e
+ mem_read_d opl
ret
do_fetch_mhl:
- movw xl,z_l
- rcall memReadByte
- mov opl,temp
+ lds xh,z_h
+ lds xl,z_l
+ mem_read_d opl
ret
do_fetch_msp:
- movw xl,z_spl
-#if DRAM_WORD_ACCESS
- rcall memReadWord
- movw opl,temp
-#else
- rcall memReadByte
- mov opl,temp
- adiw xl,1
- rcall memReadByte
- mov oph,temp
-#endif
+ movw x,z_spl
+ mem_read_d opl
+ adiw x,1
+ mem_read_d oph
ret
do_fetch_dir8:
- movw xl,z_pcl
- rcall memReadByte
+ mem_read_ds opl, z_pc
adiw z_pcl,1
- mov opl,temp
ret
do_fetch_dir16:
- movw xl,z_pcl
-#if DRAM_WORD_ACCESS
- rcall memReadWord
- movw opl,temp
-#else
- rcall memReadByte
- mov opl,temp
- adiw xl,1
- rcall memReadByte
- mov oph,temp
-#endif
- adiw z_pcl,2
+ mem_read_ds opl, z_pc
+ adiw z_pcl,1
+ mem_read_ds oph, z_pc
+ adiw z_pcl,1
ret
do_fetch_rst:
- movw xl,z_pcl
- subi xl,1
- sbci xh,0
- rcall memReadByte
- andi temp,0x38
+ movw x,z_pcl
+ sbiw x,1
+ mem_read_d opl
+ andi opl,0x38
ldi oph,0
- mov opl,temp
ret
ret
do_store_b:
- mov z_b,opl
+ sts z_b,opl
ret
do_store_c:
- mov z_c,opl
+ sts z_c,opl
ret
do_store_d:
- mov z_d,opl
+ sts z_d,opl
ret
do_store_e:
- mov z_e,opl
+ sts z_e,opl
ret
do_store_h:
- mov z_h,opl
+ sts z_h,opl
ret
do_store_l:
- mov z_l,opl
+ sts z_l,opl
ret
do_store_af:
ret
do_store_bc:
- mov z_b,oph
- mov z_c,opl
+ sts z_b,oph
+ sts z_c,opl
ret
do_store_de:
- mov z_d,oph
- mov z_e,opl
+ sts z_d,oph
+ sts z_e,opl
ret
do_store_hl:
- mov z_h,oph
- mov z_l,opl
+ sts z_h,oph
+ sts z_l,opl
ret
do_store_mbc:
- movw xl,z_c
- mov temp,opl
- rcall memWriteByte
+ lds xh,z_b
+ lds xl,z_c
+ mem_write_s opl
ret
do_store_mde:
- movw xl,z_e
- mov temp,opl
- rcall memWriteByte
+ lds xh,z_d
+ lds xl,z_e
+ mem_write_s opl
ret
do_store_mhl:
- movw xl,z_l
- mov temp,opl
- rcall memWriteByte
+ lds xh,z_h
+ lds xl,z_l
+ mem_write_s opl
ret
do_store_msp:
- movw xl,z_spl
-#if DRAM_WORD_ACCESS
- movw temp,opl
- rcall memWriteWord
-#else
- mov temp,opl
- rcall memWriteByte
+ movw xl,z_spl
+ mem_write_s opl
adiw xl,1
- mov temp,oph
- rcall memWriteByte
-#endif
+ mem_write_s oph
ret
do_store_sp:
ret
do_store_ret:
- rcall do_op_pop16
- movw z_pcl,opl
+ movw x,z_spl
+ mem_read_d z_pcl
+ adiw x,1
+ mem_read_d z_pch
+ adiw x,1
+ movw z_spl,x
+
+.if STACK_DBG
+ printnewline
+ printstring "Stack pop "
+ movw temp,z_pcl
+ rcall printhexw
+ printstring ", SP is now "
+ movw temp,z_spl
+ rcall printhexw
+ printstring ". "
+.endif
ret
do_store_call:
- push opl
- push oph
- movw opl,z_pcl
- rcall do_op_push16
- pop z_pch
- pop z_pcl
+ movw xl,z_spl
+ sbiw x,1
+ mem_write_s z_pch
+ sbiw x,1
+ mem_write_s z_pcl
+ movw z_spl,xl
+
+.if STACK_DBG
+ printnewline
+ printstring "Stack push "
+ movw temp,z_pcl
+ rcall printhexw
+ printstring ", SP is now "
+ movw temp,z_spl
+ rcall printhexw
+ printstring ". "
+.endif
+ movw z_pcl,opl
ret
+
do_store_am:
- movw xl,opl
- mov temp,z_a
- rcall memWriteByte
+ mem_write_ds op, z_a
ret
rjmp do_op_deca
-;How the flags are supposed to work:
-;7 ZFL_S - Sign flag (=MSBit of result)
-;6 ZFL_Z - Zero flag. Is 1 when the result is 0
-;4 ZFL_H - Half-carry (carry from bit 3 to 4)
-;2 ZFL_P - Parity/2-complement Overflow
-;1 ZFL_N - Subtract - set if last op was a subtract
-;0 ZFL_C - Carry
-;
-;I sure hope I got the mapping between flags and instructions correct...
-
;----------------------------------------------------------------
;| |
;| Zilog |
;| ## |Only lower 4 bits of accumulator A used |
;----------------------------------------------------------------
+;How the flags are supposed to work:
+;7 ZFL_S - Sign flag (=MSBit of result)
+;6 ZFL_Z - Zero flag. Is 1 when the result is 0
+;4 ZFL_H - Half-carry (carry from bit 3 to 4)
+;2 ZFL_P - Parity/2-complement Overflow
+;1 ZFL_N - Subtract - set if last op was a subtract
+;0 ZFL_C - Carry
+;
+;I sure hope I got the mapping between flags and instructions correct...
+
+.equ ZFL_S = 7
+.equ ZFL_Z = 6
+.equ ZFL_H = 4
+.equ ZFL_P = 2
+.equ ZFL_N = 1
+.equ ZFL_C = 0
.equ AVR_T = SREG_T
.equ AVR_H = SREG_H
.equ AVR_Z = SREG_Z
.equ AVR_C = SREG_C
-;------------------------------------------------;
-; Move single bit between two registers
-;
-; bmov dstreg,dstbit,srcreg.srcbit
-
-.macro bmov
- bst @2,@3
- bld @0,@1
-.endm
-
-
;------------------------------------------------;
; Load table value from flash indexed by source reg.
;
mov zl,@2
lpm @0,z
.endm
+
.macro do_z80_flags_HP
#if EM_Z80
bmov z_flags, ZFL_P, temp, AVR_V
.endm
+;----------------------------------------------------------------
+do_op_inv:
+ printstring "Invalid opcode @ PC="
+ movw temp,z_pcl
+ rcall printhexw
+haltinv:
+ rjmp haltinv
+
do_op_nop:
ret
+;----------------------------------------------------------------
+;|Mnemonic |SZHPNC|Description |Notes |
+;----------------------------------------------------------------
+;|OUT [n],A |------|Output |[n]=A |
+;
+;
+;Interface with peripherials goes here :)
+do_op_outa: ; out (opl),a
+.if PORT_DEBUG
+ printnewline
+ printstring "Port write: "
+ mov temp,z_a
+ rcall printhex
+ printstring " -> ("
+ mov temp,opl
+ rcall printhex
+ printstring ") "
+.endif
+ mov temp,z_a
+ mov temp2,opl
+ rcall portWrite
+ ret
+
+;----------------------------------------------------------------
+;|Mnemonic |SZHPNC|Description |Notes |
+;----------------------------------------------------------------
+;|IN A,[n] |------|Input |A=[n] |
+;
+;
+do_op_in: ; in a,(opl)
+.if PORT_DEBUG
+ printnewline
+ printstring "Port read: ("
+ mov temp,opl
+ rcall printhex
+ printstring ") -> "
+.endif
+
+ mov temp2,opl
+ rcall portRead
+ mov opl,temp
+
+.if PORT_DEBUG
+ rcall printhex
+ printstring " "
+.endif
+ ret
+
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;
;
do_op_addhl:
- add opl,z_l
- adc oph,z_h
+ lds temp,z_l
+ lds temp2,z_h
+ add opl,temp
+ adc oph,temp2
in temp,sreg
bmov z_flags,ZFL_H, temp,AVR_H
bmov z_flags,ZFL_C, temp,AVR_C
;
do_op_sthl: ;store hl to mem loc in opl:h
movw xl,opl
-#if DRAM_WORD_ACCESS
- movw temp,z_l
- rcall memWriteWord
-#else
- mov temp,z_l
- rcall memWriteByte
+ lds temp,z_l
+ mem_write
adiw xl,1
- mov temp,z_h
- rcall memWriteByte
-#endif
+ lds temp,z_h
+ mem_write
ret
;----------------------------------------------------------------
;
do_op_rmem16:
movw xl,opl
-#if DRAM_WORD_ACCESS
- rcall memReadWord
- movw opl,temp
-#else
- rcall memReadByte
- mov opl,temp
- adiw xl,1
- rcall memReadByte
- mov oph,temp
-#endif
+ mem_read_d opl
+ adiw x,1
+ mem_read_d oph
ret
;----------------------------------------------------------------
;
;
do_op_rmem8:
- movw xl,opl
- rcall memReadByte
- mov opl,temp
+ mem_read_ds opl, op
ret
;----------------------------------------------------------------
;
;
do_op_push16:
- movw xl,z_spl
- subi xl,2
- sbci xh,0
- movw z_spl,xl
-#if DRAM_WORD_ACCESS
- movw temp,opl
- rcall memWriteWord
-#else
- mov temp,opl
- rcall memWriteByte
- adiw xl,1
- mov temp,oph
- rcall memWriteByte
-#endif
+ movw xl,z_spl
+ sbiw x,1
+ mem_write_s oph
+ sbiw x,1
+ mem_write_s opl
+ movw z_spl,xl
.if STACK_DBG
- rcall printstr
- .db "Stack push ",0
- mov tempw,opl
+ printnewline
+ printstring "Stack push "
+ movw temp,opl
rcall printhexw
- rcall printstr
- .db ", SP is now ",0
- mov tempw,z_spl
+ printstring ", SP is now "
+ movw temp,z_spl
rcall printhexw
- rcall printstr
- .db ".",13,0
+ printstring ". "
.endif
ret
;
;
do_op_pop16:
- movw xl,z_spl
-#if DRAM_WORD_ACCESS
- rcall memReadWord
- movw opl,temp
-#else
- rcall memReadByte
- mov opl,temp
- adiw xl,1
- rcall memReadByte
- mov oph,temp
-#endif
-
- ldi temp,2
- add z_spl,temp
- adc z_sph,_0
+ movw x,z_spl
+ mem_read_d opl
+ adiw x,1
+ mem_read_d oph
+ adiw x,1
+ movw z_spl,x
.if STACK_DBG
- rcall printstr
- .db "Stack pop: val ",0
+ printnewline
+ printstring "Stack pop "
movw temp,opl
rcall printhexw
- rcall printstr
- .db ", SP is now",0
+ printstring ", SP is now "
movw temp,z_spl
rcall printhexw
- rcall printstr
- .db ".",13,0
+ printstring ". "
.endif
ret
;
;
do_op_exhl:
- mov temp,z_h
- mov z_h,oph
- mov oph,temp
- mov temp,z_l
- mov z_l,opl
- mov opl,temp
+ lds temp,z_l
+ lds temp2,z_h
+ sts z_l,opl
+ sts z_h,oph
+ movw opl,temp
ret
;----------------------------------------------------------------
clr insdecl
ret
-;----------------------------------------------------------------
-;|Mnemonic |SZHPNC|Description |Notes |
-;----------------------------------------------------------------
-;|OUT [n],A |------|Output |[n]=A |
-;
-;
-;Interface with peripherials goes here :)
-do_op_outa: ; out (opl),a
-.if PORT_DEBUG
- rcall printstr
- .db 13,"Port write: ",0
- mov temp,z_a
- rcall printhex
- rcall printstr
- .db " -> (",0
- mov temp,opl
- rcall printhex
- rcall printstr
- .db ")",13,0
-.endif
- mov temp,z_a
- mov temp2,opl
- rcall portWrite
- ret
-
-;----------------------------------------------------------------
-;|Mnemonic |SZHPNC|Description |Notes |
-;----------------------------------------------------------------
-;|IN A,[n] |------|Input |A=[n] |
-;
-;
-do_op_in: ; in a,(opl)
-.if PORT_DEBUG
- rcall printstr
- .db 13,"Port read: (",0
- mov temp,opl
- rcall printhex
- rcall printstr
- .db ") -> ",0
-.endif
-
- mov temp2,opl
- rcall portRead
- mov opl,temp
-
-.if PORT_DEBUG
- rcall printhex
- rcall printstr
- .db 13,0
-.endif
- ret
-
-
-;----------------------------------------------------------------
-do_op_inv:
- rcall printstr
- .db "Invalid opcode @ PC=",0,0
- movw temp,z_pcl
- rcall printhexw
-
-;----------------------------------------------------------------
-haltinv:
- rjmp haltinv
-;----------------------------------------------------------------
-; Lookup table, stolen from z80ex, Z80 emulation library.
-; http://z80ex.sourceforge.net/
-
-; The S, Z, 5 and 3 bits and the parity of the lookup value
-.org (PC+255) & 0xff00
-sz53p_tab:
- .db 0x44,0x00,0x00,0x04,0x00,0x04,0x04,0x00
- .db 0x08,0x0c,0x0c,0x08,0x0c,0x08,0x08,0x0c
- .db 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04
- .db 0x0c,0x08,0x08,0x0c,0x08,0x0c,0x0c,0x08
- .db 0x20,0x24,0x24,0x20,0x24,0x20,0x20,0x24
- .db 0x2c,0x28,0x28,0x2c,0x28,0x2c,0x2c,0x28
- .db 0x24,0x20,0x20,0x24,0x20,0x24,0x24,0x20
- .db 0x28,0x2c,0x2c,0x28,0x2c,0x28,0x28,0x2c
- .db 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04
- .db 0x0c,0x08,0x08,0x0c,0x08,0x0c,0x0c,0x08
- .db 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00
- .db 0x08,0x0c,0x0c,0x08,0x0c,0x08,0x08,0x0c
- .db 0x24,0x20,0x20,0x24,0x20,0x24,0x24,0x20
- .db 0x28,0x2c,0x2c,0x28,0x2c,0x28,0x28,0x2c
- .db 0x20,0x24,0x24,0x20,0x24,0x20,0x20,0x24
- .db 0x2c,0x28,0x28,0x2c,0x28,0x2c,0x2c,0x28
- .db 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84
- .db 0x8c,0x88,0x88,0x8c,0x88,0x8c,0x8c,0x88
- .db 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80
- .db 0x88,0x8c,0x8c,0x88,0x8c,0x88,0x88,0x8c
- .db 0xa4,0xa0,0xa0,0xa4,0xa0,0xa4,0xa4,0xa0
- .db 0xa8,0xac,0xac,0xa8,0xac,0xa8,0xa8,0xac
- .db 0xa0,0xa4,0xa4,0xa0,0xa4,0xa0,0xa0,0xa4
- .db 0xac,0xa8,0xa8,0xac,0xa8,0xac,0xac,0xa8
- .db 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80
- .db 0x88,0x8c,0x8c,0x88,0x8c,0x88,0x88,0x8c
- .db 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84
- .db 0x8c,0x88,0x88,0x8c,0x88,0x8c,0x8c,0x88
- .db 0xa0,0xa4,0xa4,0xa0,0xa4,0xa0,0xa0,0xa4
- .db 0xac,0xa8,0xa8,0xac,0xa8,0xac,0xac,0xa8
- .db 0xa4,0xa0,0xa0,0xa4,0xa0,0xa4,0xa4,0xa0
- .db 0xa8,0xac,0xac,0xa8,0xac,0xa8,0xa8,0xac
-
-
; ----------------------- Opcode decoding -------------------------
; Lookup table for Z80 opcodes. Translates the first byte of the instruction word into three
.dw (FETCH_DIR8 | OP_CPFA | STORE_NOP) ; FE nn CP n
.dw (FETCH_RST | OP_NOP | STORE_CALL) ; FF RST 38H
+;----------------------------------------------------------------
+; Lookup table, stolen from z80ex, Z80 emulation library.
+; http://z80ex.sourceforge.net/
+
+; The S, Z, 5 and 3 bits and the parity of the lookup value
+
+.org (PC+255) & 0xff00
+sz53p_tab:
+ .db 0x44,0x00,0x00,0x04,0x00,0x04,0x04,0x00
+ .db 0x08,0x0c,0x0c,0x08,0x0c,0x08,0x08,0x0c
+ .db 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04
+ .db 0x0c,0x08,0x08,0x0c,0x08,0x0c,0x0c,0x08
+ .db 0x20,0x24,0x24,0x20,0x24,0x20,0x20,0x24
+ .db 0x2c,0x28,0x28,0x2c,0x28,0x2c,0x2c,0x28
+ .db 0x24,0x20,0x20,0x24,0x20,0x24,0x24,0x20
+ .db 0x28,0x2c,0x2c,0x28,0x2c,0x28,0x28,0x2c
+ .db 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04
+ .db 0x0c,0x08,0x08,0x0c,0x08,0x0c,0x0c,0x08
+ .db 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00
+ .db 0x08,0x0c,0x0c,0x08,0x0c,0x08,0x08,0x0c
+ .db 0x24,0x20,0x20,0x24,0x20,0x24,0x24,0x20
+ .db 0x28,0x2c,0x2c,0x28,0x2c,0x28,0x28,0x2c
+ .db 0x20,0x24,0x24,0x20,0x24,0x20,0x20,0x24
+ .db 0x2c,0x28,0x28,0x2c,0x28,0x2c,0x2c,0x28
+ .db 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84
+ .db 0x8c,0x88,0x88,0x8c,0x88,0x8c,0x8c,0x88
+ .db 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80
+ .db 0x88,0x8c,0x8c,0x88,0x8c,0x88,0x88,0x8c
+ .db 0xa4,0xa0,0xa0,0xa4,0xa0,0xa4,0xa4,0xa0
+ .db 0xa8,0xac,0xac,0xa8,0xac,0xa8,0xa8,0xac
+ .db 0xa0,0xa4,0xa4,0xa0,0xa4,0xa0,0xa0,0xa4
+ .db 0xac,0xa8,0xa8,0xac,0xa8,0xac,0xac,0xa8
+ .db 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80
+ .db 0x88,0x8c,0x8c,0x88,0x8c,0x88,0x88,0x8c
+ .db 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84
+ .db 0x8c,0x88,0x88,0x8c,0x88,0x8c,0x8c,0x88
+ .db 0xa0,0xa4,0xa4,0xa0,0xa4,0xa0,0xa0,0xa4
+ .db 0xac,0xa8,0xa8,0xac,0xa8,0xac,0xac,0xa8
+ .db 0xa4,0xa0,0xa0,0xa4,0xa0,0xa4,0xa4,0xa0
+ .db 0xa8,0xac,0xac,0xa8,0xac,0xa8,0xa8,0xac
+
+
; vim:set ts=8 noet nowrap
+