NAME

CPU::Emulator::Z80 - a Z80 emulator

SYNOPSIS

# create a CPU with 64K of zeroes in RAM
my $cpu = CPU::Emulator::Z80->new();

# set a breakpoint
$cpu->memory()->poke16(0xF000, 0xDDDD); # STOP instruction
$cpu->memory()->poke(0xF002, 0x00);

$cpu->memory()->poke(0, 0xC3);     # JP 0xC000
$cpu->memory()->poke16(1, 0xC000);

# run until we hit a breakpoint ie RST 1
eval { $cpu->run(); }
print $cpu->format_registers();

DESCRIPTION

This class provides a virtual Z80 micro-processor written in pure perl. You can program it in Z80 machine code. Machine code is fast! This will make your code faster!

METHODS

new

The constructor returns an object representing a Z80 CPU. It takes several optional parameters:

memory

can be either an object inheriting from CPU::Emulator::Memory, or a string of data with which to initialise RAM. If a string is passed, then a CPU::Emulator::Memory::Banked is created of the appropriate size. If not specified at all, then a CPU::Emulator::Memory::Banked is created with 64K of zeroes.

ports

can be either 256 or 65536 (no other values are permitted) and defaults to 65536. This is the number of I/O ports that can be addressed. If set to 65536, the entire address bus is used to determine what port I/O instructions tickle. If 256, then the most significant 8 bits are ignored.

init_PC, init_A, init_B ...

For each of A B C D E F R HL IX IY PC SP, an integer, the starting value for that register, defaulting to 0.

init_A_, init_B_, ...

For each of A B C D E F HL, an integer for the starting value for that register in the alternate set, defaulting to 0. Note that contrary to normal Z80 custom these are named as X_ instead of X'. This is just for quoting convenience.

add_input_device

Takes two named parameters, 'address' and 'function', and creates an input port at that address. Reading from the port will call the function with no parameters, returning whatever the function returns.

In 256-port mode, the port is effectively replicated 256 times.

add_output_device

Takes two named parameters, 'address' and 'function', and creates an output port at that address. Writing to the port simply calls that function with the byte to be written as its only parameter.

In 256-port mode, the port is effectively replicated 256 times.

memory

Return a reference to the object that represent's the system's memory.

register

Return the object representing a specified register. This can be any of the real registers (eg D or D_) or a derived register (eg DE or L). For (HL) it returns the private internal DON'T TOUCH THIS 'W' register, for evil twisty internals reasons.

status

Return a scalar representing the entire state of the CPU or, if passed a scalar, attempt to initialise the CPU to the status it represents.

registers

Return a hashref of all the real registers and their values.

format_registers

A convenient method for getting all the registers in a nice printable format. It mostly exists to help me with debuggering, but if you promise to be good you can use it too. Just don't rely on the format remaining unchanged.

interrupt

Attempt to raise an interrupt. Whether any attention is paid to it or not depends on whether you've enabled interrupts or not in your Z80 code. Because only IM 1 is implemented, this will generate a RST 0x38 if interrupts are enabled. Note that interrupts are disabled at power-on.

This returns true if the interrupt will be acted upon, false otherwise. That is, it returns true if interrupts are enabled.

nmi

Raise a non-maskable interrupt. This generates a CALL 0x0066 as the next instruction.a This also disables interrupts. Interrupts are restored to their previous state by a RETN instruction.

run

Start the CPU running from whatever the Program Counter (PC) is set to. This will by default run for ever. However, it takes an optional parameter telling the CPU to run that number of instructions.

This returns either when that many instructions have been executed, or when a STOP instruction executed - see 'Extra Instructions' below.

On return, the PC will point at the next instruction to execute so that you can resume where you left off.

stopped

Returns true if the CPU has STOPped, false otherwise. You can use this to easily determine why the run() method returned.

EXTRA INSTRUCTIONS

Whenever any combination of two of the 0xDD and 0xFD prefixes are met, behaviour deviates from that of a normal Z80 and instead depends on the following byte:

0x00 - STOP

The run() method stops, even if the desired number of instructions has not yet been reached.

anything else

Fatal error.

PROGRAMMING THE Z80

I recommend "Programming the Z80" by Rodnay Zaks. This excellent book is unfortunately out of print, but may be available through abebooks.com http://www.abebooks.com/servlet/SearchResults?an=zaks&tn=programming+the+z80.

BUGS/WARNINGS/LIMITATIONS

Claims about making your code faster may not be true in all realities.

I assume you're using a twos-complement machine. I *think* that that's true of anything perl runs on.

Only interrupt mode 1 is implemented. All interrupts are serviced by a RST 0x38 instruction.

The DDFD- and FDDD-prefixed instructions (the "use this index register - no, wait, I meant the other one" prefixes) and the DDDD- and FDFD-prefixed instructions (the "use this index register, no really, I mean it, pleeeeease" prefixes) are silly, and have been replaced - see "Extra Instructions" above.

FEEDBACK

I welcome feedback about my code, including constructive criticism and bug reports. The best bug reports include files that I can add to the test suite, which fail with the current code in CVS and will pass once I've fixed the bug.

Feature requests are far more likely to get implemented if you submit a patch yourself.

SEE ALSO

Acme::6502

The FUSE Free Unix Spectrum Emulator: http://fuse-emulator.sourceforge.net/

CVS

http://drhyde.cvs.sourceforge.net/drhyde/perlmodules/CPU-Emulator-Z80/

AUTHOR, LICENCE and COPYRIGHT

Copyright 2008 David Cantrell <david@cantrell.org.uk>

This module is free-as-in-speech software, and may be used, distributed, and modified under the terms of the GNU General Public Licence version 2, or any later version if you prefer.

Note that this differs from the licence for the other modules. That is because the bulk of this particular module's test suite is derived from FUSE, which is GPLed. A copy of the GPL can be found in the t/fuse-tests/COPYING file.

CONSPIRACY

This module is also free-as-in-mason software.