1 // license:BSD-3-Clause 2 // copyright-holders:Carl 3 #ifndef MAME_CPU_I86_I86_H 4 #define MAME_CPU_I86_I86_H 5 6 #pragma once 7 8 #include <cpu/i386/i386dasm.h> 9 10 ///////////////////////////////////////////////////////////////// 11 12 DECLARE_DEVICE_TYPE(I8086, i8086_cpu_device) 13 DECLARE_DEVICE_TYPE(I8088, i8088_cpu_device) 14 15 #define INPUT_LINE_INT0 INPUT_LINE_IRQ0 16 #define INPUT_LINE_TEST 20 17 18 19 enum 20 { 21 I8086_PC = STATE_GENPC, 22 I8086_IP = 1, I8086_AX, I8086_CX, I8086_DX, I8086_BX, I8086_SP, I8086_BP, I8086_SI, I8086_DI, 23 I8086_AL, I8086_AH, I8086_CL, I8086_CH, I8086_DL, I8086_DH, I8086_BL, I8086_BH, 24 I8086_FLAGS, I8086_ES, I8086_CS, I8086_SS, I8086_DS, 25 I8086_VECTOR, I8086_HALT 26 }; 27 28 29 class i8086_common_cpu_device : public cpu_device, public i386_disassembler::config 30 { 31 public: lock_handler()32 auto lock_handler() { return m_lock_handler.bind(); } 33 34 protected: 35 enum 36 { 37 EXCEPTION, IRET, /* EXCEPTION, iret */ 38 INT3, INT_IMM, INTO_NT, INTO_T, /* intS */ 39 OVERRIDE, /* SEGMENT OVERRIDES */ 40 FLAG_OPS, LAHF, SAHF, /* FLAG OPERATIONS */ 41 AAA, AAS, AAM, AAD, /* ARITHMETIC ADJUSTS */ 42 DAA, DAS, /* DECIMAL ADJUSTS */ 43 CBW, CWD, /* SIGN EXTENSION */ 44 HLT, LOAD_PTR, LEA, NOP, WAIT, XLAT, /* MISC */ 45 46 JMP_SHORT, JMP_NEAR, JMP_FAR, /* DIRECT jmpS */ 47 JMP_R16, JMP_M16, JMP_M32, /* INDIRECT jmpS */ 48 CALL_NEAR, CALL_FAR, /* DIRECT callS */ 49 CALL_R16, CALL_M16, CALL_M32, /* INDIRECT callS */ 50 RET_NEAR, RET_FAR, RET_NEAR_IMM, RET_FAR_IMM, /* RETURNS */ 51 JCC_NT, JCC_T, JCXZ_NT, JCXZ_T, /* CONDITIONAL jmpS */ 52 LOOP_NT, LOOP_T, LOOPE_NT, LOOPE_T, /* LOOPS */ 53 54 IN_IMM8, IN_IMM16, IN_DX8, IN_DX16, /* PORT READS */ 55 OUT_IMM8, OUT_IMM16, OUT_DX8, OUT_DX16, /* PORT WRITES */ 56 57 MOV_RR8, MOV_RM8, MOV_MR8, /* MOVE, 8-BIT */ 58 MOV_RI8, MOV_MI8, /* MOVE, 8-BIT IMMEDIATE */ 59 MOV_RR16, MOV_RM16, MOV_MR16, /* MOVE, 16-BIT */ 60 MOV_RI16, MOV_MI16, /* MOVE, 16-BIT IMMEDIATE */ 61 MOV_AM8, MOV_AM16, MOV_MA8, MOV_MA16, /* MOVE, al/ax MEMORY */ 62 MOV_SR, MOV_SM, MOV_RS, MOV_MS, /* MOVE, SEGMENT REGISTERS */ 63 XCHG_RR8, XCHG_RM8, /* EXCHANGE, 8-BIT */ 64 XCHG_RR16, XCHG_RM16, XCHG_AR16, /* EXCHANGE, 16-BIT */ 65 66 PUSH_R16, PUSH_M16, PUSH_SEG, PUSHF, /* PUSHES */ 67 POP_R16, POP_M16, POP_SEG, POPF, /* POPS */ 68 69 ALU_RR8, ALU_RM8, ALU_MR8, /* alu OPS, 8-BIT */ 70 ALU_RI8, ALU_MI8, ALU_MI8_RO, /* alu OPS, 8-BIT IMMEDIATE */ 71 ALU_RR16, ALU_RM16, ALU_MR16, /* alu OPS, 16-BIT */ 72 ALU_RI16, ALU_MI16, ALU_MI16_RO, /* alu OPS, 16-BIT IMMEDIATE */ 73 ALU_R16I8, ALU_M16I8, ALU_M16I8_RO, /* alu OPS, 16-BIT W/8-BIT IMMEDIATE */ 74 MUL_R8, MUL_R16, MUL_M8, MUL_M16, /* mul */ 75 IMUL_R8, IMUL_R16, IMUL_M8, IMUL_M16, /* imul */ 76 DIV_R8, DIV_R16, DIV_M8, DIV_M16, /* div */ 77 IDIV_R8, IDIV_R16, IDIV_M8, IDIV_M16, /* idiv */ 78 INCDEC_R8, INCDEC_R16, INCDEC_M8, INCDEC_M16, /* inc/dec */ 79 NEGNOT_R8, NEGNOT_R16, NEGNOT_M8, NEGNOT_M16, /* neg/not */ 80 81 ROT_REG_1, ROT_REG_BASE, ROT_REG_BIT, /* REG SHIFT/ROTATE */ 82 ROT_M8_1, ROT_M8_BASE, ROT_M8_BIT, /* M8 SHIFT/ROTATE */ 83 ROT_M16_1, ROT_M16_BASE, ROT_M16_BIT, /* M16 SHIFT/ROTATE */ 84 85 CMPS8, REP_CMPS8_BASE, REP_CMPS8_COUNT, /* cmps 8-BIT */ 86 CMPS16, REP_CMPS16_BASE, REP_CMPS16_COUNT, /* cmps 16-BIT */ 87 SCAS8, REP_SCAS8_BASE, REP_SCAS8_COUNT, /* scas 8-BIT */ 88 SCAS16, REP_SCAS16_BASE, REP_SCAS16_COUNT, /* scas 16-BIT */ 89 LODS8, REP_LODS8_BASE, REP_LODS8_COUNT, /* lods 8-BIT */ 90 LODS16, REP_LODS16_BASE, REP_LODS16_COUNT, /* lods 16-BIT */ 91 STOS8, REP_STOS8_BASE, REP_STOS8_COUNT, /* stos 8-BIT */ 92 STOS16, REP_STOS16_BASE, REP_STOS16_COUNT, /* stos 16-BIT */ 93 MOVS8, REP_MOVS8_BASE, REP_MOVS8_COUNT, /* movs 8-BIT */ 94 MOVS16, REP_MOVS16_BASE, REP_MOVS16_COUNT, /* movs 16-BIT */ 95 96 INS8, REP_INS8_BASE, REP_INS8_COUNT, /* (80186) ins 8-BIT */ 97 INS16, REP_INS16_BASE, REP_INS16_COUNT, /* (80186) ins 16-BIT */ 98 OUTS8, REP_OUTS8_BASE, REP_OUTS8_COUNT, /* (80186) outs 8-BIT */ 99 OUTS16, REP_OUTS16_BASE, REP_OUTS16_COUNT, /* (80186) outs 16-BIT */ 100 PUSH_IMM, PUSHA, POPA, /* (80186) push IMMEDIATE, pusha/popa */ 101 IMUL_RRI8, IMUL_RMI8, /* (80186) imul IMMEDIATE 8-BIT */ 102 IMUL_RRI16, IMUL_RMI16, /* (80186) imul IMMEDIATE 16-BIT */ 103 ENTER0, ENTER1, ENTER_BASE, ENTER_COUNT, LEAVE, /* (80186) enter/leave */ 104 BOUND /* (80186) bound */ 105 }; 106 107 enum SREGS { ES=0, CS, SS, DS }; 108 enum WREGS { AX=0, CX, DX, BX, SP, BP, SI, DI }; 109 110 // construction/destruction 111 i8086_common_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); 112 113 // device-level overrides 114 virtual void device_start() override; 115 virtual void device_reset() override; 116 117 // device_execute_interface overrides execute_min_cycles()118 virtual uint32_t execute_min_cycles() const noexcept override { return 1; } execute_max_cycles()119 virtual uint32_t execute_max_cycles() const noexcept override { return 50; } 120 virtual void execute_set_input(int inputnum, int state) override; execute_input_edge_triggered(int inputnum)121 virtual bool execute_input_edge_triggered(int inputnum) const noexcept override { return inputnum == INPUT_LINE_NMI; } 122 123 // device_disasm_interface overrides 124 virtual std::unique_ptr<util::disasm_interface> create_disassembler() override; 125 virtual int get_mode() const override; 126 127 // device_state_interface overrides 128 virtual void state_import(const device_state_entry &entry) override; 129 virtual void state_string_export(const device_state_entry &entry, std::string &str) const override; 130 131 virtual void interrupt(int int_num, int trap = 1); 132 virtual bool common_op(uint8_t op); 133 134 // Accessing memory and io 135 virtual uint8_t read_byte(uint32_t addr); 136 virtual uint16_t read_word(uint32_t addr); 137 virtual void write_byte(uint32_t addr, uint8_t data); 138 virtual void write_word(uint32_t addr, uint16_t data); 139 virtual uint8_t read_port_byte(uint16_t port); 140 virtual uint16_t read_port_word(uint16_t port); 141 virtual void write_port_byte(uint16_t port, uint8_t data); 142 virtual void write_port_word(uint16_t port, uint16_t data); 143 144 // Executing instructions fetch_op()145 uint8_t fetch_op() { return fetch(); } 146 virtual uint8_t fetch() = 0; 147 inline uint16_t fetch_word(); 148 inline uint8_t repx_op(); 149 150 // Cycles passed while executing instructions 151 inline void CLK(uint8_t op); 152 inline void CLKM(uint8_t op_reg, uint8_t op_mem); 153 154 // Memory handling while executing instructions 155 virtual uint32_t calc_addr(int seg, uint16_t offset, int size, int op, bool override = true); 156 inline uint32_t get_ea(int size, int op); 157 inline void PutbackRMByte(uint8_t data); 158 inline void PutbackRMWord(uint16_t data); 159 inline void RegByte(uint8_t data); 160 inline void RegWord(uint16_t data); 161 inline uint8_t RegByte(); 162 inline uint16_t RegWord(); 163 inline uint16_t GetRMWord(); 164 inline uint16_t GetnextRMWord(); 165 inline uint8_t GetRMByte(); 166 inline void PutMemB(int seg, uint16_t offset, uint8_t data); 167 inline void PutMemW(int seg, uint16_t offset, uint16_t data); 168 inline uint8_t GetMemB(int seg, uint16_t offset); 169 inline uint16_t GetMemW(int seg, uint16_t offset); 170 inline void PutImmRMWord(); 171 inline void PutRMWord(uint16_t val); 172 inline void PutRMByte(uint8_t val); 173 inline void PutImmRMByte(); 174 inline void DEF_br8(); 175 inline void DEF_wr16(); 176 inline void DEF_r8b(); 177 inline void DEF_r16w(); 178 inline void DEF_ald8(); 179 inline void DEF_axd16(); 180 181 // Flags 182 inline void set_CFB(uint32_t x); 183 inline void set_CFW(uint32_t x); 184 inline void set_AF(uint32_t x,uint32_t y,uint32_t z); 185 inline void set_SF(uint32_t x); 186 inline void set_ZF(uint32_t x); 187 inline void set_PF(uint32_t x); 188 inline void set_SZPF_Byte(uint32_t x); 189 inline void set_SZPF_Word(uint32_t x); 190 inline void set_OFW_Add(uint32_t x,uint32_t y,uint32_t z); 191 inline void set_OFB_Add(uint32_t x,uint32_t y,uint32_t z); 192 inline void set_OFW_Sub(uint32_t x,uint32_t y,uint32_t z); 193 inline void set_OFB_Sub(uint32_t x,uint32_t y,uint32_t z); 194 inline uint16_t CompressFlags() const; 195 inline void ExpandFlags(uint16_t f); 196 197 // rep instructions 198 inline void i_insb(); 199 inline void i_insw(); 200 inline void i_outsb(); 201 inline void i_outsw(); 202 inline void i_movsb(); 203 inline void i_movsw(); 204 inline void i_cmpsb(); 205 inline void i_cmpsw(); 206 inline void i_stosb(); 207 inline void i_stosw(); 208 inline void i_lodsb(); 209 inline void i_lodsw(); 210 inline void i_scasb(); 211 inline void i_scasw(); 212 inline void i_popf(); 213 214 // sub implementations 215 inline uint32_t ADDB(); 216 inline uint32_t ADDX(); 217 inline uint32_t SUBB(); 218 inline uint32_t SUBX(); 219 inline void ORB(); 220 inline void ORW(); 221 inline void ANDB(); 222 inline void ANDX(); 223 inline void XORB(); 224 inline void XORW(); 225 inline void ROL_BYTE(); 226 inline void ROL_WORD(); 227 inline void ROR_BYTE(); 228 inline void ROR_WORD(); 229 inline void ROLC_BYTE(); 230 inline void ROLC_WORD(); 231 inline void RORC_BYTE(); 232 inline void RORC_WORD(); 233 inline void SHL_BYTE(uint8_t c); 234 inline void SHL_WORD(uint8_t c); 235 inline void SHR_BYTE(uint8_t c); 236 inline void SHR_WORD(uint8_t c); 237 inline void SHRA_BYTE(uint8_t c); 238 inline void SHRA_WORD(uint8_t c); 239 inline void XchgAXReg(uint8_t reg); 240 inline void IncWordReg(uint8_t reg); 241 inline void DecWordReg(uint8_t reg); 242 inline void PUSH(uint16_t data); 243 inline uint16_t POP(); 244 inline void JMP(bool cond); 245 inline void ADJ4(int8_t param1, int8_t param2); 246 inline void ADJB(int8_t param1, int8_t param2); 247 248 union 249 { /* eight general registers */ 250 uint16_t w[8]; /* viewed as 16 bits registers */ 251 uint8_t b[16]; /* or as 8 bit registers */ 252 } m_regs; 253 254 enum BREGS { 255 AL = NATIVE_ENDIAN_VALUE_LE_BE(0x0, 0x1), 256 AH = NATIVE_ENDIAN_VALUE_LE_BE(0x1, 0x0), 257 CL = NATIVE_ENDIAN_VALUE_LE_BE(0x2, 0x3), 258 CH = NATIVE_ENDIAN_VALUE_LE_BE(0x3, 0x2), 259 DL = NATIVE_ENDIAN_VALUE_LE_BE(0x4, 0x5), 260 DH = NATIVE_ENDIAN_VALUE_LE_BE(0x5, 0x4), 261 BL = NATIVE_ENDIAN_VALUE_LE_BE(0x6, 0x7), 262 BH = NATIVE_ENDIAN_VALUE_LE_BE(0x7, 0x6), 263 SPL = NATIVE_ENDIAN_VALUE_LE_BE(0x8, 0x9), 264 SPH = NATIVE_ENDIAN_VALUE_LE_BE(0x9, 0x8), 265 BPL = NATIVE_ENDIAN_VALUE_LE_BE(0xa, 0xb), 266 BPH = NATIVE_ENDIAN_VALUE_LE_BE(0xb, 0xa), 267 SIL = NATIVE_ENDIAN_VALUE_LE_BE(0xc, 0xd), 268 SIH = NATIVE_ENDIAN_VALUE_LE_BE(0xd, 0xc), 269 DIL = NATIVE_ENDIAN_VALUE_LE_BE(0xe, 0xf), 270 DIH = NATIVE_ENDIAN_VALUE_LE_BE(0xf, 0xe) 271 }; 272 273 enum { 274 I8086_READ, 275 I8086_WRITE, 276 I8086_FETCH, 277 I8086_NONE 278 }; 279 280 uint16_t m_sregs[4]; 281 282 uint16_t m_ip; 283 uint16_t m_prev_ip; 284 285 int32_t m_SignVal; 286 uint32_t m_AuxVal, m_OverVal, m_ZeroVal, m_CarryVal, m_ParityVal; /* 0 or non-0 valued flags */ 287 uint8_t m_TF, m_IF, m_DF; /* 0 or 1 valued flags */ 288 uint8_t m_IOPL, m_NT, m_MF; 289 uint32_t m_int_vector; 290 uint32_t m_pending_irq; 291 uint32_t m_nmi_state; 292 uint32_t m_irq_state; 293 uint8_t m_no_interrupt; 294 uint8_t m_fire_trap; 295 uint8_t m_test_state; 296 297 address_space *m_program, *m_opcodes; 298 memory_access<20, 0, 0, ENDIANNESS_LITTLE>::cache m_cache8; 299 memory_access<20, 1, 0, ENDIANNESS_LITTLE>::cache m_cache16; 300 301 std::function<u8 (offs_t)> m_or8; 302 address_space *m_io; 303 int m_icount; 304 305 uint32_t m_prefix_seg; /* the latest prefix segment */ 306 bool m_seg_prefix; /* prefix segment indicator */ 307 bool m_seg_prefix_next; /* prefix segment for next instruction */ 308 309 uint32_t m_ea; 310 uint16_t m_eo; 311 int m_easeg; 312 313 // Used during execution of instructions 314 uint8_t m_modrm; 315 uint32_t m_dst; 316 uint32_t m_src; 317 uint32_t m_pc; 318 319 // Lookup tables 320 uint8_t m_parity_table[256]; 321 struct { 322 struct { 323 int w[256]; 324 int b[256]; 325 } reg; 326 struct { 327 int w[256]; 328 int b[256]; 329 } RM; 330 } m_Mod_RM; 331 332 uint8_t m_timing[200]; 333 bool m_halt; 334 335 bool m_lock; 336 devcb_write_line m_lock_handler; 337 }; 338 339 class i8086_cpu_device : public i8086_common_cpu_device 340 { 341 public: 342 enum { 343 AS_STACK = AS_OPCODES + 1, 344 AS_CODE, // data reads from CS are still different from opcode fetches 345 AS_EXTRA 346 }; 347 // construction/destruction 348 i8086_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); 349 350 // device_memory_interface overrides 351 virtual space_config_vector memory_space_config() const override; if_handler()352 auto if_handler() { return m_out_if_func.bind(); } esc_opcode_handler()353 auto esc_opcode_handler() { return m_esc_opcode_handler.bind(); } esc_data_handler()354 auto esc_data_handler() { return m_esc_data_handler.bind(); } 355 356 protected: 357 i8086_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int data_bus_size); 358 359 virtual void execute_run() override; 360 virtual void device_start() override; execute_input_lines()361 virtual uint32_t execute_input_lines() const noexcept override { return 1; } 362 virtual uint8_t fetch() override; 363 inline address_space *sreg_to_space(int sreg) const; 364 virtual uint8_t read_byte(uint32_t addr) override; 365 virtual uint16_t read_word(uint32_t addr) override; 366 virtual void write_byte(uint32_t addr, uint8_t data) override; 367 virtual void write_word(uint32_t addr, uint16_t data) override; 368 369 address_space_config m_program_config; 370 address_space_config m_opcodes_config; 371 address_space_config m_stack_config; 372 address_space_config m_code_config; 373 address_space_config m_extra_config; 374 address_space_config m_io_config; 375 static const uint8_t m_i8086_timing[200]; 376 devcb_write_line m_out_if_func; 377 devcb_write32 m_esc_opcode_handler; 378 devcb_write32 m_esc_data_handler; 379 380 address_space *m_stack, *m_code, *m_extra; 381 382 protected: update_pc()383 uint32_t update_pc() { return m_pc = (m_sregs[CS] << 4) + m_ip; } 384 }; 385 386 class i8088_cpu_device : public i8086_cpu_device 387 { 388 public: 389 // construction/destruction 390 i8088_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); 391 }; 392 393 394 #endif // MAME_CPU_I86_I86_H 395