From: Leo Date: Thu, 23 Sep 2010 13:27:14 +0000 (+0000) Subject: Merged branch modules back into trunk. X-Git-Tag: 2.0-fat16~21 X-Git-Url: http://cloudbase.mooo.com/gitweb/avrcpm.git/commitdiff_plain/f0d2aa0ebc965fffaf2e871107a25a466ac13c00 Merged branch modules back into trunk. git-svn-id: svn://cu.loc/avr-cpm/trunk/avrcpm/avr@100 57430480-672e-4586-8877-bcf8adbbf3b7 --- diff --git a/8080int-jmp.asm b/8080int-jmp.asm new file mode 100644 index 0000000..742a4ed --- /dev/null +++ b/8080int-jmp.asm @@ -0,0 +1,1760 @@ +; 8080 Interpreter. +; This is part of the Z80-CP/M emulator written by Sprite_tm. +; + +; Copyright (C) 2010 Sprite_tm +; Copyright (C) 2010 Leo C. +; Copyright (C) 2010 Horst S. + +; This file is part of avrcpm. +; +; avrcpm is free software: you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by +; the Free Software Foundation, either version 3 of the License, or +; (at your option) any later version. +; +; avrcpm is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with avrcpm. If not, see . +; +; $Id$ +; + + .dseg + +z_b: .byte 1 +z_c: .byte 1 +z_d: .byte 1 +z_e: .byte 1 +z_h: .byte 1 +z_l: .byte 1 + + + .cseg + +;Init z80 +z80_init: + ldi z_pcl,low (IPLADDR) + ldi z_pch,high(IPLADDR) + + cbi flags,trace + printnewline + printstring "Ok, CPU is live!" + printnewline + +main: +.if INS_DEBUG + cbi flags,trace + cpi z_pch,DBG_TRACE_BOTTOM + brlo notraceon + cpi z_pch,DBG_TRACE_TOP + brsh notraceon + sbi flags,trace +notraceon: +.endif + + +.if PRINT_PC + cpi z_pch,DBG_TRACE_BOTTOM + brlo noprintpc + cpi z_pch,DBG_TRACE_TOP + brsh noprintpc + + printnewline + printstring "PC=" + movw temp,z_pcl + rcall printhexw + printstring " " +noprintpc: +.endif + +.if INS_DEBUG + sbic flags,trace + rcall printregs +.endif + ;hier kommt die Interruptbehandlung rein + + + mem_read_ds zl,z_pc ;zl = memReadByte(z_pc) + adiw z_pcl,1 ;++z_pc + ldi zh,high(opcjmp) ; + icall + rjmp main ; + + + +; .listmac + +;-------------------------------------------------- +; Generate a table entry for one instruction +; +; instr fetch, op, store +; +.macro instr + .ifndef opcjmp_table_pos_ + .set todo_table_pos_ = PC + ; Place the opcode jump table on the next available location. + .equ opcjmp = (PC+255) & 0xff00 + .set opcjmp_table_pos_ = opcjmp + .endif + + .if todo_table_pos_ < opcjmp + 256 + 128 + .if todo_table_pos_ + 3 >= opcjmp + .set todo_table_pos_ = opcjmp + 256 + 128 + .endif + .endif + .set do_@0_@1_@2 = todo_table_pos_ ; make a label + + .org opcjmp_table_pos_ + rjmp do_@0_@1_@2 ; generate a jump to the label + .set opcjmp_table_pos_ = PC + + .org do_@0_@1_@2 + + .set fetch_ = (@0 != do_fetch_nop) ; must call or jump to fetch phase + .set op_ = (do_@1 != do_op_nop) ; must call or jump to op phase + .set store_ = (@2 != do_store_nop) ; must jump to store phase + + .if fetch_ || op_ || store_ ; something to do + .if fetch_ ; must fetch + .if op_ || store_ + rcall @0 ; fetch and come back here + .else ; + rjmp @0 ; fetch and return to main + .endif + .endif + .if op_ ; must exec op + .if store_ + rcall do_@1 ; do op and come back here + .else + rjmp do_@1 ; do op and return to main + .endif + .endif + .if store_ ; must store + rjmp @2 ; store is allways last + .endif + .else + ret ; nop, go back to main + .endif + + .set todo_table_pos_ = PC +.endm + + +; ------------ Fetch phase stuff ----------------- + +;.org (PC+255) & 0xff00 +fetch_ops: +do_fetch_nop: + ret + +do_fetch_a: + mov opl,z_a + ret + +do_fetch_b: + lds opl,z_b + ret + +do_fetch_c: + lds opl,z_c + ret + +do_fetch_d: + lds opl,z_d + ret + +do_fetch_e: + lds opl,z_e + ret + +do_fetch_h: + lds opl,z_h + ret + +do_fetch_l: + lds opl,z_l + ret + +do_fetch_af: + mov opl,z_flags + mov oph,z_a + ret + +do_fetch_bc: + lds opl,z_c + lds oph,z_b + ret + +do_fetch_de: + lds opl,z_e + lds oph,z_d + ret + +do_fetch_hl: + lds opl,z_l + lds oph,z_h + ret + +do_fetch_sp: + movw opl,z_spl + ret + +do_fetch_mbc: + lds xh,z_b + lds xl,z_c + mem_read_d opl + ret + +do_fetch_mde: + lds xh,z_d + lds xl,z_e + mem_read_d opl + ret + +do_fetch_mhl: + lds xh,z_h + lds xl,z_l + mem_read_d opl + ret + +do_fetch_msp: + movw x,z_spl + mem_read_d opl + adiw x,1 + mem_read_d oph + ret + +do_fetch_dir8: + mem_read_ds opl, z_pc + adiw z_pcl,1 + ret + +do_fetch_dir16: + mem_read_ds opl, z_pc + adiw z_pcl,1 + mem_read_ds oph, z_pc + adiw z_pcl,1 + ret + +do_fetch_rst: + movw x,z_pcl + sbiw x,1 + mem_read_d opl + andi opl,0x38 + ldi oph,0 + ret + +; ------------ Store phase stuff ----------------- + +;.org (PC+255) & 0xff00 +store_ops: +do_store_nop: + ret + +do_store_a: + mov z_a,opl + ret + +do_store_b: + sts z_b,opl + ret + +do_store_c: + sts z_c,opl + ret + +do_store_d: + sts z_d,opl + ret + +do_store_e: + sts z_e,opl + ret + +do_store_h: + sts z_h,opl + ret + +do_store_l: + sts z_l,opl + ret + +do_store_af: + mov z_a,oph + mov z_flags,opl + ret + +do_store_bc: + sts z_b,oph + sts z_c,opl + ret + +do_store_de: + sts z_d,oph + sts z_e,opl + ret + +do_store_hl: + sts z_h,oph + sts z_l,opl + ret + +do_store_mbc: + lds xh,z_b + lds xl,z_c + mem_write_s opl + ret + +do_store_mde: + lds xh,z_d + lds xl,z_e + mem_write_s opl + ret + +do_store_mhl: + lds xh,z_h + lds xl,z_l + mem_write_s opl + ret + +do_store_msp: + movw xl,z_spl + mem_write_s opl + adiw xl,1 + mem_write_s oph + ret + +do_store_sp: + movw z_spl,opl + ret + +do_store_pc: + movw z_pcl,opl + ret + +do_store_ret: + movw x,z_spl + mem_read_d z_pcl + adiw x,1 + mem_read_d z_pch + adiw x,1 + movw z_spl,x + +.if STACK_DBG + printnewline + printstring "Stack pop " + movw temp,z_pcl + rcall printhexw + printstring ", SP is now " + movw temp,z_spl + rcall printhexw + printstring ". " +.endif + ret + +do_store_call: + movw xl,z_spl + sbiw x,1 + mem_write_s z_pch + sbiw x,1 + mem_write_s z_pcl + movw z_spl,xl + +.if STACK_DBG + printnewline + printstring "Stack push " + movw temp,z_pcl + rcall printhexw + printstring ", SP is now " + movw temp,z_spl + rcall printhexw + printstring ". " +.endif + movw z_pcl,opl + ret + + +do_store_am: + mem_write_ds op, z_a + ret + + + + +; ------------ Operation phase stuff ----------------- + +;---------------------------------------------------------------- +;| | +;| 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 | +;|----------+------+--------------------------------------------| +;| 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 | +;---------------------------------------------------------------- + +;How the flags are supposed to work: +;7 ZFL_S - Sign flag (=MSBit of result) +;6 ZFL_Z - Zero flag. Is 1 when the result is 0 +;4 ZFL_H - Half-carry (carry from bit 3 to 4) +;2 ZFL_P - Parity/2-complement Overflow +;1 ZFL_N - Subtract - set if last op was a subtract +;0 ZFL_C - Carry +; +;I sure hope I got the mapping between flags and instructions correct... + +.equ ZFL_S = 7 +.equ ZFL_Z = 6 +.equ ZFL_H = 4 +.equ ZFL_P = 2 +.equ ZFL_N = 1 +.equ ZFL_C = 0 + + +.equ AVR_T = SREG_T +.equ AVR_H = SREG_H +.equ AVR_S = SREG_S +.equ AVR_V = SREG_V +.equ AVR_N = SREG_N +.equ AVR_Z = SREG_Z +.equ AVR_C = SREG_C + +;------------------------------------------------; +; 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< (" + mov temp,opl + rcall printhex + printstring ") " +.endif + mov temp,z_a + mov temp2,opl + rcall portWrite + ret + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +;|IN A,[n] |------|Input |A=[n] | +; +; +do_op_in: ; in a,(opl) +.if PORT_DEBUG + printnewline + printstring "Port read: (" + mov temp,opl + rcall printhex + printstring ") -> " +.endif + + mov temp2,opl + rcall portRead + mov opl,temp + +.if PORT_DEBUG + rcall printhex + printstring " " +.endif + ret + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +;|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 | +; +; +do_op_inc: + inc opl +#if EM_Z80 + in temp, sreg +#endif + andi z_flags,(1<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. + do_z80_flags_op_rotate + lsr opl + brcc do_op_rrc_noc + ori opl, 0x80 + ori z_flags, (1<{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 ; 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 + ret + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +;|RLA |--0-0*|Rotate Left Acc. |A={CY,A}<- | +;|----------|SZHP C|---------- 8080 ----------------------------| +;|RLA |---- *|Rotate Left Acc. |A={CY,A}<- | +; +; +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 + ret + +;---------------------------------------------------------------- +;|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: + add z_a,opl + in temp,sreg + ldpmx z_flags,sz53p_tab,z_a ;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 | +; +; +do_op_adca: + clc + sbrc z_flags,ZFL_C + sec + adc z_a,opl + in temp,sreg + ldpmx z_flags,sz53p_tab,z_a ;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 | +;|----------|SZHP C|---------- 8080 ----------------------------| +;|SUB s |***P *|Subtract |A=A-s | + +; +do_op_subfa: + sub z_a,opl + in temp,sreg + ldpmx z_flags,sz53p_tab,z_a ;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 | +;---------------------------------------------------------------- +;|CP s |***V1*|Compare |A-s | +;|----------|SZHP C|---------- 8080 ----------------------------| +;|CP s |***P *|Compare |A-s | + +; +do_op_cpfa: + mov temp,z_a + sub temp,opl + mov opl,temp + in temp,sreg + 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 | +; +; +do_op_sbcfa: + clc + sbrc z_flags,ZFL_C + sec + sbc z_a,opl + in temp,sreg + ldpmx z_flags,sz53p_tab,z_a ;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 | +; +; TODO H-Flag +do_op_anda: + and z_a,opl ; + ldpmx z_flags,sz53p_tab,z_a ;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 | +; +; TODO: H-Flag +do_op_ora: + or z_a,opl + ldpmx z_flags,sz53p_tab,z_a ;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 | +; +; TODO: H-Flag +do_op_xora: + eor z_a,opl + ldpmx z_flags,sz53p_tab,z_a ;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 | +; +; +do_op_addhl: + lds temp,z_l + lds temp2,z_h + add opl,temp + adc oph,temp2 + in temp,sreg + bmov z_flags,ZFL_H, temp,AVR_H + bmov z_flags,ZFL_C, temp,AVR_C + do_z80_flags_clear_N + ret + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +;|LD dst,src|------|Load |dst=src | +; +; +do_op_sthl: ;store hl to mem loc in opl:h + movw xl,opl + lds temp,z_l + mem_write + adiw xl,1 + lds temp,z_h + mem_write + ret + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +;|LD dst,src|------|Load |dst=src | +; +; +do_op_rmem16: + movw xl,opl + mem_read_d opl + adiw x,1 + mem_read_d oph + ret + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +;|LD dst,src|------|Load |dst=src | +; +; +do_op_rmem8: + mem_read_ds opl, op + 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: + 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< 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 | +;-----------------------------Z80-------------------------------- +; +do_op_exhl: + lds temp,z_l + lds temp2,z_h + sts z_l,opl + sts z_h,oph + movw opl,temp + ret + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +; +; TODO: Implement IFF1, IFF2 +do_op_di: + ret + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +; +; 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 | +; +; +do_op_ifnz: + sbrs z_flags, ZFL_Z + ret + pop temp ; nix tun + pop temp ; direkt zuruech zu main + 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 | +; +; +do_op_ifz: + sbrc z_flags, ZFL_Z + ret + pop temp ; nix tun + pop temp ; direkt zuruech zu main + 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 | +; +; +do_op_ifnc: + sbrs z_flags, ZFL_C + ret + pop temp ; nix tun + pop temp ; direkt zuruech zu main + 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 | +; +; +do_op_ifc: + sbrc z_flags, ZFL_C + ret + pop temp ; nix tun + pop temp ; direkt zuruech zu main + 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 | +; +; +do_op_ifpo: + sbrs z_flags, ZFL_P + ret + pop temp ; nix tun + pop temp ; direkt zuruech zu main + 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 | +; +; +do_op_ifpe: + sbrc z_flags, ZFL_P + ret + pop temp ; nix tun + pop temp ; direkt zuruech zu main + 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 | +; +; +do_op_ifp: ;sign positive, aka s=0 + sbrs z_flags, ZFL_S + ret + pop temp ; nix tun + pop temp ; direkt zuruech zu main + 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 | +; +; +do_op_ifm: ;sign negative, aka s=1 + sbrc z_flags, ZFL_S + ret + pop temp ; nix tun + pop temp ; direkt zuruech zu main + ret + + +; ----------------------- Opcode decoding ------------------------- + +; Lookup table for Z80 opcodes. Translates the first byte of the instruction word into three +; operations: fetch, do something, store. +; The table is made of 256 words. + +; .org (PC+255) & 0xff00 + +;todo_table: +;opcjmp: +instr do_fetch_nop, op_nop, do_store_nop ;00 ;NOP +instr do_fetch_DIR16, op_nop, do_store_BC ;01 nn nn ;LD BC,nn +instr do_fetch_A, op_nop, do_store_MBC ;02 ;LD (BC),A +instr do_fetch_BC, op_INC16, do_store_BC ;03 ;INC BC +instr do_fetch_B, op_INC, do_store_B ;04 ;INC B +instr do_fetch_B, op_DEC, do_store_B ;05 ;DEC B +instr do_fetch_DIR8, op_nop, do_store_B ;06 ;LD B,n +instr do_fetch_A, op_RLC, do_store_A ;07 ;RLCA +instr do_fetch_nop, op_INV, do_store_nop ;08 ;EX AF,AF' +instr do_fetch_BC, op_ADDHL, do_store_HL ;09 ;ADD HL,BC +instr do_fetch_MBC, op_nop, do_store_A ;0A ;LD A,(BC) +instr do_fetch_BC, op_DEC16, do_store_BC ;0B ;DEC BC +instr do_fetch_C, op_INC, do_store_C ;0C ;INC C +instr do_fetch_C, op_DEC, do_store_C ;0D ;DEC C +instr do_fetch_DIR8, op_nop, do_store_C ;0E nn ;LD C,n +instr do_fetch_A, op_RRC, do_store_A ;0F ;RRCA +instr do_fetch_nop, op_INV, do_store_nop ;10 oo ;DJNZ o +instr do_fetch_DIR16, op_nop, do_store_DE ;11 nn nn ;LD DE,nn +instr do_fetch_A, op_nop, do_store_MDE ;12 ;LD (DE),A +instr do_fetch_DE, op_INC16, do_store_DE ;13 ;INC DE +instr do_fetch_D, op_INC, do_store_D ;14 ;INC D +instr do_fetch_D, op_DEC, do_store_D ;15 ;DEC D +instr do_fetch_DIR8, op_nop, do_store_D ;16 nn ;LD D,n +instr do_fetch_A, op_RL, do_store_A ;17 ;RLA +instr do_fetch_nop, op_INV, do_store_nop ;18 oo ;JR o +instr do_fetch_DE, op_ADDHL, do_store_HL ;19 ;ADD HL,DE +instr do_fetch_MDE, op_nop, do_store_A ;1A ;LD A,(DE) +instr do_fetch_DE, op_DEC16, do_store_DE ;1B ;DEC DE +instr do_fetch_E, op_INC, do_store_E ;1C ;INC E +instr do_fetch_E, op_DEC, do_store_E ;1D ;DEC E +instr do_fetch_DIR8, op_nop, do_store_E ;1E nn ;LD E,n +instr do_fetch_A, op_RR, do_store_A ;1F ;RRA +instr do_fetch_nop, op_INV, do_store_nop ;20 oo ;JR NZ,o +instr do_fetch_DIR16, op_nop, do_store_HL ;21 nn nn ;LD HL,nn +instr do_fetch_DIR16, op_STHL, do_store_nop ;22 nn nn ;LD (nn),HL +instr do_fetch_HL, op_INC16, do_store_HL ;23 ;INC HL +instr do_fetch_H, op_INC, do_store_H ;24 ;INC H +instr do_fetch_H, op_DEC, do_store_H ;25 ;DEC H +instr do_fetch_DIR8, op_nop, do_store_H ;26 nn ;LD H,n +instr do_fetch_A, op_DA, do_store_A ;27 ;DAA +instr do_fetch_nop, op_INV, do_store_nop ;28 oo ;JR Z,o +instr do_fetch_HL, op_ADDHL, do_store_HL ;29 ;ADD HL,HL +instr do_fetch_DIR16, op_RMEM16, do_store_HL ;2A nn nn ;LD HL,(nn) +instr do_fetch_HL, op_DEC16, do_store_HL ;2B ;DEC HL +instr do_fetch_L, op_INC, do_store_L ;2C ;INC L +instr do_fetch_L, op_DEC, do_store_L ;2D ;DEC L +instr do_fetch_DIR8, op_nop, do_store_L ;2E nn ;LD L,n +instr do_fetch_nop, op_CPL, do_store_nop ;2F ;CPL +instr do_fetch_nop, op_INV, do_store_nop ;30 oo ;JR NC,o +instr do_fetch_DIR16, op_nop, do_store_SP ;31 nn nn ;LD SP,nn +instr do_fetch_DIR16, op_nop, do_store_AM ;32 nn nn ;LD (nn),A +instr do_fetch_SP, op_INC16, do_store_SP ;33 ;INC SP +instr do_fetch_MHL, op_INC, do_store_MHL ;34 ;INC (HL) +instr do_fetch_MHL, op_DEC, do_store_MHL ;35 ;DEC (HL) +instr do_fetch_DIR8, op_nop, do_store_MHL ;36 nn ;LD (HL),n +instr do_fetch_nop, op_SCF, do_store_nop ;37 ;SCF +instr do_fetch_nop, op_INV, do_store_nop ;38 oo ;JR C,o +instr do_fetch_SP, op_ADDHL, do_store_HL ;39 ;ADD HL,SP +instr do_fetch_DIR16, op_RMEM8, do_store_A ;3A nn nn ;LD A,(nn) +instr do_fetch_SP, op_DEC16, do_store_SP ;3B ;DEC SP +instr do_fetch_nop, op_INCA, do_store_nop ;3C ;INC A +instr do_fetch_nop, op_DECA, do_store_nop ;3D ;DEC A +instr do_fetch_DIR8, op_nop, do_store_A ;3E nn ;LD A,n +instr do_fetch_nop, op_CCF, do_store_nop ;3F ;CCF (Complement Carry Flag, gvd) +instr do_fetch_B, op_nop, do_store_B ;40 ;LD B,B +instr do_fetch_C, op_nop, do_store_B ;41 ;LD B,C +instr do_fetch_D, op_nop, do_store_B ;42 ;LD B,D +instr do_fetch_E, op_nop, do_store_B ;43 ;LD B,E +instr do_fetch_H, op_nop, do_store_B ;44 ;LD B,H +instr do_fetch_L, op_nop, do_store_B ;45 ;LD B,L +instr do_fetch_MHL, op_nop, do_store_B ;46 ;LD B,(HL) +instr do_fetch_A, op_nop, do_store_B ;47 ;LD B,A +instr do_fetch_B, op_nop, do_store_C ;48 ;LD C,B +instr do_fetch_C, op_nop, do_store_C ;49 ;LD C,C +instr do_fetch_D, op_nop, do_store_C ;4A ;LD C,D +instr do_fetch_E, op_nop, do_store_C ;4B ;LD C,E +instr do_fetch_H, op_nop, do_store_C ;4C ;LD C,H +instr do_fetch_L, op_nop, do_store_C ;4D ;LD C,L +instr do_fetch_MHL, op_nop, do_store_C ;4E ;LD C,(HL) +instr do_fetch_A, op_nop, do_store_C ;4F ;LD C,A +instr do_fetch_B, op_nop, do_store_D ;50 ;LD D,B +instr do_fetch_C, op_nop, do_store_D ;51 ;LD D,C +instr do_fetch_D, op_nop, do_store_D ;52 ;LD D,D +instr do_fetch_E, op_nop, do_store_D ;53 ;LD D,E +instr do_fetch_H, op_nop, do_store_D ;54 ;LD D,H +instr do_fetch_L, op_nop, do_store_D ;55 ;LD D,L +instr do_fetch_MHL, op_nop, do_store_D ;56 ;LD D,(HL) +instr do_fetch_A, op_nop, do_store_D ;57 ;LD D,A +instr do_fetch_B, op_nop, do_store_E ;58 ;LD E,B +instr do_fetch_C, op_nop, do_store_E ;59 ;LD E,C +instr do_fetch_D, op_nop, do_store_E ;5A ;LD E,D +instr do_fetch_E, op_nop, do_store_E ;5B ;LD E,E +instr do_fetch_H, op_nop, do_store_E ;5C ;LD E,H +instr do_fetch_L, op_nop, do_store_E ;5D ;LD E,L +instr do_fetch_MHL, op_nop, do_store_E ;5E ;LD E,(HL) +instr do_fetch_A, op_nop, do_store_E ;5F ;LD E,A +instr do_fetch_B, op_nop, do_store_H ;60 ;LD H,B +instr do_fetch_C, op_nop, do_store_H ;61 ;LD H,C +instr do_fetch_D, op_nop, do_store_H ;62 ;LD H,D +instr do_fetch_E, op_nop, do_store_H ;63 ;LD H,E +instr do_fetch_H, op_nop, do_store_H ;64 ;LD H,H +instr do_fetch_L, op_nop, do_store_H ;65 ;LD H,L +instr do_fetch_MHL, op_nop, do_store_H ;66 ;LD H,(HL) +instr do_fetch_A, op_nop, do_store_H ;67 ;LD H,A +instr do_fetch_B, op_nop, do_store_L ;68 ;LD L,B +instr do_fetch_C, op_nop, do_store_L ;69 ;LD L,C +instr do_fetch_D, op_nop, do_store_L ;6A ;LD L,D +instr do_fetch_E, op_nop, do_store_L ;6B ;LD L,E +instr do_fetch_H, op_nop, do_store_L ;6C ;LD L,H +instr do_fetch_L, op_nop, do_store_L ;6D ;LD L,L +instr do_fetch_MHL, op_nop, do_store_L ;6E ;LD L,(HL) +instr do_fetch_A, op_nop, do_store_L ;6F ;LD L,A +instr do_fetch_B, op_nop, do_store_MHL ;70 ;LD (HL),B +instr do_fetch_C, op_nop, do_store_MHL ;71 ;LD (HL),C +instr do_fetch_D, op_nop, do_store_MHL ;72 ;LD (HL),D +instr do_fetch_E, op_nop, do_store_MHL ;73 ;LD (HL),E +instr do_fetch_H, op_nop, do_store_MHL ;74 ;LD (HL),H +instr do_fetch_L, op_nop, do_store_MHL ;75 ;LD (HL),L +instr do_fetch_nop, op_INV, do_store_nop ;76 ;HALT +instr do_fetch_A, op_nop, do_store_MHL ;77 ;LD (HL),A +instr do_fetch_B, op_nop, do_store_A ;78 ;LD A,B +instr do_fetch_C, op_nop, do_store_A ;79 ;LD A,C +instr do_fetch_D, op_nop, do_store_A ;7A ;LD A,D +instr do_fetch_E, op_nop, do_store_A ;7B ;LD A,E +instr do_fetch_H, op_nop, do_store_A ;7C ;LD A,H +instr do_fetch_L, op_nop, do_store_A ;7D ;LD A,L +instr do_fetch_MHL, op_nop, do_store_A ;7E ;LD A,(HL) +instr do_fetch_A, op_nop, do_store_A ;7F ;LD A,A +instr do_fetch_B, op_ADDA, do_store_nop ;80 ;ADD A,B +instr do_fetch_C, op_ADDA, do_store_nop ;81 ;ADD A,C +instr do_fetch_D, op_ADDA, do_store_nop ;82 ;ADD A,D +instr do_fetch_E, op_ADDA, do_store_nop ;83 ;ADD A,E +instr do_fetch_H, op_ADDA, do_store_nop ;84 ;ADD A,H +instr do_fetch_L, op_ADDA, do_store_nop ;85 ;ADD A,L +instr do_fetch_MHL, op_ADDA, do_store_nop ;86 ;ADD A,(HL) +instr do_fetch_A, op_ADDA, do_store_nop ;87 ;ADD A,A +instr do_fetch_B, op_ADCA, do_store_nop ;88 ;ADC A,B +instr do_fetch_C, op_ADCA, do_store_nop ;89 ;ADC A,C +instr do_fetch_D, op_ADCA, do_store_nop ;8A ;ADC A,D +instr do_fetch_E, op_ADCA, do_store_nop ;8B ;ADC A,E +instr do_fetch_H, op_ADCA, do_store_nop ;8C ;ADC A,H +instr do_fetch_L, op_ADCA, do_store_nop ;8D ;ADC A,L +instr do_fetch_MHL, op_ADCA, do_store_nop ;8E ;ADC A,(HL) +instr do_fetch_A, op_ADCA, do_store_nop ;8F ;ADC A,A +instr do_fetch_B, op_SUBFA, do_store_nop ;90 ;SUB A,B +instr do_fetch_C, op_SUBFA, do_store_nop ;91 ;SUB A,C +instr do_fetch_D, op_SUBFA, do_store_nop ;92 ;SUB A,D +instr do_fetch_E, op_SUBFA, do_store_nop ;93 ;SUB A,E +instr do_fetch_H, op_SUBFA, do_store_nop ;94 ;SUB A,H +instr do_fetch_L, op_SUBFA, do_store_nop ;95 ;SUB A,L +instr do_fetch_MHL, op_SUBFA, do_store_nop ;96 ;SUB A,(HL) +instr do_fetch_A, op_SUBFA, do_store_nop ;97 ;SUB A,A +instr do_fetch_B, op_SBCFA, do_store_nop ;98 ;SBC A,B +instr do_fetch_C, op_SBCFA, do_store_nop ;99 ;SBC A,C +instr do_fetch_D, op_SBCFA, do_store_nop ;9A ;SBC A,D +instr do_fetch_E, op_SBCFA, do_store_nop ;9B ;SBC A,E +instr do_fetch_H, op_SBCFA, do_store_nop ;9C ;SBC A,H +instr do_fetch_L, op_SBCFA, do_store_nop ;9D ;SBC A,L +instr do_fetch_MHL, op_SBCFA, do_store_nop ;9E ;SBC A,(HL) +instr do_fetch_A, op_SBCFA, do_store_nop ;9F ;SBC A,A +instr do_fetch_B, op_ANDA, do_store_nop ;A0 ;AND A,B +instr do_fetch_C, op_ANDA, do_store_nop ;A1 ;AND A,C +instr do_fetch_D, op_ANDA, do_store_nop ;A2 ;AND A,D +instr do_fetch_E, op_ANDA, do_store_nop ;A3 ;AND A,E +instr do_fetch_H, op_ANDA, do_store_nop ;A4 ;AND A,H +instr do_fetch_L, op_ANDA, do_store_nop ;A5 ;AND A,L +instr do_fetch_MHL, op_ANDA, do_store_nop ;A6 ;AND A,(HL) +instr do_fetch_A, op_ANDA, do_store_nop ;A7 ;AND A,A +instr do_fetch_B, op_XORA, do_store_nop ;A8 ;XOR A,B +instr do_fetch_C, op_XORA, do_store_nop ;A9 ;XOR A,C +instr do_fetch_D, op_XORA, do_store_nop ;AA ;XOR A,D +instr do_fetch_E, op_XORA, do_store_nop ;AB ;XOR A,E +instr do_fetch_H, op_XORA, do_store_nop ;AC ;XOR A,H +instr do_fetch_L, op_XORA, do_store_nop ;AD ;XOR A,L +instr do_fetch_MHL, op_XORA, do_store_nop ;AE ;XOR A,(HL) +instr do_fetch_A, op_XORA, do_store_nop ;AF ;XOR A,A +instr do_fetch_B, op_ORA, do_store_nop ;B0 ;OR A,B +instr do_fetch_C, op_ORA, do_store_nop ;B1 ;OR A,C +instr do_fetch_D, op_ORA, do_store_nop ;B2 ;OR A,D +instr do_fetch_E, op_ORA, do_store_nop ;B3 ;OR A,E +instr do_fetch_H, op_ORA, do_store_nop ;B4 ;OR A,H +instr do_fetch_L, op_ORA, do_store_nop ;B5 ;OR A,L +instr do_fetch_MHL, op_ORA, do_store_nop ;B6 ;OR A,(HL) +instr do_fetch_A, op_ORA, do_store_nop ;B7 ;OR A,A +instr do_fetch_B, op_CPFA, do_store_nop ;B8 ;CP A,B +instr do_fetch_C, op_CPFA, do_store_nop ;B9 ;CP A,C +instr do_fetch_D, op_CPFA, do_store_nop ;BA ;CP A,D +instr do_fetch_E, op_CPFA, do_store_nop ;BB ;CP A,E +instr do_fetch_H, op_CPFA, do_store_nop ;BC ;CP A,H +instr do_fetch_L, op_CPFA, do_store_nop ;BD ;CP A,L +instr do_fetch_MHL, op_CPFA, do_store_nop ;BE ;CP A,(HL) +instr do_fetch_A, op_CPFA, do_store_nop ;BF ;CP A,A +instr do_fetch_nop, op_IFNZ, do_store_RET ;C0 ;RET NZ +instr do_fetch_nop, op_POP16, do_store_BC ;C1 ;POP BC +instr do_fetch_DIR16, op_IFNZ, do_store_PC ;C2 nn nn ;JP NZ,nn +instr do_fetch_DIR16, op_nop, do_store_PC ;C3 nn nn ;JP nn +instr do_fetch_DIR16, op_IFNZ, do_store_CALL ;C4 nn nn ;CALL NZ,nn +instr do_fetch_BC, op_PUSH16, do_store_nop ;C5 ;PUSH BC +instr do_fetch_DIR8, op_ADDA, do_store_nop ;C6 nn ;ADD A,n +instr do_fetch_RST, op_nop, do_store_CALL ;C7 ;RST 0 +instr do_fetch_nop, op_IFZ, do_store_RET ;C8 ;RET Z +instr do_fetch_nop, op_nop, do_store_RET ;C9 ;RET +instr do_fetch_DIR16, op_IFZ, do_store_PC ;CA nn nn ;JP Z,nn +instr do_fetch_nop, op_INV, do_store_nop ;CB ;(Z80 specific) +instr do_fetch_DIR16, op_IFZ, do_store_CALL ;CC nn nn ;CALL Z,nn +instr do_fetch_DIR16, op_nop, do_store_CALL ;CD nn nn ;CALL nn +instr do_fetch_DIR8, op_ADCA, do_store_nop ;CE nn ;ADC A,n +instr do_fetch_RST, op_nop, do_store_CALL ;CF ;RST 8H +instr do_fetch_nop, op_IFNC, do_store_RET ;D0 ;RET NC +instr do_fetch_nop, op_POP16, do_store_DE ;D1 ;POP DE +instr do_fetch_DIR16, op_IFNC, do_store_PC ;D2 nn nn ;JP NC,nn +instr do_fetch_DIR8, op_OUTA, do_store_nop ;D3 nn ;OUT (n),A +instr do_fetch_DIR16, op_IFNC, do_store_CALL ;D4 nn nn ;CALL NC,nn +instr do_fetch_DE, op_PUSH16, do_store_nop ;D5 ;PUSH DE +instr do_fetch_DIR8, op_SUBFA, do_store_nop ;D6 nn ;SUB n +instr do_fetch_RST, op_nop, do_store_CALL ;D7 ;RST 10H +instr do_fetch_nop, op_IFC, do_store_RET ;D8 ;RET C +instr do_fetch_nop, op_nop, do_store_nop ;D9 ;EXX +instr do_fetch_DIR16, op_IFC, do_store_PC ;DA nn nn ;JP C,nn +instr do_fetch_DIR8, op_IN, do_store_A ;DB nn ;IN A,(n) +instr do_fetch_DIR16, op_IFC, do_store_CALL ;DC nn nn ;CALL C,nn +instr do_fetch_nop, op_INV, do_store_nop ;DD ;(Z80 specific) +instr do_fetch_DIR8, op_SBCFA, do_store_nop ;DE nn ;SBC A,n +instr do_fetch_RST, op_nop, do_store_CALL ;DF ;RST 18H +instr do_fetch_nop, op_IFPO, do_store_RET ;E0 ;RET PO +instr do_fetch_nop, op_POP16, do_store_HL ;E1 ;POP HL +instr do_fetch_DIR16, op_IFPO, do_store_PC ;E2 nn nn ;JP PO,nn +instr do_fetch_MSP, op_EXHL, do_store_MSP ;E3 ;EX (SP),HL +instr do_fetch_DIR16, op_IFPO, do_store_CALL ;E4 nn nn ;CALL PO,nn +instr do_fetch_HL, op_PUSH16, do_store_nop ;E5 ;PUSH HL +instr do_fetch_DIR8, op_ANDA, do_store_nop ;E6 nn ;AND n +instr do_fetch_RST, op_nop, do_store_CALL ;E7 ;RST 20H +instr do_fetch_nop, op_IFPE, do_store_RET ;E8 ;RET PE +instr do_fetch_HL, op_nop, do_store_PC ;E9 ;JP HL +instr do_fetch_DIR16, op_IFPE, do_store_PC ;EA nn nn ;JP PE,nn +instr do_fetch_DE, op_EXHL, do_store_DE ;EB ;EX DE,HL +instr do_fetch_DIR16, op_IFPE, do_store_CALL ;EC nn nn ;CALL PE,nn +instr do_fetch_nop, op_INV, do_store_nop ;ED ;(Z80 specific) +instr do_fetch_DIR8, op_XORA, do_store_nop ;EE nn ;XOR n +instr do_fetch_RST, op_nop, do_store_CALL ;EF ;RST 28H +instr do_fetch_nop, op_IFP, do_store_RET ;F0 ;RET P +instr do_fetch_nop, op_POP16, do_store_AF ;F1 ;POP AF +instr do_fetch_DIR16, op_IFP, do_store_PC ;F2 nn nn ;JP P,nn +instr do_fetch_nop, op_DI, do_store_nop ;F3 ;DI +instr do_fetch_DIR16, op_IFP, do_store_CALL ;F4 nn nn ;CALL P,nn +instr do_fetch_AF, op_PUSH16, do_store_nop ;F5 ;PUSH AF +instr do_fetch_DIR8, op_ORA, do_store_nop ;F6 nn ;OR n +instr do_fetch_RST, op_nop, do_store_CALL ;F7 ;RST 30H +instr do_fetch_nop, op_IFM, do_store_RET ;F8 ;RET M +instr do_fetch_HL, op_nop, do_store_SP ;F9 ;LD SP,HL +instr do_fetch_DIR16, op_IFM, do_store_PC ;FA nn nn ;JP M,nn +instr do_fetch_nop, op_EI, do_store_nop ;FB ;EI +instr do_fetch_DIR16, op_IFM, do_store_CALL ;FC nn nn ;CALL M,nn +instr do_fetch_nop, op_INV, do_store_nop ;FD ;(Z80 specific) +instr do_fetch_DIR8, op_CPFA, do_store_nop ;FE nn ;CP n +instr do_fetch_RST, op_nop, do_store_CALL ;FF ;RST 38H + + +;---------------------------------------------------------------- +; Lookup table, stolen from z80ex, Z80 emulation library. +; http://z80ex.sourceforge.net/ + +; The S, Z, 5 and 3 bits and the parity of the lookup value + +; .org (PC+255) & 0xff00 + .org opcjmp + 256 +sz53p_tab: + .db 0x44,0x00,0x00,0x04,0x00,0x04,0x04,0x00 + .db 0x08,0x0c,0x0c,0x08,0x0c,0x08,0x08,0x0c + .db 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04 + .db 0x0c,0x08,0x08,0x0c,0x08,0x0c,0x0c,0x08 + .db 0x20,0x24,0x24,0x20,0x24,0x20,0x20,0x24 + .db 0x2c,0x28,0x28,0x2c,0x28,0x2c,0x2c,0x28 + .db 0x24,0x20,0x20,0x24,0x20,0x24,0x24,0x20 + .db 0x28,0x2c,0x2c,0x28,0x2c,0x28,0x28,0x2c + .db 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04 + .db 0x0c,0x08,0x08,0x0c,0x08,0x0c,0x0c,0x08 + .db 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00 + .db 0x08,0x0c,0x0c,0x08,0x0c,0x08,0x08,0x0c + .db 0x24,0x20,0x20,0x24,0x20,0x24,0x24,0x20 + .db 0x28,0x2c,0x2c,0x28,0x2c,0x28,0x28,0x2c + .db 0x20,0x24,0x24,0x20,0x24,0x20,0x20,0x24 + .db 0x2c,0x28,0x28,0x2c,0x28,0x2c,0x2c,0x28 + .db 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84 + .db 0x8c,0x88,0x88,0x8c,0x88,0x8c,0x8c,0x88 + .db 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80 + .db 0x88,0x8c,0x8c,0x88,0x8c,0x88,0x88,0x8c + .db 0xa4,0xa0,0xa0,0xa4,0xa0,0xa4,0xa4,0xa0 + .db 0xa8,0xac,0xac,0xa8,0xac,0xa8,0xa8,0xac + .db 0xa0,0xa4,0xa4,0xa0,0xa4,0xa0,0xa0,0xa4 + .db 0xac,0xa8,0xa8,0xac,0xa8,0xac,0xac,0xa8 + .db 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80 + .db 0x88,0x8c,0x8c,0x88,0x8c,0x88,0x88,0x8c + .db 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84 + .db 0x8c,0x88,0x88,0x8c,0x88,0x8c,0x8c,0x88 + .db 0xa0,0xa4,0xa4,0xa0,0xa4,0xa0,0xa0,0xa4 + .db 0xac,0xa8,0xa8,0xac,0xa8,0xac,0xac,0xa8 + .db 0xa4,0xa0,0xa0,0xa4,0xa0,0xa4,0xa4,0xa0 + .db 0xa8,0xac,0xac,0xa8,0xac,0xa8,0xa8,0xac + +; vim:set ts=8 noet nowrap + diff --git a/8080int-t3-jmp.asm b/8080int-t3-jmp.asm new file mode 100644 index 0000000..0b0bdd7 --- /dev/null +++ b/8080int-t3-jmp.asm @@ -0,0 +1,1810 @@ +; 8080 Interpreter. +; This is part of the Z80-CP/M emulator written by Sprite_tm. +; + +; Copyright (C) 2010 Sprite_tm +; Copyright (C) 2010 Leo C. +; Copyright (C) 2010 Horst S. + +; This file is part of avrcpm. +; +; avrcpm is free software: you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by +; the Free Software Foundation, either version 3 of the License, or +; (at your option) any later version. +; +; avrcpm is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with avrcpm. If not, see . +; +; $Id$ +; + + .dseg + +z_b: .byte 1 +z_c: .byte 1 +z_d: .byte 1 +z_e: .byte 1 +z_h: .byte 1 +z_l: .byte 1 + + + .cseg + +;Init z80 +z80_init: + ldi z_pcl,low (IPLADDR) + ldi z_pch,high(IPLADDR) + + cbi flags,trace + printnewline + printstring "Ok, CPU is live!" + printnewline + + +main: +.if INS_DEBUG + cbi flags,trace + cpi z_pch,DBG_TRACE_BOTTOM + brlo notraceon + cpi z_pch,DBG_TRACE_TOP + brsh notraceon + sbi flags,trace +notraceon: +.endif + + +.if PRINT_PC + cpi z_pch,DBG_TRACE_BOTTOM + brlo noprintpc + cpi z_pch,DBG_TRACE_TOP + brsh noprintpc + + printnewline + printstring "PC=" + movw temp,z_pcl + rcall printhexw + printstring " " +noprintpc: +.endif + +.if INS_DEBUG + sbic flags,trace + rcall printregs +.endif + + ;hier kommt die Interruptbehandlung rein + + mem_read_s z_pc ;temp=memReadByte(z_pc) + adiw z_pcl,1 ;++z_pc + ldi zl,low(todo_table*2) ;zhl=todo_table + ldi zh,high(todo_table*2) ; + ldi temp2,3 ;1 + mul temp,temp2 ;2 + add zl,r0 ;1 + adc zh,r1 ;1 + lpm insdecl,Z+ ;do_store + lpm insdech,Z+ ;do_op + lpm zl,Z ;do_fetch + ldi zh,high(fetch_ops) + ijmp ;direkt + + +; .listmac +;----------------------------------------------------- +; Generate jump to target and position in table +; gen_opjmp target +; +.macro gen_opjmp + .ifndef opjmp_table_pos_ + .set opjmp_table_page_ = high(PC) + .set opjmp_table_pos_ = PC + .endif + .equ @0 = low(opjmp_table_pos_) + .set opjmp_table_pos_ = opjmp_table_pos_ + 1 + .if high(opjmp_table_pos_) != opjmp_table_page_ + .warning "Table 'opjump' crosses page boarder." + .message "Program will not work, unless the opjump table is relocated." + .endif + rjmp do_@0 + .endm + +;-------------------------------------------------- +; Generate a table entry for one instruction +; +; instr fetch, op, store +; +.macro instr + .ifndef inst_table_odd_ + .set inst_table_odd_ = 0 + .endif + + .if inst_table_odd_ + .db inst_table_next_, low(@2), @1, low(@0) + .set inst_table_odd_ = 0 + .else + .set inst_table_next_ = low(@0) + .db low(@2), @1 + .set inst_table_odd_ = 1 + .endif +.endm + +;----------------------------------- +; go to op. +; +.macro fetch_end + ldi zh,high(opjumps) + mov zl,insdech + ijmp +.endm + +;----------------------------------- +; go to store. +; +.macro op_end + ldi zh,high(store_ops) ; + mov zl,insdecl + ijmp +.endm + +;----------------------------------- +; go back to main +; +.macro store_end + rjmp main +.endm + +;----------------------------------- +; go back to main directly +; +.macro op_end_nojmp + rjmp main +.endm + + +; ------------ Fetch phase stuff ----------------- + +.org (PC+255) & 0xff00 +fetch_ops: +do_fetch_nop: + fetch_end + +do_fetch_a: + mov opl,z_a + fetch_end + +do_fetch_b: + lds opl,z_b + fetch_end + +do_fetch_c: + lds opl,z_c + fetch_end + +do_fetch_d: + lds opl,z_d + fetch_end + +do_fetch_e: + lds opl,z_e + fetch_end + +do_fetch_h: + lds opl,z_h + fetch_end + +do_fetch_l: + lds opl,z_l + fetch_end + +do_fetch_af: + mov opl,z_flags + mov oph,z_a + fetch_end + +do_fetch_bc: + lds opl,z_c + lds oph,z_b + fetch_end + +do_fetch_de: + lds opl,z_e + lds oph,z_d + fetch_end + +do_fetch_hl: + lds opl,z_l + lds oph,z_h + fetch_end + +do_fetch_sp: + movw opl,z_spl + fetch_end + +do_fetch_mbc: + lds xh,z_b + lds xl,z_c + mem_read_d opl + fetch_end + +do_fetch_mde: + lds xh,z_d + lds xl,z_e + mem_read_d opl + fetch_end + +do_fetch_mhl: + lds xh,z_h + lds xl,z_l + mem_read_d opl + fetch_end + +do_fetch_msp: + movw x,z_spl + mem_read_d opl + adiw x,1 + mem_read_d oph + fetch_end + +do_fetch_dir8: + mem_read_ds opl, z_pc + adiw z_pcl,1 + fetch_end + +do_fetch_dir16: + mem_read_ds opl, z_pc + adiw z_pcl,1 + mem_read_ds oph, z_pc + adiw z_pcl,1 + fetch_end + +do_fetch_rst: + movw x,z_pcl + sbiw x,1 + mem_read_d opl + andi opl,0x38 + ldi oph,0 + fetch_end + +; ------------ Store phase stuff ----------------- + +.org (PC+255) & 0xff00 +store_ops: +do_store_nop: + store_end + +do_store_a: + mov z_a,opl + store_end + +do_store_b: + sts z_b,opl + store_end + +do_store_c: + sts z_c,opl + store_end + +do_store_d: + sts z_d,opl + store_end + +do_store_e: + sts z_e,opl + store_end + +do_store_h: + sts z_h,opl + store_end + +do_store_l: + sts z_l,opl + store_end + +do_store_af: + mov z_a,oph + mov z_flags,opl + store_end + +do_store_bc: + sts z_b,oph + sts z_c,opl + store_end + +do_store_de: + sts z_d,oph + sts z_e,opl + store_end + +do_store_hl: + sts z_h,oph + sts z_l,opl + store_end + +do_store_mbc: + lds xh,z_b + lds xl,z_c + mem_write_s opl + store_end + +do_store_mde: + lds xh,z_d + lds xl,z_e + mem_write_s opl + store_end + +do_store_mhl: + lds xh,z_h + lds xl,z_l + mem_write_s opl + store_end + +do_store_msp: + movw xl,z_spl + mem_write_s opl + adiw xl,1 + mem_write_s oph + store_end + +do_store_sp: + movw z_spl,opl + store_end + +do_store_pc: + movw z_pcl,opl + store_end + +do_store_ret: + movw x,z_spl + mem_read_d z_pcl + adiw x,1 + mem_read_d z_pch + adiw x,1 + movw z_spl,x + +.if STACK_DBG + printnewline + printstring "Stack pop " + movw temp,z_pcl + rcall printhexw + printstring ", SP is now " + movw temp,z_spl + rcall printhexw + printstring ". " +.endif + store_end + +do_store_call: + movw xl,z_spl + sbiw x,1 + mem_write_s z_pch + sbiw x,1 + mem_write_s z_pcl + movw z_spl,xl + +.if STACK_DBG + printnewline + printstring "Stack push " + movw temp,z_pcl + rcall printhexw + printstring ", SP is now " + movw temp,z_spl + rcall printhexw + printstring ". " +.endif + movw z_pcl,opl + store_end + + +do_store_am: + mem_write_ds op, z_a + store_end + + + +; ------------ Operation phase stuff ----------------- + +;.org (PC+255) & 0xff00 + +opjumps: + gen_opjmp op_nop + gen_opjmp op_inc + gen_opjmp op_dec + gen_opjmp op_inc16 + gen_opjmp op_dec16 + gen_opjmp op_rlc + gen_opjmp op_rrc + gen_opjmp op_rr + gen_opjmp op_rl + gen_opjmp op_adda + gen_opjmp op_adca + gen_opjmp op_subfa + gen_opjmp op_sbcfa + gen_opjmp op_anda + gen_opjmp op_ora + gen_opjmp op_xora + gen_opjmp op_addhl + gen_opjmp op_sthl + gen_opjmp op_rmem16 + gen_opjmp op_rmem8 + gen_opjmp op_da + gen_opjmp op_scf + gen_opjmp op_cpl + gen_opjmp op_ccf + gen_opjmp op_pop16 + gen_opjmp op_push16 + gen_opjmp op_ifnz + gen_opjmp op_ifz + gen_opjmp op_ifnc + gen_opjmp op_ifc + gen_opjmp op_ifpo + gen_opjmp op_ifpe + gen_opjmp op_ifp + gen_opjmp op_ifm + gen_opjmp op_outa + gen_opjmp op_in + gen_opjmp op_exhl + gen_opjmp op_di + gen_opjmp op_ei + gen_opjmp op_inv + gen_opjmp op_cpfa + gen_opjmp op_inca + gen_opjmp op_deca + + + +;---------------------------------------------------------------- +;| | +;| 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 | +;|----------+------+--------------------------------------------| +;| 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 | +;---------------------------------------------------------------- + +;How the flags are supposed to work: +;7 ZFL_S - Sign flag (=MSBit of result) +;6 ZFL_Z - Zero flag. Is 1 when the result is 0 +;4 ZFL_H - Half-carry (carry from bit 3 to 4) +;2 ZFL_P - Parity/2-complement Overflow +;1 ZFL_N - Subtract - set if last op was a subtract +;0 ZFL_C - Carry +; +;I sure hope I got the mapping between flags and instructions correct... + +.equ ZFL_S = 7 +.equ ZFL_Z = 6 +.equ ZFL_H = 4 +.equ ZFL_P = 2 +.equ ZFL_N = 1 +.equ ZFL_C = 0 + + +.equ AVR_T = SREG_T +.equ AVR_H = SREG_H +.equ AVR_S = SREG_S +.equ AVR_V = SREG_V +.equ AVR_N = SREG_N +.equ AVR_Z = SREG_Z +.equ AVR_C = SREG_C + +;------------------------------------------------; +; 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< (" + mov temp,opl + rcall printhex + printstring ") " +.endif + mov temp,z_a + mov temp2,opl + rcall portWrite + op_end + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +;|IN A,[n] |------|Input |A=[n] | +; +; +do_op_in: ; in a,(opl) +.if PORT_DEBUG + printnewline + printstring "Port read: (" + mov temp,opl + rcall printhex + printstring ") -> " +.endif + + mov temp2,opl + rcall portRead + mov opl,temp + +.if PORT_DEBUG + rcall printhex + printstring " " +.endif + op_end + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +;|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 | +; +; +do_op_inc: + inc opl +#if EM_Z80 + in temp, sreg +#endif + andi z_flags,(1<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. + do_z80_flags_op_rotate + lsr opl + brcc do_op_rrc_noc + ori opl, 0x80 + ori z_flags, (1<{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 ; 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 + op_end + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +;|RLA |--0-0*|Rotate Left Acc. |A={CY,A}<- | +;|----------|SZHP C|---------- 8080 ----------------------------| +;|RLA |---- *|Rotate Left Acc. |A={CY,A}<- | +; +; +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 + op_end + +;---------------------------------------------------------------- +;|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: + add z_a,opl + in temp,sreg + ldpmx z_flags,sz53p_tab,z_a ;S,Z,P flag + bmov z_flags,ZFL_C, temp,AVR_C + do_z80_flags_HP + op_end + +;---------------------------------------------------------------- +;|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 | +; +; +do_op_adca: + clc + sbrc z_flags,ZFL_C + sec + adc z_a,opl + in temp,sreg + ldpmx z_flags,sz53p_tab,z_a ;S,Z,P + bmov z_flags,ZFL_C, temp,AVR_C + do_z80_flags_HP + op_end + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +;|SUB s |***V1*|Subtract |A=A-s | +;|----------|SZHP C|---------- 8080 ----------------------------| +;|SUB s |***P *|Subtract |A=A-s | + +; +do_op_subfa: + sub z_a,opl + in temp,sreg + ldpmx z_flags,sz53p_tab,z_a ;S,Z,P + bmov z_flags,ZFL_C, temp,AVR_C + do_z80_flags_HP + do_z80_flags_set_N + op_end + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +;|CP s |***V1*|Compare |A-s | +;|----------|SZHP C|---------- 8080 ----------------------------| +;|CP s |***P *|Compare |A-s | + +; +do_op_cpfa: + mov temp,z_a + sub temp,opl + mov opl,temp + in temp,sreg + 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 + op_end + +;---------------------------------------------------------------- +;|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 | +; +; +do_op_sbcfa: + clc + sbrc z_flags,ZFL_C + sec + sbc z_a,opl + in temp,sreg + ldpmx z_flags,sz53p_tab,z_a ;S,Z,P + bmov z_flags,ZFL_C, temp,AVR_C + do_z80_flags_HP + do_z80_flags_set_N + op_end + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +;|AND s |**1P00|Logical AND |A=A&s | +;|----------|SZHP C|---------- 8080 ----------------------------| +;|AND s |**-P 0|Logical AND |A=A&s | +; +; TODO H-Flag +do_op_anda: + and z_a,opl ; + ldpmx z_flags,sz53p_tab,z_a ;S,Z,P,N,C + do_z80_flags_op_and + op_end + + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +;|OR s |**0P00|Logical inclusive OR |A=Avs | +;|----------|SZHP C|---------- 8080 ----------------------------| +;|OR s |**-P00|Logical inclusive OR |A=Avs | +; +; TODO: H-Flag +do_op_ora: + or z_a,opl + ldpmx z_flags,sz53p_tab,z_a ;S,Z,H,P,N,C + do_z80_flags_op_or + op_end + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +;|XOR s |**0P00|Logical Exclusive OR |A=Axs | +;|----------|SZHP C|---------- 8080 ----------------------------| +;|XOR s |**-P 0|Logical Exclusive OR |A=Axs | +; +; TODO: H-Flag +do_op_xora: + eor z_a,opl + ldpmx z_flags,sz53p_tab,z_a ;S,Z,H,P,N,C + do_z80_flags_op_or + op_end + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +;|ADD HL,ss |--?-0*|Add |HL=HL+ss | +;|----------|SZHP C|---------- 8080 ----------------------------| +;|ADD HL,ss |---- *|Add |HL=HL+ss | +; +; +do_op_addhl: + lds temp,z_l + lds temp2,z_h + add opl,temp + adc oph,temp2 + in temp,sreg + bmov z_flags,ZFL_H, temp,AVR_H + bmov z_flags,ZFL_C, temp,AVR_C + do_z80_flags_clear_N + op_end + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +;|LD dst,src|------|Load |dst=src | +; +; +do_op_sthl: ;store hl to mem loc in opl:h + movw xl,opl + lds temp,z_l + mem_write + adiw xl,1 + lds temp,z_h + mem_write + op_end + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +;|LD dst,src|------|Load |dst=src | +; +; +do_op_rmem16: + movw xl,opl + mem_read_d opl + adiw x,1 + mem_read_d oph + op_end + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +;|LD dst,src|------|Load |dst=src | +; +; +do_op_rmem8: + mem_read_ds opl, op + op_end + +;---------------------------------------------------------------- +;|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: + 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< 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 | +;-----------------------------Z80-------------------------------- +; +do_op_exhl: + lds temp,z_l + lds temp2,z_h + sts z_l,opl + sts z_h,oph + movw opl,temp + op_end + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +; +; TODO: Implement IFF1, IFF2 +do_op_di: + op_end + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +; +; TODO: Implement IFF1, IFF2 +do_op_ei: + op_end + +;---------------------------------------------------------------- +;|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: + sbrc z_flags, ZFL_Z + op_end_nojmp + op_end + +;---------------------------------------------------------------- +;|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: + sbrs z_flags, ZFL_Z + op_end_nojmp + op_end + +;---------------------------------------------------------------- +;|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: + sbrc z_flags, ZFL_C + op_end_nojmp + op_end + +;---------------------------------------------------------------- +;|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: + sbrs z_flags, ZFL_C + op_end_nojmp + op_end + +;---------------------------------------------------------------- +;|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: + sbrc z_flags, ZFL_P + op_end_nojmp + op_end + +;---------------------------------------------------------------- +;|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: + sbrs z_flags, ZFL_P + op_end_nojmp + op_end + +;---------------------------------------------------------------- +;|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 + sbrc z_flags, ZFL_S + op_end_nojmp + op_end + +;---------------------------------------------------------------- +;|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 + sbrs z_flags, ZFL_S + op_end_nojmp + op_end + + +; ----------------------- Opcode decoding ------------------------- + +; Lookup table for Z80 opcodes. Translates the first byte of the instruction word into three +; operations: fetch, do something, store. +; The table is made of 256 words. + +;.org (PC+255) & 0xff00 +todo_table: +instr do_fetch_nop, op_nop, do_store_nop ;00 ;NOP +instr do_fetch_DIR16, op_nop, do_store_BC ;01 nn nn ;LD BC,nn +instr do_fetch_A, op_nop, do_store_MBC ;02 ;LD (BC),A +instr do_fetch_BC, op_INC16, do_store_BC ;03 ;INC BC +instr do_fetch_B, op_INC, do_store_B ;04 ;INC B +instr do_fetch_B, op_DEC, do_store_B ;05 ;DEC B +instr do_fetch_DIR8, op_nop, do_store_B ;06 ;LD B,n +instr do_fetch_A, op_RLC, do_store_A ;07 ;RLCA +instr do_fetch_nop, op_INV, do_store_nop ;08 ;EX AF,AF' +instr do_fetch_BC, op_ADDHL, do_store_HL ;09 ;ADD HL,BC +instr do_fetch_MBC, op_nop, do_store_A ;0A ;LD A,(BC) +instr do_fetch_BC, op_DEC16, do_store_BC ;0B ;DEC BC +instr do_fetch_C, op_INC, do_store_C ;0C ;INC C +instr do_fetch_C, op_DEC, do_store_C ;0D ;DEC C +instr do_fetch_DIR8, op_nop, do_store_C ;0E nn ;LD C,n +instr do_fetch_A, op_RRC, do_store_A ;0F ;RRCA +instr do_fetch_nop, op_INV, do_store_nop ;10 oo ;DJNZ o +instr do_fetch_DIR16, op_nop, do_store_DE ;11 nn nn ;LD DE,nn +instr do_fetch_A, op_nop, do_store_MDE ;12 ;LD (DE),A +instr do_fetch_DE, op_INC16, do_store_DE ;13 ;INC DE +instr do_fetch_D, op_INC, do_store_D ;14 ;INC D +instr do_fetch_D, op_DEC, do_store_D ;15 ;DEC D +instr do_fetch_DIR8, op_nop, do_store_D ;16 nn ;LD D,n +instr do_fetch_A, op_RL, do_store_A ;17 ;RLA +instr do_fetch_nop, op_INV, do_store_nop ;18 oo ;JR o +instr do_fetch_DE, op_ADDHL, do_store_HL ;19 ;ADD HL,DE +instr do_fetch_MDE, op_nop, do_store_A ;1A ;LD A,(DE) +instr do_fetch_DE, op_DEC16, do_store_DE ;1B ;DEC DE +instr do_fetch_E, op_INC, do_store_E ;1C ;INC E +instr do_fetch_E, op_DEC, do_store_E ;1D ;DEC E +instr do_fetch_DIR8, op_nop, do_store_E ;1E nn ;LD E,n +instr do_fetch_A, op_RR, do_store_A ;1F ;RRA +instr do_fetch_nop, op_INV, do_store_nop ;20 oo ;JR NZ,o +instr do_fetch_DIR16, op_nop, do_store_HL ;21 nn nn ;LD HL,nn +instr do_fetch_DIR16, op_STHL, do_store_nop ;22 nn nn ;LD (nn),HL +instr do_fetch_HL, op_INC16, do_store_HL ;23 ;INC HL +instr do_fetch_H, op_INC, do_store_H ;24 ;INC H +instr do_fetch_H, op_DEC, do_store_H ;25 ;DEC H +instr do_fetch_DIR8, op_nop, do_store_H ;26 nn ;LD H,n +instr do_fetch_A, op_DA, do_store_A ;27 ;DAA +instr do_fetch_nop, op_INV, do_store_nop ;28 oo ;JR Z,o +instr do_fetch_HL, op_ADDHL, do_store_HL ;29 ;ADD HL,HL +instr do_fetch_DIR16, op_RMEM16, do_store_HL ;2A nn nn ;LD HL,(nn) +instr do_fetch_HL, op_DEC16, do_store_HL ;2B ;DEC HL +instr do_fetch_L, op_INC, do_store_L ;2C ;INC L +instr do_fetch_L, op_DEC, do_store_L ;2D ;DEC L +instr do_fetch_DIR8, op_nop, do_store_L ;2E nn ;LD L,n +instr do_fetch_nop, op_CPL, do_store_nop ;2F ;CPL +instr do_fetch_nop, op_INV, do_store_nop ;30 oo ;JR NC,o +instr do_fetch_DIR16, op_nop, do_store_SP ;31 nn nn ;LD SP,nn +instr do_fetch_DIR16, op_nop, do_store_AM ;32 nn nn ;LD (nn),A +instr do_fetch_SP, op_INC16, do_store_SP ;33 ;INC SP +instr do_fetch_MHL, op_INC, do_store_MHL ;34 ;INC (HL) +instr do_fetch_MHL, op_DEC, do_store_MHL ;35 ;DEC (HL) +instr do_fetch_DIR8, op_nop, do_store_MHL ;36 nn ;LD (HL),n +instr do_fetch_nop, op_SCF, do_store_nop ;37 ;SCF +instr do_fetch_nop, op_INV, do_store_nop ;38 oo ;JR C,o +instr do_fetch_SP, op_ADDHL, do_store_HL ;39 ;ADD HL,SP +instr do_fetch_DIR16, op_RMEM8, do_store_A ;3A nn nn ;LD A,(nn) +instr do_fetch_SP, op_DEC16, do_store_SP ;3B ;DEC SP +instr do_fetch_nop, op_INCA, do_store_nop ;3C ;INC A +instr do_fetch_nop, op_DECA, do_store_nop ;3D ;DEC A +instr do_fetch_DIR8, op_nop, do_store_A ;3E nn ;LD A,n +instr do_fetch_nop, op_CCF, do_store_nop ;3F ;CCF (Complement Carry Flag, gvd) +instr do_fetch_B, op_nop, do_store_B ;40 ;LD B,B +instr do_fetch_C, op_nop, do_store_B ;41 ;LD B,C +instr do_fetch_D, op_nop, do_store_B ;42 ;LD B,D +instr do_fetch_E, op_nop, do_store_B ;43 ;LD B,E +instr do_fetch_H, op_nop, do_store_B ;44 ;LD B,H +instr do_fetch_L, op_nop, do_store_B ;45 ;LD B,L +instr do_fetch_MHL, op_nop, do_store_B ;46 ;LD B,(HL) +instr do_fetch_A, op_nop, do_store_B ;47 ;LD B,A +instr do_fetch_B, op_nop, do_store_C ;48 ;LD C,B +instr do_fetch_C, op_nop, do_store_C ;49 ;LD C,C +instr do_fetch_D, op_nop, do_store_C ;4A ;LD C,D +instr do_fetch_E, op_nop, do_store_C ;4B ;LD C,E +instr do_fetch_H, op_nop, do_store_C ;4C ;LD C,H +instr do_fetch_L, op_nop, do_store_C ;4D ;LD C,L +instr do_fetch_MHL, op_nop, do_store_C ;4E ;LD C,(HL) +instr do_fetch_A, op_nop, do_store_C ;4F ;LD C,A +instr do_fetch_B, op_nop, do_store_D ;50 ;LD D,B +instr do_fetch_C, op_nop, do_store_D ;51 ;LD D,C +instr do_fetch_D, op_nop, do_store_D ;52 ;LD D,D +instr do_fetch_E, op_nop, do_store_D ;53 ;LD D,E +instr do_fetch_H, op_nop, do_store_D ;54 ;LD D,H +instr do_fetch_L, op_nop, do_store_D ;55 ;LD D,L +instr do_fetch_MHL, op_nop, do_store_D ;56 ;LD D,(HL) +instr do_fetch_A, op_nop, do_store_D ;57 ;LD D,A +instr do_fetch_B, op_nop, do_store_E ;58 ;LD E,B +instr do_fetch_C, op_nop, do_store_E ;59 ;LD E,C +instr do_fetch_D, op_nop, do_store_E ;5A ;LD E,D +instr do_fetch_E, op_nop, do_store_E ;5B ;LD E,E +instr do_fetch_H, op_nop, do_store_E ;5C ;LD E,H +instr do_fetch_L, op_nop, do_store_E ;5D ;LD E,L +instr do_fetch_MHL, op_nop, do_store_E ;5E ;LD E,(HL) +instr do_fetch_A, op_nop, do_store_E ;5F ;LD E,A +instr do_fetch_B, op_nop, do_store_H ;60 ;LD H,B +instr do_fetch_C, op_nop, do_store_H ;61 ;LD H,C +instr do_fetch_D, op_nop, do_store_H ;62 ;LD H,D +instr do_fetch_E, op_nop, do_store_H ;63 ;LD H,E +instr do_fetch_H, op_nop, do_store_H ;64 ;LD H,H +instr do_fetch_L, op_nop, do_store_H ;65 ;LD H,L +instr do_fetch_MHL, op_nop, do_store_H ;66 ;LD H,(HL) +instr do_fetch_A, op_nop, do_store_H ;67 ;LD H,A +instr do_fetch_B, op_nop, do_store_L ;68 ;LD L,B +instr do_fetch_C, op_nop, do_store_L ;69 ;LD L,C +instr do_fetch_D, op_nop, do_store_L ;6A ;LD L,D +instr do_fetch_E, op_nop, do_store_L ;6B ;LD L,E +instr do_fetch_H, op_nop, do_store_L ;6C ;LD L,H +instr do_fetch_L, op_nop, do_store_L ;6D ;LD L,L +instr do_fetch_MHL, op_nop, do_store_L ;6E ;LD L,(HL) +instr do_fetch_A, op_nop, do_store_L ;6F ;LD L,A +instr do_fetch_B, op_nop, do_store_MHL ;70 ;LD (HL),B +instr do_fetch_C, op_nop, do_store_MHL ;71 ;LD (HL),C +instr do_fetch_D, op_nop, do_store_MHL ;72 ;LD (HL),D +instr do_fetch_E, op_nop, do_store_MHL ;73 ;LD (HL),E +instr do_fetch_H, op_nop, do_store_MHL ;74 ;LD (HL),H +instr do_fetch_L, op_nop, do_store_MHL ;75 ;LD (HL),L +instr do_fetch_nop, op_INV, do_store_nop ;76 ;HALT +instr do_fetch_A, op_nop, do_store_MHL ;77 ;LD (HL),A +instr do_fetch_B, op_nop, do_store_A ;78 ;LD A,B +instr do_fetch_C, op_nop, do_store_A ;79 ;LD A,C +instr do_fetch_D, op_nop, do_store_A ;7A ;LD A,D +instr do_fetch_E, op_nop, do_store_A ;7B ;LD A,E +instr do_fetch_H, op_nop, do_store_A ;7C ;LD A,H +instr do_fetch_L, op_nop, do_store_A ;7D ;LD A,L +instr do_fetch_MHL, op_nop, do_store_A ;7E ;LD A,(HL) +instr do_fetch_A, op_nop, do_store_A ;7F ;LD A,A +instr do_fetch_B, op_ADDA, do_store_nop ;80 ;ADD A,B +instr do_fetch_C, op_ADDA, do_store_nop ;81 ;ADD A,C +instr do_fetch_D, op_ADDA, do_store_nop ;82 ;ADD A,D +instr do_fetch_E, op_ADDA, do_store_nop ;83 ;ADD A,E +instr do_fetch_H, op_ADDA, do_store_nop ;84 ;ADD A,H +instr do_fetch_L, op_ADDA, do_store_nop ;85 ;ADD A,L +instr do_fetch_MHL, op_ADDA, do_store_nop ;86 ;ADD A,(HL) +instr do_fetch_A, op_ADDA, do_store_nop ;87 ;ADD A,A +instr do_fetch_B, op_ADCA, do_store_nop ;88 ;ADC A,B +instr do_fetch_C, op_ADCA, do_store_nop ;89 ;ADC A,C +instr do_fetch_D, op_ADCA, do_store_nop ;8A ;ADC A,D +instr do_fetch_E, op_ADCA, do_store_nop ;8B ;ADC A,E +instr do_fetch_H, op_ADCA, do_store_nop ;8C ;ADC A,H +instr do_fetch_L, op_ADCA, do_store_nop ;8D ;ADC A,L +instr do_fetch_MHL, op_ADCA, do_store_nop ;8E ;ADC A,(HL) +instr do_fetch_A, op_ADCA, do_store_nop ;8F ;ADC A,A +instr do_fetch_B, op_SUBFA, do_store_nop ;90 ;SUB A,B +instr do_fetch_C, op_SUBFA, do_store_nop ;91 ;SUB A,C +instr do_fetch_D, op_SUBFA, do_store_nop ;92 ;SUB A,D +instr do_fetch_E, op_SUBFA, do_store_nop ;93 ;SUB A,E +instr do_fetch_H, op_SUBFA, do_store_nop ;94 ;SUB A,H +instr do_fetch_L, op_SUBFA, do_store_nop ;95 ;SUB A,L +instr do_fetch_MHL, op_SUBFA, do_store_nop ;96 ;SUB A,(HL) +instr do_fetch_A, op_SUBFA, do_store_nop ;97 ;SUB A,A +instr do_fetch_B, op_SBCFA, do_store_nop ;98 ;SBC A,B +instr do_fetch_C, op_SBCFA, do_store_nop ;99 ;SBC A,C +instr do_fetch_D, op_SBCFA, do_store_nop ;9A ;SBC A,D +instr do_fetch_E, op_SBCFA, do_store_nop ;9B ;SBC A,E +instr do_fetch_H, op_SBCFA, do_store_nop ;9C ;SBC A,H +instr do_fetch_L, op_SBCFA, do_store_nop ;9D ;SBC A,L +instr do_fetch_MHL, op_SBCFA, do_store_nop ;9E ;SBC A,(HL) +instr do_fetch_A, op_SBCFA, do_store_nop ;9F ;SBC A,A +instr do_fetch_B, op_ANDA, do_store_nop ;A0 ;AND A,B +instr do_fetch_C, op_ANDA, do_store_nop ;A1 ;AND A,C +instr do_fetch_D, op_ANDA, do_store_nop ;A2 ;AND A,D +instr do_fetch_E, op_ANDA, do_store_nop ;A3 ;AND A,E +instr do_fetch_H, op_ANDA, do_store_nop ;A4 ;AND A,H +instr do_fetch_L, op_ANDA, do_store_nop ;A5 ;AND A,L +instr do_fetch_MHL, op_ANDA, do_store_nop ;A6 ;AND A,(HL) +instr do_fetch_A, op_ANDA, do_store_nop ;A7 ;AND A,A +instr do_fetch_B, op_XORA, do_store_nop ;A8 ;XOR A,B +instr do_fetch_C, op_XORA, do_store_nop ;A9 ;XOR A,C +instr do_fetch_D, op_XORA, do_store_nop ;AA ;XOR A,D +instr do_fetch_E, op_XORA, do_store_nop ;AB ;XOR A,E +instr do_fetch_H, op_XORA, do_store_nop ;AC ;XOR A,H +instr do_fetch_L, op_XORA, do_store_nop ;AD ;XOR A,L +instr do_fetch_MHL, op_XORA, do_store_nop ;AE ;XOR A,(HL) +instr do_fetch_A, op_XORA, do_store_nop ;AF ;XOR A,A +instr do_fetch_B, op_ORA, do_store_nop ;B0 ;OR A,B +instr do_fetch_C, op_ORA, do_store_nop ;B1 ;OR A,C +instr do_fetch_D, op_ORA, do_store_nop ;B2 ;OR A,D +instr do_fetch_E, op_ORA, do_store_nop ;B3 ;OR A,E +instr do_fetch_H, op_ORA, do_store_nop ;B4 ;OR A,H +instr do_fetch_L, op_ORA, do_store_nop ;B5 ;OR A,L +instr do_fetch_MHL, op_ORA, do_store_nop ;B6 ;OR A,(HL) +instr do_fetch_A, op_ORA, do_store_nop ;B7 ;OR A,A +instr do_fetch_B, op_CPFA, do_store_nop ;B8 ;CP A,B +instr do_fetch_C, op_CPFA, do_store_nop ;B9 ;CP A,C +instr do_fetch_D, op_CPFA, do_store_nop ;BA ;CP A,D +instr do_fetch_E, op_CPFA, do_store_nop ;BB ;CP A,E +instr do_fetch_H, op_CPFA, do_store_nop ;BC ;CP A,H +instr do_fetch_L, op_CPFA, do_store_nop ;BD ;CP A,L +instr do_fetch_MHL, op_CPFA, do_store_nop ;BE ;CP A,(HL) +instr do_fetch_A, op_CPFA, do_store_nop ;BF ;CP A,A +instr do_fetch_nop, op_IFNZ, do_store_RET ;C0 ;RET NZ +instr do_fetch_nop, op_POP16, do_store_BC ;C1 ;POP BC +instr do_fetch_DIR16, op_IFNZ, do_store_PC ;C2 nn nn ;JP NZ,nn +instr do_fetch_DIR16, op_nop, do_store_PC ;C3 nn nn ;JP nn +instr do_fetch_DIR16, op_IFNZ, do_store_CALL ;C4 nn nn ;CALL NZ,nn +instr do_fetch_BC, op_PUSH16, do_store_nop ;C5 ;PUSH BC +instr do_fetch_DIR8, op_ADDA, do_store_nop ;C6 nn ;ADD A,n +instr do_fetch_RST, op_nop, do_store_CALL ;C7 ;RST 0 +instr do_fetch_nop, op_IFZ, do_store_RET ;C8 ;RET Z +instr do_fetch_nop, op_nop, do_store_RET ;C9 ;RET +instr do_fetch_DIR16, op_IFZ, do_store_PC ;CA nn nn ;JP Z,nn +instr do_fetch_nop, op_INV, do_store_nop ;CB ;(Z80 specific) +instr do_fetch_DIR16, op_IFZ, do_store_CALL ;CC nn nn ;CALL Z,nn +instr do_fetch_DIR16, op_nop, do_store_CALL ;CD nn nn ;CALL nn +instr do_fetch_DIR8, op_ADCA, do_store_nop ;CE nn ;ADC A,n +instr do_fetch_RST, op_nop, do_store_CALL ;CF ;RST 8H +instr do_fetch_nop, op_IFNC, do_store_RET ;D0 ;RET NC +instr do_fetch_nop, op_POP16, do_store_DE ;D1 ;POP DE +instr do_fetch_DIR16, op_IFNC, do_store_PC ;D2 nn nn ;JP NC,nn +instr do_fetch_DIR8, op_OUTA, do_store_nop ;D3 nn ;OUT (n),A +instr do_fetch_DIR16, op_IFNC, do_store_CALL ;D4 nn nn ;CALL NC,nn +instr do_fetch_DE, op_PUSH16, do_store_nop ;D5 ;PUSH DE +instr do_fetch_DIR8, op_SUBFA, do_store_nop ;D6 nn ;SUB n +instr do_fetch_RST, op_nop, do_store_CALL ;D7 ;RST 10H +instr do_fetch_nop, op_IFC, do_store_RET ;D8 ;RET C +instr do_fetch_nop, op_nop, do_store_nop ;D9 ;EXX +instr do_fetch_DIR16, op_IFC, do_store_PC ;DA nn nn ;JP C,nn +instr do_fetch_DIR8, op_IN, do_store_A ;DB nn ;IN A,(n) +instr do_fetch_DIR16, op_IFC, do_store_CALL ;DC nn nn ;CALL C,nn +instr do_fetch_nop, op_INV, do_store_nop ;DD ;(Z80 specific) +instr do_fetch_DIR8, op_SBCFA, do_store_nop ;DE nn ;SBC A,n +instr do_fetch_RST, op_nop, do_store_CALL ;DF ;RST 18H +instr do_fetch_nop, op_IFPO, do_store_RET ;E0 ;RET PO +instr do_fetch_nop, op_POP16, do_store_HL ;E1 ;POP HL +instr do_fetch_DIR16, op_IFPO, do_store_PC ;E2 nn nn ;JP PO,nn +instr do_fetch_MSP, op_EXHL, do_store_MSP ;E3 ;EX (SP),HL +instr do_fetch_DIR16, op_IFPO, do_store_CALL ;E4 nn nn ;CALL PO,nn +instr do_fetch_HL, op_PUSH16, do_store_nop ;E5 ;PUSH HL +instr do_fetch_DIR8, op_ANDA, do_store_nop ;E6 nn ;AND n +instr do_fetch_RST, op_nop, do_store_CALL ;E7 ;RST 20H +instr do_fetch_nop, op_IFPE, do_store_RET ;E8 ;RET PE +instr do_fetch_HL, op_nop, do_store_PC ;E9 ;JP HL +instr do_fetch_DIR16, op_IFPE, do_store_PC ;EA nn nn ;JP PE,nn +instr do_fetch_DE, op_EXHL, do_store_DE ;EB ;EX DE,HL +instr do_fetch_DIR16, op_IFPE, do_store_CALL ;EC nn nn ;CALL PE,nn +instr do_fetch_nop, op_INV, do_store_nop ;ED ;(Z80 specific) +instr do_fetch_DIR8, op_XORA, do_store_nop ;EE nn ;XOR n +instr do_fetch_RST, op_nop, do_store_CALL ;EF ;RST 28H +instr do_fetch_nop, op_IFP, do_store_RET ;F0 ;RET P +instr do_fetch_nop, op_POP16, do_store_AF ;F1 ;POP AF +instr do_fetch_DIR16, op_IFP, do_store_PC ;F2 nn nn ;JP P,nn +instr do_fetch_nop, op_DI, do_store_nop ;F3 ;DI +instr do_fetch_DIR16, op_IFP, do_store_CALL ;F4 nn nn ;CALL P,nn +instr do_fetch_AF, op_PUSH16, do_store_nop ;F5 ;PUSH AF +instr do_fetch_DIR8, op_ORA, do_store_nop ;F6 nn ;OR n +instr do_fetch_RST, op_nop, do_store_CALL ;F7 ;RST 30H +instr do_fetch_nop, op_IFM, do_store_RET ;F8 ;RET M +instr do_fetch_HL, op_nop, do_store_SP ;F9 ;LD SP,HL +instr do_fetch_DIR16, op_IFM, do_store_PC ;FA nn nn ;JP M,nn +instr do_fetch_nop, op_EI, do_store_nop ;FB ;EI +instr do_fetch_DIR16, op_IFM, do_store_CALL ;FC nn nn ;CALL M,nn +instr do_fetch_nop, op_INV, do_store_nop ;FD ;(Z80 specific) +instr do_fetch_DIR8, op_CPFA, do_store_nop ;FE nn ;CP n +instr do_fetch_RST, op_nop, do_store_CALL ;FF ;RST 38H + +;---------------------------------------------------------------- +; Lookup table, stolen from z80ex, Z80 emulation library. +; http://z80ex.sourceforge.net/ + +; The S, Z, 5 and 3 bits and the parity of the lookup value + + .org (PC+255) & 0xff00 +sz53p_tab: + .db 0x44,0x00,0x00,0x04,0x00,0x04,0x04,0x00 + .db 0x08,0x0c,0x0c,0x08,0x0c,0x08,0x08,0x0c + .db 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04 + .db 0x0c,0x08,0x08,0x0c,0x08,0x0c,0x0c,0x08 + .db 0x20,0x24,0x24,0x20,0x24,0x20,0x20,0x24 + .db 0x2c,0x28,0x28,0x2c,0x28,0x2c,0x2c,0x28 + .db 0x24,0x20,0x20,0x24,0x20,0x24,0x24,0x20 + .db 0x28,0x2c,0x2c,0x28,0x2c,0x28,0x28,0x2c + .db 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04 + .db 0x0c,0x08,0x08,0x0c,0x08,0x0c,0x0c,0x08 + .db 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00 + .db 0x08,0x0c,0x0c,0x08,0x0c,0x08,0x08,0x0c + .db 0x24,0x20,0x20,0x24,0x20,0x24,0x24,0x20 + .db 0x28,0x2c,0x2c,0x28,0x2c,0x28,0x28,0x2c + .db 0x20,0x24,0x24,0x20,0x24,0x20,0x20,0x24 + .db 0x2c,0x28,0x28,0x2c,0x28,0x2c,0x2c,0x28 + .db 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84 + .db 0x8c,0x88,0x88,0x8c,0x88,0x8c,0x8c,0x88 + .db 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80 + .db 0x88,0x8c,0x8c,0x88,0x8c,0x88,0x88,0x8c + .db 0xa4,0xa0,0xa0,0xa4,0xa0,0xa4,0xa4,0xa0 + .db 0xa8,0xac,0xac,0xa8,0xac,0xa8,0xa8,0xac + .db 0xa0,0xa4,0xa4,0xa0,0xa4,0xa0,0xa0,0xa4 + .db 0xac,0xa8,0xa8,0xac,0xa8,0xac,0xac,0xa8 + .db 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80 + .db 0x88,0x8c,0x8c,0x88,0x8c,0x88,0x88,0x8c + .db 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84 + .db 0x8c,0x88,0x88,0x8c,0x88,0x8c,0x8c,0x88 + .db 0xa0,0xa4,0xa4,0xa0,0xa4,0xa0,0xa0,0xa4 + .db 0xac,0xa8,0xa8,0xac,0xa8,0xac,0xac,0xa8 + .db 0xa4,0xa0,0xa0,0xa4,0xa0,0xa4,0xa4,0xa0 + .db 0xa8,0xac,0xac,0xa8,0xac,0xa8,0xa8,0xac + +; vim:set ts=8 noet nowrap + diff --git a/8080int-t3.asm b/8080int-t3.asm new file mode 100644 index 0000000..9d99c02 --- /dev/null +++ b/8080int-t3.asm @@ -0,0 +1,1850 @@ +; 8080 Interpreter. +; This is part of the Z80-CP/M emulator written by Sprite_tm. +; + +; Copyright (C) 2010 Sprite_tm +; Copyright (C) 2010 Leo C. +; Copyright (C) 2010 Horst S. + +; This file is part of avrcpm. +; +; avrcpm is free software: you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by +; the Free Software Foundation, either version 3 of the License, or +; (at your option) any later version. +; +; avrcpm is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with avrcpm. If not, see . +; +; $Id$ +; + + + .dseg + +z_b: .byte 1 +z_c: .byte 1 +z_d: .byte 1 +z_e: .byte 1 +z_h: .byte 1 +z_l: .byte 1 + + + .cseg + +;Init z80 +z80_init: + ldi z_pcl,low (IPLADDR) + ldi z_pch,high(IPLADDR) + + cbi flags,trace + printnewline + printstring "Ok, CPU is live!" + printnewline + +;---------------------------------------------------------- +; 1 2 3 4 +;.db (low)do_store (low)do_op (hihg)do_op (low)do_fetch +; +;das kommt auf den stapel +; main da solls zum schluss weitergehen +;do_store wohin damit beenden mit RET +;do_op was tun beenden mit RET +; +;das wird direkt angesprungen +;do_fetch woher beenden mit RET +; +; +main: +.if INS_DEBUG + cbi flags,trace + cpi z_pch,DBG_TRACE_BOTTOM + brlo notraceon + cpi z_pch,DBG_TRACE_TOP + brsh notraceon + sbi flags,trace +notraceon: +.endif + + +.if PRINT_PC + cpi z_pch,DBG_TRACE_BOTTOM + brlo noprintpc + cpi z_pch,DBG_TRACE_TOP + brsh noprintpc + + printnewline + printstring "PC=" + movw temp,z_pcl + rcall printhexw + printstring " " +noprintpc: +.endif + +.if INS_DEBUG + sbic flags,trace + rcall printregs +.endif + + ;hier kommt die Interruptbehandlung rein + + ldi zl,low(main) ;da will ich wieder hin. + ldi zh,high(main) ; + push zl ; + push zh ; + mem_read_s z_pc ;temp=memReadByte(z_pc) + adiw z_pcl,1 ;++z_pc + ldi zl,low(todo_table*2) ;zhl=todo_table + ldi zh,high(todo_table*2) ; + ldi temp2,3 ;1 + mul temp,temp2 ;2 + add zl,r0 ;1 + adc zh,r1 ;1 + + ldi temp2,high(store_ops) ; + lpm temp,Z+ ;do_store + push temp ; low + push temp2 ; high + +.if high(opjumps) != high(opjumps) + ldi temp2,high(opjumps) +.endif + lpm temp,Z+ ;do_op + push temp ; low + push temp2 ; high + + lpm zl,Z ;do_fetch + ldi zh,high(fetch_ops) + ijmp ;direkt + + +; .listmac +;----------------------------------------------------- +; Generate jump to target and position in table +; gen_opjmp target +; +.macro gen_opjmp + .ifndef opjmp_table_pos_ + .set opjmp_table_page_ = high(PC) + .set opjmp_table_pos_ = PC + .endif + .equ @0 = low(opjmp_table_pos_) + .set opjmp_table_pos_ = opjmp_table_pos_ + 1 + .if high(opjmp_table_pos_) != opjmp_table_page_ + .warning "Table 'opjump' crosses page boarder." + .message "Program will not work, unless the opjump table is relocated." + .endif + rjmp do_@0 + .endm + +;-------------------------------------------------- +; Generate a table entry for one instruction +; +; instr fetch, op, store +; +.macro instr + .ifndef inst_table_odd_ + .set inst_table_odd_ = 0 + .endif + + .if inst_table_odd_ + .db inst_table_next_, low(@2), @1, low(@0) + .set inst_table_odd_ = 0 + .else + .set inst_table_next_ = low(@0) + .db low(@2), @1 + .set inst_table_odd_ = 1 + .endif +.endm + +;----------------------------------- +; go to op. +; +.macro fetch_end + ldi zh,high(opjumps) + mov zl,insdech + ijmp +.endm + +;----------------------------------- +; go to store. +; +.macro op_end + ldi zh,high(store_ops) ; + mov zl,insdecl + ijmp +.endm + +;----------------------------------- +; go back to main +; +.macro store_end + rjmp main +.endm + +;----------------------------------- +; go back to main +; +.macro op_end_nojmp + rjmp main +.endm + + +; ------------ Fetch phase stuff ----------------- + +.org (PC+255) & 0xff00 ; wichtig !!!fetch und store muessen in einer page liegen +fetch_ops: +do_fetch_nop: + ret + +do_fetch_a: + mov opl,z_a + ret + +do_fetch_b: + lds opl,z_b + ret + +do_fetch_c: + lds opl,z_c + ret + +do_fetch_d: + lds opl,z_d + ret + +do_fetch_e: + lds opl,z_e + ret + +do_fetch_h: + lds opl,z_h + ret + +do_fetch_l: + lds opl,z_l + ret + +do_fetch_af: + mov opl,z_flags + mov oph,z_a + ret + +do_fetch_bc: + lds opl,z_c + lds oph,z_b + ret + +do_fetch_de: + lds opl,z_e + lds oph,z_d + ret + +do_fetch_hl: + lds opl,z_l + lds oph,z_h + ret + +do_fetch_sp: + movw opl,z_spl + ret + +do_fetch_mbc: + lds xh,z_b + lds xl,z_c + mem_read_d opl + ret + +do_fetch_mde: + lds xh,z_d + lds xl,z_e + mem_read_d opl + ret + +do_fetch_mhl: + lds xh,z_h + lds xl,z_l + mem_read_d opl + ret + +do_fetch_msp: + movw x,z_spl + mem_read_d opl + adiw x,1 + mem_read_d oph + ret + +do_fetch_dir8: + mem_read_ds opl, z_pc + adiw z_pcl,1 + ret + +do_fetch_dir16: + mem_read_ds opl, z_pc + adiw z_pcl,1 + mem_read_ds oph, z_pc + adiw z_pcl,1 + ret + +do_fetch_rst: + movw x,z_pcl + sbiw x,1 + mem_read_d opl + andi opl,0x38 + ldi oph,0 + ret + +; ------------ Store phase stuff ----------------- + +.org (PC+255) & 0xff00 ; wichtig !!!fetch und store muessen in einer page liegen +store_ops: +do_store_nop: + ret + +do_store_a: + mov z_a,opl + ret + +do_store_b: + sts z_b,opl + ret + +do_store_c: + sts z_c,opl + ret + +do_store_d: + sts z_d,opl + ret + +do_store_e: + sts z_e,opl + ret + +do_store_h: + sts z_h,opl + ret + +do_store_l: + sts z_l,opl + ret + +do_store_af: + mov z_a,oph + mov z_flags,opl + ret + +do_store_bc: + sts z_b,oph + sts z_c,opl + ret + +do_store_de: + sts z_d,oph + sts z_e,opl + ret + +do_store_hl: + sts z_h,oph + sts z_l,opl + ret + +do_store_mbc: + lds xh,z_b + lds xl,z_c + mem_write_s opl + ret + +do_store_mde: + lds xh,z_d + lds xl,z_e + mem_write_s opl + ret + +do_store_mhl: + lds xh,z_h + lds xl,z_l + mem_write_s opl + ret + +do_store_msp: + movw xl,z_spl + mem_write_s opl + adiw xl,1 + mem_write_s oph + ret + +do_store_sp: + movw z_spl,opl + ret + +do_store_pc: + movw z_pcl,opl + ret + +do_store_ret: + movw x,z_spl + mem_read_d z_pcl + adiw x,1 + mem_read_d z_pch + adiw x,1 + movw z_spl,x + +.if STACK_DBG + printnewline + printstring "Stack pop " + movw temp,z_pcl + rcall printhexw + printstring ", SP is now " + movw temp,z_spl + rcall printhexw + printstring ". " +.endif + ret + +do_store_call: + movw xl,z_spl + sbiw x,1 + mem_write_s z_pch + sbiw x,1 + mem_write_s z_pcl + movw z_spl,xl + +.if STACK_DBG + printnewline + printstring "Stack push " + movw temp,z_pcl + rcall printhexw + printstring ", SP is now " + movw temp,z_spl + rcall printhexw + printstring ". " +.endif + movw z_pcl,opl + ret + + +do_store_am: + mem_write_ds op, z_a + ret + +; ------------ Operation phase stuff ----------------- + +;.org (PC+255) & 0xff00 + +opjumps: + gen_opjmp op_nop + gen_opjmp op_inc + gen_opjmp op_dec + gen_opjmp op_inc16 + gen_opjmp op_dec16 + gen_opjmp op_rlc + gen_opjmp op_rrc + gen_opjmp op_rr + gen_opjmp op_rl + gen_opjmp op_adda + gen_opjmp op_adca + gen_opjmp op_subfa + gen_opjmp op_sbcfa + gen_opjmp op_anda + gen_opjmp op_ora + gen_opjmp op_xora + gen_opjmp op_addhl + gen_opjmp op_sthl + gen_opjmp op_rmem16 + gen_opjmp op_rmem8 + gen_opjmp op_da + gen_opjmp op_scf + gen_opjmp op_cpl + gen_opjmp op_ccf + gen_opjmp op_pop16 + gen_opjmp op_push16 + gen_opjmp op_ifnz + gen_opjmp op_ifz + gen_opjmp op_ifnc + gen_opjmp op_ifc + gen_opjmp op_ifpo + gen_opjmp op_ifpe + gen_opjmp op_ifp + gen_opjmp op_ifm + gen_opjmp op_outa + gen_opjmp op_in + gen_opjmp op_exhl + gen_opjmp op_di + gen_opjmp op_ei + gen_opjmp op_inv + gen_opjmp op_cpfa + gen_opjmp op_inca + gen_opjmp op_deca + + +;---------------------------------------------------------------- +;| | +;| 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 | +;|----------+------+--------------------------------------------| +;| 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 | +;---------------------------------------------------------------- + +;How the flags are supposed to work: +;7 ZFL_S - Sign flag (=MSBit of result) +;6 ZFL_Z - Zero flag. Is 1 when the result is 0 +;4 ZFL_H - Half-carry (carry from bit 3 to 4) +;2 ZFL_P - Parity/2-complement Overflow +;1 ZFL_N - Subtract - set if last op was a subtract +;0 ZFL_C - Carry +; +;I sure hope I got the mapping between flags and instructions correct... + +.equ ZFL_S = 7 +.equ ZFL_Z = 6 +.equ ZFL_H = 4 +.equ ZFL_P = 2 +.equ ZFL_N = 1 +.equ ZFL_C = 0 + +.equ AVR_T = SREG_T +.equ AVR_H = SREG_H +.equ AVR_S = SREG_S +.equ AVR_V = SREG_V +.equ AVR_N = SREG_N +.equ AVR_Z = SREG_Z +.equ AVR_C = SREG_C + +;------------------------------------------------; +; 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< (" + mov temp,opl + rcall printhex + printstring ") " +.endif + mov temp,z_a + mov temp2,opl + rcall portWrite + ret + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +;|IN A,[n] |------|Input |A=[n] | +; +; +do_op_in: ; in a,(opl) +.if PORT_DEBUG + printnewline + printstring "Port read: (" + mov temp,opl + rcall printhex + printstring ") -> " +.endif + + mov temp2,opl + rcall portRead + mov opl,temp + +.if PORT_DEBUG + rcall printhex + printstring " " +.endif + ret + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +;|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 | +; +; +do_op_inc: + inc opl +#if EM_Z80 + in temp, sreg +#endif + andi z_flags,(1<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. + do_z80_flags_op_rotate + lsr opl + brcc do_op_rrc_noc + ori opl, 0x80 + ori z_flags, (1<{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 ; 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 + ret + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +;|RLA |--0-0*|Rotate Left Acc. |A={CY,A}<- | +;|----------|SZHP C|---------- 8080 ----------------------------| +;|RLA |---- *|Rotate Left Acc. |A={CY,A}<- | +; +; +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 + ret + +;---------------------------------------------------------------- +;|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: + add z_a,opl + in temp,sreg + ldpmx z_flags,sz53p_tab,z_a ;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 | +; +; +do_op_adca: + clc + sbrc z_flags,ZFL_C + sec + adc z_a,opl + in temp,sreg + ldpmx z_flags,sz53p_tab,z_a ;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 | +;|----------|SZHP C|---------- 8080 ----------------------------| +;|SUB s |***P *|Subtract |A=A-s | + +; +do_op_subfa: + sub z_a,opl + in temp,sreg + ldpmx z_flags,sz53p_tab,z_a ;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 | +;---------------------------------------------------------------- +;|CP s |***V1*|Compare |A-s | +;|----------|SZHP C|---------- 8080 ----------------------------| +;|CP s |***P *|Compare |A-s | + +; +do_op_cpfa: + mov temp,z_a + sub temp,opl + mov opl,temp + in temp,sreg + 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 | +; +; +do_op_sbcfa: + clc + sbrc z_flags,ZFL_C + sec + sbc z_a,opl + in temp,sreg + ldpmx z_flags,sz53p_tab,z_a ;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 | +; +; TODO H-Flag +do_op_anda: + and z_a,opl ; + ldpmx z_flags,sz53p_tab,z_a ;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 | +; +; TODO: H-Flag +do_op_ora: + or z_a,opl + ldpmx z_flags,sz53p_tab,z_a ;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 | +; +; TODO: H-Flag +do_op_xora: + eor z_a,opl + ldpmx z_flags,sz53p_tab,z_a ;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 | +; +; +do_op_addhl: + lds temp,z_l + lds temp2,z_h + add opl,temp + adc oph,temp2 + in temp,sreg + bmov z_flags,ZFL_H, temp,AVR_H + bmov z_flags,ZFL_C, temp,AVR_C + do_z80_flags_clear_N + ret + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +;|LD dst,src|------|Load |dst=src | +; +; +do_op_sthl: ;store hl to mem loc in opl:h + movw xl,opl + lds temp,z_l + mem_write + adiw xl,1 + lds temp,z_h + mem_write + ret + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +;|LD dst,src|------|Load |dst=src | +; +; +do_op_rmem16: + movw xl,opl + mem_read_d opl + adiw x,1 + mem_read_d oph + ret + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +;|LD dst,src|------|Load |dst=src | +; +; +do_op_rmem8: + mem_read_ds opl, op + 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: + 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< 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 | +;-----------------------------Z80-------------------------------- +; +do_op_exhl: + lds temp,z_l + lds temp2,z_h + sts z_l,opl + sts z_h,oph + movw opl,temp + ret + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +; +; TODO: Implement IFF1, IFF2 +do_op_di: + ret + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +; +; 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 | +; +; +do_op_ifnz: + sbrs z_flags, ZFL_Z + ret + pop temp ; nix tun + pop temp ; direkt zuruech zu main + 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 | +; +; +do_op_ifz: + sbrc z_flags, ZFL_Z + ret + pop temp ; nix tun + pop temp ; direkt zuruech zu main + 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 | +; +; +do_op_ifnc: + sbrs z_flags, ZFL_C + ret + pop temp ; nix tun + pop temp ; direkt zuruech zu main + 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 | +; +; +do_op_ifc: + sbrc z_flags, ZFL_C + ret + pop temp ; nix tun + pop temp ; direkt zuruech zu main + 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 | +; +; +do_op_ifpo: + sbrs z_flags, ZFL_P + ret + pop temp ; nix tun + pop temp ; direkt zuruech zu main + 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 | +; +; +do_op_ifpe: + sbrc z_flags, ZFL_P + ret + pop temp ; nix tun + pop temp ; direkt zuruech zu main + 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 | +; +; +do_op_ifp: ;sign positive, aka s=0 + sbrs z_flags, ZFL_S + ret + pop temp ; nix tun + pop temp ; direkt zuruech zu main + 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 | +; +; +do_op_ifm: ;sign negative, aka s=1 + sbrc z_flags, ZFL_S + ret + pop temp ; nix tun + pop temp ; direkt zuruech zu main + ret + + +; ----------------------- Opcode decoding ------------------------- + +; Lookup table for Z80 opcodes. Translates the first byte of the instruction word into three +; operations: fetch, do something, store. +; The table is made of 256 words. + +;.org (PC+255) & 0xff00 +todo_table: +instr do_fetch_nop, op_nop, do_store_nop ;00 ;NOP +instr do_fetch_DIR16, op_nop, do_store_BC ;01 nn nn ;LD BC,nn +instr do_fetch_A, op_nop, do_store_MBC ;02 ;LD (BC),A +instr do_fetch_BC, op_INC16, do_store_BC ;03 ;INC BC +instr do_fetch_B, op_INC, do_store_B ;04 ;INC B +instr do_fetch_B, op_DEC, do_store_B ;05 ;DEC B +instr do_fetch_DIR8, op_nop, do_store_B ;06 ;LD B,n +instr do_fetch_A, op_RLC, do_store_A ;07 ;RLCA +instr do_fetch_nop, op_INV, do_store_nop ;08 ;EX AF,AF' +instr do_fetch_BC, op_ADDHL, do_store_HL ;09 ;ADD HL,BC +instr do_fetch_MBC, op_nop, do_store_A ;0A ;LD A,(BC) +instr do_fetch_BC, op_DEC16, do_store_BC ;0B ;DEC BC +instr do_fetch_C, op_INC, do_store_C ;0C ;INC C +instr do_fetch_C, op_DEC, do_store_C ;0D ;DEC C +instr do_fetch_DIR8, op_nop, do_store_C ;0E nn ;LD C,n +instr do_fetch_A, op_RRC, do_store_A ;0F ;RRCA +instr do_fetch_nop, op_INV, do_store_nop ;10 oo ;DJNZ o +instr do_fetch_DIR16, op_nop, do_store_DE ;11 nn nn ;LD DE,nn +instr do_fetch_A, op_nop, do_store_MDE ;12 ;LD (DE),A +instr do_fetch_DE, op_INC16, do_store_DE ;13 ;INC DE +instr do_fetch_D, op_INC, do_store_D ;14 ;INC D +instr do_fetch_D, op_DEC, do_store_D ;15 ;DEC D +instr do_fetch_DIR8, op_nop, do_store_D ;16 nn ;LD D,n +instr do_fetch_A, op_RL, do_store_A ;17 ;RLA +instr do_fetch_nop, op_INV, do_store_nop ;18 oo ;JR o +instr do_fetch_DE, op_ADDHL, do_store_HL ;19 ;ADD HL,DE +instr do_fetch_MDE, op_nop, do_store_A ;1A ;LD A,(DE) +instr do_fetch_DE, op_DEC16, do_store_DE ;1B ;DEC DE +instr do_fetch_E, op_INC, do_store_E ;1C ;INC E +instr do_fetch_E, op_DEC, do_store_E ;1D ;DEC E +instr do_fetch_DIR8, op_nop, do_store_E ;1E nn ;LD E,n +instr do_fetch_A, op_RR, do_store_A ;1F ;RRA +instr do_fetch_nop, op_INV, do_store_nop ;20 oo ;JR NZ,o +instr do_fetch_DIR16, op_nop, do_store_HL ;21 nn nn ;LD HL,nn +instr do_fetch_DIR16, op_STHL, do_store_nop ;22 nn nn ;LD (nn),HL +instr do_fetch_HL, op_INC16, do_store_HL ;23 ;INC HL +instr do_fetch_H, op_INC, do_store_H ;24 ;INC H +instr do_fetch_H, op_DEC, do_store_H ;25 ;DEC H +instr do_fetch_DIR8, op_nop, do_store_H ;26 nn ;LD H,n +instr do_fetch_A, op_DA, do_store_A ;27 ;DAA +instr do_fetch_nop, op_INV, do_store_nop ;28 oo ;JR Z,o +instr do_fetch_HL, op_ADDHL, do_store_HL ;29 ;ADD HL,HL +instr do_fetch_DIR16, op_RMEM16, do_store_HL ;2A nn nn ;LD HL,(nn) +instr do_fetch_HL, op_DEC16, do_store_HL ;2B ;DEC HL +instr do_fetch_L, op_INC, do_store_L ;2C ;INC L +instr do_fetch_L, op_DEC, do_store_L ;2D ;DEC L +instr do_fetch_DIR8, op_nop, do_store_L ;2E nn ;LD L,n +instr do_fetch_nop, op_CPL, do_store_nop ;2F ;CPL +instr do_fetch_nop, op_INV, do_store_nop ;30 oo ;JR NC,o +instr do_fetch_DIR16, op_nop, do_store_SP ;31 nn nn ;LD SP,nn +instr do_fetch_DIR16, op_nop, do_store_AM ;32 nn nn ;LD (nn),A +instr do_fetch_SP, op_INC16, do_store_SP ;33 ;INC SP +instr do_fetch_MHL, op_INC, do_store_MHL ;34 ;INC (HL) +instr do_fetch_MHL, op_DEC, do_store_MHL ;35 ;DEC (HL) +instr do_fetch_DIR8, op_nop, do_store_MHL ;36 nn ;LD (HL),n +instr do_fetch_nop, op_SCF, do_store_nop ;37 ;SCF +instr do_fetch_nop, op_INV, do_store_nop ;38 oo ;JR C,o +instr do_fetch_SP, op_ADDHL, do_store_HL ;39 ;ADD HL,SP +instr do_fetch_DIR16, op_RMEM8, do_store_A ;3A nn nn ;LD A,(nn) +instr do_fetch_SP, op_DEC16, do_store_SP ;3B ;DEC SP +instr do_fetch_nop, op_INCA, do_store_nop ;3C ;INC A +instr do_fetch_nop, op_DECA, do_store_nop ;3D ;DEC A +instr do_fetch_DIR8, op_nop, do_store_A ;3E nn ;LD A,n +instr do_fetch_nop, op_CCF, do_store_nop ;3F ;CCF (Complement Carry Flag, gvd) +instr do_fetch_B, op_nop, do_store_B ;40 ;LD B,B +instr do_fetch_C, op_nop, do_store_B ;41 ;LD B,C +instr do_fetch_D, op_nop, do_store_B ;42 ;LD B,D +instr do_fetch_E, op_nop, do_store_B ;43 ;LD B,E +instr do_fetch_H, op_nop, do_store_B ;44 ;LD B,H +instr do_fetch_L, op_nop, do_store_B ;45 ;LD B,L +instr do_fetch_MHL, op_nop, do_store_B ;46 ;LD B,(HL) +instr do_fetch_A, op_nop, do_store_B ;47 ;LD B,A +instr do_fetch_B, op_nop, do_store_C ;48 ;LD C,B +instr do_fetch_C, op_nop, do_store_C ;49 ;LD C,C +instr do_fetch_D, op_nop, do_store_C ;4A ;LD C,D +instr do_fetch_E, op_nop, do_store_C ;4B ;LD C,E +instr do_fetch_H, op_nop, do_store_C ;4C ;LD C,H +instr do_fetch_L, op_nop, do_store_C ;4D ;LD C,L +instr do_fetch_MHL, op_nop, do_store_C ;4E ;LD C,(HL) +instr do_fetch_A, op_nop, do_store_C ;4F ;LD C,A +instr do_fetch_B, op_nop, do_store_D ;50 ;LD D,B +instr do_fetch_C, op_nop, do_store_D ;51 ;LD D,C +instr do_fetch_D, op_nop, do_store_D ;52 ;LD D,D +instr do_fetch_E, op_nop, do_store_D ;53 ;LD D,E +instr do_fetch_H, op_nop, do_store_D ;54 ;LD D,H +instr do_fetch_L, op_nop, do_store_D ;55 ;LD D,L +instr do_fetch_MHL, op_nop, do_store_D ;56 ;LD D,(HL) +instr do_fetch_A, op_nop, do_store_D ;57 ;LD D,A +instr do_fetch_B, op_nop, do_store_E ;58 ;LD E,B +instr do_fetch_C, op_nop, do_store_E ;59 ;LD E,C +instr do_fetch_D, op_nop, do_store_E ;5A ;LD E,D +instr do_fetch_E, op_nop, do_store_E ;5B ;LD E,E +instr do_fetch_H, op_nop, do_store_E ;5C ;LD E,H +instr do_fetch_L, op_nop, do_store_E ;5D ;LD E,L +instr do_fetch_MHL, op_nop, do_store_E ;5E ;LD E,(HL) +instr do_fetch_A, op_nop, do_store_E ;5F ;LD E,A +instr do_fetch_B, op_nop, do_store_H ;60 ;LD H,B +instr do_fetch_C, op_nop, do_store_H ;61 ;LD H,C +instr do_fetch_D, op_nop, do_store_H ;62 ;LD H,D +instr do_fetch_E, op_nop, do_store_H ;63 ;LD H,E +instr do_fetch_H, op_nop, do_store_H ;64 ;LD H,H +instr do_fetch_L, op_nop, do_store_H ;65 ;LD H,L +instr do_fetch_MHL, op_nop, do_store_H ;66 ;LD H,(HL) +instr do_fetch_A, op_nop, do_store_H ;67 ;LD H,A +instr do_fetch_B, op_nop, do_store_L ;68 ;LD L,B +instr do_fetch_C, op_nop, do_store_L ;69 ;LD L,C +instr do_fetch_D, op_nop, do_store_L ;6A ;LD L,D +instr do_fetch_E, op_nop, do_store_L ;6B ;LD L,E +instr do_fetch_H, op_nop, do_store_L ;6C ;LD L,H +instr do_fetch_L, op_nop, do_store_L ;6D ;LD L,L +instr do_fetch_MHL, op_nop, do_store_L ;6E ;LD L,(HL) +instr do_fetch_A, op_nop, do_store_L ;6F ;LD L,A +instr do_fetch_B, op_nop, do_store_MHL ;70 ;LD (HL),B +instr do_fetch_C, op_nop, do_store_MHL ;71 ;LD (HL),C +instr do_fetch_D, op_nop, do_store_MHL ;72 ;LD (HL),D +instr do_fetch_E, op_nop, do_store_MHL ;73 ;LD (HL),E +instr do_fetch_H, op_nop, do_store_MHL ;74 ;LD (HL),H +instr do_fetch_L, op_nop, do_store_MHL ;75 ;LD (HL),L +instr do_fetch_nop, op_INV, do_store_nop ;76 ;HALT +instr do_fetch_A, op_nop, do_store_MHL ;77 ;LD (HL),A +instr do_fetch_B, op_nop, do_store_A ;78 ;LD A,B +instr do_fetch_C, op_nop, do_store_A ;79 ;LD A,C +instr do_fetch_D, op_nop, do_store_A ;7A ;LD A,D +instr do_fetch_E, op_nop, do_store_A ;7B ;LD A,E +instr do_fetch_H, op_nop, do_store_A ;7C ;LD A,H +instr do_fetch_L, op_nop, do_store_A ;7D ;LD A,L +instr do_fetch_MHL, op_nop, do_store_A ;7E ;LD A,(HL) +instr do_fetch_A, op_nop, do_store_A ;7F ;LD A,A +instr do_fetch_B, op_ADDA, do_store_nop ;80 ;ADD A,B +instr do_fetch_C, op_ADDA, do_store_nop ;81 ;ADD A,C +instr do_fetch_D, op_ADDA, do_store_nop ;82 ;ADD A,D +instr do_fetch_E, op_ADDA, do_store_nop ;83 ;ADD A,E +instr do_fetch_H, op_ADDA, do_store_nop ;84 ;ADD A,H +instr do_fetch_L, op_ADDA, do_store_nop ;85 ;ADD A,L +instr do_fetch_MHL, op_ADDA, do_store_nop ;86 ;ADD A,(HL) +instr do_fetch_A, op_ADDA, do_store_nop ;87 ;ADD A,A +instr do_fetch_B, op_ADCA, do_store_nop ;88 ;ADC A,B +instr do_fetch_C, op_ADCA, do_store_nop ;89 ;ADC A,C +instr do_fetch_D, op_ADCA, do_store_nop ;8A ;ADC A,D +instr do_fetch_E, op_ADCA, do_store_nop ;8B ;ADC A,E +instr do_fetch_H, op_ADCA, do_store_nop ;8C ;ADC A,H +instr do_fetch_L, op_ADCA, do_store_nop ;8D ;ADC A,L +instr do_fetch_MHL, op_ADCA, do_store_nop ;8E ;ADC A,(HL) +instr do_fetch_A, op_ADCA, do_store_nop ;8F ;ADC A,A +instr do_fetch_B, op_SUBFA, do_store_nop ;90 ;SUB A,B +instr do_fetch_C, op_SUBFA, do_store_nop ;91 ;SUB A,C +instr do_fetch_D, op_SUBFA, do_store_nop ;92 ;SUB A,D +instr do_fetch_E, op_SUBFA, do_store_nop ;93 ;SUB A,E +instr do_fetch_H, op_SUBFA, do_store_nop ;94 ;SUB A,H +instr do_fetch_L, op_SUBFA, do_store_nop ;95 ;SUB A,L +instr do_fetch_MHL, op_SUBFA, do_store_nop ;96 ;SUB A,(HL) +instr do_fetch_A, op_SUBFA, do_store_nop ;97 ;SUB A,A +instr do_fetch_B, op_SBCFA, do_store_nop ;98 ;SBC A,B +instr do_fetch_C, op_SBCFA, do_store_nop ;99 ;SBC A,C +instr do_fetch_D, op_SBCFA, do_store_nop ;9A ;SBC A,D +instr do_fetch_E, op_SBCFA, do_store_nop ;9B ;SBC A,E +instr do_fetch_H, op_SBCFA, do_store_nop ;9C ;SBC A,H +instr do_fetch_L, op_SBCFA, do_store_nop ;9D ;SBC A,L +instr do_fetch_MHL, op_SBCFA, do_store_nop ;9E ;SBC A,(HL) +instr do_fetch_A, op_SBCFA, do_store_nop ;9F ;SBC A,A +instr do_fetch_B, op_ANDA, do_store_nop ;A0 ;AND A,B +instr do_fetch_C, op_ANDA, do_store_nop ;A1 ;AND A,C +instr do_fetch_D, op_ANDA, do_store_nop ;A2 ;AND A,D +instr do_fetch_E, op_ANDA, do_store_nop ;A3 ;AND A,E +instr do_fetch_H, op_ANDA, do_store_nop ;A4 ;AND A,H +instr do_fetch_L, op_ANDA, do_store_nop ;A5 ;AND A,L +instr do_fetch_MHL, op_ANDA, do_store_nop ;A6 ;AND A,(HL) +instr do_fetch_A, op_ANDA, do_store_nop ;A7 ;AND A,A +instr do_fetch_B, op_XORA, do_store_nop ;A8 ;XOR A,B +instr do_fetch_C, op_XORA, do_store_nop ;A9 ;XOR A,C +instr do_fetch_D, op_XORA, do_store_nop ;AA ;XOR A,D +instr do_fetch_E, op_XORA, do_store_nop ;AB ;XOR A,E +instr do_fetch_H, op_XORA, do_store_nop ;AC ;XOR A,H +instr do_fetch_L, op_XORA, do_store_nop ;AD ;XOR A,L +instr do_fetch_MHL, op_XORA, do_store_nop ;AE ;XOR A,(HL) +instr do_fetch_A, op_XORA, do_store_nop ;AF ;XOR A,A +instr do_fetch_B, op_ORA, do_store_nop ;B0 ;OR A,B +instr do_fetch_C, op_ORA, do_store_nop ;B1 ;OR A,C +instr do_fetch_D, op_ORA, do_store_nop ;B2 ;OR A,D +instr do_fetch_E, op_ORA, do_store_nop ;B3 ;OR A,E +instr do_fetch_H, op_ORA, do_store_nop ;B4 ;OR A,H +instr do_fetch_L, op_ORA, do_store_nop ;B5 ;OR A,L +instr do_fetch_MHL, op_ORA, do_store_nop ;B6 ;OR A,(HL) +instr do_fetch_A, op_ORA, do_store_nop ;B7 ;OR A,A +instr do_fetch_B, op_CPFA, do_store_nop ;B8 ;CP A,B +instr do_fetch_C, op_CPFA, do_store_nop ;B9 ;CP A,C +instr do_fetch_D, op_CPFA, do_store_nop ;BA ;CP A,D +instr do_fetch_E, op_CPFA, do_store_nop ;BB ;CP A,E +instr do_fetch_H, op_CPFA, do_store_nop ;BC ;CP A,H +instr do_fetch_L, op_CPFA, do_store_nop ;BD ;CP A,L +instr do_fetch_MHL, op_CPFA, do_store_nop ;BE ;CP A,(HL) +instr do_fetch_A, op_CPFA, do_store_nop ;BF ;CP A,A +instr do_fetch_nop, op_IFNZ, do_store_RET ;C0 ;RET NZ +instr do_fetch_nop, op_POP16, do_store_BC ;C1 ;POP BC +instr do_fetch_DIR16, op_IFNZ, do_store_PC ;C2 nn nn ;JP NZ,nn +instr do_fetch_DIR16, op_nop, do_store_PC ;C3 nn nn ;JP nn +instr do_fetch_DIR16, op_IFNZ, do_store_CALL ;C4 nn nn ;CALL NZ,nn +instr do_fetch_BC, op_PUSH16, do_store_nop ;C5 ;PUSH BC +instr do_fetch_DIR8, op_ADDA, do_store_nop ;C6 nn ;ADD A,n +instr do_fetch_RST, op_nop, do_store_CALL ;C7 ;RST 0 +instr do_fetch_nop, op_IFZ, do_store_RET ;C8 ;RET Z +instr do_fetch_nop, op_nop, do_store_RET ;C9 ;RET +instr do_fetch_DIR16, op_IFZ, do_store_PC ;CA nn nn ;JP Z,nn +instr do_fetch_nop, op_INV, do_store_nop ;CB ;(Z80 specific) +instr do_fetch_DIR16, op_IFZ, do_store_CALL ;CC nn nn ;CALL Z,nn +instr do_fetch_DIR16, op_nop, do_store_CALL ;CD nn nn ;CALL nn +instr do_fetch_DIR8, op_ADCA, do_store_nop ;CE nn ;ADC A,n +instr do_fetch_RST, op_nop, do_store_CALL ;CF ;RST 8H +instr do_fetch_nop, op_IFNC, do_store_RET ;D0 ;RET NC +instr do_fetch_nop, op_POP16, do_store_DE ;D1 ;POP DE +instr do_fetch_DIR16, op_IFNC, do_store_PC ;D2 nn nn ;JP NC,nn +instr do_fetch_DIR8, op_OUTA, do_store_nop ;D3 nn ;OUT (n),A +instr do_fetch_DIR16, op_IFNC, do_store_CALL ;D4 nn nn ;CALL NC,nn +instr do_fetch_DE, op_PUSH16, do_store_nop ;D5 ;PUSH DE +instr do_fetch_DIR8, op_SUBFA, do_store_nop ;D6 nn ;SUB n +instr do_fetch_RST, op_nop, do_store_CALL ;D7 ;RST 10H +instr do_fetch_nop, op_IFC, do_store_RET ;D8 ;RET C +instr do_fetch_nop, op_nop, do_store_nop ;D9 ;EXX +instr do_fetch_DIR16, op_IFC, do_store_PC ;DA nn nn ;JP C,nn +instr do_fetch_DIR8, op_IN, do_store_A ;DB nn ;IN A,(n) +instr do_fetch_DIR16, op_IFC, do_store_CALL ;DC nn nn ;CALL C,nn +instr do_fetch_nop, op_INV, do_store_nop ;DD ;(Z80 specific) +instr do_fetch_DIR8, op_SBCFA, do_store_nop ;DE nn ;SBC A,n +instr do_fetch_RST, op_nop, do_store_CALL ;DF ;RST 18H +instr do_fetch_nop, op_IFPO, do_store_RET ;E0 ;RET PO +instr do_fetch_nop, op_POP16, do_store_HL ;E1 ;POP HL +instr do_fetch_DIR16, op_IFPO, do_store_PC ;E2 nn nn ;JP PO,nn +instr do_fetch_MSP, op_EXHL, do_store_MSP ;E3 ;EX (SP),HL +instr do_fetch_DIR16, op_IFPO, do_store_CALL ;E4 nn nn ;CALL PO,nn +instr do_fetch_HL, op_PUSH16, do_store_nop ;E5 ;PUSH HL +instr do_fetch_DIR8, op_ANDA, do_store_nop ;E6 nn ;AND n +instr do_fetch_RST, op_nop, do_store_CALL ;E7 ;RST 20H +instr do_fetch_nop, op_IFPE, do_store_RET ;E8 ;RET PE +instr do_fetch_HL, op_nop, do_store_PC ;E9 ;JP HL +instr do_fetch_DIR16, op_IFPE, do_store_PC ;EA nn nn ;JP PE,nn +instr do_fetch_DE, op_EXHL, do_store_DE ;EB ;EX DE,HL +instr do_fetch_DIR16, op_IFPE, do_store_CALL ;EC nn nn ;CALL PE,nn +instr do_fetch_nop, op_INV, do_store_nop ;ED ;(Z80 specific) +instr do_fetch_DIR8, op_XORA, do_store_nop ;EE nn ;XOR n +instr do_fetch_RST, op_nop, do_store_CALL ;EF ;RST 28H +instr do_fetch_nop, op_IFP, do_store_RET ;F0 ;RET P +instr do_fetch_nop, op_POP16, do_store_AF ;F1 ;POP AF +instr do_fetch_DIR16, op_IFP, do_store_PC ;F2 nn nn ;JP P,nn +instr do_fetch_nop, op_DI, do_store_nop ;F3 ;DI +instr do_fetch_DIR16, op_IFP, do_store_CALL ;F4 nn nn ;CALL P,nn +instr do_fetch_AF, op_PUSH16, do_store_nop ;F5 ;PUSH AF +instr do_fetch_DIR8, op_ORA, do_store_nop ;F6 nn ;OR n +instr do_fetch_RST, op_nop, do_store_CALL ;F7 ;RST 30H +instr do_fetch_nop, op_IFM, do_store_RET ;F8 ;RET M +instr do_fetch_HL, op_nop, do_store_SP ;F9 ;LD SP,HL +instr do_fetch_DIR16, op_IFM, do_store_PC ;FA nn nn ;JP M,nn +instr do_fetch_nop, op_EI, do_store_nop ;FB ;EI +instr do_fetch_DIR16, op_IFM, do_store_CALL ;FC nn nn ;CALL M,nn +instr do_fetch_nop, op_INV, do_store_nop ;FD ;(Z80 specific) +instr do_fetch_DIR8, op_CPFA, do_store_nop ;FE nn ;CP n +instr do_fetch_RST, op_nop, do_store_CALL ;FF ;RST 38H + +;---------------------------------------------------------------- +; Lookup table, stolen from z80ex, Z80 emulation library. +; http://z80ex.sourceforge.net/ + +; The S, Z, 5 and 3 bits and the parity of the lookup value + + .org (PC+255) & 0xff00 +sz53p_tab: + .db 0x44,0x00,0x00,0x04,0x00,0x04,0x04,0x00 + .db 0x08,0x0c,0x0c,0x08,0x0c,0x08,0x08,0x0c + .db 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04 + .db 0x0c,0x08,0x08,0x0c,0x08,0x0c,0x0c,0x08 + .db 0x20,0x24,0x24,0x20,0x24,0x20,0x20,0x24 + .db 0x2c,0x28,0x28,0x2c,0x28,0x2c,0x2c,0x28 + .db 0x24,0x20,0x20,0x24,0x20,0x24,0x24,0x20 + .db 0x28,0x2c,0x2c,0x28,0x2c,0x28,0x28,0x2c + .db 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04 + .db 0x0c,0x08,0x08,0x0c,0x08,0x0c,0x0c,0x08 + .db 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00 + .db 0x08,0x0c,0x0c,0x08,0x0c,0x08,0x08,0x0c + .db 0x24,0x20,0x20,0x24,0x20,0x24,0x24,0x20 + .db 0x28,0x2c,0x2c,0x28,0x2c,0x28,0x28,0x2c + .db 0x20,0x24,0x24,0x20,0x24,0x20,0x20,0x24 + .db 0x2c,0x28,0x28,0x2c,0x28,0x2c,0x2c,0x28 + .db 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84 + .db 0x8c,0x88,0x88,0x8c,0x88,0x8c,0x8c,0x88 + .db 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80 + .db 0x88,0x8c,0x8c,0x88,0x8c,0x88,0x88,0x8c + .db 0xa4,0xa0,0xa0,0xa4,0xa0,0xa4,0xa4,0xa0 + .db 0xa8,0xac,0xac,0xa8,0xac,0xa8,0xa8,0xac + .db 0xa0,0xa4,0xa4,0xa0,0xa4,0xa0,0xa0,0xa4 + .db 0xac,0xa8,0xa8,0xac,0xa8,0xac,0xac,0xa8 + .db 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80 + .db 0x88,0x8c,0x8c,0x88,0x8c,0x88,0x88,0x8c + .db 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84 + .db 0x8c,0x88,0x88,0x8c,0x88,0x8c,0x8c,0x88 + .db 0xa0,0xa4,0xa4,0xa0,0xa4,0xa0,0xa0,0xa4 + .db 0xac,0xa8,0xa8,0xac,0xa8,0xac,0xac,0xa8 + .db 0xa4,0xa0,0xa0,0xa4,0xa0,0xa4,0xa4,0xa0 + .db 0xa8,0xac,0xac,0xa8,0xac,0xa8,0xa8,0xac + +; vim:set ts=8 noet nowrap + diff --git a/8080int.asm b/8080int.asm new file mode 100644 index 0000000..1acb38b --- /dev/null +++ b/8080int.asm @@ -0,0 +1,1736 @@ +; 8080 Interpreter. +; This is part of the Z80-CP/M emulator written by Sprite_tm. +; + +; Copyright (C) 2010 Sprite_tm +; Copyright (C) 2010 Leo C. +; Copyright (C) 2010 Horst S. + +; This file is part of avrcpm. +; +; avrcpm is free software: you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by +; the Free Software Foundation, either version 3 of the License, or +; (at your option) any later version. +; +; avrcpm is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with avrcpm. If not, see . +; +; $Id$ +; + +;-------------------------------------------------- +; Generate a table entry for one instruction +; +; instr fetch, op, store +; +.macro instr + .db low(@2), low(@1), high(@1), low(@0) +.endm + + + .dseg + +z_b: .byte 1 +z_c: .byte 1 +z_d: .byte 1 +z_e: .byte 1 +z_h: .byte 1 +z_l: .byte 1 + + + .cseg + +;Init z80 +z80_init: + ldi z_pcl,low (IPLADDR) + ldi z_pch,high(IPLADDR) + + cbi flags,trace + printnewline + printstring "Ok, CPU is live!" + printnewline + +;---------------------------------------------------------- +; 1 2 3 4 +;.db (low)do_store (low)do_op (hihg)do_op (low)do_fetch +; +;das kommt auf den stapel +; main da solls zum schluss weitergehen +;do_store wohin damit beenden mit RET +;do_op was tun beenden mit RET +; +;das wird direkt angesprungen +;do_fetch woher beenden mit RET +; +; +main: +.if INS_DEBUG + cbi flags,trace + cpi z_pch,DBG_TRACE_BOTTOM + brlo notraceon + cpi z_pch,DBG_TRACE_TOP + brsh notraceon + sbi flags,trace +notraceon: +.endif + + +.if PRINT_PC + cpi z_pch,DBG_TRACE_BOTTOM + brlo noprintpc + cpi z_pch,DBG_TRACE_TOP + brsh noprintpc + + printnewline + printstring "PC=" + movw temp,z_pcl + rcall printhexw + printstring " " +noprintpc: +.endif + +.if INS_DEBUG + sbic flags,trace + rcall printregs +.endif + + ;hier kommt die Interruptbehandlung rein + + ldi zl,low(main) ;da will ich wieder hin. + ldi zh,high(main) ; + push zl ; + push zh ; + mem_read_s z_pc ;temp=memReadByte(z_pc) + adiw z_pcl,1 ;++z_pc + ldi zl,low(todo_table*2) ;zhl=todo_table + ldi zh,high(todo_table*2) ; + ldi temp2,4 ;1 + mul temp,temp2 ;2 + add zl,r0 ;1 + adc zh,r1 ;1 + ldi temp2,high(store_ops) ; + lpm temp,Z+ ;do_store + push temp ; low + push temp2 ; high + + lpm temp,Z+ ;do_op + push temp ; low + lpm temp,Z+ ; high + push temp ; + + lpm zl,Z ;do_fetch + +;mov zh,temp2 ; + ldi zh,high(fetch_ops) + ijmp ;direkt + + + +; ------------ Fetch phase stuff ----------------- + +.org (PC+255) & 0xff00 ; wichtig !!!fetch und store muessen in einer page liegen +fetch_ops: +do_nop: + ret + +do_fetch_a: + mov opl,z_a + ret + +do_fetch_b: + lds opl,z_b + ret + +do_fetch_c: + lds opl,z_c + ret + +do_fetch_d: + lds opl,z_d + ret + +do_fetch_e: + lds opl,z_e + ret + +do_fetch_h: + lds opl,z_h + ret + +do_fetch_l: + lds opl,z_l + ret + +do_fetch_af: + mov opl,z_flags + mov oph,z_a + ret + +do_fetch_bc: + lds opl,z_c + lds oph,z_b + ret + +do_fetch_de: + lds opl,z_e + lds oph,z_d + ret + +do_fetch_hl: + lds opl,z_l + lds oph,z_h + ret + +do_fetch_sp: + movw opl,z_spl + ret + +do_fetch_mbc: + lds xh,z_b + lds xl,z_c + mem_read_d opl + ret + +do_fetch_mde: + lds xh,z_d + lds xl,z_e + mem_read_d opl + ret + +do_fetch_mhl: + lds xh,z_h + lds xl,z_l + mem_read_d opl + ret + +do_fetch_msp: + movw x,z_spl + mem_read_d opl + adiw x,1 + mem_read_d oph + ret + +do_fetch_dir8: + mem_read_ds opl, z_pc + adiw z_pcl,1 + ret + +do_fetch_dir16: + mem_read_ds opl, z_pc + adiw z_pcl,1 + mem_read_ds oph, z_pc + adiw z_pcl,1 + ret + +do_fetch_rst: + movw x,z_pcl + sbiw x,1 + mem_read_d opl + andi opl,0x38 + ldi oph,0 + ret + +; ------------ Store phase stuff ----------------- + +.org (PC+255) & 0xff00 ; wichtig !!!fetch und store muessen in einer page liegen +store_ops: + ret + +do_store_a: + mov z_a,opl + ret + +do_store_b: + sts z_b,opl + ret + +do_store_c: + sts z_c,opl + ret + +do_store_d: + sts z_d,opl + ret + +do_store_e: + sts z_e,opl + ret + +do_store_h: + sts z_h,opl + ret + +do_store_l: + sts z_l,opl + ret + +do_store_af: + mov z_a,oph + mov z_flags,opl + ret + +do_store_bc: + sts z_b,oph + sts z_c,opl + ret + +do_store_de: + sts z_d,oph + sts z_e,opl + ret + +do_store_hl: + sts z_h,oph + sts z_l,opl + ret + +do_store_mbc: + lds xh,z_b + lds xl,z_c + mem_write_s opl + ret + +do_store_mde: + lds xh,z_d + lds xl,z_e + mem_write_s opl + ret + +do_store_mhl: + lds xh,z_h + lds xl,z_l + mem_write_s opl + ret + +do_store_msp: + movw xl,z_spl + mem_write_s opl + adiw xl,1 + mem_write_s oph + ret + +do_store_sp: + movw z_spl,opl + ret + +do_store_pc: + movw z_pcl,opl + ret + +do_store_ret: + movw x,z_spl + mem_read_d z_pcl + adiw x,1 + mem_read_d z_pch + adiw x,1 + movw z_spl,x + +.if STACK_DBG + printnewline + printstring "Stack pop " + movw temp,z_pcl + rcall printhexw + printstring ", SP is now " + movw temp,z_spl + rcall printhexw + printstring ". " +.endif + ret + +do_store_call: + movw xl,z_spl + sbiw x,1 + mem_write_s z_pch + sbiw x,1 + mem_write_s z_pcl + movw z_spl,xl + +.if STACK_DBG + printnewline + printstring "Stack push " + movw temp,z_pcl + rcall printhexw + printstring ", SP is now " + movw temp,z_spl + rcall printhexw + printstring ". " +.endif + movw z_pcl,opl + ret + + +do_store_am: + mem_write_ds op, z_a + ret + +; ------------ Operation phase stuff ----------------- + + +;---------------------------------------------------------------- +;| | +;| 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 | +;|----------+------+--------------------------------------------| +;| 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 | +;---------------------------------------------------------------- + +;How the flags are supposed to work: +;7 ZFL_S - Sign flag (=MSBit of result) +;6 ZFL_Z - Zero flag. Is 1 when the result is 0 +;4 ZFL_H - Half-carry (carry from bit 3 to 4) +;2 ZFL_P - Parity/2-complement Overflow +;1 ZFL_N - Subtract - set if last op was a subtract +;0 ZFL_C - Carry +; +;I sure hope I got the mapping between flags and instructions correct... + +.equ ZFL_S = 7 +.equ ZFL_Z = 6 +.equ ZFL_H = 4 +.equ ZFL_P = 2 +.equ ZFL_N = 1 +.equ ZFL_C = 0 + +.equ AVR_T = SREG_T +.equ AVR_H = SREG_H +.equ AVR_S = SREG_S +.equ AVR_V = SREG_V +.equ AVR_N = SREG_N +.equ AVR_Z = SREG_Z +.equ AVR_C = SREG_C + +;------------------------------------------------; +; 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< (" + mov temp,opl + rcall printhex + printstring ") " +.endif + mov temp,z_a + mov temp2,opl + rcall portWrite + ret + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +;|IN A,[n] |------|Input |A=[n] | +; +; +do_op_in: ; in a,(opl) +.if PORT_DEBUG + printnewline + printstring "Port read: (" + mov temp,opl + rcall printhex + printstring ") -> " +.endif + + mov temp2,opl + rcall portRead + mov opl,temp + +.if PORT_DEBUG + rcall printhex + printstring " " +.endif + ret + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +;|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 | +; +; +do_op_inc: + inc opl +#if EM_Z80 + in temp, sreg +#endif + andi z_flags,(1<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. + do_z80_flags_op_rotate + lsr opl + brcc do_op_rrc_noc + ori opl, 0x80 + ori z_flags, (1<{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 ; 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 + ret + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +;|RLA |--0-0*|Rotate Left Acc. |A={CY,A}<- | +;|----------|SZHP C|---------- 8080 ----------------------------| +;|RLA |---- *|Rotate Left Acc. |A={CY,A}<- | +; +; +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 + ret + +;---------------------------------------------------------------- +;|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: + add z_a,opl + in temp,sreg + ldpmx z_flags,sz53p_tab,z_a ;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 | +; +; +do_op_adca: + clc + sbrc z_flags,ZFL_C + sec + adc z_a,opl + in temp,sreg + ldpmx z_flags,sz53p_tab,z_a ;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 | +;|----------|SZHP C|---------- 8080 ----------------------------| +;|SUB s |***P *|Subtract |A=A-s | + +; +do_op_subfa: + sub z_a,opl + in temp,sreg + ldpmx z_flags,sz53p_tab,z_a ;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 | +;---------------------------------------------------------------- +;|CP s |***V1*|Compare |A-s | +;|----------|SZHP C|---------- 8080 ----------------------------| +;|CP s |***P *|Compare |A-s | + +; +do_op_cpfa: + mov temp,z_a + sub temp,opl + mov opl,temp + in temp,sreg + 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 | +; +; +do_op_sbcfa: + clc + sbrc z_flags,ZFL_C + sec + sbc z_a,opl + in temp,sreg + ldpmx z_flags,sz53p_tab,z_a ;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 | +; +; TODO H-Flag +do_op_anda: + and z_a,opl ; + ldpmx z_flags,sz53p_tab,z_a ;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 | +; +; TODO: H-Flag +do_op_ora: + or z_a,opl + ldpmx z_flags,sz53p_tab,z_a ;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 | +; +; TODO: H-Flag +do_op_xora: + eor z_a,opl + ldpmx z_flags,sz53p_tab,z_a ;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 | +; +; +do_op_addhl: + lds temp,z_l + lds temp2,z_h + add opl,temp + adc oph,temp2 + in temp,sreg + bmov z_flags,ZFL_H, temp,AVR_H + bmov z_flags,ZFL_C, temp,AVR_C + do_z80_flags_clear_N + ret + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +;|LD dst,src|------|Load |dst=src | +; +; +do_op_sthl: ;store hl to mem loc in opl:h + movw xl,opl + lds temp,z_l + mem_write + adiw xl,1 + lds temp,z_h + mem_write + ret + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +;|LD dst,src|------|Load |dst=src | +; +; +do_op_rmem16: + movw xl,opl + mem_read_d opl + adiw x,1 + mem_read_d oph + ret + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +;|LD dst,src|------|Load |dst=src | +; +; +do_op_rmem8: + mem_read_ds opl, op + 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: + 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< 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 | +;-----------------------------Z80-------------------------------- +; +do_op_exhl: + lds temp,z_l + lds temp2,z_h + sts z_l,opl + sts z_h,oph + movw opl,temp + ret + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +; +; TODO: Implement IFF1, IFF2 +do_op_di: + ret + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +; +; 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 | +; +; +do_op_ifnz: + sbrs z_flags, ZFL_Z + ret + pop temp ; nix tun + pop temp ; direkt zuruech zu main + 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 | +; +; +do_op_ifz: + sbrc z_flags, ZFL_Z + ret + pop temp ; nix tun + pop temp ; direkt zuruech zu main + 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 | +; +; +do_op_ifnc: + sbrs z_flags, ZFL_C + ret + pop temp ; nix tun + pop temp ; direkt zuruech zu main + 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 | +; +; +do_op_ifc: + sbrc z_flags, ZFL_C + ret + pop temp ; nix tun + pop temp ; direkt zuruech zu main + 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 | +; +; +do_op_ifpo: + sbrs z_flags, ZFL_P + ret + pop temp ; nix tun + pop temp ; direkt zuruech zu main + 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 | +; +; +do_op_ifpe: + sbrc z_flags, ZFL_P + ret + pop temp ; nix tun + pop temp ; direkt zuruech zu main + 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 | +; +; +do_op_ifp: ;sign positive, aka s=0 + sbrs z_flags, ZFL_S + ret + pop temp ; nix tun + pop temp ; direkt zuruech zu main + 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 | +; +; +do_op_ifm: ;sign negative, aka s=1 + sbrc z_flags, ZFL_S + ret + pop temp ; nix tun + pop temp ; direkt zuruech zu main + ret + + +; ----------------------- Opcode decoding ------------------------- + +; Lookup table for Z80 opcodes. Translates the first byte of the instruction word into three +; operations: fetch, do something, store. +; The table is made of 256 words. + +;.org (PC+255) & 0xff00 +todo_table: +instr do_nop, do_NOP, do_nop ;00 ;NOP +instr do_fetch_DIR16, do_NOP, do_store_BC ;01 nn nn ;LD BC,nn +instr do_fetch_A, do_NOP, do_store_MBC ;02 ;LD (BC),A +instr do_fetch_BC, do_op_INC16, do_store_BC ;03 ;INC BC +instr do_fetch_B, do_op_INC, do_store_B ;04 ;INC B +instr do_fetch_B, do_op_DEC, do_store_B ;05 ;DEC B +instr do_fetch_DIR8, do_NOP, do_store_B ;06 ;LD B,n +instr do_fetch_A, do_op_RLC, do_store_A ;07 ;RLCA +instr do_nop, do_op_INV, do_nop ;08 ;EX AF,AF' +instr do_fetch_BC, do_op_ADDHL, do_store_HL ;09 ;ADD HL,BC +instr do_fetch_MBC, do_NOP, do_store_A ;0A ;LD A,(BC) +instr do_fetch_BC, do_op_DEC16, do_store_BC ;0B ;DEC BC +instr do_fetch_C, do_op_INC, do_store_C ;0C ;INC C +instr do_fetch_C, do_op_DEC, do_store_C ;0D ;DEC C +instr do_fetch_DIR8, do_NOP, do_store_C ;0E nn ;LD C,n +instr do_fetch_A, do_op_RRC, do_store_A ;0F ;RRCA +instr do_nop, do_op_INV, do_nop ;10 oo ;DJNZ o +instr do_fetch_DIR16, do_NOP, do_store_DE ;11 nn nn ;LD DE,nn +instr do_fetch_A, do_NOP, do_store_MDE ;12 ;LD (DE),A +instr do_fetch_DE, do_op_INC16, do_store_DE ;13 ;INC DE +instr do_fetch_D, do_op_INC, do_store_D ;14 ;INC D +instr do_fetch_D, do_op_DEC, do_store_D ;15 ;DEC D +instr do_fetch_DIR8, do_NOP, do_store_D ;16 nn ;LD D,n +instr do_fetch_A, do_op_RL, do_store_A ;17 ;RLA +instr do_NOP, do_op_INV, do_nop ;18 oo ;JR o +instr do_fetch_DE, do_op_ADDHL, do_store_HL ;19 ;ADD HL,DE +instr do_fetch_MDE, do_NOP, do_store_A ;1A ;LD A,(DE) +instr do_fetch_DE, do_op_DEC16, do_store_DE ;1B ;DEC DE +instr do_fetch_E, do_op_INC, do_store_E ;1C ;INC E +instr do_fetch_E, do_op_DEC, do_store_E ;1D ;DEC E +instr do_fetch_DIR8, do_NOP, do_store_E ;1E nn ;LD E,n +instr do_fetch_A, do_op_RR, do_store_A ;1F ;RRA +instr do_NOP, do_op_INV, do_nop ;20 oo ;JR NZ,o +instr do_fetch_DIR16, do_NOP, do_store_HL ;21 nn nn ;LD HL,nn +instr do_fetch_DIR16, do_op_STHL, do_nop ;22 nn nn ;LD (nn),HL +instr do_fetch_HL, do_op_INC16, do_store_HL ;23 ;INC HL +instr do_fetch_H, do_op_INC, do_store_H ;24 ;INC H +instr do_fetch_H, do_op_DEC, do_store_H ;25 ;DEC H +instr do_fetch_DIR8, do_NOP, do_store_H ;26 nn ;LD H,n +instr do_fetch_A, do_op_DA, do_store_A ;27 ;DAA +instr do_NOP, do_op_INV, do_nop ;28 oo ;JR Z,o +instr do_fetch_HL, do_op_ADDHL, do_store_HL ;29 ;ADD HL,HL +instr do_fetch_DIR16, do_op_RMEM16, do_store_HL ;2A nn nn ;LD HL,(nn) +instr do_fetch_HL, do_op_DEC16, do_store_HL ;2B ;DEC HL +instr do_fetch_L, do_op_INC, do_store_L ;2C ;INC L +instr do_fetch_L, do_op_DEC, do_store_L ;2D ;DEC L +instr do_fetch_DIR8, do_NOP, do_store_L ;2E nn ;LD L,n +instr do_NOP, do_op_CPL, do_nop ;2F ;CPL +instr do_NOP, do_op_INV, do_nop ;30 oo ;JR NC,o +instr do_fetch_DIR16, do_NOP, do_store_SP ;31 nn nn ;LD SP,nn +instr do_fetch_DIR16, do_NOP, do_store_AM ;32 nn nn ;LD (nn),A +instr do_fetch_SP, do_op_INC16, do_store_SP ;33 ;INC SP +instr do_fetch_MHL, do_op_INC, do_store_MHL ;34 ;INC (HL) +instr do_fetch_MHL, do_op_DEC, do_store_MHL ;35 ;DEC (HL) +instr do_fetch_DIR8, do_NOP, do_store_MHL ;36 nn ;LD (HL),n +instr do_NOP, do_op_SCF, do_nop ;37 ;SCF +instr do_NOP, do_op_INV, do_nop ;38 oo ;JR C,o +instr do_fetch_SP, do_op_ADDHL, do_store_HL ;39 ;ADD HL,SP +instr do_fetch_DIR16, do_op_RMEM8, do_store_A ;3A nn nn ;LD A,(nn) +instr do_fetch_SP, do_op_DEC16, do_store_SP ;3B ;DEC SP +instr do_NOP, do_op_INCA, do_nop ;3C ;INC A +instr do_NOP, do_op_DECA, do_nop ;3D ;DEC A +instr do_fetch_DIR8, do_NOP, do_store_A ;3E nn ;LD A,n +instr do_NOP, do_op_CCF, do_nop ;3F ;CCF (Complement Carry Flag, gvd) +instr do_fetch_B, do_NOP, do_store_B ;40 ;LD B,B +instr do_fetch_C, do_NOP, do_store_B ;41 ;LD B,C +instr do_fetch_D, do_NOP, do_store_B ;42 ;LD B,D +instr do_fetch_E, do_NOP, do_store_B ;43 ;LD B,E +instr do_fetch_H, do_NOP, do_store_B ;44 ;LD B,H +instr do_fetch_L, do_NOP, do_store_B ;45 ;LD B,L +instr do_fetch_MHL, do_NOP, do_store_B ;46 ;LD B,(HL) +instr do_fetch_A, do_NOP, do_store_B ;47 ;LD B,A +instr do_fetch_B, do_NOP, do_store_C ;48 ;LD C,B +instr do_fetch_C, do_NOP, do_store_C ;49 ;LD C,C +instr do_fetch_D, do_NOP, do_store_C ;4A ;LD C,D +instr do_fetch_E, do_NOP, do_store_C ;4B ;LD C,E +instr do_fetch_H, do_NOP, do_store_C ;4C ;LD C,H +instr do_fetch_L, do_NOP, do_store_C ;4D ;LD C,L +instr do_fetch_MHL, do_NOP, do_store_C ;4E ;LD C,(HL) +instr do_fetch_A, do_NOP, do_store_C ;4F ;LD C,A +instr do_fetch_B, do_NOP, do_store_D ;50 ;LD D,B +instr do_fetch_C, do_NOP, do_store_D ;51 ;LD D,C +instr do_fetch_D, do_NOP, do_store_D ;52 ;LD D,D +instr do_fetch_E, do_NOP, do_store_D ;53 ;LD D,E +instr do_fetch_H, do_NOP, do_store_D ;54 ;LD D,H +instr do_fetch_L, do_NOP, do_store_D ;55 ;LD D,L +instr do_fetch_MHL, do_NOP, do_store_D ;56 ;LD D,(HL) +instr do_fetch_A, do_NOP, do_store_D ;57 ;LD D,A +instr do_fetch_B, do_NOP, do_store_E ;58 ;LD E,B +instr do_fetch_C, do_NOP, do_store_E ;59 ;LD E,C +instr do_fetch_D, do_NOP, do_store_E ;5A ;LD E,D +instr do_fetch_E, do_NOP, do_store_E ;5B ;LD E,E +instr do_fetch_H, do_NOP, do_store_E ;5C ;LD E,H +instr do_fetch_L, do_NOP, do_store_E ;5D ;LD E,L +instr do_fetch_MHL, do_NOP, do_store_E ;5E ;LD E,(HL) +instr do_fetch_A, do_NOP, do_store_E ;5F ;LD E,A +instr do_fetch_B, do_NOP, do_store_H ;60 ;LD H,B +instr do_fetch_C, do_NOP, do_store_H ;61 ;LD H,C +instr do_fetch_D, do_NOP, do_store_H ;62 ;LD H,D +instr do_fetch_E, do_NOP, do_store_H ;63 ;LD H,E +instr do_fetch_H, do_NOP, do_store_H ;64 ;LD H,H +instr do_fetch_L, do_NOP, do_store_H ;65 ;LD H,L +instr do_fetch_MHL, do_NOP, do_store_H ;66 ;LD H,(HL) +instr do_fetch_A, do_NOP, do_store_H ;67 ;LD H,A +instr do_fetch_B, do_NOP, do_store_L ;68 ;LD L,B +instr do_fetch_C, do_NOP, do_store_L ;69 ;LD L,C +instr do_fetch_D, do_NOP, do_store_L ;6A ;LD L,D +instr do_fetch_E, do_NOP, do_store_L ;6B ;LD L,E +instr do_fetch_H, do_NOP, do_store_L ;6C ;LD L,H +instr do_fetch_L, do_NOP, do_store_L ;6D ;LD L,L +instr do_fetch_MHL, do_NOP, do_store_L ;6E ;LD L,(HL) +instr do_fetch_A, do_NOP, do_store_L ;6F ;LD L,A +instr do_fetch_B, do_NOP, do_store_MHL ;70 ;LD (HL),B +instr do_fetch_C, do_NOP, do_store_MHL ;71 ;LD (HL),C +instr do_fetch_D, do_NOP, do_store_MHL ;72 ;LD (HL),D +instr do_fetch_E, do_NOP, do_store_MHL ;73 ;LD (HL),E +instr do_fetch_H, do_NOP, do_store_MHL ;74 ;LD (HL),H +instr do_fetch_L, do_NOP, do_store_MHL ;75 ;LD (HL),L +instr do_NOP, do_op_INV, do_nop ;76 ;HALT +instr do_fetch_A, do_NOP, do_store_MHL ;77 ;LD (HL),A +instr do_fetch_B, do_NOP, do_store_A ;78 ;LD A,B +instr do_fetch_C, do_NOP, do_store_A ;79 ;LD A,C +instr do_fetch_D, do_NOP, do_store_A ;7A ;LD A,D +instr do_fetch_E, do_NOP, do_store_A ;7B ;LD A,E +instr do_fetch_H, do_NOP, do_store_A ;7C ;LD A,H +instr do_fetch_L, do_NOP, do_store_A ;7D ;LD A,L +instr do_fetch_MHL, do_NOP, do_store_A ;7E ;LD A,(HL) +instr do_fetch_A, do_NOP, do_store_A ;7F ;LD A,A +instr do_fetch_B, do_op_ADDA, do_nop ;80 ;ADD A,B +instr do_fetch_C, do_op_ADDA, do_nop ;81 ;ADD A,C +instr do_fetch_D, do_op_ADDA, do_nop ;82 ;ADD A,D +instr do_fetch_E, do_op_ADDA, do_nop ;83 ;ADD A,E +instr do_fetch_H, do_op_ADDA, do_nop ;84 ;ADD A,H +instr do_fetch_L, do_op_ADDA, do_nop ;85 ;ADD A,L +instr do_fetch_MHL, do_op_ADDA, do_nop ;86 ;ADD A,(HL) +instr do_fetch_A, do_op_ADDA, do_nop ;87 ;ADD A,A +instr do_fetch_B, do_op_ADCA, do_nop ;88 ;ADC A,B +instr do_fetch_C, do_op_ADCA, do_nop ;89 ;ADC A,C +instr do_fetch_D, do_op_ADCA, do_nop ;8A ;ADC A,D +instr do_fetch_E, do_op_ADCA, do_nop ;8B ;ADC A,E +instr do_fetch_H, do_op_ADCA, do_nop ;8C ;ADC A,H +instr do_fetch_L, do_op_ADCA, do_nop ;8D ;ADC A,L +instr do_fetch_MHL, do_op_ADCA, do_nop ;8E ;ADC A,(HL) +instr do_fetch_A, do_op_ADCA, do_nop ;8F ;ADC A,A +instr do_fetch_B, do_op_SUBFA, do_nop ;90 ;SUB A,B +instr do_fetch_C, do_op_SUBFA, do_nop ;91 ;SUB A,C +instr do_fetch_D, do_op_SUBFA, do_nop ;92 ;SUB A,D +instr do_fetch_E, do_op_SUBFA, do_nop ;93 ;SUB A,E +instr do_fetch_H, do_op_SUBFA, do_nop ;94 ;SUB A,H +instr do_fetch_L, do_op_SUBFA, do_nop ;95 ;SUB A,L +instr do_fetch_MHL, do_op_SUBFA, do_nop ;96 ;SUB A,(HL) +instr do_fetch_A, do_op_SUBFA, do_nop ;97 ;SUB A,A +instr do_fetch_B, do_op_SBCFA, do_nop ;98 ;SBC A,B +instr do_fetch_C, do_op_SBCFA, do_nop ;99 ;SBC A,C +instr do_fetch_D, do_op_SBCFA, do_nop ;9A ;SBC A,D +instr do_fetch_E, do_op_SBCFA, do_nop ;9B ;SBC A,E +instr do_fetch_H, do_op_SBCFA, do_nop ;9C ;SBC A,H +instr do_fetch_L, do_op_SBCFA, do_nop ;9D ;SBC A,L +instr do_fetch_MHL, do_op_SBCFA, do_nop ;9E ;SBC A,(HL) +instr do_fetch_A, do_op_SBCFA, do_nop ;9F ;SBC A,A +instr do_fetch_B, do_op_ANDA, do_nop ;A0 ;AND A,B +instr do_fetch_C, do_op_ANDA, do_nop ;A1 ;AND A,C +instr do_fetch_D, do_op_ANDA, do_nop ;A2 ;AND A,D +instr do_fetch_E, do_op_ANDA, do_nop ;A3 ;AND A,E +instr do_fetch_H, do_op_ANDA, do_nop ;A4 ;AND A,H +instr do_fetch_L, do_op_ANDA, do_nop ;A5 ;AND A,L +instr do_fetch_MHL, do_op_ANDA, do_nop ;A6 ;AND A,(HL) +instr do_fetch_A, do_op_ANDA, do_nop ;A7 ;AND A,A +instr do_fetch_B, do_op_XORA, do_nop ;A8 ;XOR A,B +instr do_fetch_C, do_op_XORA, do_nop ;A9 ;XOR A,C +instr do_fetch_D, do_op_XORA, do_nop ;AA ;XOR A,D +instr do_fetch_E, do_op_XORA, do_nop ;AB ;XOR A,E +instr do_fetch_H, do_op_XORA, do_nop ;AC ;XOR A,H +instr do_fetch_L, do_op_XORA, do_nop ;AD ;XOR A,L +instr do_fetch_MHL, do_op_XORA, do_nop ;AE ;XOR A,(HL) +instr do_fetch_A, do_op_XORA, do_nop ;AF ;XOR A,A +instr do_fetch_B, do_op_ORA, do_nop ;B0 ;OR A,B +instr do_fetch_C, do_op_ORA, do_nop ;B1 ;OR A,C +instr do_fetch_D, do_op_ORA, do_nop ;B2 ;OR A,D +instr do_fetch_E, do_op_ORA, do_nop ;B3 ;OR A,E +instr do_fetch_H, do_op_ORA, do_nop ;B4 ;OR A,H +instr do_fetch_L, do_op_ORA, do_nop ;B5 ;OR A,L +instr do_fetch_MHL, do_op_ORA, do_nop ;B6 ;OR A,(HL) +instr do_fetch_A, do_op_ORA, do_nop ;B7 ;OR A,A +instr do_fetch_B, do_op_CPFA, do_nop ;B8 ;CP A,B +instr do_fetch_C, do_op_CPFA, do_nop ;B9 ;CP A,C +instr do_fetch_D, do_op_CPFA, do_nop ;BA ;CP A,D +instr do_fetch_E, do_op_CPFA, do_nop ;BB ;CP A,E +instr do_fetch_H, do_op_CPFA, do_nop ;BC ;CP A,H +instr do_fetch_L, do_op_CPFA, do_nop ;BD ;CP A,L +instr do_fetch_MHL, do_op_CPFA, do_nop ;BE ;CP A,(HL) +instr do_fetch_A, do_op_CPFA, do_nop ;BF ;CP A,A +instr do_NOP, do_op_IFNZ, do_store_RET ;C0 ;RET NZ +instr do_NOP, do_op_POP16, do_store_BC ;C1 ;POP BC +instr do_fetch_DIR16, do_op_IFNZ, do_store_PC ;C2 nn nn ;JP NZ,nn +instr do_fetch_DIR16, do_NOP, do_store_PC ;C3 nn nn ;JP nn +instr do_fetch_DIR16, do_op_IFNZ, do_store_CALL ;C4 nn nn ;CALL NZ,nn +instr do_fetch_BC, do_op_PUSH16, do_nop ;C5 ;PUSH BC +instr do_fetch_DIR8, do_op_ADDA, do_nop ;C6 nn ;ADD A,n +instr do_fetch_RST, do_NOP, do_store_CALL ;C7 ;RST 0 +instr do_NOP, do_op_IFZ, do_store_RET ;C8 ;RET Z +instr do_NOP, do_nop, do_store_RET ;C9 ;RET +instr do_fetch_DIR16, do_op_IFZ, do_store_PC ;CA nn nn ;JP Z,nn +instr do_NOP, do_op_INV, do_nop ;CB ;(Z80 specific) +instr do_fetch_DIR16, do_op_IFZ, do_store_CALL ;CC nn nn ;CALL Z,nn +instr do_fetch_DIR16, do_NOP, do_store_CALL ;CD nn nn ;CALL nn +instr do_fetch_DIR8, do_op_ADCA, do_nop ;CE nn ;ADC A,n +instr do_fetch_RST, do_NOP, do_store_CALL ;CF ;RST 8H +instr do_NOP, do_op_IFNC, do_store_RET ;D0 ;RET NC +instr do_NOP, do_op_POP16, do_store_DE ;D1 ;POP DE +instr do_fetch_DIR16, do_op_IFNC, do_store_PC ;D2 nn nn ;JP NC,nn +instr do_fetch_DIR8, do_op_OUTA, do_nop ;D3 nn ;OUT (n),A +instr do_fetch_DIR16, do_op_IFNC, do_store_CALL ;D4 nn nn ;CALL NC,nn +instr do_fetch_DE, do_op_PUSH16, do_nop ;D5 ;PUSH DE +instr do_fetch_DIR8, do_op_SUBFA, do_nop ;D6 nn ;SUB n +instr do_fetch_RST, do_NOP, do_store_CALL ;D7 ;RST 10H +instr do_NOP, do_op_IFC, do_store_RET ;D8 ;RET C +instr do_NOP, do_nop, do_nop ;D9 ;EXX +instr do_fetch_DIR16, do_op_IFC, do_store_PC ;DA nn nn ;JP C,nn +instr do_fetch_DIR8, do_op_IN, do_store_A ;DB nn ;IN A,(n) +instr do_fetch_DIR16, do_op_IFC, do_store_CALL ;DC nn nn ;CALL C,nn +instr do_NOP, do_op_INV, do_nop ;DD ;(Z80 specific) +instr do_fetch_DIR8, do_op_SBCFA, do_nop ;DE nn ;SBC A,n +instr do_fetch_RST, do_NOP, do_store_CALL ;DF ;RST 18H +instr do_NOP, do_op_IFPO, do_store_RET ;E0 ;RET PO +instr do_NOP, do_op_POP16, do_store_HL ;E1 ;POP HL +instr do_fetch_DIR16, do_op_IFPO, do_store_PC ;E2 nn nn ;JP PO,nn +instr do_fetch_MSP, do_op_EXHL, do_store_MSP ;E3 ;EX (SP),HL +instr do_fetch_DIR16, do_op_IFPO, do_store_CALL ;E4 nn nn ;CALL PO,nn +instr do_fetch_HL, do_op_PUSH16, do_nop ;E5 ;PUSH HL +instr do_fetch_DIR8, do_op_ANDA, do_nop ;E6 nn ;AND n +instr do_fetch_RST, do_NOP, do_store_CALL ;E7 ;RST 20H +instr do_NOP, do_op_IFPE, do_store_RET ;E8 ;RET PE +instr do_fetch_HL, do_NOP, do_store_PC ;E9 ;JP HL +instr do_fetch_DIR16, do_op_IFPE, do_store_PC ;EA nn nn ;JP PE,nn +instr do_fetch_DE, do_op_EXHL, do_store_DE ;EB ;EX DE,HL +instr do_fetch_DIR16, do_op_IFPE, do_store_CALL ;EC nn nn ;CALL PE,nn +instr do_NOP, do_op_INV, do_nop ;ED ;(Z80 specific) +instr do_fetch_DIR8, do_op_XORA, do_nop ;EE nn ;XOR n +instr do_fetch_RST, do_NOP, do_store_CALL ;EF ;RST 28H +instr do_NOP, do_op_IFP, do_store_RET ;F0 ;RET P +instr do_NOP, do_op_POP16, do_store_AF ;F1 ;POP AF +instr do_fetch_DIR16, do_op_IFP, do_store_PC ;F2 nn nn ;JP P,nn +instr do_NOP, do_op_DI, do_nop ;F3 ;DI +instr do_fetch_DIR16, do_op_IFP, do_store_CALL ;F4 nn nn ;CALL P,nn +instr do_fetch_AF, do_op_PUSH16, do_nop ;F5 ;PUSH AF +instr do_fetch_DIR8, do_op_ORA, do_nop ;F6 nn ;OR n +instr do_fetch_RST, do_NOP, do_store_CALL ;F7 ;RST 30H +instr do_NOP, do_op_IFM, do_store_RET ;F8 ;RET M +instr do_fetch_HL, do_NOP, do_store_SP ;F9 ;LD SP,HL +instr do_fetch_DIR16, do_op_IFM, do_store_PC ;FA nn nn ;JP M,nn +instr do_NOP, do_op_EI, do_nop ;FB ;EI +instr do_fetch_DIR16, do_op_IFM, do_store_CALL ;FC nn nn ;CALL M,nn +instr do_NOP, do_op_INV, do_nop ;FD ;(Z80 specific) +instr do_fetch_DIR8, do_op_CPFA, do_nop ;FE nn ;CP n +instr do_fetch_RST, do_NOP, do_store_CALL ;FF ;RST 38H + +;---------------------------------------------------------------- +; Lookup table, stolen from z80ex, Z80 emulation library. +; http://z80ex.sourceforge.net/ + +; The S, Z, 5 and 3 bits and the parity of the lookup value + + .org (PC+255) & 0xff00 +sz53p_tab: + .db 0x44,0x00,0x00,0x04,0x00,0x04,0x04,0x00 + .db 0x08,0x0c,0x0c,0x08,0x0c,0x08,0x08,0x0c + .db 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04 + .db 0x0c,0x08,0x08,0x0c,0x08,0x0c,0x0c,0x08 + .db 0x20,0x24,0x24,0x20,0x24,0x20,0x20,0x24 + .db 0x2c,0x28,0x28,0x2c,0x28,0x2c,0x2c,0x28 + .db 0x24,0x20,0x20,0x24,0x20,0x24,0x24,0x20 + .db 0x28,0x2c,0x2c,0x28,0x2c,0x28,0x28,0x2c + .db 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04 + .db 0x0c,0x08,0x08,0x0c,0x08,0x0c,0x0c,0x08 + .db 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00 + .db 0x08,0x0c,0x0c,0x08,0x0c,0x08,0x08,0x0c + .db 0x24,0x20,0x20,0x24,0x20,0x24,0x24,0x20 + .db 0x28,0x2c,0x2c,0x28,0x2c,0x28,0x28,0x2c + .db 0x20,0x24,0x24,0x20,0x24,0x20,0x20,0x24 + .db 0x2c,0x28,0x28,0x2c,0x28,0x2c,0x2c,0x28 + .db 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84 + .db 0x8c,0x88,0x88,0x8c,0x88,0x8c,0x8c,0x88 + .db 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80 + .db 0x88,0x8c,0x8c,0x88,0x8c,0x88,0x88,0x8c + .db 0xa4,0xa0,0xa0,0xa4,0xa0,0xa4,0xa4,0xa0 + .db 0xa8,0xac,0xac,0xa8,0xac,0xa8,0xa8,0xac + .db 0xa0,0xa4,0xa4,0xa0,0xa4,0xa0,0xa0,0xa4 + .db 0xac,0xa8,0xa8,0xac,0xa8,0xac,0xac,0xa8 + .db 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80 + .db 0x88,0x8c,0x8c,0x88,0x8c,0x88,0x88,0x8c + .db 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84 + .db 0x8c,0x88,0x88,0x8c,0x88,0x8c,0x8c,0x88 + .db 0xa0,0xa4,0xa4,0xa0,0xa4,0xa0,0xa0,0xa4 + .db 0xac,0xa8,0xa8,0xac,0xa8,0xac,0xac,0xa8 + .db 0xa4,0xa0,0xa0,0xa4,0xa0,0xa4,0xa4,0xa0 + .db 0xa8,0xac,0xac,0xa8,0xac,0xa8,0xa8,0xac + +; vim:set ts=8 noet nowrap + diff --git a/Makefile b/Makefile index cc3eaf1..9fa980f 100644 --- a/Makefile +++ b/Makefile @@ -4,17 +4,18 @@ #MCU = atmega8 MCU = atmega328P -#F_CPU = 24576000 F_CPU = 20000000 #BAUD = 19200 BAUD = 57600 #BAUD = 115200 -TARGET = z80 -ASRC = z80.asm +DRAM_8BIT = 1 + +TARGET = avrcpm +ASRC = avrcpm.asm # Place -D or -U options here -CDEFS = -DF_CPU=$(F_CPU) -DBAUD=$(BAUD) -D$(MCU) +CDEFS = -DF_CPU=$(F_CPU) -DBAUD=$(BAUD) -D$(MCU) -DDRAM_8BIT=$(DRAM_8BIT) WINEPATH = C:/Programme/Atmel/AVR\ Tools/AvrAssembler2 DEFS = $(WINEPATH)/Appnotes diff --git a/avrcpm.asm b/avrcpm.asm new file mode 100644 index 0000000..10da302 --- /dev/null +++ b/avrcpm.asm @@ -0,0 +1,74 @@ +; Z80 emulator with CP/M support. The Z80-specific instructions themselves +; actually aren't implemented yet, making this more of an i8080 emulator. +; This is the main file, glueing all parts together. + +; Copyright (C) 2010 Sprite_tm +; Copyright (C) 2010 Leo C. +; +; This file is part of avrcpm. +; +; avrcpm is free software: you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by +; the Free Software Foundation, either version 3 of the License, or +; (at your option) any later version. +; +; avrcpm is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with avrcpm. If not, see . +; +; $Id$ +; + +.nolist +#if defined atmega8 + .include "m8def.inc" +#elif defined atmega168 + .include "m168def.inc" +#elif defined atmega328P + .include "m328Pdef.inc" +#else /* default */ + .include "m88def.inc" +#endif + .include "config.inc" + .include "macros.inc" +#if DRAM_8BIT /* Implies software uart */ + .include "dram-8bit.inc" +#else + .include "dram-4bit.inc" +#endif + .list + .cseg + .org 0 + rjmp start ; reset vector + + .org INT_VECTORS_SIZE + + .include "init.asm" + .include "mmc.asm" +; .include "mmc-old.asm" +#if DRAM_8BIT /* Implies software uart */ + .include "sw-uart.asm" + .include "dram-8bit.asm" +#else /* 4 bit RAM, hardware uart */ + .include "hw-uart.asm" + .include "dram-4bit.asm" +#endif + .include "remainders.asm" +; .include "z80int.asm" ;Old 8080 interpreter. +; .include "8080int.asm" ;New 8080 interpreter. +; .include "8080int-t3.asm" +; .include "8080int-t3-jmp.asm" + .include "8080int-jmp.asm" + + + .dseg +ramtop: .byte 0 + + .cseg + +; vim:set ts=8 noet nowrap + diff --git a/config.inc b/config.inc new file mode 100644 index 0000000..e14ef43 --- /dev/null +++ b/config.inc @@ -0,0 +1,287 @@ +; Configuration, hardware definition, ... +; +; Copyright (C) 2010 Sprite_tm +; Copyright (C) 2010 Leo C. +; +; This file is part of avrcpm. +; +; avrcpm is free software: you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by +; the Free Software Foundation, either version 3 of the License, or +; (at your option) any later version. +; +; avrcpm is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with avrcpm. If not, see . +; +; $Id$ +; + + +#define VMAJOR 2 /* Version number */ +#define VMINOR 0 + +#ifndef DRAM_8BIT + #define DRAM_8BIT 0 /* 1 = 8bit wide DRAM */ +#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 PARTID 0x52 /* Partition table id */ + /* http://www.win.tue.nl/~aeb/partitions/partition_types-1.html */ +#define K 1024 +#define M 1204*K + +;#define RAMSIZE 256*K*4 /* 1 chip 256Kx4 */ +#define RAMSIZE 4*M*4 * 2 /* 2 chips 4Mx4 */ + +#define RAMDISKCNT 0 /* Number of RAM disks */ +#define RAMDISKNR 'I'-'A' /* Drive "letter" for first RAM disk */ + +#define PARTID 0x52 /* Partition table id */ + /* http://www.win.tue.nl/~aeb/partitions/partition_types-1.html */ +#define IPLADDR 0x2000 /* Bootloader load address */ + +#define DRAM_WAITSTATES 1 /* Number of additional clock cycles for dram read access */ +#define REFR_RATE 64000 /* dram refresh rate in cycles/s. */ + /* Most drams need 1/15.6µs. */ +#define RXBUFSIZE 128 /* USART recieve buffer size. Must be power of 2 */ +#define TXBUFSIZE 128 /* USART transmit buffer size. Must be power of 2 */ + + + +#define EM_Z80 0 /* we don't have any z80 instructions yet */ + +.equ BOOT_DEBUG = 0 +.equ MMC_DEBUG = 0 /* Increase for more debugging */ +.equ INS_DEBUG = 0 +.equ MEMTEST = 1 +.equ BOOTWAIT = 1 +.equ PORT_DEBUG = 0 +.equ DISK_DEBUG = 0 /* Increase for more debugging */ +.equ HOSTRW_DEBUG= 0 +.equ MEMFILL = 1 +.equ STACK_DBG = 0 +.equ PRINT_PC = 0 + +#define MMC_SPI2X 1 /* 0 = SPI CLK/4, 1 = SPI CLK/2 */ + +#define MEMFILL_VAL 0xCB /* Fill ram with cbs, which will trigger an invalid opcode error. */ +#define DBG_TRACE_BOTTOM 0x01 /* Page boundaries for INS_DEBUG and PRINT_PC */ +#define DBG_TRACE_TOP 0xdc /* Trace is off, below bottom page and above top page. */ + +;----------------------------------------------------------------------- +; Port declarations + +#if DRAM_8BIT /* Implies software uart */ + +;Port D +.equ RAM_D0 = 0 +.equ RAM_D1 = 1 +.equ RAM_D2 = 2 +.equ RAM_D3 = 3 +.equ RAM_D4 = 4 +.equ RAM_D5 = 5 +.equ RAM_D6 = 6 +.equ RAM_D7 = 7 +.equ RAM_A0 = 0 +.equ RAM_A1 = 1 +.equ RAM_A2 = 2 +.equ RAM_A3 = 3 +.equ RAM_A4 = 4 +.equ RAM_A5 = 5 +.equ RAM_A6 = 6 +.equ RAM_A7 = 7 + +;Port B +.equ MMC_MOSI = 3 +.equ MMC_MISO = 4 +.equ MMC_SCK = 5 +.equ RAM_A8 = 3 +.equ RAM_A9 = 4 +.equ RAM_A10 = 5 + +.equ RXD = 0 +.equ TXD = 1 +.equ MMC_CS = 2 + +.equ P_MMC_CS = PORTB +.equ P_A8 = PORTB +.equ P_RXD = PORTB + +;Port C +.equ RAM_RAS = 0 +.equ RAM_CAS = 1 +.equ RAM_OE = 2 +.equ RAM_W = 3 + +.equ P_RAS = PORTC +.equ P_CAS = PORTC +.equ P_OE = PORTC +.equ P_W = PORTC + + +#else /* 4 bit RAM, hardware uart */ + +; Port D +.equ RXD = 0 +.equ TXD = 1 +.equ RAM_OE = 2 +.equ RAM_A8 = 3 +.equ MMC_CS = 4 +.equ RAM_A5 = 5 +.equ RAM_A6 = 6 +.equ RAM_A7 = 7 + +.equ P_RXD = PORTD +.equ P_OE = PORTD +.equ P_A8 = PORTD +.equ P_MMC_CS = PORTD +.equ P_AH = PORTD + ; RAM_A[7..5] +.equ RAM_AH_MASK = (1<. +; +; $Id$ +; + + +;---------------------------------------------- + +; Loads the byte on address xh:xl into temp. +; Uses temp2. Must not alter xh:xl + + .cseg +dram_read: +; cli + DRAM_SETADDR xh, ~0,(1<. +; +; $Id$ +; + + +; -------------------- DRAM macros--------------- + +; add wait states +; dram_wait number_of_cycles + +.macro dram_wait +.if @0 > 1 + rjmp PC+1 + dram_wait @0 - 2 +.elif @0 > 0 + nop + dram_wait @0 - 1 +.endif +.endm + +; ------------------------------------------------ + +; DRAM_SETADDR val, low_and_mask, low_or_mask, high_and_mask, high_or_mask + +.macro DRAM_SETADDR + mov temp,@0 +.if low(@1) != 0xff + andi temp,@1 +.endif +.if low(@2) != 0 + ori temp, @2 +.endif + out P_AL,temp + + mov temp,@0 +.if low(@3) != 0xff + andi temp,@3 +.endif + ori temp, @4 | (1<. +; +; $Id$ +; + + .cseg + +; ------------------ DRAM routines ------------- + +;Loads the byte on address xh:xl into temp. +;must not alter xh:xl + +dram_read: + cli ; + out PORTD,xh ;1 + out PORTC,_RAS0 ;1 + out PORTD,xl ;1 + out PORTC,_CAS0 ;1 + out DDRD,_0 ;1 + out PORTC,_OE ;1 + rjmp PC+1 ;2 + dram_wait DRAM_WAITSTATES ; + in temp,PIND ;1 + out PORTC,_255 ;1 + out DDRD,_255 ;1 + sei ; + ret + + + +;Writes the byte in temp to xh:xl +;must not alter xh:xl + +dram_write: + cli + out PORTD,xh ;1 + out PORTC,_RAS0 ;1 + out PORTD,xl ;1 + out PORTC,_CAS0 ;1 + out PORTD,temp ;1 + out PORTC,_WE ;1 + out PORTC,_255 ;1 = 7 + sei + ret + + diff --git a/dram-8bit.inc b/dram-8bit.inc new file mode 100644 index 0000000..a2b2e0c --- /dev/null +++ b/dram-8bit.inc @@ -0,0 +1,130 @@ +; DRAM interface for 2 RAM chips. Supports up to 4 Mbyte of DRAM. +; This is part of the Z80-CP/M emulator written by Sprite_tm. + +; Copyright (C) 2010 Leo C. + +; This file is part of avrcpm. +; +; avrcpm is free software: you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by +; the Free Software Foundation, either version 3 of the License, or +; (at your option) any later version. +; +; avrcpm is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with avrcpm. If not, see . +; +; $Id$ +; + + +; -------------------- DRAM macros--------------- + +; add wait states +; dram_wait number_of_cycles + +.macro dram_wait +.if @0 > 1 + rjmp PC+1 + dram_wait @0 - 2 +.elif @0 > 0 + nop + dram_wait @0 - 1 +.endif +.endm + +;---------------------------------------------- +; Read byte from DRAM +; mem_read_ds destreg, memaddr + +.macro mem_read_ds + cli ;1 + out PORTD,@1h ;1 + out PORTC,_RAS0 ;1 + out PORTD,@1l ;1 + out PORTC,_CAS0 ;1 + out DDRD,_0 ;1 + out PORTC,_OE ;1 + rjmp PC+1 ;2 + dram_wait DRAM_WAITSTATES ; + in @0,PIND ;1 + out PORTC,_255 ;1 + sei ;1 + out DDRD,_255 ;1 = 14 + DRAM_WAITSTATES +.endm + +;---------------------------------------------- +; Read byte from DRAM +; mem_read_d destreg +; x = memaddr + +.macro mem_read_d + mem_read_ds @0, x +.endm + +;---------------------------------------------- +; Read byte from DRAM +; mem_read_s memaddr +; temp = destreg + +.macro mem_read_s + mem_read_ds temp, @0 +.endm + +;---------------------------------------------- +; Read byte from DRAM +; mem_read +; temp = destreg, x = memaddr + +.macro mem_read + mem_read_ds temp, x +.endm + +;---------------------------------------------- +; Write byte to DRAM +; mem_write_ds memaddr, sourcereg + +.macro mem_write_ds + cli ;1 + out PORTD,@0h ;1 + out PORTC,_RAS0 ;1 + out PORTD,@0l ;1 + out PORTC,_CAS0 ;1 + out PORTD,@1 ;1 + out PORTC,_WE ;1 + sei ;1 + out PORTC,_255 ;1 = 9 +.endm + +;---------------------------------------------- +; Write byte to DRAM +; mem_write_d memaddr +; temp = srcreg + +.macro mem_write_d + mem_write_ds @0, temp +.endm + +;---------------------------------------------- +; Write byte to DRAM +; mem_write_s sourcereg +; xh = memaddrh, xl = memaddrl + +.macro mem_write_s + mem_write_ds x, @0 +.endm + +;---------------------------------------------- +; Write byte to DRAM +; mem_write +; xh = memaddrh, xl = memaddrl, temp = srcreg + +.macro mem_write + mem_write_ds x, temp +.endm + + diff --git a/hw-uart.asm b/hw-uart.asm new file mode 100644 index 0000000..e85721d --- /dev/null +++ b/hw-uart.asm @@ -0,0 +1,208 @@ +; Serial interface using the ATmega8/88 USART. +; This is part of the Z80-CP/M emulator written by Sprite_tm. +; +; Copyright (C) 2010 Leo C. +; +; This file is part of avrcpm. +; +; avrcpm is free software: you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by +; the Free Software Foundation, either version 3 of the License, or +; (at your option) any later version. +; +; avrcpm is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with avrcpm. If not, see . +; +; $Id$ +; + +#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) /* clever rounding */ + +#define RXBUFMASK RXBUFSIZE-1 +#define TXBUFMASK TXBUFSIZE-1 + + .dseg + +rxcount: + .byte 1 +rxidx_w: + .byte 1 +rxidx_r: + .byte 1 +txcount: + .byte 1 +txidx_w: + .byte 1 +txidx_r: + .byte 1 +rxfifo: + .byte RXBUFSIZE +txfifo: + .byte TXBUFSIZE + + + .cseg +; Init +uart_init: + + ldi temp, (1<= TXBUFSIZE) + + ldi zl,low(txfifo) ; + ldi zh,high(txfifo) ; + lds temp,txidx_w ; + add zl,temp ; + brcc PC+2 ; + inc zh ; + inc temp ; + andi temp,TXBUFMASK ; + sts txidx_w,temp ; txidx_w = ++txidx_w % TXBUFSIZE + pop temp ; + st z,temp ; txfifo[txidx_w] = char + cli + lds zl,txcount + inc zl + sts txcount,zl + ldi zl, (1<. +; +; $Id$ +; + +#define REFR_PRE 8 /* timer prescale factor 1/8 */ +#define REFR_CS 0x02 /* timer clock select for 1/8 */ +#define REFR_CNT F_CPU / REFR_RATE / REFR_PRE + + .cseg +regval_tab: + .db 0,0 + .db 0xFE,0xFC ; _RAS0 _CAS0 + .db 0xF8,0xF4 ; _OE _WE + .db 255,0 ; _255 _0 +regval_tab_e: + +start: + ldi temp,low(RAMEND) ; top of memory + out SPL,temp ; init stack pointer + ldi temp,high(RAMEND) ; top of memory + out SPH,temp ; init stack pointer + +; - Load some registers with constant values + + ldiw z,regval_tab*2 + ldiw y,0 +cp_l: lpm xh,z+ + st y+,xh + cpi zl,low(regval_tab_e*2) + brne cp_l + +; - Kill wdt + + wdr + out MCUSR,_0 + + ldi temp,(1<. +; +; $Id$ +; + +;------------------------------------------------ +; +.macro outm8 +.if @0 > 0x3f + sts @0,@1 +.else + out @0,@1 +.endif +.endm + +;------------------------------------------------ +; +.macro inm8 +.if @1 > 0x3f + lds @0,@1 +.else + in @0,@1 +.endif +.endm + +;------------------------------------------------ +; +.macro sbism8 +.if @0 > 0x1f + in _tmp0,@0 + sbrs _tmp0,@1 +.else + sbis @0,@1 +.endif +.endm + +;------------------------------------------------ +; load 16 bit constant to register pair + +.macro ldiw + ldi @0l, low(@1) + ldi @0h, high(@1) +.endm + +;------------------------------------------------ +; add 16 bit constant to register pair + +.macro addiw + subi @0l, low(-@1) + sbci @0h, high(-@1) +.endm + +;------------------------------------------------ +; Move single bit between two registers +; +; bmov dstreg,dstbit,srcreg.srcbit + +.macro bmov + bst @2,@3 + bld @0,@1 +.endm + +;------------------------------------------------ +; Print string. +; printstring "String" + +.macro printstring + rcall printstr + .if strlen(@0) % 2 + .db @0,0 + .else + .db @0,0,0 + .endif +.endm + +;------------------------------------------------ +; Print newline +; print cr, lf + +.macro printnewline + rcall printstr + .db 13,0 +.endm + + +;------------------------------------------------ +; Print a Z80 flag +; print_zflag F +; where F is the flag to print + +.macro print_zflag + +.set S_ = 'S' +.set Z_ = 'Z' +.set H_ = 'H' +.set P_ = 'P' +.set N_ = 'N' +.set C_ = 'C' + + ldi temp, ' ' + sbrc z_flags,ZFL_@0 + ldi temp, @0_ + rcall uartputc +.endm + +;------------------------------------------------ +; db_version VMAJOR, VMINOR + +.macro db_version + + .set maj1_ = @0 / 10 + .set maj0_ = @0 % 10 + .set min1_ = @1 / 10 + .set min0_ = @1 % 10 + + .if maj1_ + .if min1_ + .db maj1_+'0',maj0_+'0','.',min1_+'0',min0_+'0',0 + .else + .db maj1_+'0',maj0_+'0','.', min0_+'0',0,0 + .endif + .else + .if min1_ + .db maj0_+'0','.',min1_+'0',min0_+'0',0,0 + .else + .db maj0_+'0','.', min0_+'0',0 + .endif + .endif +.endm + +; vim:set ts=8 noet nowrap + diff --git a/mmc-old.asm b/mmc-old.asm new file mode 100644 index 0000000..edb2bbf --- /dev/null +++ b/mmc-old.asm @@ -0,0 +1,291 @@ +; ----------------- MMC/SD routines ------------------ + +mmcByteNoSend: + ldi temp,0xff +mmcByte: + +.if MMC_DEBUG + printstring "MMC: <--" + rcall printhex +.endif + + out SPDR,temp +mmcWrByteW: + in temp,SPSR + sbrs temp,7 + rjmp mmcWrByteW + in temp,SPDR + +.if MMC_DEBUG + printstring ", -->" + rcall printhex + printnewline +.endif + ret + + +;Wait till the mmc answers with the response in temp2, or till a timeout happens. +mmcWaitResp: + ldiw z,0 +mmcWaitResploop: + rcall mmcByteNoSend + cpi temp,0xff + brne mmcWaitResploopEnd + adiw zl,1 + cpi zh,255 + breq mmcWaitErr + rjmp mmcWaitResploop +mmcWaitResploopEnd: + ret + + +mmcWaitErr: + mov temp,temp2 + rcall printhex + printstring ": Error: MMC resp timeout!" + printnewline + rjmp resetAVR + +mmcInit: + ldi temp,0x53 + out SPCR,temp + + ;Init start: send 80 clocks with cs disabled + sbi P_MMC_CS,mmc_cs + +; ldi temp2,20 + ldi temp2,10 ; exactly 80 clocks +mmcInitLoop: + mov temp,temp2 + rcall mmcByte + dec temp2 + brne mmcInitLoop + + cbi P_MMC_CS,mmc_cs + rcall mmcByteNoSend + rcall mmcByteNoSend + rcall mmcByteNoSend + rcall mmcByteNoSend + rcall mmcByteNoSend + rcall mmcByteNoSend + sbi P_MMC_CS,mmc_cs + rcall mmcByteNoSend + rcall mmcByteNoSend + rcall mmcByteNoSend + rcall mmcByteNoSend + + ;Send init command + cbi P_MMC_CS,mmc_cs + ldi temp,0xff ;dummy + rcall mmcByte + ldi temp,0xff ;dummy + rcall mmcByte + ldi temp,0x40 ;cmd + rcall mmcByte + ldi temp,0 ;pxh + rcall mmcByte + ldi temp,0 ;pxl + rcall mmcByte + ldi temp,0 ;pyh + rcall mmcByte + ldi temp,0 ;pyl + rcall mmcByte + ldi temp,0x95 ;crc + rcall mmcByte + ldi temp,0xff ;return byte + rcall mmcByte + + ldi temp2,0 ;Error Code 0 + rcall mmcWaitResp ;Test on CMD0 is OK + + sbi P_MMC_CS,mmc_cs ;disable /CS + rcall mmcByteNoSend + + +;Read OCR till card is ready + ldi temp2,100 ;repeat counter +mmcInitOcrLoop: + push temp2 + + cbi P_MMC_CS,mmc_cs ;enable /CS + ldi temp,0xff ;dummy + rcall mmcByte + ldi temp,0x41 ;cmd + rcall mmcByte + ldi temp,0 ;pxh + rcall mmcByte + ldi temp,0 ;pxl + rcall mmcByte + ldi temp,0 ;pyh + rcall mmcByte + ldi temp,0 ;pyl + rcall mmcByte +; ldi temp,0x95 ;crc + ldi temp,0x01 ;crc + rcall mmcByte + rcall mmcByteNoSend + + ldi temp2,1 + rcall mmcWaitResp ;wait until mmc-card send a byte <> 0xFF + ;the first answer must be 0x01 (Idle-Mode) + cpi temp,0 + breq mmcInitOcrLoopDone ;second answer is 0x00 (Idle-Mode leave) CMD1 is OK + + sbi P_MMC_CS,mmc_cs ;disable /CS + + rcall mmcByteNoSend + + ldi temp,10 + rcall delay_ms + + pop temp2 + dec temp2 + brne mmcInitOcrLoop ;repeat + + ldi temp2,4 + rjmp mmcWaitErr + +mmcInitOcrLoopDone: + pop temp2 + sbi P_MMC_CS,mmc_cs ;disable /CS + rcall mmcByteNoSend + + out SPCR,_0 + ret + + +;Call this with yh:yl:xh:xl = sector number +; +mmcReadSect: + ldi temp,0x50 + out SPCR,temp + + cbi P_MMC_CS,mmc_cs + rcall mmcByteNoSend + ldi temp,0x51 ;cmd (read sector) + rcall mmcByte + lsl xl ;convert to byte address (*512) + rol xh + rol yl + mov temp,yl + rcall mmcByte + mov temp,xh ;pxl + rcall mmcByte + mov temp,xl ;pyh + rcall mmcByte + ldi temp,0 ;pyl + rcall mmcByte + ldi temp,0x95 ;crc + rcall mmcByte + ldi temp,0xff ;return byte + rcall mmcByte + + ;resp + ldi temp2,2 + rcall mmcWaitResp + + ;data token + ldi temp2,3 + rcall mmcWaitResp + + ;Read sector to AVR RAM + ldiw z,hostbuf +mmcreadloop: + rcall mmcByteNoSend + st z+,temp + cpi zl,low(hostbuf+512) + brne mmcreadloop + cpi zh,high(hostbuf+512) + brne mmcreadloop + + ;CRC + rcall mmcByteNoSend + rcall mmcByteNoSend + + sbi P_MMC_CS,mmc_cs + rcall mmcByteNoSend + + out SPCR,_0 + ret + + +;Call this with yh:yl:xh:xl = sector number +; +mmcWriteSect: + ldi temp,0x50 + out SPCR,temp + + cbi P_MMC_CS,mmc_cs + rcall mmcByteNoSend + + ldi temp,0x58 ;cmd (write sector) + rcall mmcByte + lsl xl ;convert to byte address (*512) + rol xh + rol yl + mov temp,yl + rcall mmcByte + mov temp,xh ;pxl + rcall mmcByte + mov temp,xl ;pyh + rcall mmcByte + ldi temp,0 ;pyl + rcall mmcByte + ldi temp,0x95 ;crc + rcall mmcByte + ldi temp,0xff ;return byte + rcall mmcByte + + ;resp + ldi temp2,1 + rcall mmcWaitResp + + ;Send data token + ldi temp,0xfe + rcall mmcByte + + ;Write sector from AVR RAM + ldiw z,hostbuf +mmcwriteloop: + ld temp,z+ + rcall mmcByte + cpi zl,low(hostbuf+512) + brne mmcwriteloop + cpi zh,high(hostbuf+512) + brne mmcwriteloop + + ;CRC + rcall mmcByteNoSend + rcall mmcByteNoSend + + ;Status. Ignored for now. + rcall mmcByteNoSend + +;Wait till the mmc has written everything +mmcwaitwritten: + rcall mmcByteNoSend + cpi temp,0xff + brne mmcwaitwritten + + sbi P_MMC_CS,mmc_cs + rcall mmcByteNoSend + + out SPCR,_0 + ret + + +;Set up wdt to time out after 1 sec. +resetAVR: + lds temp,txcount ;Wait, till tx buffer is empty + tst temp + brne resetAVR + + cli + ldi temp,(1<. +; +; $Id$ +; + +/* Definitions for MMC/SDC command */ +#define CMD0 (0) /* GO_IDLE_STATE */ +#define CMD1 (1) /* SEND_OP_COND (MMC) */ +#define ACMD41 (0x80+41) /* SEND_OP_COND (SDC) */ +#define CMD8 (8) /* SEND_IF_COND */ +#define CMD9 (9) /* SEND_CSD */ +#define CMD10 (10) /* SEND_CID */ +#define CMD12 (12) /* STOP_TRANSMISSION */ +#define ACMD13 (0x80+13) /* SD_STATUS (SDC) */ +#define CMD16 (16) /* SET_BLOCKLEN */ +#define CMD17 (17) /* READ_SINGLE_BLOCK */ +#define CMD18 (18) /* READ_MULTIPLE_BLOCK */ +#define CMD23 (23) /* SET_BLOCK_COUNT (MMC) */ +#define ACMD23 (0x80+23) /* SET_WR_BLK_ERASE_COUNT (SDC) */ +#define CMD24 (24) /* WRITE_BLOCK */ +#define CMD25 (25) /* WRITE_MULTIPLE_BLOCK */ +#define CMD55 (55) /* APP_CMD */ +#define CMD58 (58) /* READ_OCR */ + +/* Disk Status Bits (DSTATUS) */ +#define MMCST_NOINIT 0x01 /* Drive not initialized */ +#define MMCST_NODISK 0x02 /* No medium in the drive */ +#define MMCST_PROTECT 0x04 /* Write protected */ + +/* Card type flags (CardType) */ +#define CT_MMC 0x01 /* MMC ver 3 */ +#define CT_SD1 0x02 /* SD ver 1 */ +#define CT_SD2 0x04 /* SD ver 2 */ +#define CT_SDC (CT_SD1|CT_SD2) /* SD */ +#define CT_BLOCK 0x08 /* Block addressing */ + +#define RES_OK 0 /* 0: Successful */ +#define RES_ERROR 1 /* 1: R/W Error */ +#define RES_WRPRT 2 /* 2: Write Protected */ +#define RES_NOTRDY 3 /* 3: Not Ready */ +#define RES_PARERR 4 /* 4: Invalid Parameter */ + +;------------------------------------------------ +; +.macro spi_clkslow +.if MMC_DEBUG > 1 + printstring "SPI_CLK_SLOW " +.endif + ldi temp,(1< 1 + printstring "SPI_CLK_FAST " +.endif + ldi temp,(1< 1 + printstring "SPI_DISABLE " +.endif + out SPCR,_0 +.endm + + +;------------------------------------------------ +; +.macro spi_waitm + .set spiwl_ = PC + sbism8 SPSR,SPIF + rjmp spiwl_ +.endm + +;------------------------------------------------ + + .dseg + +mmcStat: + .byte 1 +mmcCardType: + .byte 1 +mmc_ocr: + .byte 4 + + + + .cseg + +;------------------------------------------------ +; Multiply 32 bit value in yh,yl,xh,xl by 512 + +mul_yx_512: + mov yh,yl + mov yl,xh + mov xh,xl + ldi xl,0 + lsl xh + rol yl + rol yh + ret + +;------------------------------------------------ +spi_rcvr: + out SPDR,_255 +spi_rcvr_l: + sbism8 SPSR,SPIF + rjmp spi_rcvr_l + in temp,SPDR +.if MMC_DEBUG > 2 + push temp + printstring "<" + rcall printhex + printstring " " + pop temp +.endif + ret + +;------------------------------------------------ +spi_xmit: +.if MMC_DEBUG > 2 + printstring ">" + rcall printhex + printstring " " +.endif + out SPDR,temp + ;fall thru +spi_wait: + sbism8 SPSR,SPIF + rjmp spi_wait + ret + +;------------------------------------------------ +; Wait for card ready +; return 1:OK, 0:Timeout + +mmcWaitReady: + push temp2 + ldi temp2,2 ;Wait for ready in timeout of 500ms. + rcall spi_rcvr +mmc_wrl: + sts delay_timer2,_255 +mmc_wrl1: + rcall spi_rcvr + cp temp,_255 + brne mmc_wrl2 + ldi temp,1 + rjmp mmc_wrbreak + +mmc_wrl2: + lds temp,delay_timer2 + cpi temp,0 + brne mmc_wrl1 + dec temp2 + brne mmc_wrl ;tmp is 0 here + +mmc_wrbreak: + pop temp2 + tst temp ;set flags + ret + + +;------------------------------------------------ +; Deselect the card and release SPI bus +; return 0 + +mmcDeselect: + sbi P_MMC_CS,mmc_cs ; CS high + rcall spi_rcvr + clr temp + ret + +;------------------------------------------------ +; Select the card and wait for ready +; return 255:Successful, 0:Timeout + +mmcSelect: + cbi P_MMC_CS,mmc_cs ; CS low + rcall mmcWaitReady + breq mmcDeselect ;return via Deselect + sbr temp,255 + ret + + +;------------------------------------------------ +; Send a command packet to MMC +; temp2: Command +; yh..xl: Argument + +mmcCmd: + sbrs temp2,7 + rjmp mmc_cmddo + +; ACMD is the command sequence of CMD55-CMD + + push yh + push yl + push xh + push xl + push temp2 + ldiw y,0 + movw x,y + ldi temp2,CMD55 + rcall mmcCmd + pop temp2 + pop xl + pop xh + pop yl + pop yh + + cpi temp,2 + brlo mmc_cmddo ; fall thru, if (retval <= 1) + + tst temp + ret ; else return error + +; Select the card and wait for ready + +mmc_cmddo: +.if MMC_DEBUG + sbrc temp2,7 + rjmp dmmccmd_nonl + printnewline + +dmmccmd_nonl: + printstring "mmcCMD: " + mov temp,temp2 + cbr temp,0x80 + rcall printhex + printstring " " + push temp2 + movw temp,y + rcall printhexw + movw temp,x + rcall printhexw + printstring " " + pop temp2 +.endif + rcall mmcDeselect + rcall mmcSelect + brne mmc_cmd_p + + ldi temp,0xFF + rjmp mmc_cmdexit + +; Send command packet + +mmc_cmd_p: + mov temp,temp2 + cbr temp,0x80 + sbr temp,0x40 + rcall spi_xmit + out SPDR,yh + rcall spi_wait + out SPDR,yl + rcall spi_wait + out SPDR,xh + rcall spi_wait + out SPDR,xl + rcall spi_wait + + ldi temp,0x95 ;CRC for CMD0(0) + cpi temp2,CMD0 + breq mmc_cmdxcrc + ldi temp,0x87 ;CRC for CMD8(0x1AA) + cpi temp2,CMD8 + breq mmc_cmdxcrc + ldi temp,0x01 ;Dummy CRC + Stop +mmc_cmdxcrc: +.if MMC_DEBUG + printstring ".. " + rcall printhex +.endif + rcall spi_xmit + +; Receive command response + + cpi temp2,CMD12 ; Skip a stuff byte when stop reading + brne mmc_cmdres + rcall spi_rcvr + +; Wait for a valid response in timeout of 10 attempts + +mmc_cmdres: + ldi temp,10 + mov _tmp1,temp +mmc_cmdrl: + rcall spi_rcvr + sbrs temp,7 + rjmp mmc_cmdexit + dec _tmp1 + brne mmc_cmdrl + +; Return with response value + +mmc_cmdexit: +.if MMC_DEBUG + printstring " CMDRes: " + rcall printhex + printstring " " + rcall uart_wait_empty +.endif + tst temp ;set flags + ret + +;------------------------------------------------ +; Check if 1 sec timeout +; return Z-Flag set, if timeout + +mmc_timeout_1s: + lds temp,delay_timer1 + tst temp + brne mmc_ttex + dec temp4 + breq mmc_ttex + ldi temp,100 + sts delay_timer1,temp +mmc_ttex: + ret + + +;------------------------------------------------ +; "Public" functions +;------------------------------------------------ + +;------------------------------------------------ +; Initialize MMC/SD card + +mmcInit: +.if MMC_DEBUG + printnewline + printstring "mmcInit " +.endif + lds temp,mmcStat ;Set 'NO INIT' status + sbr temp,MMCST_NOINIT + sts mmcStat,temp + + spi_clkslow + ldi temp2,10 +mmci_lp: + rcall spi_rcvr + dec temp2 ;80 dummy clocks + brne mmci_lp + + ldi temp3,0 ;Card type + ldi temp2,CMD0 + ldiw y,0 + movw x,y + rcall mmcCmd ;Enter Idle state + cpi temp,1 + breq mmci_1 + rjmp mmci_lend +mmci_1: + ldi temp4,10 ;Initialization timeout of 1000 ms. + ldi temp,100 + sts delay_timer1,temp + ldi temp2,CMD8 + ldiw y,0 + ldi xh,0x01 + ldi xl,0xAA + rcall mmcCmd + cpi temp,1 ;SDv2? + brne mmci_sdv1 + +; Get trailing return value of R7 response + + ldi temp2,4 + ldiw z,mmc_ocr +mmci_v2l1: + rcall spi_rcvr + st z+,temp + dec temp2 + brne mmci_v2l1 + sbiw z,4 + ldd temp,z+2 + cpi temp,0x01 + ldd temp,z+3 + cpc temp,xl ;Reuse 0xAA value in xl + brne mmci_sdv1 + +; The card can work at vdd range of 2.7-3.6V. +; Wait for leaving idle state (ACMD41 with HCS bit). + + ldi temp2,ACMD41 + ldi yh,0x40 + ldi yl,0 + ldi xh,0 + ldi xl,0 +mmci_v2l2: + rcall mmcCmd + breq mmci_ccc + rcall mmc_timeout_1s + brne mmci_v2l2 + rjmp mmci_sdv2end + +; Check CCS bit in the OCR +mmci_ccc: + ldi temp2,CMD58 + ldi yh,0 + rcall mmcCmd + brne mmci_sdv2end + + ldi temp2,4 +mmci_v2l3: + rcall spi_rcvr + st z+,temp + dec temp2 + brne mmci_v2l3 + sbiw z,4 + + sbr temp3,CT_SD2 + ldd temp,z+0 + sbrc temp,6 + sbr temp3,CT_BLOCK + +mmci_sdv2end: + rjmp mmci_lend + +; SDv1 or MMCv3 + +mmci_sdv1: + ldi temp2,ACMD41 + ldiw y,0 + movw x,y + rcall mmcCmd + cpi temp,2 + brsh mmci_mmcv3 + sbr temp3,CT_SD1 ;SDv1 + ldi temp2,ACMD41 + rjmp mmci_v1_l +mmci_mmcv3: + sbr temp3,CT_MMC ;MMCv3 + ldi temp2,CMD1 + +; Wait for leaving idle state +mmci_v1_l: + rcall mmcCmd + breq mmci_v1_2 + rcall mmc_timeout_1s + brne mmci_v1_l + rjmp mmci_lend ;Timeout + +; Set R/W block length to 512 +mmci_v1_2: + ldi temp2,CMD16 + ldiw x,512 + rcall mmcCmd + breq mmci_lend + ldi temp3,0 + +mmci_lend: + sts mmcCardType,temp3 + rcall mmcDeselect + +; Initialization succeded? + + lds temp,mmcStat + tst temp3 + breq mmci_lex + cbr temp,MMCST_NOINIT ;Yes, clear 'NO INIT' status + sts mmcStat,temp +mmci_lex: + +.if MMC_DEBUG + printnewline + printstring " CT: " + push temp + lds temp,mmcCardType + rcall printhex + pop temp + printstring " InitRes: " + rcall printhex + printstring " " +.endif + + spi_disable + ret + + +;-------------------------------------------------------------- +; Read sector +; z: Pointer to the data buffer to store read data +; yh..xl: Start sector number (LBA) + +mmcReadSect: +.if MMC_DEBUG > 1 + printnewline + printstring "mmcRdSect " +.endif + ldiw z,hostbuf ;for now + + lds _tmp0,mmcStat + ldi temp,RES_NOTRDY + sbrc _tmp0,MMCST_NOINIT + ret + + spi_clkfast + lds temp,mmcCardType + sbrs temp,log2(CT_BLOCK) + rcall mul_yx_512 ;Convert to byte address (*512) + + ldi temp2,CMD17 + rcall mmcCmd + ldi temp2,RES_ERROR + brne mmc_rdex + +; Receive a data packet from MMC + + ldiw y,512 ;Number of bytes to tranfer + ldi temp,200 ;Wait for data packet in timeout of 200ms. + sts delay_timer1,temp +mmc_rcv_wl: + rcall spi_rcvr + cp temp,_255 + brne mmc_rcv_start + lds _tmp0,delay_timer1 + cp _tmp0,_0 + brne mmc_rcv_wl +.if MMC_DEBUG > 1 + printstring "TIMEOUT " + rjmp mmc_rcv_dbg1 +.endif + +mmc_rcv_start: +.if MMC_DEBUG > 1 + cpi temp,0xFE ;If not valid data token, + breq mmc_rcv_dbg1 + printstring "Token: " + rcall printhex + printstring " " +mmc_rcv_dbg1: +.endif + cpi temp,0xFE ;If not valid data token, + brne mmc_rdex + + rcall spi_rcvr ;Shift in first byte. + out SPDR,_255 ;Start shift in next byte. +mmc_rcv_rl: + sbiw yl,1 + breq mmc_rcv_rle + st z+,temp + spi_waitm + in temp,SPDR + out SPDR,_255 + rjmp mmc_rcv_rl + +mmc_rcv_rle: + st z+,temp ;Store last byte in buffer + rcall spi_wait ; while SPI module shifts in crc part1. + rcall spi_rcvr ;Read second crc. + + ldi temp2,RES_OK ;Return success +mmc_rdex: + rcall mmcDeselect + spi_disable + mov temp,temp2 +.if MMC_DEBUG > 1 + printstring "RdSectRes: " + rcall printhex + printstring " " +.endif + ret + + +;-------------------------------------------------------------- +; Write sector +; z: Pointer to the data to be written +; yh..xl: Sector number (LBA) + +mmcWriteSect: +.if MMC_DEBUG > 1 + printnewline + printstring "mmcWrSect " +.endif + ldiw z,hostbuf ;for now + + lds _tmp0,mmcStat + ldi temp,RES_NOTRDY + sbrc _tmp0,MMCST_NOINIT + ret + + spi_clkfast + lds temp,mmcCardType + sbrs temp,log2(CT_BLOCK) + rcall mul_yx_512 ;Convert to byte address (*512) + + ldi temp2,CMD24 + rcall mmcCmd + brne mmc_wrexer + +; Send a data packet to MMC + +.if MMC_DEBUG > 2 +; printnewline + printstring "mmcXMIT " +.endif + rcall mmcWaitReady + breq mmc_wrexer + + ldi temp,0xFE ;Data token + out SPDR,temp + ldiw y,512 +mmc_x_loop: + ld temp,z+ + spi_waitm + out SPDR,temp + sbiw yl,1 + brne mmc_x_loop + + rcall spi_wait + ldi temp,0xFF ;dummy crc + rcall spi_xmit + rcall spi_xmit + rcall spi_rcvr +.if MMC_DEBUG > 2 + printstring "XMITRes: " + rcall printhex + printstring " " +.endif + andi temp,0x1F ;If not accepted, return with error + cpi temp,0x05 + ldi temp2,RES_OK ;Return success + breq mmc_wrex + +mmc_wrexer: + ldi temp,RES_ERROR +mmc_wrex: + rcall mmcDeselect + spi_disable + mov temp,temp2 +.if MMC_DEBUG > 1 + printstring "WrSectRes: " + rcall printhex + printstring " " +.endif + ret + +;-------------------------------------------------------------- +; vim:set ts=8 noet nowrap + diff --git a/remainders.asm b/remainders.asm new file mode 100644 index 0000000..2af7532 --- /dev/null +++ b/remainders.asm @@ -0,0 +1,1590 @@ +; Various functions: init, (RAM) disk, mmc, timer +; This file needs to get split up. +; +; Copyright (C) 2010 Sprite_tm +; Copyright (C) 2010 Leo C. +; +; This file is part of avrcpm. +; +; avrcpm is free software: you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by +; the Free Software Foundation, either version 3 of the License, or +; (at your option) any later version. +; +; avrcpm is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with avrcpm. If not, see . +; +; $Id$ +; + + +; ------------------- DRAM Refresh Interrupt -------------------- + + .cseg +; refresh interupt; exec 2 cbr cycles +refrint: ;4 + .org OC2Aaddr + rjmp refrint ; tim2cmpa + + .org refrint + sbis P_RAS,ram_ras ;2 + reti + ; CAS RAS + cbi P_CAS,ram_cas ;2 1| 1| + ; 1| 1| + cbi P_RAS,ram_ras ;2 |0 1| + ; |0 1| + nop ;1 |0 |0 +; nop ;1 |0 |0 + sbi P_RAS,ram_ras ;2 |0 |0 + ; |0 |0 + dram_wait DRAM_WAITSTATES-1 ; | | +; nop ;1 |0 |0 + cbi P_RAS,ram_ras ;2 |0 1| + ; |0 1| + sbi P_CAS,ram_cas ;2 |0 |0 + ; |0 |0 + sbi P_RAS,ram_ras ;2 1| |0 + ; 1| 1| + reti ;4 --> 21 cycles + + + + +;Print a unsigned lonng value to the uart +; temp4:temp3:temp2:temp = value + +print_ultoa: + push yh + push yl + push z_flags + push temp4 + push temp3 + push temp2 + push temp + + clr yl ;yl = stack level + +ultoa1: ldi z_flags, 32 ;yh = temp4:temp % 10 + clr yh ;temp4:temp /= 10 +ultoa2: lsl temp + rol temp2 + rol temp3 + rol temp4 + rol yh + cpi yh,10 + brcs ultoa3 + subi yh,10 + inc temp +ultoa3: dec z_flags + brne ultoa2 + cpi yh, 10 ;yh is a numeral digit '0'-'9' + subi yh, -'0' + push yh ;Stack it + inc yl + cp temp,_0 ;Repeat until temp4:temp gets zero + cpc temp2,_0 + cpc temp3,_0 + cpc temp4,_0 + brne ultoa1 + + ldi temp, '0' +ultoa5: cpi yl,3 ; at least 3 digits (ms) + brge ultoa6 + push temp + inc yl + rjmp ultoa5 + +ultoa6: pop temp ;Flush stacked digits + rcall uartputc + dec yl + brne ultoa6 + + pop temp + pop temp2 + pop temp3 + pop temp4 + pop z_flags + pop yl + pop yh + ret + + +;Prints temp2:temp in hex to the uart +printhexw: + push temp + mov temp,temp2 + rcall printhex + pop temp + ;fall thru + +;Prints temp in hex to the uart +printhex: + swap temp + rcall printhexn + swap temp + ;fall thru + +;Prints the lower nibble +printhexn: + push temp + andi temp,0xf + cpi temp,0xA + brlo printhexn_isno + subi temp,-7 +printhexn_isno: + subi temp,-'0' + rcall uartputc + pop temp + ret + +;Prints the zero-terminated string following the call statement. + +printstr: + push zh + push zl + push yh + push yl + push temp + in yh,sph + in yl,spl + ldd zl,y+7 + ldd zh,y+6 + + lsl zl + rol zh +printstr_loop: + lpm temp,z+ + cpi temp,0 + breq printstr_end + rcall uartputc + cpi temp,13 + brne printstr_loop + ldi temp,10 + rcall uartputc + rjmp printstr_loop + +printstr_end: + adiw zl,1 ;rounding + lsr zh + ror zl + + std y+7,zl + std y+6,zh + pop temp + pop yl + pop yh + pop zl + pop zh + ret + +; ---------------- Virtual peripherial interface ---------------- + +;The hw is modelled to make writing a CPM BIOS easier. +;Ports: +;0 - Con status. Returns 0xFF if the UART has a byte, 0 otherwise. +;1 - Console input, aka UDR. +;2 - Console output +;3 - "UART" status: bit 0=rx, bit 1 = tx +;4 - "UART" data register, no wait +;15 - Disk select +;16,17 - Track select +;18 - Sector select +;20 - Write addr l +;21 - Write addr h +;22 - Trigger - write to read, to write a sector using the above info; +; , write to allocated/dirctory/unallocated + + .equ READ_FUNC = 7 + .equ WRITE_FUNC = 6 + .equ BOOT_FUNC = 5 + .equ HOME_FUNC = 4 + + + +;***************************************************** +;* CP/M to host disk constants * +;***************************************************** + .equ MAXDISKS = 4 ;Max number of Disks (partitions) + .equ blksize = 1024 ;CP/M allocation size + .equ hostsize = 512 ;host disk sector size +; .equ hostspt = 20 ;host disk sectors/trk + .equ hostblk = hostsize/128 ;CP/M sects/host buff +; .equ CPMSPT = hostblk*hostspt;CP/M sectors/track + .equ CPMSPT = 26 ; + .equ SECMSK = hostblk-1 ;sector mask + .equ SECSHF = log2(hostblk) ;sector shift + +;***************************************************** +;* BDOS constants on entry to write * +;***************************************************** + .equ WRALL = 0 ;write to allocated + .equ WRDIR = 1 ;write to directory + .equ WRUAL = 2 ;write to unallocated + .equ WRTMSK= 3 ;write type mask + + + .dseg +ndisks: .byte 1 ;Number of CP/M disks + +seekdsk: .byte 1 ;seek disk number +seektrk: .byte 2 ;seek track number +seeksec: .byte 1 ;seek sector number + +hostparttbl: .byte 8*MAXDISKS ;host partition table (start sector, sector count) +hostparttbltop: +hostdsk: .byte 1 ;host disk number +hostlba: .byte 3 ;host sector number (relative to partition start) + +unacnt: .byte 1 ;unalloc rec cnt +unadsk: .byte 1 ;last unalloc disk +unatrk: .byte 2 ;last unalloc track +unasec: .byte 1 ;last unalloc sector + +erflag: .byte 1 ;error reporting +wrtype: .byte 1 ;write operation type +dmaadr: .byte 2 ;last dma address +hostbuf: .byte hostsize ;host buffer (from/to SD-card) + + + .cseg + +conStatus: + lds temp,rxcount + cpse temp,_0 + ldi temp,0xff + ret + +conInp: + rjmp uartgetc + +dbgOut: + printnewline + printstring "Debug: " + rcall printhex + ret + +conOut: + rjmp uartputc + +uartstat: + clr temp + lds temp2,rxcount + cpse temp2,_0 + sbr temp,0x01 + lds temp2,txcount + cpi temp2,TXBUFSIZE + breq uartst_1 + sbr temp,0x02 +uartst_1: + ret + +uartout: + lds temp2,txcount + cpi temp2,TXBUFSIZE + breq uartout_1 + rjmp uartputc +uartout_1: + ret + +uartin: + clr temp + lds temp2,rxcount + cpse temp2,_0 + rjmp uartgetc + ret + +;Called with port in temp2. Should return value in temp. +portRead: + cpi temp2,0 + breq conStatus + cpi temp2,1 + breq conInp + cpi temp2,3 + breq uartstat + cpi temp2,4 + breq uartin + + cpi temp2,15 + breq dskDiskCheck + cpi temp2,22 + breq dskErrorRet + + cpi temp2,TIMER_MSECS + brlo pr_noclock + cpi temp2,TIMER_MSECS+6 + brsh pr_noclock + rjmp clockget + +pr_noclock: + ldi temp,0xFF + ret + +;Called with port in temp2 and value in temp. +portWrite: + cpi temp2,0 + breq dbgOut + cpi temp2,2 + breq conOut + cpi temp2,4 + breq uartout + + cpi temp2,15 + breq dskDiskSel + cpi temp2,16 + breq dskTrackSel_l + cpi temp2,17 + breq dskTrackSel_h + cpi temp2,18 + breq dskSecSel + cpi temp2,20 + breq dskDmaL + cpi temp2,21 + breq dskDmaH + + cpi temp2,22 + breq dskDoIt + + cpi temp2,TIMERPORT + brlo pw_noclock + cpi temp2,TIMER_MSECS+6 + brsh pw_noclock + rjmp clockput + +pw_noclock: + ret + + +dskDiskCheck: + lds temp2,seekdsk + cpi temp2,RAMDISKNR + brsh dsk_dchrd ;maybe ramdisk + +; Check if selected disk # is less then # of disks. + + lds temp,ndisks + tst temp + brne dsk_dchpart1 + +; Need to init + + rcall dsk_partinit + cbr temp,0x80 + lds temp2,seekdsk + +dsk_dchpart1: + cp temp2,temp + brsh dsk_dcher + +dsk_dchend: + ldi temp,0 + ret + +dsk_dchrd: +#if RAMDISKCNT + cpi temp,RAMDISKNR+RAMDISKCNT + brlo dsk_dchend +#endif +dsk_dcher: + ldi temp,0xff ;error return + ret + + + + +dskErrorRet: + lds temp,erflag + ret + +dskDiskSel: + sts seekdsk,temp + ret + +dskTrackSel_l: + sts seektrk,temp + sts seektrk+1,_0 + ret + +dskTrackSel_h: + sts seektrk+1,temp + ret + +dskSecSel: + sts seeksec,temp + ret + +dskDmal: + sts dmaadr,temp + ret + +dskDmah: + sts dmaadr+1,temp + ret + +dskDoIt: +.if DISK_DEBUG + push temp + sbrc temp,READ_FUNC + rjmp dskdbgr + sbrc temp,WRITE_FUNC + rjmp dskdbgw + rjmp dskdbge + +dskdbgr: + printnewline + printstring "Disk read: " + rjmp dskdbg1 +dskdbgw: + printnewline + printstring "Disk write: " +dskdbg1: + lds temp,seekdsk + subi temp,-('A') + rcall uartputc + printstring ": track " + lds temp2,seektrk+1 + lds temp,seektrk + rcall printhexw + printstring ", sector " + lds temp,seeksec + rcall printhex + printstring ", dma-addr " + lds temp2,dmaadr+1 + lds temp,dmaadr + rcall printhexw + pop temp + push temp + sbrs temp,WRITE_FUNC + rjmp dskdbge + printstring " wrtype " + andi temp,3 + rcall printhex +dskdbge: + pop temp +.endif + ;See what has to be done. + sbrc temp,READ_FUNC + rjmp dsk_read + sbrc temp,WRITE_FUNC + rjmp dsk_write + sbrc temp,HOME_FUNC + rjmp dsk_home + sbrc temp,BOOT_FUNC + rjmp dsk_boot + + printstring "DISK I/O: Invalid Function code: " + rcall printhex + rjmp haltinv + +dsk_boot: + sts ndisks,_0 ;no active partitions +dsk_cboot: + cbi flags,hostact ;host buffer inactive + sts unacnt,_0 ;clear unalloc count + ret + +dsk_home: + sbis flags,hostwrt ;check for pending write + cbi flags,hostact ;clear host active flag + ret + + +dsk_read: + + sbi flags,readop ;read operation + ;RAM disk? + lds temp2,seekdsk +#if RAMDISKCNT + cpi temp2,RAMDISKNR + brlt PC+2 + rjmp rdskDoIt +#endif + sts unacnt,_0 + sbi flags,rsflag ;must read data + ldi temp,WRUAL ;write type + sts wrtype,temp ;treat as unalloc + rjmp dsk_rwoper ;to perform the read + + +dsk_write: + ;write the selected CP/M sector + + cbi flags,readop ;not a read operation + + ;RAM disk? + lds temp2,seekdsk +#if RAMDISKCNT + cpi temp2,RAMDISKNR + brlt PC+2 + rjmp rdskDoIt +#endif + andi temp,WRTMSK + sts wrtype,temp ;save write type + + cpi temp,WRUAL ;write unallocated? + brne dsk_chkuna ;check for unalloc + +; write to unallocated, set parameters + ldi temp,blksize/128 ;next unalloc recs + sts unacnt,temp + lds temp,seekdsk ;disk to seek + sts unadsk,temp ;unadsk = sekdsk + lds temp,seektrk + sts unatrk,temp ;unatrk = sectrk + lds temp,seektrk+1 + sts unatrk+1,temp ;unatrk = sectrk + lds temp,seeksec + sts unasec,temp ;unasec = seksec +; +dsk_chkuna: + ;check for write to unallocated sector + lds temp,unacnt ;any unalloc remain? + tst temp + breq dsk_alloc ;skip if not + +; more unallocated records remain + dec temp ;unacnt = unacnt-1 + sts unacnt,temp + lds temp,seekdsk ;same disk? + lds temp2,unadsk + cp temp,temp2 ;seekdsk = unadsk? + brne dsk_alloc ;skip if not + +; disks are the same + lds temp,unatrk + lds temp2,unatrk+1 + lds temp3,seektrk + lds temp4,seektrk+1 + cp temp,temp3 ;seektrk = unatrk? + cpc temp2,temp4 + brne dsk_alloc ;skip if not + +; tracks are the same + lds temp,seeksec ;same sector? + lds temp2,unasec + cp temp,temp2 ;seeksec = unasec? + brne dsk_alloc ;skip if not + +; match, move to next sector for future ref + inc temp2 ;unasec = unasec+1 + sts unasec,temp2 + cpi temp2,CPMSPT ;end of track? (count CP/M sectors) + brlo dsk_noovf ;skip if no overflow + +; overflow to next track + sts unasec,_0 ;unasec = 0 + lds temp,unatrk + lds temp2,unatrk+1 + subi temp, low(-1) ;unatrk = unatrk+1 + sbci temp2,high(-1) + sts unatrk,temp + sts unatrk+1,temp2 +; +dsk_noovf: + cbi flags,rsflag ;rsflag = 0 + rjmp dsk_rwoper ;to perform the write +; +dsk_alloc: + ;not an unallocated record, requires pre-read + sts unacnt,_0 ;unacnt = 0 + sbi flags,rsflag ;rsflag = 1 + +;***************************************************** +;* Common code for READ and WRITE follows * +;***************************************************** + +dsk_rwoper: + ;enter here to perform the read/write +.if DISK_DEBUG + printstring ", flags: " + in temp,flags + rcall printhex +.endif + sts erflag,_0 ;no errors (yet) + + ;Convert track/sector to an LBA address (in 128byte blocks) + + lds xl,seeksec ; + ldi xh,0 ; + ldi yl,0 ; + lds temp3,seektrk ; + lds temp4,seektrk+1 ; + ldi temp,CPMSPT ; + mul temp3,temp ; + add xl,r0 ; + adc xh,r1 ; + mul temp4,temp ; + add xh,r0 ;yl:xh:xl := sec + trk * SectorsPerTrack + adc yl,r1 ; + + mov temp,xl + andi temp,SECMSK ;mask buffer number + push temp ;save for later + + ;Convert from CP/M LBA blocks to host LBA blocks + ldi temp,SECSHF +dsk_sh1: + lsr yl + ror xh + ror xl + dec temp + brne dsk_sh1 + ;yl:xh:xl = host block to seek +; active host sector? + in _tmp0,flags ;host active flag + sbi flags,hostact ;always becomes 1 + sbrs _tmp0,hostact ;was it already? + rjmp dsk_filhst ;fill host if not + +; host buffer active, same as seek buffer? + lds temp,seekdsk + lds temp2,hostdsk ;same disk? + cp temp,temp2 ;seekdsk = hostdsk? + brne dsk_nomatch + +; same disk, same block? + lds temp,hostlba + lds temp2,hostlba+1 + lds temp3,hostlba+2 + cp xl,temp + cpc xh,temp2 + cpc yl,temp3 + breq dsk_match +; +dsk_nomatch: + ;proper disk, but not correct sector + sbis flags,hostwrt ;host written? + rjmp dsk_filhst + push xl + push xh + push yl + rcall dsk_writehost ;clear host buff + pop yl + pop xh + pop xl + +dsk_filhst: + ;may have to fill the host buffer + lds temp,seekdsk + sts hostdsk,temp + sts hostlba,xl + sts hostlba+1,xh + sts hostlba+2,yl + + sbic flags,rsflag ;need to read? + rcall dsk_readhost ;yes, if 1 + cbi flags,hostwrt ;no pending write + +dsk_match: + + ;copy data to or from buffer + ldiw z,hostbuf + ldi temp,128 + pop temp2 ;get buffer number (which part of hostbuf) + mul temp2,temp + add zl,r0 ;offset in hostbuf + adc zh,r1 +.if DISK_DEBUG > 2 + push r0 + push r1 + printstring "; host buf adr: " + pop temp2 + pop temp + rcall printhexw +.endif + + lds xl,dmaadr + lds xh,dmaadr+1 + ldi temp3,128 ;length of move + sbic flags,readop ;which way? + rjmp dsk_rmove ;skip if read + +; mark write operation + sbi flags,hostwrt ;hostwrt = 1 +dsk_wmove: + mem_read + st z+,temp + adiw xl,1 + dec temp3 + brne dsk_wmove + rjmp dsk_rwmfin + +dsk_rmove: + ld temp,z+ + mem_write + adiw xl,1 + dec temp3 + brne dsk_rmove +dsk_rwmfin: +; data has been moved to/from host buffer + lds temp,wrtype ;write type + cpi temp,WRDIR ;to directory? + breq dsk_wdir + ret ;no further processing +dsk_wdir: +; clear host buffer for directory write + lds temp,erflag + tst temp ;errors? + breq dsk_wdir1 + ret ;skip if so +dsk_wdir1: + rcall dsk_writehost ;clear host buff + cbi flags,hostwrt ;buffer written + ret + +;***************************************************** + +; hostdsk = host disk #, (partition #) +; hostlba = host block #, relative to partition start +; Read/Write "hostsize" bytes to/from hostbuf + + +dsk_hostparam: + ldiw z,hostparttbl + lds temp,hostdsk +.if HOSTRW_DEBUG + push temp + subi temp,-('A') + rcall uartputc + printstring ": " + pop temp +.endif + + lsl temp + lsl temp + lsl temp + add zl,temp + adc zh,_0 + + lds temp,hostlba + lds temp2,hostlba+1 + lds temp3,hostlba+2 + +.if HOSTRW_DEBUG + printstring "lba: " + clr temp4 + rcall print_ultoa +.endif + + ldd xl,z+4 + ldd xh,z+5 + ldd yl,z+6 + + cp temp,xl + cpc temp2,xh + cpc temp3,yl + brcs dsk_hp1 + +.if HOSTRW_DEBUG + printstring ", max: " + push temp4 + push temp3 + push temp2 + push temp + movw temp,x + mov temp3,yl + clr temp4 + rcall print_ultoa + pop temp + pop temp2 + pop temp3 + pop temp4 + printstring " " +.endif + + clr temp + ret + +dsk_hp1: + ldd xl,z+0 + ldd xh,z+1 + ldd yl,z+2 + ldd yh,z+3 + + add xl,temp + adc xh,temp2 + adc yl,temp3 + adc yh,_0 +.if HOSTRW_DEBUG + printstring ", abs:" + push temp4 + push temp3 + push temp2 + push temp + movw temp,x + movw temp3,y + rcall print_ultoa + pop temp + pop temp2 + pop temp3 + pop temp4 + printstring " " +.endif + ori temp,255 +dsk_hpex: + ret + +;***************************************************** +;* WRITEhost performs the physical write to * +;* the host disk, READhost reads the physical * +;* disk. * +;***************************************************** + +dsk_writehost: +.if HOSTRW_DEBUG + printnewline + printstring "host write " +.endif + rcall dsk_hostparam + breq dsk_rdwr_err + + rcall mmcWriteSect + tst temp + breq dsk_rdwr_ok + + rcall dsk_partinit + cbr temp,0x80 + breq dsk_rdwr_err + + rcall dsk_hostparam + breq dsk_rdwr_err + rcall mmcWriteSect + tst temp + brne dsk_rdwr_err + rjmp dsk_rdwr_ok + + +dsk_readhost: +.if HOSTRW_DEBUG + printnewline + printstring "host read " +.endif + rcall dsk_hostparam + breq dsk_rdwr_err + + rcall mmcReadSect + tst temp + breq dsk_rdwr_ok + + rcall dsk_partinit + cbr temp,0x80 + breq dsk_rdwr_err + + rcall dsk_hostparam + breq dsk_rdwr_err + rcall mmcReadSect + tst temp + brne dsk_rdwr_err + +dsk_rdwr_ok: + sts erflag,_0 + ret + +dsk_rdwr_err: + sts erflag,_255 + ret + +;*************************************************************************** + +#if RAMDISKCNT + +; ----------------- RAM disk ----------------- + + .dseg +rdskbuf: + .byte 128 + + .cseg +;---------------------------------------------- + +rdsk_adr: + ldi xl,0 + lds xh,seeksec + lds temp2,seektrk + + lsr xh + ror xl ;Col 0..7 + + mov temp,temp2 + andi temp,0x0f + swap temp + or xh,temp ;Row 0..7 + + ldiw z,rdskbuf + ldi temp3,128 + DRAM_SETADDR xh, ~0,(1< 1 + mov temp,xh + rcall printhex + printstring " " + mov temp,xl + rcall printhex + printstring " " +.endif + ret + +;---------------------------------------------- + +rdskDoIt: + sts erflag,_0 + sbis flags,readop + rjmp rdsk_wr + +.if DISK_DEBUG > 1 + printnewline + printstring "rd-adr: " +.endif + rcall rdsk_adr +rdsk_rdl: + DRAM_SETADDR xl, ~(1< 1 + printnewline + printstring "wr-adr: " +.endif + lds xl,dmaadr + lds xh,dmaadr+1 + ldiw z,rdskbuf + ldi temp3,128 +rdsk_wrldl: + mem_read + st z+,temp + adiw x,1 + dec temp3 + brne rdsk_wrldl + + ldi temp2,RAM_DQ_MASK | (1<. +; +; $Id$ +; + +#define SSER_BIT_TC (F_CPU+BAUD/2) / BAUD + +#define RXBUFMASK RXBUFSIZE-1 +#define TXBUFMASK TXBUFSIZE-1 + + .dseg + +srx_state: + .byte 1 +srx_char_to: + .byte 1 +srx_dr: + .byte 1 +;srx_lastedge: +; .byte 2 +stx_bitcount: + .byte 1 +stx_dr: + .byte 1 +rxcount: + .byte 1 +rxidx_w: + .byte 1 +rxidx_r: + .byte 1 +txcount: + .byte 1 +txidx_w: + .byte 1 +txidx_r: + .byte 1 +rxfifo: + .byte RXBUFSIZE +txfifo: + .byte TXBUFSIZE + + + .cseg + +; Init +uart_init: + +; - Init clock/timer system and serial port + +; Init timer 1 as +; - Soft UART TX (OC1A/OCR1A). +; - Soft UART RX (ICP1/ICR1). +; - 1ms System timer is already configured at this point. + + ldi temp,(1<= TXBUFSIZE) + + ldi zl,low(txfifo) ; + ldi zh,high(txfifo) ; + lds temp,txidx_w ; + add zl,temp ; + brcc PC+2 ; + inc zh ; + inc temp ; + andi temp,TXBUFMASK ; + sts txidx_w,temp ; txidx_w = ++txidx_w % TXBUFSIZE + pop temp ; + st z,temp ; txfifo[txidx_w] = char + cli + lds zh,txcount + inc zh + sts txcount,zh + dec zh + brne sputc_e +; Enable transmitter + inm8 zh,TIMSK1 + ori zh,(1<. +; along with avrcpm. If not, see . ; ; $Id$ ; -;.nolist -#if defined atmega8 - .include "m8def.inc" -#elif defined atmega168 - .include "m168def.inc" -#elif defined atmega328P - .include "m328Pdef.inc" -#else /* default */ - .include "m88def.inc" - ;FUSE_H=0xDF - ;FUSE_L=0xF7 -#endif -.list -.listmac - - - -#ifndef F_CPU - #define F_CPU 20000000 /* system clock in Hz; defaults to 20MHz */ -#endif -#ifndef BAUD - #define BAUD 38400 /* console baud rate */ -#endif - -#define PARTID 0x52 /* Partition table id */ - /* http://www.win.tue.nl/~aeb/partitions/partition_types-1.html */ -#define RAMDISKNR 'I'-'A' /* Driveletter for first RAM disk */ -#define RAMDISKCNT 1 /* Number of RAM disks */ - -#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) /* clever rounding */ - -#define RXBUFSIZE 64 /* USART recieve buffer size. Must be power of 2 */ -#define TXBUFSIZE 64 /* USART transmit buffer size. Must be power of 2 */ - -#define DRAM_WAITSTATES 1 /* Number of additional clock cycles for dram read access */ -#define REFR_RATE 64000 /* dram refresh rate in cycles/s. */ - /* Most drams need 1/15.6µs. */ -#define REFR_PRE 8 /* timer prescale factor */ -#define REFR_CS 0x02 /* timer clock select for 1/8 */ -#define REFR_CNT F_CPU / REFR_RATE / REFR_PRE - - - -#define DRAM_WORD_ACCESS 0 /* experimental */ - -#define EM_Z80 0 /* we don't have any z80 instructions yet */ - -.equ MMC_DEBUG = 0 -.equ INS_DEBUG = 0 -.equ MEMTEST = 1 -.equ BOOTWAIT = 1 -.equ PORT_DEBUG = 0 -.equ DISK_DEBUG = 0 /* Increase for more debugging */ -.equ HOSTRW_DEBUG= 0 -.equ MEMFILL_CB = 1 -.equ STACK_DBG = 0 -.equ PRINT_PC = 0 - -;Port declarations - -; Port D -.equ rxd = 0 -.equ txd = 1 -.equ ram_oe = 2 -.equ ram_a8 = 3 -.equ mmc_cs = 4 -.equ ram_a5 = 5 -.equ ram_a6 = 6 -.equ ram_a7 = 7 - -.equ P_OE = PORTD -.equ P_AH = PORTD -.equ P_A8 = PORTD -.equ P_MMC_CS = PORTD - ; ram_a[7..5] -.equ RAM_AH_MASK = (1< 0x3f - sts @0,@1 -.else - out @0,@1 -.endif -.endm - -;---------------------------------------- -; -.macro inm8 -.if @1 > 0x3f - lds @0,@1 -.else - in @0,@1 -.endif -.endm - - - -; -------------------- DRAM --------------- - -; DRAM_SETADDR val, low_and_mask, low_or_mask, high_and_mask, high_or_mask -.macro DRAM_SETADDR - mov temp,@0 -.if low(@1) != 0xff - andi temp,@1 -.endif -.if low(@2) != 0 - ori temp, @2 -.endif - out P_AL,temp - - mov temp,@0 -.if low(@3) != 0xff - andi temp,@3 -.endif - ori temp, @4 | (1< 1 - rjmp PC+1 - dram_wait @0 - 2 -.elif @0 > 0 - nop - dram_wait @0 - 1 -.endif -.endm - - -.cseg -.org 0 - rjmp start ; reset vector -.org OC2Aaddr - rjmp refrint ; tim2cmpa -.org OC1Aaddr ; Timer/Counter1 Compare Match A - rjmp sysclockint ; 1ms system timer -.org URXCaddr - rjmp rxint ; USART receive int. -.org UDREaddr - rjmp txint ; USART transmit int. - -.org INT_VECTORS_SIZE - -start: - ldi temp,low(RAMEND) ; top of memory - out SPL,temp ; init stack pointer - ldi temp,high(RAMEND) ; top of memory - out SPH,temp ; init stack pointer - - clr _0 - -; - Kill wdt - wdr - out MCUSR,_0 - - ldi temp,(1< 2 - push r0 - push r1 - clr _0 - rcall printstr - .db "; host buf adr: ",0,0 - pop temp2 - pop temp - rcall printhexw -.endif - clr _0 - - lds xl,dmaadr - lds xh,dmaadr+1 - ldi temp3,128 ;length of move - sbic flags,readop ;which way? - rjmp dsk_rmove ;skip if read - -; mark write operation - sbi flags,hostwrt ;hostwrt = 1 -dsk_wmove: - rcall memReadByte - st z+,temp - adiw xl,1 - dec temp3 - brne dsk_wmove - rjmp dsk_rwmfin - -dsk_rmove: - ld temp,z+ - rcall memWriteByte - adiw xl,1 - dec temp3 - brne dsk_rmove -dsk_rwmfin: -; data has been moved to/from host buffer - lds temp,wrtype ;write type - cpi temp,WRDIR ;to directory? - breq dsk_wdir - ret ;no further processing -dsk_wdir: -; clear host buffer for directory write - lds temp,erflag - tst temp ;errors? - breq dsk_wdir1 - ret ;skip if so -dsk_wdir1: - rcall dsk_writehost ;clear host buff - cbi flags,hostwrt ;buffer written - ret - -;***************************************************** - -; hostdsk = host disk #, (partition #) -; hostlba = host block #, relative to partition start -; Read/Write "hostsize" bytes to/from hostbuf - - -dsk_hostparam: - ldi zl,low(hostparttbl) - ldi zh,high(hostparttbl) - lds temp,hostdsk -.if HOSTRW_DEBUG - push temp - subi temp,-('A') - rcall uartputc - rcall printstr - .db ": ",0,0 - pop temp -.endif - - lsl temp - lsl temp - lsl temp - add zl,temp - adc zh,_0 - - lds temp,hostlba - lds temp2,hostlba+1 - lds temp3,hostlba+2 - -.if HOSTRW_DEBUG - rcall printstr - .db "lba: ",0 - clr temp4 - rcall print_ultoa -.endif - - ldd xl,z+4 - ldd xh,z+5 - ldd yl,z+6 - - cp temp,xl - cpc temp2,xh - cpc temp3,yl - brcs dsk_hp1 - -.if HOSTRW_DEBUG - rcall printstr - .db ", max: ",0 - push temp4 - push temp3 - push temp2 - push temp - movw temp,x - mov temp3,yl - clr temp4 - rcall print_ultoa - pop temp - pop temp2 - pop temp3 - pop temp4 - rcall printstr - .db " ",0 -.endif - - clr temp - ret - -dsk_hp1: - ldd xl,z+0 - ldd xh,z+1 - ldd yl,z+2 - ldd yh,z+3 - - add xl,temp - adc xh,temp2 - adc zl,temp3 - adc zh,_0 -.if HOSTRW_DEBUG - rcall printstr - .db ", abs:",0,0 - push temp4 - push temp3 - push temp2 - push temp - movw temp,x - movw temp3,y - rcall print_ultoa - pop temp - pop temp2 - pop temp3 - pop temp4 - rcall printstr - .db " ",0 -.endif - ori temp,255 -dsk_hpex: - ret - -;***************************************************** -;* WRITEhost performs the physical write to * -;* the host disk, READhost reads the physical * -;* disk. * -;***************************************************** - -dsk_writehost: -.if HOSTRW_DEBUG - rcall printstr - .db 13,"host write ",0,0 -.endif - rcall dsk_hostparam - brne dsk_wr1 - ldi temp,255 - sts erflag,temp - ret - -dsk_wr1: - rcall mmcWriteSect - sts erflag,_0 - ret - -dsk_readhost: -.if HOSTRW_DEBUG - rcall printstr - .db 13,"host read ",0,0 -.endif - rcall dsk_hostparam - brne dsk_rd1 - ldi temp,255 - sts erflag,temp - ret - -dsk_rd1: - rcall mmcReadSect - sts erflag,_0 - ret - - -;*************************************************************************** -; ----------------- RAM disk ----------------- - - .dseg -rdskbuf: - .byte 128 - - .cseg -;---------------------------------------------- - -rdsk_adr: - ldi xl,0 - lds xh,seeksec - lds temp2,seektrk - - lsr xh - ror xl ;Col 0..7 - - mov temp,temp2 - andi temp,0x0f - swap temp - or xh,temp ;Row 0..7 - - ldi zl,low (rdskbuf) - ldi zh,high(rdskbuf) - ldi temp3,128 - DRAM_SETADDR xh, ~0,(1< 1 - mov temp,xh - rcall printhex - rcall printstr - .db " ",0 - mov temp,xl - rcall printhex - rcall printstr - .db " ",0 -.endif - ret - -;---------------------------------------------- - -rdskDoIt: - sts erflag,_0 - sbis flags,readop - rjmp rdsk_wr - -.if DISK_DEBUG > 1 - rcall printstr - .db 13,"rd-adr: ",0 -.endif - rcall rdsk_adr -rdsk_rdl: - DRAM_SETADDR xl, ~(1< 1 - rcall printstr - .db 13,"wr-adr: ",0 -.endif - lds xl,dmaadr - lds xh,dmaadr+1 - ldi zl,low (rdskbuf) - ldi zh,high(rdskbuf) - ldi temp3,128 -rdsk_wrldl: - rcall dram_read - st z+,temp - adiw x,1 - dec temp3 - brne rdsk_wrldl - - ldi temp2,RAM_DQ_MASK | (1<",0 - rcall printhex - rcall printstr - .db ".",13,0 -.endif - ret - - -;Wait till the mmc answers with the response in temp2, or till a timeout happens. -mmcWaitResp: - ldi zl,0 - ldi zh,0 -mmcWaitResploop: - rcall mmcByteNoSend - cpi temp,0xff - brne mmcWaitResploopEnd - adiw zl,1 - cpi zh,255 - breq mmcWaitErr - rjmp mmcWaitResploop -mmcWaitResploopEnd: - ret - - -mmcWaitErr: - mov temp,temp2 - rcall printhex - rcall printstr - .db ": Error: MMC resp timeout!",13,0 - rjmp resetAVR - -mmcInit: - ldi temp,0x53 - out SPCR,temp - - ;Init start: send 80 clocks with cs disabled - sbi P_MMC_CS,mmc_cs - -; ldi temp2,20 - ldi temp2,10 ; exactly 80 clocks -mmcInitLoop: - mov temp,temp2 - rcall mmcByte - dec temp2 - brne mmcInitLoop - - cbi P_MMC_CS,mmc_cs - rcall mmcByteNoSend - rcall mmcByteNoSend - rcall mmcByteNoSend - rcall mmcByteNoSend - rcall mmcByteNoSend - rcall mmcByteNoSend - sbi P_MMC_CS,mmc_cs - rcall mmcByteNoSend - rcall mmcByteNoSend - rcall mmcByteNoSend - rcall mmcByteNoSend - - ;Send init command - cbi P_MMC_CS,mmc_cs - ldi temp,0xff ;dummy - rcall mmcByte - ldi temp,0xff ;dummy - rcall mmcByte - ldi temp,0x40 ;cmd - rcall mmcByte - ldi temp,0 ;pxh - rcall mmcByte - ldi temp,0 ;pxl - rcall mmcByte - ldi temp,0 ;pyh - rcall mmcByte - ldi temp,0 ;pyl - rcall mmcByte - ldi temp,0x95 ;crc - rcall mmcByte - ldi temp,0xff ;return byte - rcall mmcByte - - ldi temp2,0 ;Error Code 0 - rcall mmcWaitResp ;Test on CMD0 is OK - - sbi P_MMC_CS,mmc_cs ;disable /CS - rcall mmcByteNoSend - - -;Read OCR till card is ready - ldi temp2,100 ;repeat counter -mmcInitOcrLoop: - push temp2 - - cbi P_MMC_CS,mmc_cs ;enable /CS - ldi temp,0xff ;dummy - rcall mmcByte - ldi temp,0x41 ;cmd - rcall mmcByte - ldi temp,0 ;pxh - rcall mmcByte - ldi temp,0 ;pxl - rcall mmcByte - ldi temp,0 ;pyh - rcall mmcByte - ldi temp,0 ;pyl - rcall mmcByte -; ldi temp,0x95 ;crc - ldi temp,0x01 ;crc - rcall mmcByte - rcall mmcByteNoSend - - ldi temp2,1 - rcall mmcWaitResp ;wait until mmc-card send a byte <> 0xFF - ;the first answer must be 0x01 (Idle-Mode) - cpi temp,0 - breq mmcInitOcrLoopDone ;second answer is 0x00 (Idle-Mode leave) CMD1 is OK - - sbi P_MMC_CS,mmc_cs ;disable /CS - - rcall mmcByteNoSend - - ldi temp,10 - rcall delay_ms - - pop temp2 - dec temp2 - brne mmcInitOcrLoop ;repeat - - ldi temp2,4 - rjmp mmcWaitErr - -mmcInitOcrLoopDone: - pop temp2 - sbi P_MMC_CS,mmc_cs ;disable /CS - rcall mmcByteNoSend - - out SPCR,_0 - ret - - -;Call this with yh:yl:xh:xl = sector number -; -mmcReadSect: - ldi temp,0x50 - out SPCR,temp - - cbi P_MMC_CS,mmc_cs - rcall mmcByteNoSend - ldi temp,0x51 ;cmd (read sector) - rcall mmcByte - lsl xl ;convert to byte address (*512) - rol xh - rol yl - mov temp,yl - rcall mmcByte - mov temp,xh ;pxl - rcall mmcByte - mov temp,xl ;pyh - rcall mmcByte - ldi temp,0 ;pyl - rcall mmcByte - ldi temp,0x95 ;crc - rcall mmcByte - ldi temp,0xff ;return byte - rcall mmcByte - - ;resp - ldi temp2,2 - rcall mmcWaitResp - - ;data token - ldi temp2,3 - rcall mmcWaitResp - - ;Read sector to AVR RAM - ldi zl,low(hostbuf) - ldi zh,high(hostbuf) -mmcreadloop: - rcall mmcByteNoSend - st z+,temp - cpi zl,low(hostbuf+512) - brne mmcreadloop - cpi zh,high(hostbuf+512) - brne mmcreadloop - - ;CRC - rcall mmcByteNoSend - rcall mmcByteNoSend - - sbi P_MMC_CS,mmc_cs - rcall mmcByteNoSend - - out SPCR,_0 - ret - - -;Call this with yh:yl:xh:xl = sector number -; -mmcWriteSect: - ldi temp,0x50 - out SPCR,temp - - cbi P_MMC_CS,mmc_cs - rcall mmcByteNoSend - - ldi temp,0x58 ;cmd (write sector) - rcall mmcByte - lsl xl ;convert to byte address (*512) - rol xh - rol yl - mov temp,yl - rcall mmcByte - mov temp,xh ;pxl - rcall mmcByte - mov temp,xl ;pyh - rcall mmcByte - ldi temp,0 ;pyl - rcall mmcByte - ldi temp,0x95 ;crc - rcall mmcByte - ldi temp,0xff ;return byte - rcall mmcByte - - ;resp - ldi temp2,1 - rcall mmcWaitResp - - ;Send data token - ldi temp,0xfe - rcall mmcByte - - ;Write sector from AVR RAM - ldi zl,low(hostbuf) - ldi zh,high(hostbuf) -mmcwriteloop: - ld temp,z+ - rcall mmcByte - cpi zl,low(hostbuf+512) - brne mmcwriteloop - cpi zh,high(hostbuf+512) - brne mmcwriteloop - - ;CRC - rcall mmcByteNoSend - rcall mmcByteNoSend - - ;Status. Ignored for now. - rcall mmcByteNoSend - -;Wait till the mmc has written everything -mmcwaitwritten: - rcall mmcByteNoSend - cpi temp,0xff - brne mmcwaitwritten - - sbi P_MMC_CS,mmc_cs - rcall mmcByteNoSend - - out SPCR,_0 - ret - - -;Set up wdt to time out after 1 sec. -resetAVR: - lds temp,txcount ;Wait, till tx buffer is empty - tst temp - brne resetAVR - - cli - ldi temp,(1< 21 cycles - - -; ------------- system timer 1ms --------------- - .dseg - -delay_timer: - .byte 1 -timer_base: -timer_ms: - .byte 2 -timer_s: - .byte 4 -; don't change order here, clock put/get depends on it. -cntms_out: ; register for ms - .byte 2 -utime_io: ; register for uptime. - .byte 4 -cnt_1ms: - .byte 2 -uptime: - .byte 4 -timer_top: - .equ timer_size = timer_top - timer_base - - .equ clkofs = cnt_1ms-cntms_out - .equ timerofs = cnt_1ms-timer_ms - - .cseg -sysclockint: - push zl - in zl,SREG - push zl - push zh - - lds zl,delay_timer - subi zl,1 - brcs syscl1 - sts delay_timer,zl -syscl1: - lds zl,cnt_1ms - lds zh,cnt_1ms+1 - adiw z,1 - - sts cnt_1ms,zl - sts cnt_1ms+1,zh - cpi zl,low(1000) - ldi zl,high(1000) ;doesn't change flags - cpc zh,zl - brlo syscl_end - - ldi zl,0 ;can't use _0 register in int. - sts cnt_1ms,zl - sts cnt_1ms+1,zl - - lds zl,uptime+0 - inc zl - sts uptime+0,zl - brne syscl_end - lds zl,uptime+1 - inc zl - sts uptime+1,zl - brne syscl_end - lds zl,uptime+2 - inc zl - sts uptime+2,zl - brne syscl_end - lds zl,uptime+3 - inc zl - sts uptime+3,zl - -syscl_end: - pop zh - pop zl - out SREG,zl - pop zl - reti - -; wait for temp ms - -delay_ms: - sts delay_timer,temp -dly_loop: - lds temp,delay_timer - cpi temp,0 - brne dly_loop - ret - -; - -clockget: - ldi temp,0xFF - subi temp2,TIMER_MSECS - brcs clkget_end ;Port number in range? - ldi zl,low(cntms_out) - ldi zh,high(cntms_out) - breq clkget_copy ;lowest byte requestet, latch clock - cpi temp2,6 - brsh clkget_end ;Port number to high? - - add zl,temp2 - brcc PC+2 - inc zh - ld temp,z -clkget_end: - ret - - - -clkget_copy: - ldi temp2,6 - cli -clkget_l: - ldd temp,z+clkofs - st z+,temp - dec temp2 - brne clkget_l - sei - lds temp,cntms_out - ;req. byte in temp - ret - -clockput: - subi temp2,TIMERPORT - brcs clkput_end ;Port number in range? - brne clkput_1 - - ; clock control - - cpi temp,starttimercmd - breq timer_start - cpi temp,quitTimerCmd - breq timer_quit - cpi temp,printTimerCmd - breq timer_print - cpi temp,uptimeCmd - brne cp_ex - rjmp uptime_print -cp_ex: - ret - -timer_quit: - rcall timer_print - rjmp timer_start - -clkput_1: - dec temp2 - ldi zl,low(cntms_out) - ldi zh,high(cntms_out) - breq clkput_copy ;lowest byte requestet, latch clock - cpi temp2,6 - brsh clkput_end ;Port number to high? - - add zl,temp2 - brcc PC+2 - inc zh - st z,temp -clkput_end: - ret - -clkput_copy: - st z,temp - adiw z,5 - ldi temp2,6 - cli -clkput_l: - ldd temp,z+clkofs - st z+,temp - dec temp2 - brne clkput_l - sei - ret - -; start/reset timer -; -timer_start: - ldi zl,low(timer_ms) - ldi zh,high(timer_ms) - ldi temp2,6 - cli -ts_loop: - ldd temp,z+timerofs - st z+,temp - dec temp2 - brne ts_loop - sei - ret - - -; print timer -; - -timer_print: - push yh - push yl - ldi zl,low(timer_ms) - ldi zh,high(timer_ms) - -; put ms on stack (16 bit) - - cli - ldd yl,z+timerofs - ld temp2,z+ - sub yl,temp2 - ldd yh,z+timerofs - ld temp2,z+ - sbc yh,temp2 - brsh tp_s - - subi yl,low(-1000) - sbci yh,high(-1000) - sec -tp_s: - push yh - push yl - - ldd temp,z+timerofs - ld yl,z+ - sbc temp,yl - - ldd temp2,z+timerofs - ld yh,z+ - sbc temp2,yh - - ldd temp3,z+timerofs - ld yl,z+ - sbc temp3,yl - - sei - ldd temp4,z+timerofs - ld yh,z+ - sbc temp4,yh - - rcall printstr - .db 13,"Timer running. Elapsed: ",0 - rcall print_ultoa - - rcall printstr - .db ".",0 - pop temp - pop temp2 - ldi temp3,0 - ldi temp4,0 - rcall print_ultoa - rcall printstr - .db "s.",0,0 - - pop yl - pop yh - ret - -uptime_print: - - ldi zl,low(cnt_1ms) - ldi zh,high(cnt_1ms) - - cli - ld temp,z+ - push temp - ld temp,z+ - push temp - - ld temp,z+ - ld temp2,z+ - ld temp3,z+ - sei - ld temp4,z+ - - rcall printstr - .db 13,"Uptime: ",0 - - rcall print_ultoa - rcall printstr - .db ",",0 - - ldi temp3,0 - ldi temp4,0 - pop temp2 - pop temp - rcall print_ultoa - rcall printstr - .db "s.",0,0 - - ret - - - -; --------------- Debugging stuff --------------- - -;Print a unsigned lonng value to the uart -; temp4:temp3:temp2:temp = value - -print_ultoa: - push yh - push yl - push z_flags - push temp4 - push temp3 - push temp2 - push temp - - clr yl ;yl = stack level - -ultoa1: ldi z_flags, 32 ;yh = temp4:temp % 10 - clr yh ;temp4:temp /= 10 -ultoa2: lsl temp - rol temp2 - rol temp3 - rol temp4 - rol yh - cpi yh,10 - brcs ultoa3 - subi yh,10 - inc temp -ultoa3: dec z_flags - brne ultoa2 - cpi yh, 10 ;yh is a numeral digit '0'-'9' - subi yh, -'0' - push yh ;Stack it - inc yl - cp temp,_0 ;Repeat until temp4:temp gets zero - cpc temp2,_0 - cpc temp3,_0 - cpc temp4,_0 - brne ultoa1 - - ldi temp, '0' -ultoa5: cpi yl,3 ; at least 3 digits (ms) - brge ultoa6 - push temp - inc yl - rjmp ultoa5 - -ultoa6: pop temp ;Flush stacked digits - rcall uartputc - dec yl - brne ultoa6 - - pop temp - pop temp2 - pop temp3 - pop temp4 - pop z_flags - pop yl - pop yh - ret - - -;Prints temp2:temp in hex to the uart -printhexw: - push temp - mov temp,temp2 - rcall printhex - pop temp - ;fall thru - -;Prints temp in hex to the uart -printhex: - swap temp - rcall printhexn - swap temp - ;fall thru - -;Prints the lower nibble -printhexn: - push temp - andi temp,0xf - cpi temp,0xA - brlo printhexn_isno - subi temp,-7 -printhexn_isno: - subi temp,-'0' - rcall uartputc - pop temp - ret - -;Prints the zero-terminated string following the call statement. - -printstr: - push zh - push zl - push yh - push yl - push temp - in yh,sph - in yl,spl - ldd zl,y+7 - ldd zh,y+6 - - lsl zl - rol zh -printstr_loop: - lpm temp,z+ - cpi temp,0 - breq printstr_end - rcall uartputc - cpi temp,13 - brne printstr_loop - ldi temp,10 - rcall uartputc - rjmp printstr_loop - -printstr_end: - adiw zl,1 - lsr zh - ror zl - - std y+7,zl - std y+6,zh - pop temp - pop yl - pop yh - pop zl - pop zh - ret - -; --------------- AVR HW <-> Z80 periph stuff ------------------ - -.equ memReadByte = dram_read -.equ memWriteByte = dram_write -#if DRAM_WORD_ACCESS -.equ memReadWord = dram_read_w -.equ memWriteWord = dram_write_w -#endif - ; -------------------------------------------------------------- - .dseg - -#define RXBUFMASK RXBUFSIZE-1 -#define TXBUFMASK TXBUFSIZE-1 - -rxcount: - .byte 1 -rxidx_w: - .byte 1 -rxidx_r: - .byte 1 -txcount: - .byte 1 -txidx_w: - .byte 1 -txidx_r: - .byte 1 -rxfifo: - .byte RXBUFSIZE -txfifo: - .byte TXBUFSIZE - -ramtop: .byte 0 - .cseg - -; Save received character in a circular buffer. Do nothing if buffer overflows. - -rxint: - push temp - in temp,sreg - push temp - push zh - push zl - inm8 temp,RXTXDR0 - lds zh,rxcount ;if rxcount < RXBUFSIZE - cpi zh,RXBUFSIZE ; (room for at least 1 char?) - brsh rxi_ov ; - inc zh ; - sts rxcount,zh ; rxcount++ - - ldi zl,low(rxfifo) ; - lds zh,rxidx_w ; - add zl,zh ; - inc zh ; - andi zh,RXBUFMASK ; - sts rxidx_w,zh ; rxidx_w = ++rxidx_w % RXBUFSIZE - ldi zh,high(rxfifo) ; - brcc PC+2 ; - inc zh ; - st z,temp ; rxfifo[rxidx_w] = char -rxi_ov: ;endif - pop zl - pop zh - pop temp - out sreg,temp - pop temp - reti - - -;Fetches a char from the buffer to temp. If none available, waits till one is. - -uartgetc: - lds temp,rxcount ; Number of characters in buffer - tst temp - breq uartgetc ;Wait for char - - push zh - push zl - ldi zl,low(rxfifo) - ldi zh,high(rxfifo) - lds temp,rxidx_r - add zl,temp - brcc PC+2 - inc zh - inc temp - andi temp,RXBUFMASK - sts rxidx_r,temp - cli - lds temp,rxcount - dec temp - sts rxcount,temp - sei - ld temp,z ;don't forget to get the char - pop zl - pop zh - ret - -txint: - push temp - in temp,sreg - push temp - lds temp,txcount ;if txcount != 0 - tst temp ; - breq txi_e ; - - dec temp ; - sts txcount,temp ; --txcount - push zh ; - push zl ; - ldi zl,low(txfifo) ; - ldi zh,high(txfifo) ; - lds temp,txidx_r ; - add zl,temp ; - brcc PC+2 ; - inc zh ; - inc temp ; - andi temp,TXBUFMASK ; - sts txidx_r,temp ; - ld temp,z - outm8 RXTXDR0,temp - pop zl - pop zh -txi_e: ;endif - lds temp,txcount - tst temp - brne txi_x - ldi temp, (1<= TXBUFSIZE) - - ldi zl,low(txfifo) ; - ldi zh,high(txfifo) ; - lds temp,txidx_w ; - add zl,temp ; - brcc PC+2 ; - inc zh ; - inc temp ; - andi temp,TXBUFMASK ; - sts txidx_w,temp ; txidx_w = ++txidx_w % TXBUFSIZE - pop temp ; - st z,temp ; txfifo[txidx_w] = char - cli - lds zl,txcount - inc zl - sts txcount,zl - ldi zl, (1< (" + mov temp,opl + rcall printhex + printstring ") " +.endif + mov temp,z_a + mov temp2,opl + rcall portWrite + ret + +;---------------------------------------------------------------- +;|Mnemonic |SZHPNC|Description |Notes | +;---------------------------------------------------------------- +;|IN A,[n] |------|Input |A=[n] | +; +; +do_op_in: ; in a,(opl) +.if PORT_DEBUG + printnewline + printstring "Port read: (" + mov temp,opl + rcall printhex + printstring ") -> " +.endif + + mov temp2,opl + rcall portRead + mov opl,temp + +.if PORT_DEBUG + rcall printhex + printstring " " +.endif + ret + ;---------------------------------------------------------------- ;|Mnemonic |SZHPNC|Description |Notes | ;---------------------------------------------------------------- @@ -3750,8 +1243,10 @@ do_op_xora: ; ; do_op_addhl: - add opl,z_l - adc oph,z_h + lds temp,z_l + lds temp2,z_h + add opl,temp + adc oph,temp2 in temp,sreg bmov z_flags,ZFL_H, temp,AVR_H bmov z_flags,ZFL_C, temp,AVR_C @@ -3766,16 +1261,11 @@ do_op_addhl: ; do_op_sthl: ;store hl to mem loc in opl:h movw xl,opl -#if DRAM_WORD_ACCESS - movw temp,z_l - rcall memWriteWord -#else - mov temp,z_l - rcall memWriteByte + lds temp,z_l + mem_write adiw xl,1 - mov temp,z_h - rcall memWriteByte -#endif + lds temp,z_h + mem_write ret ;---------------------------------------------------------------- @@ -3786,16 +1276,9 @@ do_op_sthl: ;store hl to mem loc in opl:h ; do_op_rmem16: movw xl,opl -#if DRAM_WORD_ACCESS - rcall memReadWord - movw opl,temp -#else - rcall memReadByte - mov opl,temp - adiw xl,1 - rcall memReadByte - mov oph,temp -#endif + mem_read_d opl + adiw x,1 + mem_read_d oph ret ;---------------------------------------------------------------- @@ -3805,9 +1288,7 @@ do_op_rmem16: ; ; do_op_rmem8: - movw xl,opl - rcall memReadByte - mov opl,temp + mem_read_ds opl, op ret ;---------------------------------------------------------------- @@ -3990,32 +1471,22 @@ do_op_cpl: ; ; do_op_push16: - movw xl,z_spl - subi xl,2 - sbci xh,0 - movw z_spl,xl -#if DRAM_WORD_ACCESS - movw temp,opl - rcall memWriteWord -#else - mov temp,opl - rcall memWriteByte - adiw xl,1 - mov temp,oph - rcall memWriteByte -#endif + movw xl,z_spl + sbiw x,1 + mem_write_s oph + sbiw x,1 + mem_write_s opl + movw z_spl,xl .if STACK_DBG - rcall printstr - .db "Stack push ",0 - mov tempw,opl + printnewline + printstring "Stack push " + movw temp,opl rcall printhexw - rcall printstr - .db ", SP is now ",0 - mov tempw,z_spl + printstring ", SP is now " + movw temp,z_spl rcall printhexw - rcall printstr - .db ".",13,0 + printstring ". " .endif ret @@ -4028,34 +1499,23 @@ do_op_push16: ; ; do_op_pop16: - movw xl,z_spl -#if DRAM_WORD_ACCESS - rcall memReadWord - movw opl,temp -#else - rcall memReadByte - mov opl,temp - adiw xl,1 - rcall memReadByte - mov oph,temp -#endif - - ldi temp,2 - add z_spl,temp - adc z_sph,_0 + movw x,z_spl + mem_read_d opl + adiw x,1 + mem_read_d oph + adiw x,1 + movw z_spl,x .if STACK_DBG - rcall printstr - .db "Stack pop: val ",0 + printnewline + printstring "Stack pop " movw temp,opl rcall printhexw - rcall printstr - .db ", SP is now",0 + printstring ", SP is now " movw temp,z_spl rcall printhexw - rcall printstr - .db ".",13,0 + printstring ". " .endif ret @@ -4067,12 +1527,11 @@ do_op_pop16: ; ; do_op_exhl: - mov temp,z_h - mov z_h,oph - mov oph,temp - mov temp,z_l - mov z_l,opl - mov opl,temp + lds temp,z_l + lds temp2,z_h + sts z_l,opl + sts z_h,oph + movw opl,temp ret ;---------------------------------------------------------------- @@ -4211,111 +1670,7 @@ do_op_ifm: ;sign negative, aka s=1 clr insdecl ret -;---------------------------------------------------------------- -;|Mnemonic |SZHPNC|Description |Notes | -;---------------------------------------------------------------- -;|OUT [n],A |------|Output |[n]=A | -; -; -;Interface with peripherials goes here :) -do_op_outa: ; out (opl),a -.if PORT_DEBUG - rcall printstr - .db 13,"Port write: ",0 - mov temp,z_a - rcall printhex - rcall printstr - .db " -> (",0 - mov temp,opl - rcall printhex - rcall printstr - .db ")",13,0 -.endif - mov temp,z_a - mov temp2,opl - rcall portWrite - ret - -;---------------------------------------------------------------- -;|Mnemonic |SZHPNC|Description |Notes | -;---------------------------------------------------------------- -;|IN A,[n] |------|Input |A=[n] | -; -; -do_op_in: ; in a,(opl) -.if PORT_DEBUG - rcall printstr - .db 13,"Port read: (",0 - mov temp,opl - rcall printhex - rcall printstr - .db ") -> ",0 -.endif - - mov temp2,opl - rcall portRead - mov opl,temp - -.if PORT_DEBUG - rcall printhex - rcall printstr - .db 13,0 -.endif - ret - - -;---------------------------------------------------------------- -do_op_inv: - rcall printstr - .db "Invalid opcode @ PC=",0,0 - movw temp,z_pcl - rcall printhexw - -;---------------------------------------------------------------- -haltinv: - rjmp haltinv -;---------------------------------------------------------------- -; Lookup table, stolen from z80ex, Z80 emulation library. -; http://z80ex.sourceforge.net/ - -; The S, Z, 5 and 3 bits and the parity of the lookup value -.org (PC+255) & 0xff00 -sz53p_tab: - .db 0x44,0x00,0x00,0x04,0x00,0x04,0x04,0x00 - .db 0x08,0x0c,0x0c,0x08,0x0c,0x08,0x08,0x0c - .db 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04 - .db 0x0c,0x08,0x08,0x0c,0x08,0x0c,0x0c,0x08 - .db 0x20,0x24,0x24,0x20,0x24,0x20,0x20,0x24 - .db 0x2c,0x28,0x28,0x2c,0x28,0x2c,0x2c,0x28 - .db 0x24,0x20,0x20,0x24,0x20,0x24,0x24,0x20 - .db 0x28,0x2c,0x2c,0x28,0x2c,0x28,0x28,0x2c - .db 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04 - .db 0x0c,0x08,0x08,0x0c,0x08,0x0c,0x0c,0x08 - .db 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00 - .db 0x08,0x0c,0x0c,0x08,0x0c,0x08,0x08,0x0c - .db 0x24,0x20,0x20,0x24,0x20,0x24,0x24,0x20 - .db 0x28,0x2c,0x2c,0x28,0x2c,0x28,0x28,0x2c - .db 0x20,0x24,0x24,0x20,0x24,0x20,0x20,0x24 - .db 0x2c,0x28,0x28,0x2c,0x28,0x2c,0x2c,0x28 - .db 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84 - .db 0x8c,0x88,0x88,0x8c,0x88,0x8c,0x8c,0x88 - .db 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80 - .db 0x88,0x8c,0x8c,0x88,0x8c,0x88,0x88,0x8c - .db 0xa4,0xa0,0xa0,0xa4,0xa0,0xa4,0xa4,0xa0 - .db 0xa8,0xac,0xac,0xa8,0xac,0xa8,0xa8,0xac - .db 0xa0,0xa4,0xa4,0xa0,0xa4,0xa0,0xa0,0xa4 - .db 0xac,0xa8,0xa8,0xac,0xa8,0xac,0xac,0xa8 - .db 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80 - .db 0x88,0x8c,0x8c,0x88,0x8c,0x88,0x88,0x8c - .db 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84 - .db 0x8c,0x88,0x88,0x8c,0x88,0x8c,0x8c,0x88 - .db 0xa0,0xa4,0xa4,0xa0,0xa4,0xa0,0xa0,0xa4 - .db 0xac,0xa8,0xa8,0xac,0xa8,0xac,0xac,0xa8 - .db 0xa4,0xa0,0xa0,0xa4,0xa0,0xa4,0xa4,0xa0 - .db 0xa8,0xac,0xac,0xa8,0xac,0xa8,0xa8,0xac - - ; ----------------------- Opcode decoding ------------------------- ; Lookup table for Z80 opcodes. Translates the first byte of the instruction word into three @@ -4582,4 +1937,47 @@ inst_table: .dw (FETCH_DIR8 | OP_CPFA | STORE_NOP) ; FE nn CP n .dw (FETCH_RST | OP_NOP | STORE_CALL) ; FF RST 38H +;---------------------------------------------------------------- +; Lookup table, stolen from z80ex, Z80 emulation library. +; http://z80ex.sourceforge.net/ + +; The S, Z, 5 and 3 bits and the parity of the lookup value + +.org (PC+255) & 0xff00 +sz53p_tab: + .db 0x44,0x00,0x00,0x04,0x00,0x04,0x04,0x00 + .db 0x08,0x0c,0x0c,0x08,0x0c,0x08,0x08,0x0c + .db 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04 + .db 0x0c,0x08,0x08,0x0c,0x08,0x0c,0x0c,0x08 + .db 0x20,0x24,0x24,0x20,0x24,0x20,0x20,0x24 + .db 0x2c,0x28,0x28,0x2c,0x28,0x2c,0x2c,0x28 + .db 0x24,0x20,0x20,0x24,0x20,0x24,0x24,0x20 + .db 0x28,0x2c,0x2c,0x28,0x2c,0x28,0x28,0x2c + .db 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04 + .db 0x0c,0x08,0x08,0x0c,0x08,0x0c,0x0c,0x08 + .db 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00 + .db 0x08,0x0c,0x0c,0x08,0x0c,0x08,0x08,0x0c + .db 0x24,0x20,0x20,0x24,0x20,0x24,0x24,0x20 + .db 0x28,0x2c,0x2c,0x28,0x2c,0x28,0x28,0x2c + .db 0x20,0x24,0x24,0x20,0x24,0x20,0x20,0x24 + .db 0x2c,0x28,0x28,0x2c,0x28,0x2c,0x2c,0x28 + .db 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84 + .db 0x8c,0x88,0x88,0x8c,0x88,0x8c,0x8c,0x88 + .db 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80 + .db 0x88,0x8c,0x8c,0x88,0x8c,0x88,0x88,0x8c + .db 0xa4,0xa0,0xa0,0xa4,0xa0,0xa4,0xa4,0xa0 + .db 0xa8,0xac,0xac,0xa8,0xac,0xa8,0xa8,0xac + .db 0xa0,0xa4,0xa4,0xa0,0xa4,0xa0,0xa0,0xa4 + .db 0xac,0xa8,0xa8,0xac,0xa8,0xac,0xac,0xa8 + .db 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80 + .db 0x88,0x8c,0x8c,0x88,0x8c,0x88,0x88,0x8c + .db 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84 + .db 0x8c,0x88,0x88,0x8c,0x88,0x8c,0x8c,0x88 + .db 0xa0,0xa4,0xa4,0xa0,0xa4,0xa0,0xa0,0xa4 + .db 0xac,0xa8,0xa8,0xac,0xa8,0xac,0xac,0xa8 + .db 0xa4,0xa0,0xa0,0xa4,0xa0,0xa4,0xa4,0xa0 + .db 0xa8,0xac,0xac,0xa8,0xac,0xa8,0xa8,0xac + + ; vim:set ts=8 noet nowrap +