; 8080/Z80 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$
;
#if EM_Z80
#define OPC_TABSTART 0x1900
#else
#define OPC_TABSTART 0x1200
#endif
.dseg
z_regs:
z_b: .byte 1
z_c: .byte 1
z_d: .byte 1
z_e: .byte 1
z_h: .byte 1
z_l: .byte 1
.equ oz_b = 0
.equ oz_c = 1
.equ oz_d = 2
.equ oz_e = 3
.equ oz_h = 4
.equ oz_l = 5
#if EM_Z80
z_b2: .byte 1
z_c2: .byte 1
z_d2: .byte 1
z_e2: .byte 1
z_h2: .byte 1
z_l2: .byte 1
z_f2: .byte 1
z_a2: .byte 1
.equ r2ofs = z_b2-z_b
.equ oz_b2 = 6
.equ oz_c2 = 7
.equ oz_d2 = 8
.equ oz_e2 = 9
.equ oz_h2 = 10
.equ oz_l2 = 11
.equ oz_f2 = 12
.equ oz_a2 = 13
z_xh: .byte 1
z_xl: .byte 1
z_yh: .byte 1
z_yl: .byte 1
z_i: .byte 1
z_r: .byte 1
.equ oz_xh = 14
.equ oz_xl = 15
.equ oz_yh = 16
.equ oz_yl = 17
.equ oz_i = 18
.equ oz_r = 19
z_istat: .byte 1
.equ oz_istat = 20
.equ IM_MASK = 0x03 ;Mask IM 0..2
.equ IM0 = 0
.equ IM1 = 1
.equ IM2 = 2
.equ IFF1 = 2 ;IFF1 Flag
.equ IFF2 = 3 ;IFF2 Flag
#endif
.cseg
;Init z80
z80_init:
ldiw z_pc,IPLADDR
ldiw y,z_regs
cbi flags,trace
clr intstat
printnewline
.if INS_DEBUG
sbr intstat,(1< 2047
.set longdist_ = 1 ; target action out of reach for rel jump
.else
rjmp action_1_ ; do op and return to main
.endif
.endif
.set done_ = 0
.if (cnt_ > 1) || longdist_
; two or tree actions
.if defined (l_@0_@1_@2)
.if (PC - l_@0_@1_@2) <= 2047
rjmp l_@0_@1_@2 ; generate a jump to action table
.set done_ = 1
.endif
.endif
.if !done_
.if todo_table_pos_ == 0
.set todo_table_pos_ = opcjmp_table_pos_ - 2048
.if todo_table_pos_ < pc_save_
.set todo_table_pos_ = pc_save_
.endif
.endif
.if todo_table_pos_ < opc_tablow_
.if todo_table_pos_ + 2*cnt_ > opc_tablow_
.set todo_table_pos_ = opc_tabend_
.endif
.endif
.if defined (l_@0_@1_@2)
rjmp todo_table_pos_
.org todo_table_pos_
jmp l_@0_@1_@2
.set todo_table_pos_ = PC
.set done_ = 1
.endif
.endif
.if !done_
.equ l_@0_@1_@2 = todo_table_pos_ ; make a label
rjmp l_@0_@1_@2 ; generate a jump to action table
.org l_@0_@1_@2
.if fetch_ ; must fetch
.if op_ || store_
.if do_@0 == 0
m_do_@0
.else
lcall do_@0 ; fetch and come back here
.endif
.else
.if do_@0 == 0
m_do_@0
ret
.else
ljmp do_@0 ; do op and return to main
.endif
.endif
.endif
.if op_ ; must exec op
.if store_
.if do_@1 == 0
m_do_@1
.else
lcall do_@1 ; fetch and come back here
.endif
.else
.if do_@1 == 0
m_do_@1
ret
.else
ljmp do_@1 ; do op and return to main
.endif
.endif
.endif
.if store_ ; must store
.if do_@2 == 0
m_do_@2
ret
.else
ljmp do_@2 ; store is allways last
.endif
.endif
.set todo_table_pos_ = PC
.endif
.endif
.if todo_table_pos_ == 0
.org pc_save_
.else
.org todo_table_pos_
.endif
.endm
do_x_nop:
ret
; ------------ Fetch phase stuff -----------------
fetch_ops:
.equ do_fetch_nop = do_x_nop
.macro m_do_fetch_a
mov opl,z_a
.endm
.equ do_fetch_a = 0
; mov opl,z_a
; ret
.macro m_do_fetch_b
ldd opl,y+oz_b
.endm
.equ do_fetch_b = 0
; ldd opl,y+oz_b
; ret
.macro m_do_fetch_c
ldd opl,y+oz_c
.endm
.equ do_fetch_c = 0
; ldd opl,y+oz_c
; ret
.macro m_do_fetch_d
ldd opl,y+oz_d
.endm
.equ do_fetch_d = 0
; ldd opl,y+oz_d
; ret
.macro m_do_fetch_e
ldd opl,y+oz_e
.endm
.equ do_fetch_e = 0
; ldd opl,y+oz_e
; ret
.macro m_do_fetch_h
ldd opl,y+oz_h
.endm
.equ do_fetch_h = 0
; ldd opl,y+oz_h
; ret
.macro m_do_fetch_l
ldd opl,y+oz_l
.endm
.equ do_fetch_l = 0
; ldd opl,y+oz_l
; ret
do_fetch_af:
mov opl,z_flags
mov oph,z_a
ret
do_fetch_bc:
ldd opl,y+oz_c
ldd oph,y+oz_b
ret
do_fetch_de:
ldd opl,y+oz_e
ldd oph,y+oz_d
ret
do_fetch_hl:
ldd opl,y+oz_l
ldd oph,y+oz_h
ret
.macro m_do_fetch_sp
movw opl,z_spl
.endm
.equ do_fetch_sp = 0
; movw opl,z_spl
; ret
do_fetch_mbc:
ldd xh,y+oz_b
ldd xl,y+oz_c
mem_read_d z_a
ret
do_fetch_mde:
ldd xh,y+oz_d
ldd xl,y+oz_e
mem_read_d z_a
ret
do_fetch_mhl:
ldd xh,y+oz_h
ldd xl,y+oz_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 -----------------
store_ops:
.equ do_store_nop = do_x_nop
do_store_a:
mov z_a,opl
ret
;.macro m_do_store_b
; std y+oz_b,opl
;.endm
;.equ do_store_b = 0
do_store_b:
std y+oz_b,opl
ret
do_store_c:
std y+oz_c,opl
ret
do_store_d:
std y+oz_d,opl
ret
do_store_e:
std y+oz_e,opl
ret
do_store_h:
std y+oz_h,opl
ret
do_store_l:
std y+oz_l,opl
ret
do_store_af:
mov z_a,oph
mov z_flags,opl
ret
do_store_bc:
std y+oz_b,oph
std y+oz_c,opl
ret
do_store_de:
std y+oz_d,oph
std y+oz_e,opl
ret
do_store_hl:
std y+oz_h,oph
std y+oz_l,opl
ret
do_store_mbc:
ldd xh,y+oz_b
ldd xl,y+oz_c
mem_write_s z_a
ret
do_store_mde:
ldd xh,y+oz_d
ldd xl,y+oz_e
mem_write_s z_a
ret
do_store_mhl:
ldd xh,y+oz_h
ldd xl,y+oz_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_pcrel: ;add displacement to PC
#if EM_Z80
clr oph
tst opl ;sign extend
brpl stpcr1
com oph
stpcr1:
add z_pcl,opl
adc z_pch,oph
ret
#else
rjmp do_op_inv
#endif
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 |IFF1 = IFF2 = 0 |
;|DJNZ e |------|Dec., Jump Non-Zero |B=B-1 till B=0 |
;|EI |------|Enable Interrupts |IFF1 = IFF2 = 1 |
;|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
; TODO: check Z80 flag settings
;------------------------------------------------;
; Load table value from flash indexed by source reg.
;
; ldpmx dstreg,tablebase,indexreg
;
; (3 words, 5 cycles)
.macro ldpmx
ldi zh,high(@1*2) ; table must be page aligned
mov zl,@2
lpm @0,z
.endm
.macro do_z80_flags_V
#if EM_Z80
bmov z_flags, ZFL_P, temp, AVR_V
#endif
.endm
.macro do_z80_flags_H
#if EM_Z80
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
lcall printhex
printstring ") "
.endif
mov temp,z_a
mov temp2,opl
lcall portWrite
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|IN A,[n] |------|Input |A=[n] |
;
;
do_op_ina: ; in a,(opl)
.if PORT_DEBUG
printnewline
printstring "Port read: ("
mov temp,opl
lcall printhex
printstring ") -> "
.endif
mov temp2,opl
lcall portRead
mov z_a,temp
.if PORT_DEBUG
lcall 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:
#if EM_Z80
andi z_flags,(1<A |
;|----------|SZHP C|---------- 8080 ----------------------------|
;|RRCA |---- *|Rotate Right Circular|A=->A |
;
;
do_op_rrca:
;Rotate Right Cyclical. All bits move 1 to the
;right, the lsb becomes c and msb.
do_z80_flags_op_rotate
lsr z_a
brcc do_op_rrc_noc
ldi temp,0x80
or z_a,temp
ori z_flags, (1<{CY,A} |
;|----------|SZHP C|---------- 8080 ----------------------------|
;|RRA |---- *|Rotate Right Acc. |A=->{CY,A} |
;
;
do_op_rra:
;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, z_a,0 ; Bit 0 --> CY
ror z_a
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_rla:
;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, z_a,7 ; Bit 7 --> CY
rol z_a
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
bmov z_flags,ZFL_H, temp,AVR_H
do_z80_flags_V
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
bmov z_flags,ZFL_H, temp,AVR_H
do_z80_flags_V
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
bmov z_flags,ZFL_H, temp,AVR_H
do_z80_flags_V
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 temp2,z_a
sub temp2,opl
in temp,sreg
ldpmx z_flags,sz53p_tab,temp2 ;S,Z,P
bmov z_flags,ZFL_C, temp,AVR_C
bmov z_flags,ZFL_H, temp,AVR_H
do_z80_flags_V
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
bmov z_flags,ZFL_H, temp,AVR_H
do_z80_flags_V
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 |
;
;
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 |
;
;
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 |
;
;
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:
ldd temp,y+oz_l
ldd temp2,y+oz_h
add opl,temp
adc oph,temp2
std y+oz_l,opl
std y+oz_h,oph
in temp,sreg
bmov z_flags,ZFL_C, temp,AVR_C
do_z80_flags_H
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
ldd temp,y+oz_l
mem_write
adiw xl,1
ldd temp,y+oz_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 ----------------------------|
; 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 val in | Number |C flag |
; | Oper |Before |upper digit |Before |lower digit| added |After |
; | |DAA |(bit 7-4) |DAA |(bit 3-0) | to A |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 |
; -------------------------------------------------------------------
;
; The H flag is affected as follows:
;
; ---------------------
; | N | H | low |H' |
; | | |nibble | |
; |---+---+-------+---|
; | 0 | * | 0-9 | 0 |
; | 0 | * | a-f | 1 |
; | 1 | 0 | * | 0 |
; | 1 | 1 | 6-f | 0 |
; | 1 | 1 | 0-5 | 1 |
; ---------------------
;
; Ohter flags:
; N: Unaffected.
; P/V: Set if Acc. is even parity after operation, reset otherwise.
; 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 0
#if EM_Z80
sbrc z_flags,ZFL_N ;if add-op
rjmp op_da_sub ;then
#endif
do_op_DAA:
op_da_add:
ldi temp2,0 ; new C, H and N flag
sbrc z_flags,ZFL_H ; |
rjmp op_da_a01 ; if (H flag ...
mov temp,opl ; |
andi temp,0x0f ; |
cpi temp,0x0a ; or (lower nibble >= 0x0A))
brlo op_da_a10 ; |
op_da_a01: ; then
ldi oph,0x06 ; add 6 to lower nibble
add opl,oph ;
brhc op_da_02 ; if
ori temp2,(1<= 0xA0)
brlo op_da_a13 ;
op_da_a12: ;
ldi oph,0x60 ; add 6 to lower nibble
add opl,oph ;
ori temp2,(1<= 0x0A))
brlo op_da_s10 ; |
op_da_s01: ; then
ldi oph,0x06 ; add 6 to lower nibble
sub opl,oph ;
brhc PC+2 ; if
ori temp2,(1<= 0xA0)
brlo op_da_s13 ;
op_da_s12: ;
ldi oph,0x60 ; add 6 to lower nibble
sub opl,oph ;
ori temp2,(1<= 0x0A)
brlo op_da_a10 ; |
ori oph,0x06 ; add 6
ori temp2,(1<= 0x90)
brlo op_da_a03 ; |
op_da_a02:
ori oph,0x60 ; add 0x60
ori temp2,(1<= 0xA0)
brlo op_da_a13 ;
op_da_a12:
ori oph,0x60 ; add 0x60
ori temp2,(1<= 0x0A)
brlo op_da_s10 ; |
ori oph,0x06 ; sub 6
sbrc z_flags,ZFL_C ; |
rjmp op_da_s02 ; if (C flag ...
cpi opl,0x90 ; |... or upper nibble >= 0x90)
brlo op_da_s03 ; |
op_da_s02:
ori oph,0x60 ; sub 0x60
ori temp2,(1<= 0xA0)
brlo op_da_s13 ;
op_da_s12:
ori oph,0x60 ; sub 0x60
ori temp2,(1<HL |
;|EX DE,HL |------|Exchange |DE<->HL |
;-----------------------------Z80--------------------------------
;
do_op_exhl:
ldd temp,y+oz_l
ldd temp2,y+oz_h
std y+oz_l,opl
std y+oz_h,oph
movw opl,temp
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|DI |------|Disable Interrupts |IFF1 = IFF2 = 0 |
;|EI |------|Enable Interrupts |IFF1 = IFF2 = 1 |
;
do_op_DI:
#if EM_Z80
ldd temp,y+oz_istat
andi temp,~((1<AF' |
do_op_EXAF:
ldd temp,y+oz_f2
ldd temp2,y+oz_a2
std y+oz_f2,z_flags
std y+oz_a2,z_a
mov z_flags,temp
mov z_a,temp2
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|EXX |------|Exchange |qq<->qq' (except AF)|
do_op_EXX:
ldiw z,z_b
ldi temp3,6
opexx_loop:
ld temp,z
ldd temp2,z+r2ofs
std z+r2ofs,temp
st z+,temp2
dec temp3
brne opexx_loop
ret
#else
do_op_djnz:
do_op_EXAF:
do_op_EXX:
ljmp do_op_inv
ret
#endif
#if EM_Z80
do_op_noni:
sbiw z_pcl,1 ;--z_pc
ret
do_op_prefixED:
mem_read_ds zl,z_pc ;zl = memReadByte(z_pc)
adiw z_pcl,1 ;++z_pc
ldi zh,high(EDjmp) ;
ijmp
do_op_prefixDD:
cbi flags,prefixfd
mem_read_ds zl,z_pc ;zl = memReadByte(z_pc)
adiw z_pcl,1 ;++z_pc
ldi zh,high(DDFDjmp) ;
ijmp
do_op_prefixFD:
sbi flags,prefixfd
mem_read_ds zl,z_pc ;zl = memReadByte(z_pc)
adiw z_pcl,1 ;++z_pc
ldi zh,high(DDFDjmp) ;
ijmp
do_op_prefixCB:
mem_read_ds zl,z_pc ;zl = memReadByte(z_pc)
adiw z_pcl,1 ;++z_pc
ldi zh,high(CBjmp) ;
ijmp
do_op_prefixDDFDCB:
sbic flags,prefixfd
rjmp opprxcb_fd
ldd xh,y+oz_xh
ldd xl,y+oz_xl
rjmp opprxcb_1
opprxcb_fd:
ldd xh,y+oz_yh
ldd xl,y+oz_yl
opprxcb_1:
mem_read_s z_pc ;get displacement
adiw z_pcl,1 ;++z_pc
clr temp2 ;sign extend
tst temp
brpl PC+2
com temp2
add xl,temp ;add displacement
adc xh,temp2
mem_read_d opl
mem_read_ds zl,z_pc ;zl = opcode
adiw z_pcl,1 ;++z_pc
ldi zh,high(DDFDCBjmp) ;
icall
mem_write_s opl
ret
#else ; TODO: geht das so?
do_op_prefixED:
do_op_prefixDD:
do_op_prefixFD:
do_op_prefixCB:
ljmp do_op_inv
ret
#endif
; ----------------------- 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.
opctable opcjmp
instr fetch_nop, op_nop, store_nop ;00 ;NOP
instr fetch_DIR16, op_nop, store_BC ;01 nn nn ;LD BC,nn
instr fetch_nop, op_nop, store_MBC ;02 ;LD (BC),A
instr fetch_BC, op_INC16, store_BC ;03 ;INC BC
instr fetch_B, op_INC, store_B ;04 ;INC B
instr fetch_B, op_DEC, store_B ;05 ;DEC B
instr fetch_DIR8, op_nop, store_B ;06 ;LD B,n
instr fetch_nop, op_RLCA, store_nop ;07 ;RLCA
instr fetch_nop, op_EXAF, store_nop ;08 ;EX AF,AF'
instr fetch_BC, op_ADDHL, store_nop ;09 ;ADD HL,BC
instr fetch_MBC, op_nop, store_nop ;0A ;LD A,(BC)
instr fetch_BC, op_DEC16, store_BC ;0B ;DEC BC
instr fetch_C, op_INC, store_C ;0C ;INC C
instr fetch_C, op_DEC, store_C ;0D ;DEC C
instr fetch_DIR8, op_nop, store_C ;0E nn ;LD C,n
instr fetch_nop, op_RRCA, store_nop ;0F ;RRCA
instr fetch_DIR8, op_DJNZ, store_nop ;10 oo ;DJNZ o
instr fetch_DIR16, op_nop, store_DE ;11 nn nn ;LD DE,nn
instr fetch_nop, op_nop, store_MDE ;12 ;LD (DE),A
instr fetch_DE, op_INC16, store_DE ;13 ;INC DE
instr fetch_D, op_INC, store_D ;14 ;INC D
instr fetch_D, op_DEC, store_D ;15 ;DEC D
instr fetch_DIR8, op_nop, store_D ;16 nn ;LD D,n
instr fetch_nop, op_RLA, store_nop ;17 ;RLA
instr fetch_DIR8, op_nop, store_pcrel ;18 oo ;JR o
instr fetch_DE, op_ADDHL, store_nop ;19 ;ADD HL,DE
instr fetch_MDE, op_nop, store_nop ;1A ;LD A,(DE)
instr fetch_DE, op_DEC16, store_DE ;1B ;DEC DE
instr fetch_E, op_INC, store_E ;1C ;INC E
instr fetch_E, op_DEC, store_E ;1D ;DEC E
instr fetch_DIR8, op_nop, store_E ;1E nn ;LD E,n
instr fetch_nop, op_RRA, store_nop ;1F ;RRA
instr fetch_DIR8, op_IFNZ, store_pcrel ;20 oo ;JR NZ,o
instr fetch_DIR16, op_nop, store_HL ;21 nn nn ;LD HL,nn
instr fetch_DIR16, op_STHL, store_nop ;22 nn nn ;LD (nn),HL
instr fetch_HL, op_INC16, store_HL ;23 ;INC HL
instr fetch_H, op_INC, store_H ;24 ;INC H
instr fetch_H, op_DEC, store_H ;25 ;DEC H
instr fetch_DIR8, op_nop, store_H ;26 nn ;LD H,n
instr fetch_A, op_DAA, store_A ;27 ;DAA
instr fetch_DIR8, op_IFZ, store_pcrel ;28 oo ;JR Z,o
instr fetch_HL, op_ADDHL, store_nop ;29 ;ADD HL,HL
instr fetch_DIR16, op_RMEM16, store_HL ;2A nn nn ;LD HL,(nn)
instr fetch_HL, op_DEC16, store_HL ;2B ;DEC HL
instr fetch_L, op_INC, store_L ;2C ;INC L
instr fetch_L, op_DEC, store_L ;2D ;DEC L
instr fetch_DIR8, op_nop, store_L ;2E nn ;LD L,n
instr fetch_nop, op_CPL, store_nop ;2F ;CPL
instr fetch_DIR8, op_IFNC, store_pcrel ;30 oo ;JR NC,o
instr fetch_DIR16, op_nop, store_SP ;31 nn nn ;LD SP,nn
instr fetch_DIR16, op_nop, store_AM ;32 nn nn ;LD (nn),A
instr fetch_SP, op_INC16, store_SP ;33 ;INC SP
instr fetch_MHL, op_INC, store_MHL ;34 ;INC (HL)
instr fetch_MHL, op_DEC, store_MHL ;35 ;DEC (HL)
instr fetch_DIR8, op_nop, store_MHL ;36 nn ;LD (HL),n
instr fetch_nop, op_SCF, store_nop ;37 ;SCF
instr fetch_DIR8, op_IFC, store_pcrel ;38 oo ;JR C,o
instr fetch_SP, op_ADDHL, store_nop ;39 ;ADD HL,SP
instr fetch_DIR16, op_RMEM8, store_A ;3A nn nn ;LD A,(nn)
instr fetch_SP, op_DEC16, store_SP ;3B ;DEC SP
instr fetch_nop, op_INCA, store_nop ;3C ;INC A
instr fetch_nop, op_DECA, store_nop ;3D ;DEC A
instr fetch_DIR8, op_nop, store_A ;3E nn ;LD A,n
instr fetch_nop, op_CCF, store_nop ;3F ;CCF (Complement Carry Flag, gvd)
instr fetch_nop, op_nop, store_nop ;40 ;LD B,B
instr fetch_C, op_nop, store_B ;41 ;LD B,C
instr fetch_D, op_nop, store_B ;42 ;LD B,D
instr fetch_E, op_nop, store_B ;43 ;LD B,E
instr fetch_H, op_nop, store_B ;44 ;LD B,H
instr fetch_L, op_nop, store_B ;45 ;LD B,L
instr fetch_MHL, op_nop, store_B ;46 ;LD B,(HL)
instr fetch_A, op_nop, store_B ;47 ;LD B,A
instr fetch_B, op_nop, store_C ;48 ;LD C,B
instr fetch_nop, op_nop, store_nop ;49 ;LD C,C
instr fetch_D, op_nop, store_C ;4A ;LD C,D
instr fetch_E, op_nop, store_C ;4B ;LD C,E
instr fetch_H, op_nop, store_C ;4C ;LD C,H
instr fetch_L, op_nop, store_C ;4D ;LD C,L
instr fetch_MHL, op_nop, store_C ;4E ;LD C,(HL)
instr fetch_A, op_nop, store_C ;4F ;LD C,A
instr fetch_B, op_nop, store_D ;50 ;LD D,B
instr fetch_C, op_nop, store_D ;51 ;LD D,C
instr fetch_nop, op_nop, store_nop ;52 ;LD D,D
instr fetch_E, op_nop, store_D ;53 ;LD D,E
instr fetch_H, op_nop, store_D ;54 ;LD D,H
instr fetch_L, op_nop, store_D ;55 ;LD D,L
instr fetch_MHL, op_nop, store_D ;56 ;LD D,(HL)
instr fetch_A, op_nop, store_D ;57 ;LD D,A
instr fetch_B, op_nop, store_E ;58 ;LD E,B
instr fetch_C, op_nop, store_E ;59 ;LD E,C
instr fetch_D, op_nop, store_E ;5A ;LD E,D
instr fetch_nop, op_nop, store_nop ;5B ;LD E,E
instr fetch_H, op_nop, store_E ;5C ;LD E,H
instr fetch_L, op_nop, store_E ;5D ;LD E,L
instr fetch_MHL, op_nop, store_E ;5E ;LD E,(HL)
instr fetch_A, op_nop, store_E ;5F ;LD E,A
instr fetch_B, op_nop, store_H ;60 ;LD H,B
instr fetch_C, op_nop, store_H ;61 ;LD H,C
instr fetch_D, op_nop, store_H ;62 ;LD H,D
instr fetch_E, op_nop, store_H ;63 ;LD H,E
instr fetch_nop, op_nop, store_nop ;64 ;LD H,H
instr fetch_L, op_nop, store_H ;65 ;LD H,L
instr fetch_MHL, op_nop, store_H ;66 ;LD H,(HL)
instr fetch_A, op_nop, store_H ;67 ;LD H,A
instr fetch_B, op_nop, store_L ;68 ;LD L,B
instr fetch_C, op_nop, store_L ;69 ;LD L,C
instr fetch_D, op_nop, store_L ;6A ;LD L,D
instr fetch_E, op_nop, store_L ;6B ;LD L,E
instr fetch_H, op_nop, store_L ;6C ;LD L,H
instr fetch_nop, op_nop, store_nop ;6D ;LD L,L
instr fetch_MHL, op_nop, store_L ;6E ;LD L,(HL)
instr fetch_A, op_nop, store_L ;6F ;LD L,A
instr fetch_B, op_nop, store_MHL ;70 ;LD (HL),B
instr fetch_C, op_nop, store_MHL ;71 ;LD (HL),C
instr fetch_D, op_nop, store_MHL ;72 ;LD (HL),D
instr fetch_E, op_nop, store_MHL ;73 ;LD (HL),E
instr fetch_H, op_nop, store_MHL ;74 ;LD (HL),H
instr fetch_L, op_nop, store_MHL ;75 ;LD (HL),L
instr fetch_nop, op_HALT, store_nop ;76 ;HALT
instr fetch_A, op_nop, store_MHL ;77 ;LD (HL),A
instr fetch_B, op_nop, store_A ;78 ;LD A,B
instr fetch_C, op_nop, store_A ;79 ;LD A,C
instr fetch_D, op_nop, store_A ;7A ;LD A,D
instr fetch_E, op_nop, store_A ;7B ;LD A,E
instr fetch_H, op_nop, store_A ;7C ;LD A,H
instr fetch_L, op_nop, store_A ;7D ;LD A,L
instr fetch_MHL, op_nop, store_A ;7E ;LD A,(HL)
instr fetch_nop, op_nop, store_nop ;7F ;LD A,A
instr fetch_B, op_ADDA, store_nop ;80 ;ADD A,B
instr fetch_C, op_ADDA, store_nop ;81 ;ADD A,C
instr fetch_D, op_ADDA, store_nop ;82 ;ADD A,D
instr fetch_E, op_ADDA, store_nop ;83 ;ADD A,E
instr fetch_H, op_ADDA, store_nop ;84 ;ADD A,H
instr fetch_L, op_ADDA, store_nop ;85 ;ADD A,L
instr fetch_MHL, op_ADDA, store_nop ;86 ;ADD A,(HL)
instr fetch_A, op_ADDA, store_nop ;87 ;ADD A,A
instr fetch_B, op_ADCA, store_nop ;88 ;ADC A,B
instr fetch_C, op_ADCA, store_nop ;89 ;ADC A,C
instr fetch_D, op_ADCA, store_nop ;8A ;ADC A,D
instr fetch_E, op_ADCA, store_nop ;8B ;ADC A,E
instr fetch_H, op_ADCA, store_nop ;8C ;ADC A,H
instr fetch_L, op_ADCA, store_nop ;8D ;ADC A,L
instr fetch_MHL, op_ADCA, store_nop ;8E ;ADC A,(HL)
instr fetch_A, op_ADCA, store_nop ;8F ;ADC A,A
instr fetch_B, op_SUBFA, store_nop ;90 ;SUB A,B
instr fetch_C, op_SUBFA, store_nop ;91 ;SUB A,C
instr fetch_D, op_SUBFA, store_nop ;92 ;SUB A,D
instr fetch_E, op_SUBFA, store_nop ;93 ;SUB A,E
instr fetch_H, op_SUBFA, store_nop ;94 ;SUB A,H
instr fetch_L, op_SUBFA, store_nop ;95 ;SUB A,L
instr fetch_MHL, op_SUBFA, store_nop ;96 ;SUB A,(HL)
instr fetch_A, op_SUBFA, store_nop ;97 ;SUB A,A
instr fetch_B, op_SBCFA, store_nop ;98 ;SBC A,B
instr fetch_C, op_SBCFA, store_nop ;99 ;SBC A,C
instr fetch_D, op_SBCFA, store_nop ;9A ;SBC A,D
instr fetch_E, op_SBCFA, store_nop ;9B ;SBC A,E
instr fetch_H, op_SBCFA, store_nop ;9C ;SBC A,H
instr fetch_L, op_SBCFA, store_nop ;9D ;SBC A,L
instr fetch_MHL, op_SBCFA, store_nop ;9E ;SBC A,(HL)
instr fetch_A, op_SBCFA, store_nop ;9F ;SBC A,A
instr fetch_B, op_ANDA, store_nop ;A0 ;AND A,B
instr fetch_C, op_ANDA, store_nop ;A1 ;AND A,C
instr fetch_D, op_ANDA, store_nop ;A2 ;AND A,D
instr fetch_E, op_ANDA, store_nop ;A3 ;AND A,E
instr fetch_H, op_ANDA, store_nop ;A4 ;AND A,H
instr fetch_L, op_ANDA, store_nop ;A5 ;AND A,L
instr fetch_MHL, op_ANDA, store_nop ;A6 ;AND A,(HL)
instr fetch_A, op_ANDA, store_nop ;A7 ;AND A,A
instr fetch_B, op_XORA, store_nop ;A8 ;XOR A,B
instr fetch_C, op_XORA, store_nop ;A9 ;XOR A,C
instr fetch_D, op_XORA, store_nop ;AA ;XOR A,D
instr fetch_E, op_XORA, store_nop ;AB ;XOR A,E
instr fetch_H, op_XORA, store_nop ;AC ;XOR A,H
instr fetch_L, op_XORA, store_nop ;AD ;XOR A,L
instr fetch_MHL, op_XORA, store_nop ;AE ;XOR A,(HL)
instr fetch_A, op_XORA, store_nop ;AF ;XOR A,A
instr fetch_B, op_ORA, store_nop ;B0 ;OR A,B
instr fetch_C, op_ORA, store_nop ;B1 ;OR A,C
instr fetch_D, op_ORA, store_nop ;B2 ;OR A,D
instr fetch_E, op_ORA, store_nop ;B3 ;OR A,E
instr fetch_H, op_ORA, store_nop ;B4 ;OR A,H
instr fetch_L, op_ORA, store_nop ;B5 ;OR A,L
instr fetch_MHL, op_ORA, store_nop ;B6 ;OR A,(HL)
instr fetch_A, op_ORA, store_nop ;B7 ;OR A,A
instr fetch_B, op_CPFA, store_nop ;B8 ;CP A,B
instr fetch_C, op_CPFA, store_nop ;B9 ;CP A,C
instr fetch_D, op_CPFA, store_nop ;BA ;CP A,D
instr fetch_E, op_CPFA, store_nop ;BB ;CP A,E
instr fetch_H, op_CPFA, store_nop ;BC ;CP A,H
instr fetch_L, op_CPFA, store_nop ;BD ;CP A,L
instr fetch_MHL, op_CPFA, store_nop ;BE ;CP A,(HL)
instr fetch_A, op_CPFA, store_nop ;BF ;CP A,A
instr fetch_nop, op_IFNZ, store_RET ;C0 ;RET NZ
instr fetch_nop, op_POP16, store_BC ;C1 ;POP BC
instr fetch_DIR16, op_IFNZ, store_PC ;C2 nn nn ;JP NZ,nn
instr fetch_DIR16, op_nop, store_PC ;C3 nn nn ;JP nn
instr fetch_DIR16, op_IFNZ, store_CALL ;C4 nn nn ;CALL NZ,nn
instr fetch_BC, op_PUSH16, store_nop ;C5 ;PUSH BC
instr fetch_DIR8, op_ADDA, store_nop ;C6 nn ;ADD A,n
instr fetch_RST, op_nop, store_CALL ;C7 ;RST 0
instr fetch_nop, op_IFZ, store_RET ;C8 ;RET Z
instr fetch_nop, op_nop, store_RET ;C9 ;RET
instr fetch_DIR16, op_IFZ, store_PC ;CA nn nn ;JP Z,nn
instr fetch_nop, op_prefixCB, store_nop ;CB ;(CB opcode prefix)
instr fetch_DIR16, op_IFZ, store_CALL ;CC nn nn ;CALL Z,nn
instr fetch_DIR16, op_nop, store_CALL ;CD nn nn ;CALL nn
instr fetch_DIR8, op_ADCA, store_nop ;CE nn ;ADC A,n
instr fetch_RST, op_nop, store_CALL ;CF ;RST 8H
instr fetch_nop, op_IFNC, store_RET ;D0 ;RET NC
instr fetch_nop, op_POP16, store_DE ;D1 ;POP DE
instr fetch_DIR16, op_IFNC, store_PC ;D2 nn nn ;JP NC,nn
instr fetch_DIR8, op_OUTA, store_nop ;D3 nn ;OUT (n),A
instr fetch_DIR16, op_IFNC, store_CALL ;D4 nn nn ;CALL NC,nn
instr fetch_DE, op_PUSH16, store_nop ;D5 ;PUSH DE
instr fetch_DIR8, op_SUBFA, store_nop ;D6 nn ;SUB n
instr fetch_RST, op_nop, store_CALL ;D7 ;RST 10H
instr fetch_nop, op_IFC, store_RET ;D8 ;RET C
instr fetch_nop, op_EXX, store_nop ;D9 ;EXX
instr fetch_DIR16, op_IFC, store_PC ;DA nn nn ;JP C,nn
instr fetch_DIR8, op_INA, store_nop ;DB nn ;IN A,(n)
instr fetch_DIR16, op_IFC, store_CALL ;DC nn nn ;CALL C,nn
instr fetch_nop, op_prefixDD, store_nop ;DD ;(DD opcode prefix)
instr fetch_DIR8, op_SBCFA, store_nop ;DE nn ;SBC A,n
instr fetch_RST, op_nop, store_CALL ;DF ;RST 18H
instr fetch_nop, op_IFPO, store_RET ;E0 ;RET PO
instr fetch_nop, op_POP16, store_HL ;E1 ;POP HL
instr fetch_DIR16, op_IFPO, store_PC ;E2 nn nn ;JP PO,nn
instr fetch_MSP, op_EXHL, store_MSP ;E3 ;EX (SP),HL
instr fetch_DIR16, op_IFPO, store_CALL ;E4 nn nn ;CALL PO,nn
instr fetch_HL, op_PUSH16, store_nop ;E5 ;PUSH HL
instr fetch_DIR8, op_ANDA, store_nop ;E6 nn ;AND n
instr fetch_RST, op_nop, store_CALL ;E7 ;RST 20H
instr fetch_nop, op_IFPE, store_RET ;E8 ;RET PE
instr fetch_HL, op_nop, store_PC ;E9 ;JP HL
instr fetch_DIR16, op_IFPE, store_PC ;EA nn nn ;JP PE,nn
instr fetch_DE, op_EXHL, store_DE ;EB ;EX DE,HL
instr fetch_DIR16, op_IFPE, store_CALL ;EC nn nn ;CALL PE,nn
instr fetch_nop, op_prefixED, store_nop ;ED ;(ED opcode prefix)
instr fetch_DIR8, op_XORA, store_nop ;EE nn ;XOR n
instr fetch_RST, op_nop, store_CALL ;EF ;RST 28H
instr fetch_nop, op_IFP, store_RET ;F0 ;RET P
instr fetch_nop, op_POP16, store_AF ;F1 ;POP AF
instr fetch_DIR16, op_IFP, store_PC ;F2 nn nn ;JP P,nn
instr fetch_nop, op_DI, store_nop ;F3 ;DI
instr fetch_DIR16, op_IFP, store_CALL ;F4 nn nn ;CALL P,nn
instr fetch_AF, op_PUSH16, store_nop ;F5 ;PUSH AF
instr fetch_DIR8, op_ORA, store_nop ;F6 nn ;OR n
instr fetch_RST, op_nop, store_CALL ;F7 ;RST 30H
instr fetch_nop, op_IFM, store_RET ;F8 ;RET M
instr fetch_HL, op_nop, store_SP ;F9 ;LD SP,HL
instr fetch_DIR16, op_IFM, store_PC ;FA nn nn ;JP M,nn
instr fetch_nop, op_EI, store_nop ;FB ;EI
instr fetch_DIR16, op_IFM, store_CALL ;FC nn nn ;CALL M,nn
instr fetch_nop, op_prefixFD, store_nop ;FD ;(FD opcode prefix)
instr fetch_DIR8, op_CPFA, store_nop ;FE nn ;CP n
instr fetch_RST, op_nop, store_CALL ;FF ;RST 38H
#if EM_Z80
do_fetch_0:
ldi opl,0
ret
do_fetch_dir8_2:
movw xl,z_pcl
adiw xl,1
mem_read_d opl
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|IN r,[C] |***P0-|Input |r=[C] |
;
do_op_in: ; in opl,(opl)
.if PORT_DEBUG
printnewline
printstring "Port read: ("
mov temp,opl
rcall printhex
printstring ") -> "
.endif
mov temp2,opl
lcall portRead
mov opl,temp
bst z_flags,ZFL_C ;save Carry
ldpmx z_flags,sz53p_tab,temp ;S,Z,P
bld z_flags,ZFL_C
.if PORT_DEBUG
rcall printhex
printstring " "
.endif
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|OUT [C],r |------|Output |[C]=r |
;
do_op_out: ; out (c),opl
mov temp,opl
ldd temp2,y+oz_c
lcall portWrite
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|LD dst,src|------|Load |dst=src |
;
do_op_stbc: ;store bc to mem loc in opl:h
movw xl,opl
ldd temp,y+oz_c
mem_write
adiw xl,1
ldd temp,y+oz_b
mem_write
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|LD dst,src|------|Load |dst=src |
;
;
do_op_stde: ;store de to mem loc in opl:h
movw xl,opl
ldd temp,y+oz_e
mem_write
adiw xl,1
ldd temp,y+oz_d
mem_write
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|LD dst,src|------|Load |dst=src |
;
;
do_op_stsp: ;store sp to mem loc in opl:h
movw xl,opl
mem_write_s z_spl
adiw xl,1
mem_write_s z_sph
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|ADC HL,ss |***V0*|Add with Carry |HL=HL+ss+CY |
;
do_op_ADCHL:
ldd temp,y+oz_l
ldd temp2,y+oz_h
clc
sbrc z_flags,ZFL_C
sec
adc opl,temp
in temp,sreg ; save lower Z
adc oph,temp2
in temp2,sreg
std y+oz_l,opl
std y+oz_h,oph
and temp,temp2 ; 16bit Z
ldi z_flags,0 ; clear N
bmov z_flags,ZFL_C, temp2,AVR_C
bmov z_flags,ZFL_P, temp2,AVR_V
bmov z_flags,ZFL_H, temp2,AVR_H
bmov z_flags,ZFL_Z, temp,AVR_Z
bmov z_flags,ZFL_S, temp2,AVR_N
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|SBC HL,ss |***V1*|Subtract with carry |HL=HL-ss-CY |
;
;
do_op_sbchl:
ldd temp,y+oz_l
ldd temp2,y+oz_h
cp temp,opl ; set z
clc
sbrc z_flags,ZFL_C
sec
sbc temp,opl
sbc temp2,oph
std y+oz_l,temp
std y+oz_h,temp2
in temp,sreg
ldi z_flags,(1< P |
;|LD i,A |------|Load |(i=I,R) |
do_op_ldai:
ldd z_a,y+oz_i
rjmp op_ldar1
do_op_ldar:
ldd z_a,y+oz_r
op_ldar1:
bst z_flags,ZFL_C ;save C
ldpmx z_flags,sz53p_tab,z_a ;S,Z,H,P,N
bld z_flags,ZFL_C ;
ldd temp,y+oz_istat
bmov z_flags,ZFL_P, temp,IFF2
ret
do_op_ldia:
std y+oz_i,z_a
ret
do_op_ldra:
std y+oz_r,z_a
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|RLD |**0P0-|Rotate Left 4 bits |{A,[HL]}={A,[HL]}<- ##|
;|RRD |**0P0-|Rotate Right 4 bits |{A,[HL]}=->{A,[HL]} ##|
do_op_rld:
swap opl
mov oph,opl
andi opl,0xf0
andi oph,0x0f
mov temp,z_a
andi temp,0x0f
or opl,temp
mov temp,z_a
andi temp,0xf0
or temp,oph
mov z_a,temp
bst z_flags,ZFL_C ;save C
ldpmx z_flags,sz53p_tab,z_a ;S,Z,H,P,N
bld z_flags,ZFL_C ;
ret
do_op_rrd:
mov oph,opl
andi opl,0xf0
andi oph,0x0f
mov temp,z_a
andi temp,0x0f
or opl,temp
swap opl
mov temp,z_a
andi temp,0xf0
or temp,oph
mov z_a,temp
bst z_flags,ZFL_C ;save C
ldpmx z_flags,sz53p_tab,z_a ;S,Z,H,P,N
bld z_flags,ZFL_C ;
ret
do_fetch_xh:
sbis flags,prefixfd
ldd opl,y+oz_xh
sbic flags,prefixfd
ldd opl,y+oz_yh
ret
do_fetch_xl:
sbis flags,prefixfd
ldd opl,y+oz_xl
sbic flags,prefixfd
ldd opl,y+oz_yl
ret
do_fetch_mxx:
sbic flags,prefixfd
rjmp fetchmxx_fd
ldd xh,y+oz_xh
ldd xl,y+oz_xl
rjmp fetchmxx1
fetchmxx_fd:
ldd xh,y+oz_yh
ldd xl,y+oz_yl
fetchmxx1:
mem_read_ds opl, z_pc ;get displacement
adiw z_pcl,1
clr oph ;sign extend
tst opl
brpl fetchmxx2
com oph
fetchmxx2:
add xl,opl ;add displacement
adc xh,oph
mem_read_d opl ;get operand
ret ;(Ix+d) still in xl,xh
do_fetch_xx:
sbic flags,prefixfd
rjmp fetchxx_fd
ldd opl,y+oz_xl
ldd oph,y+oz_xh
ret
fetchxx_fd:
ldd opl,y+oz_yl
ldd oph,y+oz_yh
ret
do_store_xh:
sbis flags,prefixfd
std y+oz_xh,opl
sbic flags,prefixfd
std y+oz_yh,opl
ret
do_store_xl:
sbis flags,prefixfd
std y+oz_xl,opl
sbic flags,prefixfd
std y+oz_yl,opl
ret
do_store_mxx:
sbic flags,prefixfd
rjmp storemxx_fd
ldd xh,y+oz_xh
ldd xl,y+oz_xl
rjmp storemxx1
storemxx_fd:
ldd xh,y+oz_yh
ldd xl,y+oz_yl
storemxx1:
mem_read_s z_pc ;get displacement
adiw z_pcl,1
clr temp2 ;sign extend
tst temp
brpl storemxx2
com temp2
storemxx2:
add xl,temp ;add displacement
adc xh,temp2
mem_write_s opl ;store operand
ret
do_store_mxx_0:
mem_write_s opl ;store operand
ret
do_store_mxx_2:
sbic flags,prefixfd
rjmp storemxx2_fd
ldd xh,y+oz_xh
ldd xl,y+oz_xl
rjmp storemxx21
storemxx2_fd:
ldd xh,y+oz_yh
ldd xl,y+oz_yl
storemxx21:
mem_read_s z_pc ;get displacement
adiw z_pcl,1
adiw z_pcl,1
clr temp2 ;sign extend
tst temp
brpl storemxx22
com temp2
storemxx22:
add xl,temp ;add displacement
adc xh,temp2
mem_write_s opl ;store operand
ret
do_store_xx:
sbic flags,prefixfd
rjmp storexx_fd
std y+oz_xl,opl
std y+oz_xh,oph
ret
storexx_fd:
std y+oz_yl,opl
std y+oz_yh,oph
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|LD dst,src|------|Load |dst=src |
;
;
do_op_stxx: ;store xx to mem loc in opl:h
movw xl,opl
sbis flags,prefixfd
ldd temp,y+oz_xl
sbic flags,prefixfd
ldd temp,y+oz_yl
mem_write
adiw xl,1
sbis flags,prefixfd
ldd temp,y+oz_xh
sbic flags,prefixfd
ldd temp,y+oz_yh
mem_write
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|EX [SP],IX|------|Exchange |[SP]<->IX |
;|EX [SP],IY|------|Exchange |[SP]<->IY |
;
do_op_EXxx:
sbic flags,prefixfd
rjmp opexxx_fd
ldd temp,y+oz_xl
ldd temp2,y+oz_xh
std y+oz_xl,opl
std y+oz_xh,oph
rjmp opexxxe
opexxx_fd:
ldd temp,y+oz_yl
ldd temp2,y+oz_yh
std y+oz_yl,opl
std y+oz_yh,oph
opexxxe:
movw opl,temp
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|ADD IX,pp |--*-0*|Add |IX=IX+pp |
;|ADD IY,rr |--*-0*|Add |IY=IY+rr |
;
;
do_op_addxx:
sbic flags,prefixfd
rjmp opadx_fd
ldd temp,y+oz_xl
ldd temp2,y+oz_xh
add opl,temp
adc oph,temp2
std y+oz_xl,opl
std y+oz_xh,oph
rjmp opadx_e
opadx_fd:
ldd temp,y+oz_yl
ldd temp2,y+oz_yh
add opl,temp
adc oph,temp2
std y+oz_yl,opl
std y+oz_yh,oph
opadx_e:
in temp,sreg
bmov z_flags,ZFL_C, temp,AVR_C
do_z80_flags_H
do_z80_flags_clear_N
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|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 |
;
op_LDxx_common:
ldd zh,y+oz_h ;H
ldd zl,y+oz_l ;L
ldd xh,y+oz_d ;D
ldd xl,y+oz_e ;E
ldd oph,y+oz_b ;B
ldd opl,y+oz_c ;C
mem_read_ds temp, z
mem_write_ds x, temp
cbr z_flags,(1<m |
;|RL m |**0P0*|Rotate Left |m={CY,m}<- |
;|RR m |**0P0*|Rotate Right |m=->{CY,m} |
;|SLA m |**0P0*|Shift Left Arithmetic|m=m*2 |
;|SRA m |**0P0*|Shift Right Arith. |m=m/2 |
;|SLL m |**0P0*|Shift Right Logical |
;|SRL m |**0P0*|Shift Right Logical |m=->{0,m,CY} |
do_op_rlc:
;Rotate Left Cyclical. All bits move 1 to the
;left, the msb becomes c and lsb.
clr temp
lsl opl
adc temp,_0
or opl,temp
ldpmx z_flags,sz53p_tab,opl ;S,Z,H,P,N
or z_flags,temp
ret
do_op_rrc:
;Rotate Right Cyclical. All bits move 1 to the
;right, the lsb becomes c and msb.
lsr opl
brcc PC+2
ori opl,0x80
ldpmx z_flags,sz53p_tab,opl ;S,Z,H,P,N
bmov z_flags,ZFL_C, opl,7
ret
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
rol opl
in temp,sreg
ldpmx z_flags,sz53p_tab,opl ;S,Z,H,P,N
bmov z_flags,ZFL_C, temp,AVR_C
ret
do_op_rr:
;Rotate Right. All bits move 1 to the right, the lsb
;becomes c, c becomes msb.
ror opl
in temp,sreg ;CY
bmov opl,7, z_flags,ZFL_C ;old CY --> Bit 7
ldpmx z_flags,sz53p_tab,opl ;S,Z,H,P,N
bmov z_flags,ZFL_C, temp,AVR_C ;
ret
do_op_sla:
lsl opl
in temp,sreg
ldpmx z_flags,sz53p_tab,opl ;S,Z,H,P,N
bmov z_flags,ZFL_C, temp,AVR_C ;
ret
do_op_sra:
lsr opl
in temp,sreg
bmov opl,7, opl,6 ;old CY --> Bit 7
ldpmx z_flags,sz53p_tab,opl ;S,Z,H,P,N
bmov z_flags,ZFL_C, temp,AVR_C ;
ret
do_op_sll:
sec
rol opl
in temp,sreg
ldpmx z_flags,sz53p_tab,opl ;S,Z,H,P,N
bmov z_flags,ZFL_C, temp,AVR_C ;
ret
do_op_srl:
lsr opl
in temp,sreg
ldpmx z_flags,sz53p_tab,opl ;S,Z,H,P,N
bmov z_flags,ZFL_C, temp,AVR_C ;
ret
;----------------------------------------------------------------
;|Mnemonic |SZHPNC|Description |Notes |
;----------------------------------------------------------------
;|BIT b,m |?*1?0-|Test Bit |m&{2^b} |
;|RES b,m |------|Reset bit |m=m&{~2^b} |
;|SET b,m |------|Set bit |m=mv{2^b} |
do_op_BIT7:
ldi temp,0x80
rjmp opbit
do_op_BIT6:
ldi temp,0x40
rjmp opbit
do_op_BIT5:
ldi temp,0x20
rjmp opbit
do_op_BIT4:
ldi temp,0x10
rjmp opbit
do_op_BIT3:
ldi temp,0x08
rjmp opbit
do_op_BIT2:
ldi temp,0x04
rjmp opbit
do_op_BIT1:
ldi temp,0x02
rjmp opbit
do_op_BIT0:
ldi temp,0x01
opbit:
and temp,opl
in temp,sreg
ori z_flags,(1<