v1.0.0 -> v0.1; Z related update; Removed slot-based callbacks; Small module ABI changes.

This commit is contained in:
redcode
2018-01-28 18:24:18 +01:00
parent 9c9e6a51f1
commit d15fb3625e
6 changed files with 201 additions and 323 deletions

View File

@@ -1,5 +1,5 @@
# Zilog Z80 CPU Emulator
Copyright © 1999-2016 Manuel Sainz de Baranda y Goñi.
Copyright © 1999-2018 Manuel Sainz de Baranda y Goñi.
Released under the terms of the [GNU General Public License v3](http://www.gnu.org/copyleft/gpl.html).
This is a very accurate [Z80](http://en.wikipedia.org/wiki/Zilog_Z80) [emulator](http://en.wikipedia.org/wiki/Emulator) I wrote many years ago. It has been used in several machine emulators by other people and it has been extensivelly tested. It's very fast and small (although there are faster ones written in assembly), its structure is very clear and the code is commented.
@@ -9,7 +9,7 @@ If you are looking for an accurate Zilog Z80 CPU emulator for your project maybe
## Building
In order to compile you must install [Z](http://github.com/redcode/Z), a **header only** library which provides types, macros, inline functions, and a lot of utilities to detect the particularities of the compiler and the target system. This is the only dependency, the standard C library and its headers are not used and the emulator doesn't need to be dynamically linked with any library.
In order to compile you must install [Z](http://github.com/redcode/Z), a **header only** library which provides types, macros, inline functions, and a lot of utilities to detect the particularities of the compiler and the target system at compile time. This is the only dependency, the standard C library and its headers are not used and the emulator doesn't need to be dynamically linked with any library.
A Xcode project is provided to build the emulator. It has the following targets:
@@ -18,22 +18,19 @@ A Xcode project is provided to build the emulator. It has the following targets:
Name | Description
--- | ---
dynamic | Shared library.
module | Module for A.C.M.E.
dynamic module | Shared library with a module ABI to be used in modular multi-machine emulators.
static | Static library.
static+ABI | Static library with a descriptive ABI to be used in modular multi-machine emulators. Building the ABI implies callback pointers with slots enabled.
static+ABI-API | The same as above but exposing only the symbol of the ABI, the API functions will be private.
static module | Static library with a descriptive ABI to be used in monolithic multi-machine emulators.
#### Constants used in Z80.h
Name | Description
--- | ---
CPU_Z80_STATIC | You need to define this if you are using the emulator as a static library or if you have added its sources to your project.
CPU_Z80_USE_SLOTS | Always needed when using the ABI. Each callback function will have its own context pointer, which should store the address of the object assigned to the call.
#### Constants used in Z80.c
Name | Description
--- | ---
CPU_Z80_DYNAMIC | Needed to build a shared library. Exports the public symbols.
CPU_Z80_BUILD_ABI | Builds the ABI of type `ZCPUEmulatorABI` declared in the header with the identifier `abi_emulation_cpu_z80`.
CPU_Z80_BUILD_MODULE_ABI | Builds a generic module ABI of type `ZModuleABI`. This constant enables `CPU_Z80_BUILD_ABI` automatically so `abi_emulation_cpu_z80` will be build too. This option is intended to be used when building a true module loadable at runtime with `dlopen()`, `LoadLibrary()` or similar. The module ABI can be accessed retrieving the **weak** symbol `__module_abi__`.
CPU_Z80_HIDE_API | Makes the API functions private.
@@ -43,26 +40,6 @@ CPU_Z80_USE_LOCAL_HEADER | Use this if you have imported _Z80.h_ and _Z80.c_ to
## API
#### `z80_run`
**Description**
Runs the CPU for the given number of ```cycles```.
**Prototype**
```C
zsize z80_run(Z80 *object, zsize cycles);
```
**Parameters**
`object` → A pointer to an emulator instance.
`cycles` → The number of cycles to be executed.
**Return value**
The number of cycles executed.
**Discusion**
Given the fact that one Z80 instruction needs between 4 and 23 cycles to be executed, it is not always possible to run the CPU the exact number of cycles specfified.
#### `z80_power`
**Description**
@@ -89,6 +66,26 @@ void z80_reset(Z80 *object);
**Parameters**
`object` → A pointer to an emulator instance.
#### `z80_run`
**Description**
Runs the CPU for the given number of ```cycles```.
**Prototype**
```C
zusize z80_run(Z80 *object, zusize cycles);
```
**Parameters**
`object` → A pointer to an emulator instance.
`cycles` → The number of cycles to be executed.
**Return value**
The number of cycles executed.
**Discusion**
Given the fact that one Z80 instruction needs between 4 and 23 cycles to be executed, it is not always possible to run the CPU the exact number of cycles specfified.
#### `z80_nmi`
**Description**
@@ -220,9 +217,3 @@ ZContextSwitch halt;
**Parameters**
`context` → A pointer to the calling emulator instance.
`state` → `ON` if halted, `OFF` otherwise.
## History
* __[v1.0.0](http://github.com/redcode/Z80/releases/tag/v1.0.0)__ _(2016-09-30)_
* Initial release.

View File

@@ -0,0 +1,60 @@
/* Zilog Z80 CPU Emulator C API
____ ____ ___ ___ ___
/ __ \ / ___\ / __` __`\ / __`\
/\ \/ \/\ \__/_/\ \/\ \/\ \/\ __/
\ \__/\_\ \_____\ \_\ \_\ \_\ \____\
\/_/\/_/\/_____/\/_/\/_/\/_/\/____/
Copyright (C) 1999-2018 Manuel Sainz de Baranda y Goñi.
Released under the terms of the GNU General Public License v3. */
#ifndef __emulation_CPU_Z80_H__
#define __emulation_CPU_Z80_H__
#include <Z/hardware/CPU/architecture/Z80.h>
#include <Z/ABIs/generic/emulation.h>
typedef struct {
zusize cycles;
ZZ80State state;
Z16Bit xy;
zuint8 r7;
Z32Bit data;
void* callback_context;
ZContext16BitAddressRead8Bit read;
ZContext16BitAddressWrite8Bit write;
ZContext16BitAddressRead8Bit in;
ZContext16BitAddressWrite8Bit out;
ZContextRead32Bit int_data;
ZContextSwitch halt;
} Z80;
Z_C_SYMBOLS_BEGIN
#ifndef CPU_Z80_ABI
# ifdef CPU_Z80_STATIC
# define CPU_Z80_ABI
# else
# define CPU_Z80_ABI Z_API
# endif
#endif
CPU_Z80_ABI extern ZCPUEmulatorABI const abi_emulation_cpu_z80;
#ifndef CPU_Z80_API
# ifdef CPU_Z80_STATIC
# define CPU_Z80_API
# else
# define CPU_Z80_API Z_API
# endif
#endif
CPU_Z80_API void z80_power(Z80 *object, zboolean state);
CPU_Z80_API void z80_reset(Z80 *object);
CPU_Z80_API zusize z80_run (Z80 *object, zusize cycles);
CPU_Z80_API void z80_nmi (Z80 *object);
CPU_Z80_API void z80_int (Z80 *object, zboolean state);
Z_C_SYMBOLS_END
#endif /* __emulation_CPU_Z80_H__ */

View File

@@ -8,15 +8,13 @@
/* Begin PBXBuildFile section */
6428A5751AAFC6DF00634F5D /* Z80.h in Headers */ = {isa = PBXBuildFile; fileRef = 6428A5741AAFC6DF00634F5D /* Z80.h */; settings = {ATTRIBUTES = (Public, ); }; };
6428A5771AAFC72900634F5D /* Z80.c in Sources */ = {isa = PBXBuildFile; fileRef = 6428A5761AAFC72900634F5D /* Z80.c */; settings = {COMPILER_FLAGS = "-DCPU_Z80_DYNAMIC"; }; };
6428A5801AAFEF1D00634F5D /* Z80.c in Sources */ = {isa = PBXBuildFile; fileRef = 6428A5761AAFC72900634F5D /* Z80.c */; };
648C13AF1CCDFA8D00C8DCE1 /* Z80.c in Sources */ = {isa = PBXBuildFile; fileRef = 6428A5761AAFC72900634F5D /* Z80.c */; settings = {COMPILER_FLAGS = "-DCPU_Z80_DYNAMIC -DCPU_Z80_BUILD_MODULE_ABI"; }; };
6428A5771AAFC72900634F5D /* Z80.c in Sources */ = {isa = PBXBuildFile; fileRef = 6428A5761AAFC72900634F5D /* Z80.c */; };
6428A5801AAFEF1D00634F5D /* Z80.c in Sources */ = {isa = PBXBuildFile; fileRef = 6428A5761AAFC72900634F5D /* Z80.c */; settings = {COMPILER_FLAGS = "-DCPU_Z80_STATIC"; }; };
648C13AF1CCDFA8D00C8DCE1 /* Z80.c in Sources */ = {isa = PBXBuildFile; fileRef = 6428A5761AAFC72900634F5D /* Z80.c */; settings = {COMPILER_FLAGS = "-DCPU_Z80_BUILD_MODULE_ABI"; }; };
648C13B21CCDFA8D00C8DCE1 /* Z80.h in Headers */ = {isa = PBXBuildFile; fileRef = 6428A5741AAFC6DF00634F5D /* Z80.h */; settings = {ATTRIBUTES = (Public, ); }; };
648C13C31CCDFBEF00C8DCE1 /* Z80.c in Sources */ = {isa = PBXBuildFile; fileRef = 6428A5761AAFC72900634F5D /* Z80.c */; settings = {COMPILER_FLAGS = "-DCPU_Z80_BUILD_ABI"; }; };
648C13CC1CCDFC7700C8DCE1 /* Z80.c in Sources */ = {isa = PBXBuildFile; fileRef = 6428A5761AAFC72900634F5D /* Z80.c */; settings = {COMPILER_FLAGS = "-DCPU_Z80_BUILD_ABI -DCPU_Z80_HIDE_API"; }; };
648C13C31CCDFBEF00C8DCE1 /* Z80.c in Sources */ = {isa = PBXBuildFile; fileRef = 6428A5761AAFC72900634F5D /* Z80.c */; settings = {COMPILER_FLAGS = "-DCPU_Z80_STATIC -DCPU_Z80_BUILD_ABI"; }; };
64F8E3361CD656DA0083A613 /* Z80.h in Headers */ = {isa = PBXBuildFile; fileRef = 6428A5741AAFC6DF00634F5D /* Z80.h */; settings = {ATTRIBUTES = (Public, ); }; };
64F8E3371CD656DB0083A613 /* Z80.h in Headers */ = {isa = PBXBuildFile; fileRef = 6428A5741AAFC6DF00634F5D /* Z80.h */; settings = {ATTRIBUTES = (Public, ); }; };
64F8E3381CD656DB0083A613 /* Z80.h in Headers */ = {isa = PBXBuildFile; fileRef = 6428A5741AAFC6DF00634F5D /* Z80.h */; settings = {ATTRIBUTES = (Public, ); }; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
@@ -26,7 +24,6 @@
6428A57C1AAFEDED00634F5D /* libZ80.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libZ80.a; sourceTree = BUILT_PRODUCTS_DIR; };
648C13B61CCDFA8D00C8DCE1 /* Z80.CPU */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = Z80.CPU; sourceTree = BUILT_PRODUCTS_DIR; };
648C13C91CCDFBEF00C8DCE1 /* libZ80.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libZ80.a; sourceTree = BUILT_PRODUCTS_DIR; };
648C13D21CCDFC7700C8DCE1 /* libZ80.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libZ80.a; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -58,13 +55,6 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
648C13CD1CCDFC7700C8DCE1 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
@@ -84,7 +74,6 @@
6428A57C1AAFEDED00634F5D /* libZ80.a */,
648C13B61CCDFA8D00C8DCE1 /* Z80.CPU */,
648C13C91CCDFBEF00C8DCE1 /* libZ80.a */,
648C13D21CCDFC7700C8DCE1 /* libZ80.a */,
);
name = Products;
sourceTree = "<group>";
@@ -142,14 +131,6 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
648C13CE1CCDFC7700C8DCE1 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
64F8E3381CD656DB0083A613 /* Z80.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
@@ -187,9 +168,9 @@
productReference = 6428A57C1AAFEDED00634F5D /* libZ80.a */;
productType = "com.apple.product-type.library.static";
};
648C13AD1CCDFA8D00C8DCE1 /* Z80 (module) */ = {
648C13AD1CCDFA8D00C8DCE1 /* Z80 (dynamic module) */ = {
isa = PBXNativeTarget;
buildConfigurationList = 648C13B31CCDFA8D00C8DCE1 /* Build configuration list for PBXNativeTarget "Z80 (module)" */;
buildConfigurationList = 648C13B31CCDFA8D00C8DCE1 /* Build configuration list for PBXNativeTarget "Z80 (dynamic module)" */;
buildPhases = (
648C13AE1CCDFA8D00C8DCE1 /* Sources */,
648C13B01CCDFA8D00C8DCE1 /* Frameworks */,
@@ -199,14 +180,14 @@
);
dependencies = (
);
name = "Z80 (module)";
name = "Z80 (dynamic module)";
productName = Z80;
productReference = 648C13B61CCDFA8D00C8DCE1 /* Z80.CPU */;
productType = "com.apple.product-type.library.dynamic";
};
648C13C11CCDFBEF00C8DCE1 /* Z80 (static +ABI) */ = {
648C13C11CCDFBEF00C8DCE1 /* Z80 (static module) */ = {
isa = PBXNativeTarget;
buildConfigurationList = 648C13C61CCDFBEF00C8DCE1 /* Build configuration list for PBXNativeTarget "Z80 (static +ABI)" */;
buildConfigurationList = 648C13C61CCDFBEF00C8DCE1 /* Build configuration list for PBXNativeTarget "Z80 (static module)" */;
buildPhases = (
648C13C21CCDFBEF00C8DCE1 /* Sources */,
648C13C41CCDFBEF00C8DCE1 /* Frameworks */,
@@ -216,28 +197,11 @@
);
dependencies = (
);
name = "Z80 (static +ABI)";
name = "Z80 (static module)";
productName = "Z80-Static";
productReference = 648C13C91CCDFBEF00C8DCE1 /* libZ80.a */;
productType = "com.apple.product-type.library.static";
};
648C13CA1CCDFC7700C8DCE1 /* Z80 (static +ABI -API) */ = {
isa = PBXNativeTarget;
buildConfigurationList = 648C13CF1CCDFC7700C8DCE1 /* Build configuration list for PBXNativeTarget "Z80 (static +ABI -API)" */;
buildPhases = (
648C13CB1CCDFC7700C8DCE1 /* Sources */,
648C13CD1CCDFC7700C8DCE1 /* Frameworks */,
648C13CE1CCDFC7700C8DCE1 /* Headers */,
);
buildRules = (
);
dependencies = (
);
name = "Z80 (static +ABI -API)";
productName = "Z80-Static";
productReference = 648C13D21CCDFC7700C8DCE1 /* libZ80.a */;
productType = "com.apple.product-type.library.static";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
@@ -268,10 +232,9 @@
projectRoot = "";
targets = (
6428A5681AAFC68700634F5D /* Z80 (dynamic) */,
648C13AD1CCDFA8D00C8DCE1 /* Z80 (module) */,
648C13AD1CCDFA8D00C8DCE1 /* Z80 (dynamic module) */,
6428A57B1AAFEDED00634F5D /* Z80 (static) */,
648C13C11CCDFBEF00C8DCE1 /* Z80 (static +ABI) */,
648C13CA1CCDFC7700C8DCE1 /* Z80 (static +ABI -API) */,
648C13C11CCDFBEF00C8DCE1 /* Z80 (static module) */,
);
};
/* End PBXProject section */
@@ -309,14 +272,6 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
648C13CB1CCDFC7700C8DCE1 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
648C13CC1CCDFC7700C8DCE1 /* Z80.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
@@ -324,7 +279,6 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
CLANG_ENABLE_MODULES = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
@@ -365,7 +319,6 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
CLANG_ENABLE_MODULES = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
@@ -477,22 +430,6 @@
};
name = Release;
};
648C13D01CCDFC7700C8DCE1 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
PRODUCT_NAME = Z80;
PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/emulation/CPU;
};
name = Debug;
};
648C13D11CCDFC7700C8DCE1 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
PRODUCT_NAME = Z80;
PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/emulation/CPU;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
@@ -523,7 +460,7 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
648C13B31CCDFA8D00C8DCE1 /* Build configuration list for PBXNativeTarget "Z80 (module)" */ = {
648C13B31CCDFA8D00C8DCE1 /* Build configuration list for PBXNativeTarget "Z80 (dynamic module)" */ = {
isa = XCConfigurationList;
buildConfigurations = (
648C13B41CCDFA8D00C8DCE1 /* Debug */,
@@ -532,7 +469,7 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
648C13C61CCDFBEF00C8DCE1 /* Build configuration list for PBXNativeTarget "Z80 (static +ABI)" */ = {
648C13C61CCDFBEF00C8DCE1 /* Build configuration list for PBXNativeTarget "Z80 (static module)" */ = {
isa = XCConfigurationList;
buildConfigurations = (
648C13C71CCDFBEF00C8DCE1 /* Debug */,
@@ -541,15 +478,6 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
648C13CF1CCDFC7700C8DCE1 /* Build configuration list for PBXNativeTarget "Z80 (static +ABI -API)" */ = {
isa = XCConfigurationList;
buildConfigurations = (
648C13D01CCDFC7700C8DCE1 /* Debug */,
648C13D11CCDFC7700C8DCE1 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 6428A5611AAFC68700634F5D /* Project object */;

View File

@@ -4,30 +4,26 @@
/\ \/ \/\ \__/_/\ \/\ \/\ \/\ __/
\ \__/\_\ \_____\ \_\ \_\ \_\ \____\
\/_/\/_/\/_____/\/_/\/_/\/_/\/____/
Copyright © 1999-2016 Manuel Sainz de Baranda y Goñi.
Copyright (C) 1999-2018 Manuel Sainz de Baranda y Goñi.
Released under the terms of the GNU General Public License v3. */
#include <Z/macros/value.h>
#include <Z/macros/pointer.h>
#if !defined(CPU_Z80_USE_SLOTS) && (defined(CPU_Z80_BUILD_ABI) || defined(CPU_Z80_BUILD_MODULE_ABI))
# define CPU_Z80_USE_SLOTS
#endif
#if defined(CPU_Z80_HIDE_API)
# define CPU_Z80_API static
#elif defined(CPU_Z80_DYNAMIC)
# define CPU_Z80_API Z_API_EXPORT
#else
#elif defined(CPU_Z80_STATIC)
# define CPU_Z80_API
#else
# define CPU_Z80_API Z_API_EXPORT
#endif
#if defined(CPU_Z80_HIDE_ABI)
# define CPU_Z80_ABI static
#elif defined(CPU_Z80_DYNAMIC)
# define CPU_Z80_ABI Z_API_EXPORT
#else
#elif defined(CPU_Z80_STATIC)
# define CPU_Z80_ABI
#else
# define CPU_Z80_ABI Z_API_EXPORT
#endif
#if defined(CPU_Z80_USE_LOCAL_HEADER)
@@ -51,22 +47,14 @@ typedef zuint8 (* Instruction)(Z80 *object);
/* MARK: - Macros & Functions: Callback */
#if defined(CPU_Z80_USE_SLOTS)
# define CB_ACTION(name) object->cb.name.action
# define CB_OBJECT(name) object->cb.name.object
#else
# define CB_ACTION(name) object->cb.name
# define CB_OBJECT(name) object->cb_context
#endif
#define READ_8(address) CB_ACTION(read )(CB_OBJECT(read ), (address) )
#define WRITE_8(address, value) CB_ACTION(write )(CB_OBJECT(write ), (address), (value))
#define IN(port) CB_ACTION(in )(CB_OBJECT(in ), (port ) )
#define OUT(port, value) CB_ACTION(out )(CB_OBJECT(out ), (port ), (value))
#define INT_DATA CB_ACTION(int_data)(CB_OBJECT(int_data) )
#define READ_OFFSET(address) (zint8)READ_8(address)
#define SET_HALT if (CB_ACTION(halt) != NULL) CB_ACTION(halt)(CB_OBJECT(halt), TRUE )
#define CLEAR_HALT if (CB_ACTION(halt) != NULL) CB_ACTION(halt)(CB_OBJECT(halt), FALSE)
#define READ_8(address) object->read (object->callback_context, (address))
#define WRITE_8(address, value) object->write (object->callback_context, (address), (value))
#define IN(port) object->in (object->callback_context, (port))
#define OUT(port, value) object->out (object->callback_context, (port), (value))
#define INT_DATA object->int_data(object->callback_context)
#define READ_OFFSET(address) (zsint8)READ_8(address)
#define SET_HALT if (object->halt != NULL) object->halt(object->callback_context, TRUE )
#define CLEAR_HALT if (object->halt != NULL) object->halt(object->callback_context, FALSE)
Z_INLINE zuint16 read_16bit(Z80 *object, zuint16 address)
@@ -113,7 +101,7 @@ Z_INLINE void write_16bit(Z80 *object, zuint16 address, zuint16 value)
#define IYL object->state.Z_Z80_STATE_MEMBER_IYL
#define I object->state.Z_Z80_STATE_MEMBER_I
#define R object->state.Z_Z80_STATE_MEMBER_R
#define R_ALL (R & 127) | (R7 & 128)
#define R_ALL ((R & 127) | (R7 & 128))
/* MARK: - Macros: Internal State */
@@ -141,7 +129,7 @@ Z_INLINE void write_16bit(Z80 *object, zuint16 address, zuint16 value)
/* MARK: - Macros: Memory Addressing */
#define XY object->xy.value_uint16
#define XY_ADDRESS XY + object->data.array_int8[2]
#define XY_ADDRESS (XY + object->data.array_sint8[2])
/* MARK: - Macros: Flags */
@@ -200,24 +188,24 @@ static zuint8 const pf_parity_table[256] = {
#define PF_PARITY(value) pf_parity_table[value]
#define VF(function, operand) \
Z_INLINE zuint8 pf_overflow_##function##8(zint8 a, zint8 b) \
{ \
zint16 total = a operand b; \
\
return total < -128 || total > 127 ? PF : 0; \
#define VF(function, operand) \
Z_INLINE zuint8 pf_overflow_##function##8(zsint8 a, zsint8 b) \
{ \
zsint16 total = a operand b; \
\
return total < -128 || total > 127 ? PF : 0; \
}
VF(add, +)
VF(sub, -)
#undef VF
#define VF(function, bits, total_bits, operand, minimum, maximum) \
Z_INLINE zuint8 pf_overflow_##function##bits(zint##bits a, zint##bits b, zuint8 carry) \
{ \
zint##total_bits total = a operand b operand carry; \
\
return total < minimum || total > maximum ? PF : 0; \
#define VF(function, bits, total_bits, operand, minimum, maximum) \
Z_INLINE zuint8 pf_overflow_##function##bits(zsint##bits a, zsint##bits b, zuint8 carry) \
{ \
zsint##total_bits total = a operand b operand carry; \
\
return total < minimum || total > maximum ? PF : 0; \
}
VF(adc, 8, 16, +, -128, 127)
@@ -226,7 +214,7 @@ VF(adc, 16, 32, +, -32768, 32767)
VF(sbc, 16, 32, -, -32768, 32767)
/* MARK: - 8 Bit Register Resolution
/* MARK: - 8-Bit Register Resolution
.----------. .---------. .-----------. .-----------.
| 76543210 | | X / Y | | J / K | | P / Q |
@@ -275,7 +263,7 @@ R_8(__jjj___ , j_k_p_q_table, 1, 56, >> 3)
R_8(_____kkk , j_k_p_q_table, 1, 7, )
/* MARK: - 16 Bit Register Resolution
/* MARK: - 16-Bit Register Resolution
.----------. .---------. .---------. .---------.
| 76543210 | | S | | T | | W |
@@ -343,7 +331,7 @@ Z_INLINE zboolean __zzz___(Z80 *object)
}
/* MARK: - 8 Bit Arithmetic and Logical Operation Resolution and Execution
/* MARK: - 8-Bit Arithmetic and Logical Operation Resolution and Execution
.----------. .-----------. .-------------------------------.
| 76543210 | | U | | S | Z | Y | H | X | P | N | C |
@@ -803,7 +791,7 @@ Z_INLINE void add_RR_NN(Z80 *object, zuint16 *r, zuint16 v)
#define RET PC = READ_16(SP); SP += 2;
/* MARK: - Instructions: 8 Bit Load Group
/* MARK: - Instructions: 8-Bit Load Group
.---------------------------------------------------------------------------.
| 0 1 2 3 Flags |
| Assembly 76543210765432107654321076543210 szyhxpnc Cycles |
@@ -857,7 +845,7 @@ INSTRUCTION(ld_i_a) {PC += 2; I = A; return 9;}
INSTRUCTION(ld_r_a) {PC += 2; R = R7 = A; return 9;}
/* MARK: - Instructions: 16 Bit Load Group
/* MARK: - Instructions: 16-Bit Load Group
.---------------------------------------------------------------------------.
| 0 1 2 3 Flags |
| Assembly 76543210765432107654321076543210 szyhxpnc Cycles |
@@ -936,7 +924,7 @@ INSTRUCTION(cpd) {PC += 2; CPX (--) return 16;}
INSTRUCTION(cpdr) {PC += 2; CPXR(--) }
/* MARK: - Instructions: 8 Bit Arithmetic and Logical Group
/* MARK: - Instructions: 8-Bit Arithmetic and Logical Group
.---------------------------------------------------------------------------.
| 0 1 2 3 Flags |
| Assembly 76543210765432107654321076543210 szyhxpnc Cycles |
@@ -1087,7 +1075,7 @@ INSTRUCTION(scf)
}
/* MARK: - Instructions: 16 Bit Arithmetic Group
/* MARK: - Instructions: 16-Bit Arithmetic Group
.---------------------------------------------------------------------------.
| 0 1 2 3 Flags |
| Assembly 76543210765432107654321076543210 szyhxpnc Cycles |
@@ -1410,7 +1398,65 @@ INSTRUCTION(ED_illegal) {PC += 2; return 8;}
/* MARK: - Main Functions */
CPU_Z80_API zsize z80_run(Z80 *object, zsize cycles)
CPU_Z80_API void z80_power(Z80 *object, zboolean state)
{
if (state)
{
# ifdef Z_Z80_RESET_IS_EQUAL_TO_POWER_ON
z80_reset(object);
# else
PC = Z_Z80_VALUE_AFTER_POWER_ON_PC;
SP = Z_Z80_VALUE_AFTER_POWER_ON_SP;
IX = Z_Z80_VALUE_AFTER_POWER_ON_IX;
IY = Z_Z80_VALUE_AFTER_POWER_ON_IY;
AF = Z_Z80_VALUE_AFTER_POWER_ON_AF;
BC = Z_Z80_VALUE_AFTER_POWER_ON_BC;
DE = Z_Z80_VALUE_AFTER_POWER_ON_DE;
HL = Z_Z80_VALUE_AFTER_POWER_ON_HL;
AF_ = Z_Z80_VALUE_AFTER_POWER_ON_AF_;
BC_ = Z_Z80_VALUE_AFTER_POWER_ON_BC_;
DE_ = Z_Z80_VALUE_AFTER_POWER_ON_DE_;
HL_ = Z_Z80_VALUE_AFTER_POWER_ON_HL_;
R = Z_Z80_VALUE_AFTER_POWER_ON_R;
I = Z_Z80_VALUE_AFTER_POWER_ON_I;
IFF1 = Z_Z80_VALUE_AFTER_POWER_ON_IFF1;
IFF2 = Z_Z80_VALUE_AFTER_POWER_ON_IFF2;
IM = Z_Z80_VALUE_AFTER_POWER_ON_IM;
EI = HALT = INT = NMI = 0;
# endif
}
else PC = SP = IX = IY = AF = BC = DE = HL = AF_ = BC_ = DE_ = HL_ = I = R =
IFF1 = IFF2 = IM = EI = HALT = INT = NMI = 0;
}
CPU_Z80_API void z80_reset(Z80 *object)
{
PC = Z_Z80_VALUE_AFTER_RESET_PC;
SP = Z_Z80_VALUE_AFTER_RESET_SP;
IX = Z_Z80_VALUE_AFTER_RESET_IX;
IY = Z_Z80_VALUE_AFTER_RESET_IY;
AF = Z_Z80_VALUE_AFTER_RESET_AF;
BC = Z_Z80_VALUE_AFTER_RESET_BC;
DE = Z_Z80_VALUE_AFTER_RESET_DE;
HL = Z_Z80_VALUE_AFTER_RESET_HL;
AF_ = Z_Z80_VALUE_AFTER_RESET_AF_;
BC_ = Z_Z80_VALUE_AFTER_RESET_BC_;
DE_ = Z_Z80_VALUE_AFTER_RESET_DE_;
HL_ = Z_Z80_VALUE_AFTER_RESET_HL_;
R = Z_Z80_VALUE_AFTER_RESET_R;
I = Z_Z80_VALUE_AFTER_RESET_I;
IFF1 = Z_Z80_VALUE_AFTER_RESET_IFF1;
IFF2 = Z_Z80_VALUE_AFTER_RESET_IFF2;
IM = Z_Z80_VALUE_AFTER_RESET_IM;
EI = HALT = INT = NMI = 0;
}
CPU_Z80_API zusize z80_run(Z80 *object, zusize cycles)
{
zuint32 data;
@@ -1533,64 +1579,6 @@ CPU_Z80_API zsize z80_run(Z80 *object, zsize cycles)
}
CPU_Z80_API void z80_reset(Z80 *object)
{
PC = Z_Z80_VALUE_AFTER_RESET_PC;
SP = Z_Z80_VALUE_AFTER_RESET_SP;
IX = Z_Z80_VALUE_AFTER_RESET_IX;
IY = Z_Z80_VALUE_AFTER_RESET_IY;
AF = Z_Z80_VALUE_AFTER_RESET_AF;
BC = Z_Z80_VALUE_AFTER_RESET_BC;
DE = Z_Z80_VALUE_AFTER_RESET_DE;
HL = Z_Z80_VALUE_AFTER_RESET_HL;
AF_ = Z_Z80_VALUE_AFTER_RESET_AF_;
BC_ = Z_Z80_VALUE_AFTER_RESET_BC_;
DE_ = Z_Z80_VALUE_AFTER_RESET_DE_;
HL_ = Z_Z80_VALUE_AFTER_RESET_HL_;
R = Z_Z80_VALUE_AFTER_RESET_R;
I = Z_Z80_VALUE_AFTER_RESET_I;
IFF1 = Z_Z80_VALUE_AFTER_RESET_IFF1;
IFF2 = Z_Z80_VALUE_AFTER_RESET_IFF2;
IM = Z_Z80_VALUE_AFTER_RESET_IM;
EI = HALT = INT = NMI = 0;
}
CPU_Z80_API void z80_power(Z80 *object, zboolean state)
{
if (state)
{
# ifdef Z_Z80_RESET_IS_EQUAL_TO_POWER_ON
z80_reset(object);
# else
PC = Z_Z80_VALUE_AFTER_POWER_ON_PC;
SP = Z_Z80_VALUE_AFTER_POWER_ON_SP;
IX = Z_Z80_VALUE_AFTER_POWER_ON_IX;
IY = Z_Z80_VALUE_AFTER_POWER_ON_IY;
AF = Z_Z80_VALUE_AFTER_POWER_ON_AF;
BC = Z_Z80_VALUE_AFTER_POWER_ON_BC;
DE = Z_Z80_VALUE_AFTER_POWER_ON_DE;
HL = Z_Z80_VALUE_AFTER_POWER_ON_HL;
AF_ = Z_Z80_VALUE_AFTER_POWER_ON_AF_;
BC_ = Z_Z80_VALUE_AFTER_POWER_ON_BC_;
DE_ = Z_Z80_VALUE_AFTER_POWER_ON_DE_;
HL_ = Z_Z80_VALUE_AFTER_POWER_ON_HL_;
R = Z_Z80_VALUE_AFTER_POWER_ON_R;
I = Z_Z80_VALUE_AFTER_POWER_ON_I;
IFF1 = Z_Z80_VALUE_AFTER_POWER_ON_IFF1;
IFF2 = Z_Z80_VALUE_AFTER_POWER_ON_IFF2;
IM = Z_Z80_VALUE_AFTER_POWER_ON_IM;
EI = HALT = INT = NMI = 0;
# endif
}
else PC = SP = IX = IY = AF = BC = DE = HL = AF_ = BC_ = DE_ = HL_ = I = R =
IFF1 = IFF2 = IM = EI = HALT = INT = NMI = 0;
}
CPU_Z80_API void z80_nmi(Z80 *object) {NMI = TRUE ;}
CPU_Z80_API void z80_int(Z80 *object, zboolean state) {INT = state;}
@@ -1612,15 +1600,13 @@ CPU_Z80_API void z80_int(Z80 *object, zboolean state) {INT = state;}
{Z_EMULATOR_FUNCTION_IRQ, (ZEmulatorFunction)z80_int }
};
# define SLOT_OFFSET(name) Z_OFFSET_OF(Z80, cb.name)
static ZCPUEmulatorInstanceImport const instance_imports[6] = {
{Z_EMULATOR_FUNCTION_READ_8BIT, SLOT_OFFSET(read )},
{Z_EMULATOR_FUNCTION_WRITE_8BIT, SLOT_OFFSET(write )},
{Z_EMULATOR_FUNCTION_IN_8BIT, SLOT_OFFSET(in )},
{Z_EMULATOR_FUNCTION_OUT_8BIT, SLOT_OFFSET(out )},
{Z_EMULATOR_FUNCTION_IRQ_DATA, SLOT_OFFSET(int_data)},
{Z_EMULATOR_FUNCTION_HALT, SLOT_OFFSET(halt )}
{Z_EMULATOR_FUNCTION_READ_8BIT, O(read )},
{Z_EMULATOR_FUNCTION_WRITE_8BIT, O(write )},
{Z_EMULATOR_FUNCTION_IN_8BIT, O(in )},
{Z_EMULATOR_FUNCTION_OUT_8BIT, O(out )},
{Z_EMULATOR_FUNCTION_IRQ_DATA, O(int_data)},
{Z_EMULATOR_FUNCTION_HALT, O(halt )}
};
CPU_Z80_ABI ZCPUEmulatorABI const abi_emulation_cpu_z80 = {
@@ -1629,7 +1615,7 @@ CPU_Z80_API void z80_int(Z80 *object, zboolean state) {INT = state;}
/* export_count */ 7,
/* exports */ exports,
/* instance_size */ sizeof(Z80),
/* instance_state_offset */ Z_OFFSET_OF(Z80, state),
/* instance_state_offset */ O(state),
/* instance_state_size */ sizeof(ZZ80State),
/* instance_import_count */ 6,
/* instance_imports */ instance_imports
@@ -1641,11 +1627,7 @@ CPU_Z80_API void z80_int(Z80 *object, zboolean state) {INT = state;}
# include <Z/ABIs/generic/module.h>
static zcharacter const information[] =
"C1999-2016 Manuel Sainz de Baranda y Goñi\n"
"LGPLv3";
static ZModuleUnit const unit = {"Z80", "Z80", Z_VERSION(1, 0, 0), information, &abi_emulation_cpu_z80};
static ZModuleUnit const unit = {"Z80", "Z80", Z_VERSION(0, 1, 0), &abi_emulation_cpu_z80};
static ZModuleDomain const domain = {"Emulation.CPU", Z_VERSION(1, 0, 0), 1, &unit};
Z_API_WEAK_EXPORT ZModuleABI const __module_abi__ = {1, &domain};

View File

@@ -1,83 +0,0 @@
/* Zilog Z80 CPU Emulator C API
____ ____ ___ ___ ___
/ __ \ / ___\ / __` __`\ / __`\
/\ \/ \/\ \__/_/\ \/\ \/\ \/\ __/
\ \__/\_\ \_____\ \_\ \_\ \_\ \____\
\/_/\/_/\/_____/\/_/\/_/\/_/\/____/
Copyright © 1999-2016 Manuel Sainz de Baranda y Goñi.
Released under the terms of the GNU General Public License v3. */
#ifndef __emulation_CPU_Z80_H__
#define __emulation_CPU_Z80_H__
#include <Z/hardware/CPU/architecture/Z80.h>
#include <Z/ABIs/generic/emulation.h>
#ifdef CPU_Z80_USE_SLOTS
# include <Z/macros/slot.h>
#endif
typedef struct {
zsize cycles;
ZZ80State state;
Z16Bit xy;
zuint8 r7;
Z32Bit data;
# ifdef CPU_Z80_USE_SLOTS
struct {ZSlot(ZContext16BitAddressRead8Bit ) read;
ZSlot(ZContext16BitAddressWrite8Bit) write;
ZSlot(ZContext16BitAddressRead8Bit ) in;
ZSlot(ZContext16BitAddressWrite8Bit) out;
ZSlot(ZContextRead32Bit ) int_data;
ZSlot(ZContextSwitch ) halt;
} cb;
# else
void* cb_context;
struct {ZContext16BitAddressRead8Bit read;
ZContext16BitAddressWrite8Bit write;
ZContext16BitAddressRead8Bit in;
ZContext16BitAddressWrite8Bit out;
ZContextRead32Bit int_data;
ZContextSwitch halt;
} cb;
# endif
} Z80;
Z_C_SYMBOLS_BEGIN
#ifndef CPU_Z80_ABI
# ifdef CPU_Z80_STATIC
# define CPU_Z80_ABI
# else
# define CPU_Z80_ABI Z_API
# endif
#endif
CPU_Z80_ABI extern ZCPUEmulatorABI const abi_emulation_cpu_z80;
#ifndef CPU_Z80_API
# ifdef CPU_Z80_STATIC
# define CPU_Z80_API
# else
# define CPU_Z80_API Z_API
# endif
#endif
CPU_Z80_API zsize z80_run (Z80* object,
zsize cycles);
CPU_Z80_API void z80_power (Z80* object,
zboolean state);
CPU_Z80_API void z80_reset (Z80* object);
CPU_Z80_API void z80_nmi (Z80* object);
CPU_Z80_API void z80_int (Z80* object,
zboolean state);
Z_C_SYMBOLS_END
#endif /* __emulation_CPU_Z80_H__ */