fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
1/*****************************************************************************
2 * pce *
3 *****************************************************************************/
4
5/*****************************************************************************
6 * File name: src/cpu/e8080/e8080.h *
7 * Created: 2012-11-28 by Hampa Hug <hampa@hampa.ch> *
8 * Copyright: (C) 2012-2025 Hampa Hug <hampa@hampa.ch> *
9 *****************************************************************************/
10
11/*****************************************************************************
12 * This program is free software. You can redistribute it and / or modify it *
13 * under the terms of the GNU General Public License version 2 as published *
14 * by the Free Software Foundation. *
15 * *
16 * This program is distributed in the hope that it will be useful, but *
17 * WITHOUT ANY WARRANTY, without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General *
19 * Public License for more details. *
20 *****************************************************************************/
21
22
23#ifndef PCE_E8080_H
24#define PCE_E8080_H 1
25
26
27#include <stdio.h>
28
29
30#define E8080_FLAG_Z80 1
31
32
33/* CPU flags */
34#define E8080_FLG_C 0x01
35#define E8080_FLG_N 0x02
36#define E8080_FLG_P 0x04
37#define E8080_FLG_3 0x08
38#define E8080_FLG_A 0x10
39#define E8080_FLG_5 0x20
40#define E8080_FLG_Z 0x40
41#define E8080_FLG_S 0x80
42
43
44struct e8080_t;
45
46
47typedef void (*e8080_opcode_f) (struct e8080_t *c);
48
49
50typedef struct e8080_t {
51 unsigned flags;
52
53 unsigned short pc;
54 unsigned short sp;
55 unsigned short ix;
56 unsigned short iy;
57 unsigned char psw;
58 unsigned char psw2;
59 unsigned char reg[8];
60 unsigned char reg2[8];
61 unsigned char i;
62 unsigned char r;
63
64 unsigned char iff;
65 unsigned char iff2;
66
67 unsigned char im;
68
69 unsigned char halt;
70
71 unsigned char int_val;
72 unsigned char nmi_val;
73 unsigned char int_req;
74
75 unsigned int_cnt;
76 unsigned short int_pc;
77
78 void *mem_rd_ext;
79 void *mem_wr_ext;
80
81 unsigned char (*get_uint8) (void *ext, unsigned long addr);
82 void (*set_uint8) (void *ext, unsigned long addr, unsigned char val);
83
84 unsigned char *mem_map_rd[64];
85 unsigned char *mem_map_wr[64];
86
87 void *port_rd_ext;
88 void *port_wr_ext;
89
90 unsigned char (*get_port8) (void *ext, unsigned long addr);
91 void (*set_port8) (void *ext, unsigned long addr, unsigned char val);
92
93 void *hook_exec_ext;
94 int (*hook_exec) (void *ext);
95
96 void *hook_undef_ext;
97 int (*hook_undef) (void *ext, unsigned op);
98
99 void *hook_rst_ext;
100 int (*hook_rst) (void *ext, unsigned n);
101
102 unsigned char inst[4];
103
104 e8080_opcode_f op[256];
105
106 unsigned delay;
107 unsigned long clkcnt;
108 unsigned long inscnt;
109} e8080_t;
110
111
112#define e8080_get_a(c) ((c)->reg[7])
113#define e8080_get_b(c) ((c)->reg[0])
114#define e8080_get_c(c) ((c)->reg[1])
115#define e8080_get_d(c) ((c)->reg[2])
116#define e8080_get_e(c) ((c)->reg[3])
117#define e8080_get_h(c) ((c)->reg[4])
118#define e8080_get_l(c) ((c)->reg[5])
119#define e8080_get_bc(c) e8080_get_rp ((c), 0, 1)
120#define e8080_get_de(c) e8080_get_rp ((c), 2, 3)
121#define e8080_get_hl(c) e8080_get_rp ((c), 4, 5)
122#define e8080_get_pc(c) ((c)->pc)
123#define e8080_get_sp(c) ((c)->sp)
124#define e8080_get_ix(c) ((c)->ix)
125#define e8080_get_iy(c) ((c)->iy)
126#define e8080_get_ixl(c) ((c)->ix & 0xff)
127#define e8080_get_ixh(c) (((c)->ix >> 8) & 0xff)
128#define e8080_get_iyl(c) ((c)->iy & 0xff)
129#define e8080_get_iyh(c) (((c)->iy >> 8) & 0xff)
130#define e8080_get_i(c) ((c)->i)
131#define e8080_get_r(c) ((c)->r)
132#define e8080_get_psw(c) ((c)->psw)
133#define e8080_get_reg8(c, r) ((c)->reg[(r) & 7])
134
135#define e8080_get_a2(c) ((c)->reg2[7]);
136#define e8080_get_b2(c) ((c)->reg2[0]);
137#define e8080_get_c2(c) ((c)->reg2[1]);
138#define e8080_get_d2(c) ((c)->reg2[2]);
139#define e8080_get_e2(c) ((c)->reg2[3]);
140#define e8080_get_h2(c) ((c)->reg2[4]);
141#define e8080_get_l2(c) ((c)->reg2[5]);
142#define e8080_get_psw2(c) ((c)->psw2)
143
144#define e8080_get_halt(c) ((c)->halt)
145#define e8080_get_iff1(c) ((c)->iff)
146#define e8080_get_iff2(c) ((c)->iff2)
147#define e8080_get_im(c) ((c)->im)
148#define e8080_get_int_cnt(c) ((c)->int_cnt)
149#define e8080_get_int_pc(c) ((c)->int_pc)
150
151#define e8080_set_a(c, v) do { (c)->reg[7] = (v) & 0xff; } while (0)
152#define e8080_set_b(c, v) do { (c)->reg[0] = (v) & 0xff; } while (0)
153#define e8080_set_c(c, v) do { (c)->reg[1] = (v) & 0xff; } while (0)
154#define e8080_set_d(c, v) do { (c)->reg[2] = (v) & 0xff; } while (0)
155#define e8080_set_e(c, v) do { (c)->reg[3] = (v) & 0xff; } while (0)
156#define e8080_set_h(c, v) do { (c)->reg[4] = (v) & 0xff; } while (0)
157#define e8080_set_l(c, v) do { (c)->reg[5] = (v) & 0xff; } while (0)
158#define e8080_set_bc(c, v) e8080_set_rp ((c), 0, 1, (v))
159#define e8080_set_de(c, v) e8080_set_rp ((c), 2, 3, (v))
160#define e8080_set_hl(c, v) e8080_set_rp ((c), 4, 5, (v))
161#define e8080_set_pc(c, v) do { (c)->pc = (v) & 0xffff; } while (0)
162#define e8080_set_sp(c, v) do { (c)->sp = (v) & 0xffff; } while (0)
163#define e8080_set_ix(c, v) do { (c)->ix = (v) & 0xffff; } while (0)
164#define e8080_set_iy(c, v) do { (c)->iy = (v) & 0xffff; } while (0)
165#define e8080_set_ixl(c, v) do { (c)->ix = ((c)->ix & 0xff00) | ((v) & 0xff); } while (0)
166#define e8080_set_ixh(c, v) do { (c)->ix = ((c)->ix & 0x00ff) | (((v) & 0xff) << 8); } while (0)
167#define e8080_set_iyl(c, v) do { (c)->iy = ((c)->iy & 0xff00) | ((v) & 0xff); } while (0)
168#define e8080_set_iyh(c, v) do { (c)->iy = ((c)->iy & 0x00ff) | (((v) & 0xff) << 8); } while (0)
169#define e8080_set_i(c, v) do { (c)->i = (v) & 0xff; } while (0)
170#define e8080_set_r(c, v) do { (c)->r = (v) & 0xff; } while (0)
171#define e8080_set_psw(c, v) do { (c)->psw = (v) & 0xff; } while (0)
172#define e8080_set_reg8(c, r, v) do { (c)->reg[(r) & 7] = (v) & 0xff; } while (0)
173
174#define e8080_set_a2(c, v) do { (c)->reg2[7] = (v) & 0xff; } while (0)
175#define e8080_set_b2(c, v) do { (c)->reg2[0] = (v) & 0xff; } while (0)
176#define e8080_set_c2(c, v) do { (c)->reg2[1] = (v) & 0xff; } while (0)
177#define e8080_set_d2(c, v) do { (c)->reg2[2] = (v) & 0xff; } while (0)
178#define e8080_set_e2(c, v) do { (c)->reg2[3] = (v) & 0xff; } while (0)
179#define e8080_set_h2(c, v) do { (c)->reg2[4] = (v) & 0xff; } while (0)
180#define e8080_set_l2(c, v) do { (c)->reg2[5] = (v) & 0xff; } while (0)
181#define e8080_set_psw2(c, v) do { (c)->psw2 = (v) & 0xff; } while (0)
182
183#define e8080_set_halt(c, v) do { (c)->halt = ((v) != 0); } while (0)
184#define e8080_set_iff1(c, v) do { (c)->iff = ((v) != 0); } while (0)
185#define e8080_set_iff2(c, v) do { (c)->iff2 = ((v) != 0); } while (0)
186#define e8080_set_im(c, v) do { (c)->im = (v); } while (0)
187#define e8080_set_int_cnt(c, v) do { (c)->int_cnt = (v); } while (0)
188#define e8080_set_int_pc(c, v) do { (c)->int_pc = (v) & 0xffff; } while (0)
189
190#define e8080_get_cf(c) (((c)->psw & E8080_FLG_C) != 0)
191#define e8080_get_nf(c) (((c)->psw & E8080_FLG_N) != 0)
192#define e8080_get_pf(c) (((c)->psw & E8080_FLG_P) != 0)
193#define e8080_get_af(c) (((c)->psw & E8080_FLG_A) != 0)
194#define e8080_get_zf(c) (((c)->psw & E8080_FLG_Z) != 0)
195#define e8080_get_sf(c) (((c)->psw & E8080_FLG_S) != 0)
196
197#define e8080_set_flag(c, f, v) \
198 do { if (v) (c)->psw |= (f); else (c)->psw &= ~(f); } while (0)
199#define e8080_set_cf(c, v) e8080_set_flag (c, E8080_FLG_C, v)
200#define e8080_set_nf(c, v) e8080_set_flag (c, E8080_FLG_N, v)
201#define e8080_set_pf(c, v) e8080_set_flag (c, E8080_FLG_P, v)
202#define e8080_set_af(c, v) e8080_set_flag (c, E8080_FLG_A, v)
203#define e8080_set_zf(c, v) e8080_set_flag (c, E8080_FLG_Z, v)
204#define e8080_set_sf(c, v) e8080_set_flag (c, E8080_FLG_S, v)
205
206
207static inline
208unsigned e8080_get_rp (const e8080_t *c, unsigned r1, unsigned r2)
209{
210 return (((unsigned) c->reg[r1] << 8) | c->reg[r2]);
211}
212
213static inline
214void e8080_set_rp (e8080_t *c, unsigned r1, unsigned r2, unsigned val)
215{
216 c->reg[r1] = (val >> 8) & 0xff;
217 c->reg[r2] = val & 0xff;
218}
219
220static inline
221unsigned char e8080_get_mem8 (e8080_t *c, unsigned short addr)
222{
223 const unsigned char *p;
224
225 p = c->mem_map_rd[(addr >> 10) & 0x3f];
226
227 if (p != NULL) {
228 return (p[addr & 0x3ff]);
229 }
230
231 return (c->get_uint8 (c->mem_rd_ext, addr));
232}
233
234static inline
235void e8080_set_mem8 (e8080_t *c, unsigned short addr, unsigned char val)
236{
237 unsigned char *p;
238
239 p = c->mem_map_wr[(addr >> 10) & 0x3f];
240
241 if (p != NULL) {
242 p[addr & 0x3ff] = val;
243 }
244 else {
245 c->set_uint8 (c->mem_wr_ext, addr, val);
246 }
247}
248
249static inline
250unsigned short e8080_get_mem16 (e8080_t *c, unsigned short addr)
251{
252 unsigned short val;
253
254 val = e8080_get_mem8 (c, addr) & 0xff;
255 val |= (unsigned) (e8080_get_mem8 (c, addr + 1) & 0xff) << 8;
256
257 return (val);
258}
259
260static inline
261void e8080_set_mem16 (e8080_t *c, unsigned short addr, unsigned short val)
262{
263 e8080_set_mem8 (c, addr, val);
264 e8080_set_mem8 (c, addr + 1, val >> 8);
265}
266
267
268/*****************************************************************************
269 * @short Initialize a 8080 context
270 *****************************************************************************/
271void e8080_init (e8080_t *c);
272
273/*****************************************************************************
274 * @short Create and initialize a new 8080 context
275 *****************************************************************************/
276e8080_t *e8080_new (void);
277
278/*****************************************************************************
279 * @short Free the resources used by a 8080 context
280 *****************************************************************************/
281void e8080_free (e8080_t *c);
282
283/*****************************************************************************
284 * @short Delete a 8080 context
285 *****************************************************************************/
286void e8080_del (e8080_t *c);
287
288void e8080_set_mem_map_rd (e8080_t *c, unsigned addr1, unsigned addr2, unsigned char *p);
289void e8080_set_mem_map_wr (e8080_t *c, unsigned addr1, unsigned addr2, unsigned char *p);
290
291void e8080_set_8080 (e8080_t *c);
292void e8080_set_z80 (e8080_t *c);
293
294/*****************************************************************************
295 * @short Get the CPU flags
296 *****************************************************************************/
297unsigned e8080_get_flags (e8080_t *c);
298
299/*****************************************************************************
300 * @short Set the CPU flags
301 *****************************************************************************/
302void e8080_set_flags (e8080_t *c, unsigned flags);
303
304void e8080_set_mem_read_fct (e8080_t *c, void *ext, void *get8);
305void e8080_set_mem_write_fct (e8080_t *c, void *ext, void *set8);
306void e8080_set_mem_fct (e8080_t *c, void *mem, void *get8, void *set8);
307
308void e8080_set_port_read_fct (e8080_t *c, void *ext, void *get8);
309void e8080_set_port_write_fct (e8080_t *c, void *ext, void *set8);
310void e8080_set_port_fct (e8080_t *c, void *ext, void *get8, void *set8);
311
312void e8080_set_hook_exec_fct (e8080_t *c, void *ext, void *fct);
313void e8080_set_hook_undef_fct (e8080_t *c, void *ext, void *fct);
314void e8080_set_hook_rst_fct (e8080_t *c, void *ext, void *fct);
315
316void e8080_rst (e8080_t *c, unsigned val);
317
318void e8080_set_int (e8080_t *c, unsigned char val);
319
320unsigned char e8080_get_port8 (e8080_t *c, unsigned addr);
321void e8080_set_port8 (e8080_t *c, unsigned addr, unsigned char val);
322
323int e8080_get_reg (e8080_t *c, const char *reg, unsigned long *val);
324int e8080_set_reg (e8080_t *c, const char *reg, unsigned long val);
325
326
327/*****************************************************************************
328 * @short Get the number of executed clock cycles
329 *****************************************************************************/
330unsigned long e8080_get_clock (e8080_t *c);
331
332/*****************************************************************************
333 * @short Get the number of executed instructions
334 *****************************************************************************/
335unsigned long e8080_get_opcnt (e8080_t *c);
336
337/*****************************************************************************
338 * @short Get the current delay
339 *****************************************************************************/
340unsigned e8080_get_delay (e8080_t *c);
341
342
343/*****************************************************************************
344 * @short Reset the 8080
345 *****************************************************************************/
346void e8080_reset (e8080_t *c);
347
348/*****************************************************************************
349 * @short Execute one instruction
350 *****************************************************************************/
351void e8080_execute (e8080_t *c);
352
353/*****************************************************************************
354 * @short Clock the 8080
355 * @param c The 8080 context
356 * @param n The number of clock cycles
357 *****************************************************************************/
358void e8080_clock (e8080_t *c, unsigned n);
359
360
361
362#define E8080_OPF_COND 0x0001
363#define E8080_OPF_JMP 0x0002
364#define E8080_OPF_CALL 0x0004
365#define E8080_OPF_RET 0x0008
366#define E8080_OPF_UND 0x0010
367#define E8080_OPF_Z80 0x0020
368
369typedef struct {
370 unsigned short flags;
371
372 unsigned short pc;
373 unsigned data_cnt;
374 unsigned char data[8];
375
376 char op[16];
377
378 unsigned arg_cnt;
379 char arg[2][16];
380} e8080_disasm_t;
381
382
383void e8080_disasm (e8080_disasm_t *op, const unsigned char *src, unsigned short pc);
384void e8080_disasm_mem (e8080_t *c, e8080_disasm_t *op, unsigned short pc);
385void e8080_disasm_cur (e8080_t *c, e8080_disasm_t *op);
386
387void z80_disasm (e8080_disasm_t *op, const unsigned char *src, unsigned short pc);
388void z80_disasm_mem (e8080_t *c, e8080_disasm_t *op, unsigned short pc);
389void z80_disasm_cur (e8080_t *c, e8080_disasm_t *op);
390
391
392#endif