X-Git-Url: http://cloudbase.mooo.com/gitweb/avrcpm.git/blobdiff_plain/828e6f1e1b090a20ef2e595d8fc259f512423ef8..411b34bd372992e583428ab5edea4d758b518e95:/z80.asm diff --git a/z80.asm b/z80.asm index 6e8d57b..efb91df 100755 --- a/z80.asm +++ b/z80.asm @@ -16,16 +16,57 @@ ; You should have received a copy of the GNU General Public License ; along with this program. If not, see . +;.nolist +#if defined atmega8 + .include "m8def.inc" +#elif defined atmega168 + .include "m168def.inc" +#else /* default */ + .include "m88def.inc" + ;FUSE_H=0xDF + ;FUSE_L=0xF7 +#endif +.list -;FUSE_H=0xDF -;FUSE_L=0xF7 -.include "m88def.inc" -;device ATmega88 +.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 */ +#endif +#ifndef BAUD + #define BAUD 38400 /* console baud rate */ +#endif + + +#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 + + +#if defined __ATmega8__ + .equ refr_vect = OC2addr +#else + .equ refr_vect = OC2Aaddr +#endif + + +#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 @@ -44,25 +85,53 @@ .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< 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 @@ -908,7 +1103,7 @@ mmcReadSect: 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 @@ -951,7 +1146,7 @@ mmcreadloop: rcall mmcByteNoSend rcall mmcByteNoSend - sbi portd,mmc_cs + sbi P_MMC_CS,mmc_cs rcall mmcByteNoSend ldi temp,0 @@ -965,7 +1160,7 @@ mmcWriteSect: ldi temp,0x50 out SPCR,temp - cbi portd,mmc_cs + cbi P_MMC_CS,mmc_cs rcall mmcByteNoSend ldi temp,0x58 ;cmd (write sector) @@ -1018,7 +1213,7 @@ mmcwaitwritten: cpi temp,0xff brne mmcwaitwritten - sbi portd,mmc_cs + sbi P_MMC_CS,mmc_cs rcall mmcByteNoSend ldi temp,0 @@ -1029,15 +1224,44 @@ mmcwaitwritten: ;Set up wdt to time out after 1 sec. resetAVR: cli - ldi temp,0x10 +#if defined __ATmega8__ + ldi temp,(1< 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 + + ldi zl,0 + 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 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 + ldi insdech,0 + cp temp,insdech ;Repeat until oph:temp gets zero + cpc temp2,insdech + cpc opl,insdech + cpc oph,insdech + 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 @@ -1303,25 +1978,108 @@ printstr_end: .equ memReadByte = dram_read .equ memWriteByte = dram_write +; -------------------------------------------------------------- + .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,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. -;Fetches a char from the uart to temp. If none available, waits till one is. uartgetc: - lds temp,ucsr0a - sbrs temp,7 - rjmp uartgetc - lds temp,udr0 + 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__ +uartputc_l: + sbis UCSRA,UDRE + rjmp uartputc_l + out UDR,temp +#else push temp uartputc_l: - lds temp,ucsr0a - sbrs temp,5 + lds temp,UCSR0A + sbrs temp,UDRE0 rjmp uartputc_l pop temp - sts udr0,temp + sts UDR0,temp +#endif ret ; ------------ Fetch phase stuff ----------------- @@ -1405,10 +2163,6 @@ do_fetch_l: do_fetch_af: mov opl,z_flags mov oph,z_a - rcall do_op_calcparity - andi opl,~(1<HL | -;|EX [SP],xx|------|Exchange |[SP]<->xx | -;|EX AF,AF' |------|Exchange |AF<->AF' | -;|EX DE,HL |------|Exchange |DE<->HL | -;|EXX |------|Exchange |qq<->qq' (except AF)| -;|HALT |------|Halt | | -;|IM n |------|Interrupt Mode | (n=0,1,2)| -;|IN A,[n] |------|Input |A=[n] | -;|IN r,[C] |***P0-|Input |r=[C] | -;|INC r |***V0-|Increment |r=r+1 | -;|INC [HL] |***V0-|Increment |[HL]=[HL]+1 | -;|INC xx |------|Increment |xx=xx+1 | -;|INC [xx+d]|***V0-|Increment |[xx+d]=[xx+d]+1 | -;|INC ss |------|Increment |ss=ss+1 | -;|IND |?*??1-|Input and Decrement |[HL]=[C],HL=HL-1,B=B-1| -;|INDR |?1??1-|Input, Dec., Repeat |IND till B=0 | -;|INI |?*??1-|Input and Increment |[HL]=[C],HL=HL+1,B=B-1| -;|INIR |?1??1-|Input, Inc., Repeat |INI till B=0 | -;|JP [HL] |------|Unconditional Jump |PC=[HL] | -;|JP [xx] |------|Unconditional Jump |PC=[xx] | -;|JP nn |------|Unconditional Jump |PC=nn | -;|JP cc,nn |------|Conditional Jump |If cc JP | -;|JR e |------|Unconditional Jump |PC=PC+e | -;|JR cc,e |------|Conditional Jump |If cc JR(cc=C,NC,NZ,Z)| -;|LD dst,src|------|Load |dst=src | -;|LD A,i |**0*0-|Load |A=i (i=I,R)| -;|LDD |--0*0-|Load and Decrement |[DE]=[HL],HL=HL-1,# | -;|LDDR |--000-|Load, Dec., Repeat |LDD till BC=0 | -;|LDI |--0*0-|Load and Increment |[DE]=[HL],HL=HL+1,# | -;|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 | -;|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 | -;|OUT [n],A |------|Output |[n]=A | -;|OUTD |?*??1-|Output and Decrement |[C]=[HL],HL=HL-1,B=B-1| -;|OUTI |?*??1-|Output and Increment |[C]=[HL],HL=HL+1,B=B-1| -;|POP xx |------|Pop |xx=[SP]+ | -;|POP qq |------|Pop |qq=[SP]+ | -;|PUSH xx |------|Push |-[SP]=xx | -;|PUSH qq |------|Push |-[SP]=qq | -;|RES b,m |------|Reset bit |m=m&{~2^b} | -;|RET |------|Return |PC=[SP]+ | -;|RET cc |------|Conditional Return |If cc RET | -;|RETI |------|Return from Interrupt|PC=[SP]+ | -;|RETN |------|Return from NMI |PC=[SP]+ | -;|RL m |**0P0*|Rotate Left |m={CY,m}<- | -;|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} | -;|RRC m |**0P0*|Rotate Right Circular|m=->m | -;|RRCA |--0-0*|Rotate Right Circular|A=->A | -;|RRD |**0P0-|Rotate Right 4 bits |{A,[HL]}=->{A,[HL]} ##| -;|RST p |------|Restart | (p=0H,8H,10H,...,38H)| -;|SBC A,s |***V1*|Subtract with Carry |A=A-s-CY | -;|SBC HL,ss |**?V1*|Subtract with Carry |HL=HL-ss-CY | -;|SCF |--0-01|Set Carry Flag |CY=1 | -;|SET b,m |------|Set bit |m=mv{2^b} | -;|SLA m |**0P0*|Shift Left Arithmetic|m=m*2 | -;|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 | -;|----------+------+--------------------------------------------| -;| F |-*01? |Flag unaffected/affected/reset/set/unknown | -;| S |S |Sign flag (Bit 7) | -;| Z | Z |Zero flag (Bit 6) | -;| HC | H |Half Carry flag (Bit 4) | -;| P/V | P |Parity/Overflow flag (Bit 2, V=overflow) | -;| N | N |Add/Subtract flag (Bit 1) | -;| CY | C|Carry flag (Bit 0) | -;|-----------------+--------------------------------------------| -;| n |Immediate addressing | -;| nn |Immediate extended addressing | -;| e |Relative addressing (PC=PC+2+offset) | -;| [nn] |Extended addressing | -;| [xx+d] |Indexed addressing | -;| r |Register addressing | -;| [rr] |Register indirect addressing | -;| |Implied addressing | -;| b |Bit addressing | -;| p |Modified page zero addressing (see RST) | -;|-----------------+--------------------------------------------| -;|DEFB n(,...) |Define Byte(s) | -;|DEFB 'str'(,...) |Define Byte ASCII string(s) | -;|DEFS nn |Define Storage Block | -;|DEFW nn(,...) |Define Word(s) | -;|-----------------+--------------------------------------------| -;| A B C D E |Registers (8-bit) | -;| AF BC DE HL |Register pairs (16-bit) | -;| F |Flag register (8-bit) | -;| I |Interrupt page address register (8-bit) | -;| IX IY |Index registers (16-bit) | -;| PC |Program Counter register (16-bit) | -;| R |Memory Refresh register | -;| SP |Stack Pointer register (16-bit) | -;|-----------------+--------------------------------------------| -;| b |One bit (0 to 7) | -;| cc |Condition (C,M,NC,NZ,P,PE,PO,Z) | -;| d |One-byte expression (-128 to +127) | -;| dst |Destination s, ss, [BC], [DE], [HL], [nn] | -;| e |One-byte expression (-126 to +129) | -;| m |Any register r, [HL] or [xx+d] | -;| n |One-byte expression (0 to 255) | -;| nn |Two-byte expression (0 to 65535) | -;| pp |Register pair BC, DE, IX or SP | -;| qq |Register pair AF, BC, DE or HL | -;| qq' |Alternative register pair AF, BC, DE or HL | -;| r |Register A, B, C, D, E, H or L | -;| rr |Register pair BC, DE, IY or SP | -;| s |Any register r, value n, [HL] or [xx+d] | -;| src |Source s, ss, [BC], [DE], [HL], nn, [nn] | -;| ss |Register pair BC, DE, HL or SP | -;| xx |Index register IX or IY | -;|-----------------+--------------------------------------------| -;| + - * / ^ |Add/subtract/multiply/divide/exponent | -;| & ~ v x |Logical AND/NOT/inclusive OR/exclusive OR | -;| <- -> |Rotate left/right | -;| [ ] |Indirect addressing | -;| [ ]+ -[ ] |Indirect addressing auto-increment/decrement| -;| { } |Combination of operands | -;| # |Also BC=BC-1,DE=DE-1 | -;| ## |Only lower 4 bits of accumulator A used | -;---------------------------------------------------------------- - - -;ToDo: Parity at more instructions... - +;---------------------------------------------------------------- +;| | +;| Zilog | +;| | +;| ZZZZZZZ 88888 000 | +;| Z 8 8 0 0 | +;| Z 8 8 0 0 0 | +;| Z 88888 0 0 0 | +;| Z 8 8 0 0 0 | +;| Z 8 8 0 0 | +;| ZZZZZZZ 88888 000 | +;| | +;| Z80 MICROPROCESSOR Instruction Set Summary | +;| | +;---------------------------------------------------------------- +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;|----------+------+---------------------+----------------------| +;|ADC A,s |***V0*|Add with Carry |A=A+s+CY | +;|ADC HL,ss |**?V0*|Add with Carry |HL=HL+ss+CY | +;|ADD A,s |***V0*|Add |A=A+s | +;|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 |**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 | +;|CCF |--?-0*|Complement Carry Flag|CY=~CY | +;|CP s |***V1*|Compare |A-s | +;|CPD |****1-|Compare and Decrement|A-[HL],HL=HL-1,BC=BC-1| +;|CPDR |****1-|Compare, Dec., Repeat|CPD till A=[HL]or BC=0| +;|CPI |****1-|Compare and Increment|A-[HL],HL=HL+1,BC=BC-1| +;|CPIR |****1-|Compare, Inc., Repeat|CPI till A=[HL]or BC=0| +;|CPL |--1-1-|Complement |A=~A | +;|DAA |***P-*|Decimal Adjust Acc. |A=BCD format | +;|DEC s |***V1-|Decrement |s=s-1 | +;|DEC xx |------|Decrement |xx=xx-1 | +;|DEC ss |------|Decrement |ss=ss-1 | +;|DI |------|Disable Interrupts | | +;|DJNZ e |------|Dec., Jump Non-Zero |B=B-1 till B=0 | +;|EI |------|Enable Interrupts | | +;|EX [SP],HL|------|Exchange |[SP]<->HL | +;|EX [SP],xx|------|Exchange |[SP]<->xx | +;|EX AF,AF' |------|Exchange |AF<->AF' | +;|EX DE,HL |------|Exchange |DE<->HL | +;|EXX |------|Exchange |qq<->qq' (except AF)| +;|HALT |------|Halt | | +;|IM n |------|Interrupt Mode | (n=0,1,2)| +;|IN A,[n] |------|Input |A=[n] | +;|IN r,[C] |***P0-|Input |r=[C] | +;|INC r |***V0-|Increment |r=r+1 | +;|INC [HL] |***V0-|Increment |[HL]=[HL]+1 | +;|INC xx |------|Increment |xx=xx+1 | +;|INC [xx+d]|***V0-|Increment |[xx+d]=[xx+d]+1 | +;|INC ss |------|Increment |ss=ss+1 | +;|IND |?*??1-|Input and Decrement |[HL]=[C],HL=HL-1,B=B-1| +;|INDR |?1??1-|Input, Dec., Repeat |IND till B=0 | +;|INI |?*??1-|Input and Increment |[HL]=[C],HL=HL+1,B=B-1| +;|INIR |?1??1-|Input, Inc., Repeat |INI till B=0 | +;|JP [HL] |------|Unconditional Jump |PC=[HL] | +;|JP [xx] |------|Unconditional Jump |PC=[xx] | +;|JP nn |------|Unconditional Jump |PC=nn | +;|JP cc,nn |------|Conditional Jump |If cc JP | +;|JR e |------|Unconditional Jump |PC=PC+e | +;|JR cc,e |------|Conditional Jump |If cc JR(cc=C,NC,NZ,Z)| +;|LD dst,src|------|Load |dst=src | +;|LD A,i |**0*0-|Load |A=i (i=I,R)| +;|LDD |--0*0-|Load and Decrement |[DE]=[HL],HL=HL-1,# | +;|LDDR |--000-|Load, Dec., Repeat |LDD till BC=0 | +;|LDI |--0*0-|Load and Increment |[DE]=[HL],HL=HL+1,# | +;|LDIR |--000-|Load, Inc., Repeat |LDI till BC=0 | +;|NEG |***V1*|Negate |A=-A | +;|NOP |------|No Operation | | +;|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 | +;|OUT [n],A |------|Output |[n]=A | +;|OUTD |?*??1-|Output and Decrement |[C]=[HL],HL=HL-1,B=B-1| +;|OUTI |?*??1-|Output and Increment |[C]=[HL],HL=HL+1,B=B-1| +;|POP xx |------|Pop |xx=[SP]+ | +;|POP qq |------|Pop |qq=[SP]+ | +;|PUSH xx |------|Push |-[SP]=xx | +;|PUSH qq |------|Push |-[SP]=qq | +;|RES b,m |------|Reset bit |m=m&{~2^b} | +;|RET |------|Return |PC=[SP]+ | +;|RET cc |------|Conditional Return |If cc RET | +;|RETI |------|Return from Interrupt|PC=[SP]+ | +;|RETN |------|Return from NMI |PC=[SP]+ | +;|RL m |**0P0*|Rotate Left |m={CY,m}<- | +;|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<- | +;|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} | +;|RRC m |**0P0*|Rotate Right Circular|m=->m | +;|RRCA |--0-0*|Rotate Right Circular|A=->A | +;|RRD |**0P0-|Rotate Right 4 bits |{A,[HL]}=->{A,[HL]} ##| +;|RST p |------|Restart | (p=0H,8H,10H,...,38H)| +;|SBC A,s |***V1*|Subtract with Carry |A=A-s-CY | +;|SBC HL,ss |**?V1*|Subtract with Carry |HL=HL-ss-CY | +;|SCF |--0-01|Set Carry Flag |CY=1 | +;|SET b,m |------|Set bit |m=mv{2^b} | +;|SLA m |**0P0*|Shift Left Arithmetic|m=m*2 | +;|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 |**0P00|Logical Exclusive OR |A=Axs | +;|----------+------+--------------------------------------------| + + +.equ AVR_T = 6 .equ AVR_H = 5 .equ AVR_S = 4 .equ AVR_V = 3 @@ -1959,95 +2642,165 @@ opjumps: .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 zl,low (@1*2) + ldi zh,high(@1*2) + add zl,@2 + brcc PC+2 + inc zh + 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<A | -; -; OK +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +;|RRCA |--0-0*|Rotate Right Circular|A=->A | +;|----------|SZHP C|---------- 8080 ----------------------------| +;|RRCA |---- *|Rotate Right Circular|A=->A | +; +; do_op_rrc: ;Rotate Right Cyclical. All bits move 1 to the ;right, the lsb becomes c and msb. - andi z_flags, ~( (1<{CY,A} | -; -; OK +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +;|RRA |--0-0*|Rotate Right Acc. |A=->{CY,A} | +;|----------|SZHP C|---------- 8080 ----------------------------| +;|RRA |---- *|Rotate Right Acc. |A=->{CY,A} | +; +; 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< CY rol opl - in temp,sreg - andi z_flags,0b11101100 - bst temp,AVR_C - bld z_flags,ZFL_C ret -;---------------------------------------------------------------- -;|Mnemonic |SZHPNC|Description |Notes | -;---------------------------------------------------------------- -; -; Not yet checked +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +;|ADD A,s |***V0*|Add |A=A+s | +;|----------|SZHP C|---------- 8080 ----------------------------| +;|ADD A,s |***P *|Add |A=A+s | +; +; 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< 9 + cpi temp,0x0a + brlo op_da_06n +op_da_06: + ori oph,0x06 +op_da_06n: + sbrc z_flags,(1< todo + 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<HL | +;|EX DE,HL |------|Exchange |DE<->HL | +; +; do_op_exhl: mov temp,z_h mov z_h,oph @@ -2475,27 +3357,30 @@ do_op_exhl: mov opl,temp ret -;---------------------------------------------------------------- -;|Mnemonic |SZHPNC|Description |Notes | -;---------------------------------------------------------------- -; -; Not yet checked +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +; +; TODO: Implement IFF1, IFF2 do_op_di: ret -;---------------------------------------------------------------- -;|Mnemonic |SZHPNC|Description |Notes | -;---------------------------------------------------------------- -; -; Not yet checked +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +; +; TODO: Implement IFF1, IFF2 do_op_ei: ret -;---------------------------------------------------------------- -;|Mnemonic |SZHPNC|Description |Notes | -;---------------------------------------------------------------- -; -; Not yet checked +;---------------------------------------------------------------- +;|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 | +; +; do_op_ifnz: sbrs z_flags, ZFL_Z ret @@ -2503,11 +3388,14 @@ do_op_ifnz: ldi insdecl, 0 ret -;---------------------------------------------------------------- -;|Mnemonic |SZHPNC|Description |Notes | -;---------------------------------------------------------------- -; -; Not yet checked +;---------------------------------------------------------------- +;|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 | +; +; do_op_ifz: sbrc z_flags, ZFL_Z ret @@ -2515,23 +3403,29 @@ do_op_ifz: ldi insdecl, 0 ret -;---------------------------------------------------------------- -;|Mnemonic |SZHPNC|Description |Notes | -;---------------------------------------------------------------- -; -; Not yet checked +;---------------------------------------------------------------- +;|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 | +; +; do_op_ifnc: sbrs z_flags, ZFL_C - ret + ret ldi insdech, 0 ldi insdecl, 0 ret -;---------------------------------------------------------------- -;|Mnemonic |SZHPNC|Description |Notes | -;---------------------------------------------------------------- -; -; Not yet checked +;---------------------------------------------------------------- +;|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 | +; +; do_op_ifc: sbrc z_flags, ZFL_C ret @@ -2539,37 +3433,44 @@ do_op_ifc: ldi insdecl, 0 ret -;---------------------------------------------------------------- -;|Mnemonic |SZHPNC|Description |Notes | -;---------------------------------------------------------------- -; -; Not yet checked +;---------------------------------------------------------------- +;|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 | +; +; do_op_ifpo: - rcall do_op_calcparity - sbrs temp2, 0 + sbrs z_flags, ZFL_P ret ldi insdech, 0 ldi insdecl, 0 ret -;---------------------------------------------------------------- -;|Mnemonic |SZHPNC|Description |Notes | -;---------------------------------------------------------------- -; -; Not yet checked +;---------------------------------------------------------------- +;|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 | +; +; do_op_ifpe: - rcall do_op_calcparity - sbrc temp2, 0 + sbrc z_flags, ZFL_P ret ldi insdech, 0 ldi insdecl, 0 ret -;---------------------------------------------------------------- -;|Mnemonic |SZHPNC|Description |Notes | -;---------------------------------------------------------------- -; -; Not yet checked +;---------------------------------------------------------------- +;|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 | +; +; do_op_ifp: ;sign positive, aka s=0 sbrs z_flags, ZFL_S ret @@ -2577,11 +3478,14 @@ do_op_ifp: ;sign positive, aka s=0 ldi insdecl,0 ret -;---------------------------------------------------------------- -;|Mnemonic |SZHPNC|Description |Notes | -;---------------------------------------------------------------- -; -; Not yet checked +;---------------------------------------------------------------- +;|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 | +; +; do_op_ifm: ;sign negative, aka s=1 sbrc z_flags, ZFL_S ret @@ -2589,11 +3493,12 @@ do_op_ifm: ;sign negative, aka s=1 ldi insdecl, 0 ret -;---------------------------------------------------------------- -;|Mnemonic |SZHPNC|Description |Notes | -;---------------------------------------------------------------- -; -; Not yet checked +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +;|OUT [n],A |------|Output |[n]=A | +; +; ;Interface with peripherials goes here :) do_op_outa: ; out (opl),a .if PORT_DEBUG @@ -2613,11 +3518,12 @@ do_op_outa: ; out (opl),a rcall portWrite ret -;---------------------------------------------------------------- -;|Mnemonic |SZHPNC|Description |Notes | -;---------------------------------------------------------------- -; -; Not yet checked +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +;|IN A,[n] |------|Input |A=[n] | +; +; do_op_in: ; in a,(opl) .if PORT_DEBUG rcall printstr @@ -2639,7 +3545,9 @@ do_op_in: ; in a,(opl) .endif ret -;---------------------------------------------------------------- +;---------------------------------------------------------------- + +#if 0 do_op_calcparity: ldi temp2,1 sbrc parityb,0 @@ -2660,8 +3568,9 @@ do_op_calcparity: inc temp2 andi temp2,1 ret +#endif -;---------------------------------------------------------------- +;---------------------------------------------------------------- do_op_inv: rcall printstr .db "Invalid opcode @ PC=",0,0 @@ -2669,11 +3578,50 @@ do_op_inv: rcall printhex mov temp,z_pcl rcall printhex - -;---------------------------------------------------------------- + +;---------------------------------------------------------------- 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 +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 ------------------------- @@ -2940,3 +3888,6 @@ inst_table: .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 +