fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 392 lines 14 kB view raw
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