]> cloudbase.mooo.com Git - avrcpm.git/commitdiff
Merged branch modules back into trunk.
authorLeo <erbl259-lmu@yahoo.de>
Thu, 23 Sep 2010 13:27:14 +0000 (13:27 +0000)
committerLeo <erbl259-lmu@yahoo.de>
Thu, 23 Sep 2010 13:27:14 +0000 (13:27 +0000)
git-svn-id: svn://cu.loc/avr-cpm/trunk/avrcpm/avr@100 57430480-672e-4586-8877-bcf8adbbf3b7

19 files changed:
8080int-jmp.asm [new file with mode: 0644]
8080int-t3-jmp.asm [new file with mode: 0644]
8080int-t3.asm [new file with mode: 0644]
8080int.asm [new file with mode: 0644]
Makefile
avrcpm.asm [new file with mode: 0644]
config.inc [new file with mode: 0644]
dram-4bit.asm [new file with mode: 0644]
dram-4bit.inc [new file with mode: 0644]
dram-8bit.asm [new file with mode: 0644]
dram-8bit.inc [new file with mode: 0644]
hw-uart.asm [new file with mode: 0644]
init.asm [new file with mode: 0644]
macros.inc [new file with mode: 0644]
mmc-old.asm [new file with mode: 0644]
mmc.asm [new file with mode: 0644]
remainders.asm [new file with mode: 0644]
sw-uart.asm [new file with mode: 0644]
z80int.asm [moved from z80.asm with 55% similarity]

diff --git a/8080int-jmp.asm b/8080int-jmp.asm
new file mode 100644 (file)
index 0000000..742a4ed
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+;
+;    $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<<ZFL_N)       ; Negation auf 1
+#endif
+.endm
+
+.macro do_z80_flags_set_HN
+#if EM_Z80
+       ori     z_flags,(1<<ZFL_N)|(1<<ZFL_H)
+#endif
+.endm
+
+.macro do_z80_flags_clear_N
+#if EM_Z80
+       andi    z_flags,~(1<<ZFL_N)
+#endif
+.endm
+
+.macro do_z80_flags_op_rotate
+       ; must not change avr carry flag!
+#if EM_Z80
+       andi   z_flags, ~( (1<<ZFL_H) | (1<<ZFL_N) | (1<<ZFL_C) )
+#else
+       andi   z_flags, ~( (1<<ZFL_C) )
+#endif
+.endm
+
+.macro do_z80_flags_op_and
+#if EM_Z80
+       ori     z_flags,(1<<ZFL_H)
+#else
+       ori     z_flags,(1<<ZFL_H)
+#endif
+.endm
+
+.macro do_z80_flags_op_or
+#if EM_Z80
+#endif
+.endm
+
+
+;----------------------------------------------------------------
+
+do_op_inv:
+       sbiw    z_pcl,1
+       rcall printregs
+       printstring "Invalid opcode! "
+
+haltinv:
+       rjmp haltinv
+
+do_op_nop:
+       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
+       printnewline
+       printstring "Port write: "
+       mov temp,z_a
+       rcall printhex
+       printstring " -> ("
+       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<<ZFL_H)|(1<<ZFL_C)   ; preserve C-, and H-flag
+       ldpmx   temp2, sz53p_tab, opl
+       or      z_flags,temp2           ;
+       do_z80_flags_HP
+       ret
+
+do_op_inca:
+       inc     z_a
+#if EM_Z80
+       in      temp, sreg
+#endif
+       andi    z_flags,(1<<ZFL_H)|(1<<ZFL_C)   ; preserve C-, and H-flag
+       ldpmx   temp2, sz53p_tab, z_a
+       or      z_flags,temp2           ;
+       do_z80_flags_HP
+       ret
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|DEC r     |***V1-|Decrement            |s=s-1                 |
+;|INC [HL]  |***V0-|Increment            |[HL]=[HL]+1           |
+;|INC [xx+d]|***V0-|Increment            |[xx+d]=[xx+d]+1       |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|DEC r     |**-P -|Increment            |r=r+1                 |
+;|DEC [HL]  |**-P -|Increment            |[HL]=[HL]+1           |
+;
+;
+do_op_dec:
+       dec     opl
+#if EM_Z80
+       in    temp, sreg
+#endif
+       andi    z_flags,(1<<ZFL_H)|(1<<ZFL_C)   ; preserve C-, and H-flag
+       ldpmx   temp2, sz53p_tab, opl
+       or      z_flags,temp2           ;
+       do_z80_flags_HP
+       do_z80_flags_set_N
+       ret
+
+do_op_deca:
+       dec     z_a
+#if EM_Z80
+       in    temp, sreg
+#endif
+       andi    z_flags,(1<<ZFL_H)|(1<<ZFL_C)   ; preserve C-, and H-flag
+       ldpmx   temp2, sz53p_tab, z_a
+       or      z_flags,temp2           ;
+       do_z80_flags_HP
+       do_z80_flags_set_N
+       ret
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|INC xx    |------|Increment            |xx=xx+1               |
+;|INC ss    |------|Increment            |ss=ss+1               |
+;
+; 
+do_op_inc16:
+       subi    opl,low(-1)
+       sbci    oph,high(-1)
+       ret
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|DEC xx    |------|Decrement            |xx=xx-1               |
+;|DEC ss    |------|Decrement            |ss=ss-1               |
+;
+; 
+do_op_dec16:
+       subi   opl, 1
+       sbci   oph, 0
+       ret
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|RLCA      |--0-0*|Rotate Left Circular |A=A<-                 |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|RLCA      |---- *|Rotate Left Circular |A=A<-                 |
+;
+;
+do_op_rlc:
+       ;Rotate Left Cyclical. All bits move 1 to the 
+       ;left, the msb becomes c and lsb.
+       do_z80_flags_op_rotate
+       lsl    opl
+       brcc   do_op_rlc_noc
+       ori    opl, 1
+       ori    z_flags, (1<<ZFL_C)
+do_op_rlc_noc:
+       ret
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|RRCA      |--0-0*|Rotate Right Circular|A=->A                 |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|RRCA      |---- *|Rotate Right Circular|A=->A                 |
+;
+;
+do_op_rrc: 
+       ;Rotate Right Cyclical. All bits move 1 to the 
+       ;right, the lsb becomes c and msb.
+       do_z80_flags_op_rotate
+       lsr    opl
+       brcc   do_op_rrc_noc
+       ori    opl, 0x80
+       ori    z_flags, (1<<ZFL_C)
+do_op_rrc_noc:
+       ret
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|RRA       |--0-0*|Rotate Right Acc.    |A=->{CY,A}            |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|RRA       |---- *|Rotate Right Acc.    |A=->{CY,A}            |
+;
+; 
+do_op_rr: 
+       ;Rotate Right. All bits move 1 to the right, the lsb 
+       ;becomes c, c becomes msb.
+       clc                             ; 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<<ZFL_C)
+       rjmp    op_da_60
+       cpi     opl,0xa0
+       brlo    op_da_60n
+op_da_60:                              
+       ori     oph,0x60
+op_da_60n:                             
+       cpi     opl,0x9a
+       brlo    op_da_99n
+       ori     z_flags,(1<<ZFL_C); set C
+op_da_99n:
+       sbrs    z_flags,ZFL_N                   ; if sub-op
+       rjmp    op_da_add                       ; then
+       sub     opl,oph
+       rjmp    op_da_ex
+op_da_add:                                     ; else add-op
+       cpi     opl,0x91
+       brlo    op_da_60n2
+       mov     temp,opl
+       andi    temp,0x0f
+       cpi     temp,0x0a
+       brlo    op_da_60n2
+       ori     oph,0x60
+op_da_60n2:
+       add     opl,oph
+op_da_ex:
+       in      temp,SREG       
+       sbrc    temp,AVR_H
+       ori     z_flags,(1<<ZFL_C)
+       andi    z_flags,(1<<ZFL_N)|(1<<ZFL_C)   ; preserve C,N
+       ldpmx   temp2, sz53p_tab, opl           ; get S,Z,P
+       or      z_flags,temp2
+       bmov    z_flags,ZFL_H, temp,AVR_H       ; H  (?)
+       ret
+#else
+
+do_op_da:
+       sbrc    z_flags,ZFL_N                   ; if add-op     
+       rjmp    do_op_da_sub                    ; then
+       ldi             temp2,0                 ;
+       mov             temp,opl                ;
+       andi    temp,0x0f                       ;
+       cpi             temp,0x0a               ;       if lower digit > 9
+       brlo    do_op_da_h                      ;
+       ori             temp2,0x06              ;               add 6 to lower digit
+do_op_da_h:                                    ;
+       sbrc    z_flags,ZFL_H                   ;   ... or H-Flag
+       ori             temp2,0x06              ;
+       add             opl,temp2               ;
+
+       ldi             temp2,0                 ;
+       mov             temp,opl                ;
+       andi    temp,0xf0                       ;
+       cpi             temp,0xa0               ;
+       brlo    do_op_da_c                      ;
+       ori             temp2,0x60              ;
+do_op_da_c:                                    ; else sub-op
+       sbrc    z_flags,ZFL_C                   ;
+       ori             temp2,0x60              ;
+       andi    z_flags, ~( (1<<ZFL_S) | (1<<ZFL_Z) | (1<<ZFL_H) )
+       add             opl,temp2               ;
+       in              temp,SREG               ;
+       bst             temp,AVR_Z              ;Z-Flag
+       bld             z_flags,ZFL_Z           ;
+       bst             temp,AVR_N              ;S-Flag
+       bst             z_flags,ZFL_S           ;
+       sbrc    temp2,5                         ;C-Flag, set if 0x06 added
+       ori             z_flags,(1<<ZFL_C)      ;
+                                               ;H-Flag?
+       ret
+       
+do_op_da_sub:                                  ;TODO:
+       rcall do_op_inv
+       ret
+#endif
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|SCF       |--0-01|Set Carry Flag       |CY=1                  |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;
+;
+do_op_scf:
+       andi    z_flags,~((1<<ZFL_H)|(1<<ZFL_N))
+       ori     z_flags,(1<<ZFL_C)
+       ret
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|CCF       |--?-0*|Complement Carry Flag|CY=~CY                |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|SCF       |---- 1|Set Carry Flag       |CY=1                  |
+;
+;TODO: H-Flag
+do_op_ccf:
+       do_z80_flags_clear_N
+       ldi temp,(1<<ZFL_C)
+       eor z_flags,temp
+       ret
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|CPL       |--1-1-|Complement           |A=~A                  |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|CPL       |---- -|Complement           |A=~A                  |
+;
+;
+do_op_cpl:
+       com z_a
+       do_z80_flags_set_HN
+       ret
+
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|PUSH xx   |------|Push                 |-[SP]=xx              |
+;|PUSH qq   |------|Push                 |-[SP]=qq              |
+;
+;
+do_op_push16:
+       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
+       printnewline
+       printstring "Stack push "
+       movw temp,opl
+       rcall printhexw
+       printstring ", SP is now "
+       movw temp,z_spl
+       rcall printhexw
+       printstring ". "
+.endif
+
+       ret
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|POP xx    |------|Pop                  |xx=[SP]+              |
+;|POP qq    |------|Pop                  |qq=[SP]+              |
+;
+;
+do_op_pop16:
+       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
+       printnewline
+       printstring "Stack pop  "
+       movw temp,opl
+       rcall printhexw
+       printstring ", SP is now "
+       movw temp,z_spl
+       rcall printhexw
+       printstring ". "
+.endif
+       ret
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|EX [SP],HL|------|Exchange             |[SP]<->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 (file)
index 0000000..0b0bdd7
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+;
+;    $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<<ZFL_N)       ; Negation auf 1
+#endif
+.endm
+
+.macro do_z80_flags_set_HN
+#if EM_Z80
+       ori     z_flags,(1<<ZFL_N)|(1<<ZFL_H)
+#endif
+.endm
+
+.macro do_z80_flags_clear_N
+#if EM_Z80
+       andi    z_flags,~(1<<ZFL_N)
+#endif
+.endm
+
+.macro do_z80_flags_op_rotate
+       ; must not change avr carry flag!
+#if EM_Z80
+       andi   z_flags, ~( (1<<ZFL_H) | (1<<ZFL_N) | (1<<ZFL_C) )
+#else
+       andi   z_flags, ~( (1<<ZFL_C) )
+#endif
+.endm
+
+.macro do_z80_flags_op_and
+#if EM_Z80
+       ori     z_flags,(1<<ZFL_H)
+#else
+       ori     z_flags,(1<<ZFL_H)
+#endif
+.endm
+
+.macro do_z80_flags_op_or
+#if EM_Z80
+#endif
+.endm
+
+
+;----------------------------------------------------------------
+
+do_op_inv:
+       printstring "Invalid opcode @ PC="
+       movw   temp,z_pcl
+       rcall printhexw
+
+haltinv:
+       rjmp haltinv
+
+do_op_nop:
+       op_end
+       
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|OUT [n],A |------|Output               |[n]=A                 |
+;
+;
+;Interface with peripherials goes here :)
+do_op_outa: ; out (opl),a
+.if PORT_DEBUG
+       printnewline
+       printstring "Port write: "
+       mov temp,z_a
+       rcall printhex
+       printstring " -> ("
+       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<<ZFL_H)|(1<<ZFL_C)   ; preserve C-, and H-flag
+       ldpmx   temp2, sz53p_tab, opl
+       or      z_flags,temp2           ;
+       do_z80_flags_HP
+       op_end
+
+do_op_inca:
+       inc     z_a
+#if EM_Z80
+       in      temp, sreg
+#endif
+       andi    z_flags,(1<<ZFL_H)|(1<<ZFL_C)   ; preserve C-, and H-flag
+       ldpmx   temp2, sz53p_tab, z_a
+       or      z_flags,temp2           ;
+       do_z80_flags_HP
+       op_end
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|DEC r     |***V1-|Decrement            |s=s-1                 |
+;|INC [HL]  |***V0-|Increment            |[HL]=[HL]+1           |
+;|INC [xx+d]|***V0-|Increment            |[xx+d]=[xx+d]+1       |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|DEC r     |**-P -|Increment            |r=r+1                 |
+;|DEC [HL]  |**-P -|Increment            |[HL]=[HL]+1           |
+;
+;
+do_op_dec:
+       dec     opl
+#if EM_Z80
+       in    temp, sreg
+#endif
+       andi    z_flags,(1<<ZFL_H)|(1<<ZFL_C)   ; preserve C-, and H-flag
+       ldpmx   temp2, sz53p_tab, opl
+       or      z_flags,temp2           ;
+       do_z80_flags_HP
+       do_z80_flags_set_N
+       op_end
+
+do_op_deca:
+       dec     z_a
+#if EM_Z80
+       in    temp, sreg
+#endif
+       andi    z_flags,(1<<ZFL_H)|(1<<ZFL_C)   ; preserve C-, and H-flag
+       ldpmx   temp2, sz53p_tab, z_a
+       or      z_flags,temp2           ;
+       do_z80_flags_HP
+       do_z80_flags_set_N
+       op_end
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|INC xx    |------|Increment            |xx=xx+1               |
+;|INC ss    |------|Increment            |ss=ss+1               |
+;
+; 
+do_op_inc16:
+       subi    opl,low(-1)
+       sbci    oph,high(-1)
+       op_end
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|DEC xx    |------|Decrement            |xx=xx-1               |
+;|DEC ss    |------|Decrement            |ss=ss-1               |
+;
+; 
+do_op_dec16:
+       subi   opl, 1
+       sbci   oph, 0
+       op_end
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|RLCA      |--0-0*|Rotate Left Circular |A=A<-                 |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|RLCA      |---- *|Rotate Left Circular |A=A<-                 |
+;
+;
+do_op_rlc:
+       ;Rotate Left Cyclical. All bits move 1 to the 
+       ;left, the msb becomes c and lsb.
+       do_z80_flags_op_rotate
+       lsl    opl
+       brcc   do_op_rlc_noc
+       ori    opl, 1
+       ori    z_flags, (1<<ZFL_C)
+do_op_rlc_noc:
+       op_end
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|RRCA      |--0-0*|Rotate Right Circular|A=->A                 |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|RRCA      |---- *|Rotate Right Circular|A=->A                 |
+;
+;
+do_op_rrc: 
+       ;Rotate Right Cyclical. All bits move 1 to the 
+       ;right, the lsb becomes c and msb.
+       do_z80_flags_op_rotate
+       lsr    opl
+       brcc   do_op_rrc_noc
+       ori    opl, 0x80
+       ori    z_flags, (1<<ZFL_C)
+do_op_rrc_noc:
+       op_end
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|RRA       |--0-0*|Rotate Right Acc.    |A=->{CY,A}            |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|RRA       |---- *|Rotate Right Acc.    |A=->{CY,A}            |
+;
+; 
+do_op_rr: 
+       ;Rotate Right. All bits move 1 to the right, the lsb 
+       ;becomes c, c becomes msb.
+       clc                             ; 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<<ZFL_C)
+       rjmp    op_da_60
+       cpi     opl,0xa0
+       brlo    op_da_60n
+op_da_60:                              
+       ori     oph,0x60
+op_da_60n:                             
+       cpi     opl,0x9a
+       brlo    op_da_99n
+       ori     z_flags,(1<<ZFL_C); set C
+op_da_99n:
+       sbrs    z_flags,ZFL_N                   ; if sub-op
+       rjmp    op_da_add                       ; then
+       sub     opl,oph
+       rjmp    op_da_ex
+op_da_add:                                     ; else add-op
+       cpi     opl,0x91
+       brlo    op_da_60n2
+       mov     temp,opl
+       andi    temp,0x0f
+       cpi     temp,0x0a
+       brlo    op_da_60n2
+       ori     oph,0x60
+op_da_60n2:
+       add     opl,oph
+op_da_ex:
+       in      temp,SREG       
+       sbrc    temp,AVR_H
+       ori     z_flags,(1<<ZFL_C)
+       andi    z_flags,(1<<ZFL_N)|(1<<ZFL_C)   ; preserve C,N
+       ldpmx   temp2, sz53p_tab, opl           ; get S,Z,P
+       or      z_flags,temp2
+       bmov    z_flags,ZFL_H, temp,AVR_H       ; H  (?)
+       op_end
+#else
+
+do_op_da:
+       sbrc    z_flags,ZFL_N                   ; if add-op     
+       rjmp    do_op_da_sub                    ; then
+       ldi             temp2,0                 ;
+       mov             temp,opl                ;
+       andi    temp,0x0f                       ;
+       cpi             temp,0x0a               ;       if lower digit > 9
+       brlo    do_op_da_h                      ;
+       ori             temp2,0x06              ;               add 6 to lower digit
+do_op_da_h:                                    ;
+       sbrc    z_flags,ZFL_H                   ;   ... or H-Flag
+       ori             temp2,0x06              ;
+       add             opl,temp2               ;
+
+       ldi             temp2,0                 ;
+       mov             temp,opl                ;
+       andi    temp,0xf0                       ;
+       cpi             temp,0xa0               ;
+       brlo    do_op_da_c                      ;
+       ori             temp2,0x60              ;
+do_op_da_c:                                    ; else sub-op
+       sbrc    z_flags,ZFL_C                   ;
+       ori             temp2,0x60              ;
+       andi    z_flags, ~( (1<<ZFL_S) | (1<<ZFL_Z) | (1<<ZFL_H) )
+       add             opl,temp2               ;
+       in              temp,SREG               ;
+       bst             temp,AVR_Z              ;Z-Flag
+       bld             z_flags,ZFL_Z           ;
+       bst             temp,AVR_N              ;S-Flag
+       bst             z_flags,ZFL_S           ;
+       sbrc    temp2,5                         ;C-Flag, set if 0x06 added
+       ori             z_flags,(1<<ZFL_C)      ;
+                                               ;H-Flag?
+       op_end
+       
+do_op_da_sub:                                  ;TODO:
+       rcall do_op_inv
+       op_end
+#endif
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|SCF       |--0-01|Set Carry Flag       |CY=1                  |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;
+;
+do_op_scf:
+       andi    z_flags,~((1<<ZFL_H)|(1<<ZFL_N))
+       ori     z_flags,(1<<ZFL_C)
+       op_end
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|CCF       |--?-0*|Complement Carry Flag|CY=~CY                |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|SCF       |---- 1|Set Carry Flag       |CY=1                  |
+;
+;TODO: H-Flag
+do_op_ccf:
+       do_z80_flags_clear_N
+       ldi temp,(1<<ZFL_C)
+       eor z_flags,temp
+       op_end
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|CPL       |--1-1-|Complement           |A=~A                  |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|CPL       |---- -|Complement           |A=~A                  |
+;
+;
+do_op_cpl:
+       com z_a
+       do_z80_flags_set_HN
+       op_end
+
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|PUSH xx   |------|Push                 |-[SP]=xx              |
+;|PUSH qq   |------|Push                 |-[SP]=qq              |
+;
+;
+do_op_push16:
+       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
+       printnewline
+       printstring "Stack push "
+       movw temp,opl
+       rcall printhexw
+       printstring ", SP is now "
+       movw temp,z_spl
+       rcall printhexw
+       printstring ". "
+.endif
+
+       op_end
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|POP xx    |------|Pop                  |xx=[SP]+              |
+;|POP qq    |------|Pop                  |qq=[SP]+              |
+;
+;
+do_op_pop16:
+       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
+       printnewline
+       printstring "Stack pop  "
+       movw temp,opl
+       rcall printhexw
+       printstring ", SP is now "
+       movw temp,z_spl
+       rcall printhexw
+       printstring ". "
+.endif
+       op_end
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|EX [SP],HL|------|Exchange             |[SP]<->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 (file)
index 0000000..9d99c02
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+;
+;    $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<<ZFL_N)       ; Negation auf 1
+#endif
+.endm
+
+.macro do_z80_flags_set_HN
+#if EM_Z80
+       ori     z_flags,(1<<ZFL_N)|(1<<ZFL_H)
+#endif
+.endm
+
+.macro do_z80_flags_clear_N
+#if EM_Z80
+       andi    z_flags,~(1<<ZFL_N)
+#endif
+.endm
+
+.macro do_z80_flags_op_rotate
+       ; must not change avr carry flag!
+#if EM_Z80
+       andi   z_flags, ~( (1<<ZFL_H) | (1<<ZFL_N) | (1<<ZFL_C) )
+#else
+       andi   z_flags, ~( (1<<ZFL_C) )
+#endif
+.endm
+
+.macro do_z80_flags_op_and
+#if EM_Z80
+       ori     z_flags,(1<<ZFL_H)
+#else
+       ori     z_flags,(1<<ZFL_H)
+#endif
+.endm
+
+.macro do_z80_flags_op_or
+#if EM_Z80
+#endif
+.endm
+
+
+;----------------------------------------------------------------
+
+do_op_inv:
+       printstring "Invalid opcode @ PC="
+       movw   temp,z_pcl
+       rcall printhexw
+
+haltinv:
+       rjmp haltinv
+
+do_op_nop:
+       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
+       printnewline
+       printstring "Port write: "
+       mov temp,z_a
+       rcall printhex
+       printstring " -> ("
+       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<<ZFL_H)|(1<<ZFL_C)   ; preserve C-, and H-flag
+       ldpmx   temp2, sz53p_tab, opl
+       or      z_flags,temp2           ;
+       do_z80_flags_HP
+       ret
+
+do_op_inca:
+       inc     z_a
+#if EM_Z80
+       in      temp, sreg
+#endif
+       andi    z_flags,(1<<ZFL_H)|(1<<ZFL_C)   ; preserve C-, and H-flag
+       ldpmx   temp2, sz53p_tab, z_a
+       or      z_flags,temp2           ;
+       do_z80_flags_HP
+       ret
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|DEC r     |***V1-|Decrement            |s=s-1                 |
+;|INC [HL]  |***V0-|Increment            |[HL]=[HL]+1           |
+;|INC [xx+d]|***V0-|Increment            |[xx+d]=[xx+d]+1       |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|DEC r     |**-P -|Increment            |r=r+1                 |
+;|DEC [HL]  |**-P -|Increment            |[HL]=[HL]+1           |
+;
+;
+do_op_dec:
+       dec     opl
+#if EM_Z80
+       in    temp, sreg
+#endif
+       andi    z_flags,(1<<ZFL_H)|(1<<ZFL_C)   ; preserve C-, and H-flag
+       ldpmx   temp2, sz53p_tab, opl
+       or      z_flags,temp2           ;
+       do_z80_flags_HP
+       do_z80_flags_set_N
+       ret
+
+do_op_deca:
+       dec     z_a
+#if EM_Z80
+       in    temp, sreg
+#endif
+       andi    z_flags,(1<<ZFL_H)|(1<<ZFL_C)   ; preserve C-, and H-flag
+       ldpmx   temp2, sz53p_tab, z_a
+       or      z_flags,temp2           ;
+       do_z80_flags_HP
+       do_z80_flags_set_N
+       ret
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|INC xx    |------|Increment            |xx=xx+1               |
+;|INC ss    |------|Increment            |ss=ss+1               |
+;
+; 
+do_op_inc16:
+       subi    opl,low(-1)
+       sbci    oph,high(-1)
+       ret
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|DEC xx    |------|Decrement            |xx=xx-1               |
+;|DEC ss    |------|Decrement            |ss=ss-1               |
+;
+; 
+do_op_dec16:
+       subi   opl, 1
+       sbci   oph, 0
+       ret
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|RLCA      |--0-0*|Rotate Left Circular |A=A<-                 |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|RLCA      |---- *|Rotate Left Circular |A=A<-                 |
+;
+;
+do_op_rlc:
+       ;Rotate Left Cyclical. All bits move 1 to the 
+       ;left, the msb becomes c and lsb.
+       do_z80_flags_op_rotate
+       lsl    opl
+       brcc   do_op_rlc_noc
+       ori    opl, 1
+       ori    z_flags, (1<<ZFL_C)
+do_op_rlc_noc:
+       ret
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|RRCA      |--0-0*|Rotate Right Circular|A=->A                 |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|RRCA      |---- *|Rotate Right Circular|A=->A                 |
+;
+;
+do_op_rrc: 
+       ;Rotate Right Cyclical. All bits move 1 to the 
+       ;right, the lsb becomes c and msb.
+       do_z80_flags_op_rotate
+       lsr    opl
+       brcc   do_op_rrc_noc
+       ori    opl, 0x80
+       ori    z_flags, (1<<ZFL_C)
+do_op_rrc_noc:
+       ret
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|RRA       |--0-0*|Rotate Right Acc.    |A=->{CY,A}            |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|RRA       |---- *|Rotate Right Acc.    |A=->{CY,A}            |
+;
+; 
+do_op_rr: 
+       ;Rotate Right. All bits move 1 to the right, the lsb 
+       ;becomes c, c becomes msb.
+       clc                             ; 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<<ZFL_C)
+       rjmp    op_da_60
+       cpi     opl,0xa0
+       brlo    op_da_60n
+op_da_60:                              
+       ori     oph,0x60
+op_da_60n:                             
+       cpi     opl,0x9a
+       brlo    op_da_99n
+       ori     z_flags,(1<<ZFL_C); set C
+op_da_99n:
+       sbrs    z_flags,ZFL_N                   ; if sub-op
+       rjmp    op_da_add                       ; then
+       sub     opl,oph
+       rjmp    op_da_ex
+op_da_add:                                     ; else add-op
+       cpi     opl,0x91
+       brlo    op_da_60n2
+       mov     temp,opl
+       andi    temp,0x0f
+       cpi     temp,0x0a
+       brlo    op_da_60n2
+       ori     oph,0x60
+op_da_60n2:
+       add     opl,oph
+op_da_ex:
+       in      temp,SREG       
+       sbrc    temp,AVR_H
+       ori     z_flags,(1<<ZFL_C)
+       andi    z_flags,(1<<ZFL_N)|(1<<ZFL_C)   ; preserve C,N
+       ldpmx   temp2, sz53p_tab, opl           ; get S,Z,P
+       or      z_flags,temp2
+       bmov    z_flags,ZFL_H, temp,AVR_H       ; H  (?)
+       ret
+#else
+
+do_op_da:
+       sbrc    z_flags,ZFL_N                   ; if add-op     
+       rjmp    do_op_da_sub                    ; then
+       ldi             temp2,0                 ;
+       mov             temp,opl                ;
+       andi    temp,0x0f                       ;
+       cpi             temp,0x0a               ;if lower digit > 9
+       brlo    do_op_da_h                      ;
+       ori             temp2,0x06              ;       add 6 to lower digit
+do_op_da_h:                                    ;
+       sbrc    z_flags,ZFL_H                   ;   ... or H-Flag
+       ori             temp2,0x06              ;
+       add             opl,temp2               ;
+
+       ldi             temp2,0                 ;
+       mov             temp,opl                ;
+       andi    temp,0xf0                       ;
+       cpi             temp,0xa0               ;
+       brlo    do_op_da_c                      ;
+       ori             temp2,0x60              ;
+do_op_da_c:                                    ; else sub-op
+       sbrc    z_flags,ZFL_C                   ;
+       ori             temp2,0x60              ;
+       andi    z_flags, ~( (1<<ZFL_S) | (1<<ZFL_Z) | (1<<ZFL_H) )
+       add             opl,temp2               ;
+       in              temp,SREG               ;
+       bst             temp,AVR_Z              ;Z-Flag
+       bld             z_flags,ZFL_Z           ;
+       bst             temp,AVR_N              ;S-Flag
+       bst             z_flags,ZFL_S           ;
+       sbrc    temp2,5                         ;C-Flag, set if 0x06 added
+       ori             z_flags,(1<<ZFL_C)      ;
+                                               ;H-Flag?
+       ret
+       
+do_op_da_sub:                                  ;TODO:
+       rcall do_op_inv
+       ret
+#endif
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|SCF       |--0-01|Set Carry Flag       |CY=1                  |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;
+;
+do_op_scf:
+       andi    z_flags,~((1<<ZFL_H)|(1<<ZFL_N))
+       ori     z_flags,(1<<ZFL_C)
+       ret
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|CCF       |--?-0*|Complement Carry Flag|CY=~CY                |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|SCF       |---- 1|Set Carry Flag       |CY=1                  |
+;
+;TODO: H-Flag
+do_op_ccf:
+       do_z80_flags_clear_N
+       ldi temp,(1<<ZFL_C)
+       eor z_flags,temp
+       ret
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|CPL       |--1-1-|Complement           |A=~A                  |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|CPL       |---- -|Complement           |A=~A                  |
+;
+;
+do_op_cpl:
+       com z_a
+       do_z80_flags_set_HN
+       ret
+
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|PUSH xx   |------|Push                 |-[SP]=xx              |
+;|PUSH qq   |------|Push                 |-[SP]=qq              |
+;
+;
+do_op_push16:
+       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
+       printnewline
+       printstring "Stack push "
+       movw temp,opl
+       rcall printhexw
+       printstring ", SP is now "
+       movw temp,z_spl
+       rcall printhexw
+       printstring ". "
+.endif
+
+       ret
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|POP xx    |------|Pop                  |xx=[SP]+              |
+;|POP qq    |------|Pop                  |qq=[SP]+              |
+;
+;
+do_op_pop16:
+       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
+       printnewline
+       printstring "Stack pop  "
+       movw temp,opl
+       rcall printhexw
+       printstring ", SP is now "
+       movw temp,z_spl
+       rcall printhexw
+       printstring ". "
+.endif
+       ret
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|EX [SP],HL|------|Exchange             |[SP]<->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 (file)
index 0000000..1acb38b
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+;
+;    $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<<ZFL_N)       ; Negation auf 1
+#endif
+.endm
+
+.macro do_z80_flags_set_HN
+#if EM_Z80
+       ori     z_flags,(1<<ZFL_N)|(1<<ZFL_H)
+#endif
+.endm
+
+.macro do_z80_flags_clear_N
+#if EM_Z80
+       andi    z_flags,~(1<<ZFL_N)
+#endif
+.endm
+
+.macro do_z80_flags_op_rotate
+       ; must not change avr carry flag!
+#if EM_Z80
+       andi   z_flags, ~( (1<<ZFL_H) | (1<<ZFL_N) | (1<<ZFL_C) )
+#else
+       andi   z_flags, ~( (1<<ZFL_C) )
+#endif
+.endm
+
+.macro do_z80_flags_op_and
+#if EM_Z80
+       ori     z_flags,(1<<ZFL_H)
+#else
+       ori     z_flags,(1<<ZFL_H)
+#endif
+.endm
+
+.macro do_z80_flags_op_or
+#if EM_Z80
+#endif
+.endm
+
+
+;----------------------------------------------------------------
+
+do_op_inv:
+       printstring "Invalid opcode @ PC="
+       movw   temp,z_pcl
+       rcall printhexw
+
+haltinv:
+       rjmp haltinv
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|OUT [n],A |------|Output               |[n]=A                 |
+;
+;
+;Interface with peripherials goes here :)
+do_op_outa: ; out (opl),a
+.if PORT_DEBUG
+       printnewline
+       printstring "Port write: "
+       mov temp,z_a
+       rcall printhex
+       printstring " -> ("
+       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<<ZFL_H)|(1<<ZFL_C)   ; preserve C-, and H-flag
+       ldpmx   temp2, sz53p_tab, opl
+       or      z_flags,temp2           ;
+       do_z80_flags_HP
+       ret
+
+do_op_inca:
+       inc     z_a
+#if EM_Z80
+       in      temp, sreg
+#endif
+       andi    z_flags,(1<<ZFL_H)|(1<<ZFL_C)   ; preserve C-, and H-flag
+       ldpmx   temp2, sz53p_tab, z_a
+       or      z_flags,temp2           ;
+       do_z80_flags_HP
+       ret
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|DEC r     |***V1-|Decrement            |s=s-1                 |
+;|INC [HL]  |***V0-|Increment            |[HL]=[HL]+1           |
+;|INC [xx+d]|***V0-|Increment            |[xx+d]=[xx+d]+1       |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|DEC r     |**-P -|Increment            |r=r+1                 |
+;|DEC [HL]  |**-P -|Increment            |[HL]=[HL]+1           |
+;
+;
+do_op_dec:
+       dec     opl
+#if EM_Z80
+       in    temp, sreg
+#endif
+       andi    z_flags,(1<<ZFL_H)|(1<<ZFL_C)   ; preserve C-, and H-flag
+       ldpmx   temp2, sz53p_tab, opl
+       or      z_flags,temp2           ;
+       do_z80_flags_HP
+       do_z80_flags_set_N
+       ret
+
+do_op_deca:
+       dec     z_a
+#if EM_Z80
+       in    temp, sreg
+#endif
+       andi    z_flags,(1<<ZFL_H)|(1<<ZFL_C)   ; preserve C-, and H-flag
+       ldpmx   temp2, sz53p_tab, z_a
+       or      z_flags,temp2           ;
+       do_z80_flags_HP
+       do_z80_flags_set_N
+       ret
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|INC xx    |------|Increment            |xx=xx+1               |
+;|INC ss    |------|Increment            |ss=ss+1               |
+;
+; 
+do_op_inc16:
+       subi    opl,low(-1)
+       sbci    oph,high(-1)
+       ret
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|DEC xx    |------|Decrement            |xx=xx-1               |
+;|DEC ss    |------|Decrement            |ss=ss-1               |
+;
+; 
+do_op_dec16:
+       subi   opl, 1
+       sbci   oph, 0
+       ret
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|RLCA      |--0-0*|Rotate Left Circular |A=A<-                 |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|RLCA      |---- *|Rotate Left Circular |A=A<-                 |
+;
+;
+do_op_rlc:
+       ;Rotate Left Cyclical. All bits move 1 to the 
+       ;left, the msb becomes c and lsb.
+       do_z80_flags_op_rotate
+       lsl    opl
+       brcc   do_op_rlc_noc
+       ori    opl, 1
+       ori    z_flags, (1<<ZFL_C)
+do_op_rlc_noc:
+       ret
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|RRCA      |--0-0*|Rotate Right Circular|A=->A                 |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|RRCA      |---- *|Rotate Right Circular|A=->A                 |
+;
+;
+do_op_rrc: 
+       ;Rotate Right Cyclical. All bits move 1 to the 
+       ;right, the lsb becomes c and msb.
+       do_z80_flags_op_rotate
+       lsr    opl
+       brcc   do_op_rrc_noc
+       ori    opl, 0x80
+       ori    z_flags, (1<<ZFL_C)
+do_op_rrc_noc:
+       ret
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|RRA       |--0-0*|Rotate Right Acc.    |A=->{CY,A}            |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|RRA       |---- *|Rotate Right Acc.    |A=->{CY,A}            |
+;
+; 
+do_op_rr: 
+       ;Rotate Right. All bits move 1 to the right, the lsb 
+       ;becomes c, c becomes msb.
+       clc                             ; 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<<ZFL_C)
+       rjmp    op_da_60
+       cpi     opl,0xa0
+       brlo    op_da_60n
+op_da_60:                              
+       ori     oph,0x60
+op_da_60n:                             
+       cpi     opl,0x9a
+       brlo    op_da_99n
+       ori     z_flags,(1<<ZFL_C); set C
+op_da_99n:
+       sbrs    z_flags,ZFL_N                   ; if sub-op
+       rjmp    op_da_add                       ; then
+       sub     opl,oph
+       rjmp    op_da_ex
+op_da_add:                                     ; else add-op
+       cpi     opl,0x91
+       brlo    op_da_60n2
+       mov     temp,opl
+       andi    temp,0x0f
+       cpi     temp,0x0a
+       brlo    op_da_60n2
+       ori     oph,0x60
+op_da_60n2:
+       add     opl,oph
+op_da_ex:
+       in      temp,SREG       
+       sbrc    temp,AVR_H
+       ori     z_flags,(1<<ZFL_C)
+       andi    z_flags,(1<<ZFL_N)|(1<<ZFL_C)   ; preserve C,N
+       ldpmx   temp2, sz53p_tab, opl           ; get S,Z,P
+       or      z_flags,temp2
+       bmov    z_flags,ZFL_H, temp,AVR_H       ; H  (?)
+       ret
+#else
+
+do_op_da:
+       sbrc    z_flags,ZFL_N                   ; if add-op     
+       rjmp    do_op_da_sub                    ; then
+       ldi             temp2,0                 ;
+       mov             temp,opl                ;
+       andi    temp,0x0f                       ;
+       cpi             temp,0x0a               ;if lower digit > 9
+       brlo    do_op_da_h                      ;
+       ori             temp2,0x06              ;       add 6 to lower digit
+do_op_da_h:                                    ;
+       sbrc    z_flags,ZFL_H                   ;   ... or H-Flag
+       ori             temp2,0x06              ;
+       add             opl,temp2               ;
+
+       ldi             temp2,0                 ;
+       mov             temp,opl                ;
+       andi    temp,0xf0                       ;
+       cpi             temp,0xa0               ;
+       brlo    do_op_da_c                      ;
+       ori             temp2,0x60              ;
+do_op_da_c:                                    ; else sub-op
+       sbrc    z_flags,ZFL_C                   ;
+       ori             temp2,0x60              ;
+       andi    z_flags, ~( (1<<ZFL_S) | (1<<ZFL_Z) | (1<<ZFL_H) )
+       add             opl,temp2               ;
+       in              temp,SREG               ;
+       bst             temp,AVR_Z              ;Z-Flag
+       bld             z_flags,ZFL_Z           ;
+       bst             temp,AVR_N              ;S-Flag
+       bst             z_flags,ZFL_S           ;
+       sbrc    temp2,5                         ;C-Flag, set if 0x06 added
+       ori             z_flags,(1<<ZFL_C)      ;
+                                               ;H-Flag?
+       ret
+       
+do_op_da_sub:                                  ;TODO:
+       rcall do_op_inv
+       ret
+#endif
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|SCF       |--0-01|Set Carry Flag       |CY=1                  |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;
+;
+do_op_scf:
+       andi    z_flags,~((1<<ZFL_H)|(1<<ZFL_N))
+       ori     z_flags,(1<<ZFL_C)
+       ret
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|CCF       |--?-0*|Complement Carry Flag|CY=~CY                |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|SCF       |---- 1|Set Carry Flag       |CY=1                  |
+;
+;TODO: H-Flag
+do_op_ccf:
+       do_z80_flags_clear_N
+       ldi temp,(1<<ZFL_C)
+       eor z_flags,temp
+       ret
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|CPL       |--1-1-|Complement           |A=~A                  |
+;|----------|SZHP C|---------- 8080 ----------------------------|
+;|CPL       |---- -|Complement           |A=~A                  |
+;
+;
+do_op_cpl:
+       com z_a
+       do_z80_flags_set_HN
+       ret
+
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|PUSH xx   |------|Push                 |-[SP]=xx              |
+;|PUSH qq   |------|Push                 |-[SP]=qq              |
+;
+;
+do_op_push16:
+       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
+       printnewline
+       printstring "Stack push "
+       movw temp,opl
+       rcall printhexw
+       printstring ", SP is now "
+       movw temp,z_spl
+       rcall printhexw
+       printstring ". "
+.endif
+
+       ret
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|POP xx    |------|Pop                  |xx=[SP]+              |
+;|POP qq    |------|Pop                  |qq=[SP]+              |
+;
+;
+do_op_pop16:
+       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
+       printnewline
+       printstring "Stack pop  "
+       movw temp,opl
+       rcall printhexw
+       printstring ", SP is now "
+       movw temp,z_spl
+       rcall printhexw
+       printstring ". "
+.endif
+       ret
+
+;----------------------------------------------------------------
+;|Mnemonic  |SZHPNC|Description          |Notes                 |
+;----------------------------------------------------------------
+;|EX [SP],HL|------|Exchange             |[SP]<->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
+
index cc3eaf11fb8e441a34f2cfbfd0b13fccf13334b1..9fa980f85d6e41ea88ec156ad5d14d68d0899703 100644 (file)
--- 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 (file)
index 0000000..10da302
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+;
+;    $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 (file)
index 0000000..e14ef43
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+;
+;    $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<<RAM_A8)|(1<<RAM_A7)|(1<<RAM_A6)|(1<<RAM_A5)
+.equ PD_OUTPUT_MASK = (1<<MMC_CS) | (1<<RAM_OE) | RAM_AH_MASK
+
+
+;Port B
+.equ RAM_A4    = 0
+.equ RAM_A3    = 1
+.equ RAM_A2    = 2
+.equ RAM_A1    = 3
+.equ MMC_MOSI  = 3
+.equ RAM_A0    = 4
+.equ MMC_MISO  = 4
+.equ RAM_RAS   = 5
+.equ MMC_SCK   = 5
+
+.equ P_RAS     = PORTB
+.equ P_AL      = PORTB
+                       ; RAM_A[4..0]
+.equ RAM_AL_MASK = (1<<RAM_A4)|(1<<RAM_A3)|(1<<RAM_A2)|(1<<RAM_A1)|(1<<RAM_A0)
+.equ PB_OUTPUT_MASK = (1<<RAM_ras) | RAM_AL_MASK
+
+;Port C
+.equ RAM_D0    = 0
+.equ RAM_D1    = 1
+.equ RAM_D2    = 2
+.equ RAM_D3    = 3
+.equ RAM_W     = 4
+.equ RAM_CAS   = 5
+
+.equ P_DQ      = PORTC
+.equ P_W       = PORTC
+.equ P_CAS     = PORTC
+
+.equ RAM_DQ_MASK = (1<<RAM_D3)|(1<<RAM_D2)|(1<<RAM_D1)|(1<<RAM_D0)
+.equ PC_OUTPUT_MASK = (1<<RAM_CAS)|(1<<RAM_W)
+
+#endif /* DRAM_8BIT */
+
+
+;-----------------------------------------------------------------------
+;Register definitions
+
+.def   _tmp0   = r0
+.def   _tmp1   = r1
+
+.def   _RAS0   = r2
+.def   _CAS0   = r3
+.def   _OE     = r4
+.def   _WE     = r5
+.def   _255    = r6
+.def   _0      = r7
+.def   z_a     = r9
+;.def  stx_bitcount  = r9
+;.def  stx_dr        = r10
+.def   srx_lastedgel = r10
+.def   srx_lastedgeh = r11
+
+.def   insstore= r8    ;
+;.def  insop   = r13   ;
+.def   insdecl = r12   ;
+.def   insdech = r13   ;
+.def   z_spl   = r14
+.def   z_sph   = r15   ;
+.def   temp    = r16   ;
+.def   temp2   = r17   ;
+.def   temp3   = r18
+.def   temp4   = r19
+.def   z_flags = r20   ;
+                       ;
+.def   opl     = r22   ;
+.def   oph     = r23   ;
+.def   z_pcl   = r24   ;
+.def   z_pch   = r25   ;
+; xl           ;r26
+; xh           ;r27
+; yl           ;r28
+; yh           ;r29
+; zl           ;r30    ;
+; zh           ;r31    ;
+
+
+
+#if defined __ATmega8__
+.equ   flags   = TWBR
+.equ   P_PUD   = SFIOR
+#else
+.equ   flags   = GPIOR0
+.equ   P_PUD   = MCUCR
+#endif
+
+; Flags:
+       .equ    hostact = 7             ;host active flag
+       .equ    hostwrt = 6             ;host written flag
+       .equ    rsflag  = 5             ;read sector flag
+       .equ    readop  = 4             ;1 if read operation
+       .equ    trace   = 0
+
+; This is the base z80 port address for clock access
+#define        TIMERPORT   0x40
+#define TIMER_CTL   TIMERPORT
+#define TIMER_MSECS TIMERPORT+1
+#define TIMER_SECS  TIMER_MSECS+2
+
+#define starttimercmd  1
+#define quitTimerCmd   2
+#define printTimerCmd  15
+#define uptimeCmd      16
+
+#if defined __ATmega8__
+.equ   RXTXDR0 = UDR
+.equ   UCSR0A  = UCSRA
+.equ    UDRE0  = UDRE
+.equ   UCSR0B  = UCSRB
+.equ    RXCIE0 = RXCIE
+.equ    UDRIE0 = UDRIE
+.equ    RXEN0  = RXEN
+.equ    TXEN0  = TXEN
+.equ   UCSR0C  = UCSRC
+.equ    UCSZ00 = UCSZ0
+.equ    UCSZ01 = UCSZ1
+.equ   UBRR0H  = UBRRH
+.equ   UBRR0L  = UBRRL
+.equ   OCR2A   = OCR2
+.equ   OC2Aaddr= OC2addr
+.equ   TCCR2A  = TCCR2
+.equ   TCCR2B  = TCCR2
+.equ   TIMSK1  = TIMSK
+.equ   TIMSK2  = TIMSK
+.equ   OCIE2A  = OCIE2
+.equ   TIFR1   = TIFR
+.equ   ICIE1   = TICIE1
+#else
+.equ   RXTXDR0 = UDR0
+#endif
+
+; vim:set ts=8 noet nowrap
+
+
diff --git a/dram-4bit.asm b/dram-4bit.asm
new file mode 100644 (file)
index 0000000..e0d088a
--- /dev/null
@@ -0,0 +1,92 @@
+; DRAM interface for *one* 256K x 4 bit DRAM chip.
+; This is part of the Z80-CP/M emulator written by Sprite_tm.
+
+;    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 <http://www.gnu.org/licenses/>.
+;
+;    $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<<ram_ras), ~(1<<ram_a8), (1<<ram_oe)
+       cbi P_RAS,ram_ras
+       DRAM_SETADDR xl, ~(1<<ram_ras),0, ~((1<<ram_oe)), (1<<ram_a8)
+       cbi P_CAS,ram_cas
+       cbi P_A8,ram_a8
+       dram_wait DRAM_WAITSTATES       ;
+       in  temp,P_DQ-2         ; PIN
+       out P_CAS,_255
+
+       cbi P_CAS,ram_cas
+       andi temp,0x0f
+       swap temp
+       dram_wait DRAM_WAITSTATES       ;
+       in  temp2,P_DQ-2        ; PIN
+       andi temp2,0x0f
+       or  temp,temp2
+
+       out P_OE, _255
+       out P_CAS,_255
+       out P_RAS,_255
+;      sei
+       ret
+
+
+;Writes the byte in temp to  xh:xl
+; Uses temp2. Must not alter xh:xl
+
+dram_write:
+;      cli
+       ldi temp2,RAM_DQ_MASK | (1<<ram_w) | (1<<ram_cas)
+       out DDRC,temp2
+
+       mov  temp2,temp
+       andi temp,RAM_DQ_MASK & ~(1<<ram_w)
+       ori temp,(1<<ram_cas)
+       out PORTC,temp
+       DRAM_SETADDR xh, ~0,(1<<ram_ras), ~(1<<ram_a8),(1<<ram_oe)
+       cbi P_RAS,ram_ras
+       DRAM_SETADDR xl, ~(1<<ram_ras),0, ~((1<<ram_a8)),(1<<ram_oe)
+       cbi PORTC,ram_cas
+       sbi PORTC,ram_cas
+
+       sbi PORTD,ram_a8
+       swap temp2
+
+       andi temp2,RAM_DQ_MASK & ~(1<<ram_w)
+       ori temp2,(1<<ram_cas)
+       out PORTC,temp2
+       cbr temp2,(1<<ram_cas)
+       out PORTC,temp2
+       ldi temp,~RAM_DQ_MASK | (1<<ram_w) | (1<<ram_cas)
+       out PORTC,_255
+       out DDRC,temp
+       out P_RAS,_255
+;      sei
+       ret
+
+; vim:set ts=8 noet nowrap
+
diff --git a/dram-4bit.inc b/dram-4bit.inc
new file mode 100644 (file)
index 0000000..2e08ae8
--- /dev/null
@@ -0,0 +1,140 @@
+; DRAM interface for *one* 256K x 4 bit DRAM chip.
+; This is part of the Z80-CP/M emulator written by Sprite_tm.
+
+;    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 <http://www.gnu.org/licenses/>.
+;
+;    $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<<mmc_cs)
+       out P_AH,temp
+.endm
+
+
+;----------------------------------------------
+; Read byte from DRAM
+;      temp = destreg, xh = memaddrh, xl = memaddrl
+
+.macro mem_read
+       rcall   dram_read
+.endm
+
+;----------------------------------------------
+; Read byte from DRAM
+;      mem_read  memaddr
+;      temp = destreg
+
+.macro mem_read_s
+       movw    xl,@0l
+       rcall   dram_read
+.endm
+
+;----------------------------------------------
+; Read byte from DRAM
+;      mem_read  destreg
+;      xh = memaddrh, xl = memaddrl
+
+.macro mem_read_d
+       rcall   dram_read
+       mov     @0,temp
+.endm
+
+;----------------------------------------------
+; Read byte from DRAM
+;      mem_read  destreg, memaddr
+
+.macro mem_read_ds
+       movw    xl,@1l
+       rcall   dram_read
+       mov     @0,temp
+.endm
+
+;----------------------------------------------
+; Write byte to DRAM
+;      xh = memaddrh, xl = memaddrl, temp = srcreg
+
+.macro mem_write
+       rcall   dram_write
+.endm
+
+;----------------------------------------------
+; Write byte to DRAM
+;      temp = srcreg
+;      mem_write  memaddr
+
+.macro mem_write_d
+       movw    x,@0l
+       rcall   dram_write
+.endm
+
+;----------------------------------------------
+; Write byte to DRAM
+;      xh = memaddrh, xl = memaddrl
+;      mem_write  sourcereg
+
+.macro mem_write_s
+       mov     temp,@0
+       rcall   dram_write
+.endm
+
+;----------------------------------------------
+; Write byte to DRAM
+;      mem_write  memaddr, sourcereg
+
+.macro mem_write_ds
+       movw    x,@0l
+       mov     temp,@1
+       rcall   dram_write
+.endm
+
+
diff --git a/dram-8bit.asm b/dram-8bit.asm
new file mode 100644 (file)
index 0000000..b335894
--- /dev/null
@@ -0,0 +1,64 @@
+; 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 <http://www.gnu.org/licenses/>.
+;
+;    $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 (file)
index 0000000..a2b2e0c
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+;
+;    $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 (file)
index 0000000..e85721d
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+;
+;    $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<<TXEN0) | (1<<RXEN0) | (1<<RXCIE0)
+       outm8 UCSR0B,temp
+.ifdef URSEL
+       ldi temp, (1<<URSEL) | (1<<UCSZ01) | (1<<UCSZ00)
+.else
+       ldi temp, (1<<UCSZ01) | (1<<UCSZ00)
+.endif
+       outm8 UCSR0C,temp
+       ldi temp, HIGH(UBRR_VAL)
+       outm8 UBRR0H,temp
+       ldi temp, LOW(UBRR_VAL)
+       outm8 UBRR0L,temp
+       ret
+
+; Save received character in a circular buffer. Do nothing if buffer overflows.
+
+rxint:
+       .org URXCaddr   
+       rjmp rxint              ; USART receive int.
+
+       .org 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: 
+       .org UDREaddr
+       rjmp txint              ; USART transmit int.
+
+       .org 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<<TXEN0) | (1<<RXEN0) | (1<<RXCIE0)
+       outm8 UCSR0B,temp
+txi_x:
+       pop     temp
+       out     sreg,temp
+       pop     temp
+       reti
+
+
+;Sends a char from temp to the uart. 
+uartputc:
+       push    zh
+       push    zl
+       push    temp
+putc_l:
+       lds     temp,txcount            ;do {
+       cpi     temp,TXBUFSIZE          ;
+       brsh    putc_l                  ;} while (txcount >= 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<<UDRIE0) | (1<<TXEN0) | (1<<RXEN0) | (1<<RXCIE0)
+       outm8   UCSR0B,zl
+       sei
+       pop     zl
+       pop     zh
+       ret
+
+; vim:set ts=8 noet nowrap
+
diff --git a/init.asm b/init.asm
new file mode 100644 (file)
index 0000000..7b9d9fb
--- /dev/null
+++ b/init.asm
@@ -0,0 +1,252 @@
+;    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 <http://www.gnu.org/licenses/>.
+;
+;    $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<<WDCE) | (1<<WDE)
+       outm8   WDTCSR,temp
+       ldi temp,(1<<WDCE)
+       outm8   WDTCSR,temp
+       
+; - Setup Ports
+
+       ldi     temp,(1<<PUD)           ;disable pullups
+       outm8   P_PUD,temp
+       out     PORTD,_255              ;all pins high
+       out     PORTB,_255
+       out     PORTC,_255
+       out     DDRD,_255               ; all outputs
+       out     DDRB,_255
+       out     DDRC,_255
+       cbi     P_RXD-1,RXD             ; RXD pin is input
+
+       outm8   TIMSK1,_0
+       outm8   TIMSK2,_0
+       outm8   TCCR2A,_0
+       outm8   TCCR2B,_0
+
+; - Clear RAM
+
+       ldiw    z,SRAM_START
+       ldi     temp2,high(ramtop)
+clr_l:
+       st      z+,_0
+       cpi     zl,low(ramtop)
+       cpc     zh,temp2
+       brne    clr_l
+
+
+; Init clock/timer system
+
+; Init timer 1 as 1 ms system clock tick.
+
+       ldi     temp, low (F_CPU/1000)
+       ldi     temp2,high(F_CPU/1000)
+       outm8   OCR1BH,temp2
+       outm8   OCR1BL,temp
+       ldi     temp,(1<<ICNC1)|(1<<CS10)       ;Noise cancel, fall. edge, Normal Mode, clk/1
+       outm8   TCCR1B,temp
+       inm8    temp,TIMSK1
+       ori     temp,(1<<OCIE1B)                ;Enable 1ms int.
+       outm8   TIMSK1,temp
+
+; - Init serial port
+
+       rcall   uart_init
+       
+;Init timer2. Refresh-call should happen every (8ms/512)=312 cycles.
+
+       ldi     temp,REFR_CNT*2                 ; 2 cycles per int
+       outm8   OCR2A,temp
+       inm8    temp,TCCR2A
+       ori     temp,(1<<WGM21)                 ;CTC mode
+       outm8   TCCR2A,temp
+       inm8    temp,TCCR2B
+       ori     temp,REFR_CS                    ;clk/REFR_PRE
+       outm8   TCCR2B,temp
+       inm8    temp,TIMSK2
+       ori     temp, (1<<OCIE2A)
+       outm8   TIMSK2,temp
+
+       sei
+
+
+.if BOOTWAIT
+       ldi temp,10
+       rcall delay_ms
+
+.endif
+
+       rcall   printstr
+       .db     13,13,"CPM on an AVR, v"
+       db_version VMAJOR, VMINOR
+               
+.if MEMTEST
+       printnewline
+       printstring "Testing RAM: fill..."
+
+;Fill RAM
+       ldiw    x,0
+ramtestw:
+       mov temp,xh
+       eor temp,xl
+       mem_write
+       adiw xl,1
+       brcc ramtestw
+       printstring "wait..."
+
+       ldi     temp2,8
+ramtestwl:
+       ldi     temp,255
+       rcall   delay_ms
+       dec     temp2
+       brne    ramtestwl
+
+       printstring "reread..."
+
+;re-read RAM
+       ldiw    x,0
+       clr     temp3
+ramtestr:
+       mem_read
+       mov     temp2,xh
+       eor     temp2,xl
+       cp      temp,temp2
+       breq    ramtestrok
+       push    temp
+       cpi     temp3,0         ;if first error
+       brne    ramtest2
+       inc     temp3
+       ldi     temp,10         ;newline
+       rcall   uartPutc
+ramtest2:
+       ldi     temp,13         ;return
+       rcall   uartPutc
+       pop     temp
+       rcall   printhex
+       ldi     temp,'<'
+       rcall   uartPutc
+       mov     temp,xh
+       eor     temp,xl
+       rcall   printhex
+       ldi     temp,'@'
+       rcall   uartPutc
+       movw    temp,x
+       rcall   printhexw
+ramtestrok:
+       adiw    xl,1
+       brcc    ramtestr
+
+.endif
+
+.if MEMFILL
+       ldiw    x,0
+ramfillw:
+       ldi temp,MEMFILL_VAL
+       mem_write
+       adiw xl,1
+       brcc ramfillw
+.endif
+
+
+;----------------------------------------------------------------------------
+
+boot_again:
+       printnewline
+       printstring "Initing mmc...",0
+       rcall   dsk_partinit
+
+       cbr     temp,0x80
+       brne    boot_ipl2
+       printstring "No bootable CP/M disk found! Please change MMC/SD-Card."
+       ldi     temp2,18
+boot_iplwl:
+       ldi     temp,255
+       rcall   delay_ms
+       dec     temp2
+       brne    boot_iplwl
+       rjmp    boot_again
+       
+
+boot_ipl2:
+       rcall   prnt_parttbl
+       printnewline
+       printstring "Partinit done."
+
+; Read first sector of first CP/M partition
+
+       lds     xl,hostparttbl
+       lds     xh,hostparttbl+1
+       lds     yl,hostparttbl+2
+       lds     yh,hostparttbl+3
+       rcall   mmcReadSect
+
+       rcall   dsk_cboot               ;init (de)blocking buffer
+
+;First sector of disk or first CP/M partition is in hostbuf.
+
+;Save to Z80 RAM (only 128 bytes because that's retro)
+       ldiw z,hostbuf
+       ldiw x,IPLADDR
+iplwriteloop:
+       ld temp,z+
+       mem_write
+       adiw xl,1
+       cpi zl,low(hostbuf+128)
+       brne iplwriteloop
+       cpi zh,high(hostbuf+128)
+       brne iplwriteloop
+       rjmp z80_init
+
+
diff --git a/macros.inc b/macros.inc
new file mode 100644 (file)
index 0000000..e6559c5
--- /dev/null
@@ -0,0 +1,149 @@
+;    Commonly used macros
+;
+;    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 <http://www.gnu.org/licenses/>.
+;
+;    $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 (file)
index 0000000..edb2bbf
--- /dev/null
@@ -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<<WDCE)
+       outm8 WDTCSR,temp
+       ldi temp,(1<<WDCE) | (1<<WDE) | (110<<WDP0)
+       outm8 WDTCSR,temp
+resetwait:
+       rjmp resetwait
+
+
diff --git a/mmc.asm b/mmc.asm
new file mode 100644 (file)
index 0000000..1a04542
--- /dev/null
+++ b/mmc.asm
@@ -0,0 +1,670 @@
+;    MMC/SD-Card routines
+;
+;    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 <http://www.gnu.org/licenses/>.
+;
+;    $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<<SPE)|(1<<MSTR)|(1<<SPR1)|(1<<SPR0)     ;clk/128
+       out     SPCR,temp
+       out     SPSR,_0
+.endm
+
+;------------------------------------------------
+; 
+.macro spi_clkfast
+.if MMC_DEBUG > 1
+       printstring     "SPI_CLK_FAST "
+.endif
+       ldi     temp,(1<<SPE)|(1<<MSTR)                 ;clk/4
+       out     SPCR,temp
+#if MMC_SPI2X
+       ldi     temp,(1<<SPI2X)
+       out     SPSR,temp
+#else
+       out     SPSR,_0
+#endif
+.endm
+
+;------------------------------------------------
+; 
+.macro spi_disable
+.if MMC_DEBUG > 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<n> is the command sequence of CMD55-CMD<n>      
+       
+       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 (file)
index 0000000..2af7532
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+;
+;    $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<<ram_ras), ~0,(1<<ram_a8)|(1<<ram_oe)
+       cbi     P_RAS,ram_ras
+
+.if DISK_DEBUG > 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<<ram_ras),0, ~((1<<ram_oe)), (1<<ram_a8)
+       cbi     P_CAS,ram_cas
+       cbi     P_A8,ram_a8
+       inc     xl
+       dram_wait DRAM_WAITSTATES       ;
+       in      temp,P_DQ-2             ; PIN
+       sbi     P_CAS,ram_cas
+
+       cbi     P_CAS,ram_cas
+       andi    temp,0x0f
+       swap    temp
+       dram_wait DRAM_WAITSTATES       ;
+       in      temp2,P_DQ-2            ; PIN
+       andi    temp2,0x0f
+       or      temp,temp2
+
+       sbi     P_OE,ram_oe
+       sbi     P_CAS,ram_cas
+       dec     temp3
+       st      z+,temp
+       brne    rdsk_rdl
+
+       sbi     P_RAS,ram_ras
+       ldiw    z,rdskbuf
+       lds     xl,dmaadr
+       lds     xh,dmaadr+1
+       ldi     temp3,128       
+rdsk_rdstl:
+       ld      temp,z+
+       mem_write
+       adiw    x,1
+       dec     temp3
+       brne    rdsk_rdstl
+       ret
+       
+
+rdsk_wr:
+.if DISK_DEBUG > 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<<ram_w) | (1<<ram_cas)
+       out     DDRC,temp2
+       rcall   rdsk_adr
+rdsk_wrl:
+       ld      temp,z+
+       mov     temp2,temp
+       andi    temp,RAM_DQ_MASK & ~(1<<ram_w)
+       ori     temp,(1<<ram_cas)
+       out     PORTC,temp
+       DRAM_SETADDR xl, ~(1<<ram_ras),0, ~((1<<ram_a8)),(1<<ram_oe)
+       cbi     PORTC,ram_cas
+       sbi     PORTD,ram_a8
+       sbi     PORTC,ram_cas
+       swap    temp2
+       andi    temp2,RAM_DQ_MASK & ~(1<<ram_w)
+       ori     temp2,(1<<ram_cas)
+       out     PORTC,temp2
+       cbi     PORTC,ram_cas
+       inc     xl
+       sbi     PORTC,ram_cas
+       dec     temp3
+       brne    rdsk_wrl
+
+       sbi     P_RAS,ram_ras
+       ldi     temp,~RAM_DQ_MASK | (1<<ram_w) | (1<<ram_cas)
+       out     DDRC,temp
+       out     PORTC,temp
+       ret
+
+
+#endif /* RAMDISKCNT */
+
+;---------------------------------------------------------------------
+
+; Partition table offsets:
+#define PART_TYPE   4
+#define PART_START  8
+#define PART_SIZE  12
+
+       .dseg
+tmp_tbl:
+       .byte   8*MAXDISKS
+
+       .cseg
+dsk_partinit:
+       sts     ndisks,_0
+       rcall   mmcInit
+       andi    temp,MMCST_NOINIT & MMCST_NODISK
+       brne    dsk_pierr
+       
+;Load first sector from MMC (boot sector)
+       ldiw    y,0                     ; Sector 0
+       movw    x,y
+       rcall   mmcReadSect
+       tst     temp
+       breq    dsk_pi1
+
+dsk_pierr:
+       clr     temp
+       ret
+
+dsk_pi1:
+       ldiw    y,tmp_tbl
+       ldi     temp2,8*MAXDISKS
+dsk_picl:
+       st      y+,_0
+       dec     temp2
+       brne    dsk_picl
+       sbiw    y,8*MAXDISKS
+
+;Test, if it has a valid MBR
+
+       ldiw    z,hostbuf+510-1 ;Point to last byte of partition table
+
+       ldi     temp3,0                 ;temp3 holds number of found disks (paritions)
+       ldd     temp,z+1                ;MBR signature (0xAA55)  at and of sector?
+       ldd     temp2,z+2
+       ldi     temp4,0xAA
+       cpi     temp,0x55               
+       cpc     temp2,temp4
+       breq    dsk_part
+
+;No MBR, no partition table ...
+       inc     temp3                   ;pretend we have one.
+       ldi     temp,high((1<<16) * 128/512)
+       std     y+0,_0                  ;start at beginning of card
+       std     y+1,_0
+       std     y+2,_0
+       std     y+3,_0
+       std     y+4,_0                  ;max CP/M 2.2 disk size
+       std     y+5,temp                ;
+       std     y+6,_0
+       std     y+7,_0
+       rjmp    dsk_pend
+               
+;Search Partition Table for CP/M partitions
+dsk_part:
+       sbiw    z,63                    ;Now at first byte of partition table
+       ldi     temp4,high(hostbuf+510)
+dsk_ploop:
+       ldd     temp,z+PART_TYPE
+       cpi     temp,PARTID
+       brne    dsk_nextp
+       
+; Found a CP/M partition
+       
+       ldd     temp,z+PART_START
+       st      y+,temp
+       ldd     temp,z+PART_START+1
+       st      y+,temp
+       ldd     temp,z+PART_START+2
+       st      y+,temp
+       ldd     temp,z+PART_START+3
+       st      y+,temp
+       
+       ldd     temp,z+PART_SIZE
+       st      y+,temp
+       ldd     temp,z+PART_SIZE+1
+       st      y+,temp
+       ldd     temp,z+PART_SIZE+2
+       st      y+,temp
+       ldd     temp,z+PART_SIZE+3
+       st      y+,temp
+
+       inc     temp3
+       cpi     temp3,MAXDISKS
+       breq    dsk_pend        
+dsk_nextp:
+       adiw    zl,16
+       cpi     zl,low(hostbuf+510)
+       cpc     zh,temp4
+       brlo    dsk_ploop
+
+dsk_pend:
+
+;Store new partitions and check if the SD card has been changed.
+
+       ldiw    y,tmp_tbl
+       ldiw    z,hostparttbl
+       ldi     temp4,8*MAXDISKS
+       clt
+dsk_pcpl:
+       ld      temp,y+
+       ld      temp2,z
+       st      z+,temp
+       cpse    temp,temp2
+        set
+       dec     temp4
+       brne    dsk_pcpl
+
+       mov     temp,temp3
+       sts     ndisks,temp
+       brtc    dsk_pcpe
+
+       tst     temp
+       breq    dsk_pcpe
+
+; SD card changed.
+       sbr     temp,0x80
+
+dsk_pcpe:
+       ret
+
+;---------------------------------------------------------------------
+; Print partition table info
+
+prnt_parttbl:
+       ldiw    z,hostparttbl
+pprl:
+       ldd     xl,z+4                  ;Get partition size
+       ldd     xh,z+5
+       ldd     yl,z+6
+       ldd     yh,z+7
+       cp      xl,_0                   ;If zero ...
+       cpc     xh,_0
+       cpc     yl,_0
+       cpc     yh,_0
+       breq    pppre           ;... No more partitions.
+
+       ldd     temp,z+0                ;Get partition start
+       ldd     temp2,z+1
+       ldd     temp3,z+2
+       ldd     temp4,z+3
+       printnewline
+       cp      temp,_0                 ;If zero ...
+       cpc     temp2,_0
+       cpc     temp3,_0
+       cpc     temp4,_0
+       breq    prnop           ;... no partition table at 0
+
+       rcall   prstr_table
+       rjmp    pprsz
+prnop:
+       rcall   prstr_image
+pprsz:
+       rcall   print_ultoa
+       printstring ", size: "
+       movw    temp,x
+       movw    temp3,y
+
+       lsr     temp4
+       ror     temp3
+       ror     temp2
+       ror     temp
+       rcall   print_ultoa
+       printstring "KB."
+       
+       adiw    z,8
+       ldi     temp,high(hostparttbltop)
+       cpi     zl,  low (hostparttbltop)
+       cpc     zh,temp
+       brlo    pprl
+pppre:
+       ret
+       
+prstr_table:
+       printstring "CP/M partition at: "
+       ret
+prstr_image:
+       printstring "Assuming CP/M image at: "
+       ret
+       
+; ****************************************************************************
+
+; ------------- system timer 1ms ---------------
+
+       .dseg
+
+delay_timer1:
+       .byte   1
+delay_timer2:
+       .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:
+       .org OC1Baddr           ; Timer/Counter1 Compare Match B
+       rjmp sysclockint        ; 1ms system timer
+
+       .org sysclockint
+       push    zl
+       in      zl,SREG
+       push    zl
+       push    zh
+       inm8    zl,OCR1BL
+       inm8    zh,OCR1BH
+       addiw   z,F_CPU/1000
+       outm8   OCR1BH,zh
+       outm8   OCR1BL,zl
+       
+#if DRAM_8BIT  /* Implies software uart */
+       lds     zl,srx_char_to
+       subi    zl,1
+       brcs    syscl0
+       sts     srx_char_to,zl
+       brne    syscl0
+       rcall   srx_to
+syscl0:
+#endif
+       lds     zl,delay_timer1
+       subi    zl,1
+       brcs    syscl_t1n
+       sts     delay_timer1,zl
+syscl_t1n:     
+       lds     zl,delay_timer2
+       subi    zl,1
+       brcs    syscl_t2n
+       sts     delay_timer2,zl
+syscl_t2n:     
+       lds     zl,cnt_1ms
+       lds     zh,cnt_1ms+1
+       adiw    z,1
+       
+       sts     cnt_1ms,zl
+       sts     cnt_1ms+1,zh
+       cpi     zl,low(1000)
+       ldi     zl,high(1000)           ;doesn't change flags
+       cpc     zh,zl
+       brlo    syscl_end
+       
+       sts     cnt_1ms,_0
+       sts     cnt_1ms+1,_0
+
+       lds     zl,uptime+0
+       inc     zl
+       sts     uptime+0,zl
+       brne    syscl_end
+       lds     zl,uptime+1
+       inc     zl
+       sts     uptime+1,zl
+       brne    syscl_end
+       lds     zl,uptime+2
+       inc     zl
+       sts     uptime+2,zl
+       brne    syscl_end
+       lds     zl,uptime+3
+       inc     zl
+       sts     uptime+3,zl
+       
+syscl_end:
+       pop     zh
+       pop     zl
+       out     SREG,zl
+       pop     zl
+       reti
+
+; wait for temp ms
+
+delay_ms:
+       sts     delay_timer1,temp
+dly_loop:
+       lds     temp,delay_timer1
+       cpi     temp,0
+       brne    dly_loop
+       ret
+
+; 
+
+clockget:
+       ldi     temp,0xFF
+       subi    temp2,TIMER_MSECS
+       brcs    clkget_end              ;Port number in range?
+       ldiw    z,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
+       ldiw    z,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:
+       ldiw    z,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
+       ldiw    z,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
+       
+       addiw   y,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
+       
+       printnewline
+       printstring "Timer running. Elapsed: "
+       rcall   print_ultoa
+
+       printstring "."
+       pop     temp
+       pop     temp2
+       ldi     temp3,0
+       ldi     temp4,0
+       rcall   print_ultoa
+       printstring "s."
+
+       pop     yl
+       pop     yh
+       ret
+       
+uptime_print:
+
+       ldiw    z,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+
+       
+       printnewline
+       printstring "Uptime: "
+       
+       rcall   print_ultoa
+       printstring ","
+
+       ldi     temp3,0
+       ldi     temp4,0
+       pop     temp2
+       pop     temp
+       rcall print_ultoa
+       printstring "s."
+
+       ret
+
+
+       
+; --------------- Debugging stuff ---------------
+; Print a line with the Z80 main registers
+
+;.if INS_DEBUG
+
+zflags_to_ch:
+       .db     "SZ H PNC",0,0
+       
+printregs:
+       printnewline
+
+       push    zl
+       push    zh
+       ldiw    z,zflags_to_ch*2
+       mov     temp2,z_flags
+pr_zfl_next:
+       lpm     temp,z+
+       tst     temp
+       breq    pr_zfl_end
+       cpi     temp,' '                        ; Test if no flag
+       breq    pr_zfl_noflag
+       sbrs    temp2,7                 ; 
+        ldi    temp,' '                        ; Flag not set
+       rcall   uartputc
+pr_zfl_noflag:
+       rol     temp2
+       rjmp    pr_zfl_next
+pr_zfl_end:
+       pop     zh
+       pop     zl      
+
+       printstring "  A ="
+       mov     temp,z_a
+       rcall   printhex        
+       printstring " BC ="
+       lds     temp2,z_b
+       lds     temp, z_c
+       rcall   printhexw
+       printstring " DE ="
+       lds     temp2,z_d
+       lds     temp, z_e
+       rcall   printhexw
+       printstring " HL ="
+       lds     temp2,z_h
+       lds     temp, z_l
+       rcall   printhexw
+       printstring " SP ="
+       movw    temp, z_spl
+       rcall   printhexw
+       printstring " PC ="
+       movw    temp, z_pcl
+       rcall   printhexw
+       printstring "       "
+       movw    xl,z_pcl
+       mem_read
+       rcall   printhex
+       printstring " "
+       adiw    x,1
+       mem_read
+       rcall   printhex
+       printstring " "
+       adiw    x,1
+       mem_read
+       rcall   printhex
+       printstring " "
+       ret
+;.endif
+
+
diff --git a/sw-uart.asm b/sw-uart.asm
new file mode 100644 (file)
index 0000000..36d814c
--- /dev/null
@@ -0,0 +1,533 @@
+; 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 <http://www.gnu.org/licenses/>.
+;
+;    $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<<COM1A1)|(1<<COM1A0)    ;OC1A high on compare match (UART TX)
+       outm8   TCCR1A,temp
+
+       ldi     temp,(1<<ICF1)                  ;clear pending int
+       out     TIFR1,temp
+       inm8    temp,TIMSK1
+       ori     temp,(1<<ICIE1)                 ;Enable input capture int.  (UART RX)
+       outm8   TIMSK1,temp
+       ret
+       
+;------------------------------------------------------------------
+
+       .cseg
+srxint:
+       .org    ICP1addr                ; Timer/Counter1 Input Capture
+       rjmp srxint                     ; Soft UART: RX
+
+       .org    srxint
+       
+       push    temp
+       in      temp,sreg
+       push    temp
+       push    zh
+       push    zl
+       inm8    zl,ICR1L
+       inm8    zh,ICR1H
+       push    temp2
+       ldi     temp2,(1<<ICES1)
+       inm8    temp,TCCR1B
+       eor     temp,temp2                      ;toggle edge
+       outm8   TCCR1B,temp
+       ldi     temp,(1<<ICF1)                  ;clear pending int
+       out     TIFR1,temp
+       
+#if 0
+       lds     temp,srx_state
+       subi    temp,-'0'
+       rcall   uartputc
+       lds     temp,srx_dr
+       rcall   printhex
+#endif 
+       lds     temp,srx_state
+       cpi     temp,0
+       brne    srxi_S1         
+
+; State 0: Wait for start bit
+
+;      sts     srx_lastedge,zl                 ;save beginning of start bit
+;      sts     srx_lastedge+1,zh
+       movw    srx_lastedgel,zl
+       ldi     temp,1
+       sts     srx_state,temp
+       ldi     temp,2
+       sts     srx_char_to,temp
+       sbis    P_RXD-2,RXD                     ;RXD still low?
+       rjmp    srxi_end2
+       ldi     zl,(1<<ICNC1)|(1<<CS10)         ;next edge is falling edge
+       outm8   TCCR1B,zl
+       ldi     zh,(1<<ICF1)                    ;clear pending int
+       out     TIFR1,zh
+       sts     srx_state,_0
+       sts     srx_char_to,_0
+       rjmp    srxi_end2
+
+srxi_S1:
+       cpi     temp,1
+       brne    srxi_S2
+
+; State 1: Check start bit (and collect 0-bits)
+
+;      lds     temp,srx_lastedge
+;      lds     temp2,srx_lastedge+1
+;      sts     srx_lastedge,zl
+;      sts     srx_lastedge+1,zh
+
+       movw    temp,srx_lastedgel
+       movw    srx_lastedgel,zl
+
+       sub     zl,temp
+       sbc     zh,temp2
+       subi    zl,low ((SSER_BIT_TC+1)/2)
+       sbci    zh,high((SSER_BIT_TC+1)/2)
+       brcs    srxi_sberr
+
+;      mov     temp,zh 
+;      rcall   printhex
+;      mov     temp,zl
+;      rcall   printhex
+
+       ldi     temp,0x80
+srxi_1l:
+       subi    zl,low(SSER_BIT_TC)
+       sbci    zh,high(SSER_BIT_TC)
+       brcs    srxi_1be
+       lsr     temp
+       brcc    srxi_1l
+       rjmp    srxi_complete
+srxi_1be:
+       sts     srx_dr,temp
+       ldi     temp,2
+       sts     srx_state,temp
+       rjmp    srxi_end2
+
+srxi_sberr:
+       ldi     temp,(1<<ICNC1)|(1<<CS10)       ;next edge is falling edge
+       outm8   TCCR1B,temp
+       ldi     temp,(1<<ICF1)          ;clear pending int
+       out     TIFR1,temp
+       sts     srx_state,_0            ;next state
+#if 1
+       ldi     temp,'?'
+       rcall   uartputc
+       subi    zl,low (-(SSER_BIT_TC+1)/2)
+       sbci    zh,high(-(SSER_BIT_TC+1)/2)
+       mov     temp,zh
+       rcall   printhex
+       mov     temp,zl
+       rcall   printhex
+#endif
+       rjmp    srxi_end2
+
+srxi_S2:
+       cpi     temp,2
+       brne    srxi_S3
+
+; State 2: collect 1-bits
+
+;      lds     temp,srx_lastedge
+;      lds     temp2,srx_lastedge+1
+;      sts     srx_lastedge,zl
+;      sts     srx_lastedge+1,zh
+
+       movw    temp,srx_lastedgel
+       movw    srx_lastedgel,zl
+
+       sub     zl,temp
+       sbc     zh,temp2
+       subi    zl,low ((SSER_BIT_TC+1)/2)
+       sbci    zh,high((SSER_BIT_TC+1)/2)
+
+       lds     temp,srx_dr
+srxi_2l:
+       sec                             ;one more 1 bit
+       ror     temp
+       brcs    srxi_complete1          ;8 bits recieved
+       subi    zl,low(SSER_BIT_TC)
+       sbci    zh,high(SSER_BIT_TC)
+       brcc    srxi_2l
+       
+       sts     srx_dr,temp
+       ldi     temp,3
+       sts     srx_state,temp
+       rjmp    srxi_end2
+       
+srxi_complete1:
+       ldi     temp2,1                 ;We are in start bit now.
+       sts     srx_state,temp2
+       ldi     temp2,2
+       sts     srx_char_to,temp2
+       rjmp    srxi_complete
+       
+srxi_S3:
+       cpi     temp,3
+       brne    srxi_S4
+
+; State 3: collect 0-bits
+
+;      lds     temp,srx_lastedge
+;      lds     temp2,srx_lastedge+1
+;      sts     srx_lastedge,zl
+;      sts     srx_lastedge+1,zh
+
+       movw    temp,srx_lastedgel
+       movw    srx_lastedgel,zl
+
+       sub     zl,temp
+       sbc     zh,temp2
+       subi    zl,low ((SSER_BIT_TC+1)/2)
+       sbci    zh,high((SSER_BIT_TC+1)/2)
+
+       lds     temp,srx_dr
+srxi_3l:
+                                       ;one more 0 bit
+       lsr     temp
+       brcs    srxi_complete0          ;8 bits recieved
+       subi    zl,low(SSER_BIT_TC)
+       sbci    zh,high(SSER_BIT_TC)
+       brcc    srxi_3l
+       
+       sts     srx_dr,temp
+       ldi     temp,2
+       sts     srx_state,temp
+       rjmp    srxi_end2
+
+srxi_S4:
+       ldi     zl,(1<<ICNC1)|(1<<CS10) ;next edge is falling edge
+       outm8   TCCR1B,zl
+       ldi     zl,(1<<ICF1)            ;clear pending int
+       sts     srx_state,_0            ;next state
+       rjmp    srxi_end2
+
+srxi_complete0:        
+       sts     srx_char_to,_0          ;clear timeout
+       sts     srx_state,_0            ;next state
+srxi_complete:
+#if 0
+       ldi     zl,(1<<ICNC1)|(1<<CS10) ;next edge is falling edge
+       outm8   TCCR1B,zl
+       ldi     zl,(1<<ICF1)            ;clear pending int
+       out     TIFR1,zl
+#endif
+
+; Save received character in a circular buffer. Do nothing if buffer overflows.
+
+       lds     zh,rxcount              ;if rxcount < RXBUFSIZE
+       cpi     zh,RXBUFSIZE            ;   (room for at least 1 char?)
+       brsh    srxi_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
+srxi_ov:                                       ;endif
+
+srxi_end2:
+       pop     temp2
+srxi_end: 
+       pop     zl
+       pop     zh
+       pop     temp
+       out     sreg,temp
+       pop     temp
+       reti
+
+
+;----------------------------------------------------------------------
+
+       .cseg
+stxint:
+       .org    OC1Aaddr                ; Timer/Counter1 Compare Match A
+       rjmp stxint                     ; Soft UART: TX
+
+       .org stxint
+       
+       push    temp
+       in      temp,sreg
+       push    temp
+       push    zh
+
+       inm8    temp,OCR1AL
+       inm8    zh,OCR1AH
+       subi    temp,low(-SSER_BIT_TC)
+       sbci    zh,high(-SSER_BIT_TC)
+       outm8   OCR1AH,zh
+       outm8   OCR1AL,temp
+       lds     temp,stx_bitcount
+       tst     temp
+       breq    stxi_nxtchar
+       
+       dec     temp
+       sts     stx_bitcount,temp
+       ldi     zh,9                            ;Start bit?
+       cp      temp,zh
+       ldi     zh,(1<<COM1A1)
+       breq    stxi_0
+       lds     temp,stx_dr
+       sbrs    temp,0
+       ldi     zh,(1<<COM1A1)|(1<<COM1A0)
+       lsr     temp
+       sts     stx_dr,temp
+stxi_0:
+       outm8   TCCR1A,zh
+       pop     zh
+       pop     temp
+       out     sreg,temp
+       pop     temp
+       reti
+
+; more characters?
+stxi_nxtchar:
+       lds     temp,txcount            ;if txcount != 0
+       tst     temp                    ;
+       breq    stxi_dis
+; get next char
+       push    zl
+       dec     temp                    ;
+       sts     txcount,temp            ;   --txcount
+       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
+       com     temp
+       sts     stx_dr,temp
+       ldi     temp,10
+       sts     stx_bitcount,temp
+       pop     zl
+       pop     zh
+       pop     temp
+       out     sreg,temp
+       pop     temp
+       reti
+
+; disable transmitter
+stxi_dis:
+       ldi     temp,(1<<COM1A1)|(1<<COM1A0)
+       outm8   TCCR1A,temp
+       inm8    temp,TIMSK1
+       andi    temp,~(1<<OCIE1A)
+       outm8   TIMSK1,temp
+       pop     zh
+       pop     temp
+       out     sreg,temp
+       pop     temp
+       reti
+;------------------------------------------------------------------
+
+srx_to:
+#if 0
+       ldi     zl,(1<<ICNC1)|(1<<CS10) ;next edge is falling edge
+       outm8   TCCR1B,zl
+       ldi     zl,(1<<ICF1)            ;clear pending int
+       out     TIFR1,zl
+#endif
+       push    temp
+
+#if 0
+       ldi     temp,'|'
+       rcall   uartputc
+#endif
+       lds     temp,srx_dr
+       mov     zl,temp
+       com     zl
+       andi    zl,0x80
+srxto_l:
+       lsr     temp
+       or      temp,zl
+       brcc    srxto_l
+       
+; Save received character in a circular buffer. Do nothing if buffer overflows.
+
+       lds     zh,rxcount              ;if rxcount < RXBUFSIZE
+       cpi     zh,RXBUFSIZE            ;   (room for at least 1 char?)
+       brsh    srxto_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
+srxto_ov:                                      ;endif
+       sts     srx_state,_0            ;next state
+       
+       pop     temp
+       ret
+       
+       
+;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
+
+;Sends a char from temp to the soft uart. 
+
+uartputc:
+       push    zh
+       push    zl
+       in      zl,sreg
+       push    zl
+       push    temp
+sputc_l:
+       lds     temp,txcount            ;do {
+       cpi     temp,TXBUFSIZE          ;
+       brsh    sputc_l                 ;} while (txcount >= 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<<OCIE1A)
+       outm8   TIMSK1,zh
+sputc_e:
+       pop     zl
+       out     sreg,zl
+       pop     zl
+       pop     zh
+       ret
+
+
+; Wait, till tx buffer is empty.
+
+uart_wait_empty:
+       push    temp
+uwe_loop:
+       lds     temp,txcount
+       tst     temp
+       brne    uwe_loop
+       pop     temp
+       ret
+
+
+; vim:set ts=8 noet nowrap
+
similarity index 55%
rename from z80.asm
rename to z80int.asm
index 2ebec01a44dd8c4b9fe1f8d2ee615a7030ab00f8..870719ad7c86e4ae08233973264fd2023f37476b 100644 (file)
--- a/z80.asm
-;    Z80 emulator with CP/M support. The Z80-specific instructions themselves actually aren't
-;    implemented yet, making this more of an i8080 emulator.
-;    
+; Z80 Interpreter.
+; This is part of the Z80-CP/M emulator written by Sprite_tm.
+; The Z80-specific instructions themselves actually aren't
+; implemented yet, making this more of an i8080 emulator.
+
 ;    Copyright (C) 2010 Sprite_tm
+;    Copyright (C) 2010 Leo C.
+
+;    This file is part of avrcpm.
 ;
-;    This program is free software: you can redistribute it and/or modify
-;    it under the terms of the GNU General Public License as published by
+;    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.
 ;
-;    This program is distributed in the hope that it will be useful,
+;    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 this program.  If not, see <http://www.gnu.org/licenses/>.
+;    along with avrcpm.  If not, see <http://www.gnu.org/licenses/>.
 ;
 ;    $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<<ram_a8)|(1<<ram_a7)|(1<<ram_a6)|(1<<ram_a5)
-.equ PD_OUTPUT_MASK = (1<<mmc_cs) | (1<<ram_oe) | RAM_AH_MASK
-
-
-;Port B
-.equ ram_a4 =  0
-.equ ram_a3 =  1
-.equ ram_a2 =  2
-.equ ram_a1 =  3
-.equ mmc_mosi =        3
-.equ ram_a0 =  4
-.equ mmc_miso =        4
-.equ ram_ras = 5
-.equ mmc_sck = 5
-
-
-.equ P_RAS = PORTB
-.equ P_AL  = PORTB
-                       ; ram_a[4..0]
-.equ RAM_AL_MASK = (1<<ram_a4)|(1<<ram_a3)|(1<<ram_a2)|(1<<ram_a1)|(1<<ram_a0)
-.equ PB_OUTPUT_MASK = (1<<ram_ras) | RAM_AL_MASK
-
-;Port C
-.equ ram_d0 =  0
-.equ ram_d1 =  1
-.equ ram_d2 =  2
-.equ ram_d3 =  3
-.equ ram_w  =  4
-.equ ram_cas=  5
-
-.equ P_DQ  = PORTC
-.equ P_W   = PORTC
-.equ P_CAS = PORTC
-.equ RAM_DQ_MASK = (1<<ram_d3)|(1<<ram_d2)|(1<<ram_d1)|(1<<ram_d0)
-.equ PC_OUTPUT_MASK = (1<<ram_cas)|(1<<ram_w)
-
-
-;Flag bits in z_flags
-.equ ZFL_S     =       7
-.equ ZFL_Z     =       6
-.equ ZFL_H     =       4
-.equ ZFL_P     =       2
-.equ ZFL_N     =       1
-.equ ZFL_C     =       0
-
-;Register definitions
-
-.def   _tmp    = r0    ;  0
-.def   _0      = r1
-
-.def   z_c     = r4
-.def   z_b     = r5
-.def   z_e     = r6
-.def   z_d     = r7
-.def   z_l     = r8
-.def   z_h     = r9
-.def   z_a     = r10
-
-.def   insdecl = r12   ;
-.def   insdech = r13   ;
-.def   z_spl   = r14
-.def   z_sph   = r15   ;
-.def   temp    = r16   ;
-.def   temp2   = r17   ;
-.def   temp3   = r18
-.def   temp4   = r19
-.def   z_flags = r20   ;
-                       ;
-.def   opl     = r22   ;
-.def   oph     = r23   ;
-.def   z_pcl   = r24   ;
-.def   z_pch   = r25   ;
-; xl           ;r26
-; xh           ;r27
-; yl           ;r28
-; yh           ;r29
-; zl           ;r30    ;
-; zh           ;r31    ;
-
-
-
-#if defined __ATmega8__
-.equ   flags   = TWBR
-.equ   P_PUD   = SFIOR
-#else
-.equ   flags   = GPIOR0
-.equ   P_PUD   = MCUCR
-#endif
-
-; Flags:
-       .equ    hostact = 7             ;host active flag
-       .equ    hostwrt = 6             ;host written flag
-       .equ    rsflag  = 5             ;read sector flag
-       .equ    readop  = 4             ;1 if read operation
-       .equ    trace   = 0
-
-; This is the base z80 port address for clock access
-#define        TIMERPORT 0x40
-#define TIMER_CTL   TIMERPORT
-#define TIMER_MSECS TIMERPORT+1
-#define TIMER_SECS  TIMER_MSECS+2
-
-#define starttimercmd  1
-#define quitTimerCmd   2
-#define printTimerCmd  15
-#define uptimeCmd      16
-
-#if defined __ATmega8__
-.equ   RXTXDR0 = UDR
-.equ   UCSR0A  = UCSRA
-.equ    UDRE0  = UDRE
-.equ   UCSR0B  = UCSRB
-.equ    RXCIE0 = RXCIE
-.equ    UDRIE0 = UDRIE
-.equ    RXEN0  = RXEN
-.equ    TXEN0  = TXEN
-.equ   UCSR0C  = UCSRC
-.equ    UCSZ00 = UCSZ0
-.equ    UCSZ01 = UCSZ1
-.equ   UBRR0H  = UBRRH
-.equ   UBRR0L  = UBRRL
-.equ   OCR2A   = OCR2
-.equ   OC2Aaddr= OC2addr
-.equ   TCCR2A  = TCCR2
-.equ   TCCR2B  = TCCR2
-.equ   TIMSK1  = TIMSK
-.equ   TIMSK2  = TIMSK
-.equ   OCIE2A  = OCIE2
-.equ   TIFR1   = TIFR
-.equ   ICIE1   = TICIE1
-#else
-.equ   RXTXDR0 = UDR0
-#endif
-
-
-;----------------------------------------
-; 
-.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
-
-
-
-; -------------------- 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<<mmc_cs)
-       out P_AH,temp
-.endm
-
-;----------------------------------------
-; 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
-
-
-.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<<WDCE) | (1<<WDE)
-       outm8   WDTCSR,temp
-       ldi temp,(1<<WDCE)
-       outm8   WDTCSR,temp
-
-; - Clear RAM
-
-       ldi     zl,low(SRAM_START)
-       ldi     zh,high(SRAM_START)
-       ldi     temp2,high(ramtop)
-clr_l:
-       st      z+,_0
-       cpi     zl,low(ramtop)
-       cpc     zh,temp2
-       brne    clr_l
-
-; - Setup Ports
-       ldi     temp,(1<<PUD)           ;disable pullups
-       outm8   P_PUD,temp
-       ldi     temp,0xFF
-       out     PORTD,temp              ;all pins high
-       out     PORTB,temp
-       out     PORTC,temp
-       out     DDRD,temp               ; all outputs
-       out     DDRB,temp
-       out     DDRC,temp
-
-       outm8   TIMSK1,_0
-       outm8   TIMSK2,_0
-       outm8   TCCR2A,_0
-       outm8   TCCR2B,_0
-
-
-; - Init serial port
-
-       ldi temp, (1<<TXEN0) | (1<<RXEN0) | (1<<RXCIE0)
-       outm8 UCSR0B,temp
-.ifdef URSEL
-       ldi temp, (1<<URSEL) | (1<<UCSZ01) | (1<<UCSZ00)
-.else
-       ldi temp, (1<<UCSZ01) | (1<<UCSZ00)
-.endif
-       outm8 UCSR0C,temp
-       ldi temp, HIGH(UBRR_VAL)
-       outm8 UBRR0H,temp
-       ldi temp, LOW(UBRR_VAL)
-       outm8 UBRR0L,temp
-
-; Init clock/timer system
-
-; Init timer 1 as 1 ms system clock tick.
-
-       ldi     temp,high(F_CPU/1000)
-       outm8   OCR1AH,temp
-       ldi     temp,low(F_CPU/1000)
-       outm8   OCR1AL,temp
-       ldi     temp,(1<<WGM12) | (1<<CS10)     ;CTC, clk/1
-       outm8   TCCR1B,temp
-       inm8    temp,TIMSK1
-       ori     temp,(1<<OCIE1A)
-       outm8   TIMSK1,temp
-
-;Init timer2. Refresh-call should happen every (8ms/512)=312 cycles.
-
-       ldi     temp,REFR_CNT*2                 ; 2 cycles per int
-       outm8   OCR2A,temp
-       inm8    temp,TCCR2A
-       ori     temp,(1<<WGM21)                 ;CTC mode
-       outm8   TCCR2A,temp
-       inm8    temp,TCCR2B
-       ori     temp,REFR_CS                    ;clk/REFR_PRE
-       outm8   TCCR2B,temp
-       inm8    temp,TIMSK2
-       ori     temp, (1<<OCIE2A)
-       outm8   TIMSK2,temp
-
-       sei
-
-
-.if BOOTWAIT
-       ldi temp,10
-       rcall delay_ms
-
-.endif
-
-       rcall printstr
-       .db 13,"CPM on an AVR, v1.0",13,0
-
-
-.if MEMTEST
-       rcall printstr
-       .db 13,"Testing RAM: fill...",0
-
-;Fill RAM
-       ldi xl,0
-       ldi xh,0
-ramtestw:
-       mov temp,xh
-       eor temp,xl
-       rcall memwritebyte
-       adiw xl,1
-       brcc ramtestw
-       rcall printstr
-       .db "wait...",0
-
-       ldi     temp2,8
-ramtestwl:
-       ldi     temp,255
-       rcall   delay_ms
-       dec     temp2
-       brne    ramtestwl
-
-       rcall printstr
-       .db "reread...",13,0,0
-
-;re-read RAM
-       ldi xl,0
-       ldi xh,0
-ramtestr:
-       rcall memReadByte
-       mov temp2,xh
-       eor temp2,xl
-       cp temp,temp2
-       breq ramtestrok
-       rcall printhex
-       ldi temp,'<'
-       rcall uartPutc
-       mov temp,xh
-       eor temp,xl
-       rcall printhex
-       ldi temp,'@'
-       rcall uartPutc
-       movw temp,x
-       rcall printhexw
-       ldi temp,13
-       rcall uartPutc
-ramtestrok:
-       adiw xl,1
-       brcc ramtestr
-
-.endif
-
-.if MEMFILL_CB
-       ;Fill ram with cbs, which (for now) will trigger an invalid opcode error.
-       ldi xl,0
-       ldi xh,0
-ramfillw:
-       ldi temp,0xcb
-       rcall memwritebyte
-       adiw xl,1
-       brcc ramfillw
-.endif
-
-
-;----------------------------------------------------------------------------
-
-boot_again:
-       rcall printstr
-       .db 13,"Initing mmc...",0
-       rcall   dsk_partinit
-       rcall printstr
-       .db 13,"Partinit done.",0
-
-       lds     temp,ndisks
-       tst     temp
-       brne    boot_ipl2
-       rcall   printstr
-       .db     "No bootable CP/M disk found! Please change MMC/SD-Card",13,0
-       ldi     temp2,18
-boot_iplwl:
-       ldi     temp,255
-       rcall   delay_ms
-       dec     temp2
-       brne    boot_iplwl
-       rjmp    boot_again
-       
-
-boot_ipl2:
-
-; Read first sector of first CP/M partition
-
-       lds     xl,hostparttbl
-       lds     xh,hostparttbl+1
-       lds     yl,hostparttbl+2
-       lds     yh,hostparttbl+3
-       rcall   mmcReadSect
-
-       rcall   dsk_cboot               ;init (de)blocking buffer
-
-;First sector of disk or first CP/M partition is in hostbuf.
+       .dseg
 
-;Save to Z80 RAM (only 128 bytes because that's retro)
-       ldi zl,low(hostbuf)
-       ldi zh,high(hostbuf)
-       ldi xh,0x20
-       ldi xl,0x00
-iplwriteloop:
-       ld temp,z+
-       rcall memWriteByte
-       adiw xl,1
-       cpi zl,low(hostbuf+128)
-       brne iplwriteloop
-       cpi zh,high(hostbuf+128)
-       brne iplwriteloop
+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
-       ldi temp,0x00
-       mov z_pcl,temp
-       ldi temp,0x20
-       mov z_pch,temp
+z80_init:
+       ldi z_pcl,low (IPLADDR)
+       ldi z_pch,high(IPLADDR)
 
        cbi     flags,trace
-       rcall printstr
-       .db 13,"Ok, CPU is live!",13,0,0
+       printnewline
+       printstring "Ok, CPU is live!"
+       printnewline
 
 main:
+.if INS_DEBUG
        cbi     flags,trace
-       cpi z_pch,1
+       cpi z_pch,DBG_TRACE_BOTTOM
        brlo notraceon
-       cpi z_pch,$dc
+       cpi z_pch,DBG_TRACE_TOP
        brsh notraceon
        sbi     flags,trace
 notraceon:
+.endif
 
 
 .if PRINT_PC
-       cpi z_pch,1
+       cpi z_pch,DBG_TRACE_BOTTOM
        brlo noprintpc
-       cpi z_pch,0xdc
+       cpi z_pch,DBG_TRACE_TOP
        brsh noprintpc
 
-       rcall printstr
-       .db 13,"PC=",0
+       printnewline
+       printstring "PC="
        movw temp,z_pcl
        rcall printhexw
-       ldi temp,' '
-;      ldi temp,10
-;      rcall uartputc
+       printstring " "
 noprintpc:
 .endif
 
        ; *** Stage 1: Fetch next opcode
-       movw xl,z_pcl
-       rcall memReadByte
+       mem_read_s z_pc
 
 
 .if INS_DEBUG
        sbis    flags,trace
        rjmp    notrace1
-       rcall printstr
-       .db "PC=",0
+       printnewline
+       printstring "PC="
        push temp
        movw temp,z_pcl
        rcall printhexw
        pop temp
-       rcall printstr
-       .db ", opcode=",0
+       printstring ", opcode="
        rcall printhex
 notrace1:
 .endif
@@ -587,12 +101,9 @@ notrace1:
 .if INS_DEBUG
        sbis    flags,trace
        rjmp    notrace2
-       rcall printstr
-       .db ", decoded=",0,0
-       movw temp,insdecl
-       rcall printhexw
-       rcall printstr
-       .db ".",13,0,0
+       printstring ", decoded="
+       movw    temp,insdecl
+       rcall   printhexw
 notrace2:
 .endif
 
@@ -609,16 +120,21 @@ notrace2:
 .if INS_DEBUG
        sbis    flags,trace
        rjmp    notrace3
-       rcall printstr
-       .db "pre: oph:l=",0
-       mov tempw,opl
-       rcall printhexw
-       rcall printstr
-       .db " -- ",0,0
+       printstring "  pre: op="
+       movw    temp,opl
+       rcall   printhexw
 notrace3:
+       rjmp    nonofetch
 .endif
 
 nofetch:
+.if INS_DEBUG
+       sbis    flags,trace
+       rjmp    nonofetch
+       printstring "              "
+
+nonofetch:
+.endif
        ; *** Stage 4: Execute operation :) Use the op jumptable for this.
        mov temp,insdech
        andi temp,0xFC
@@ -634,14 +150,21 @@ nofetch:
 .if INS_DEBUG
        sbis    flags,trace
        rjmp    notrace4
-       rcall printstr
-       .db ",post:oph:l=",0,0
-       movw temp,opl
-       rcall printhexw
+       printstring "  post: op="
+       movw    temp,opl
+       rcall   printhexw
 notrace4:
+       rjmp    nonooper
 .endif
 
 nooper:
+.if INS_DEBUG
+       sbis    flags,trace
+       rjmp    nonooper
+       printstring "               "
+
+nonooper:
+.endif
        ; *** Stage 5: Store operand. Use the store jumptable for this.
        swap insdecl
        swap insdech
@@ -660,2101 +183,16 @@ nooper:
 .if INS_DEBUG
        sbis    flags,trace
        rjmp    notrace5
-       rcall printstr
-       .db ", stored.",0
+       printstring " stored "
 notrace5:
 .endif
 
 nostore:
-
-.if INS_DEBUG
-       sbis    flags,trace
-       rjmp    notrace6
-       rcall printstr
-       .db 13,0
-notrace6:
-.endif
-
        ;All done. Neeeext!
        rjmp main
 
-
-
-
-; ----------------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
-;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)
-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
-       tst temp
-       breq PC+2
-        ldi temp,0xff
-       ret
-
-conInp:
-       rjmp uartGetc
-
-dbgOut:
-       rcall printstr
-       .db "Debug: ",0
-       rcall printhex
-       rcall printstr
-       .db 13,0
-       ret
-
-conOut:
-       rjmp uartputc
-
-
-;Called with port in temp2. Should return value in temp.
-portRead:
-       cpi temp2,0
-       breq conStatus
-       cpi temp2,1
-       breq conInp
-
-       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,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     temp,seekdsk
-       cpi     temp,RAMDISKNR
-       brsh    dsk_dchrd                       ;maybe ramdisk
-
-       lds     temp2,ndisks    ;check if selected disk # is less then # of disks
-       tst     temp2
-       brne    dsk_dchpart1
-
-; Need to init
-
-       rcall   dsk_partinit
-       lds     temp2,ndisks
-       lds     temp,seekdsk
-       
-dsk_dchpart1:
-       cp      temp,temp2
-       brsh    dsk_dcher
-       
-dsk_dchend:
-       ldi     temp,0
-       ret
-
-dsk_dchrd:
-       cpi     temp,RAMDISKNR+RAMDISKCNT
-       brlo    dsk_dchend
-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:
-       rcall printstr
-       .db 13,"Disk read:  ",0
-       rjmp    dskdbg1
-dskdbgw:
-       rcall printstr
-       .db 13,"Disk write: ",0
-dskdbg1:
-       lds     temp,seekdsk
-       subi    temp,-('A')
-       rcall   uartputc
-       rcall   printstr
-       .db     ": track ",0,0
-       lds temp2,seektrk+1
-       lds temp,seektrk
-       rcall printhexw
-       rcall printstr
-       .db ", sector ",0
-       lds temp,seeksec
-       rcall printhex
-       rcall printstr
-       .db ", dma-addr ",0
-       lds temp2,dmaadr+1
-       lds temp,dmaadr
-       rcall printhexw
-       pop     temp
-       push    temp
-       sbrs    temp,WRITE_FUNC
-        rjmp   dskdbge
-       rcall printstr
-       .db " wrtype ",0,0
-       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
-
-       rcall   printstr
-       .db "DISK I/O: Invalid Function code: ",0
-       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
-       cpi     temp2,RAMDISKNR
-       brlt    PC+2
-        rjmp   rdskDoIt
-
-       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
-       cpi     temp2,RAMDISKNR
-       brlt    PC+2
-        rjmp   rdskDoIt
-       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
-       rcall   printstr
-       .db     ", flags: ",0
-       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                   ;
-       clr     _0
-
-       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      _tmp,flags              ;host active flag
-       sbi     flags,hostact           ;always becomes 1
-       sbrs    _tmp,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
-       ldi     zl,low(hostbuf)
-       ldi     zh,high(hostbuf)
-       ldi     temp,128
-       pop     temp2                   ;get buffer number (which part of hostbuf)
-       mul     temp2,temp
-       add     zl,r0                   ;offset in hostbuf
-       adc     zh,r1
-.if DISK_DEBUG > 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<<ram_ras), ~0,(1<<ram_a8)|(1<<ram_oe)
-       cbi     P_RAS,ram_ras
-
-.if DISK_DEBUG > 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<<ram_ras),0, ~((1<<ram_oe)), (1<<ram_a8)
-       cbi     P_CAS,ram_cas
-       cbi     P_A8,ram_a8
-       inc     xl
-       dram_wait DRAM_WAITSTATES       ;
-       in      temp,P_DQ-2             ; PIN
-       sbi     P_CAS,ram_cas
-
-       cbi     P_CAS,ram_cas
-       andi    temp,0x0f
-       swap    temp
-       dram_wait DRAM_WAITSTATES       ;
-       in      temp2,P_DQ-2    ; PIN
-       andi    temp2,0x0f
-       or      temp,temp2
-
-       sbi     P_OE,ram_oe
-       sbi     P_CAS,ram_cas
-       dec     temp3
-       st      z+,temp
-       brne    rdsk_rdl
-
-       sbi     P_RAS,ram_ras
-       ldi     zl,low (rdskbuf)
-       ldi     zh,high(rdskbuf)
-       lds     xl,dmaadr
-       lds     xh,dmaadr+1
-       ldi     temp3,128       
-rdsk_rdstl:
-       ld      temp,z+
-       rcall   dram_write
-       adiw    x,1
-       dec     temp3
-       brne    rdsk_rdstl
-       ret
-       
-
-rdsk_wr:
-.if DISK_DEBUG > 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<<ram_w) | (1<<ram_cas)
-       out     DDRC,temp2
-       rcall   rdsk_adr
-rdsk_wrl:
-       ld      temp,z+
-       mov     temp2,temp
-       andi    temp,RAM_DQ_MASK & ~(1<<ram_w)
-       ori     temp,(1<<ram_cas)
-       out     PORTC,temp
-       DRAM_SETADDR xl, ~(1<<ram_ras),0, ~((1<<ram_a8)),(1<<ram_oe)
-       cbi     PORTC,ram_cas
-       sbi     PORTD,ram_a8
-       sbi     PORTC,ram_cas
-       swap    temp2
-       andi    temp2,RAM_DQ_MASK & ~(1<<ram_w)
-       ori     temp2,(1<<ram_cas)
-       out     PORTC,temp2
-       cbi     PORTC,ram_cas
-       inc     xl
-       sbi     PORTC,ram_cas
-       dec     temp3
-       brne    rdsk_wrl
-
-       sbi     P_RAS,ram_ras
-       ldi     temp,~RAM_DQ_MASK | (1<<ram_w) | (1<<ram_cas)
-       out     DDRC,temp
-       out     PORTC,temp
-       ret
-
-;--------------------------------------------------------------------- 
-
-; Partition table offsets:
-#define PART_TYPE   4
-#define PART_START  8
-#define PART_SIZE  12
-
-       .dseg
-tmp_tbl:
-       .byte   8*MAXDISKS
-
-       .cseg
-dsk_partinit:
-
-       rcall mmcInit
-
-;Load first sector from MMC (boot sector)
-
-       ldi     yh,0                    ; Sector 0
-       ldi     yl,0
-       movw    x,y
-       rcall   mmcReadSect
-
-       ldi     yl,low(tmp_tbl)
-       ldi     yh,high(tmp_tbl)
-       ldi     temp2,8*MAXDISKS
-dsk_picl:
-       st      y+,_0
-       dec     temp2
-       brne    dsk_picl
-       sbiw    y,8*MAXDISKS
-#if 0
-       rcall   printstr
-       .db     ", ",0,0
-       movw    temp,y
-       rcall   printhexw
-#endif
-
-;Test, if it has a valid MBR
-
-       ldi     zl,low(hostbuf+510-1)   ;Point to last byte of partition table
-       ldi     zh,high(hostbuf+510-1)
-
-       ldi     temp3,0                 ;temp3 holds number of found disks (paritions)
-       ldd     temp,z+1                ;MBR signature (0xAA55)  at and of sector?
-       ldd     temp2,z+2
-       ldi     temp4,0xAA
-       cpi     temp,0x55               
-       cpc     temp2,temp4
-       breq    dsk_part
-
-;No MBR, no partition table ...
-       inc     temp3                   ;pretend we have one.
-       ldi     temp,high((1<<16) * 128/512)
-       std     y+0,_0                  ;start at beginning of card
-       std     y+1,_0
-       std     y+2,_0
-       std     y+3,_0
-       std     y+4,_0                  ;max CP/M 2.2 disk size
-       std     y+5,temp                ;
-       std     y+6,_0
-       std     y+7,_0
-       rjmp    dsk_pend
-               
-;Search Partition Table for CP/M partitions
-dsk_part:
-       sbiw    z,63                    ;Now at first byte of partition table
-       ldi     temp4,high(hostbuf+510)
-dsk_ploop:
-       ldd     temp,z+PART_TYPE
-       cpi     temp,PARTID
-       brne    dsk_nextp
-       
-; Found a CP/M partition
-       
-       ldd     temp,z+PART_START
-       st      y+,temp
-       ldd     temp,z+PART_START+1
-       st      y+,temp
-       ldd     temp,z+PART_START+2
-       st      y+,temp
-       ldd     temp,z+PART_START+3
-       st      y+,temp
-       
-       ldd     temp,z+PART_SIZE
-       st      y+,temp
-       ldd     temp,z+PART_SIZE+1
-       st      y+,temp
-       ldd     temp,z+PART_SIZE+2
-       st      y+,temp
-       ldd     temp,z+PART_SIZE+3
-       st      y+,temp
-
-
-       inc     temp3
-       cpi     temp3,MAXDISKS
-       breq    dsk_pend        
-dsk_nextp:
-       adiw    zl,16
-       cpi     zl,low(hostbuf+510)
-       cpc     zh,temp4
-       brlo    dsk_ploop
-
-dsk_pend:
-       sts     ndisks,temp3
-
-;Store new partitions and check if the SD card has been changed.
-
-       ldi     yl,low(tmp_tbl)
-       ldi     yh,high(tmp_tbl)
-       ldi     zl,low(hostparttbl)
-       ldi     zh,high(hostparttbl)
-       ldi     temp3,8*MAXDISKS
-       clt
-dsk_pcpl:
-       ld      temp,y+
-       ld      temp2,z
-       st      z+,temp
-       cp      temp,temp2
-       cpse    temp,temp2
-        set
-       dec     temp3
-       brne    dsk_pcpl
-       
-       brtc    dsk_pcpe
-
-       lds     temp,ndisks
-       tst     temp
-       breq    dsk_pcpe
-
-; SD card changed, print Info.
-
-       sbiw    z,8*MAXDISKS
-
-dsk_pprl:
-       ldd     temp,z+4
-       ldd     temp2,z+5
-       or      temp,temp2
-       ldd     temp2,z+6
-       or      temp,temp2
-       ldd     temp2,z+7
-       or      temp,temp2
-       
-       breq    dsk_pcpe
-
-       rcall   printstr
-       .db     13,"CP/M partition at: ",0,0
-       ldd     temp,z+0
-       ldd     temp2,z+1
-       ldd     temp3,z+2
-       ldd     temp4,z+3
-       rcall   print_ultoa
-       rcall   printstr
-       .db     ", size: ",0,0
-       ldd     temp,z+4
-       ldd     temp2,z+5
-       ldd     temp3,z+6
-       ldd     temp4,z+7
-       lsr     temp4
-       ror     temp3
-       ror     temp2
-       ror     temp
-       rcall   print_ultoa
-       rcall   printstr
-       .db     "KB.",0
-       
-       adiw    z,8
-       ldi     temp,high(hostparttbl)
-       cpi     xl,low (hostparttbl)
-       cpc     xh,temp
-       brlo    dsk_pprl
-       
-dsk_pcpe:
-       lds     temp,ndisks
-       ret
-
-       
-;***************************************************************************
-
-; ----------------- MMC/SD routines ------------------
-
-mmcByteNoSend:
-       ldi temp,0xff
-mmcByte:
-
-.if MMC_DEBUG
-       rcall printstr
-       .db "MMC: <--",0
-       rcall printhex
-.endif
-       
-       out SPDR,temp
-mmcWrByteW:
-       in temp,SPSR
-       sbrs temp,7
-        rjmp mmcWrByteW
-       in temp,SPDR
-
-.if MMC_DEBUG
-       rcall printstr
-       .db ", -->",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<<WDCE)
-       outm8 WDTCSR,temp
-       ldi temp,(1<<WDCE) | (1<<WDE) | (110<<WDP0)
-       outm8 WDTCSR,temp
-resetwait:
-       rjmp resetwait
-
-; ------------------ DRAM routines -------------
-
-;Loads the byte on address xh:xl into temp.
-;must not alter xh:xl
-
-dram_read:
-       cli
-       DRAM_SETADDR xh, ~0,(1<<ram_ras), ~(1<<ram_a8), (1<<ram_oe)
-       cbi P_RAS,ram_ras
-       DRAM_SETADDR xl, ~(1<<ram_ras),0, ~((1<<ram_oe)), (1<<ram_a8)
-       cbi P_CAS,ram_cas
-       cbi P_A8,ram_a8
-       dram_wait DRAM_WAITSTATES       ;
-       in  temp,P_DQ-2         ; PIN
-       sbi P_CAS,ram_cas
-
-       cbi P_CAS,ram_cas
-       andi temp,0x0f
-       swap temp
-       dram_wait DRAM_WAITSTATES       ;
-       in  temp2,P_DQ-2        ; PIN
-       andi temp2,0x0f
-       or  temp,temp2
-
-       sbi P_OE,ram_oe
-       sbi P_CAS,ram_cas
-       sbi P_RAS,ram_ras
-       sei
-       ret
-
-#if DRAM_WORD_ACCESS
-dram_read_w:
-       cpi xl,255
-       brne dram_read_w1
-       
-       rcall dram_read
-       push temp
-       adiw xl,1
-       rcall dram_read
-       mov temp2,temp
-       pop temp
-       ret     
-
-dram_read_w1:
-       cli
-       DRAM_SETADDR xh, ~0,(1<<ram_ras), ~(1<<ram_a8),(1<<ram_oe)
-       cbi P_RAS,ram_ras
-       DRAM_SETADDR xl, ~(1<<ram_ras),0, ~((1<<ram_oe)), (1<<ram_a8)
-       cbi P_CAS,ram_cas
-       cbi P_A8,ram_a8
-       nop
-       in  temp,P_DQ-2         ; PIN
-       sbi P_CAS,ram_cas
-       cbi P_CAS,ram_cas
-       andi temp,0x0f
-       swap temp
-       nop
-       in  temp2,P_DQ-2        ; PIN
-       sbi P_CAS,ram_cas
-       andi temp2,0x0f
-       or  temp,temp2
-       
-;      push temp
-       mov _wl,temp
-       inc xl
-       DRAM_SETADDR xl, ~(1<<ram_ras),0, ~((1<<ram_oe)), (1<<ram_a8)
-       cbi P_CAS,ram_cas
-       cbi P_A8,ram_a8
-       nop
-       in  temp,P_DQ-2         ; PIN
-       sbi P_CAS,ram_cas
-       cbi P_CAS,ram_cas
-       andi temp,0x0f
-       swap temp
-       nop
-       in  temp2,P_DQ-2        ; PIN
-       sbi P_CAS,ram_cas
-       andi temp2,0x0f
-       or  temp2,temp
-;      pop temp
-       mov temp,_wl
-
-       sbi P_OE,ram_oe
-       sbi P_RAS,ram_ras
-       sei
-       ret
-#endif
-
-;Writes the byte in temp to  xh:xl
-;must not alter xh:xl
-
-dram_write:
-       cli
-       ldi temp2,RAM_DQ_MASK | (1<<ram_w) | (1<<ram_cas)
-       out DDRC,temp2
-
-       mov  temp2,temp
-       andi temp,RAM_DQ_MASK & ~(1<<ram_w)
-       ori temp,(1<<ram_cas)
-       out PORTC,temp
-       DRAM_SETADDR xh, ~0,(1<<ram_ras), ~(1<<ram_a8),(1<<ram_oe)
-       cbi P_RAS,ram_ras
-       DRAM_SETADDR xl, ~(1<<ram_ras),0, ~((1<<ram_a8)),(1<<ram_oe)
-       cbi PORTC,ram_cas
-       sbi PORTC,ram_cas
-
-       sbi PORTD,ram_a8
-       swap temp2
-
-       andi temp2,RAM_DQ_MASK & ~(1<<ram_w)
-       ori temp2,(1<<ram_cas)
-       out PORTC,temp2
-
-       cbi PORTC,ram_cas
-       sbi P_RAS,ram_ras
-
-       ldi temp,~RAM_DQ_MASK | (1<<ram_w) | (1<<ram_cas)
-       out DDRC,temp
-       out PORTC,temp
-       sei
-       ret
-
-#if DRAM_WORD_ACCESS
-dram_write_w:
-       cpi xl,255
-       brne dram_write_w1
-       
-       push temp2
-       rcall dram_write
-       pop temp
-       adiw xl,1
-       rcall dram_write
-       ret     
-
-dram_write_w1:
-       cli
-       push temp2
-       ldi temp2,RAM_DQ_MASK | (1<<ram_w) | (1<<ram_cas)
-       out DDRC,temp2
-
-       mov  temp2,temp
-       andi temp,RAM_DQ_MASK & ~(1<<ram_w)
-       ori temp,(1<<ram_cas)
-       out PORTC,temp
-
-       DRAM_SETADDR xh, ~0,(1<<ram_ras), ~(1<<ram_a8),(1<<ram_oe)
-       cbi P_RAS,ram_ras
-       DRAM_SETADDR xl, ~(1<<ram_ras),0, ~((1<<ram_a8)),(1<<ram_oe)
-       cbi PORTC,ram_cas
-       sbi PORTC,ram_cas
-
-       sbi PORTD,ram_a8
-       swap temp2
-
-       andi temp2,RAM_DQ_MASK & ~(1<<ram_w)
-       ori temp2,(1<<ram_cas)
-       out PORTC,temp2
-
-       cbi PORTC,ram_cas
-       sbi PORTC,ram_cas
-
-       pop temp
-       inc xl
-       mov  temp2,temp
-       andi temp,RAM_DQ_MASK & ~(1<<ram_w)
-       ori temp,(1<<ram_cas)
-       out PORTC,temp
-
-       DRAM_SETADDR xl, ~(1<<ram_ras),0, ~((1<<ram_a8)),(1<<ram_oe)
-       cbi PORTC,ram_cas
-       sbi PORTC,ram_cas
-
-       sbi PORTD,ram_a8
-       swap temp2
-
-       andi temp2,RAM_DQ_MASK & ~(1<<ram_w)
-       ori temp2,(1<<ram_cas)
-       out PORTC,temp2
-       cbi PORTC,ram_cas
-
-       sbi P_RAS,ram_ras
-
-       ldi temp,~RAM_DQ_MASK | (1<<ram_w) | (1<<ram_cas)
-       out DDRC,temp
-       out PORTC,temp
-       sei
-       ret
-#endif
-
-; ****************************************************************************
-
-; refresh interupt; exec 2 cbr cycles
-refrint:                       ;4
-
-       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
-
-
-; ------------- 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<<TXEN0) | (1<<RXEN0) | (1<<RXCIE0)
-       outm8 UCSR0B,temp
-txi_x:
-       pop     temp
-       out     sreg,temp
-       pop     temp
-       reti
-
-
-;Sends a char from temp to the uart. 
-uartputc:
-       push    zh
-       push    zl
-       push    temp
-putc_l:
-       lds     temp,txcount            ;do {
-       cpi     temp,TXBUFSIZE          ;
-       brsh    putc_l                  ;} while (txcount >= 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<<UDRIE0) | (1<<TXEN0) | (1<<RXEN0) | (1<<RXCIE0)
-       outm8   UCSR0B,zl
-       sei
-       pop     zl
-       pop     zh
-       ret
-
 ; ------------ Fetch phase stuff -----------------
 
 .equ FETCH_NOP = (0<<0)
@@ -2810,27 +248,27 @@ do_fetch_a:
        ret
 
 do_fetch_b:
-       mov opl,z_b
+       lds opl,z_b
        ret
 
 do_fetch_c:
-       mov opl,z_c
+       lds opl,z_c
        ret
 
 do_fetch_d:
-       mov opl,z_d
+       lds opl,z_d
        ret
 
 do_fetch_e:
-       mov opl,z_e
+       lds opl,z_e
        ret
 
 do_fetch_h:
-       mov opl,z_h
+       lds opl,z_h
        ret
 
 do_fetch_l:
-       mov opl,z_l
+       lds opl,z_l
        ret
 
 do_fetch_af:
@@ -2839,15 +277,18 @@ do_fetch_af:
        ret
 
 do_fetch_bc:
-       movw opl,z_c
+       lds opl,z_c
+       lds oph,z_b
        ret
 
 do_fetch_de:
-       movw opl,z_e
+       lds opl,z_e
+       lds oph,z_d
        ret
 
 do_fetch_hl:
-       movw opl,z_l
+       lds opl,z_l
+       lds oph,z_h
        ret
 
 do_fetch_sp:
@@ -2855,67 +296,48 @@ do_fetch_sp:
        ret
 
 do_fetch_mbc:
-       movw xl,z_c
-       rcall memReadByte
-       mov opl,temp
+       lds xh,z_b
+       lds xl,z_c
+       mem_read_d opl
        ret
 
 do_fetch_mde:
-       movw xl,z_e
-       rcall memReadByte
-       mov opl,temp
+       lds xh,z_d
+       lds xl,z_e
+       mem_read_d opl
        ret
 
 do_fetch_mhl:
-       movw xl,z_l
-       rcall memReadByte
-       mov opl,temp
+       lds xh,z_h
+       lds xl,z_l
+       mem_read_d opl
        ret
 
 do_fetch_msp:
-       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 
+       movw x,z_spl
+       mem_read_d opl
+       adiw x,1
+       mem_read_d oph
        ret
 
 do_fetch_dir8:
-       movw xl,z_pcl
-       rcall memReadByte
+       mem_read_ds opl, z_pc
        adiw z_pcl,1
-       mov opl,temp
        ret
 
 do_fetch_dir16:
-       movw xl,z_pcl
-#if DRAM_WORD_ACCESS
-       rcall memReadWord
-       movw opl,temp
-#else
-       rcall memReadByte
-       mov opl,temp
-       adiw xl,1
-       rcall memReadByte
-       mov oph,temp
-#endif 
-       adiw z_pcl,2
+       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 xl,z_pcl
-       subi xl,1
-       sbci xh,0
-       rcall memReadByte
-       andi temp,0x38
+       movw x,z_pcl
+       sbiw x,1
+       mem_read_d opl
+       andi opl,0x38
        ldi oph,0
-       mov opl,temp
        ret
        
 
@@ -2977,27 +399,27 @@ do_store_a:
        ret
 
 do_store_b:
-       mov z_b,opl
+       sts z_b,opl
        ret
 
 do_store_c:
-       mov z_c,opl
+       sts z_c,opl
        ret
 
 do_store_d:
-       mov z_d,opl
+       sts z_d,opl
        ret
 
 do_store_e:
-       mov z_e,opl
+       sts z_e,opl
        ret
 
 do_store_h:
-       mov z_h,opl
+       sts z_h,opl
        ret
 
 do_store_l:
-       mov z_l,opl
+       sts z_l,opl
        ret
 
 do_store_af:
@@ -3006,50 +428,43 @@ do_store_af:
        ret
 
 do_store_bc:
-       mov z_b,oph
-       mov z_c,opl
+       sts z_b,oph
+       sts z_c,opl
        ret
 
 do_store_de:
-       mov z_d,oph
-       mov z_e,opl
+       sts z_d,oph
+       sts z_e,opl
        ret
 
 do_store_hl:
-       mov z_h,oph
-       mov z_l,opl
+       sts z_h,oph
+       sts z_l,opl
        ret
 
 do_store_mbc:
-       movw xl,z_c
-       mov temp,opl
-       rcall memWriteByte
+       lds xh,z_b
+       lds xl,z_c
+       mem_write_s opl
        ret
 
 do_store_mde:
-       movw xl,z_e
-       mov temp,opl
-       rcall memWriteByte
+       lds xh,z_d
+       lds xl,z_e
+       mem_write_s opl
        ret
 
 do_store_mhl:
-       movw xl,z_l
-       mov temp,opl
-       rcall memWriteByte
+       lds xh,z_h
+       lds xl,z_l
+       mem_write_s opl
        ret
 
 do_store_msp:
-       movw xl,z_spl
-#if DRAM_WORD_ACCESS
-       movw temp,opl
-       rcall memWriteWord
-#else
-       mov temp,opl
-       rcall memWriteByte
+       movw xl,z_spl
+       mem_write_s opl
        adiw xl,1
-       mov temp,oph
-       rcall memWriteByte
-#endif
+       mem_write_s oph
        ret
 
 do_store_sp:
@@ -3061,23 +476,49 @@ do_store_pc:
        ret
 
 do_store_ret:
-       rcall do_op_pop16
-       movw z_pcl,opl
+       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:
-       push opl
-       push oph
-       movw opl,z_pcl
-       rcall do_op_push16
-       pop z_pch
-       pop z_pcl
+       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:
-       movw xl,opl
-       mov temp,z_a
-       rcall memWriteByte
+       mem_write_ds op, z_a
        ret
 
 
@@ -3174,16 +615,6 @@ opjumps:
        rjmp do_op_deca
 
 
-;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...
-
 ;----------------------------------------------------------------
 ;|                                                              |
 ;|                            Zilog                             |
@@ -3356,6 +787,22 @@ opjumps:
 ;| ##              |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
@@ -3365,17 +812,6 @@ opjumps:
 .equ AVR_Z = SREG_Z
 .equ AVR_C = SREG_C
 
-;------------------------------------------------;
-; Move single bit between two registers
-;
-;      bmov    dstreg,dstbit,srcreg.srcbit
-
-.macro bmov
-       bst     @2,@3
-       bld     @0,@1
-.endm
-
-
 ;------------------------------------------------;
 ; Load table value from flash indexed by source reg.
 ;
@@ -3388,6 +824,7 @@ opjumps:
        mov     zl,@2                  
        lpm     @0,z    
 .endm
+
 .macro do_z80_flags_HP
 #if EM_Z80
        bmov    z_flags, ZFL_P, temp, AVR_V
@@ -3436,9 +873,65 @@ opjumps:
 .endm
 
 
+;----------------------------------------------------------------
+do_op_inv:
+       printstring "Invalid opcode @ PC="
+       movw   temp,z_pcl
+       rcall printhexw
+haltinv:
+       rjmp haltinv
+        
 do_op_nop:
        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
+       printnewline
+       printstring "Port write: "
+       mov temp,z_a
+       rcall printhex
+       printstring " -> ("
+       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
+