; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
-
+;.nolist
#if defined atmega8
.include "m8def.inc"
-
-#elif defined atmega48
- .include "m48def.inc"
+#elif defined atmega168
+ .include "m168def.inc"
#else /* default */
.include "m88def.inc"
;FUSE_H=0xDF
;FUSE_L=0xF7
#endif
+.list
+.listmac
+
+#ifndef DRAM_DQ_ORDER /* If this is set to 1, the portbits */
+ #define DRAM_DQ_ORDER 0 /* for DRAM D1 and WE are swapped. */
+#endif
+
#ifndef F_CPU
#define F_CPU 20000000 /* system clock in Hz; defaults to 20MHz */
#define BAUD 38400 /* console baud rate */
#endif
-;
-.equ UBRR_VAL = ((F_CPU+BAUD*8)/(BAUD*16)-1) ; clever rounding
-#define REFR_RATE 64000 /* dram refresh rate. most drams need 1/15.6µs */
+#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 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
.equ refr_vect = OC2Aaddr
#endif
+#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 = 0
-.equ BOOTWAIT = 0
+.equ MEMTEST = 1
+.equ BOOTWAIT = 1
.equ PORT_DEBUG = 0
.equ DISK_DEBUG = 0
.equ MEMFILL_CB = 1
.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 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_d1 = 0
-.equ ram_w = 1
-.equ ram_d2 = 2
-.equ ram_d4 = 3
-.equ ram_d3 = 4
+#if DRAM_DQ_ORDER == 1
+.equ ram_d1 = 1
+.equ ram_w = 4
+#else /* original */
+.equ ram_d1 = 4
+.equ ram_w = 1
+#endif
+.equ ram_d0 = 0
+.equ ram_d2 = 2
+.equ ram_d3 = 3
.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_C = 0
;Register definitions
-.def z_a = r2
+.def _tmp = r0 ; 0
+.def _0 = r1
+;.def z_a = r2
.def z_b = r3
.def z_c = r4
.def z_d = r5
.def z_e = r6
.def z_l = r7
.def z_h = r8
-.def z_spl = r9
-.def z_sph = r10
-
-.def dsk_trk = r11
-.def dsk_sec = r12
-.def dsk_dmah = r13
-.def dsk_dmal = r14
-
-.def parityb = r15
-
-.def temp = R16 ;The temp register
-.def temp2 = R17 ;Second temp register
-.def trace = r18
-.def opl = r19
-.def oph = r20
-.def adrl = r21
-.def adrh = r22
-.def insdecl = r23
-.def z_pcl = r24
-.def z_pch = r25
-.def insdech = r26
-.def z_flags = r27
-
-
-;SRAM
-.dseg
+;.def z_spl = r9
+;.def z_sph = r10
+
+.def z_a = r11
+
+
+.def _wl = r12
+.def _wh = 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 trace = r21 ;
+.def insdecl = r22 ;
+.def insdech = r23 ;
+.def z_pcl = r24 ;
+.def z_pch = r25 ;
+.undef xl ;r26
+.undef xh ;r27
+.undef yl ;r28
+.undef yh ;r29
+.def opl = r26 ;
+.def oph = r27 ;
+.def adrl = r28 ;
+.def adrh = r29 ;
+; zl ;r30 ;
+; zh ;r31 ;
+
+
+; 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
+
+
+
+ ;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:
.org 0
rjmp start ; reset vector
.org refr_vect
- rjmp refrint ; tim2cmpa
-
+ 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
+
.org INT_VECTORS_SIZE
+
start:
ldi temp,low(RAMEND) ; top of memory
out SPL,temp ; init stack pointer
; - Kill wdt
wdr
#if defined __ATmega8__
- ldi temp,0
- out MCUCSR,temp
+ out MCUCSR,_0
ldi temp,(1<<WDCE) | (1<<WDE)
out WDTCSR,temp
ldi temp,(1<<WDCE)
out WDTCSR,temp
+ ldi temp,(1<<PUD) ;disable pullups
+ out SFIOR,temp
#else
- ldi temp,0
- out MCUSR,temp
+ out MCUSR,_0
ldi temp,(1<<WDCE) | (1<<WDE)
sts WDTCSR,temp
ldi temp,(1<<WDCE)
sts WDTCSR,temp
+ ldi temp,(1<<PUD) ;disable pullups
+ out MCUCR,temp
#endif
; - Setup Ports
- ldi temp,$3F
+ ldi temp,PB_OUTPUT_MASK
out DDRB,temp
- ldi temp,$FE
+ ldi temp,PD_OUTPUT_MASK
out DDRD,temp
- ldi temp,$22
+ ldi temp,PC_OUTPUT_MASK
out DDRC,temp
- sbi PORTC,ram_w
- sbi PORTC,ram_cas
- sbi PORTB,ram_ras
- sbi PORTD,ram_oe
- sbi PORTD,mmc_cs
+ sbi P_W,ram_w
+ sbi P_CAS,ram_cas
+ sbi P_RAS,ram_ras
+ sbi P_OE,ram_oe
+ sbi P_MMC_CS,mmc_cs
; - Init serial port
+
+ sts rxcount,_0 ; reset receive buffer
+ sts rxidx_r,_0
+ sts rxidx_w,_0
+
+
#if defined __ATmega8__
- ldi temp, (1<<TXEN) | (1<<RXEN)
+ ldi temp, (1<<TXEN) | (1<<RXEN) | (1<<RXCIE)
out UCSRB,temp
ldi temp, (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0)
out UCSRC,temp
ldi temp, LOW(UBRR_VAL)
out UBRRL,temp
#else
- ldi temp, (1<<TXEN0) | (1<<RXEN0)
+ ldi temp, (1<<TXEN0) | (1<<RXEN0) | (1<<RXCIE0)
sts UCSR0B,temp
ldi temp, (1<<UCSZ01) | (1<<UCSZ00)
sts UCSR0C,temp
;Init timer2. Refresh-call should happen every (8ms/512)=312 cycles.
#ifdef __ATmega8__
- ldi temp,REFR_CNT
+ ldi temp,REFR_CNT*2 ; 2 cycles per int
out OCR2,temp
ldi temp,(1<<WGM21) | REFR_CS ;CTC, clk/REFR_PRE
out TCCR2,temp
ldi temp, (1<<OCIE2)
out TIMSK,temp
#else
- ldi temp,REFR_CNT ;=312 cycles
+ ldi temp,REFR_CNT ;=312 cycles
sts OCR2A,temp
ldi temp, (1<<WGM21)
sts TCCR2A,temp
ldi temp,(1<<OCIE2A)
sts TIMSK2,temp
#endif
+
+
+; Init clock/timer system
+
+ ldi zl,low(timer_base)
+ ldi zh,high(timer_base)
+ ldi temp2,timer_size
+ti_loop:
+ st z+,_0
+ dec temp2
+ brne ti_loop
+
+; Init timer 1 as 1 ms system clock tick.
+
+#ifdef __ATmega8__
+ ldi temp,high(F_CPU/1000)
+ out OCR1AH,temp
+ ldi temp,low(F_CPU/1000)
+ out OCR1AL,temp
+ ldi temp,(1<<WGM12) | (1<<CS10) ;CTC, clk/1
+ out TCCR1B,temp
+ in temp,TIMSK
+ ori temp,(1<<OCIE1A)
+ out TIMSK,temp
+#else
+ ldi temp,high(F_CPU/1000)
+ sts OCR1AH,temp
+ ldi temp,low(F_CPU/1000)
+ sts OCR1AL,temp
+ ldi temp,(1<<WGM12) | (1<<CS10) ;CTC, clk/1
+ sts TCCR1B,temp
+ lds temp,TIMSK1
+ ori temp,(1<<OCIE1A)
+ sts TIMSK1,temp
+#endif
sei
.if BOOTWAIT
- push temp
- ldi temp,0
-bootwait1:
- push temp
- ldi temp,0
-bootwait2:
- dec temp
- brne bootwait2
- pop temp
- dec temp
- brne bootwait1
+ ldi temp,10
+ rcall delay_ms
.endif
.if MEMTEST
rcall printstr
- .db "Testing RAM...",13,0
+ .db "Testing RAM: fill...",0,0
;Fill RAM
ldi adrl,0
mov temp,adrh
eor temp,adrl
rcall memwritebyte
- ldi temp,1
- ldi temp2,0
- add adrl,temp
- adc adrh,temp2
+ adiw adrl,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 adrl,0
ldi temp,13
rcall uartPutc
ramtestrok:
- ldi temp,1
- ldi temp2,0
- add adrl,temp
- adc adrh,temp2
+ adiw adrl,1
brcc ramtestr
.endif
ramfillw:
ldi temp,0xcb
rcall memwritebyte
- ldi temp,1
- ldi temp2,0
- add adrl,temp
- adc adrh,temp2
+ adiw adrl,1
brcc ramfillw
.endif
rcall memWriteByte
pop zl
pop zh
- ldi temp,1
- ldi temp2,0
- add adrl,temp
- adc adrh,temp2
+ adiw adrl,1
cpi zl,low(sectbuff+128)
brne iplwriteloop
cpi zh,high(sectbuff+128)
.endif
; *** Stage 1: Fetch next opcode
- mov adrl,z_pcl
- mov adrh,z_pch
+ movw adrl,z_pcl
rcall memReadByte
adiw z_pcl,1
.endif
; *** Stage 2: Decode it using the ins_table.
- ldi temp2,0
- ldi zl,low(inst_table*2)
ldi zh,high(inst_table*2)
+ mov zl,temp
add zl,temp
- adc zh,temp2
- add zl,temp
- adc zh,temp2
+ adc zh,_0
lpm insdecl,Z+
lpm insdech,Z
; *** Stage 3: Fetch operand. Use the fetch jumptable for this.
mov temp,insdecl
andi temp,0x1F
- cpi temp,0
breq nofetch
- ldi temp2,0
- lsl temp
- ldi zl,low(fetchjumps*2)
- ldi zh,high(fetchjumps*2)
+ ldi zl,low(fetchjumps)
+ ldi zh,high(fetchjumps)
add zl,temp
- adc zh,temp2
-
- lpm temp,Z+
- lpm temp2,Z
- mov zl,temp
- mov zh,temp2
+ adc zh,_0
icall
.if INS_DEBUG
; *** Stage 4: Execute operation :) Use the op jumptable for this.
mov temp,insdech
andi temp,0xFC
- lsr temp
- cpi temp,0
breq nooper
- ldi zl,low(opjumps*2)
- ldi zh,high(opjumps*2)
- ldi temp2,0
+ lsr temp
+ lsr temp
+ ldi zl,low(opjumps)
+ ldi zh,high(opjumps)
add zl,temp
- adc zh,temp2
- lpm temp,Z+
- lpm temp2,Z
- mov zl,temp
- mov zh,temp2
+ adc zh,_0
icall
.if INS_DEBUG
andi temp,0x0E
andi insdech,0x30
or temp,insdech
- cpi temp,0
breq nostore
- ldi zl,low(storejumps*2)
- ldi zh,high(storejumps*2)
- ldi temp2,0
+ lsr temp
+ ldi zl,low(storejumps)
+ ldi zh,high(storejumps)
add zl,temp
- adc zh,temp2
- lpm temp,Z+
- lpm temp2,Z
- mov zl,temp
- mov zh,temp2
+ adc zh,_0
icall
.if INS_DEBUG
breq conStatus
cpi temp2,1
breq conInp
+
+ 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.
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
conStatus:
- ldi temp,0
-#if defined __ATmega8__
- sbic UCSRA,RXC
-#else
- lds temp2,UCSR0A
- sbrc temp2,RXC0
-#endif
+
+ lds temp,rxcount
+ tst temp
+ breq PC+2
ldi temp,0xff
ret
rcall uartputc
ret
+
+
dskTrackSel:
- mov dsk_trk,temp
+ sts dsk_trk,temp
ret
dskSecSel:
- mov dsk_sec,temp
+ sts dsk_sec,temp
ret
dskDmal:
- mov dsk_dmal,temp
+ sts dsk_dmal,temp
ret
dskDmah:
- mov dsk_dmah,temp
+ sts dsk_dmah,temp
ret
dskDoIt:
push temp
rcall printstr
.db "Disk read: track ",0
- mov temp,dsk_trk
+ lds temp,dsk_trk
rcall printhex
rcall printstr
.db " sector ",0
- mov temp,dsk_sec
+ lds temp,dsk_sec
rcall printhex
rcall printstr
.db " dma-addr ",0
- mov temp,dsk_dmah
+ lds temp,dsk_dmah
rcall printhex
- mov temp,dsk_dmal
+ lds temp,dsk_dmal
rcall printhex
rcall printstr
.db ".",13,0
;First, convert track/sector to an LBA address (in 128byte blocks)
push temp
- mov adrl,dsk_sec
+ lds adrl,dsk_sec
ldi adrh,0
- mov temp2,dsk_trk
+ lds temp2,dsk_trk
+ ldi temp,26
dskXlateLoop:
cpi temp2,0
breq dskXlateLoopEnd
- ldi temp,26
add adrl,temp
- ldi temp,0
- adc adrh,temp
+ adc adrh,_0
dec temp2
rjmp dskXlateLoop
dskXlateLoopEnd:
sbrc adrl,1
inc zh
- mov adrh,dsk_dmah
- mov adrl,dsk_dmal
+ lds adrh,dsk_dmah
+ lds adrl,dsk_dmal
ldi temp2,128
dskDoItReadMemLoop:
rcall memWriteByte
pop zl
pop zh
- ldi temp,1
- ldi temp2,0
- add adrl,temp
- adc adrh,temp2
+ adiw adrl,1
pop temp2
dec temp2
brne dskDoItReadMemLoop
push temp
rcall printstr
.db "Disk write: track ",0
- mov temp,dsk_trk
+ lds temp,dsk_trk
rcall printhex
rcall printstr
.db " sector ",0
- mov temp,dsk_sec
+ lds temp,dsk_sec
rcall printhex
rcall printstr
.db " dma-addr ",0
- mov temp,dsk_dmah
+ lds temp,dsk_dmah
rcall printhex
- mov temp,dsk_dmal
+ lds temp,dsk_dmal
rcall printhex
rcall printstr
.db ".",13,0
adc zh,temp2
sbrc adrl,1
inc zh
- mov adrh,dsk_dmah
- mov adrl,dsk_dmal
+ lds adrh,dsk_dmah
+ lds adrl,dsk_dmal
ldi temp2,128
dskDoItWriteMemLoop:
push temp2
pop zl
pop zh
st z+,temp
- ldi temp,1
- ldi temp2,0
- add adrl,temp
- adc adrh,temp2
+ adiw adrl,1
pop temp2
dec temp2
;All done :)
ret
+
; ----------------- MMC/SD routines ------------------
out SPCR,temp
;Init start: send 80 clocks with cs disabled
- sbi PORTD,mmc_cs
+ sbi P_MMC_CS,mmc_cs
- ldi temp2,20
+; ldi temp2,20
+ ldi temp2,10 ; exactly 80 clocks
mmcInitLoop:
mov temp,temp2
rcall mmcByte
dec temp2
brne mmcInitLoop
- cbi PORTD,mmc_cs
+ cbi P_MMC_CS,mmc_cs
rcall mmcByteNoSend
rcall mmcByteNoSend
rcall mmcByteNoSend
rcall mmcByteNoSend
rcall mmcByteNoSend
rcall mmcByteNoSend
- sbi PORTD,mmc_cs
+ sbi P_MMC_CS,mmc_cs
rcall mmcByteNoSend
rcall mmcByteNoSend
rcall mmcByteNoSend
rcall mmcByteNoSend
;Send init command
- cbi PORTD,mmc_cs
+ cbi P_MMC_CS,mmc_cs
ldi temp,0xff ;dummy
rcall mmcByte
ldi temp,0xff ;dummy
ldi temp,0xff ;return byte
rcall mmcByte
- ldi temp2,0
- rcall mmcWaitResp
+ ldi temp2,0 ;Error Code 0
+ rcall mmcWaitResp ;Test on CMD0 is OK
- sbi PORTD,mmc_cs
+ sbi P_MMC_CS,mmc_cs ;disable /CS
rcall mmcByteNoSend
;Read OCR till card is ready
- ldi temp2,150
+ ldi temp2,20 ;repeat counter
mmcInitOcrLoop:
push temp2
- cbi PORTD,mmc_cs
+ cbi P_MMC_CS,mmc_cs ;enable /CS
ldi temp,0xff ;dummy
rcall mmcByte
ldi temp,0x41 ;cmd
rcall mmcByte
ldi temp,0 ;pyl
rcall mmcByte
- ldi temp,0x95 ;crc
+; ldi temp,0x95 ;crc
+ ldi temp,0x01 ;crc
rcall mmcByte
rcall mmcByteNoSend
ldi temp2,1
- rcall mmcWaitResp
+ rcall mmcWaitResp ;wait until mmc-card send a byte <> 0xFF
+ ;the first answer must be 0x01 (Idle-Mode)
cpi temp,0
- breq mmcInitOcrLoopDone
+ breq mmcInitOcrLoopDone ;second answer is 0x00 (Idle-Mode leave) CMD1 is OK
- sbi PORTD,mmc_cs
- rcall mmcByteNoSend
+ sbi P_MMC_CS,mmc_cs ;disable /CS
+
+; rcall mmcByteNoSend ;unnecessary
+
+ ldi temp,10
+ rcall delay_ms
pop temp2
dec temp2
cpi temp2,0
- brne mmcInitOcrLoop
+ brne mmcInitOcrLoop ;repeat
- ldi temp,4
+ ldi temp2,4
rjmp mmcWaitErr
mmcInitOcrLoopDone:
pop temp2
- sbi PORTD,mmc_cs
+ sbi P_MMC_CS,mmc_cs ;disable /CS
rcall mmcByteNoSend
- ldi temp,0
- out SPCR,temp
+ out SPCR,_0
ret
ldi temp,0x50
out SPCR,temp
- cbi PORTD,mmc_cs
+ cbi P_MMC_CS,mmc_cs
rcall mmcByteNoSend
ldi temp,0x51 ;cmd (read sector)
rcall mmcByte
rcall mmcByteNoSend
rcall mmcByteNoSend
- sbi PORTD,mmc_cs
+ sbi P_MMC_CS,mmc_cs
rcall mmcByteNoSend
- ldi temp,0
- out SPCR,temp
+ out SPCR,_0
ret
ldi temp,0x50
out SPCR,temp
- cbi PORTD,mmc_cs
+ cbi P_MMC_CS,mmc_cs
rcall mmcByteNoSend
ldi temp,0x58 ;cmd (write sector)
cpi temp,0xff
brne mmcwaitwritten
- sbi PORTD,mmc_cs
+ sbi P_MMC_CS,mmc_cs
rcall mmcByteNoSend
- ldi temp,0
- out SPCR,temp
+ out SPCR,_0
ret
; ------------------ DRAM routines -------------
+; TODO:
+
+#if DRAM_DQ_ORDER == 1
+ #define CLASSIC_DRAM 0
+#else
+ #define CLASSIC_DRAM 1 /* Change manualy, if you want new hw w/ old sw */
+#endif
+
+
+#if DRAM_DQ_ORDER == 0
+ #if CLASSIC_DRAM == 1
+ #error "Old harware can not work with new software!"
+ #endif
+#endif
+
+; ****************************************************************************
+
+#if CLASSIC_DRAM
+
+; ********************** DRAM routines from Sprite_tm ************************
+
;Sends the address in zh:zl to the ram
dram_setaddr:
push temp
- in temp,PORTD
+ in temp,portd
andi temp,0x17
- out PORTD,temp
- in temp,PORTB
+ out portd,temp
+ in temp,portb
andi temp,0xE0
- out PORTB,temp
+ out portb,temp
sbrc zl,0
- sbi PORTB,ram_a0
+ sbi portb,ram_a0
sbrc zl,1
- sbi PORTB,ram_a1
+ sbi portb,ram_a1
sbrc zl,2
- sbi PORTB,ram_a2
+ sbi portb,ram_a2
sbrc zl,3
- sbi PORTB,ram_a3
+ sbi portb,ram_a3
sbrc zl,4
- sbi PORTB,ram_a4
+ sbi portb,ram_a4
sbrc zl,5
- sbi PORTD,ram_a5
+ sbi portd,ram_a5
sbrc zl,6
- sbi PORTD,ram_a6
+ sbi portd,ram_a6
sbrc zl,7
- sbi PORTD,ram_a7
+ sbi portd,ram_a7
sbrc zh,0
- sbi PORTD,ram_a8
+ sbi portd,ram_a8
pop temp
ret
dram_getnibble:
andi temp,0xf0
- sbic pinc,ram_d1
+ sbic pinc,ram_d0
ori temp,0x1
- sbic pinc,ram_d2
+ sbic pinc,ram_d1
ori temp,0x2
- sbic pinc,ram_d3
+ sbic pinc,ram_d2
ori temp,0x4
- sbic pinc,ram_d4
+ sbic pinc,ram_d3
ori temp,0x8
ret
dram_sendnibble:
push temp2
- in temp2,PORTC
- andi temp2,0xE2
+ in temp2,portc
+ andi temp2,~RAM_DQ_MASK
sbrc temp,0
- ori temp2,(1<<ram_d1)
+ ori temp2,(1<<ram_d0)
sbrc temp,1
- ori temp2,(1<<ram_d2)
+ ori temp2,(1<<ram_d1)
sbrc temp,2
- ori temp2,(1<<ram_d3)
+ ori temp2,(1<<ram_d2)
sbrc temp,3
- ori temp2,(1<<ram_d4)
+ ori temp2,(1<<ram_d3)
- out PORTC,temp2
+ out portc,temp2
pop temp2
ret
rol zh
;z=addr[15-7]
rcall dram_setaddr
- cbi PORTB,ram_ras
+ cbi portb,ram_ras
ldi zh,0
mov zl,adrl
andi zl,0x7F
rcall dram_setaddr
nop
- cbi PORTC,ram_cas
+ cbi portc,ram_cas
nop
nop
- cbi PORTD,ram_oe
+ cbi portd,ram_oe
nop
rcall dram_getnibble
- sbi PORTD,ram_oe
+ sbi portd,ram_oe
swap temp
- sbi PORTC,ram_cas
+ sbi portc,ram_cas
ldi zh,0
mov zl,adrl
ori zl,0x80
rcall dram_setaddr
nop
- cbi PORTC,ram_cas
+ cbi portc,ram_cas
nop
- cbi PORTD,ram_oe
+ cbi portd,ram_oe
nop
nop
rcall dram_getnibble
- sbi PORTD,ram_oe
- sbi PORTC,ram_cas
- sbi PORTB,ram_ras
+ sbi portd,ram_oe
+ sbi portc,ram_cas
+ sbi portb,ram_ras
sei
ret
cli
in temp2,ddrc
- ori temp2,0x1d
+ ori temp2,RAM_DQ_MASK
out ddrc,temp2
rcall dram_sendnibble
rcall dram_setaddr
nop
nop
- cbi PORTB,ram_ras
+ cbi portb,ram_ras
ldi zh,0
mov zl,adrl
rcall dram_setaddr
nop
nop
- cbi PORTC,ram_cas
+ cbi portc,ram_cas
nop
nop
- cbi PORTC,ram_w
+ cbi portc,ram_w
nop
nop
nop
- sbi PORTC,ram_w
- sbi PORTC,ram_cas
+ sbi portc,ram_w
+ sbi portc,ram_cas
ldi zh,0
rcall dram_setaddr
swap temp
rcall dram_sendnibble
- cbi PORTC,ram_cas
+ cbi portc,ram_cas
nop
nop
- cbi PORTC,ram_w
+ cbi portc,ram_w
nop
nop
- sbi PORTC,ram_w
+ sbi portc,ram_w
nop
nop
- sbi PORTC,ram_cas
- sbi PORTB,ram_ras
+ sbi portc,ram_cas
+ sbi portb,ram_ras
in temp,ddrc
- andi temp,0xE2
+ andi temp,~RAM_DQ_MASK
out ddrc,temp
- in temp,PORTC
- andi temp,0xE2
- out PORTC,temp
+ in temp,portc
+ andi temp,~RAM_DQ_MASK
+ out portc,temp
sei
ret
+#endif /* CLASSIC_DRAM == 1 */
+
+; ****************************************************************************
+
+#if ! CLASSIC_DRAM
+
+; ***************************** New DRAM routines ****************************
+
+;todo: see below
+.macro DRAM_SETADDR
+#if 1
+ in temp,P_AL
+ andi temp,~RAM_AL_MASK
+ sbrc @0,0
+ ori temp,(1<<ram_a0)
+ sbrc @0,1
+ ori temp,(1<<ram_a1)
+ sbrc @0,2
+ ori temp,(1<<ram_a2)
+ sbrc @0,3
+ ori temp,(1<<ram_a3)
+ sbrc @0,4
+ ori temp,(1<<ram_a4)
+ out P_AL,temp
+#else
+ out PORTB,@0
+#endif
-refrint:
+ in temp,P_AH
+ andi temp,~RAM_AH_MASK
+ sbrc @0,5
+ ori temp,(1<<ram_a5)
+ sbrc @0,6
+ ori temp,(1<<ram_a6)
+ sbrc @0,7
+ ori temp,(1<<ram_a7)
+ out P_AH,temp
+.endm
+ ret
+
+
+;Loads the byte on address adrh:adrl into temp.
+;must not alter adrh:adrl
+
+dram_read:
+ cli
+ cbi P_A8,ram_a8
+ DRAM_SETADDR adrh
+ cbi P_RAS,ram_ras
+
+ DRAM_SETADDR adrl
+ cbi P_CAS,ram_cas
+ cbi P_OE,ram_oe
nop
-; nop
-; nop
- cbi PORTC,ram_cas
-; nop
-; nop
-; nop
-; nop
- cbi PORTB,ram_ras
nop
-; nop
-; nop
-; nop
+ in temp,P_DQ-2 ; PIN
+ sbi P_CAS,ram_cas
+
+ sbi P_A8,ram_a8
+ cbi P_CAS,ram_cas
+ andi temp,0x0f
+ swap temp
+ in temp2,P_DQ-2 ; PIN
+ andi temp2,0x0f
+ or temp,temp2
+ swap temp
+
+ sbi P_OE,ram_oe
+ sbi P_CAS,ram_cas
+ sbi P_RAS,ram_ras
+ sei
+ ret
+
+
+;Writes the byte in temp to adrh:adrl
+;must not alter adrh:adrl
+
+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
+
+ cbi PORTD,ram_a8
+ DRAM_SETADDR adrh
+ cbi P_RAS,ram_ras
+ DRAM_SETADDR adrl
+ cbi PORTC,ram_cas
sbi PORTC,ram_cas
-; nop
-; nop
-; nop
-; nop
- sbi PORTB,ram_ras
-; nop
-; nop
-; nop
-; nop
-; nop
+
+ 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 /* CLASSIC_DRAM == 0 */
+
+; ****************************************************************************
+
+; refresh interupt; exec 2 cbr cycles
+refrint:
+ ;4 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
+; 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 10ms ---------------
+ .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
+
+ sts cnt_1ms,_0
+ sts cnt_1ms+1,_0
+
+ 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 adrh
+ push adrl
+ push oph
+ push opl
+ ldi zl,low(timer_ms)
+ ldi zh,high(timer_ms)
+
+; put ms on stack (16 bit)
+
+ cli
+ ldd adrl,z+timerofs
+ ld temp2,z+
+ sub adrl,temp2
+ ldd adrh,z+timerofs
+ ld temp2,z+
+ sbc adrh,temp2
+ brsh tp_s
+
+ subi adrl,low(-1000)
+ sbci adrh,high(-1000)
+ sec
+tp_s:
+ push adrh
+ push adrl
+
+;
+
+ ldd temp,z+timerofs
+ ld adrl,z+
+ sbc temp,adrl
+
+ ldd temp2,z+timerofs
+ ld adrh,z+
+ sbc temp2,adrh
+
+ ldd opl,z+timerofs
+ ld adrl,z+
+ sbc opl,adrl
+
+ sei
+ ldd oph,z+timerofs
+ ld adrh,z+
+ sbc oph,adrh
+
+ rcall printstr
+ .db 13,"Timer running. Elapsed: ",0
+ rcall print_ultoa
+
+ rcall printstr
+ .db ",",0
+ ldi opl,0
+ ldi oph,0
+ pop temp
+ pop temp2
+ rcall print_ultoa
+ rcall printstr
+ .db "s.",0,0
+
+ pop opl
+ pop oph
+ pop adrl
+ pop adrh
+ ret
+
+uptime_print:
+
+ push oph
+ push opl
+ 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 opl,z+
+ sei
+ ld oph,z+
+
+ rcall printstr
+ .db 13,"Uptime: ",0
+
+ rcall print_ultoa
+ rcall printstr
+ .db ",",0
+
+ ldi opl,0
+ ldi oph,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
+
+print_ultoa:
+ push adrh
+ push adrl
+ push insdech
+
+ clr adrl ;adrl = stack level
+
+ultoa1: ldi insdech, 32 ;adrh = oph:temp % 10
+ clr adrh ;oph:temp /= 10
+ultoa2: lsl temp
+ rol temp2
+ rol opl
+ rol oph
+ rol adrh
+ cpi adrh,10
+ brcs ultoa3
+ subi adrh,10
+ inc temp
+ultoa3: dec insdech
+ 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
+ cpc temp2,_0
+ cpc opl,_0
+ cpc oph,_0
+ brne ultoa1
+
+ ldi temp, '0'
+ultoa5: cpi adrl,3 ; at least 3 digits (ms)
+ brge ultoa6
+ push temp
+ inc adrl
+ rjmp ultoa5
+
+ultoa6: pop temp ;Flush stacked digits
+ rcall uartputc
+ dec adrl
+ brne ultoa6
+
+ pop insdech
+ pop adrl
+ pop adrh
+ ret
+
+
;Prints the lower nibble of temp in hex to the uart
printhexn:
push temp
.equ memReadByte = dram_read
.equ memWriteByte = dram_write
+#if DRAM_WORD_ACCESS
+.equ memReadWord = dram_read_w
+.equ memWriteWord = dram_write_w
+#endif
+; --------------------------------------------------------------
-
-;Fetches a char from the uart to temp. If none available, waits till one is.
-uartgetc:
-#if defined __ATmega8__
- sbis UCSRA,RXC
- rjmp uartgetc
- in temp,UDR
+ .dseg
+
+#define RXBUFMASK RXBUFSIZE-1
+
+rxcount:
+ .byte 1
+rxidx_w:
+ .byte 1
+rxidx_r:
+ .byte 1
+rxfifo:
+ .byte RXBUFSIZE
+ .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
+#ifdef __ATmega8__
+ in temp,UDR
#else
- lds temp,UCSR0A
- sbrs temp,RXC0
- rjmp uartgetc
- lds temp,UDR0
+ lds temp,UDR0
#endif
+ 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
+
+ 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
+
+
;Sends a char from temp to the uart.
uartputc:
#if defined __ATmega8__
;Jump table for fetch routines. Make sure to keep this in sync with the .equs!
fetchjumps:
-.dw do_fetch_nop
-.dw do_fetch_a
-.dw do_fetch_b
-.dw do_fetch_c
-.dw do_fetch_d
-.dw do_fetch_e
-.dw do_fetch_h
-.dw do_fetch_l
-.dw do_fetch_af
-.dw do_fetch_bc
-.dw do_fetch_de
-.dw do_fetch_hl
-.dw do_fetch_sp
-.dw do_fetch_mbc
-.dw do_fetch_mde
-.dw do_fetch_mhl
-.dw do_fetch_msp
-.dw do_fetch_dir8
-.dw do_fetch_dir16
-.dw do_fetch_rst
+ rjmp do_fetch_nop
+ rjmp do_fetch_a
+ rjmp do_fetch_b
+ rjmp do_fetch_c
+ rjmp do_fetch_d
+ rjmp do_fetch_e
+ rjmp do_fetch_h
+ rjmp do_fetch_l
+ rjmp do_fetch_af
+ rjmp do_fetch_bc
+ rjmp do_fetch_de
+ rjmp do_fetch_hl
+ rjmp do_fetch_sp
+ rjmp do_fetch_mbc
+ rjmp do_fetch_mde
+ rjmp do_fetch_mhl
+ rjmp do_fetch_msp
+ rjmp do_fetch_dir8
+ rjmp do_fetch_dir16
+ rjmp do_fetch_rst
do_fetch_nop:
ret
do_fetch_af:
mov opl,z_flags
mov oph,z_a
- rcall do_op_calcparity
- andi opl,~(1<<ZFL_P)
- sbrs temp2,0
- ori opl,(1<<ZFL_P)
ret
do_fetch_bc:
ret
do_fetch_sp:
- mov opl,z_spl
- mov oph,z_sph
+ movw opl,z_spl
ret
do_fetch_mbc:
ret
do_fetch_msp:
- mov adrh,z_sph
- mov adrl,z_spl
+ movw adrl,z_spl
+#if DRAM_WORD_ACCESS
+ rcall memReadWord
+ movw opl,temp
+#else
rcall memReadByte
mov opl,temp
- mov adrh,z_sph
- mov adrl,z_spl
- ldi temp,1
- ldi temp2,0
- add adrl,temp
- adc adrh,temp2
+ adiw adrl,1
rcall memReadByte
mov oph,temp
+#endif
ret
do_fetch_dir8:
- mov adrl,z_pcl
- mov adrh,z_pch
+ movw adrl,z_pcl
rcall memReadByte
adiw z_pcl,1
mov opl,temp
ret
do_fetch_dir16:
- mov adrl,z_pcl
- mov adrh,z_pch
+ movw adrl,z_pcl
+#if DRAM_WORD_ACCESS
+ rcall memReadWord
+ movw opl,temp
+#else
rcall memReadByte
mov opl,temp
- adiw z_pcl,1
- mov adrl,z_pcl
- mov adrh,z_pch
+ adiw adrl,1
rcall memReadByte
- adiw z_pcl,1
mov oph,temp
+#endif
+ adiw z_pcl,2
ret
do_fetch_rst:
- mov adrl,z_pcl
- mov adrh,z_pch
+ movw adrl,z_pcl
+ subi adrl,1
+ sbci adrh,0
rcall memReadByte
andi temp,0x38
ldi oph,0
;Jump table for store routines. Make sure to keep this in sync with the .equs!
storejumps:
-.dw do_store_nop
-.dw do_store_a
-.dw do_store_b
-.dw do_store_c
-.dw do_store_d
-.dw do_store_e
-.dw do_store_h
-.dw do_store_l
-.dw do_store_af
-.dw do_store_bc
-.dw do_store_de
-.dw do_store_hl
-.dw do_store_sp
-.dw do_store_pc
-.dw do_store_mbc
-.dw do_store_mde
-.dw do_store_mhl
-.dw do_store_msp
-.dw do_store_ret
-.dw do_store_call
-.dw do_store_am
+ rjmp do_store_nop
+ rjmp do_store_a
+ rjmp do_store_b
+ rjmp do_store_c
+ rjmp do_store_d
+ rjmp do_store_e
+ rjmp do_store_h
+ rjmp do_store_l
+ rjmp do_store_af
+ rjmp do_store_bc
+ rjmp do_store_de
+ rjmp do_store_hl
+ rjmp do_store_sp
+ rjmp do_store_pc
+ rjmp do_store_mbc
+ rjmp do_store_mde
+ rjmp do_store_mhl
+ rjmp do_store_msp
+ rjmp do_store_ret
+ rjmp do_store_call
+ rjmp do_store_am
do_store_nop:
do_store_af:
mov z_a,oph
mov z_flags,opl
- ldi temp,0
- mov parityb,temp
- sbrs z_flags,ZFL_P
- inc parityb
ret
do_store_bc:
ret
do_store_msp:
- mov adrh,z_sph
- mov adrl,z_spl
+ movw adrl,z_spl
+#if DRAM_WORD_ACCESS
+ movw temp,opl
+ rcall memWriteWord
+#else
mov temp,opl
rcall memWriteByte
-
- mov adrh,z_sph
- mov adrl,z_spl
- ldi temp,1
- ldi temp2,0
- add adrl,temp
- adc adrh,temp2
+ adiw adrl,1
mov temp,oph
rcall memWriteByte
-
+#endif
ret
do_store_sp:
- mov z_sph,oph
- mov z_spl,opl
+ movw z_spl,opl
ret
do_store_pc:
- mov z_pch,oph
- mov z_pcl,opl
+ movw z_pcl,opl
ret
do_store_ret:
rcall do_op_pop16
- mov z_pcl,opl
- mov z_pch,oph
+ movw z_pcl,opl
ret
do_store_call:
push opl
push oph
- mov opl,z_pcl
- mov oph,z_pch
+ movw opl,z_pcl
rcall do_op_push16
pop z_pch
pop z_pcl
ret
do_store_am:
- mov adrh,oph
- mov adrl,opl
+ movw adrl,opl
mov temp,z_a
rcall memWriteByte
ret
.equ OP_INV = (39<<10)
opjumps:
-.dw do_op_nop
-.dw do_op_inc
-.dw do_op_dec
-.dw do_op_inc16
-.dw do_op_dec16
-.dw do_op_rlc
-.dw do_op_rrc
-.dw do_op_rr
-.dw do_op_rl
-.dw do_op_adda
-.dw do_op_adca
-.dw do_op_subfa
-.dw do_op_sbcfa
-.dw do_op_anda
-.dw do_op_ora
-.dw do_op_xora
-.dw do_op_addhl
-.dw do_op_sthl
-.dw do_op_rmem16
-.dw do_op_rmem8
-.dw do_op_da
-.dw do_op_scf
-.dw do_op_cpl
-.dw do_op_ccf
-.dw do_op_pop16
-.dw do_op_push16
-.dw do_op_ifnz
-.dw do_op_ifz
-.dw do_op_ifnc
-.dw do_op_ifc
-.dw do_op_ifpo
-.dw do_op_ifpe
-.dw do_op_ifp
-.dw do_op_ifm
-.dw do_op_outa
-.dw do_op_in
-.dw do_op_exhl
-.dw do_op_di
-.dw do_op_ei
-.dw do_op_inv
+ rjmp do_op_nop
+ rjmp do_op_inc
+ rjmp do_op_dec
+ rjmp do_op_inc16
+ rjmp do_op_dec16
+ rjmp do_op_rlc
+ rjmp do_op_rrc
+ rjmp do_op_rr
+ rjmp do_op_rl
+ rjmp do_op_adda
+ rjmp do_op_adca
+ rjmp do_op_subfa
+ rjmp do_op_sbcfa
+ rjmp do_op_anda
+ rjmp do_op_ora
+ rjmp do_op_xora
+ rjmp do_op_addhl
+ rjmp do_op_sthl
+ rjmp do_op_rmem16
+ rjmp do_op_rmem8
+ rjmp do_op_da
+ rjmp do_op_scf
+ rjmp do_op_cpl
+ rjmp do_op_ccf
+ rjmp do_op_pop16
+ rjmp do_op_push16
+ rjmp do_op_ifnz
+ rjmp do_op_ifz
+ rjmp do_op_ifnc
+ rjmp do_op_ifc
+ rjmp do_op_ifpo
+ rjmp do_op_ifpe
+ rjmp do_op_ifp
+ rjmp do_op_ifm
+ rjmp do_op_outa
+ rjmp do_op_in
+ rjmp do_op_exhl
+ rjmp do_op_di
+ rjmp do_op_ei
+ rjmp do_op_inv
;How the flags are supposed to work:
;|ADD HL,ss |--?-0*|Add |HL=HL+ss |
;|ADD IX,pp |--?-0*|Add |IX=IX+pp |
;|ADD IY,rr |--?-0*|Add |IY=IY+rr |
-;|AND s |***P00|Logical AND |A=A&s |
+;|AND s |**1P00|Logical AND |A=A&s |
;|BIT b,m |?*1?0-|Test Bit |m&{2^b} |
;|CALL cc,nn|------|Conditional Call |If cc CALL |
;|CALL nn |------|Unconditional Call |-[SP]=PC,PC=nn |
;|LDIR |--000-|Load, Inc., Repeat |LDI till BC=0 |
;|NEG |***V1*|Negate |A=-A |
;|NOP |------|No Operation | |
-;|OR s |***P00|Logical inclusive OR |A=Avs |
+;|OR s |**0P00|Logical inclusive OR |A=Avs |
;|OTDR |?1??1-|Output, Dec., Repeat |OUTD till B=0 |
;|OTIR |?1??1-|Output, Inc., Repeat |OUTI till B=0 |
;|OUT [C],r |------|Output |[C]=r |
;|RLA |--0-0*|Rotate Left Acc. |A={CY,A}<- |
;|RLC m |**0P0*|Rotate Left Circular |m=m<- |
;|RLCA |--0-0*|Rotate Left Circular |A=A<- |
-;----------------------------------------------------------------
-;----------------------------------------------------------------
-;|Mnemonic |SZHPNC|Description |Notes |
-;|----------+------+---------------------+----------------------|
;|RLD |**0P0-|Rotate Left 4 bits |{A,[HL]}={A,[HL]}<- ##|
;|RR m |**0P0*|Rotate Right |m=->{CY,m} |
;|RRA |--0-0*|Rotate Right Acc. |A=->{CY,A} |
;|SRA m |**0P0*|Shift Right Arith. |m=m/2 |
;|SRL m |**0P0*|Shift Right Logical |m=->{0,m,CY} |
;|SUB s |***V1*|Subtract |A=A-s |
-;|XOR s |***P00|Logical Exclusive OR |A=Axs |
+;|XOR s |**0P00|Logical Exclusive OR |A=Axs |
;|----------+------+--------------------------------------------|
;| F |-*01? |Flag unaffected/affected/reset/set/unknown |
;| S |S |Sign flag (Bit 7) |
;----------------------------------------------------------------
-;ToDo: Parity at more instructions...
-
+.equ AVR_T = 6
.equ AVR_H = 5
.equ AVR_S = 4
.equ AVR_V = 3
.equ AVR_Z = 1
.equ AVR_C = 0
+;------------------------------------------------;
+; 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.
+;
+; ldpmx dstreg,tablebase,indexreg
+;
+; (6 words, 8 cycles)
+
+.macro ldpmx
+ ldi zh,high(@1*2) ; table must be page aligned
+ mov zl,@2
+ lpm @0,z
+.endm
+
+.macro do_z80_flags_HP
+#if EM_Z80
+ bmov z_flags, ZFL_P, temp, AVR_V
+ bmov z_flags, ZFL_H, temp, AVR_H
+#endif
+.endm
+
+.macro do_z80_flags_set_N
+#if EM_Z80
+ ori z_flags, (1<<ZFL_N) ; Negation auf 1
+#endif
+.endm
+
+.macro do_z80_flags_set_HN
+#if EM_Z80
+ ori z_flags,(1<<ZFL_N)|(1<<ZFL_H)
+#endif
+.endm
+
+.macro do_z80_flags_clear_N
+#if EM_Z80
+ andi z_flags,~(1<<ZFL_N)
+#endif
+.endm
+
+.macro do_z80_flags_op_rotate
+ ; must not change avr carry flag!
+#if EM_Z80
+ andi z_flags, ~( (1<<ZFL_H) | (1<<ZFL_N) | (1<<ZFL_C) )
+#else
+ andi z_flags, ~( (1<<ZFL_C) )
+#endif
+.endm
+
+.macro do_z80_flags_op_and
+#if EM_Z80
+ ori z_flags,(1<<ZFL_H)
+#else
+ ori z_flags,(1<<ZFL_H)
+#endif
+.endm
+
+.macro do_z80_flags_op_or
+#if EM_Z80
+#endif
+.endm
+
+
do_op_nop:
ret
;|INC r |***V0-|Increment |r=r+1 |
;|INC [HL] |***V0-|Increment |[HL]=[HL]+1 |
;|INC [xx+d]|***V0-|Increment |[xx+d]=[xx+d]+1 |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|INC r |**-P0-|Increment |r=r+1 |
+;|INC [HL] |**-P0-|Increment |[HL]=[HL]+1 |
;
-; OK
+;
do_op_inc:
- andi z_flags, (1<<ZFL_C) ; bis auf Carry alles auf 0
- ldi temp, 1
- add opl, temp
- in temp, sreg
- mov parityb, opl
- bst temp, AVR_Z ; Zero
- bld z_flags, ZFL_Z
- sbrc opl, 7 ; Sign
- ori z_flags, (1<<ZFL_S)
- bst temp, AVR_H ; Half Sign
- bld z_flags, ZFL_H
- bst temp, AVR_C ; Overflow
- bld z_flags, ZFL_P
+ ldi temp,1
+ add opl,temp
+ in temp, sreg
+ andi z_flags,(1<<ZFL_H)|(1<<ZFL_C) ; preserve C-, and H-flag
+ ldpmx temp2, sz53p_tab, opl
+ or z_flags,temp2 ;
+ do_z80_flags_HP
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
-;|DEC s |***V1-|Decrement |s=s-1 |
+;|DEC r |***V1-|Decrement |s=s-1 |
+;|INC [HL] |***V0-|Increment |[HL]=[HL]+1 |
+;|INC [xx+d]|***V0-|Increment |[xx+d]=[xx+d]+1 |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|DEC r |**-P -|Increment |r=r+1 |
+;|DEC [HL] |**-P -|Increment |[HL]=[HL]+1 |
+;
;
-; OK
do_op_dec:
- andi z_flags, (1<<ZFL_C) ; bis auf Carry alles auf 0
- ori z_flags, (1<<ZFL_N) ; Negation auf 1
- ldi temp, 1
- sub opl, temp
+ subi opl,1
in temp, sreg
- mov parityb, opl
- bst temp, AVR_Z ; Zero
- bld z_flags, ZFL_Z
- bst temp, AVR_S ; Sign
- bld z_flags, ZFL_S
- bst temp, AVR_H ; Half Sign
- bld z_flags, ZFL_H
- bst temp, AVR_C ; Underflow
- bld z_flags, ZFL_P
+ andi z_flags,(1<<ZFL_H)|(1<<ZFL_C) ; preserve C-, and H-flag
+ ldpmx temp2, sz53p_tab, opl
+ or z_flags,temp2 ;
+ do_z80_flags_HP
+ do_z80_flags_set_N
ret
;|INC xx |------|Increment |xx=xx+1 |
;|INC ss |------|Increment |ss=ss+1 |
;
-; OK
+;
do_op_inc16:
- ldi temp, 1
- ldi temp2, 0
- add opl, temp
- adc oph, temp2
+ adiw opl,1
ret
;----------------------------------------------------------------
;|DEC xx |------|Decrement |xx=xx-1 |
;|DEC ss |------|Decrement |ss=ss-1 |
;
-; OK
+;
do_op_dec16:
- ldi temp, 1
- ldi temp2, 0
- sub opl, temp
- sbc oph, temp2
+ subi opl, 1
+ sbci oph, 0
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|RLCA |--0-0*|Rotate Left Circular |A=A<- |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|RLCA |---- *|Rotate Left Circular |A=A<- |
+;
;
-; OK
do_op_rlc:
;Rotate Left Cyclical. All bits move 1 to the
;left, the msb becomes c and lsb.
- andi z_flags, ~( (1<<ZFL_H) | (1<<ZFL_N) | (1<<ZFL_C) )
+ do_z80_flags_op_rotate
lsl opl
brcc do_op_rlc_noc
ori opl, 1
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|RRCA |--0-0*|Rotate Right Circular|A=->A |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|RRCA |---- *|Rotate Right Circular|A=->A |
+;
;
-; OK
do_op_rrc:
;Rotate Right Cyclical. All bits move 1 to the
;right, the lsb becomes c and msb.
- andi z_flags, ~( (1<<ZFL_H) | (1<<ZFL_N) | (1<<ZFL_C) )
+ do_z80_flags_op_rotate
lsr opl
brcc do_op_rrc_noc
ori opl, 0x80
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|RRA |--0-0*|Rotate Right Acc. |A=->{CY,A} |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|RRA |---- *|Rotate Right Acc. |A=->{CY,A} |
;
-; OK
+;
do_op_rr:
;Rotate Right. All bits move 1 to the right, the lsb
;becomes c, c becomes msb.
- clc
+ clc ; get z80 carry to avr carry
sbrc z_flags,ZFL_C
sec
+ do_z80_flags_op_rotate ; (clear ZFL_C, doesn't change AVR_C)
+ bmov z_flags,ZFL_C, opl,0 ; Bit 0 --> CY
ror opl
- in temp,sreg
- andi z_flags,~( (1<<ZFL_H) | (1<<ZFL_N) | (1<<ZFL_C) )
- bst temp,AVR_C
- bld z_flags,ZFL_C
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
+;|RLA |--0-0*|Rotate Left Acc. |A={CY,A}<- |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|RLA |---- *|Rotate Left Acc. |A={CY,A}<- |
;
-; Not yet checked
+;
do_op_rl:
;Rotate Left. All bits move 1 to the left, the msb
;becomes c, c becomes lsb.
clc
sbrc z_flags,ZFL_C
sec
+ do_z80_flags_op_rotate ; (clear ZFL_C, doesn't change AVR_C)
+ bmov z_flags,ZFL_C, opl,7 ; Bit 7 --> CY
rol opl
- in temp,sreg
- andi z_flags,0b11101100
- bst temp,AVR_C
- bld z_flags,ZFL_C
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
+;|ADD A,s |***V0*|Add |A=A+s |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|ADD A,s |***P *|Add |A=A+s |
+;
;
-; Not yet checked
do_op_adda:
- ldi z_flags,0
add opl,z_a
in temp,sreg
- bst temp,AVR_Z
- bld z_flags,ZFL_Z
- bst temp,AVR_S
- cpi opl,$80
- brne adda_no_s
- ori z_flags,(1<<ZFL_S)
-adda_no_s:
- bst temp,AVR_H
- bld z_flags,ZFL_H
- bst temp,AVR_V
- bld z_flags,ZFL_P
- bst temp,AVR_C
- bld z_flags,ZFL_C
+ ldpmx z_flags,sz53p_tab,opl ;S,Z,P flag
+ bmov z_flags,ZFL_C, temp,AVR_C
+ do_z80_flags_HP
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
+;|ADC A,s |***V0*|Add with Carry |A=A+s+CY |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|ADC A,s |***P *|Add with Carry |A=A+s+CY |
+;
;
-; Not yet checked
do_op_adca:
clc
sbrc z_flags,ZFL_C
sec
adc opl,z_a
in temp,sreg
- ldi z_flags,0
- bst temp,AVR_Z
- bld z_flags,ZFL_Z
- sbrc opl,7
- ori z_flags,(1<<ZFL_S)
- bst temp,AVR_H
- bld z_flags,ZFL_H
- bst temp,AVR_V
- bld z_flags,ZFL_P
- bst temp,AVR_C
- bld z_flags,ZFL_C
- andi z_flags,~(1<<ZFL_N)
+ ldpmx z_flags,sz53p_tab,opl ;S,Z,P
+ bmov z_flags,ZFL_C, temp,AVR_C
+ do_z80_flags_HP
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
+;|SUB s |***V1*|Subtract |A=A-s |
+;|CP s |***V1*|Compare |A-s |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|SUB s |***P *|Subtract |A=A-s |
+;|CP s |***P *|Compare |A-s |
+
;
-; Not yet checked
do_op_subfa:
mov temp,z_a
sub temp,opl
mov opl,temp
in temp,sreg
- bst temp,AVR_Z
- bld z_flags,ZFL_Z
- bst temp,AVR_S
- bld z_flags,ZFL_S
- bst temp,AVR_H
- bld z_flags,ZFL_H
- bst temp,AVR_V
- bld z_flags,ZFL_P
- bst temp,AVR_C
- bld z_flags,ZFL_C
- ori z_flags,(1<<ZFL_N)
+ ldpmx z_flags,sz53p_tab,opl ;S,Z,P
+ bmov z_flags,ZFL_C, temp,AVR_C
+ do_z80_flags_HP
+ do_z80_flags_set_N
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
+;|SBC A,s |***V1*|Subtract with Carry |A=A-s-CY |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|SBC A,s |***P *|Subtract with Carry |A=A-s-CY |
+;
;
-; Not yet checked
do_op_sbcfa:
mov temp,z_a
clc
sbc temp,opl
mov opl,temp
in temp,sreg
- bst temp,AVR_S
- bld z_flags,ZFL_S
- bst temp,AVR_H
- bld z_flags,ZFL_H
- bst temp,AVR_V
- bld z_flags,ZFL_P
- bst temp,AVR_C
- bld z_flags,ZFL_C
- cpi opl,0 ;AVR doesn't set Z?
- in temp,sreg
- bst temp,AVR_Z
- bld z_flags,ZFL_Z
- ori z_flags,(1<<ZFL_N)
+ ldpmx z_flags,sz53p_tab,opl ;S,Z,P
+ bmov z_flags,ZFL_C, temp,AVR_C
+ do_z80_flags_HP
+ do_z80_flags_set_N
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
+;|AND s |**1P00|Logical AND |A=A&s |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|AND s |**-P 0|Logical AND |A=A&s |
;
-; Not yet checked
+; TODO H-Flag
do_op_anda:
- ldi z_flags,0
- and opl,z_a
- in temp,sreg
- bst temp,AVR_Z
- bld z_flags,ZFL_Z
- bst temp,AVR_S
- bld z_flags,ZFL_S
- bst temp,AVR_H
- bld z_flags,ZFL_H
- mov temp,opl
+ and opl,z_a ;
+ ldpmx z_flags,sz53p_tab,opl ;S,Z,P,N,C
+ do_z80_flags_op_and
ret
+
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
+;|OR s |**0P00|Logical inclusive OR |A=Avs |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|OR s |**-P00|Logical inclusive OR |A=Avs |
;
-; Not yet checked
+; TODO: H-Flag
do_op_ora:
- ldi z_flags,0
or opl,z_a
- in temp,sreg
- bst temp,AVR_Z
- bld z_flags,ZFL_Z
- bst temp,AVR_S
- bld z_flags,ZFL_S
- bst temp,AVR_H
- bld z_flags,ZFL_H
- mov temp,opl
+ ldpmx z_flags,sz53p_tab,opl ;S,Z,H,P,N,C
+ do_z80_flags_op_or
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
+;|XOR s |**0P00|Logical Exclusive OR |A=Axs |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|XOR s |**-P 0|Logical Exclusive OR |A=Axs |
;
-; Not yet checked
+; TODO: H-Flag
do_op_xora:
- ldi z_flags,0
eor opl,z_a
- in temp,sreg
- bst temp,AVR_Z
- bld z_flags,ZFL_Z
- bst temp,AVR_S
- bld z_flags,ZFL_S
- bst temp,AVR_H
- bld z_flags,ZFL_H
- mov temp,opl
+ ldpmx z_flags,sz53p_tab,opl ;S,Z,H,P,N,C
+ do_z80_flags_op_or
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
+;|ADD HL,ss |--?-0*|Add |HL=HL+ss |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|ADD HL,ss |---- *|Add |HL=HL+ss |
+;
;
-; Not yet checked
do_op_addhl:
add opl,z_l
adc oph,z_h
in temp,sreg
- bst temp,AVR_C
- bld z_flags,ZFL_C
- andi z_flags,~(1<<ZFL_N)
+ bmov z_flags,ZFL_H, temp,AVR_H
+ bmov z_flags,ZFL_C, temp,AVR_C
+ do_z80_flags_clear_N
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
+;|LD dst,src|------|Load |dst=src |
;
-; Not yet checked
-do_op_sthl: ;store hl to mem loc in opl
- ;ToDo: check flags
- mov adrl,opl
- mov adrh,oph
+;
+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
+ rcall memWriteWord
+#else
mov temp,z_l
rcall memWriteByte
-
- ldi temp,1
- ldi temp2,0
- add opl,temp
- adc oph,temp2
-
- mov adrl,opl
- mov adrh,oph
+ adiw adrl,1
mov temp,z_h
rcall memWriteByte
-
+#endif
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
+;|LD dst,src|------|Load |dst=src |
;
-; Not yet checked
+;
do_op_rmem16:
- mov adrl,opl
- mov adrh,oph
+ movw adrl,opl
+#if DRAM_WORD_ACCESS
+ rcall memReadWord
+ movw opl,temp
+#else
rcall memReadByte
mov opl,temp
- ldi temp,1
- add adrl,temp
- ldi temp,0
- adc adrh,temp
+ adiw adrl,1
rcall memReadByte
mov oph,temp
+#endif
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
+;|LD dst,src|------|Load |dst=src |
+;
;
-; Not yet checked
do_op_rmem8:
- mov adrl,opl
- mov adrh,oph
+ movw adrl,opl
rcall memReadByte
mov opl,temp
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
+;|DAA |***P-*|Decimal Adjust Acc. | |
+;|----------|SZHP C|---------- 8080 ----------------------------|
;
; Not yet checked
+
+; Description (http://www.z80.info/z80syntx.htm#DAA):
+; This instruction conditionally adjusts the accumulator for BCD addition
+; and subtraction operations. For addition (ADD, ADC, INC) or subtraction
+; (SUB, SBC, DEC, NEC), the following table indicates the operation performed:
+;
+; -------------------------------------------------------------------------------
+; | | C Flag | HEX value in | H Flag | HEX value in | Number | C flag|
+; | Operation| Before | upper digit | Before | lower digit | added | After |
+; | | DAA | (bit 7-4) | DAA | (bit 3-0) | to byte | DAA |
+; |-----------------------------------------------------------------------------|
+; | | 0 | 0-9 | 0 | 0-9 | 00 | 0 |
+; | ADD | 0 | 0-8 | 0 | A-F | 06 | 0 |
+; | | 0 | 0-9 | 1 | 0-3 | 06 | 0 |
+; | ADC | 0 | A-F | 0 | 0-9 | 60 | 1 |
+; | | 0 | 9-F | 0 | A-F | 66 | 1 |
+; | INC | 0 | A-F | 1 | 0-3 | 66 | 1 |
+; | | 1 | 0-2 | 0 | 0-9 | 60 | 1 |
+; | | 1 | 0-2 | 0 | A-F | 66 | 1 |
+; | | 1 | 0-3 | 1 | 0-3 | 66 | 1 |
+; |-----------------------------------------------------------------------------|
+; | SUB | 0 | 0-9 | 0 | 0-9 | 00 | 0 |
+; | SBC | 0 | 0-8 | 1 | 6-F | FA | 0 |
+; | DEC | 1 | 7-F | 0 | 0-9 | A0 | 1 |
+; | NEG | 1 | 6-F | 1 | 6-F | 9A | 1 |
+; |-----------------------------------------------------------------------------|
+;
+; Flags:
+; C: See instruction.
+; N: Unaffected.
+; P/V: Set if Acc. is even parity after operation, reset otherwise.
+; H: See instruction.
+; Z: Set if Acc. is Zero after operation, reset otherwise.
+; S: Set if most significant bit of Acc. is 1 after operation, reset otherwise.
+
+
+
+#if 1
do_op_da:
- ;DAA -> todo
- rcall do_op_inv
- mov temp,opl
+ ldi oph,0 ; what to add
+ sbrc z_flags,ZFL_H ; if H-Flag
+ rjmp op_da_06
+ mov temp,opl
+ andi temp,0x0f ; ... or lower digit > 9
+ cpi temp,0x0a
+ brlo op_da_06n
+op_da_06:
+ ori oph,0x06
+op_da_06n:
+ sbrc z_flags,(1<<ZFL_C)
+ rjmp op_da_60
+ cpi opl,0xa0
+ brlo op_da_60n
+op_da_60:
+ ori oph,0x60
+op_da_60n:
+ cpi opl,0x9a
+ brlo op_da_99n
+ ori z_flags,(1<<ZFL_C); set C
+op_da_99n:
+ sbrs z_flags,ZFL_N ; if sub-op
+ rjmp op_da_add ; then
+ sub opl,oph
+ rjmp op_da_ex
+op_da_add: ; else add-op
+ cpi opl,0x91
+ brlo op_da_60n2
+ mov temp,opl
+ andi temp,0x0f
+ cpi temp,0x0a
+ brlo op_da_60n2
+ ori oph,0x60
+op_da_60n2:
+ add opl,oph
+op_da_ex:
+ in temp,SREG
+ sbrc temp,AVR_H
+ ori z_flags,(1<<ZFL_C)
+ andi z_flags,(1<<ZFL_N)|(1<<ZFL_C) ; preserve C,N
+ ldpmx temp2, sz53p_tab, opl ; get S,Z,P
+ or z_flags,temp2
+ bmov z_flags,ZFL_H, temp,AVR_H ; H (?)
ret
+#else
+do_op_da:
+ sbrc z_flags,ZFL_N ; if add-op
+ rjmp do_op_da_sub ; then
+ ldi temp2,0 ;
+ mov temp,opl ;
+ andi temp,0x0f ;
+ cpi temp,0x0a ; if lower digit > 9
+ brlo do_op_da_h ;
+ ori temp2,0x06 ; add 6 to lower digit
+do_op_da_h: ;
+ sbrc z_flags,ZFL_H ; ... or H-Flag
+ ori temp2,0x06 ;
+ add opl,temp2 ;
+
+ ldi temp2,0 ;
+ mov temp,opl ;
+ andi temp,0xf0 ;
+ cpi temp,0xa0 ;
+ brlo do_op_da_c ;
+ ori temp2,0x60 ;
+do_op_da_c: ; else sub-op
+ sbrc z_flags,ZFL_C ;
+ ori temp2,0x60 ;
+ andi z_flags, ~( (1<<ZFL_S) | (1<<ZFL_Z) | (1<<ZFL_H) )
+ add opl,temp2 ;
+ in temp,SREG ;
+ bst temp,AVR_Z ;Z-Flag
+ bld z_flags,ZFL_Z ;
+ bst temp,AVR_N ;S-Flag
+ bst z_flags,ZFL_S ;
+ sbrc temp2,5 ;C-Flag, set if 0x06 added
+ ori z_flags,(1<<ZFL_C) ;
+ ;H-Flag?
+ ret
+
+do_op_da_sub: ;TODO:
+ rcall do_op_inv
+ ret
+#endif
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
+;|SCF |--0-01|Set Carry Flag |CY=1 |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;
;
-; Not yet checked
do_op_scf:
- ori z_flags,(1<<ZFL_C)
+ andi z_flags,~((1<<ZFL_H)|(1<<ZFL_N))
+ ori z_flags,(1<<ZFL_C)
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
+;|CCF |--?-0*|Complement Carry Flag|CY=~CY |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|SCF |---- 1|Set Carry Flag |CY=1 |
;
-; Not yet checked
+;TODO: H-Flag
do_op_ccf:
+ do_z80_flags_clear_N
ldi temp,(1<<ZFL_C)
eor z_flags,temp
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
+;|CPL |--1-1-|Complement |A=~A |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|CPL |---- -|Complement |A=~A |
+;
;
-; Not yet checked
do_op_cpl:
com opl
- ori z_flags,(1<<ZFL_N)|(1<<ZFL_H)
+ do_z80_flags_set_HN
ret
+
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
+;|PUSH xx |------|Push |-[SP]=xx |
+;|PUSH qq |------|Push |-[SP]=qq |
+;
;
-; Not yet checked
do_op_push16:
- ldi temp,1
- ldi temp2,0
- sub z_spl,temp
- sbc z_sph,temp2
-
- mov adrl,z_spl
- mov adrh,z_sph
- mov temp,oph
- rcall memWriteByte
-
- ldi temp,1
- ldi temp2,0
- sub z_spl,temp
- sbc z_sph,temp2
-
- mov adrl,z_spl
- mov adrh,z_sph
+ movw adrl,z_spl
+ subi adrl,2
+ sbci adrh,0
+ movw z_spl,adrl
+#if DRAM_WORD_ACCESS
+ movw temp,opl
+ rcall memWriteWord
+#else
mov temp,opl
rcall memWriteByte
+ adiw adrl,1
+ mov temp,oph
+ rcall memWriteByte
+#endif
.if STACK_DBG
rcall printstr
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
+;|POP xx |------|Pop |xx=[SP]+ |
+;|POP qq |------|Pop |qq=[SP]+ |
+;
;
-; Not yet checked
do_op_pop16:
- mov adrl,z_spl
- mov adrh,z_sph
+ movw adrl,z_spl
+#if DRAM_WORD_ACCESS
+ rcall memReadWord
+ movw opl,temp
+#else
rcall memReadByte
mov opl,temp
-
- ldi temp,1
- ldi temp2,0
- add z_spl,temp
- adc z_sph,temp2
-
- mov adrl,z_spl
- mov adrh,z_sph
+ adiw adrl,1
rcall memReadByte
mov oph,temp
+#endif
- ldi temp,1
- ldi temp2,0
+ ldi temp,2
add z_spl,temp
- adc z_sph,temp2
+ adc z_sph,_0
.if STACK_DBG
rcall printstr
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
+;|EX [SP],HL|------|Exchange |[SP]<->HL |
+;|EX DE,HL |------|Exchange |DE<->HL |
;
-; Not yet checked
+;
do_op_exhl:
mov temp,z_h
mov z_h,oph
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;
-; Not yet checked
+; TODO: Implement IFF1, IFF2
do_op_di:
ret
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;
-; Not yet checked
+; TODO: Implement IFF1, IFF2
do_op_ei:
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
+;|CALL cc,nn|------|Conditional Call |If cc CALL |
+;|JP cc,nn |------|Conditional Jump |If cc JP |
+;|RET cc |------|Conditional Return |If cc RET |
+;
;
-; Not yet checked
do_op_ifnz:
sbrs z_flags, ZFL_Z
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
+;|CALL cc,nn|------|Conditional Call |If cc CALL |
+;|JP cc,nn |------|Conditional Jump |If cc JP |
+;|RET cc |------|Conditional Return |If cc RET |
+;
;
-; Not yet checked
do_op_ifz:
sbrc z_flags, ZFL_Z
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
+;|CALL cc,nn|------|Conditional Call |If cc CALL |
+;|JP cc,nn |------|Conditional Jump |If cc JP |
+;|RET cc |------|Conditional Return |If cc RET |
+;
;
-; Not yet checked
do_op_ifnc:
sbrs z_flags, ZFL_C
- ret
+ ret
ldi insdech, 0
ldi insdecl, 0
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
+;|CALL cc,nn|------|Conditional Call |If cc CALL |
+;|JP cc,nn |------|Conditional Jump |If cc JP |
+;|RET cc |------|Conditional Return |If cc RET |
+;
;
-; Not yet checked
do_op_ifc:
sbrc z_flags, ZFL_C
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
+;|CALL cc,nn|------|Conditional Call |If cc CALL |
+;|JP cc,nn |------|Conditional Jump |If cc JP |
+;|RET cc |------|Conditional Return |If cc RET |
+;
;
-; Not yet checked
do_op_ifpo:
- rcall do_op_calcparity
- sbrs temp2, 0
+ sbrs z_flags, ZFL_P
ret
ldi insdech, 0
ldi insdecl, 0
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
+;|CALL cc,nn|------|Conditional Call |If cc CALL |
+;|JP cc,nn |------|Conditional Jump |If cc JP |
+;|RET cc |------|Conditional Return |If cc RET |
+;
;
-; Not yet checked
do_op_ifpe:
- rcall do_op_calcparity
- sbrc temp2, 0
+ sbrc z_flags, ZFL_P
ret
ldi insdech, 0
ldi insdecl, 0
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
+;|CALL cc,nn|------|Conditional Call |If cc CALL |
+;|JP cc,nn |------|Conditional Jump |If cc JP |
+;|RET cc |------|Conditional Return |If cc RET |
+;
;
-; Not yet checked
do_op_ifp: ;sign positive, aka s=0
sbrs z_flags, ZFL_S
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
+;|CALL cc,nn|------|Conditional Call |If cc CALL |
+;|JP cc,nn |------|Conditional Jump |If cc JP |
+;|RET cc |------|Conditional Return |If cc RET |
+;
;
-; Not yet checked
do_op_ifm: ;sign negative, aka s=1
sbrc z_flags, ZFL_S
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
+;|OUT [n],A |------|Output |[n]=A |
+;
;
-; Not yet checked
;Interface with peripherials goes here :)
do_op_outa: ; out (opl),a
.if PORT_DEBUG
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
+;|IN A,[n] |------|Input |A=[n] |
+;
;
-; Not yet checked
do_op_in: ; in a,(opl)
.if PORT_DEBUG
rcall printstr
.endif
ret
-;----------------------------------------------------------------
-do_op_calcparity:
- ldi temp2,1
- sbrc parityb,0
- inc temp2
- sbrc parityb,1
- inc temp2
- sbrc parityb,2
- inc temp2
- sbrc parityb,3
- inc temp2
- sbrc parityb,4
- inc temp2
- sbrc parityb,5
- inc temp2
- sbrc parityb,6
- inc temp2
- sbrc parityb,7
- inc temp2
- andi temp2,1
- ret
;----------------------------------------------------------------
do_op_inv:
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 -------------------------
; 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_DIR16| OP_NOP | STORE_BC ) ; 01 nn nn LD BC,nn
-.dw (FETCH_A | OP_NOP | STORE_MBC ) ; 02 LD (BC),A
-.dw (FETCH_BC | OP_INC16 | STORE_BC ) ; 03 INC BC
-.dw (FETCH_B | OP_INC | STORE_B ) ; 04 INC B
-.dw (FETCH_B | OP_DEC | STORE_B ) ; 05 DEC B
-.dw (FETCH_DIR8 | OP_NOP | STORE_B ) ; 06 nn LD B,n
-.dw (FETCH_A | OP_RLC | STORE_A ) ; 07 RLCA
-.dw (FETCH_NOP | OP_INV | STORE_NOP) ; 08 EX AF,AF' (Z80)
-.dw (FETCH_BC | OP_ADDHL | STORE_HL ) ; 09 ADD HL,BC
-.dw (FETCH_MBC | OP_NOP | STORE_A ) ; 0A LD A,(BC)
-.dw (FETCH_BC | OP_DEC16 | STORE_BC ) ; 0B DEC BC
-.dw (FETCH_C | OP_INC | STORE_C ) ; 0C INC C
-.dw (FETCH_C | OP_DEC | STORE_C ) ; 0D DEC C
-.dw (FETCH_DIR8 | OP_NOP | STORE_C ) ; 0E nn LD C,n
-.dw (FETCH_A | OP_RRC | STORE_A ) ; 0F RRCA
-.dw (FETCH_NOP | OP_INV | STORE_NOP) ; 10 oo DJNZ o (Z80)
+.dw (FETCH_NOP | OP_NOP | STORE_NOP) ; 00 NOP
+.dw (FETCH_DIR16| OP_NOP | STORE_BC ) ; 01 nn nn LD BC,nn
+.dw (FETCH_A | OP_NOP | STORE_MBC) ; 02 LD (BC),A
+.dw (FETCH_BC | OP_INC16 | STORE_BC ) ; 03 INC BC
+.dw (FETCH_B | OP_INC | STORE_B ) ; 04 INC B
+.dw (FETCH_B | OP_DEC | STORE_B ) ; 05 DEC B
+.dw (FETCH_DIR8 | OP_NOP | STORE_B ) ; 06 nn LD B,n
+.dw (FETCH_A | OP_RLC | STORE_A ) ; 07 RLCA
+.dw (FETCH_NOP | OP_INV | STORE_NOP) ; 08 EX AF,AF' (Z80)
+.dw (FETCH_BC | OP_ADDHL | STORE_HL ) ; 09 ADD HL,BC
+.dw (FETCH_MBC | OP_NOP | STORE_A ) ; 0A LD A,(BC)
+.dw (FETCH_BC | OP_DEC16 | STORE_BC ) ; 0B DEC BC
+.dw (FETCH_C | OP_INC | STORE_C ) ; 0C INC C
+.dw (FETCH_C | OP_DEC | STORE_C ) ; 0D DEC C
+.dw (FETCH_DIR8 | OP_NOP | STORE_C ) ; 0E nn LD C,n
+.dw (FETCH_A | OP_RRC | STORE_A ) ; 0F RRCA
+.dw (FETCH_NOP | OP_INV | STORE_NOP) ; 10 oo DJNZ o (Z80)
.dw (FETCH_DIR16| OP_NOP | STORE_DE ) ; 11 nn nn LD DE,nn
.dw (FETCH_A | OP_NOP | STORE_MDE) ; 12 LD (DE),A
-.dw (FETCH_DE | OP_INC16 | STORE_DE ) ; 13 INC DE
+.dw (FETCH_DE | OP_INC16 | STORE_DE ) ; 13 INC DE
.dw (FETCH_D | OP_INC | STORE_D ) ; 14 INC D
.dw (FETCH_D | OP_DEC | STORE_D ) ; 15 DEC D
.dw (FETCH_DIR8 | OP_NOP | STORE_D ) ; 16 nn LD D,n
.dw (FETCH_DIR8 | OP_SUBFA | STORE_A ) ; D6 nn SUB n
.dw (FETCH_RST | OP_NOP | STORE_CALL) ; D7 RST 10H
.dw (FETCH_NOP | OP_IFC | STORE_RET) ; D8 RET C
-.dw (FETCH_NOP | OP_INV | STORE_NOP) ; D9 EXX (Z80)
+.dw (FETCH_NOP | OP_INV | STORE_NOP) ; D9 EXX (Z80)
.dw (FETCH_DIR16| OP_IFC | STORE_PC ) ; DA nn nn JP C,nn
.dw (FETCH_DIR8 | OP_IN | STORE_A ) ; DB nn IN A,(n)
.dw (FETCH_DIR16| OP_IFC | STORE_CALL) ; DC nn nn CALL C,nn
.dw (FETCH_NOP | OP_INV | STORE_NOP) ; FD (Z80 specific)
.dw (FETCH_DIR8 | OP_SUBFA | STORE_NOP) ; FE nn CP n
.dw (FETCH_RST | OP_NOP | STORE_CALL) ; FF RST 38H
+
+; vim:set ts=8 noet nowrap
+