Giter Club home page Giter Club logo

z80emu's Introduction

z80emu
Version 1.1.3

Copyright (c) 2012-2017 Lin Ke-Fong
 
z80emu is a free portable Z80 processor emulator. Its performance is comparable
to other Z80 emulators. It emulates all undocumented features as described in 
"The Undocumented Z80 Documented Version 0.91" and passes both the zexdoc and 
zexall Z80 instruction exerciser tests. Code is pure ANSI C.
 
The Makefile will compile a sample program to run zexdoc.com and zexall.com.
Only needed CP/M BIOS functions are emulated. See zextest.c for details.
 
All structures and functions are documented in the code, please read the header
files. To use z80emu in your programs, modify z80config.h to configure the 
emulator, and in z80user.h, write the memory read/write and port input/output 
macros to interface with your system to emulate. The macros for zextest.c are 
simple examples. You shouldn't have to modify z80emu.c or any other files.
 
z80emu works a little bit differently from other emulators. Instead of a switch
case for all opcodes, it converts them to "generic" instructions and then do
the switch case. Registers and operands are then decoded during execution. All 
of this is done using several tables (see maketables.c). The code is more 
compact, which should make it fit inside L1 instruction cache.
 
You may find further information regarding the Z80 on http://www.z80.info. This
emulator is heavily based on the information found on this website. And I would
like to thank all its contributors. In particular, Sean Young for "The 
Undocumented Z80 Documented" and Christian Dinu for "Decoding Z80 Opcodes". The
zexdoc and zexall programs have been written by Frank D. Cringles.
 
I would like to thank Hugo Clement, Guy Hermann, Julien Montmartin, and Pierre
Rousseau for review and testing.
 
Sebastien Katz, Pierre Rousseau, and Thibaut Mattern made me start this project
as part of a Sega Master System console emulator. That was long ago, back at
university. I hope I will complete a full emulator someday.
 
Feel free to send bug reports, comments, and suggestions to:
 
[email protected]
 
Revision history:

1.1.3 (18th September 2017)

Another gross mistake fixed in the interrupt handling code: In mode 2, the 
interrupt vector wasn't dereferenced! Thank you rootednode for finding and
reporting this issue.

1.1.2 (20th June 2017)

The implementation of the "IM" Interrupt Mode selection instruction was 
completely wrong. The zextests don't check it and it seems that it was never
encountered in the few systems emulated so far. This bug has gone unnoticed 
until now. Thank you Chris Despoinidis for reporting that bug.

1.1.1 (28th February 2017)

I made the wrong assumption that char is signed by default. It is in fact 
implementation (compiler) dependent. So explicit (signed char) casts are now
used instead. Otherwise, with unsigned char compilers, the zextests will have
a few failing CRC checks. In fact, relative jumps will also fail to emulate 
correctly. Thank you SmallRoomLabs for finding and reporting this issue, and 
Mark Allender for verifying it.
 
1.1.0 "first-app" (22th December 2016)

Ten years already! But hopefully, work on the Sega Master System emulator has 
restarted. For the first application of z80emu, redesign its user API, the
original being really bad. Add 2 header files for the user to customize instead
of having to modify z80emu.h, update the documentation: make it clear what 
variables each macro can expect, compute the register decoding tables only once
at reset, and add a (void *) context for interfacing with the system to 
emulate. All these changes should make the API better organized and easier to 
use. 
 
1.0.2 (12th February 2014)
 
Conditional relative jump (JR_DD_E) instructions such as "jr NZ, loop_label"
were not decoded correctly, just a silly bug in a macro to extract bits. The 
zexdoc and zexall exercisers have excellent coverage of ALU instructions, but
they both don't feature a single "JR" instruction! Hence this (very obvious)
bug has gone unnoticed. Thank you Marcelo Dantas.
 
1.0.1 (14th November 2012)
 
Original implementation of zextest used int64_t. In retrospect, this was a poor 
choice. Using double to count cycles is ANSI and has more than enough precision 
to do so. Thank you Chris Pressey.
 
1.0.0 (13th March 2012)
 
Initial commit on github. Actually, the code has been almost entirely written 
during the summer of 2006.

z80emu's People

Contributors

anotherlin avatar cpressey avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

z80emu's Issues

halted state is not kept between emulation calls

Hello. If you run the cpu for N cycles, a HALT instruction occurs, then you run it for more cycles, the next run it will not recall that it is halted. This would not matter if you're interrupting it between two emulation calls, but if you're not, it needs to remember that it is halted. I fixed it by adding a halted flag in the state struct and that flag is set to 0 when the interrupt function is called. You might have a cleaner way of implementing it, so I won't submit a patch.

Inconsistent execution ld sp,ix

I am trying to use this emulator to test a compiler and it looked it was working fine,
but now I am facing some issues when dealing with the stack.

"ld sp, ix" behaves inconsistently depending on the context; which results in wrong sp value.

Mode2 Interrupts

It looks like the mode 2 interrupts implementation is bad. It is actually jumping to the location generated by the interrupt instead of reading the actual address to jump to from that location. I made some modifications to make it dereference that interrupt vector and it seems to work great.

2 instructions in one step

First, thanks for this project, it helps me a lot ^^ I'm trying to create a java z80 just for fun and I'm using z80emu step by step as a reference to correct my emulator and it's a huuuuuuge help to be able to step by step zexdoc and zexall !

But while running zexdoc at step 3115 we have a DI instruction:

1d2e f3             DI
1d2f ed 73 8d 1d    LD (1d8d),SP
1d33 31 05 01       LD SP,0105

step=3115
a=cd f=8b b=00 c=09 d=02 e=03 h=00 l=2c i=00 r=0d ixl=00 ixh=00 iyl=00 iyh=00 
sp=c8f0 pc=1d2e iff1=0 iff2=0 m=0 
mem=f3 ed 73 8d 1d 
stack=2c 00 03 02 09
(hl)=00 (de)=3c (ix)=d3 00 00 00 00 (iy)=d3 00 00 00 00

And at next step, the status is:

step=3116 
a=cd f=8b b=00 c=09 d=02 e=03 h=00 l=2c i=00 r=10 ixl=00 ixh=00 iyl=00 iyh=00 
sp=c8f0 pc=1d33 iff1=0 iff2=0 m=0 
mem=31 05 01 fd e1
stack=2c 00 03 02 09 
(hl)=00 (de)=3c (ix)=d3 00 00 00 00 (iy)=d3 00 00 00 00

PC has moved to address 1d33 instead of 1d2f and R has moved from 0d to 10.
It seems that 2 instructions has been executed instead of just DI.

There is not wrong z80 implementation, but 2 steps have been executed instead of one, is this a design choice ?

Thanks

PC value in context

Hello,

Can you please help me why I got 0x0001 as PC value? Thank you!

https://github.com/iddq/z80emu/blob/master/tnc2.c

 ./tnc2  | head -10
Testing "testfiles/TNC2118A.ROM"...
out: 223 value: . 2, PC: 0x1
out: 223 value: U 85, PC: 0x1
out: 223 value: . 2, PC: 0x1
 in: 223 value: 2
out: 223 value: . 2, PC: 0x1
out: 223 value: . 253, PC: 0x1
out: 223 value: . 2, PC: 0x1
 in: 223 value: 2
 in: 221 value: 0

Assuming that char is signed

Hi, thanks for putting up this project at github. I've currently using it in a project running on a ESP8266 (Xtensa LX106 CPU) and ran in to some troubles with the code expecting that a char is signed in a few places.

The xtensa compiler assumes that a char is signed unsigned.

        int sum1=100; int sum2=100; int sum3=100;
        int value=-5;
        char c=(char)value;
        unsigned uc=(unsigned char)value;   
        signed char sc=(signed char)value;
        sum1+=c;
        sum2+=uc;
        sum3+=sc;
        os_printf("sum+c=%d sum+uc=%d sum+sc=%d\n",sum1,sum2,sum3);
        // ESP8266 --> sum+c=351 sum+uc=351 sum+sc=95
        // GCC X86 --> sum+c=95  sum+uc=351 sum+sc=95

This screwed up the implementation of relative jumps (something that zexall didn't detect!) and also made zexall report failures for the shift and rolls instructions. I spent a good while trying to figure out what what wrong with the shf/rol implementation, but when I by chance discovered the bug in the relative jumps I then realized what was the cause and it was an easy fix to get it all working perfectly.

Would you be interested in a pull request for my fix of these issues?

license

please clarify what is the license in the classical "COPYING" file

Added feature

Not a bug just a new feature i added.

When EI (enable interrupts) occur i need to know if there is an interrupt waiting so i should leave the emulating loop so i added a new function also i am not sure if it is a bug but i also changed the
number_cycles += 4; with number_cycles = elapsed_cycles+4; so the loop will end after 4 cycles.

`
case EI: {
bool c;

							state->iff1 = state->iff2 = 1;

#ifdef Z80_CATCH_EI

							state->status = Z80_STATUS_FLAG_EI;
							goto stop_emulation;

#else

							/* See comment for DI. */

						   // number_cycles += 4;
						   //TODO:Ask if there is an interrupt
						   // getint before exiting
						   Z80_GetInterrupt(c);
						   if (c) {
							number_cycles = elapsed_cycles+4;
						   }
                            break;

#endif

					}

`

on user.h just added a new macro

#define Z80_GetInterrupt(x)
{
(x) = MyZ80->Z_GetInterrupt();
}

MyZ80 is a Delphi class i use to communicate with C++ Builder so people just put there their own function that tells Z80 if there is an interrupt waiting in order to break the emulation.
If i don't use this the emulation is very slow because it exits the loop every 100 cycles which interrupts get enabled and then disabled again on the machine that i emulate.

Anyway i am ok with these changes just letting you know in case you wanted to implement something like that for everyone to use.

Interrupt modes

Hi,

i took the liberty of using your emulator on my project that emulates a 1980s home computer and i think there is a bug on selecting the Interrupt Mode.
The byte that Selects IM 1 are ED 56 and the original code selects IM 0
I replaced that code with this one and it worked ok (haven't tested the other modes):
``
case IM_N: {

							/* "IM 0/1" (0xed prefixed opcodes 0x4e and
                             * 0x6e) is treated like a "IM 0".
							 */

							if ((opcode & 0x08)) //IM2
								state->im = Z80_INTERRUPT_MODE_2;
							else if ((opcode & 0x10))

									state->im = Z80_INTERRUPT_MODE_1;

							else
									state->im = Z80_INTERRUPT_MODE_0;

                            break;

``

Very good work.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.