.include "m8def.inc"
#elif defined atmega168
.include "m168def.inc"
+#elif defined atmega328P
+ .include "m328Pdef.inc"
#else /* default */
.include "m88def.inc"
;FUSE_H=0xDF
.equ refr_vect = OC2Aaddr
#endif
-#define DRAM_WORD_ACCESS 1 /* experimental */
+#define DRAM_WORD_ACCESS 0 /* experimental */
-#define EM_Z80 0 /* we don't have any z80 instructions yet */
+#define EM_Z80 0 /* we don't have any z80 instructions yet */
.equ MMC_DEBUG = 0
.equ INS_DEBUG = 0
.equ ram_ras = 5
.equ mmc_sck = 5
-.equ P_RAS = PORTB
+.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 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)
.equ ZFL_N = 1
.equ ZFL_C = 0
+;Register definitions
+.undef xl ;r26
+.undef xh ;r27
+
+.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 ;
+.def adrl = r26 ;
+.def adrh = r27 ;
+; yl ;r28
+; yh ;r29
+; zl ;r30 ;
+; zh ;r31 ;
+
+
+#if 0
;Register definitions
.def _tmp = r0 ; 0
.def _0 = r1
.def z_h = r8
;.def z_spl = r9
;.def z_sph = r10
-
.def z_a = r11
-
-
.def _wl = r12
.def _wh = r13
.def z_spl = r14
.def adrh = r29 ;
; zl ;r30 ;
; zh ;r31 ;
+#endif
+#if defined __ATmega8__
+ .equ flags = TWBR
+#else
+ .equ flags = GPIOR0
+#endif
+
+ .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
- ;SRAM
- .dseg
-
-dsk_trk: .byte 1
-dsk_sec: .byte 1
-dsk_dmah: .byte 1
-dsk_dmal: .byte 1
-
-;Sector buffer for 512 byte reads/writes from/to SD-card
-
-sectbuff:
- .byte 512
-
-
.cseg
.org 0
rjmp start ; reset vector
rcall mmcReadSect
;Save to Z80 RAM (only 128 bytes because that's retro)
- ldi zl,low(sectbuff)
- ldi zh,high(sectbuff)
+ ldi zl,low(hostbuf)
+ ldi zh,high(hostbuf)
ldi adrh,0x20
ldi adrl,0x00
iplwriteloop:
pop zl
pop zh
adiw adrl,1
- cpi zl,low(sectbuff+128)
+ cpi zl,low(hostbuf+128)
brne iplwriteloop
- cpi zh,high(sectbuff+128)
+ cpi zh,high(hostbuf+128)
brne iplwriteloop
-
+ rcall dsk_boot ;init (de)blocking buffer
;Init z80
ldi temp,0x20
mov z_pch,temp
- ldi trace,0
+ cbi flags,trace
rcall printstr
.db 13,"Ok, CPU is live!",13,0,0
main:
- ldi trace,0
+ cbi flags,trace
cpi z_pch,1
brlo notraceon
cpi z_pch,$dc
brsh notraceon
- ldi trace,1
+ sbi flags,trace
notraceon:
.if INS_DEBUG
- cpi trace,0
- breq notrace1
+ sbis flags,trace
+ rjmp notrace1
rcall printstr
.db "PC=",0
push temp
lpm insdech,Z
.if INS_DEBUG
- cpi trace,0
- breq notrace2
+ sbis flags,trace
+ rjmp notrace2
rcall printstr
.db ", decoded=",0
mov temp,insdech
icall
.if INS_DEBUG
- cpi trace,0
- breq notrace3
+ sbis flags,trace
+ rjmp notrace3
rcall printstr
.db "pre: oph:l=",0
mov temp,oph
icall
.if INS_DEBUG
- cpi trace,0
- breq notrace4
+ sbis flags,trace
+ rjmp notrace4
rcall printstr
.db ",post:oph:l=",0
mov temp,oph
; *** Stage 5: Store operand. Use the store jumptable for this.
swap insdecl
swap insdech
- mov temp,insdecl
+ movw temp,insdecl
andi temp,0x0E
- andi insdech,0x30
- or temp,insdech
+ andi temp2,0x30
+ or temp,temp2
breq nostore
lsr temp
ldi zl,low(storejumps)
icall
.if INS_DEBUG
- cpi trace,0
- breq notrace5
+ sbis flags,trace
+ rjmp notrace5
rcall printstr
.db ", stored.",0
notrace5:
nostore:
.if INS_DEBUG
- cpi trace,0
- breq notrace6
+ sbis flags,trace
+ rjmp notrace6
rcall printstr
.db 13,0
notrace6:
;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
-;16 - Track select
-;18 - Sector select
-;20 - Write addr l
-;21 - Write addr h
-;22 - Trigger - write 1 to read, 2 to write a sector using the above info.
-; This will automatically move track, sector and dma addr to the next sector.
+;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 1 to read, 2 to write a sector using the above info;
+; 3 - 5, 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 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
+seekdsk: .byte 1 ;seek disk number
+seektrk: .byte 2 ;seek track number
+seeksec: .byte 1 ;seek sector number
+
+hostdsk: .byte 1 ;host disk number
+hostlba: .byte 2 ;host track number
+
+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
+
;Called with port in temp2. Should return value in temp.
portRead:
cpi temp2,0
cpi temp2,2
breq conOut
cpi temp2,16
- breq dskTrackSel
+ 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
-dskTrackSel:
- sts dsk_trk,temp
+dskTrackSel_l:
+ sts seektrk,temp
+ sts seektrk+1,_0
+ ret
+
+dskTrackSel_h:
+ sts seektrk+1,temp
ret
dskSecSel:
- sts dsk_sec,temp
+ sts seeksec,temp
ret
dskDmal:
- sts dsk_dmal,temp
+ sts dmaadr,temp
ret
dskDmah:
- sts dsk_dmah,temp
+ sts dmaadr+1,temp
ret
dskDoIt:
+ ;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:
+ 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:
+
+.if 0
+ rcall timer_quit
+ rcall printstr
+ .db " In",0
+.endif
+
.if DISK_DEBUG
push temp
rcall printstr
+ .db 13,0
+ rcall printstr
.db "Disk read: track ",0
- lds temp,dsk_trk
+ lds temp,seektrk+1
+ rcall printhex
+ lds temp,seektrk
rcall printhex
rcall printstr
- .db " sector ",0
- lds temp,dsk_sec
+ .db " sector ",0,0
+ lds temp,seeksec
rcall printhex
rcall printstr
- .db " dma-addr ",0
- lds temp,dsk_dmah
+ .db " dma-addr ",0,0
+ lds temp,dmaadr+1
rcall printhex
- lds temp,dsk_dmal
+ lds temp,dmaadr
rcall printhex
- rcall printstr
- .db ".",13,0
+; rcall printstr
+; .db ".",13,0,0
pop temp
.endif
+ sts unacnt,_0
+ sbi flags,readop ;read operation
+ sbi flags,rsflag ;must read data
+ ldi temp,WRUAL ;write type
+ sts wrtype,temp ;treat as unalloc
+ rjmp dsk_rwoper ;to perform the read
- ;First, convert track/sector to an LBA address (in 128byte blocks)
- push temp
- lds adrl,dsk_sec
- ldi adrh,0
- lds temp2,dsk_trk
- ldi temp,26
-dskXlateLoop:
- cpi temp2,0
- breq dskXlateLoopEnd
- add adrl,temp
- adc adrh,_0
- dec temp2
- rjmp dskXlateLoop
-dskXlateLoopEnd:
- pop temp
- ;Now, see what has to be done.
- cpi temp,1
- breq dskDoItRead
- cpi temp,2
- breq dskDoItWrite
-
-dskDoItRead:
- push adrl
- ;Convert from 128-byte LBA blocks to 512-byte LBA blocks
- lsr adrh
- ror adrl
- lsr adrh
- ror adrl
- ;Read 512-byte sector
- rcall mmcReadSect
- pop adrl
-
- ;Now, move the correct portion of the sector from AVR ram to Z80 ram
- ldi zl,low(sectbuff)
- ldi zh,high(sectbuff)
- ldi temp,128
- ldi temp2,0
- sbrc adrl,0
- add zl,temp
- sbrc adrl,0
- adc zh,temp2
- sbrc adrl,1
- inc zh
-
- lds adrh,dsk_dmah
- lds adrl,dsk_dmal
-
- ldi temp2,128
-dskDoItReadMemLoop:
- push temp2
- ld temp,z+
- push zh
- push zl
- rcall memWriteByte
- pop zl
- pop zh
- adiw adrl,1
- pop temp2
- dec temp2
- brne dskDoItReadMemLoop
- ret
+dsk_write:
+ ;write the selected CP/M sector
-dskDoItWrite:
-;The write routines is a bit naive: it'll read the 512-byte sector the 128byte CPM-sector
-;resides in into memory, will overwrite the needed 128 byte with the Z80s memory buffer
-;and will then write it back to disk. In theory, this would mean that every 512 bytes
-;written will take 4 write cycles, while theoretically the writes could be deferred so we
-;would only have to do one write cycle.
+ andi temp,WRTMSK
+ sts wrtype,temp ;save write type
+ cbi flags,readop ;not a read operation
.if DISK_DEBUG
push temp
rcall printstr
- .db "Disk write: track ",0
- lds temp,dsk_trk
+ .db 13,0
+ rcall printstr
+ .db "Disk write: track ",0,0
+ lds temp,seektrk+1
+ rcall printhex
+ lds temp,seektrk
rcall printhex
rcall printstr
- .db " sector ",0
- lds temp,dsk_sec
+ .db " sector ",0,0
+ lds temp,seeksec
rcall printhex
rcall printstr
- .db " dma-addr ",0
- lds temp,dsk_dmah
+ .db " dma-addr ",0,0
+ lds temp,dmaadr+1
rcall printhex
- lds temp,dsk_dmal
+ lds temp,dmaadr
rcall printhex
rcall printstr
- .db ".",13,0
+ .db " wrtype ",0,0
+ lds temp,wrtype
+ rcall printhex
+; rcall printstr
+; .db ".",13,0,0
pop temp
.endif
+ 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
+ sts erflag,_0 ;no errors (yet)
+
+ ;Convert track/sector to an LBA address (in 128byte blocks)
+
+ lds adrl,seeksec ;
+ ldi adrh,0 ;
+ lds temp3,seektrk ;
+ lds temp4,seektrk+1 ;
+ ldi temp,CPMSPT ;
+ mul temp3,temp ;
+ add adrl,r0 ;
+ adc adrh,r1 ;
+ mul temp4,temp ;
+ add adrh,r0 ;adrh:adrl := sec + trk * SectorsPerTrack
+ clr _0
+
+ mov temp,adrl
+ andi temp,SECMSK ;mask buffer number
+ push temp ;save for later
+.if DISK_DEBUG
+ rcall printstr
+ .db "; bufnr: ",0,0
+ rcall printhex
+.endif
- push adrl
- push adrh
- ;Convert from 128-byte LBA blocks to 512-byte LBA blocks
- lsr adrh
- ror adrl
- lsr adrh
- ror adrl
- ;Read 512-byte sector
- rcall mmcReadSect
- pop adrh
- pop adrl
-
- push adrl
- push adrh
-
-;Copy the data from the Z80 DMA buffer in external memory to the right place in the
-;sector buffer.
- ;Now, move the correct portion of the sector from AVR ram to Z80 ram
- ldi zl,low(sectbuff)
- ldi zh,high(sectbuff)
- ldi temp,128
- ldi temp2,0
- sbrc adrl,0
- add zl,temp
- sbrc adrl,0
- adc zh,temp2
- sbrc adrl,1
- inc zh
- lds adrh,dsk_dmah
- lds adrl,dsk_dmal
- ldi temp2,128
-dskDoItWriteMemLoop:
- push temp2
-
- push zh
- push zl
+ ;Convert from CP/M LBA blocks to host LBA blocks
+ ldi temp,SECSHF
+dsk_sh1:
+ lsr adrh
+ ror adrl
+ dec temp
+ brne dsk_sh1
+ ;adrh:adrl = host block to seek
+; active host sector?
+ sbis flags,hostact ;host active?
+ rjmp dsk_filhst ;fill host if not
+
+; host buffer active, same as seek buffer?
+ lds temp,seekdsk
+ lds temp3,hostdsk ;same disk?
+ cp temp,temp3 ;seekdsk = hostdsk?
+ brne dsk_nomatch
+
+; same disk, same block?
+ lds temp3,hostlba
+ lds temp4,hostlba+1
+ cp adrl,temp3
+ cpc adrh,temp4
+ breq dsk_match
+;
+dsk_nomatch:
+ ;proper disk, but not correct sector
+ sbic flags,hostwrt ;host written?
+ rcall dsk_writehost ;clear host buff
+
+dsk_filhst:
+ ;may have to fill the host buffer
+ lds temp,seekdsk
+ sts hostdsk,temp
+ sts hostlba,adrl
+ sts hostlba+1,adrh
+
+ sbic flags,rsflag ;need to read?
+ rcall dsk_readhost ;yes, if 1
+ cbi flags,hostwrt ;no pending write
+
+dsk_match:
+ sbi flags,hostact ;host buffer active now
+
+ ;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
+ push r0
+ push r1
+ clr _0
+ rcall printstr
+ .db "; host buf adr: ",0,0
+ pop temp
+ rcall printhex
+ pop temp
+ rcall printhex
+.endif
+ clr _0
+
+ lds adrl,dmaadr
+ lds adrh,dmaadr+1
+ push yl
+ ldi yl,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
- pop zl
- pop zh
st z+,temp
adiw adrl,1
+ dec yl
+ brne dsk_wmove
+ rjmp dsk_rwmfin
+
+dsk_rmove:
+ ld temp,z+
+ rcall memWriteByte
+ adiw adrl,1
+ dec yl
+ brne dsk_rmove
+dsk_rwmfin:
+ pop yl
+; data has been moved to/from host buffer
+ lds temp,wrtype ;write type
+ cpi temp,WRDIR ;to directory?
+ breq dsk_wdir
+ lds temp,erflag
+.if 0
+ rcall timer_quit
+ rcall printstr
+ .db " Out",0
+.endif
+ 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
+ lds temp,erflag
+ ret
+
+
+;*****************************************************
+;* WRITEhost performs the physical write to *
+;* the host disk, READhost reads the physical *
+;* disk. *
+;*****************************************************
+
+dsk_writehost:
+ ;hostdsk = host disk #, hostlba = host block #.
+ ;Write "hostsize" bytes from hostbuf and return
+ ;error flag in erflag.
+ ;Return erflag non-zero if error
+
+ push adrh
+ push adrl
+ lds adrl,hostlba
+ lds adrh,hostlba+1
+ rcall mmcWriteSect
+ pop adrl
+ pop adrh
+ sts erflag,_0
+ ret
- pop temp2
- dec temp2
- brne dskDoItWriteMemLoop
+dsk_readhost:
+ ;hostdsk = host disk #, hostlba = host block #.
+ ;Read "hostsiz" bytes into hostbuf and return
+ ;error flag in erflag.
- pop adrh
- pop adrl
+ push adrh
+ push adrl
+ lds adrl,hostlba
+ lds adrh,hostlba+1
+ rcall mmcReadSect
+ pop adrl
+ pop adrh
+ sts erflag,_0
+ ret
- ;Convert from 128-byte LBA blocks to 512-byte LBA blocks
- lsr adrh
- ror adrl
- lsr adrh
- ror adrl
- ;Write the sector back.
- rcall mmcWriteSect
- ;All done :)
- ret
-
+;***************************************************************************
; ----------------- MMC/SD routines ------------------
rcall mmcWaitResp
;Read sector to AVR RAM
- ldi zl,low(sectbuff)
- ldi zh,high(sectbuff)
+ ldi zl,low(hostbuf)
+ ldi zh,high(hostbuf)
mmcreadloop:
rcall mmcByteNoSend
st z+,temp
- cpi zl,low(sectbuff+512)
+ cpi zl,low(hostbuf+512)
brne mmcreadloop
- cpi zh,high(sectbuff+512)
+ cpi zh,high(hostbuf+512)
brne mmcreadloop
;CRC
rcall mmcByte
;Write sector from AVR RAM
- ldi zl,low(sectbuff)
- ldi zh,high(sectbuff)
+ ldi zl,low(hostbuf)
+ ldi zh,high(hostbuf)
mmcwriteloop:
ld temp,z+
rcall mmcByte
- cpi zl,low(sectbuff+512)
+ cpi zl,low(hostbuf+512)
brne mmcwriteloop
- cpi zh,high(sectbuff+512)
+ cpi zh,high(hostbuf+512)
brne mmcwriteloop
;CRC
resetwait:
rjmp resetwait
-
; ------------------ DRAM routines -------------
; DRAM_SETADDR val, low_and_mask, low_or_mask, high_and_mask, high_or_mask
out P_AH,temp
.endm
-
;Loads the byte on address adrh:adrl into temp.
;must not alter adrh:adrl
andi temp,RAM_DQ_MASK & ~(1<<ram_w)
ori temp,(1<<ram_cas)
out PORTC,temp
-
DRAM_SETADDR adrh, ~0,(1<<ram_ras), ~(1<<ram_a8),(1<<ram_oe)
cbi P_RAS,ram_ras
DRAM_SETADDR adrl, ~(1<<ram_ras),0, ~((1<<ram_a8)),(1<<ram_oe)
;
timer_print:
- push adrh
- push adrl
- push oph
- push opl
+ push yh
+ push yl
ldi zl,low(timer_ms)
ldi zh,high(timer_ms)
; put ms on stack (16 bit)
cli
- ldd adrl,z+timerofs
+ ldd yl,z+timerofs
ld temp2,z+
- sub adrl,temp2
- ldd adrh,z+timerofs
+ sub yl,temp2
+ ldd yh,z+timerofs
ld temp2,z+
- sbc adrh,temp2
+ sbc yh,temp2
brsh tp_s
- subi adrl,low(-1000)
- sbci adrh,high(-1000)
+ subi yl,low(-1000)
+ sbci yh,high(-1000)
sec
tp_s:
- push adrh
- push adrl
+ push yh
+ push yl
-;
-
ldd temp,z+timerofs
- ld adrl,z+
- sbc temp,adrl
+ ld yl,z+
+ sbc temp,yl
ldd temp2,z+timerofs
- ld adrh,z+
- sbc temp2,adrh
+ ld yh,z+
+ sbc temp2,yh
- ldd opl,z+timerofs
- ld adrl,z+
- sbc opl,adrl
+ ldd temp3,z+timerofs
+ ld yl,z+
+ sbc temp3,yl
sei
- ldd oph,z+timerofs
- ld adrh,z+
- sbc oph,adrh
+ 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
- ldi opl,0
- ldi oph,0
+ .db ".",0
pop temp
pop temp2
+ ldi temp3,0
+ ldi temp4,0
rcall print_ultoa
rcall printstr
.db "s.",0,0
- pop opl
- pop oph
- pop adrl
- pop adrh
+ pop yl
+ pop yh
ret
uptime_print:
- push oph
- push opl
ldi zl,low(cnt_1ms)
ldi zh,high(cnt_1ms)
ld temp,z+
ld temp2,z+
- ld opl,z+
+ ld temp3,z+
sei
- ld oph,z+
+ ld temp4,z+
rcall printstr
.db 13,"Uptime: ",0
rcall printstr
.db ",",0
- ldi opl,0
- ldi oph,0
+ ldi temp3,0
+ ldi temp4,0
pop temp2
pop temp
rcall print_ultoa
rcall printstr
.db "s.",0,0
- pop opl
- pop oph
ret
; --------------- Debugging stuff ---------------
;Print a unsigned lonng value to the uart
-; oph:opl:temp2:temp = value
+; temp4:temp3:temp2:temp = value
print_ultoa:
- push adrh
- push adrl
- push insdech
+ push yh
+ push yl
+ push z_flags
- clr adrl ;adrl = stack level
+ clr yl ;yl = stack level
-ultoa1: ldi insdech, 32 ;adrh = oph:temp % 10
- clr adrh ;oph:temp /= 10
+ultoa1: ldi z_flags, 32 ;yh = temp4:temp % 10
+ clr yh ;temp4:temp /= 10
ultoa2: lsl temp
rol temp2
- rol opl
- rol oph
- rol adrh
- cpi adrh,10
+ rol temp3
+ rol temp4
+ rol yh
+ cpi yh,10
brcs ultoa3
- subi adrh,10
+ subi yh,10
inc temp
-ultoa3: dec insdech
+ultoa3: dec z_flags
brne ultoa2
- cpi adrh, 10 ;adrh is a numeral digit '0'-'9'
- subi adrh, -'0'
- push adrh ;Stack it
- inc adrl
- cp temp,_0 ;Repeat until oph:temp gets zero
+ 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 opl,_0
- cpc oph,_0
+ cpc temp3,_0
+ cpc temp4,_0
brne ultoa1
ldi temp, '0'
-ultoa5: cpi adrl,3 ; at least 3 digits (ms)
+ultoa5: cpi yl,3 ; at least 3 digits (ms)
brge ultoa6
push temp
- inc adrl
+ inc yl
rjmp ultoa5
ultoa6: pop temp ;Flush stacked digits
rcall uartputc
- dec adrl
+ dec yl
brne ultoa6
- pop insdech
- pop adrl
- pop adrh
+ pop z_flags
+ pop yl
+ pop yh
ret
rcall printhexn
ret
-;Prints the zero-terminated string following the call statement. WARNING: Destroys temp.
+;Prints the zero-terminated string following the call statement.
+
printstr:
- pop zh
- pop zl
- push temp
+ push zh
+ push zl
+ push r29
+ push r28
+ push temp
+ in r29,sph
+ in r28,spl
+ ldd zl,y+7
+ ldd zh,y+6
lsl zl
rol zh
-
printstr_loop:
lpm temp,z+
cpi temp,0
lsr zh
ror zl
- pop temp
- push zl
- push zh
+ std y+7,zl
+ std y+6,zh
+ pop temp
+ pop r28
+ pop r29
+ pop zl
+ pop zh
ret
-
; --------------- AVR HW <-> Z80 periph stuff ------------------
.equ memReadByte = dram_read
ret
do_fetch_bc:
- mov opl,z_c
- mov oph,z_b
+ movw opl,z_c
ret
do_fetch_de:
- mov opl,z_e
- mov oph,z_d
+ movw opl,z_e
ret
do_fetch_hl:
- mov opl,z_l
- mov oph,z_h
+ movw opl,z_l
ret
do_fetch_sp:
ret
do_fetch_mbc:
- mov adrh,z_b
- mov adrl,z_c
+ movw adrl,z_c
rcall memReadByte
mov opl,temp
ret
do_fetch_mde:
- mov adrh,z_d
- mov adrl,z_e
+ movw adrl,z_e
rcall memReadByte
mov opl,temp
ret
do_fetch_mhl:
- mov adrh,z_h
- mov adrl,z_l
+ movw adrl,z_l
rcall memReadByte
mov opl,temp
ret
#else
rcall memReadByte
mov opl,temp
-
adiw adrl,1
rcall memReadByte
mov oph,temp
ret
do_store_mbc:
- mov adrh,z_b
- mov adrl,z_c
+ movw adrl,z_c
mov temp,opl
rcall memWriteByte
ret
do_store_mde:
- mov adrh,z_d
- mov adrl,z_e
+ movw adrl,z_e
mov temp,opl
rcall memWriteByte
ret
do_store_mhl:
- mov adrh,z_h
- mov adrl,z_l
+ movw adrl,z_l
mov temp,opl
rcall memWriteByte
ret
mov zl,@2
lpm @0,z
.endm
-
.macro do_z80_flags_HP
#if EM_Z80
bmov z_flags, ZFL_P, temp, AVR_V
;
;
do_op_inc16:
- adiw opl,1
+ subi opl,low(-1)
+ sbci oph,high(-1)
ret
;----------------------------------------------------------------
do_op_sthl: ;store hl to mem loc in opl:h
movw adrl,opl
#if DRAM_WORD_ACCESS
- mov temp,z_l
- mov temp2,z_h
+ movw temp,z_l
rcall memWriteWord
#else
mov temp,z_l
add z_spl,temp
adc z_sph,_0
+
.if STACK_DBG
rcall printstr
.db "Stack pop: val ",0
do_op_ifnz:
sbrs z_flags, ZFL_Z
ret
- ldi insdech, 0
- ldi insdecl, 0
+ clr insdech
+ clr insdecl
ret
;----------------------------------------------------------------
do_op_ifz:
sbrc z_flags, ZFL_Z
ret
- ldi insdech, 0
- ldi insdecl, 0
+ clr insdech
+ clr insdecl
ret
;----------------------------------------------------------------
do_op_ifnc:
sbrs z_flags, ZFL_C
ret
- ldi insdech, 0
- ldi insdecl, 0
+ clr insdech
+ clr insdecl
ret
;----------------------------------------------------------------
do_op_ifc:
sbrc z_flags, ZFL_C
ret
- ldi insdech, 0
- ldi insdecl, 0
+ clr insdech
+ clr insdecl
ret
;----------------------------------------------------------------
do_op_ifpo:
sbrs z_flags, ZFL_P
ret
- ldi insdech, 0
- ldi insdecl, 0
+ clr insdech
+ clr insdecl
ret
;----------------------------------------------------------------
do_op_ifpe:
sbrc z_flags, ZFL_P
ret
- ldi insdech, 0
- ldi insdecl, 0
+ clr insdech
+ clr insdecl
ret
;----------------------------------------------------------------
do_op_ifp: ;sign positive, aka s=0
sbrs z_flags, ZFL_S
ret
- ldi insdech,0
- ldi insdecl,0
+ clr insdech
+ clr insdecl
ret
;----------------------------------------------------------------
do_op_ifm: ;sign negative, aka s=1
sbrc z_flags, ZFL_S
ret
- ldi insdech, 0
- ldi insdecl, 0
+ clr insdech
+ clr insdecl
ret
;----------------------------------------------------------------
; The table is made of 256 words. These 16-bit words consist of
; the fetch operation (bit 0-4), the processing operation (bit 10-16) and the store
; operation (bit 5-9).
-
.org (PC+255) & 0xff00
inst_table:
.dw (FETCH_NOP | OP_NOP | STORE_NOP) ; 00 NOP
.dw (FETCH_RST | OP_NOP | STORE_CALL) ; FF RST 38H
; vim:set ts=8 noet nowrap
-