********************************************************************************
                                    z80em86

               A Z80 emulator coded in Intel 86 assembly language

                      Copyright (C) 1992-2009 Stewart Kay

For contact details please see the 'Contact' section at the end of this file.
********************************************************************************

Distribution License
====================
See license.txt in this distribution.

Overview
========
z80em86 is a Z80 CPU emulator with hardware emulation coded entirely in
Intel 86 assembly language and designed to run under MSDOS.  The emulator
will also run under Windows 98/Me/2000/XP (Vista/W7 not tried) as a 16 bit
application and under DosEmu on Linux systems.

The coding for this Z80 emulator started sometime back in 1992 and was
mainly complete by 1993 with some further minor changes made in 1995.  Other
changes have been made recently to allow the program to work under Windows
2000 as a 16 bit application.  The software was never released and is now
being released for the first time under the GPL.

The emulator does not try to be fancy but does support a basic DOS Window
interface system and supports hardware emulation allowing Z80 operating
systems to be coded for it.

The idea to write the emulator came to surface when I purchased an IBM
compatible i386 machine and wanted to learn 8086 Assembly language so I
decided that coding up a Z80 emulator to run under DOS would be an
interesting and educational exercise.  The goal was to produce a Z80
emulator to run as fast as possible and to emulate the Z80 documented
instruction set.

The emulator as it stands also supports some generic hardware emulation
functions that makes it possible to boot and run a Z80 operating system. 
The emulator can boot from a floppy disk or a HDD disk image.

The entire memory allocated to z80em86 by DOS on start-up is freed and the
memory re-allocated. Two banks of 64K each are allocated for use as system
banks allowing banked operating systems to be implemented.  16K is allocated
to a DOS window system and the remainder is allocated in 16K blocks usable
by a Z80 operating system.  Typically these extra blocks can be used to
implement a RAM disk.

A fully implemented CP/M 3 banked and non banked system with support
utilities is also available to be used with the emulator.  This is not
supplied with z80em86 but will be made available elsewhere.  See 'Z80
Operating systems' section near the end of this document.

A slightly modified CP/M program 'zexdoc.com' has been used for testing. 
See 'Tesing z80em86' section below.

The software is well organised and broken up into module groups as defined
in the Z80 CPU documentation.

The following is a list of ideas for possible future development:

1. Convert to 32 bit assembly language.
2. Add cycle counting for each opcode.
3. Add optional memory and IO handler functions.
4. Add interrupt support.
5. Add undocumented Z80 instructions and flags.
6. Provide a build option to compile without hardware emulation support so
   that it just emulates Z80 code and provide a 'C' wrapper.
7. Add multi processor support.

You can get the emulator package(s) from here:

http://www.cpm.z80.de/source.html
http://www.gaby.de/z80/z80emu.htm

RUNNING Z80EMU86
================

Starting
--------
The emulator may be started with some options on the command line.  The user
may optionally specify if a floppy disk 'A' or 'B' is to be booted from
instead of a HDD disk image.

Boot from floppy drive A:
>z80em86 -a

Boot from floppy drive B:
>z80em86 -b

If no drive options are specified the emulator will check for a HDD raw disk
image file (z80hdd.dsk) or if that does not exist prompt the user to insert
a floppy disk into drive 'A' to boot from.

The emulator will attempt to load the first sector from side #0, track #0
from the HDD image or floppy disk into memory at address 80 hex in the Z80
memory map.  The PC register will be set to address 80 hex and the SP
register to address FFFF hex upon execution.

The Z80 emulator now executes the Z80 code at address 80 hex which most
likely contains some sort of boot strap loader for loading an operating
system into memory.

In addition to the optional floppy drive parameter a second parameter can be
passed that a Z80 system can make use of.  One of the support programs for
the CP/M 3 system that runs under the Z80 emulator makes use of this
parameter allowing a submit file or a CP/M 3 command to be passed.

Interrupting emulation
----------------------
As the emulator is running, execution can be interrupted by pressing the
CTRL+ALT+I keys to bring up a DOS Window of options.  These allow the
emulator to be Reset (R), Exit to DOS (E) or Continue (C).  This provides a
convenient method to pause the emulator then resuming by selecting Continue.

DOS critical error handler
--------------------------
Emulation employs a DOS critical error handler that will display a DOS
window message if any critical error occurs during emulation.

Z80 CPU emulation
=================
Emulation of all Zilog documented instructions is supported except for I/O,
interrupt and related instructions.  A DOS Window message will report any
non emulated instruction.

Handling of some Z80 instructions
---------------------------------
IM 0    : Interrupt mode #0, the emulation of this code stops the emulator
          and prompts the user to reset the Z80 or exit to DOS.
IM 1    : Interrupt mode #1, same action as IM 0
IM 2    : Interrupt mode #2, same action as IM 0

DI, EI  : Disable/Enable Interrupts, these instructions only affect the Z80
          IFF flags. These have no affect on the host system's interrupts.

HALT    : Halt processing, the halt instruction halts the emulator and
          alerts the user that the HALT instruction was executed and then
          prompts the user to reboot the CP/M system.

IN, OUT : Input/Output port, all input/output (and block) instructions are
          ignored as these are hardware dependent.  The emulator will stop
          and alert the user that an IN/OUT instruction was executed and
          then prompt the user to reboot the CP/M system.

RETI    : Execution is halted.
RETN    : Execution is halted.

LD A,I  : Emulated but does nothing.
LD I,A  : Emulated but does nothing.
LD A,R  : Emulated but does nothing.
LD R,A  : Emulated but does nothing.

Z80 and 8086 register/memory relationships
------------------------------------------
Z80 Register    8086 Register/(Memory)
A               AL
B               CH
C               CL
D               DH
E               DL
H               BH
L               BL
I               (Z80I)
R               (Z80R)
AF              AL + SAHF
BC              CX
DE              DX
HL              BX
PC              BP
SP              (Z80SP)
IX              (Z80IX)
IY              (Z80IY)
AF'             (Z80AF)
BC'             (Z80BC)
DE'             (Z80DE)
HL'             (Z80HL)

Variable        Bits            Description
FlagN           8               Emulates the Z80 N flag
Z80SP           16              Z80 stack pointer storage
Z80IX           16              Z80 X index register storage
Z80IY           16              Z80 Y index register storage
Z80BC           16              Z80 2nd BC register storage
Z80DE           16              Z80 2nd DE register storage
Z80HL           16              Z80 2nd HL register storage

Segments
reg ES (extra segment addresses the Z80 memory map segment)
reg DS (data segment addresses tables and data)
reg CS (code segment is the emulator code segment)
reg SS (stack segment is the stack pointer segment)

Hardware emulation
==================
The emulator supports emulation of hardware and other host system calls by
making use of one of the Z80's OUT instructions:

OUT (Fn),A

Where 'Fn' is the required function and allows up to 256 functions at the
base level.  As the emulator was originally designed not to emulate I/O
opcodes this provided a convenient method to access emulated hardware.

The functions are contained in the 'T7' table found in the 'table.asm'
assembly file.

Functions 00-1FH - Keyboard
---------------------------
Fn(H)   Table name      Description
00      kbd1in          Initialise kbd1
01      kbd1st          kbd1 status
                          Return: A(AL)=Keyboard status (not ready=0)
02      kbd1ip          kbd1 input
                          Return: A(AL)=Keyboard character
10      kbd2in          Initialise kbd2 (STDIN)
11      kbd2st          kbd2 status (STDIN)
                          Return: A(AL)=STDIN status (not ready=0)
12      kbd2in          kbd2 input (STDIN)
                          Return: A(AL)=STDIN character

Functions 20-3FH - CRT
----------------------
The CRT emulates a Televideo 920/ADM-3A Video Terminal on crt1 and provides
STDOUT on crt2 using the DOS video service.

Fn(H)   Table name      Description
20      crt1in          CRT #1 Initialise
21      crt1st          CRT #1 ready status
                          Return: A(AL)=output status
22      crt1op          CRT #1 output character
                          Pass: C(CL)=output character
30      crt2in          CRT #2 Initialise (STDOUT)
31      crt2st          CRT #2 ready status (STDOUT)
                          Return: A(AL)=output status
32      crt2on          CRT #1 output character (STDOUT)
                          Pass: C(CL)=output character

Functions 40-4FH - LPT
----------------------
Fn(H)   Table name      Description
40      lptini          Initialise LPT port
                          Pass: DE(DX)=LPT port (0-3)
41      lptsta          LPT ready status
                          Pass: DE(DX)=LPT port (0-3)
                          Return: A(AL)=output status (not ready=0)
42      lptout          LPT output character
                          Pass: DE(DX)=LPT port (0-3)
                                 C(CL)=output character

Functions 50-5FH - COMMUNICATIONS
---------------------------------
Fn(H)   Table name      Description
50      comini          Initialise com port
                          Pass: DE(DX)=Coms port (0-3)
                          A(AL)=baud/parity/data bits/stop bits
51      comist          Input status
                          Pass: DE(DX)=Coms port (0-3)
                          Return: input status in reg A(AL)
52      cominp          Input byte
                          Pass: DE(DX)=Coms port (0-3)
                          Return: input character in reg A(AL)
53      comost          Output status
                          Pass: DE(DX)=Coms port (0-3)
                          Return: output status in reg A(AL)
54      comout          Output byte
                          Pass: DE(DX)=Coms port (0-3), C(CL)=output character

Functions 60-6FH - TIME/DATE
----------------------------
Fn(H)   Table name      Description
60      gettme          Get time
                          Pass: reg HL(BX) = Z80 address to return results
                          Return: mem[HL(BX)+0] = hours in BCD
                                  mem[HL(BX)+1] = minutes in BCD
                                  mem[HL(BX)+2] = seconds in BCD
61      settme          Set time
                          Pass: reg HL(BX) = Z80 address of parameters
                                mem[HL(BX)+0] = hours in BCD
                                mem[HL(BX)+1] = minutes in BCD
                                mem[HL(BX)+2] = seconds in BCD
62      getdte          Get date
                          Pass: reg HL(BX) = Z80 address to return result
                          Return: mem[HL(BX)+0] = days since 31st December 1977
63      setdte          Set date
                          Pass: reg HL(BX) = Z80 address of parameter
                          Return: mem[HL(BX)+0] = days since 31st December 1977

Functions 80-8FH - DISK
-----------------------
Fn(H)   Table name      Description
80      rdflop          Read floppy disk
                          Pass: A(AL)=sector size code (0=128, 1=256, 2=512, 3=1024)
                                B(CH)=track number
                                C(CL)=sector number
                                D(DH)=side select
                                E(DL)=drive code (0=drive A, 1=drive B)
                                HL(BX)=buffer address
                          Return: A(AL)=0 if no errors, 1 if error
81      wrflop          Write floppy disk
                          Values same as 'rdflop'
82      rdhard          Read hard disk image
                          Pass: B(CH)=track number
                                C(CL)=sector number
                                E(DL)=drive code (2=drive C, 3=drive D etc)
                                HL(BX)=buffer address
                          Return: A(AL)=0 if no errors, 1 if error
83      wrhard          Write hard disk image
                          Values same as 'rdhard'
84      GtBoot          Get boot drive
                          Return: A(AL)=boot drive
85      GtHard          Get hard disk drive
                          Return: A(AL)=HDD drive or FFh if none
86      FlHard          Flush HDD file buffer

Functions 90-9FH - MEMORY BLOCKS
--------------------------------
Fn(H)   Table name      Description
90      blkcnt          Get count of blocks available (1 block=16384 bytes)
                          Return: A(AL)=number of blocks
91      blkget          Get 128 bytes from block (1 record=128 bytes) from
                        the current DMA bank. (see bnkdma function)
                          Pass:  C(CL)=block number
                                 D(DH)=starting record number
                                 E(DL)=number of records
                                HL(BX)=Z80 destination address
92      blkput          Put 128 bytes in block (1 record=128 bytes) for
                        the current DMA bank. (see bnkdma function)
                          Pass:  C(CL)=block number
                                 D(DH)=starting record number
                                 E(DL)=number of records
                                HL(BX)=Z80 source address
93      blkfil          Fill 128 bytes in block (1 record=128 bytes) for
                        the current DMA bank. (see bnkdma function)
                          Pass:  A(AL)=fill value
                                 C(CL)=block number
                                 D(DH)=starting record number
                                 E(DL)=number of records

Functions A0-BFH - INTERRUPT SERVICES
-------------------------------------
Fn(H)   Table name      Description
A0      GtZseg          Return Z80 map segment address
                          Pass: HL(BX)=Z80 address to place result
A1      intfnc          Call a ROM BIOS/DOS Interrupt service
                          Pass: BC(CX)=0AA55h
                                DE(DX)=055AAh
                                HL(BX)=base address of register table
                                 A(AL)=Interrupt
B0      GetByt          Get byte from memory
                          Pass: DE(DX)=segment
                                HL(BX)=offset
                          Return: A(AL)=byte
B1      SetByt          Set byte in memory
                          Pass: DE(DX)=segment
                                HL(BX)=offset
                                 A(AL)=byte

Functions F0-F7H - BANKING
--------------------------
Fn(H)   Table name      Description
F0      bnkuse          Set bank size to use
                          Pass: BC(CX)=sets banking, size of bank #0, #1
F1      bnksel          Select bank
                          Pass: A(AL)=bank 0 or 1
F2      bnkmve          Move memory in current bank or bank to bank
                          Pass: HL(BX)=destination address
                                DE(DX)=source address
                                BC(CX)=amount to be moved
F3      bnkdta          Set destination and source banks
                          Pass: B(CH)=destination bank
                                C(CL)=source bank
F4      bnkdma          Set DMA bank #0 or #1
                          Pass: A(AL)=DMA bank 0 or 1

Functions F8-FFH - CONTROL
--------------------------
Fn(H)   Table name      Description
F8      prmsta          Get parameter passed status
                          Return: A(AL)=FFh if parameter passed
F9      prmget          Get the parameters address
                          Pass: HL(BX)=Z80 address to place result
                          Return: Z80[HL+0]=parameter buffer data segment
                                  Z80[HL+2]=parameter buffer offset
FA      vidsta          Get the video on/off status
                          Return: A(AL)=FFh if video is off
FB      vidset          Set video on/off
                          Pass: A(AL)=FFh turn video off
FC      usrbyt          Get/Set a user byte (0-31)
                          Pass:  C(CL)=0 to get, else set
                                 A(AL)=byte to set (if set)
                                HL(BX)=byte offset (0-31)
                          Return: A(AL)=get byte (if get)
FD      failed          Set boot strap failure
FE      rstz80          Reset the Z80 emulator
FF      extemu          Exit the Z80 emulator back to DOS

SOURCE CODE
===========
The software was originally developed to be compiled with Turbo Pascal's
TASM assembler and then linked with TLINK to produce an EXE binary under a
DOS environment.  The original work has been converted to NASM (8086) format
for future development work and can be developed under a Unix environment.

The conversion process used the NOMYSO V4.0 MASM/TASM to NASM source
converter available here:

www.devoresoftware.com/nomyso

The sources required some changes by hand afterwards.  Comparing of the
original compiled/linked executable to that produced by NASM and TLINK/ALINK
is not really possible as different opcodes for some instructions are used
and optimising differences exist.  TASM (v3.2) does not appear to have
anyway of turning optimisation off and there are other areas where the
optimisation does not work consistently.

z80em86 Source Files
--------------------
arith8.asm      8-bit Arithmetic and Logical Group
arith16.asm     16-bit Arithmetic Group
bit.asm         Bit Test Group
call.asm        Call and Return Group
control.asm     General Purpose Arithmetic and CPU Control Groups
exchange.asm    Exchange, Block Transfer, Block Search Groups
io.asm          Input and Output Group
jump.asm        Jump Group
load8.asm       8-bit Load Group
load16.asm      16-bit Load Group
res.asm         Bit Reset Group
rotate.asm      Rotate and Shift Group
set.asm         Bit Set Group

insthand.asm    Instruction Handler for Extended Opcodes
macros.asm      Macros
table.asm       Z80 Opcodes and Function Interface tables

function.asm    General function interface support for Z80 system code
hardware.asm    Hardware interface support for Z80 system code
main.asm        Main assembly module
video.asm       Video function support for Z80 system code
window.asm      Window and Screen Output support for error messages

Utility Source Files
--------------------
z80hdd.pas	A Turbo Pascal program that can be used to create a 4MB
                formatted HDD disk image.

Code Execution
--------------
Code execution commences in 'main.asm' at '..start'

Z80 Source Opcode Labels
------------------------
The labels used are 6 character maximum which was common at the time as it
fitted neatly in the first tab column of 8 spaces.

Label format for Z80 opcodes:

ABC

A - All labels that reference a Z80 instruction commence with 'Z_'
B - The capital letters that follow is the mnemonic.
C - operand associated with mnemonic as follows:-

a=reg A
b=reg B   bc=reg BC
c=reg C
d=reg D   de=reg DE
e=reg E
h=reg H   hl=reg HL   x=reg IX   y=reg IY   z=(HL)  w=(IX)  v=(IY)
l=reg L
f=reg F   sp=reg SP   n=$12      n=$1234    m=($1234)
i=reg I
r=reg R

Tesing z80em86
==============
In recent times a CP/M program 'zexdoc.com' has been used for testing and
debugging emulation. 'zexdoc.com' is the documented Z80 flags version of
'zexall.com' but both versions test undocumented instructions.

The 'zexdoc' source code was modified to disable tests where undocumented
instructions were used as these caused the emulator to stop. 'zexdoc.com'
passed all the tests for undocumented instructions.  The disabled tests may
contain documented instructions and as such will not be tested.

The source file (CPM.zip) came from here:
http://mdfs.net/Software/Z80/Exerciser/

The following tests were disabled as undocumented instructions are included
in the tests.  Place a semicolon in front of these and recompile:

alu8rx, incxh, incxl, incyh, incyl, ld8ixy, ld8rrx, rotxy, rotz80

These all passed the test (no CRC errors):

adc16, add16, add16x, add16y, alu8i, alu8r, alu8x, bitx, bitz80, cpd1, cpi1,
daaop, inca, incb, incbc, incc, incd, incde, ince, inch, inchl, incix, inciy,
incl, incm, incsp, incx, ld161, ld162, ld163, ld164, ld165, ld166, ld167,
ld168, ld16im, ld16ix, ld8bd, ld8im, ld8imx, ld8ix1, ld8ix2, ld8ix3, ld8rr,
lda, ldd1, ldd2, ldi1, ldi2, negop, rldop, rot8080, srz80, srzx, st8ix1,
st8ix2, st8ix3, stabd

Output from running the tests
-----------------------------
Execution times to complete the tests on various hardware/systems:

* Athlon XP 1.8GHz (2200+) PC, W2000 Pro 'cmd' prompt: 55 seconds.
* Athlon XP 1.8GHz (2200+) PC, W98 'Startup disk': 47 seconds.
* Linux Athlon AMD64 dual core (3800+), 32 bit Linux and DosEmu: 227 seconds.

Z80doc instruction exerciser
<adc,sbc> hl,<bc,de,hl,sp>....  OK
add hl,<bc,de,hl,sp>..........  OK
add ix,<bc,de,ix,sp>..........  OK
add iy,<bc,de,iy,sp>..........  OK
aluop a,nn....................  OK
aluop a,<b,c,d,e,h,l,(hl),a>..  OK
aluop a,(<ix,iy>+1)...........  OK
bit n,(<ix,iy>+1).............  OK
bit n,<b,c,d,e,h,l,(hl),a>....  OK
cpd<r>........................  OK
cpi<r>........................  OK
<daa,cpl,scf,ccf>.............  OK
<inc,dec> a...................  OK
<inc,dec> b...................  OK
<inc,dec> bc..................  OK
<inc,dec> c...................  OK
<inc,dec> d...................  OK
<inc,dec> de..................  OK
<inc,dec> e...................  OK
<inc,dec> h...................  OK
<inc,dec> hl..................  OK
<inc,dec> ix..................  OK
<inc,dec> iy..................  OK
<inc,dec> l...................  OK
<inc,dec> (hl)................  OK
<inc,dec> sp..................  OK
<inc,dec> (<ix,iy>+1).........  OK
ld <bc,de>,(nnnn).............  OK
ld hl,(nnnn)..................  OK
ld sp,(nnnn)..................  OK
ld <ix,iy>,(nnnn).............  OK
ld (nnnn),<bc,de>.............  OK
ld (nnnn),hl..................  OK
ld (nnnn),sp..................  OK
ld (nnnn),<ix,iy>.............  OK
ld <bc,de,hl,sp>,nnnn.........  OK
ld <ix,iy>,nnnn...............  OK
ld a,<(bc),(de)>..............  OK
ld <b,c,d,e,h,l,(hl),a>,nn....  OK
ld (<ix,iy>+1),nn.............  OK
ld <b,c,d,e>,(<ix,iy>+1)......  OK
ld <h,l>,(<ix,iy>+1)..........  OK
ld a,(<ix,iy>+1)..............  OK
ld <bcdehla>,<bcdehla>........  OK
ld a,(nnnn) / ld (nnnn),a.....  OK
ldd<r> (1)....................  OK
ldd<r> (2)....................  OK
ldi<r> (1)....................  OK
ldi<r> (2)....................  OK
neg...........................  OK
<rrd,rld>.....................  OK
<rlca,rrca,rla,rra>...........  OK
<set,res> n,<bcdehl(hl)a>.....  OK
<set,res> n,(<ix,iy>+1).......  OK
ld (<ix,iy>+1),<b,c,d,e>......  OK
ld (<ix,iy>+1),<h,l>..........  OK
ld (<ix,iy>+1),a..............  OK
ld (<bc,de>),a................  OK
Tests complete

Z80 Operating systems
=====================
This emulator project does not provide any sort of operating system.  It
simply emulates a Z80 CPU and provides some hardware support that may be
used by an operating system.

The emulator on start-up will load a boot sector from a floppy disk or HDD
disk image and execute the code loaded.  What code is loaded and run is
determined by the user and what code is on the disk.

I have coded a customised CP/M 3 BIOS and CP/M 3 support utilities that have
been designed to run under this emulator.  The system may be booted in
banked or non banked mode.  Further information about the system can be
found in the CP/M 3 package.

This README file should provide all the information needed for anyone to
write other systems to be run under the emulator.

The CP/M 3 system and support files are available as a single package from
here:

http://www.cpm.z80.de/source.html
http://www.gaby.de/z80/z80emu.htm

Links
=====
- The Unofficial CP/M Web site
  http://www.cpm.z80.de

- Walnut Creek CDROM,  contains a lot of CP/M stuff
  http://z80cpu.eu/mirrors/oldcomputers.dyndns.org/cdrom/cpm

- Other sites:
  http://www.digitalresearch.biz/CPM.HTM
  http://www.classiccmp.org/dunfield/
  http://www.seasip.demon.co.uk/Unix/LibDsk/
  http://www.seasip.demon.co.uk/Cpm/index.html
  http://www.znode51.de/indexe.htm
  http://www.z80.eu/cpmcomp.html

Projects by this author
=======================

uBee512
-------
An emulator for the Microbee Z80 ROM, FDD and HDD based models.

http://www.microbee-mspp.org.au/public_repository

uBeeDisk
--------
A tool for converting disks/images from one to another with
auto detection options for Microbee disks.

http://www.microbee-mspp.org.au/public_repository

z80em86
-------
A Z80 CPU emulator coded in Intel 86 assembly language.

http://www.cpm.z80.de/source.html
http://www.gaby.de/z80/z80emu.htm

Contact
=======
If you have any new feature suggestions, bug reports, etc. then please send
an email to: ubee512@gmail.com

Please state which project your referring to.

Stewart
