1 |
dpavlin |
111 |
/** Z80: portable Z80 emulator *******************************/ |
2 |
|
|
/** **/ |
3 |
|
|
/** Z80.h **/ |
4 |
|
|
/** **/ |
5 |
|
|
/** This file contains declarations relevant to emulation **/ |
6 |
|
|
/** of Z80 CPU. **/ |
7 |
|
|
/** **/ |
8 |
|
|
/** Copyright (C) Marat Fayzullin 1994-2007 **/ |
9 |
|
|
/** You are not allowed to distribute this software **/ |
10 |
|
|
/** commercially. Please, notify me, if you make any **/ |
11 |
|
|
/** changes to this file. **/ |
12 |
|
|
/*************************************************************/ |
13 |
|
|
#ifndef Z80_H |
14 |
|
|
#define Z80_H |
15 |
|
|
|
16 |
|
|
/* Compilation options: */ |
17 |
|
|
/* #define DEBUG */ /* Compile debugging version */ |
18 |
|
|
/* #define LSB_FIRST */ /* Compile for low-endian CPU */ |
19 |
|
|
/* #define MSB_FIRST */ /* Compile for hi-endian CPU */ |
20 |
|
|
|
21 |
|
|
/* LoopZ80() may return: */ |
22 |
|
|
#define INT_RST00 0x00C7 /* RST 00h */ |
23 |
|
|
#define INT_RST08 0x00CF /* RST 08h */ |
24 |
|
|
#define INT_RST10 0x00D7 /* RST 10h */ |
25 |
|
|
#define INT_RST18 0x00DF /* RST 18h */ |
26 |
|
|
#define INT_RST20 0x00E7 /* RST 20h */ |
27 |
|
|
#define INT_RST28 0x00EF /* RST 28h */ |
28 |
|
|
#define INT_RST30 0x00F7 /* RST 30h */ |
29 |
|
|
#define INT_RST38 0x00FF /* RST 38h */ |
30 |
|
|
#define INT_IRQ INT_RST38 /* Default IRQ opcode is FFh */ |
31 |
|
|
#define INT_NMI 0xFFFD /* Non-maskable interrupt */ |
32 |
|
|
#define INT_NONE 0xFFFF /* No interrupt required */ |
33 |
|
|
#define INT_QUIT 0xFFFE /* Exit the emulation */ |
34 |
|
|
|
35 |
|
|
/* Bits in Z80 F register: */ |
36 |
|
|
#define S_FLAG 0x80 /* 1: Result negative */ |
37 |
|
|
#define Z_FLAG 0x40 /* 1: Result is zero */ |
38 |
|
|
#define H_FLAG 0x10 /* 1: Halfcarry/Halfborrow */ |
39 |
|
|
#define P_FLAG 0x04 /* 1: Result is even */ |
40 |
|
|
#define V_FLAG 0x04 /* 1: Overflow occured */ |
41 |
|
|
#define N_FLAG 0x02 /* 1: Subtraction occured */ |
42 |
|
|
#define C_FLAG 0x01 /* 1: Carry/Borrow occured */ |
43 |
|
|
|
44 |
|
|
/* Bits in IFF flip-flops: */ |
45 |
|
|
#define IFF_1 0x01 /* IFF1 flip-flop */ |
46 |
|
|
#define IFF_IM1 0x02 /* 1: IM1 mode */ |
47 |
|
|
#define IFF_IM2 0x04 /* 1: IM2 mode */ |
48 |
|
|
#define IFF_2 0x08 /* IFF2 flip-flop */ |
49 |
|
|
#define IFF_EI 0x20 /* 1: EI pending */ |
50 |
|
|
#define IFF_HALT 0x80 /* 1: CPU HALTed */ |
51 |
|
|
|
52 |
|
|
/** Simple Datatypes *****************************************/ |
53 |
|
|
/** NOTICE: sizeof(byte)=1 and sizeof(word)=2 **/ |
54 |
|
|
/*************************************************************/ |
55 |
|
|
#ifndef BYTE_TYPE_DEFINED |
56 |
|
|
#define BYTE_TYPE_DEFINED |
57 |
|
|
typedef unsigned char byte; |
58 |
|
|
#endif |
59 |
|
|
#ifndef WORD_TYPE_DEFINED |
60 |
|
|
#define WORD_TYPE_DEFINED |
61 |
|
|
typedef unsigned short word; |
62 |
|
|
#endif |
63 |
|
|
typedef signed char offset; |
64 |
|
|
|
65 |
|
|
/** Structured Datatypes *************************************/ |
66 |
|
|
/** NOTICE: #define LSB_FIRST for machines where least **/ |
67 |
|
|
/** signifcant byte goes first. **/ |
68 |
|
|
/*************************************************************/ |
69 |
|
|
typedef union |
70 |
|
|
{ |
71 |
|
|
#ifdef LSB_FIRST |
72 |
|
|
struct { byte l,h; } B; |
73 |
|
|
#else |
74 |
|
|
struct { byte h,l; } B; |
75 |
|
|
#endif |
76 |
|
|
word W; |
77 |
|
|
} pair; |
78 |
|
|
|
79 |
|
|
typedef struct |
80 |
|
|
{ |
81 |
|
|
pair AF,BC,DE,HL,IX,IY,PC,SP; /* Main registers */ |
82 |
|
|
pair AF1,BC1,DE1,HL1; /* Shadow registers */ |
83 |
|
|
byte IFF,I; /* Interrupt registers */ |
84 |
|
|
byte R; /* Refresh register */ |
85 |
|
|
|
86 |
|
|
int IPeriod,ICount; /* Set IPeriod to number of CPU cycles */ |
87 |
|
|
/* between calls to LoopZ80() */ |
88 |
|
|
int IBackup; /* Private, don't touch */ |
89 |
|
|
word IRequest; /* Set to address of pending IRQ */ |
90 |
|
|
byte IAutoReset; /* Set to 1 to autom. reset IRequest */ |
91 |
|
|
byte TrapBadOps; /* Set to 1 to warn of illegal opcodes */ |
92 |
|
|
word Trap; /* Set Trap to address to trace from */ |
93 |
|
|
byte Trace; /* Set Trace=1 to start tracing */ |
94 |
|
|
void *User; /* Arbitrary user data (ID,RAM*,etc.) */ |
95 |
|
|
} Z80; |
96 |
|
|
|
97 |
|
|
/** ResetZ80() ***********************************************/ |
98 |
|
|
/** This function can be used to reset the registers before **/ |
99 |
|
|
/** starting execution with RunZ80(). It sets registers to **/ |
100 |
|
|
/** their initial values. **/ |
101 |
|
|
/*************************************************************/ |
102 |
|
|
void ResetZ80(register Z80 *R); |
103 |
|
|
|
104 |
|
|
/** ExecZ80() ************************************************/ |
105 |
|
|
/** This function will execute given number of Z80 cycles. **/ |
106 |
|
|
/** It will then return the number of cycles left, possibly **/ |
107 |
|
|
/** negative, and current register values in R. **/ |
108 |
|
|
/*************************************************************/ |
109 |
|
|
#ifdef EXECZ80 |
110 |
|
|
int ExecZ80(register Z80 *R,register int RunCycles); |
111 |
|
|
#endif |
112 |
|
|
|
113 |
|
|
/** IntZ80() *************************************************/ |
114 |
|
|
/** This function will generate interrupt of given vector. **/ |
115 |
|
|
/*************************************************************/ |
116 |
|
|
void IntZ80(register Z80 *R,register word Vector); |
117 |
|
|
|
118 |
|
|
/** RunZ80() *************************************************/ |
119 |
|
|
/** This function will run Z80 code until an LoopZ80() call **/ |
120 |
|
|
/** returns INT_QUIT. It will return the PC at which **/ |
121 |
|
|
/** emulation stopped, and current register values in R. **/ |
122 |
|
|
/*************************************************************/ |
123 |
|
|
#ifndef EXECZ80 |
124 |
|
|
word RunZ80(register Z80 *R); |
125 |
|
|
#endif |
126 |
|
|
|
127 |
|
|
/** RdZ80()/WrZ80() ******************************************/ |
128 |
|
|
/** These functions are called when access to RAM occurs. **/ |
129 |
|
|
/** They allow to control memory access. **/ |
130 |
|
|
/************************************ TO BE WRITTEN BY USER **/ |
131 |
|
|
void WrZ80(register word Addr,register byte Value); |
132 |
|
|
byte RdZ80(register word Addr); |
133 |
|
|
|
134 |
|
|
/** InZ80()/OutZ80() *****************************************/ |
135 |
|
|
/** Z80 emulation calls these functions to read/write from **/ |
136 |
|
|
/** I/O ports. There can be 65536 I/O ports, but only first **/ |
137 |
|
|
/** 256 are usually used. **/ |
138 |
|
|
/************************************ TO BE WRITTEN BY USER **/ |
139 |
|
|
void OutZ80(register word Port,register byte Value); |
140 |
|
|
byte InZ80(register word Port); |
141 |
|
|
|
142 |
|
|
/** PatchZ80() ***********************************************/ |
143 |
|
|
/** Z80 emulation calls this function when it encounters a **/ |
144 |
|
|
/** special patch command (ED FE) provided for user needs. **/ |
145 |
|
|
/** For example, it can be called to emulate BIOS calls, **/ |
146 |
|
|
/** such as disk and tape access. Replace it with an empty **/ |
147 |
|
|
/** macro for no patching. **/ |
148 |
|
|
/************************************ TO BE WRITTEN BY USER **/ |
149 |
|
|
void PatchZ80(register Z80 *R); |
150 |
|
|
|
151 |
|
|
/** DebugZ80() ***********************************************/ |
152 |
|
|
/** This function should exist if DEBUG is #defined. When **/ |
153 |
|
|
/** Trace!=0, it is called after each command executed by **/ |
154 |
|
|
/** the CPU, and given the Z80 registers. Emulation exits **/ |
155 |
|
|
/** if DebugZ80() returns 0. **/ |
156 |
|
|
/*************************************************************/ |
157 |
|
|
#ifdef DEBUG |
158 |
|
|
byte DebugZ80(register Z80 *R); |
159 |
|
|
#endif |
160 |
|
|
|
161 |
|
|
/** LoopZ80() ************************************************/ |
162 |
|
|
/** Z80 emulation calls this function periodically to check **/ |
163 |
|
|
/** if the system hardware requires any interrupts. This **/ |
164 |
|
|
/** function must return an address of the interrupt vector **/ |
165 |
|
|
/** (0x0038, 0x0066, etc.) or INT_NONE for no interrupt. **/ |
166 |
|
|
/** Return INT_QUIT to exit the emulation loop. **/ |
167 |
|
|
/************************************ TO BE WRITTEN BY USER **/ |
168 |
|
|
word LoopZ80(register Z80 *R); |
169 |
|
|
|
170 |
|
|
/** JumpZ80() ************************************************/ |
171 |
|
|
/** Z80 emulation calls this function when it executes a **/ |
172 |
|
|
/** JP, JR, CALL, RST, or RET. You can use JumpZ80() to **/ |
173 |
|
|
/** trap these opcodes and switch memory layout. **/ |
174 |
|
|
/************************************ TO BE WRITTEN BY USER **/ |
175 |
|
|
#ifndef JUMPZ80 |
176 |
|
|
#define JumpZ80(PC) |
177 |
|
|
#else |
178 |
|
|
void JumpZ80(word PC); |
179 |
|
|
#endif |
180 |
|
|
|
181 |
|
|
#endif /* Z80_H */ |