]> cloudbase.mooo.com Git - avrcpm.git/blobdiff - z80int.asm
Merged branch modules back into trunk.
[avrcpm.git] / z80int.asm
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
+