2 Skelton for retropc emulator
5 Author : Takeda.Toshiya
11 #if defined(_MSC_VER) && (_MSC_VER >= 1400)
12 #pragma warning( disable : 4146 )
13 #pragma warning( disable : 4996 )
21 #define DIVIDE_FAULT 0
22 #define NMI_INT_VECTOR 2
23 #define OVERFLOW_TRAP 4
24 #define BOUNDS_CHECK_FAULT 5
25 #define ILLEGAL_INSTRUCTION 6
26 #define GENERAL_PROTECTION_FAULT 13
31 typedef enum { ES, CS, SS, DS } SREGS;
32 typedef enum { AX, CX, DX, BX, SP, BP, SI, DI } WREGS;
36 AH, AL, CH, CL, DH, DL, BH, BL,
37 SPH, SPL, BPH, BPL, SIH, SIL, DIH, DIL,
39 AL, AH, CL, CH, DL, DH, BL, BH,
40 SPL, SPH, BPL, BPH, SIL, SIH, DIL, DIH,
55 static const uint8 parity_table[256] = {
56 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
57 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
58 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
59 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
60 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
61 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
62 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
63 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
64 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
65 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
66 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
67 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
68 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
69 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
70 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
71 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
74 /************************************************************************/
76 struct i80x86_timing {
77 uint8 exception, iret; /* exception, IRET */
78 uint8 int3, int_imm, into_nt, into_t; /* INTs */
79 uint8 override; /* segment overrides */
80 uint8 flag_ops, lahf, sahf; /* flag operations */
81 uint8 aaa, aas, aam, aad; /* arithmetic adjusts */
82 uint8 daa, das; /* decimal adjusts */
83 uint8 cbw, cwd; /* sign extension */
84 uint8 hlt, load_ptr, lea, nop, wait, xlat; /* misc */
86 uint8 jmp_short, jmp_near, jmp_far; /* direct JMPs */
87 uint8 jmp_r16, jmp_m16, jmp_m32; /* indirect JMPs */
88 uint8 call_near, call_far; /* direct CALLs */
89 uint8 call_r16, call_m16, call_m32; /* indirect CALLs */
90 uint8 ret_near, ret_far, ret_near_imm, ret_far_imm; /* returns */
91 uint8 jcc_nt, jcc_t, jcxz_nt, jcxz_t; /* conditional JMPs */
92 uint8 loop_nt, loop_t, loope_nt, loope_t; /* loops */
94 uint8 in_imm8, in_imm16, in_dx8, in_dx16; /* port reads */
95 uint8 out_imm8, out_imm16, out_dx8, out_dx16; /* port writes */
97 uint8 mov_rr8, mov_rm8, mov_mr8; /* move, 8-bit */
98 uint8 mov_ri8, mov_mi8; /* move, 8-bit immediate */
99 uint8 mov_rr16, mov_rm16, mov_mr16; /* move, 16-bit */
100 uint8 mov_ri16, mov_mi16; /* move, 16-bit immediate */
101 uint8 mov_am8, mov_am16, mov_ma8, mov_ma16; /* move, AL/AX memory */
102 uint8 mov_sr, mov_sm, mov_rs, mov_ms; /* move, segment registers */
103 uint8 xchg_rr8, xchg_rm8; /* exchange, 8-bit */
104 uint8 xchg_rr16, xchg_rm16, xchg_ar16; /* exchange, 16-bit */
106 uint8 push_r16, push_m16, push_seg, pushf; /* pushes */
107 uint8 pop_r16, pop_m16, pop_seg, popf; /* pops */
109 uint8 alu_rr8, alu_rm8, alu_mr8; /* ALU ops, 8-bit */
110 uint8 alu_ri8, alu_mi8, alu_mi8_ro; /* ALU ops, 8-bit immediate */
111 uint8 alu_rr16, alu_rm16, alu_mr16; /* ALU ops, 16-bit */
112 uint8 alu_ri16, alu_mi16, alu_mi16_ro; /* ALU ops, 16-bit immediate */
113 uint8 alu_r16i8, alu_m16i8, alu_m16i8_ro; /* ALU ops, 16-bit w/8-bit immediate */
114 uint8 mul_r8, mul_r16, mul_m8, mul_m16; /* MUL */
115 uint8 imul_r8, imul_r16, imul_m8, imul_m16; /* IMUL */
116 uint8 div_r8, div_r16, div_m8, div_m16; /* DIV */
117 uint8 idiv_r8, idiv_r16, idiv_m8, idiv_m16; /* IDIV */
118 uint8 incdec_r8, incdec_r16, incdec_m8, incdec_m16; /* INC/DEC */
119 uint8 negnot_r8, negnot_r16, negnot_m8, negnot_m16; /* NEG/NOT */
121 uint8 rot_reg_1, rot_reg_base, rot_reg_bit; /* reg shift/rotate */
122 uint8 rot_m8_1, rot_m8_base, rot_m8_bit; /* m8 shift/rotate */
123 uint8 rot_m16_1, rot_m16_base, rot_m16_bit; /* m16 shift/rotate */
125 uint8 cmps8, rep_cmps8_base, rep_cmps8_count; /* CMPS 8-bit */
126 uint8 cmps16, rep_cmps16_base, rep_cmps16_count; /* CMPS 16-bit */
127 uint8 scas8, rep_scas8_base, rep_scas8_count; /* SCAS 8-bit */
128 uint8 scas16, rep_scas16_base, rep_scas16_count; /* SCAS 16-bit */
129 uint8 lods8, rep_lods8_base, rep_lods8_count; /* LODS 8-bit */
130 uint8 lods16, rep_lods16_base, rep_lods16_count; /* LODS 16-bit */
131 uint8 stos8, rep_stos8_base, rep_stos8_count; /* STOS 8-bit */
132 uint8 stos16, rep_stos16_base, rep_stos16_count; /* STOS 16-bit */
133 uint8 movs8, rep_movs8_base, rep_movs8_count; /* MOVS 8-bit */
134 uint8 movs16, rep_movs16_base, rep_movs16_count; /* MOVS 16-bit */
136 uint8 ins8, rep_ins8_base, rep_ins8_count; /* (80186) INS 8-bit */
137 uint8 ins16, rep_ins16_base, rep_ins16_count; /* (80186) INS 16-bit */
138 uint8 outs8, rep_outs8_base, rep_outs8_count; /* (80186) OUTS 8-bit */
139 uint8 outs16, rep_outs16_base, rep_outs16_count; /* (80186) OUTS 16-bit */
140 uint8 push_imm, pusha, popa; /* (80186) PUSH immediate, PUSHA/POPA */
141 uint8 imul_rri8, imul_rmi8; /* (80186) IMUL immediate 8-bit */
142 uint8 imul_rri16, imul_rmi16; /* (80186) IMUL immediate 16-bit */
143 uint8 enter0, enter1, enter_base, enter_count, leave; /* (80186) ENTER/LEAVE */
144 uint8 bound; /* (80186) BOUND */
148 /* these come from the 8088 timings in OPCODE.LST, but with the
149 penalty for 16-bit memory accesses removed wherever possible */
150 static const struct i80x86_timing timing = {
151 51, 32, /* exception, IRET */
152 2, 0, 4, 2, /* INTs */
153 2, /* segment overrides */
154 2, 4, 4, /* flag operations */
155 4, 4, 83, 60, /* arithmetic adjusts */
156 4, 4, /* decimal adjusts */
157 2, 5, /* sign extension */
158 2, 24, 2, 2, 3, 11, /* misc */
160 15, 15, 15, /* direct JMPs */
161 11, 18, 24, /* indirect JMPs */
162 19, 28, /* direct CALLs */
163 16, 21, 37, /* indirect CALLs */
164 20, 32, 24, 31, /* returns */
165 4, 16, 6, 18, /* conditional JMPs */
166 5, 17, 6, 18, /* loops */
168 10, 14, 8, 12, /* port reads */
169 10, 14, 8, 12, /* port writes */
171 2, 8, 9, /* move, 8-bit */
172 4, 10, /* move, 8-bit immediate */
173 2, 8, 9, /* move, 16-bit */
174 4, 10, /* move, 16-bit immediate */
175 10, 10, 10, 10, /* move, AL/AX memory */
176 2, 8, 2, 9, /* move, segment registers */
177 4, 17, /* exchange, 8-bit */
178 4, 17, 3, /* exchange, 16-bit */
180 15, 24, 14, 14, /* pushes */
181 12, 25, 12, 12, /* pops */
183 3, 9, 16, /* ALU ops, 8-bit */
184 4, 17, 10, /* ALU ops, 8-bit immediate */
185 3, 9, 16, /* ALU ops, 16-bit */
186 4, 17, 10, /* ALU ops, 16-bit immediate */
187 4, 17, 10, /* ALU ops, 16-bit w/8-bit immediate */
188 70, 118, 76, 128, /* MUL */
189 80, 128, 86, 138, /* IMUL */
190 80, 144, 86, 154, /* DIV */
191 101, 165, 107, 175, /* IDIV */
192 3, 2, 15, 15, /* INC/DEC */
193 3, 3, 16, 16, /* NEG/NOT */
195 2, 8, 4, /* reg shift/rotate */
196 15, 20, 4, /* m8 shift/rotate */
197 15, 20, 4, /* m16 shift/rotate */
199 22, 9, 21, /* CMPS 8-bit */
200 22, 9, 21, /* CMPS 16-bit */
201 15, 9, 14, /* SCAS 8-bit */
202 15, 9, 14, /* SCAS 16-bit */
203 12, 9, 11, /* LODS 8-bit */
204 12, 9, 11, /* LODS 16-bit */
205 11, 9, 10, /* STOS 8-bit */
206 11, 9, 10, /* STOS 16-bit */
207 18, 9, 17, /* MOVS 8-bit */
208 18, 9, 17, /* MOVS 16-bit */
211 /* these come from the Intel 80186 datasheet */
212 static const struct i80x86_timing timing = {
213 45, 28, /* exception, IRET */
214 0, 2, 4, 3, /* INTs */
215 2, /* segment overrides */
216 2, 2, 3, /* flag operations */
217 8, 7, 19, 15, /* arithmetic adjusts */
218 4, 4, /* decimal adjusts */
219 2, 4, /* sign extension */
220 2, 18, 6, 2, 6, 11, /* misc */
222 14, 14, 14, /* direct JMPs */
223 11, 17, 26, /* indirect JMPs */
224 15, 23, /* direct CALLs */
225 13, 19, 38, /* indirect CALLs */
226 16, 22, 18, 25, /* returns */
227 4, 13, 5, 15, /* conditional JMPs */
228 6, 16, 6, 16, /* loops */
230 10, 10, 8, 8, /* port reads */
231 9, 9, 7, 7, /* port writes */
233 2, 9, 12, /* move, 8-bit */
234 3, 12, /* move, 8-bit immediate */
235 2, 9, 12, /* move, 16-bit */
236 4, 13, /* move, 16-bit immediate */
237 8, 8, 9, 9, /* move, AL/AX memory */
238 2, 11, 2, 11, /* move, segment registers */
239 4, 17, /* exchange, 8-bit */
240 4, 17, 3, /* exchange, 16-bit */
242 10, 16, 9, 9, /* pushes */
243 10, 20, 8, 8, /* pops */
245 3, 10, 10, /* ALU ops, 8-bit */
246 4, 16, 10, /* ALU ops, 8-bit immediate */
247 3, 10, 10, /* ALU ops, 16-bit */
248 4, 16, 10, /* ALU ops, 16-bit immediate */
249 4, 16, 10, /* ALU ops, 16-bit w/8-bit immediate */
250 26, 35, 32, 41, /* MUL */
251 25, 34, 31, 40, /* IMUL */
252 29, 38, 35, 44, /* DIV */
253 44, 53, 50, 59, /* IDIV */
254 3, 3, 15, 15, /* INC/DEC */
255 3, 3, 10, 10, /* NEG/NOT */
257 2, 5, 1, /* reg shift/rotate */
258 15, 17, 1, /* m8 shift/rotate */
259 15, 17, 1, /* m16 shift/rotate */
261 22, 5, 22, /* CMPS 8-bit */
262 22, 5, 22, /* CMPS 16-bit */
263 15, 5, 15, /* SCAS 8-bit */
264 15, 5, 15, /* SCAS 16-bit */
265 12, 6, 11, /* LODS 8-bit */
266 12, 6, 11, /* LODS 16-bit */
267 10, 6, 9, /* STOS 8-bit */
268 10, 6, 9, /* STOS 16-bit */
269 14, 8, 8, /* MOVS 8-bit */
270 14, 8, 8, /* MOVS 16-bit */
272 14, 8, 8, /* (80186) INS 8-bit */
273 14, 8, 8, /* (80186) INS 16-bit */
274 14, 8, 8, /* (80186) OUTS 8-bit */
275 14, 8, 8, /* (80186) OUTS 16-bit */
276 14, 68, 83, /* (80186) PUSH immediate, PUSHA/POPA */
277 22, 29, /* (80186) IMUL immediate 8-bit */
278 25, 32, /* (80186) IMUL immediate 16-bit */
279 15, 25, 4, 16, 8, /* (80186) ENTER/LEAVE */
280 33, /* (80186) BOUND */
284 /************************************************************************/
286 #define SetTF(x) (TF = (x))
287 #define SetIF(x) (IF = (x))
288 #define SetDF(x) (DirVal = (x) ? -1 : 1)
289 #define SetMD(x) (MF = (x))
291 #define SetOFW_Add(x, y, z) (OverVal = ((x) ^ (y)) & ((x) ^ (z)) & 0x8000)
292 #define SetOFB_Add(x, y, z) (OverVal = ((x) ^ (y)) & ((x) ^ (z)) & 0x80)
293 #define SetOFW_Sub(x, y, z) (OverVal = ((z) ^ (y)) & ((z) ^ (x)) & 0x8000)
294 #define SetOFB_Sub(x, y, z) (OverVal = ((z) ^ (y)) & ((z) ^ (x)) & 0x80)
296 #define SetCFB(x) (CarryVal = (x) & 0x100)
297 #define SetCFW(x) (CarryVal = (x) & 0x10000)
298 #define SetAF(x, y, z) (AuxVal = ((x) ^ ((y) ^ (z))) & 0x10)
299 #define SetSF(x) (SignVal = (x))
300 #define SetZF(x) (ZeroVal = (x))
301 #define SetPF(x) (ParityVal = (x))
303 #define SetSZPF_Byte(x) (ParityVal = SignVal = ZeroVal = (int8)(x))
304 #define SetSZPF_Word(x) (ParityVal = SignVal = ZeroVal = (int16)(x))
306 #define ADDB(dst, src) { unsigned res = (dst) + (src); SetCFB(res); SetOFB_Add(res, src, dst); SetAF(res, src, dst); SetSZPF_Byte(res); dst = (uint8)res; }
307 #define ADDW(dst, src) { unsigned res = (dst) + (src); SetCFW(res); SetOFW_Add(res, src, dst); SetAF(res, src, dst); SetSZPF_Word(res); dst = (uint16)res; }
309 #define SUBB(dst, src) { unsigned res = (dst) - (src); SetCFB(res); SetOFB_Sub(res, src, dst); SetAF(res, src, dst); SetSZPF_Byte(res); dst = (uint8)res; }
310 #define SUBW(dst, src) { unsigned res = (dst) - (src); SetCFW(res); SetOFW_Sub(res, src, dst); SetAF(res, src, dst); SetSZPF_Word(res); dst = (uint16)res; }
312 #define ORB(dst, src) dst |= (src); CarryVal = OverVal = AuxVal = 0; SetSZPF_Byte(dst)
313 #define ORW(dst, src) dst |= (src); CarryVal = OverVal = AuxVal = 0; SetSZPF_Word(dst)
315 #define ANDB(dst, src) dst &= (src); CarryVal = OverVal = AuxVal = 0; SetSZPF_Byte(dst)
316 #define ANDW(dst, src) dst &= (src); CarryVal = OverVal = AuxVal = 0; SetSZPF_Word(dst)
318 #define XORB(dst, src) dst ^= (src); CarryVal = OverVal = AuxVal = 0; SetSZPF_Byte(dst)
319 #define XORW(dst, src) dst ^= (src); CarryVal = OverVal = AuxVal = 0; SetSZPF_Word(dst)
321 #define CF (CarryVal != 0)
322 #define SF (SignVal < 0)
323 #define ZF (ZeroVal == 0)
324 #define PF parity_table[ParityVal]
325 #define AF (AuxVal != 0)
326 #define OF (OverVal != 0)
327 #define DF (DirVal < 0)
330 /************************************************************************/
332 #define AMASK 0xfffff
334 #define read_mem_byte(a) d_mem->read_data8((a) & AMASK)
335 #define read_mem_word(a) d_mem->read_data16((a) & AMASK)
336 #define write_mem_byte(a, d) d_mem->write_data8((a) & AMASK, (d))
337 #define write_mem_word(a, d) d_mem->write_data16((a) & AMASK, (d))
339 #define read_port_byte(a) d_io->read_io8(a)
340 #define read_port_word(a) d_io->read_io16(a)
341 #define write_port_byte(a, d) d_io->write_io8((a), (d))
342 #define write_port_word(a, d) d_io->write_io16((a), (d))
344 /************************************************************************/
346 #define SegBase(Seg) (sregs[Seg] << 4)
348 #define DefaultSeg(Seg) ((seg_prefix && (Seg == DS || Seg == SS)) ? prefix_seg : Seg)
349 #define DefaultBase(Seg) ((seg_prefix && (Seg == DS || Seg == SS)) ? base[prefix_seg] : base[Seg])
351 #define GetMemB(Seg, Off) (read_mem_byte((DefaultBase(Seg) + (Off)) & AMASK))
352 #define GetMemW(Seg, Off) (read_mem_word((DefaultBase(Seg) + (Off)) & AMASK))
353 #define PutMemB(Seg, Off, x) write_mem_byte((DefaultBase(Seg) + (Off)) & AMASK, (x))
354 #define PutMemW(Seg, Off, x) write_mem_word((DefaultBase(Seg) + (Off)) & AMASK, (x))
356 #define ReadByte(ea) (read_mem_byte((ea) & AMASK))
357 #define ReadWord(ea) (read_mem_word((ea) & AMASK))
358 #define WriteByte(ea, val) write_mem_byte((ea) & AMASK, val);
359 #define WriteWord(ea, val) write_mem_word((ea) & AMASK, val);
361 #define FETCH read_mem_byte(pc++)
362 #define FETCHOP read_mem_byte(pc++)
363 #define FETCHWORD(var) { var = read_mem_word(pc); pc += 2; }
364 #define PUSH(val) { regs.w[SP] -= 2; WriteWord(((base[SS] + regs.w[SP]) & AMASK), val); }
365 #define POP(var) { regs.w[SP] += 2; var = ReadWord(((base[SS] + ((regs.w[SP]-2) & 0xffff)) & AMASK)); }
367 /************************************************************************/
369 #define CompressFlags() (uint16)(CF | (PF << 2) | (AF << 4) | (ZF << 6) | (SF << 7) | (TF << 8) | (IF << 9) | (DF << 10) | (OF << 11) | (MD << 15))
371 #define ExpandFlags(f) { \
372 CarryVal = (f) & 1; \
373 ParityVal = !((f) & 4); \
374 AuxVal = (f) & 0x10; \
375 ZeroVal = !((f) & 0x40); \
376 SignVal = ((f) & 0x80) ? -1 : 0; \
377 TF = ((f) & 0x100) >> 8; \
378 IF = ((f) & 0x200) >> 9; \
379 MF = ((f) & 0x8000) >> 15; \
380 DirVal = ((f) & 0x400) ? -1 : 1; \
381 OverVal = (f) & 0x800; \
384 /************************************************************************/
386 #define RegWord(ModRM) regs.w[Mod_RM.reg.w[ModRM]]
387 #define RegByte(ModRM) regs.b[Mod_RM.reg.b[ModRM]]
389 #define GetRMWord(ModRM) \
390 ((ModRM) >= 0xc0 ? regs.w[Mod_RM.RM.w[ModRM]] : (GetEA(ModRM), ReadWord(ea)))
392 #define PutbackRMWord(ModRM, val) { \
393 if (ModRM >= 0xc0) { \
394 regs.w[Mod_RM.RM.w[ModRM]] = val; \
396 WriteWord(ea, val); \
400 #define GetNextRMWord ( \
404 #define GetRMWordOffset(offs) ( \
405 ReadWord(ea - eo + (uint16)(eo + offs)) \
408 #define GetRMByteOffset(offs) ( \
409 ReadByte(ea - eo + (uint16)(eo + offs)) \
412 #define PutRMWord(ModRM, val) { \
413 if (ModRM >= 0xc0) { \
414 regs.w[Mod_RM.RM.w[ModRM]] = val; \
417 WriteWord(ea, val); \
421 #define PutRMWordOffset(offs, val) \
422 WriteWord(ea - eo + (uint16)(eo + offs), val)
424 #define PutRMByteOffset(offs, val) \
425 WriteByte(ea - eo + (uint16)(eo + offs), val)
427 #define PutImmRMWord(ModRM) { \
429 if (ModRM >= 0xc0) { \
430 FETCHWORD(regs.w[Mod_RM.RM.w[ModRM]]) \
434 WriteWord(ea, val); \
438 #define GetRMByte(ModRM) \
439 ((ModRM) >= 0xc0 ? regs.b[Mod_RM.RM.b[ModRM]] : (GetEA(ModRM), ReadByte(ea)))
441 #define PutRMByte(ModRM, val) { \
442 if (ModRM >= 0xc0) { \
443 regs.b[Mod_RM.RM.b[ModRM]] = val; \
446 WriteByte(ea, val); \
450 #define PutImmRMByte(ModRM) { \
451 if (ModRM >= 0xc0) { \
452 regs.b[Mod_RM.RM.b[ModRM]] = FETCH; \
455 WriteByte(ea, FETCH); \
459 #define PutbackRMByte(ModRM, val) { \
460 if (ModRM >= 0xc0) { \
461 regs.b[Mod_RM.RM.b[ModRM]] = val; \
463 WriteByte(ea, val); \
467 #define DEF_br8(dst, src) \
468 unsigned ModRM = FETCHOP; \
469 unsigned src = RegByte(ModRM); \
470 unsigned dst = GetRMByte(ModRM)
472 #define DEF_wr16(dst, src) \
473 unsigned ModRM = FETCHOP; \
474 unsigned src = RegWord(ModRM); \
475 unsigned dst = GetRMWord(ModRM)
477 #define DEF_r8b(dst, src) \
478 unsigned ModRM = FETCHOP; \
479 unsigned dst = RegByte(ModRM); \
480 unsigned src = GetRMByte(ModRM)
482 #define DEF_r16w(dst, src) \
483 unsigned ModRM = FETCHOP; \
484 unsigned dst = RegWord(ModRM); \
485 unsigned src = GetRMWord(ModRM)
487 #define DEF_ald8(dst, src) \
488 unsigned src = FETCHOP; \
489 unsigned dst = regs.b[AL]
491 #define DEF_axd16(dst, src) \
492 unsigned src = FETCHOP; \
493 unsigned dst = regs.w[AX]; \
496 /************************************************************************/
499 #define INLINE inline
502 #define offs_t UINT32
504 // Disassembler constants
505 const UINT32 DASMFLAG_SUPPORTED = 0x80000000; // are disassembly flags supported?
506 const UINT32 DASMFLAG_STEP_OUT = 0x40000000; // this instruction should be the end of a step out sequence
507 const UINT32 DASMFLAG_STEP_OVER = 0x20000000; // this instruction should be stepped over by setting a breakpoint afterwards
508 const UINT32 DASMFLAG_OVERINSTMASK = 0x18000000; // number of extra instructions to skip when stepping over
509 const UINT32 DASMFLAG_OVERINSTSHIFT = 27; // bits to shift after masking to get the value
510 const UINT32 DASMFLAG_LENGTHMASK = 0x0000ffff; // the low 16-bits contain the actual length
512 /* Highly useful macro for compile-time knowledge of an array size */
513 #define ARRAY_LENGTH(x) (sizeof(x) / sizeof(x[0]))
515 int necv_dasm_one(char *buffer, UINT32 eip, const UINT8 *oprom);
517 void I86::initialize()
519 static const BREGS reg_name[8] = {AL, CL, DL, BL, AH, CH, DH, BH};
521 for(int i = 0; i < 256; i++) {
522 Mod_RM.reg.b[i] = reg_name[(i & 0x38) >> 3];
523 Mod_RM.reg.w[i] = (WREGS)((i & 0x38) >> 3);
525 for(int i = 0xc0; i < 0x100; i++) {
526 Mod_RM.RM.w[i] = (WREGS)(i & 7);
527 Mod_RM.RM.b[i] = (BREGS)reg_name[i & 7];
530 d_mem_stored = d_mem;
532 d_debugger->set_context_mem(d_mem);
533 d_debugger->set_context_io(d_io);
539 for(int i = 0; i < 8; i++) {
543 sregs[SS] = sregs[DS] = sregs[ES] = 0;
545 base[CS] = SegBase(CS);
546 base[SS] = base[DS] = base[ES] = 0;
550 AuxVal = OverVal = SignVal = ZeroVal = CarryVal = 0;
552 ParityVal = TF = IF = MF = 0;
554 icount = extra_icount = 0;
559 pc = 0xffff0 & AMASK;
568 int I86::run(int clock)
570 /* return now if BUSREQ */
572 #ifdef SINGLE_MODE_DMA
577 int passed_icount = max(1, extra_icount);
578 icount = extra_icount = 0;
579 return passed_icount;
584 // run only one opcode
585 icount = -extra_icount;
588 run_one_opecode_debugger();
594 /* run cpu while given clocks */
596 int first_icount = icount;
597 icount -= extra_icount;
600 while(icount > 0 && !busreq) {
602 run_one_opecode_debugger();
607 int passed_icount = first_icount - icount;
608 if(busreq && icount > 0) {
611 return passed_icount;
616 void I86::run_one_opecode_debugger()
618 bool now_debugging = d_debugger->now_debugging;
620 d_debugger->check_break_points(pc);
621 if(d_debugger->now_suspended) {
623 while(d_debugger->now_debugging && d_debugger->now_suspended) {
627 if(d_debugger->now_debugging) {
628 d_mem = d_io = d_debugger;
630 now_debugging = false;
635 if(!d_debugger->now_going) {
636 d_debugger->now_suspended = true;
638 d_mem = d_mem_stored;
647 void I86::run_one_opecode()
651 // ugly patch for PC/JX hardware diagnostics :-(
653 if(pc == 0xff040) pc = 0xff04a;
654 if(pc == 0xff17d) pc = 0xff18f;
657 if(pc == 0xfa909) { regs.b[BH] = read_port_byte(0xa1); pc = 0xfa97c; }
658 if(pc == 0xff6e1) { regs.b[AL] = 0x0d; pc += 2; }
661 instruction(FETCHOP);
662 if(int_state & NMI_REQ_BIT) {
667 int_state &= ~NMI_REQ_BIT;
668 interrupt(NMI_INT_VECTOR);
669 } else if((int_state & INT_REQ_BIT) && IF) {
676 #ifdef SINGLE_MODE_DMA
681 icount -= extra_icount;
685 void I86::write_signal(int id, uint32 data, uint32 mask)
687 if(id == SIG_CPU_NMI) {
689 int_state |= NMI_REQ_BIT;
691 int_state &= ~NMI_REQ_BIT;
693 } else if(id == SIG_CPU_BUSREQ) {
694 busreq = ((data & mask) != 0);
695 } else if(id == SIG_I86_TEST) {
696 test_state = ((data & mask) != 0);
700 void I86::set_intr_line(bool line, bool pending, uint32 bit)
703 int_state |= INT_REQ_BIT;
705 int_state &= ~INT_REQ_BIT;
710 void I86::debug_write_data8(uint32 addr, uint32 data)
713 d_mem_stored->write_data8w(addr, data, &wait);
716 uint32 I86::debug_read_data8(uint32 addr)
719 return d_mem_stored->read_data8w(addr, &wait);
722 void I86::debug_write_data16(uint32 addr, uint32 data)
725 d_mem_stored->write_data16w(addr, data, &wait);
728 uint32 I86::debug_read_data16(uint32 addr)
731 return d_mem_stored->read_data16w(addr, &wait);
734 void I86::debug_write_io8(uint32 addr, uint32 data)
737 d_io_stored->write_io8w(addr, data, &wait);
740 uint32 I86::debug_read_io8(uint32 addr) {
742 return d_io_stored->read_io8w(addr, &wait);
745 void I86::debug_write_io16(uint32 addr, uint32 data)
748 d_io_stored->write_io16w(addr, data, &wait);
751 uint32 I86::debug_read_io16(uint32 addr) {
753 return d_io_stored->read_io16w(addr, &wait);
756 bool I86::debug_write_reg(_TCHAR *reg, uint32 data)
758 if(_tcsicmp(reg, _T("IP")) == 0) {
759 pc = ((data & 0xffff) + base[CS]) & AMASK;
760 } else if(_tcsicmp(reg, _T("AX")) == 0) {
762 } else if(_tcsicmp(reg, _T("BX")) == 0) {
764 } else if(_tcsicmp(reg, _T("CX")) == 0) {
766 } else if(_tcsicmp(reg, _T("DX")) == 0) {
768 } else if(_tcsicmp(reg, _T("SP")) == 0) {
770 } else if(_tcsicmp(reg, _T("BP")) == 0) {
772 } else if(_tcsicmp(reg, _T("SI")) == 0) {
774 } else if(_tcsicmp(reg, _T("DI")) == 0) {
776 } else if(_tcsicmp(reg, _T("AL")) == 0) {
778 } else if(_tcsicmp(reg, _T("AH")) == 0) {
780 } else if(_tcsicmp(reg, _T("BL")) == 0) {
782 } else if(_tcsicmp(reg, _T("BH")) == 0) {
784 } else if(_tcsicmp(reg, _T("CL")) == 0) {
786 } else if(_tcsicmp(reg, _T("CH")) == 0) {
788 } else if(_tcsicmp(reg, _T("DL")) == 0) {
790 } else if(_tcsicmp(reg, _T("DH")) == 0) {
798 void I86::debug_regs_info(_TCHAR *buffer, size_t buffer_len)
800 _stprintf_s(buffer, buffer_len,
801 _T("AX=%04X BX=%04X CX=%04X DX=%04X SP=%04X BP=%04X SI=%04X DI=%04X\nDS=%04X ES=%04X SS=%04X CS=%04X IP=%04X FLAG=[%c%c%c%c%c%c%c%c%c]"),
802 regs.w[AX], regs.w[BX], regs.w[CX], regs.w[DX], regs.w[SP], regs.w[BP], regs.w[SI], regs.w[DI], sregs[DS], sregs[ES], sregs[SS], sregs[CS], (uint16)(pc - base[CS]),
803 OF ? _T('O') : _T('-'), DF ? _T('D') : _T('-'), IF ? _T('I') : _T('-'), TF ? _T('T') : _T('-'),
804 SF ? _T('S') : _T('-'), ZF ? _T('Z') : _T('-'), AF ? _T('A') : _T('-'), PF ? _T('P') : _T('-'), CF ? _T('C') : _T('-'));
807 int I86::debug_dasm(uint32 pc, _TCHAR *buffer, size_t buffer_len)
809 UINT32 eip = (UINT32)(uint16)(pc - base[CS]);
811 for(int i = 0; i < 16; i++) {
813 ops[i] = d_mem->read_data8w(pc + i, &wait);
815 return necv_dasm_one(buffer, eip, ops) & DASMFLAG_LENGTHMASK;
819 void I86::interrupt(int int_num)
821 unsigned dest_seg, dest_off;
822 uint16 ip = pc - base[CS];
825 int_num = d_pic->intr_ack() & 0xff;
826 int_state &= ~INT_REQ_BIT;
828 dest_off = ReadWord(int_num * 4);
829 dest_seg = ReadWord(int_num * 4 + 2);
835 sregs[CS] = (uint16)dest_seg;
836 base[CS] = SegBase(CS);
837 pc = (base[CS] + dest_off) & AMASK;
838 icount -= timing.exception;
843 instruction(FETCHOP);
847 unsigned I86::GetEA(unsigned ModRM)
850 case 0x00: case 0x08: case 0x10: case 0x18: case 0x20: case 0x28: case 0x30: case 0x38:
851 icount -= 7; eo = (uint16)(regs.w[BX] + regs.w[SI]); ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
852 case 0x01: case 0x09: case 0x11: case 0x19: case 0x21: case 0x29: case 0x31: case 0x39:
853 icount -= 8; eo = (uint16)(regs.w[BX] + regs.w[DI]); ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
854 case 0x02: case 0x0a: case 0x12: case 0x1a: case 0x22: case 0x2a: case 0x32: case 0x3a:
855 icount -= 8; eo = (uint16)(regs.w[BP] + regs.w[SI]); ea_seg = DefaultSeg(SS); ea = DefaultBase(SS) + eo; return ea;
856 case 0x03: case 0x0b: case 0x13: case 0x1b: case 0x23: case 0x2b: case 0x33: case 0x3b:
857 icount -= 7; eo = (uint16)(regs.w[BP] + regs.w[DI]); ea_seg = DefaultSeg(SS); ea = DefaultBase(SS) + eo; return ea;
858 case 0x04: case 0x0c: case 0x14: case 0x1c: case 0x24: case 0x2c: case 0x34: case 0x3c:
859 icount -= 5; eo = regs.w[SI]; ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
860 case 0x05: case 0x0d: case 0x15: case 0x1d: case 0x25: case 0x2d: case 0x35: case 0x3d:
861 icount -= 5; eo = regs.w[DI]; ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
862 case 0x06: case 0x0e: case 0x16: case 0x1e: case 0x26: case 0x2e: case 0x36: case 0x3e:
863 icount -= 6; eo = FETCHOP; eo += FETCHOP << 8; ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
864 case 0x07: case 0x0f: case 0x17: case 0x1f: case 0x27: case 0x2f: case 0x37: case 0x3f:
865 icount -= 5; eo = regs.w[BX]; ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
867 case 0x40: case 0x48: case 0x50: case 0x58: case 0x60: case 0x68: case 0x70: case 0x78:
868 icount -= 11; eo = (uint16)(regs.w[BX] + regs.w[SI] + (int8)FETCHOP); ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
869 case 0x41: case 0x49: case 0x51: case 0x59: case 0x61: case 0x69: case 0x71: case 0x79:
870 icount -= 12; eo = (uint16)(regs.w[BX] + regs.w[DI] + (int8)FETCHOP); ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
871 case 0x42: case 0x4a: case 0x52: case 0x5a: case 0x62: case 0x6a: case 0x72: case 0x7a:
872 icount -= 12; eo = (uint16)(regs.w[BP] + regs.w[SI] + (int8)FETCHOP); ea_seg = DefaultSeg(SS); ea = DefaultBase(SS) + eo; return ea;
873 case 0x43: case 0x4b: case 0x53: case 0x5b: case 0x63: case 0x6b: case 0x73: case 0x7b:
874 icount -= 11; eo = (uint16)(regs.w[BP] + regs.w[DI] + (int8)FETCHOP); ea_seg = DefaultSeg(SS); ea = DefaultBase(SS) + eo; return ea;
875 case 0x44: case 0x4c: case 0x54: case 0x5c: case 0x64: case 0x6c: case 0x74: case 0x7c:
876 icount -= 9; eo = (uint16)(regs.w[SI] + (int8)FETCHOP); ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
877 case 0x45: case 0x4d: case 0x55: case 0x5d: case 0x65: case 0x6d: case 0x75: case 0x7d:
878 icount -= 9; eo = (uint16)(regs.w[DI] + (int8)FETCHOP); ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
879 case 0x46: case 0x4e: case 0x56: case 0x5e: case 0x66: case 0x6e: case 0x76: case 0x7e:
880 icount -= 9; eo = (uint16)(regs.w[BP] + (int8)FETCHOP); ea_seg = DefaultSeg(SS); ea = DefaultBase(SS) + eo; return ea;
881 case 0x47: case 0x4f: case 0x57: case 0x5f: case 0x67: case 0x6f: case 0x77: case 0x7f:
882 icount -= 9; eo = (uint16)(regs.w[BX] + (int8)FETCHOP); ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
884 case 0x80: case 0x88: case 0x90: case 0x98: case 0xa0: case 0xa8: case 0xb0: case 0xb8:
885 icount -= 11; eo = FETCHOP; eo += FETCHOP << 8; eo += regs.w[BX] + regs.w[SI]; ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + (uint16)eo; return ea;
886 case 0x81: case 0x89: case 0x91: case 0x99: case 0xa1: case 0xa9: case 0xb1: case 0xb9:
887 icount -= 12; eo = FETCHOP; eo += FETCHOP << 8; eo += regs.w[BX] + regs.w[DI]; ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + (uint16)eo; return ea;
888 case 0x82: case 0x8a: case 0x92: case 0x9a: case 0xa2: case 0xaa: case 0xb2: case 0xba:
889 icount -= 12; eo = FETCHOP; eo += FETCHOP << 8; eo += regs.w[BP] + regs.w[SI]; ea_seg = DefaultSeg(SS); ea = DefaultBase(SS) + (uint16)eo; return ea;
890 case 0x83: case 0x8b: case 0x93: case 0x9b: case 0xa3: case 0xab: case 0xb3: case 0xbb:
891 icount -= 11; eo = FETCHOP; eo += FETCHOP << 8; eo += regs.w[BP] + regs.w[DI]; ea_seg = DefaultSeg(DS); ea = DefaultBase(SS) + (uint16)eo; return ea;
892 case 0x84: case 0x8c: case 0x94: case 0x9c: case 0xa4: case 0xac: case 0xb4: case 0xbc:
893 icount -= 9; eo = FETCHOP; eo += FETCHOP << 8; eo += regs.w[SI]; ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + (uint16)eo; return ea;
894 case 0x85: case 0x8d: case 0x95: case 0x9d: case 0xa5: case 0xad: case 0xb5: case 0xbd:
895 icount -= 9; eo = FETCHOP; eo += FETCHOP << 8; eo += regs.w[DI]; ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + (uint16)eo; return ea;
896 case 0x86: case 0x8e: case 0x96: case 0x9e: case 0xa6: case 0xae: case 0xb6: case 0xbe:
897 icount -= 9; eo = FETCHOP; eo += FETCHOP << 8; eo += regs.w[BP]; ea_seg = DefaultSeg(SS); ea = DefaultBase(SS) + (uint16)eo; return ea;
898 case 0x87: case 0x8f: case 0x97: case 0x9f: case 0xa7: case 0xaf: case 0xb7: case 0xbf:
899 icount -= 9; eo = FETCHOP; eo += FETCHOP << 8; eo += regs.w[BX]; ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + (uint16)eo; return ea;
904 void I86::rotate_shift_byte(unsigned ModRM, unsigned count)
906 unsigned src = (unsigned)GetRMByte(ModRM);
910 icount -= (ModRM >= 0xc0) ? timing.rot_reg_base : timing.rot_m8_base;
911 } else if(count == 1) {
912 icount -= (ModRM >= 0xc0) ? timing.rot_reg_1 : timing.rot_m8_1;
914 switch((ModRM >> 3) & 7) {
915 case 0: /* ROL eb, 1 */
916 CarryVal = src & 0x80;
917 dst = (src << 1) + CF;
918 PutbackRMByte(ModRM, dst);
919 OverVal = (src ^ dst) & 0x80;
921 case 1: /* ROR eb, 1 */
922 CarryVal = src & 0x01;
923 dst = ((CF << 8) + src) >> 1;
924 PutbackRMByte(ModRM, dst);
925 OverVal = (src ^ dst) & 0x80;
927 case 2: /* RCL eb, 1 */
928 dst = (src << 1) + CF;
929 PutbackRMByte(ModRM, dst);
931 OverVal = (src ^ dst) & 0x80;
933 case 3: /* RCR eb, 1 */
934 dst = ((CF << 8) + src) >> 1;
935 PutbackRMByte(ModRM, dst);
936 CarryVal = src & 0x01;
937 OverVal = (src ^ dst) & 0x80;
939 case 4: /* SHL eb, 1 */
942 PutbackRMByte(ModRM, dst);
944 OverVal = (src ^ dst) & 0x80;
948 case 5: /* SHR eb, 1 */
950 PutbackRMByte(ModRM, dst);
951 CarryVal = src & 0x01;
952 OverVal = src & 0x80;
956 case 7: /* SAR eb, 1 */
957 dst = ((int8)src) >> 1;
958 PutbackRMByte(ModRM, dst);
959 CarryVal = src & 0x01;
964 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
974 icount -= (ModRM >= 0xc0) ? timing.rot_reg_base + timing.rot_reg_bit : timing.rot_m8_base + timing.rot_m8_bit;
976 switch((ModRM >> 3) & 7) {
977 case 0: /* ROL eb, count */
978 for(; count > 0; count--) {
979 CarryVal = dst & 0x80;
980 dst = (dst << 1) + CF;
982 PutbackRMByte(ModRM, (uint8)dst);
984 case 1: /* ROR eb, count */
985 for(; count > 0; count--) {
986 CarryVal = dst & 0x01;
987 dst = (dst >> 1) + (CF << 7);
989 PutbackRMByte(ModRM, (uint8)dst);
991 case 2: /* RCL eb, count */
992 for(; count > 0; count--) {
993 dst = (dst << 1) + CF;
996 PutbackRMByte(ModRM, (uint8)dst);
998 case 3: /* RCR eb, count */
999 for(; count > 0; count--) {
1000 dst = (CF << 8) + dst;
1001 CarryVal = dst & 0x01;
1004 PutbackRMByte(ModRM, (uint8)dst);
1006 case 4: /* SHL eb, count */
1012 PutbackRMByte(ModRM, (uint8)dst);
1014 case 5: /* SHR eb, count */
1016 CarryVal = dst & 0x01;
1020 PutbackRMByte(ModRM, (uint8)dst);
1022 case 7: /* SAR eb, count */
1023 dst = ((int8)dst) >> (count - 1);
1024 CarryVal = dst & 0x01;
1025 dst = ((int8)((uint8)dst)) >> 1;
1028 PutbackRMByte(ModRM, (uint8)dst);
1030 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
1042 void I86::rotate_shift_word(unsigned ModRM, unsigned count)
1044 unsigned src = GetRMWord(ModRM);
1048 icount -= (ModRM >= 0xc0) ? timing.rot_reg_base : timing.rot_m16_base;
1049 } else if(count == 1) {
1050 icount -= (ModRM >= 0xc0) ? timing.rot_reg_1 : timing.rot_m16_1;
1052 switch((ModRM >> 3) & 7) {
1053 case 0: /* ROL ew, 1 */
1054 CarryVal = src & 0x8000;
1055 dst = (src << 1) + CF;
1056 PutbackRMWord(ModRM, dst);
1057 OverVal = (src ^ dst) & 0x8000;
1059 case 1: /* ROR ew, 1 */
1060 CarryVal = src & 0x01;
1061 dst = ((CF << 16) + src) >> 1;
1062 PutbackRMWord(ModRM, dst);
1063 OverVal = (src ^ dst) & 0x8000;
1065 case 2: /* RCL ew, 1 */
1066 dst = (src << 1) + CF;
1067 PutbackRMWord(ModRM, dst);
1069 OverVal = (src ^ dst) & 0x8000;
1071 case 3: /* RCR ew, 1 */
1072 dst = ((CF << 16) + src) >> 1;
1073 PutbackRMWord(ModRM, dst);
1074 CarryVal = src & 0x01;
1075 OverVal = (src ^ dst) & 0x8000;
1077 case 4: /* SHL ew, 1 */
1080 PutbackRMWord(ModRM, dst);
1082 OverVal = (src ^ dst) & 0x8000;
1086 case 5: /* SHR ew, 1 */
1088 PutbackRMWord(ModRM, dst);
1089 CarryVal = src & 0x01;
1090 OverVal = src & 0x8000;
1094 case 7: /* SAR ew, 1 */
1095 dst = ((int16)src) >> 1;
1096 PutbackRMWord(ModRM, dst);
1097 CarryVal = src & 0x01;
1102 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
1112 icount -= (ModRM >= 0xc0) ? timing.rot_reg_base + timing.rot_reg_bit : timing.rot_m8_base + timing.rot_m16_bit;
1114 switch((ModRM >> 3) & 7) {
1115 case 0: /* ROL ew, count */
1116 for(; count > 0; count--) {
1117 CarryVal = dst & 0x8000;
1118 dst = (dst << 1) + CF;
1120 PutbackRMWord(ModRM, dst);
1122 case 1: /* ROR ew, count */
1123 for(; count > 0; count--) {
1124 CarryVal = dst & 0x01;
1125 dst = (dst >> 1) + (CF << 15);
1127 PutbackRMWord(ModRM, dst);
1129 case 2: /* RCL ew, count */
1130 for(; count > 0; count--) {
1131 dst = (dst << 1) + CF;
1134 PutbackRMWord(ModRM, dst);
1136 case 3: /* RCR ew, count */
1137 for(; count > 0; count--) {
1138 dst = dst + (CF << 16);
1139 CarryVal = dst & 0x01;
1142 PutbackRMWord(ModRM, dst);
1144 case 4: /* SHL ew, count */
1150 PutbackRMWord(ModRM, dst);
1152 case 5: /* SHR ew, count */
1154 CarryVal = dst & 0x01;
1158 PutbackRMWord(ModRM, dst);
1160 case 7: /* SAR ew, count */
1161 dst = ((int16)dst) >> (count - 1);
1162 CarryVal = dst & 0x01;
1163 dst = ((int16)((uint16)dst)) >> 1;
1166 PutbackRMWord(ModRM, dst);
1175 void I86::instruction(uint8 code)
1180 case 0x00: _add_br8(); break;
1181 case 0x01: _add_wr16(); break;
1182 case 0x02: _add_r8b(); break;
1183 case 0x03: _add_r16w(); break;
1184 case 0x04: _add_ald8(); break;
1185 case 0x05: _add_axd16(); break;
1186 case 0x06: _push_es(); break;
1187 case 0x07: _pop_es(); break;
1188 case 0x08: _or_br8(); break;
1189 case 0x09: _or_wr16(); break;
1190 case 0x0a: _or_r8b(); break;
1191 case 0x0b: _or_r16w(); break;
1192 case 0x0c: _or_ald8(); break;
1193 case 0x0d: _or_axd16(); break;
1194 case 0x0e: _push_cs(); break;
1195 #if defined(HAS_V30)
1196 case 0x0f: _0fpre(); break;
1198 case 0x0f: _invalid(); break;
1200 case 0x10: _adc_br8(); break;
1201 case 0x11: _adc_wr16(); break;
1202 case 0x12: _adc_r8b(); break;
1203 case 0x13: _adc_r16w(); break;
1204 case 0x14: _adc_ald8(); break;
1205 case 0x15: _adc_axd16(); break;
1206 case 0x16: _push_ss(); break;
1207 case 0x17: _pop_ss(); break;
1208 case 0x18: _sbb_br8(); break;
1209 case 0x19: _sbb_wr16(); break;
1210 case 0x1a: _sbb_r8b(); break;
1211 case 0x1b: _sbb_r16w(); break;
1212 case 0x1c: _sbb_ald8(); break;
1213 case 0x1d: _sbb_axd16(); break;
1214 case 0x1e: _push_ds(); break;
1215 case 0x1f: _pop_ds(); break;
1216 case 0x20: _and_br8(); break;
1217 case 0x21: _and_wr16(); break;
1218 case 0x22: _and_r8b(); break;
1219 case 0x23: _and_r16w(); break;
1220 case 0x24: _and_ald8(); break;
1221 case 0x25: _and_axd16(); break;
1222 case 0x26: _es(); break;
1223 case 0x27: _daa(); break;
1224 case 0x28: _sub_br8(); break;
1225 case 0x29: _sub_wr16(); break;
1226 case 0x2a: _sub_r8b(); break;
1227 case 0x2b: _sub_r16w(); break;
1228 case 0x2c: _sub_ald8(); break;
1229 case 0x2d: _sub_axd16(); break;
1230 case 0x2e: _cs(); break;
1231 case 0x2f: _das(); break;
1232 case 0x30: _xor_br8(); break;
1233 case 0x31: _xor_wr16(); break;
1234 case 0x32: _xor_r8b(); break;
1235 case 0x33: _xor_r16w(); break;
1236 case 0x34: _xor_ald8(); break;
1237 case 0x35: _xor_axd16(); break;
1238 case 0x36: _ss(); break;
1239 case 0x37: _aaa(); break;
1240 case 0x38: _cmp_br8(); break;
1241 case 0x39: _cmp_wr16(); break;
1242 case 0x3a: _cmp_r8b(); break;
1243 case 0x3b: _cmp_r16w(); break;
1244 case 0x3c: _cmp_ald8(); break;
1245 case 0x3d: _cmp_axd16(); break;
1246 case 0x3e: _ds(); break;
1247 case 0x3f: _aas(); break;
1248 case 0x40: _inc_ax(); break;
1249 case 0x41: _inc_cx(); break;
1250 case 0x42: _inc_dx(); break;
1251 case 0x43: _inc_bx(); break;
1252 case 0x44: _inc_sp(); break;
1253 case 0x45: _inc_bp(); break;
1254 case 0x46: _inc_si(); break;
1255 case 0x47: _inc_di(); break;
1256 case 0x48: _dec_ax(); break;
1257 case 0x49: _dec_cx(); break;
1258 case 0x4a: _dec_dx(); break;
1259 case 0x4b: _dec_bx(); break;
1260 case 0x4c: _dec_sp(); break;
1261 case 0x4d: _dec_bp(); break;
1262 case 0x4e: _dec_si(); break;
1263 case 0x4f: _dec_di(); break;
1264 case 0x50: _push_ax(); break;
1265 case 0x51: _push_cx(); break;
1266 case 0x52: _push_dx(); break;
1267 case 0x53: _push_bx(); break;
1268 case 0x54: _push_sp(); break;
1269 case 0x55: _push_bp(); break;
1270 case 0x56: _push_si(); break;
1271 case 0x57: _push_di(); break;
1272 case 0x58: _pop_ax(); break;
1273 case 0x59: _pop_cx(); break;
1274 case 0x5a: _pop_dx(); break;
1275 case 0x5b: _pop_bx(); break;
1276 case 0x5c: _pop_sp(); break;
1277 case 0x5d: _pop_bp(); break;
1278 case 0x5e: _pop_si(); break;
1279 case 0x5f: _pop_di(); break;
1280 #if defined(HAS_V30)
1281 case 0x60: _pusha(); break;
1282 case 0x61: _popa(); break;
1283 case 0x62: _bound(); break;
1285 case 0x60: _invalid(); break;
1286 case 0x61: _invalid(); break;
1287 case 0x62: _invalid(); break;
1289 case 0x63: _invalid(); break;
1290 #if defined(HAS_V30)
1291 case 0x64: _repc(0); break;
1292 case 0x65: _repc(1); break;
1294 case 0x64: _invalid(); break;
1295 case 0x65: _invalid(); break;
1297 case 0x66: _invalid(); break;
1298 case 0x67: _invalid(); break;
1299 #if defined(HAS_V30)
1300 case 0x68: _push_d16(); break;
1301 case 0x69: _imul_d16(); break;
1302 case 0x6a: _push_d8(); break;
1303 case 0x6b: _imul_d8(); break;
1304 case 0x6c: _insb(); break;
1305 case 0x6d: _insw(); break;
1306 case 0x6e: _outsb(); break;
1307 case 0x6f: _outsw(); break;
1309 case 0x68: _invalid(); break;
1310 case 0x69: _invalid(); break;
1311 case 0x6a: _invalid(); break;
1312 case 0x6b: _invalid(); break;
1313 case 0x6c: _invalid(); break;
1314 case 0x6d: _invalid(); break;
1315 case 0x6e: _invalid(); break;
1316 case 0x6f: _invalid(); break;
1318 case 0x70: _jo(); break;
1319 case 0x71: _jno(); break;
1320 case 0x72: _jb(); break;
1321 case 0x73: _jnb(); break;
1322 case 0x74: _jz(); break;
1323 case 0x75: _jnz(); break;
1324 case 0x76: _jbe(); break;
1325 case 0x77: _jnbe(); break;
1326 case 0x78: _js(); break;
1327 case 0x79: _jns(); break;
1328 case 0x7a: _jp(); break;
1329 case 0x7b: _jnp(); break;
1330 case 0x7c: _jl(); break;
1331 case 0x7d: _jnl(); break;
1332 case 0x7e: _jle(); break;
1333 case 0x7f: _jnle(); break;
1334 case 0x80: _80pre(); break;
1335 case 0x81: _81pre(); break;
1336 case 0x82: _82pre(); break;
1337 case 0x83: _83pre(); break;
1338 case 0x84: _test_br8(); break;
1339 case 0x85: _test_wr16(); break;
1340 case 0x86: _xchg_br8(); break;
1341 case 0x87: _xchg_wr16(); break;
1342 case 0x88: _mov_br8(); break;
1343 case 0x89: _mov_wr16(); break;
1344 case 0x8a: _mov_r8b(); break;
1345 case 0x8b: _mov_r16w(); break;
1346 case 0x8c: _mov_wsreg(); break;
1347 case 0x8d: _lea(); break;
1348 case 0x8e: _mov_sregw(); break;
1349 case 0x8f: _popw(); break;
1350 case 0x90: _nop(); break;
1351 case 0x91: _xchg_axcx(); break;
1352 case 0x92: _xchg_axdx(); break;
1353 case 0x93: _xchg_axbx(); break;
1354 case 0x94: _xchg_axsp(); break;
1355 case 0x95: _xchg_axbp(); break;
1356 case 0x96: _xchg_axsi(); break;
1357 case 0x97: _xchg_axdi(); break;
1358 case 0x98: _cbw(); break;
1359 case 0x99: _cwd(); break;
1360 case 0x9a: _call_far(); break;
1361 case 0x9b: _wait(); break;
1362 case 0x9c: _pushf(); break;
1363 case 0x9d: _popf(); break;
1364 case 0x9e: _sahf(); break;
1365 case 0x9f: _lahf(); break;
1366 case 0xa0: _mov_aldisp(); break;
1367 case 0xa1: _mov_axdisp(); break;
1368 case 0xa2: _mov_dispal(); break;
1369 case 0xa3: _mov_dispax(); break;
1370 case 0xa4: _movsb(); break;
1371 case 0xa5: _movsw(); break;
1372 case 0xa6: _cmpsb(); break;
1373 case 0xa7: _cmpsw(); break;
1374 case 0xa8: _test_ald8(); break;
1375 case 0xa9: _test_axd16(); break;
1376 case 0xaa: _stosb(); break;
1377 case 0xab: _stosw(); break;
1378 case 0xac: _lodsb(); break;
1379 case 0xad: _lodsw(); break;
1380 case 0xae: _scasb(); break;
1381 case 0xaf: _scasw(); break;
1382 case 0xb0: _mov_ald8(); break;
1383 case 0xb1: _mov_cld8(); break;
1384 case 0xb2: _mov_dld8(); break;
1385 case 0xb3: _mov_bld8(); break;
1386 case 0xb4: _mov_ahd8(); break;
1387 case 0xb5: _mov_chd8(); break;
1388 case 0xb6: _mov_dhd8(); break;
1389 case 0xb7: _mov_bhd8(); break;
1390 case 0xb8: _mov_axd16(); break;
1391 case 0xb9: _mov_cxd16(); break;
1392 case 0xba: _mov_dxd16(); break;
1393 case 0xbb: _mov_bxd16(); break;
1394 case 0xbc: _mov_spd16(); break;
1395 case 0xbd: _mov_bpd16(); break;
1396 case 0xbe: _mov_sid16(); break;
1397 case 0xbf: _mov_did16(); break;
1398 #if defined(HAS_V30)
1399 case 0xc0: _rotshft_bd8(); break;
1400 case 0xc1: _rotshft_wd8(); break;
1402 case 0xc0: _invalid(); break;
1403 case 0xc1: _invalid(); break;
1405 case 0xc2: _ret_d16(); break;
1406 case 0xc3: _ret(); break;
1407 case 0xc4: _les_dw(); break;
1408 case 0xc5: _lds_dw(); break;
1409 case 0xc6: _mov_bd8(); break;
1410 case 0xc7: _mov_wd16(); break;
1411 #if defined(HAS_V30)
1412 case 0xc8: _enter(); break;
1413 case 0xc9: _leav(); break; /* _leave() */
1415 case 0xc8: _invalid(); break;
1416 case 0xc9: _invalid(); break;
1418 case 0xca: _retf_d16(); break;
1419 case 0xcb: _retf(); break;
1420 case 0xcc: _int3(); break;
1421 case 0xcd: _int(); break;
1422 case 0xce: _into(); break;
1423 case 0xcf: _iret(); break;
1424 case 0xd0: _rotshft_b(); break;
1425 case 0xd1: _rotshft_w(); break;
1426 case 0xd2: _rotshft_bcl(); break;
1427 case 0xd3: _rotshft_wcl(); break;
1428 case 0xd4: _aam(); break;
1429 case 0xd5: _aad(); break;
1430 #if defined(HAS_V30)
1431 case 0xd6: _setalc(); break;
1433 case 0xd6: _invalid(); break;
1435 case 0xd7: _xlat(); break;
1436 case 0xd8: _escape(); break;
1437 case 0xd9: _escape(); break;
1438 case 0xda: _escape(); break;
1439 case 0xdb: _escape(); break;
1440 case 0xdc: _escape(); break;
1441 case 0xdd: _escape(); break;
1442 case 0xde: _escape(); break;
1443 case 0xdf: _escape(); break;
1444 case 0xe0: _loopne(); break;
1445 case 0xe1: _loope(); break;
1446 case 0xe2: _loop(); break;
1447 case 0xe3: _jcxz(); break;
1448 case 0xe4: _inal(); break;
1449 case 0xe5: _inax(); break;
1450 case 0xe6: _outal(); break;
1451 case 0xe7: _outax(); break;
1452 case 0xe8: _call_d16(); break;
1453 case 0xe9: _jmp_d16(); break;
1454 case 0xea: _jmp_far(); break;
1455 case 0xeb: _jmp_d8(); break;
1456 case 0xec: _inaldx(); break;
1457 case 0xed: _inaxdx(); break;
1458 case 0xee: _outdxal(); break;
1459 case 0xef: _outdxax(); break;
1460 case 0xf0: _lock(); break;
1461 case 0xf1: _invalid(); break;
1462 case 0xf2: _repne(); break;
1463 case 0xf3: _repe(); break;
1464 case 0xf4: _hlt(); break;
1465 case 0xf5: _cmc(); break;
1466 case 0xf6: _f6pre(); break;
1467 case 0xf7: _f7pre(); break;
1468 case 0xf8: _clc(); break;
1469 case 0xf9: _stc(); break;
1470 case 0xfa: _cli(); break;
1471 case 0xfb: _sti(); break;
1472 case 0xfc: _cld(); break;
1473 case 0xfd: _std(); break;
1474 case 0xfe: _fepre(); break;
1475 case 0xff: _ffpre(); break;
1476 default: _add_br8(); break;
1477 //default: __assume(0);
1481 inline void I86::_add_br8() /* Opcode 0x00 */
1484 icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
1486 PutbackRMByte(ModRM, dst);
1489 inline void I86::_add_wr16() /* Opcode 0x01 */
1492 icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
1494 PutbackRMWord(ModRM, dst);
1497 inline void I86::_add_r8b() /* Opcode 0x02 */
1500 icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
1502 RegByte(ModRM) = dst;
1505 inline void I86::_add_r16w() /* Opcode 0x03 */
1508 icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
1510 RegWord(ModRM) = dst;
1513 inline void I86::_add_ald8() /* Opcode 0x04 */
1516 icount -= timing.alu_ri8;
1521 inline void I86::_add_axd16() /* Opcode 0x05 */
1523 DEF_axd16(dst, src);
1524 icount -= timing.alu_ri16;
1529 inline void I86::_push_es() /* Opcode 0x06 */
1531 icount -= timing.push_seg;
1535 inline void I86::_pop_es() /* Opcode 0x07 */
1538 base[ES] = SegBase(ES);
1539 icount -= timing.pop_seg;
1542 inline void I86::_or_br8() /* Opcode 0x08 */
1545 icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
1547 PutbackRMByte(ModRM, dst);
1550 inline void I86::_or_wr16() /* Opcode 0x09 */
1553 icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
1555 PutbackRMWord(ModRM, dst);
1558 inline void I86::_or_r8b() /* Opcode 0x0a */
1561 icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
1563 RegByte(ModRM) = dst;
1566 inline void I86::_or_r16w() /* Opcode 0x0b */
1569 icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
1571 RegWord(ModRM) = dst;
1574 inline void I86::_or_ald8() /* Opcode 0x0c */
1577 icount -= timing.alu_ri8;
1582 inline void I86::_or_axd16() /* Opcode 0x0d */
1584 DEF_axd16(dst, src);
1585 icount -= timing.alu_ri16;
1590 inline void I86::_push_cs() /* Opcode 0x0e */
1592 icount -= timing.push_seg;
1596 #if defined(HAS_V30)
1597 inline void I86::_0fpre() /* Opcode 0x0f */
1599 static const uint16 bytes[] = {
1600 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768
1602 unsigned code = FETCH;
1608 case 0x10: /* 0F 10 47 30 - TEST1 [bx+30h], cl */
1611 tmp = regs.b[Mod_RM.RM.b[ModRM]];
1619 tmp2 = regs.b[CL] & 7;
1620 SetZF(tmp & bytes[tmp2]);
1622 case 0x11: /* 0F 11 47 30 - TEST1 [bx+30h], cl */
1625 tmp = regs.w[Mod_RM.RM.w[ModRM]];
1633 tmp2 = regs.b[CL] & 0xf;
1634 SetZF(tmp & bytes[tmp2]);
1636 case 0x12: /* 0F 12 [mod:000:r/m] - CLR1 reg/m8, cl */
1639 tmp = regs.b[Mod_RM.RM.b[ModRM]];
1647 tmp2 = regs.b[CL] & 7;
1648 tmp &= ~bytes[tmp2];
1649 PutbackRMByte(ModRM, tmp);
1651 case 0x13: /* 0F 13 [mod:000:r/m] - CLR1 reg/m16, cl */
1654 tmp = regs.w[Mod_RM.RM.w[ModRM]];
1662 tmp2 = regs.b[CL] & 0xf;
1663 tmp &= ~bytes[tmp2];
1664 PutbackRMWord(ModRM, tmp);
1666 case 0x14: /* 0F 14 47 30 - SET1 [bx+30h], cl */
1669 tmp = regs.b[Mod_RM.RM.b[ModRM]];
1677 tmp2 = regs.b[CL] & 7;
1679 PutbackRMByte(ModRM, tmp);
1681 case 0x15: /* 0F 15 C6 - SET1 si, cl */
1684 tmp = regs.w[Mod_RM.RM.w[ModRM]];
1692 tmp2 = regs.b[CL] & 0xf;
1694 PutbackRMWord(ModRM, tmp);
1696 case 0x16: /* 0F 16 C6 - NOT1 si, cl */
1699 tmp = regs.b[Mod_RM.RM.b[ModRM]];
1707 tmp2 = regs.b[CL] & 7;
1708 if(tmp & bytes[tmp2]) {
1709 tmp &= ~bytes[tmp2];
1713 PutbackRMByte(ModRM, tmp);
1715 case 0x17: /* 0F 17 C6 - NOT1 si, cl */
1718 tmp = regs.w[Mod_RM.RM.w[ModRM]];
1726 tmp2 = regs.b[CL] & 0xf;
1727 if(tmp & bytes[tmp2]) {
1728 tmp &= ~bytes[tmp2];
1732 PutbackRMWord(ModRM, tmp);
1734 case 0x18: /* 0F 18 XX - TEST1 [bx+30h], 07 */
1737 tmp = regs.b[Mod_RM.RM.b[ModRM]];
1747 SetZF(tmp & bytes[tmp2]);
1749 case 0x19: /* 0F 19 XX - TEST1 [bx+30h], 07 */
1752 tmp = regs.w[Mod_RM.RM.w[ModRM]];
1762 SetZF(tmp & bytes[tmp2]);
1764 case 0x1a: /* 0F 1A 06 - CLR1 si, cl */
1767 tmp = regs.b[Mod_RM.RM.b[ModRM]];
1777 tmp &= ~bytes[tmp2];
1778 PutbackRMByte(ModRM, tmp);
1780 case 0x1B: /* 0F 1B 06 - CLR1 si, cl */
1783 tmp = regs.w[Mod_RM.RM.w[ModRM]];
1793 tmp &= ~bytes[tmp2];
1794 PutbackRMWord(ModRM, tmp);
1796 case 0x1C: /* 0F 1C 47 30 - SET1 [bx+30h], cl */
1799 tmp = regs.b[Mod_RM.RM.b[ModRM]];
1810 PutbackRMByte(ModRM, tmp);
1812 case 0x1D: /* 0F 1D C6 - SET1 si, cl */
1815 tmp = regs.w[Mod_RM.RM.w[ModRM]];
1826 PutbackRMWord(ModRM, tmp);
1828 case 0x1e: /* 0F 1e C6 - NOT1 si, 07 */
1831 tmp = regs.b[Mod_RM.RM.b[ModRM]];
1841 if(tmp & bytes[tmp2]) {
1842 tmp &= ~bytes[tmp2];
1846 PutbackRMByte(ModRM, tmp);
1848 case 0x1f: /* 0F 1f C6 - NOT1 si, 07 */
1851 tmp = regs.w[Mod_RM.RM.w[ModRM]];
1861 if(tmp & bytes[tmp2]) {
1862 tmp &= ~bytes[tmp2];
1866 PutbackRMWord(ModRM, tmp);
1868 case 0x20: /* 0F 20 59 - add4s */
1870 /* length in words ! */
1871 int count = (regs.b[CL] + 1) / 2;
1872 unsigned di = regs.w[DI];
1873 unsigned si = regs.w[SI];
1876 CarryVal = 0; /* NOT ADC */
1877 for(int i = 0; i < count; i++) {
1878 tmp = GetMemB(DS, si);
1879 tmp2 = GetMemB(ES, di);
1880 int v1 = (tmp >> 4) * 10 + (tmp & 0xf);
1881 int v2 = (tmp2 >> 4) * 10 + (tmp2 & 0xf);
1882 int result = v1 + v2 + CarryVal;
1883 CarryVal = result > 99 ? 1 : 0;
1884 result = result % 100;
1885 v1 = ((result / 10) << 4) | (result % 10);
1886 PutMemB(ES, di, v1);
1894 icount -= 7 + 19 * count;
1897 case 0x22: /* 0F 22 59 - sub4s */
1899 int count = (regs.b[CL] + 1) / 2;
1900 unsigned di = regs.w[DI];
1901 unsigned si = regs.w[SI];
1904 CarryVal = 0; /* NOT ADC */
1905 for(int i = 0; i < count; i++) {
1906 tmp = GetMemB(ES, di);
1907 tmp2 = GetMemB(DS, si);
1908 int v1 = (tmp >> 4) * 10 + (tmp & 0xf);
1909 int v2 = (tmp2 >> 4) * 10 + (tmp2 & 0xf), result;
1910 if(v1 < (v2 + CarryVal)) {
1912 result = v1 - (v2 + CarryVal);
1915 result = v1 - (v2 + CarryVal);
1918 v1 = ((result / 10) << 4) | (result % 10);
1919 PutMemB(ES, di, v1);
1927 icount -= 7 + 19 * count;
1933 case 0x26: /* 0F 22 59 - cmp4s */
1935 int count = (regs.b[CL] + 1) / 2;
1936 unsigned di = regs.w[DI];
1937 unsigned si = regs.w[SI];
1940 CarryVal = 0; /* NOT ADC */
1941 for(int i = 0; i < count; i++) {
1942 tmp = GetMemB(ES, di);
1943 tmp2 = GetMemB(DS, si);
1944 int v1 = (tmp >> 4) * 10 + (tmp & 0xf);
1945 int v2 = (tmp2 >> 4) * 10 + (tmp2 & 0xf), result;
1946 if(v1 < (v2 + CarryVal)) {
1948 result = v1 - (v2 + CarryVal);
1951 result = v1 - (v2 + CarryVal);
1954 v1 = ((result / 10) << 4) | (result % 10);
1955 /* PutMemB(ES, di, v1); /* no store, only compare */
1963 icount -= 7 + 19 * (regs.b[CL] + 1);
1966 case 0x28: /* 0F 28 C7 - ROL4 bh */
1969 tmp = regs.b[Mod_RM.RM.b[ModRM]];
1978 tmp |= regs.b[AL] & 0xf;
1979 regs.b[AL] = (regs.b[AL] & 0xf0) | ((tmp >> 8) & 0xf);
1981 PutbackRMByte(ModRM, tmp);
1983 case 0x29: /* 0F 29 C7 - ROL4 bx */
1986 case 0x2A: /* 0F 2a c2 - ROR4 bh */
1989 tmp = regs.b[Mod_RM.RM.b[ModRM]];
1997 tmp2 = (regs.b[AL] & 0xf) << 4;
1998 regs.b[AL] = (regs.b[AL] & 0xf0) | (tmp & 0xf);
1999 tmp = tmp2 | (tmp >> 4);
2000 PutbackRMByte(ModRM, tmp);
2002 case 0x2B: /* 0F 2b c2 - ROR4 bx */
2005 case 0x2D: /* 0Fh 2Dh < 1111 1RRR> */
2009 case 0x31: /* 0F 31 [mod:reg:r/m] - INS reg8, reg8 or INS reg8, imm4 */
2012 tmp = regs.b[Mod_RM.RM.b[ModRM]];
2021 case 0x33: /* 0F 33 [mod:reg:r/m] - EXT reg8, reg8 or EXT reg8, imm4 */
2024 tmp = regs.b[Mod_RM.RM.b[ModRM]];
2055 case 0xff: /* 0F ff imm8 - BRKEM */
2064 inline void I86::_adc_br8() /* Opcode 0x10 */
2067 icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
2070 PutbackRMByte(ModRM, dst);
2073 inline void I86::_adc_wr16() /* Opcode 0x11 */
2076 icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
2079 PutbackRMWord(ModRM, dst);
2082 inline void I86::_adc_r8b() /* Opcode 0x12 */
2085 icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
2088 RegByte(ModRM) = dst;
2091 inline void I86::_adc_r16w() /* Opcode 0x13 */
2094 icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
2097 RegWord(ModRM) = dst;
2100 inline void I86::_adc_ald8() /* Opcode 0x14 */
2103 icount -= timing.alu_ri8;
2109 inline void I86::_adc_axd16() /* Opcode 0x15 */
2111 DEF_axd16(dst, src);
2112 icount -= timing.alu_ri16;
2118 inline void I86::_push_ss() /* Opcode 0x16 */
2121 icount -= timing.push_seg;
2124 inline void I86::_pop_ss() /* Opcode 0x17 */
2127 base[SS] = SegBase(SS);
2128 icount -= timing.pop_seg;
2129 instruction(FETCHOP); /* no interrupt before next instruction */
2132 inline void I86::_sbb_br8() /* Opcode 0x18 */
2135 icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
2138 PutbackRMByte(ModRM, dst);
2141 inline void I86::_sbb_wr16() /* Opcode 0x19 */
2144 icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
2147 PutbackRMWord(ModRM, dst);
2150 inline void I86::_sbb_r8b() /* Opcode 0x1a */
2153 icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
2156 RegByte(ModRM) = dst;
2159 inline void I86::_sbb_r16w() /* Opcode 0x1b */
2162 icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
2165 RegWord(ModRM) = dst;
2168 inline void I86::_sbb_ald8() /* Opcode 0x1c */
2171 icount -= timing.alu_ri8;
2177 inline void I86::_sbb_axd16() /* Opcode 0x1d */
2179 DEF_axd16(dst, src);
2180 icount -= timing.alu_ri16;
2186 inline void I86::_push_ds() /* Opcode 0x1e */
2189 icount -= timing.push_seg;
2192 inline void I86::_pop_ds() /* Opcode 0x1f */
2195 base[DS] = SegBase(DS);
2196 icount -= timing.push_seg;
2199 inline void I86::_and_br8() /* Opcode 0x20 */
2202 icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
2204 PutbackRMByte(ModRM, dst);
2207 inline void I86::_and_wr16() /* Opcode 0x21 */
2210 icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
2212 PutbackRMWord(ModRM, dst);
2215 inline void I86::_and_r8b() /* Opcode 0x22 */
2218 icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
2220 RegByte(ModRM) = dst;
2223 inline void I86::_and_r16w() /* Opcode 0x23 */
2226 icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
2228 RegWord(ModRM) = dst;
2231 inline void I86::_and_ald8() /* Opcode 0x24 */
2234 icount -= timing.alu_ri8;
2239 inline void I86::_and_axd16() /* Opcode 0x25 */
2241 DEF_axd16(dst, src);
2242 icount -= timing.alu_ri16;
2247 inline void I86::_es() /* Opcode 0x26 */
2251 icount -= timing.override;
2252 instruction(FETCHOP);
2255 inline void I86::_daa() /* Opcode 0x27 */
2257 if(AF || ((regs.b[AL] & 0xf) > 9)) {
2259 regs.b[AL] = tmp = regs.b[AL] + 6;
2261 CarryVal |= tmp & 0x100;
2264 if(CF || (regs.b[AL] > 0x9f)) {
2269 SetSZPF_Byte(regs.b[AL]);
2270 icount -= timing.daa;
2273 inline void I86::_sub_br8() /* Opcode 0x28 */
2276 icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
2278 PutbackRMByte(ModRM, dst);
2281 inline void I86::_sub_wr16() /* Opcode 0x29 */
2284 icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
2286 PutbackRMWord(ModRM, dst);
2289 inline void I86::_sub_r8b() /* Opcode 0x2a */
2292 icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
2294 RegByte(ModRM) = dst;
2297 inline void I86::_sub_r16w() /* Opcode 0x2b */
2300 icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
2302 RegWord(ModRM) = dst;
2305 inline void I86::_sub_ald8() /* Opcode 0x2c */
2308 icount -= timing.alu_ri8;
2313 inline void I86::_sub_axd16() /* Opcode 0x2d */
2315 DEF_axd16(dst, src);
2316 icount -= timing.alu_ri16;
2321 inline void I86::_cs() /* Opcode 0x2e */
2325 icount -= timing.override;
2326 instruction(FETCHOP);
2329 inline void I86::_das() /* Opcode 0x2f */
2331 uint8 tmpAL = regs.b[AL];
2332 if(AF || ((regs.b[AL] & 0xf) > 9)) {
2334 regs.b[AL] = tmp = regs.b[AL] - 6;
2336 CarryVal |= tmp & 0x100;
2339 if(CF || (tmpAL > 0x9f)) {
2344 SetSZPF_Byte(regs.b[AL]);
2345 icount -= timing.das;
2348 inline void I86::_xor_br8() /* Opcode 0x30 */
2351 icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
2353 PutbackRMByte(ModRM, dst);
2356 inline void I86::_xor_wr16() /* Opcode 0x31 */
2359 icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
2361 PutbackRMWord(ModRM, dst);
2364 inline void I86::_xor_r8b() /* Opcode 0x32 */
2367 icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
2369 RegByte(ModRM) = dst;
2372 inline void I86::_xor_r16w() /* Opcode 0x33 */
2375 icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
2377 RegWord(ModRM) = dst;
2380 inline void I86::_xor_ald8() /* Opcode 0x34 */
2383 icount -= timing.alu_ri8;
2388 inline void I86::_xor_axd16() /* Opcode 0x35 */
2390 DEF_axd16(dst, src);
2391 icount -= timing.alu_ri16;
2396 inline void I86::_ss() /* Opcode 0x36 */
2400 icount -= timing.override;
2401 instruction(FETCHOP);
2404 inline void I86::_aaa() /* Opcode 0x37 */
2407 if(regs.b[AL]>0xf9) {
2410 if(AF || ((regs.b[AL] & 0xf) > 9)) {
2412 regs.b[AH] += ALcarry;
2420 icount -= timing.aaa;
2423 inline void I86::_cmp_br8() /* Opcode 0x38 */
2426 icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
2430 inline void I86::_cmp_wr16() /* Opcode 0x39 */
2433 icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
2437 inline void I86::_cmp_r8b() /* Opcode 0x3a */
2440 icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
2444 inline void I86::_cmp_r16w() /* Opcode 0x3b */
2447 icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
2451 inline void I86::_cmp_ald8() /* Opcode 0x3c */
2454 icount -= timing.alu_ri8;
2458 inline void I86::_cmp_axd16() /* Opcode 0x3d */
2460 DEF_axd16(dst, src);
2461 icount -= timing.alu_ri16;
2465 inline void I86::_ds() /* Opcode 0x3e */
2469 icount -= timing.override;
2470 instruction(FETCHOP);
2473 inline void I86::_aas() /* Opcode 0x3f */
2476 if(regs.b[AL] > 0xf9) {
2479 if(AF || ((regs.b[AL] & 0xf) > 9)) {
2489 icount -= timing.aas;
2492 #define IncWordReg(Reg) { \
2493 unsigned tmp = (unsigned)regs.w[Reg]; \
2494 unsigned tmp1 = tmp + 1; \
2495 SetOFW_Add(tmp1, tmp, 1); \
2496 SetAF(tmp1, tmp, 1); \
2497 SetSZPF_Word(tmp1); \
2498 regs.w[Reg] = tmp1; \
2499 icount -= timing.incdec_r16; \
2502 inline void I86::_inc_ax() /* Opcode 0x40 */
2507 inline void I86::_inc_cx() /* Opcode 0x41 */
2512 inline void I86::_inc_dx() /* Opcode 0x42 */
2517 inline void I86::_inc_bx() /* Opcode 0x43 */
2522 inline void I86::_inc_sp() /* Opcode 0x44 */
2527 inline void I86::_inc_bp() /* Opcode 0x45 */
2532 inline void I86::_inc_si() /* Opcode 0x46 */
2537 inline void I86::_inc_di() /* Opcode 0x47 */
2542 #define DecWordReg(Reg) { \
2543 unsigned tmp = (unsigned)regs.w[Reg]; \
2544 unsigned tmp1 = tmp - 1; \
2545 SetOFW_Sub(tmp1, 1, tmp); \
2546 SetAF(tmp1, tmp, 1); \
2547 SetSZPF_Word(tmp1); \
2548 regs.w[Reg] = tmp1; \
2549 icount -= timing.incdec_r16; \
2552 inline void I86::_dec_ax() /* Opcode 0x48 */
2557 inline void I86::_dec_cx() /* Opcode 0x49 */
2562 inline void I86::_dec_dx() /* Opcode 0x4a */
2567 inline void I86::_dec_bx() /* Opcode 0x4b */
2572 inline void I86::_dec_sp() /* Opcode 0x4c */
2577 inline void I86::_dec_bp() /* Opcode 0x4d */
2582 inline void I86::_dec_si() /* Opcode 0x4e */
2587 inline void I86::_dec_di() /* Opcode 0x4f */
2592 inline void I86::_push_ax() /* Opcode 0x50 */
2594 icount -= timing.push_r16;
2598 inline void I86::_push_cx() /* Opcode 0x51 */
2600 icount -= timing.push_r16;
2604 inline void I86::_push_dx() /* Opcode 0x52 */
2606 icount -= timing.push_r16;
2610 inline void I86::_push_bx() /* Opcode 0x53 */
2612 icount -= timing.push_r16;
2616 inline void I86::_push_sp() /* Opcode 0x54 */
2618 unsigned tmp = regs.w[SP];
2620 icount -= timing.push_r16;
2624 inline void I86::_push_bp() /* Opcode 0x55 */
2626 icount -= timing.push_r16;
2630 inline void I86::_push_si() /* Opcode 0x56 */
2632 icount -= timing.push_r16;
2636 inline void I86::_push_di() /* Opcode 0x57 */
2638 icount -= timing.push_r16;
2642 inline void I86::_pop_ax() /* Opcode 0x58 */
2644 icount -= timing.pop_r16;
2648 inline void I86::_pop_cx() /* Opcode 0x59 */
2650 icount -= timing.pop_r16;
2654 inline void I86::_pop_dx() /* Opcode 0x5a */
2656 icount -= timing.pop_r16;
2660 inline void I86::_pop_bx() /* Opcode 0x5b */
2662 icount -= timing.pop_r16;
2666 inline void I86::_pop_sp() /* Opcode 0x5c */
2670 icount -= timing.pop_r16;
2675 inline void I86::_pop_bp() /* Opcode 0x5d */
2677 icount -= timing.pop_r16;
2681 inline void I86::_pop_si() /* Opcode 0x5e */
2683 icount -= timing.pop_r16;
2687 inline void I86::_pop_di() /* Opcode 0x5f */
2689 icount -= timing.pop_r16;
2693 inline void I86::_pusha() /* Opcode 0x60 */
2695 unsigned tmp = regs.w[SP];
2697 icount -= timing.pusha;
2708 inline void I86::_popa() /* Opcode 0x61 */
2712 icount -= timing.popa;
2723 inline void I86::_bound() /* Opcode 0x62 */
2725 unsigned ModRM = FETCHOP;
2726 int low = (int16)GetRMWord(ModRM);
2727 int high = (int16)GetNextRMWord;
2728 int tmp = (int16)RegWord(ModRM);
2729 if(tmp < low || tmp>high) {
2730 pc -= (seg_prefix ? 3 : 2);
2731 interrupt(BOUNDS_CHECK_FAULT);
2733 icount -= timing.bound;
2736 inline void I86::_repc(int flagval)
2739 unsigned next = FETCHOP;
2740 unsigned count = regs.w[CX];
2743 case 0x26: /* ES: */
2749 case 0x2e: /* CS: */
2755 case 0x36: /* SS: */
2761 case 0x3e: /* DS: */
2767 case 0x6c: /* REP INSB */
2768 icount -= 9 - count;
2769 for(; (CF == flagval) && (count > 0); count--) {
2774 case 0x6d: /* REP INSW */
2775 icount -= 9 - count;
2776 for(; (CF == flagval) && (count > 0); count--) {
2781 case 0x6e: /* REP OUTSB */
2782 icount -= 9 - count;
2783 for(; (CF == flagval) && (count > 0); count--) {
2788 case 0x6f: /* REP OUTSW */
2789 icount -= 9 - count;
2790 for(; (CF == flagval) && (count > 0); count--) {
2795 case 0xa4: /* REP MOVSB */
2796 icount -= 9 - count;
2797 for(; (CF == flagval) && (count > 0); count--) {
2802 case 0xa5: /* REP MOVSW */
2803 icount -= 9 - count;
2804 for(; (CF == flagval) && (count > 0); count--) {
2809 case 0xa6: /* REP(N)E CMPSB */
2811 for(ZeroVal = !flagval; (ZF == flagval) && (CF == flagval) && (count > 0); count--) {
2816 case 0xa7: /* REP(N)E CMPSW */
2818 for(ZeroVal = !flagval; (ZF == flagval) && (CF == flagval) && (count > 0); count--) {
2823 case 0xaa: /* REP STOSB */
2824 icount -= 9 - count;
2825 for(; (CF == flagval) && (count > 0); count--) {
2830 case 0xab: /* REP STOSW */
2831 icount -= 9 - count;
2832 for(; (CF == flagval) && (count > 0); count--) {
2837 case 0xac: /* REP LODSB */
2839 for(; (CF == flagval) && (count > 0); count--) {
2844 case 0xad: /* REP LODSW */
2846 for(; (CF == flagval) && (count > 0); count--) {
2851 case 0xae: /* REP(N)E SCASB */
2853 for(ZeroVal = !flagval; (ZF == flagval) && (CF == flagval) && (count > 0); count--) {
2858 case 0xaf: /* REP(N)E SCASW */
2860 for(ZeroVal = !flagval; (ZF == flagval) && (CF == flagval) && (count > 0); count--) {
2871 inline void I86::_push_d16() /* Opcode 0x68 */
2873 unsigned tmp = FETCH;
2874 icount -= timing.push_imm;
2879 inline void I86::_imul_d16() /* Opcode 0x69 */
2882 unsigned src2 = FETCH;
2883 src += (FETCH << 8);
2884 icount -= (ModRM >= 0xc0) ? timing.imul_rri16 : timing.imul_rmi16;
2885 dst = (int32)((int16)src) * (int32)((int16)src2);
2886 CarryVal = OverVal = (((int32)dst) >> 15 != 0) && (((int32)dst) >> 15 != -1);
2887 RegWord(ModRM) = (uint16)dst;
2890 inline void I86::_push_d8() /* Opcode 0x6a */
2892 unsigned tmp = (uint16)((int16)((int8)FETCH));
2893 icount -= timing.push_imm;
2897 inline void I86::_imul_d8() /* Opcode 0x6b */
2900 unsigned src2 = (uint16)((int16)((int8)FETCH));
2901 icount -= (ModRM >= 0xc0) ? timing.imul_rri8 : timing.imul_rmi8;
2902 dst = (int32)((int16)src) * (int32)((int16)src2);
2903 CarryVal = OverVal = (((int32)dst) >> 15 != 0) && (((int32)dst) >> 15 != -1);
2904 RegWord(ModRM) = (uint16)dst;
2907 inline void I86::_insb() /* Opcode 0x6c */
2909 icount -= timing.ins8;
2910 PutMemB(ES, regs.w[DI], read_port_byte(regs.w[DX]));
2911 regs.w[DI] += DirVal;
2914 inline void I86::_insw() /* Opcode 0x6d */
2916 icount -= timing.ins16;
2917 PutMemW(ES, regs.w[DI], read_port_word(regs.w[DX]));
2918 regs.w[DI] += 2 * DirVal;
2921 inline void I86::_outsb() /* Opcode 0x6e */
2923 icount -= timing.outs8;
2924 write_port_byte(regs.w[DX], GetMemB(DS, regs.w[SI]));
2925 regs.w[SI] += DirVal; /* GOL 11/27/01 */
2928 inline void I86::_outsw() /* Opcode 0x6f */
2930 icount -= timing.outs16;
2931 write_port_word(regs.w[DX], GetMemW(DS, regs.w[SI]));
2932 regs.w[SI] += 2 * DirVal; /* GOL 11/27/01 */
2935 inline void I86::_jo() /* Opcode 0x70 */
2937 int tmp = (int)((int8)FETCH);
2940 icount -= timing.jcc_t;
2942 icount -= timing.jcc_nt;
2946 inline void I86::_jno() /* Opcode 0x71 */
2948 int tmp = (int)((int8)FETCH);
2951 icount -= timing.jcc_t;
2953 icount -= timing.jcc_nt;
2957 inline void I86::_jb() /* Opcode 0x72 */
2959 int tmp = (int)((int8)FETCH);
2962 icount -= timing.jcc_t;
2964 icount -= timing.jcc_nt;
2968 inline void I86::_jnb() /* Opcode 0x73 */
2970 int tmp = (int)((int8)FETCH);
2973 icount -= timing.jcc_t;
2975 icount -= timing.jcc_nt;
2979 inline void I86::_jz() /* Opcode 0x74 */
2981 int tmp = (int)((int8)FETCH);
2984 icount -= timing.jcc_t;
2986 icount -= timing.jcc_nt;
2990 inline void I86::_jnz() /* Opcode 0x75 */
2992 int tmp = (int)((int8)FETCH);
2995 icount -= timing.jcc_t;
2997 icount -= timing.jcc_nt;
3001 inline void I86::_jbe() /* Opcode 0x76 */
3003 int tmp = (int)((int8)FETCH);
3006 icount -= timing.jcc_t;
3008 icount -= timing.jcc_nt;
3012 inline void I86::_jnbe() /* Opcode 0x77 */
3014 int tmp = (int)((int8)FETCH);
3017 icount -= timing.jcc_t;
3019 icount -= timing.jcc_nt;
3023 inline void I86::_js() /* Opcode 0x78 */
3025 int tmp = (int)((int8)FETCH);
3028 icount -= timing.jcc_t;
3030 icount -= timing.jcc_nt;
3034 inline void I86::_jns() /* Opcode 0x79 */
3036 int tmp = (int)((int8)FETCH);
3039 icount -= timing.jcc_t;
3041 icount -= timing.jcc_nt;
3045 inline void I86::_jp() /* Opcode 0x7a */
3047 int tmp = (int)((int8)FETCH);
3050 icount -= timing.jcc_t;
3052 icount -= timing.jcc_nt;
3056 inline void I86::_jnp() /* Opcode 0x7b */
3058 int tmp = (int)((int8)FETCH);
3061 icount -= timing.jcc_t;
3063 icount -= timing.jcc_nt;
3067 inline void I86::_jl() /* Opcode 0x7c */
3069 int tmp = (int)((int8)FETCH);
3070 if((SF!= OF) && !ZF) {
3072 icount -= timing.jcc_t;
3074 icount -= timing.jcc_nt;
3078 inline void I86::_jnl() /* Opcode 0x7d */
3080 int tmp = (int)((int8)FETCH);
3081 if(ZF || (SF == OF)) {
3083 icount -= timing.jcc_t;
3085 icount -= timing.jcc_nt;
3089 inline void I86::_jle() /* Opcode 0x7e */
3091 int tmp = (int)((int8)FETCH);
3092 if(ZF || (SF!= OF)) {
3094 icount -= timing.jcc_t;
3096 icount -= timing.jcc_nt;
3100 inline void I86::_jnle() /* Opcode 0x7f */
3102 int tmp = (int)((int8)FETCH);
3103 if((SF == OF) && !ZF) {
3105 icount -= timing.jcc_t;
3107 icount -= timing.jcc_nt;
3111 inline void I86::_80pre() /* Opcode 0x80 */
3113 unsigned ModRM = FETCHOP;
3114 unsigned dst = GetRMByte(ModRM);
3115 unsigned src = FETCH;
3117 switch((ModRM >> 3) & 7) {
3118 case 0: /* ADD eb, d8 */
3120 PutbackRMByte(ModRM, dst);
3121 icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
3123 case 1: /* OR eb, d8 */
3125 PutbackRMByte(ModRM, dst);
3126 icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
3128 case 2: /* ADC eb, d8 */
3131 PutbackRMByte(ModRM, dst);
3132 icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
3134 case 3: /* SBB eb, b8 */
3137 PutbackRMByte(ModRM, dst);
3138 icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
3140 case 4: /* AND eb, d8 */
3142 PutbackRMByte(ModRM, dst);
3143 icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
3145 case 5: /* SUB eb, d8 */
3147 PutbackRMByte(ModRM, dst);
3148 icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
3150 case 6: /* XOR eb, d8 */
3152 PutbackRMByte(ModRM, dst);
3153 icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
3155 case 7: /* CMP eb, d8 */
3157 icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8_ro;
3165 inline void I86::_81pre() /* Opcode 0x81 */
3167 unsigned ModRM = FETCH;
3168 unsigned dst = GetRMWord(ModRM);
3169 unsigned src = FETCH;
3170 src += (FETCH << 8);
3172 switch((ModRM >> 3) & 7) {
3173 case 0: /* ADD ew, d16 */
3175 PutbackRMWord(ModRM, dst);
3176 icount -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
3178 case 1: /* OR ew, d16 */
3180 PutbackRMWord(ModRM, dst);
3181 icount -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
3183 case 2: /* ADC ew, d16 */
3186 PutbackRMWord(ModRM, dst);
3187 icount -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
3189 case 3: /* SBB ew, d16 */
3192 PutbackRMWord(ModRM, dst);
3193 icount -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
3195 case 4: /* AND ew, d16 */
3197 PutbackRMWord(ModRM, dst);
3198 icount -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
3200 case 5: /* SUB ew, d16 */
3202 PutbackRMWord(ModRM, dst);
3203 icount -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
3205 case 6: /* XOR ew, d16 */
3207 PutbackRMWord(ModRM, dst);
3208 icount -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
3210 case 7: /* CMP ew, d16 */
3212 icount -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16_ro;
3220 inline void I86::_82pre() /* Opcode 0x82 */
3222 unsigned ModRM = FETCH;
3223 unsigned dst = GetRMByte(ModRM);
3224 unsigned src = FETCH;
3226 switch((ModRM >> 3) & 7) {
3227 case 0: /* ADD eb, d8 */
3229 PutbackRMByte(ModRM, dst);
3230 icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
3232 case 1: /* OR eb, d8 */
3234 PutbackRMByte(ModRM, dst);
3235 icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
3237 case 2: /* ADC eb, d8 */
3240 PutbackRMByte(ModRM, dst);
3241 icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
3243 case 3: /* SBB eb, d8 */
3246 PutbackRMByte(ModRM, dst);
3247 icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
3249 case 4: /* AND eb, d8 */
3251 PutbackRMByte(ModRM, dst);
3252 icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
3254 case 5: /* SUB eb, d8 */
3256 PutbackRMByte(ModRM, dst);
3257 icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
3259 case 6: /* XOR eb, d8 */
3261 PutbackRMByte(ModRM, dst);
3262 icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
3264 case 7: /* CMP eb, d8 */
3266 icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8_ro;
3274 inline void I86::_83pre() /* Opcode 0x83 */
3276 unsigned ModRM = FETCH;
3277 unsigned dst = GetRMWord(ModRM);
3278 unsigned src = (uint16)((int16)((int8)FETCH));
3280 switch((ModRM >> 3) & 7) {
3281 case 0: /* ADD ew, d16 */
3283 PutbackRMWord(ModRM, dst);
3284 icount -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
3286 case 1: /* OR ew, d16 */
3288 PutbackRMWord(ModRM, dst);
3289 icount -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
3291 case 2: /* ADC ew, d16 */
3294 PutbackRMWord(ModRM, dst);
3295 icount -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
3297 case 3: /* SBB ew, d16 */
3300 PutbackRMWord(ModRM, dst);
3301 icount -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
3303 case 4: /* AND ew, d16 */
3305 PutbackRMWord(ModRM, dst);
3306 icount -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
3308 case 5: /* SUB ew, d16 */
3310 PutbackRMWord(ModRM, dst);
3311 icount -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
3313 case 6: /* XOR ew, d16 */
3315 PutbackRMWord(ModRM, dst);
3316 icount -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
3318 case 7: /* CMP ew, d16 */
3320 icount -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8_ro;
3328 inline void I86::_test_br8() /* Opcode 0x84 */
3331 icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
3335 inline void I86::_test_wr16() /* Opcode 0x85 */
3338 icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
3342 inline void I86::_xchg_br8() /* Opcode 0x86 */
3345 icount -= (ModRM >= 0xc0) ? timing.xchg_rr8 : timing.xchg_rm8;
3346 RegByte(ModRM) = dst;
3347 PutbackRMByte(ModRM, src);
3350 inline void I86::_xchg_wr16() /* Opcode 0x87 */
3353 icount -= (ModRM >= 0xc0) ? timing.xchg_rr16 : timing.xchg_rm16;
3354 RegWord(ModRM) = dst;
3355 PutbackRMWord(ModRM, src);
3358 inline void I86::_mov_br8() /* Opcode 0x88 */
3360 unsigned ModRM = FETCH;
3361 uint8 src = RegByte(ModRM);
3362 icount -= (ModRM >= 0xc0) ? timing.mov_rr8 : timing.mov_mr8;
3363 PutRMByte(ModRM, src);
3366 inline void I86::_mov_wr16() /* Opcode 0x89 */
3368 unsigned ModRM = FETCH;
3369 uint16 src = RegWord(ModRM);
3370 icount -= (ModRM >= 0xc0) ? timing.mov_rr16 : timing.mov_mr16;
3371 PutRMWord(ModRM, src);
3374 inline void I86::_mov_r8b() /* Opcode 0x8a */
3376 unsigned ModRM = FETCH;
3377 uint8 src = GetRMByte(ModRM);
3378 icount -= (ModRM >= 0xc0) ? timing.mov_rr8 : timing.mov_rm8;
3379 RegByte(ModRM) = src;
3382 inline void I86::_mov_r16w() /* Opcode 0x8b */
3384 unsigned ModRM = FETCH;
3385 uint16 src = GetRMWord(ModRM);
3386 icount -= (ModRM >= 0xc0) ? timing.mov_rr8 : timing.mov_rm16;
3387 RegWord(ModRM) = src;
3390 inline void I86::_mov_wsreg() /* Opcode 0x8c */
3392 unsigned ModRM = FETCH;
3393 icount -= (ModRM >= 0xc0) ? timing.mov_rs : timing.mov_ms;
3395 return; /* 1xx is invalid */
3397 PutRMWord(ModRM, sregs[(ModRM & 0x38) >> 3]);
3400 inline void I86::_lea() /* Opcode 0x8d */
3402 unsigned ModRM = FETCH;
3403 icount -= timing.lea;
3405 RegWord(ModRM) = eo; /* effective offset (no segment part) */
3408 inline void I86::_mov_sregw() /* Opcode 0x8e */
3410 unsigned ModRM = FETCH;
3411 uint16 src = GetRMWord(ModRM);
3413 icount -= (ModRM >= 0xc0) ? timing.mov_sr : timing.mov_sm;
3414 switch((ModRM >> 3) & 7) {
3415 case 0: /* mov es, ew */
3417 base[ES] = SegBase(ES);
3419 case 1: /* mov cs, ew */
3420 break; /* doesn't do a jump far */
3421 case 2: /* mov ss, ew */
3423 base[SS] = SegBase(SS); /* no interrupt allowed before next instr */
3424 instruction(FETCHOP);
3426 case 3: /* mov ds, ew */
3428 base[DS] = SegBase(DS);
3441 inline void I86::_popw() /* Opcode 0x8f */
3443 unsigned ModRM = FETCH;
3446 icount -= (ModRM >= 0xc0) ? timing.pop_r16 : timing.pop_m16;
3447 PutRMWord(ModRM, tmp);
3450 #define XchgAXReg(Reg) { \
3452 tmp = regs.w[Reg]; \
3453 regs.w[Reg] = regs.w[AX]; \
3455 icount -= timing.xchg_ar16; \
3458 inline void I86::_nop() /* Opcode 0x90 */
3460 /* this is XchgAXReg(AX); */
3461 icount -= timing.nop;
3464 inline void I86::_xchg_axcx() /* Opcode 0x91 */
3469 inline void I86::_xchg_axdx() /* Opcode 0x92 */
3474 inline void I86::_xchg_axbx() /* Opcode 0x93 */
3479 inline void I86::_xchg_axsp() /* Opcode 0x94 */
3484 inline void I86::_xchg_axbp() /* Opcode 0x95 */
3489 inline void I86::_xchg_axsi() /* Opcode 0x96 */
3494 inline void I86::_xchg_axdi() /* Opcode 0x97 */
3499 inline void I86::_cbw() /* Opcode 0x98 */
3501 icount -= timing.cbw;
3502 regs.b[AH] = (regs.b[AL] & 0x80) ? 0xff : 0;
3505 inline void I86::_cwd() /* Opcode 0x99 */
3507 icount -= timing.cwd;
3508 regs.w[DX] = (regs.b[AH] & 0x80) ? 0xffff : 0;
3511 inline void I86::_call_far() /* Opcode 0x9a */
3525 sregs[CS] = (uint16)tmp2;
3526 base[CS] = SegBase(CS);
3527 pc = (base[CS] + (uint16)tmp) & AMASK;
3528 #ifdef I86_PSEUDO_BIOS
3529 if(d_bios && d_bios->bios_call_i86(pc, regs.w, sregs, &ZeroVal, &CarryVal)) {
3534 icount -= timing.call_far;
3537 inline void I86::_wait() /* Opcode 0x9b */
3542 icount -= timing.wait;
3545 inline void I86::_pushf() /* Opcode 0x9c */
3548 icount -= timing.pushf;
3550 tmp = CompressFlags();
3554 inline void I86::_popf() /* Opcode 0x9d */
3558 icount -= timing.popf;
3565 /* if the IF is set, and an interrupt is pending, signal an interrupt */
3566 if(IF && (int_state & INT_REQ_BIT)) {
3571 inline void I86::_sahf() /* Opcode 0x9e */
3573 unsigned tmp = (CompressFlags() & 0xff00) | (regs.b[AH] & 0xd5);
3574 icount -= timing.sahf;
3578 inline void I86::_lahf() /* Opcode 0x9f */
3580 regs.b[AH] = CompressFlags() & 0xff;
3581 icount -= timing.lahf;
3584 inline void I86::_mov_aldisp() /* Opcode 0xa0 */
3591 icount -= timing.mov_am8;
3592 regs.b[AL] = GetMemB(DS, addr);
3595 inline void I86::_mov_axdisp() /* Opcode 0xa1 */
3602 icount -= timing.mov_am16;
3603 regs.w[AX] = GetMemW(DS, addr);
3606 inline void I86::_mov_dispal() /* Opcode 0xa2 */
3613 icount -= timing.mov_ma8;
3614 PutMemB(DS, addr, regs.b[AL]);
3617 inline void I86::_mov_dispax() /* Opcode 0xa3 */
3624 icount -= timing.mov_ma16;
3625 PutMemW(DS, addr, regs.w[AX]);
3628 inline void I86::_movsb() /* Opcode 0xa4 */
3630 uint8 tmp = GetMemB(DS, regs.w[SI]);
3631 PutMemB(ES, regs.w[DI], tmp);
3632 regs.w[DI] += DirVal;
3633 regs.w[SI] += DirVal;
3634 icount -= timing.movs8;
3637 inline void I86::_movsw() /* Opcode 0xa5 */
3639 uint16 tmp = GetMemW(DS, regs.w[SI]);
3640 PutMemW(ES, regs.w[DI], tmp);
3641 regs.w[DI] += 2 * DirVal;
3642 regs.w[SI] += 2 * DirVal;
3643 icount -= timing.movs16;
3646 inline void I86::_cmpsb() /* Opcode 0xa6 */
3648 unsigned dst = GetMemB(ES, regs.w[DI]);
3649 unsigned src = GetMemB(DS, regs.w[SI]);
3650 SUBB(src, dst); /* opposite of the usual convention */
3651 regs.w[DI] += DirVal;
3652 regs.w[SI] += DirVal;
3653 icount -= timing.cmps8;
3656 inline void I86::_cmpsw() /* Opcode 0xa7 */
3658 unsigned dst = GetMemW(ES, regs.w[DI]);
3659 unsigned src = GetMemW(DS, regs.w[SI]);
3660 SUBW(src, dst); /* opposite of the usual convention */
3661 regs.w[DI] += 2 * DirVal;
3662 regs.w[SI] += 2 * DirVal;
3663 icount -= timing.cmps16;
3666 inline void I86::_test_ald8() /* Opcode 0xa8 */
3669 icount -= timing.alu_ri8;
3673 inline void I86::_test_axd16() /* Opcode 0xa9 */
3675 DEF_axd16(dst, src);
3676 icount -= timing.alu_ri16;
3680 inline void I86::_stosb() /* Opcode 0xaa */
3682 PutMemB(ES, regs.w[DI], regs.b[AL]);
3683 regs.w[DI] += DirVal;
3684 icount -= timing.stos8;
3687 inline void I86::_stosw() /* Opcode 0xab */
3689 PutMemW(ES, regs.w[DI], regs.w[AX]);
3690 regs.w[DI] += 2 * DirVal;
3691 icount -= timing.stos16;
3694 inline void I86::_lodsb() /* Opcode 0xac */
3696 regs.b[AL] = GetMemB(DS, regs.w[SI]);
3697 regs.w[SI] += DirVal;
3698 icount -= timing.lods8;
3701 inline void I86::_lodsw() /* Opcode 0xad */
3703 regs.w[AX] = GetMemW(DS, regs.w[SI]);
3704 regs.w[SI] += 2 * DirVal;
3705 icount -= timing.lods16;
3708 inline void I86::_scasb() /* Opcode 0xae */
3710 unsigned src = GetMemB(ES, regs.w[DI]);
3711 unsigned dst = regs.b[AL];
3713 regs.w[DI] += DirVal;
3714 icount -= timing.scas8;
3717 inline void I86::_scasw() /* Opcode 0xaf */
3719 unsigned src = GetMemW(ES, regs.w[DI]);
3720 unsigned dst = regs.w[AX];
3722 regs.w[DI] += 2 * DirVal;
3723 icount -= timing.scas16;
3726 inline void I86::_mov_ald8() /* Opcode 0xb0 */
3729 icount -= timing.mov_ri8;
3732 inline void I86::_mov_cld8() /* Opcode 0xb1 */
3735 icount -= timing.mov_ri8;
3738 inline void I86::_mov_dld8() /* Opcode 0xb2 */
3741 icount -= timing.mov_ri8;
3744 inline void I86::_mov_bld8() /* Opcode 0xb3 */
3747 icount -= timing.mov_ri8;
3750 inline void I86::_mov_ahd8() /* Opcode 0xb4 */
3753 icount -= timing.mov_ri8;
3756 inline void I86::_mov_chd8() /* Opcode 0xb5 */
3759 icount -= timing.mov_ri8;
3762 inline void I86::_mov_dhd8() /* Opcode 0xb6 */
3765 icount -= timing.mov_ri8;
3768 inline void I86::_mov_bhd8() /* Opcode 0xb7 */
3771 icount -= timing.mov_ri8;
3774 inline void I86::_mov_axd16() /* Opcode 0xb8 */
3778 icount -= timing.mov_ri16;
3781 inline void I86::_mov_cxd16() /* Opcode 0xb9 */
3785 icount -= timing.mov_ri16;
3788 inline void I86::_mov_dxd16() /* Opcode 0xba */
3792 icount -= timing.mov_ri16;
3795 inline void I86::_mov_bxd16() /* Opcode 0xbb */
3799 icount -= timing.mov_ri16;
3802 inline void I86::_mov_spd16() /* Opcode 0xbc */
3804 regs.b[SPL] = FETCH;
3805 regs.b[SPH] = FETCH;
3806 icount -= timing.mov_ri16;
3809 inline void I86::_mov_bpd16() /* Opcode 0xbd */
3811 regs.b[BPL] = FETCH;
3812 regs.b[BPH] = FETCH;
3813 icount -= timing.mov_ri16;
3816 inline void I86::_mov_sid16() /* Opcode 0xbe */
3818 regs.b[SIL] = FETCH;
3819 regs.b[SIH] = FETCH;
3820 icount -= timing.mov_ri16;
3823 inline void I86::_mov_did16() /* Opcode 0xbf */
3825 regs.b[DIL] = FETCH;
3826 regs.b[DIH] = FETCH;
3827 icount -= timing.mov_ri16;
3830 inline void I86::_rotshft_bd8() /* Opcode 0xc0 */
3832 unsigned ModRM = FETCH;
3833 unsigned count = FETCH;
3835 rotate_shift_byte(ModRM, count);
3838 inline void I86::_rotshft_wd8() /* Opcode 0xc1 */
3840 unsigned ModRM = FETCH;
3841 unsigned count = FETCH;
3843 rotate_shift_word(ModRM, count);
3846 inline void I86::_ret_d16() /* Opcode 0xc2 */
3848 unsigned count = FETCH;
3849 count += FETCH << 8;
3851 pc = (pc + base[CS]) & AMASK;
3852 regs.w[SP] += count;
3853 icount -= timing.ret_near_imm;
3856 inline void I86::_ret() /* Opcode 0xc3 */
3859 pc = (pc + base[CS]) & AMASK;
3860 icount -= timing.ret_near;
3863 inline void I86::_les_dw() /* Opcode 0xc4 */
3865 unsigned ModRM = FETCH;
3866 uint16 tmp = GetRMWord(ModRM);
3867 RegWord(ModRM) = tmp;
3868 sregs[ES] = GetNextRMWord;
3869 base[ES] = SegBase(ES);
3870 icount -= timing.load_ptr;
3873 inline void I86::_lds_dw() /* Opcode 0xc5 */
3875 unsigned ModRM = FETCH;
3876 uint16 tmp = GetRMWord(ModRM);
3877 RegWord(ModRM) = tmp;
3878 sregs[DS] = GetNextRMWord;
3879 base[DS] = SegBase(DS);
3880 icount -= timing.load_ptr;
3883 inline void I86::_mov_bd8() /* Opcode 0xc6 */
3885 unsigned ModRM = FETCH;
3886 icount -= (ModRM >= 0xc0) ? timing.mov_ri8 : timing.mov_mi8;
3887 PutImmRMByte(ModRM);
3890 inline void I86::_mov_wd16() /* Opcode 0xc7 */
3892 unsigned ModRM = FETCH;
3893 icount -= (ModRM >= 0xc0) ? timing.mov_ri16 : timing.mov_mi16;
3894 PutImmRMWord(ModRM);
3897 inline void I86::_enter() /* Opcode 0xc8 */
3899 unsigned nb = FETCH;
3904 icount -= (level == 0) ? timing.enter0 : (level == 1) ? timing.enter1 : timing.enter_base + level * timing.enter_count;
3906 regs.w[BP] = regs.w[SP];
3908 for(i = 1; i < level; i++) {
3909 PUSH(GetMemW(SS, regs.w[BP] - i * 2));
3916 inline void I86::_leav() /* Opcode 0xc9 */
3918 icount -= timing.leave;
3919 regs.w[SP] = regs.w[BP];
3923 inline void I86::_retf_d16() /* Opcode 0xca */
3925 unsigned count = FETCH;
3926 count += FETCH << 8;
3929 base[CS] = SegBase(CS);
3930 pc = (pc + base[CS]) & AMASK;
3931 regs.w[SP] += count;
3932 icount -= timing.ret_far_imm;
3935 inline void I86::_retf() /* Opcode 0xcb */
3939 base[CS] = SegBase(CS);
3940 pc = (pc + base[CS]) & AMASK;
3941 icount -= timing.ret_far;
3944 inline void I86::_int3() /* Opcode 0xcc */
3946 icount -= timing.int3;
3950 inline void I86::_int() /* Opcode 0xcd */
3952 unsigned int_num = FETCH;
3953 icount -= timing.int_imm;
3954 #ifdef I86_PSEUDO_BIOS
3955 if(d_bios && d_bios->bios_int_i86(int_num, regs.w, sregs, &ZeroVal, &CarryVal)) {
3963 inline void I86::_into() /* Opcode 0xce */
3966 icount -= timing.into_t;
3967 interrupt(OVERFLOW_TRAP);
3969 icount -= timing.into_nt;
3973 inline void I86::_iret() /* Opcode 0xcf */
3975 icount -= timing.iret;
3978 base[CS] = SegBase(CS);
3979 pc = (pc + base[CS]) & AMASK;
3982 /* if the IF is set, and an interrupt is pending, signal an interrupt */
3983 if(IF && (int_state & INT_REQ_BIT)) {
3988 inline void I86::_rotshft_b() /* Opcode 0xd0 */
3990 rotate_shift_byte(FETCHOP, 1);
3993 inline void I86::_rotshft_w() /* Opcode 0xd1 */
3995 rotate_shift_word(FETCHOP, 1);
3998 inline void I86::_rotshft_bcl() /* Opcode 0xd2 */
4000 rotate_shift_byte(FETCHOP, regs.b[CL]);
4003 inline void I86::_rotshft_wcl() /* Opcode 0xd3 */
4005 rotate_shift_word(FETCHOP, regs.b[CL]);
4008 /* OB: Opcode works on NEC V-Series but not the Variants */
4009 /* one could specify any byte value as operand but the NECs */
4010 /* always substitute 0x0a. */
4011 inline void I86::_aam() /* Opcode 0xd4 */
4013 unsigned mult = FETCH;
4014 icount -= timing.aam;
4016 interrupt(DIVIDE_FAULT);
4018 regs.b[AH] = regs.b[AL] / mult;
4020 SetSZPF_Word(regs.w[AX]);
4024 inline void I86::_aad() /* Opcode 0xd5 */
4026 unsigned mult = FETCH;
4027 icount -= timing.aad;
4028 regs.b[AL] = regs.b[AH] * mult + regs.b[AL];
4035 inline void I86::_setalc() /* Opcode 0xd6 */
4037 regs.b[AL] = (CF) ? 0xff : 0x00;
4041 inline void I86::_xlat() /* Opcode 0xd7 */
4043 unsigned dest = regs.w[BX] + regs.b[AL];
4044 icount -= timing.xlat;
4045 regs.b[AL] = GetMemB(DS, dest);
4048 inline void I86::_escape() /* Opcodes 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde and 0xdf */
4050 unsigned ModRM = FETCH;
4051 icount -= timing.nop;
4055 inline void I86::_loopne() /* Opcode 0xe0 */
4057 int disp = (int)((int8)FETCH);
4058 unsigned tmp = regs.w[CX] - 1;
4061 icount -= timing.loop_t;
4064 icount -= timing.loop_nt;
4068 inline void I86::_loope() /* Opcode 0xe1 */
4070 int disp = (int)((int8)FETCH);
4071 unsigned tmp = regs.w[CX] - 1;
4074 icount -= timing.loope_t;
4077 icount -= timing.loope_nt;
4081 inline void I86::_loop() /* Opcode 0xe2 */
4083 int disp = (int)((int8)FETCH);
4084 unsigned tmp = regs.w[CX] - 1;
4087 icount -= timing.loop_t;
4090 icount -= timing.loop_nt;
4094 inline void I86::_jcxz() /* Opcode 0xe3 */
4096 int disp = (int)((int8)FETCH);
4097 if(regs.w[CX] == 0) {
4098 icount -= timing.jcxz_t;
4101 icount -= timing.jcxz_nt;
4105 inline void I86::_inal() /* Opcode 0xe4 */
4107 unsigned port = FETCH;
4108 icount -= timing.in_imm8;
4109 regs.b[AL] = read_port_byte(port);
4112 inline void I86::_inax() /* Opcode 0xe5 */
4114 unsigned port = FETCH;
4115 icount -= timing.in_imm16;
4116 regs.w[AX] = read_port_word(port);
4119 inline void I86::_outal() /* Opcode 0xe6 */
4121 unsigned port = FETCH;
4122 icount -= timing.out_imm8;
4123 write_port_byte(port, regs.b[AL]);
4126 inline void I86::_outax() /* Opcode 0xe7 */
4128 unsigned port = FETCH;
4129 icount -= timing.out_imm16;
4130 write_port_word(port, regs.w[AX]);
4133 inline void I86::_call_d16() /* Opcode 0xe8 */
4141 pc = (ip + base[CS]) & AMASK;
4142 #ifdef I86_PSEUDO_BIOS
4143 if(d_bios && d_bios->bios_call_i86(pc, regs.w, sregs, &ZeroVal, &CarryVal)) {
4148 icount -= timing.call_near;
4151 inline void I86::_jmp_d16() /* Opcode 0xe9 */
4156 ip = pc - base[CS] + tmp;
4157 pc = (ip + base[CS]) & AMASK;
4158 icount -= timing.jmp_near;
4161 inline void I86::_jmp_far() /* Opcode 0xea */
4171 sregs[CS] = (uint16)tmp1;
4172 base[CS] = SegBase(CS);
4173 pc = (base[CS] + tmp) & AMASK;
4174 icount -= timing.jmp_far;
4177 inline void I86::_jmp_d8() /* Opcode 0xeb */
4179 int tmp = (int)((int8)FETCH);
4181 icount -= timing.jmp_short;
4184 inline void I86::_inaldx() /* Opcode 0xec */
4186 icount -= timing.in_dx8;
4187 regs.b[AL] = read_port_byte(regs.w[DX]);
4190 inline void I86::_inaxdx() /* Opcode 0xed */
4192 unsigned port = regs.w[DX];
4193 icount -= timing.in_dx16;
4194 regs.w[AX] = read_port_word(port);
4197 inline void I86::_outdxal() /* Opcode 0xee */
4199 icount -= timing.out_dx8;
4200 write_port_byte(regs.w[DX], regs.b[AL]);
4203 inline void I86::_outdxax() /* Opcode 0xef */
4205 unsigned port = regs.w[DX];
4206 icount -= timing.out_dx16;
4207 write_port_word(port, regs.w[AX]);
4210 /* I think thats not a V20 instruction...*/
4211 inline void I86::_lock() /* Opcode 0xf0 */
4213 icount -= timing.nop;
4214 instruction(FETCHOP); /* un-interruptible */
4217 inline void I86::_rep(int flagval)
4219 /* Handles rep- and repnz- prefixes. flagval is the value of ZF for the
4220 loop to continue for CMPS and SCAS instructions. */
4222 unsigned next = FETCHOP;
4223 unsigned count = regs.w[CX];
4226 case 0x26: /* ES: */
4229 icount -= timing.override;
4232 case 0x2e: /* CS: */
4235 icount -= timing.override;
4238 case 0x36: /* SS: */
4241 icount -= timing.override;
4244 case 0x3e: /* DS: */
4247 icount -= timing.override;
4251 case 0x6c: /* REP INSB */
4252 icount -= timing.rep_ins8_base;
4253 for(; count > 0; count--) {
4254 PutMemB(ES, regs.w[DI], read_port_byte(regs.w[DX]));
4255 regs.w[DI] += DirVal;
4256 icount -= timing.rep_ins8_count;
4260 case 0x6d: /* REP INSW */
4261 icount -= timing.rep_ins16_base;
4262 for(; count > 0; count--) {
4263 PutMemW(ES, regs.w[DI], read_port_word(regs.w[DX]));
4264 regs.w[DI] += 2 * DirVal;
4265 icount -= timing.rep_ins16_count;
4269 case 0x6e: /* REP OUTSB */
4270 icount -= timing.rep_outs8_base;
4271 for(; count > 0; count--) {
4272 write_port_byte(regs.w[DX], GetMemB(DS, regs.w[SI]));
4273 regs.w[SI] += DirVal; /* GOL 11/27/01 */
4274 icount -= timing.rep_outs8_count;
4278 case 0x6f: /* REP OUTSW */
4279 icount -= timing.rep_outs16_base;
4280 for(; count > 0; count--) {
4281 write_port_word(regs.w[DX], GetMemW(DS, regs.w[SI]));
4282 regs.w[SI] += 2 * DirVal; /* GOL 11/27/01 */
4283 icount -= timing.rep_outs16_count;
4288 case 0xa4: /* REP MOVSB */
4289 icount -= timing.rep_movs8_base;
4290 for(; count > 0; count--) {
4292 tmp = GetMemB(DS, regs.w[SI]);
4293 PutMemB(ES, regs.w[DI], tmp);
4294 regs.w[DI] += DirVal;
4295 regs.w[SI] += DirVal;
4296 icount -= timing.rep_movs8_count;
4300 case 0xa5: /* REP MOVSW */
4301 icount -= timing.rep_movs16_base;
4302 for(; count > 0; count--) {
4304 tmp = GetMemW(DS, regs.w[SI]);
4305 PutMemW(ES, regs.w[DI], tmp);
4306 regs.w[DI] += 2 * DirVal;
4307 regs.w[SI] += 2 * DirVal;
4308 icount -= timing.rep_movs16_count;
4312 case 0xa6: /* REP(N)E CMPSB */
4313 icount -= timing.rep_cmps8_base;
4314 for(ZeroVal = !flagval; (ZF == flagval) && (count > 0); count--) {
4316 dst = GetMemB(ES, regs.w[DI]);
4317 src = GetMemB(DS, regs.w[SI]);
4318 SUBB(src, dst); /* opposite of the usual convention */
4319 regs.w[DI] += DirVal;
4320 regs.w[SI] += DirVal;
4321 icount -= timing.rep_cmps8_count;
4325 case 0xa7: /* REP(N)E CMPSW */
4326 icount -= timing.rep_cmps16_base;
4327 for(ZeroVal = !flagval; (ZF == flagval) && (count > 0); count--) {
4329 dst = GetMemW(ES, regs.w[DI]);
4330 src = GetMemW(DS, regs.w[SI]);
4331 SUBW(src, dst); /* opposite of the usual convention */
4332 regs.w[DI] += 2 * DirVal;
4333 regs.w[SI] += 2 * DirVal;
4334 icount -= timing.rep_cmps16_count;
4338 case 0xaa: /* REP STOSB */
4339 icount -= timing.rep_stos8_base;
4340 for(; count > 0; count--) {
4341 PutMemB(ES, regs.w[DI], regs.b[AL]);
4342 regs.w[DI] += DirVal;
4343 icount -= timing.rep_stos8_count;
4347 case 0xab: /* REP STOSW */
4348 icount -= timing.rep_stos16_base;
4349 for(; count > 0; count--) {
4350 PutMemW(ES, regs.w[DI], regs.w[AX]);
4351 regs.w[DI] += 2 * DirVal;
4352 icount -= timing.rep_stos16_count;
4356 case 0xac: /* REP LODSB */
4357 icount -= timing.rep_lods8_base;
4358 for(; count > 0; count--) {
4359 regs.b[AL] = GetMemB(DS, regs.w[SI]);
4360 regs.w[SI] += DirVal;
4361 icount -= timing.rep_lods8_count;
4365 case 0xad: /* REP LODSW */
4366 icount -= timing.rep_lods16_base;
4367 for(; count > 0; count--) {
4368 regs.w[AX] = GetMemW(DS, regs.w[SI]);
4369 regs.w[SI] += 2 * DirVal;
4370 icount -= timing.rep_lods16_count;
4374 case 0xae: /* REP(N)E SCASB */
4375 icount -= timing.rep_scas8_base;
4376 for(ZeroVal = !flagval; (ZF == flagval) && (count > 0); count--) {
4378 src = GetMemB(ES, regs.w[DI]);
4381 regs.w[DI] += DirVal;
4382 icount -= timing.rep_scas8_count;
4386 case 0xaf: /* REP(N)E SCASW */
4387 icount -= timing.rep_scas16_base;
4388 for(ZeroVal = !flagval; (ZF == flagval) && (count > 0); count--) {
4390 src = GetMemW(ES, regs.w[DI]);
4393 regs.w[DI] += 2 * DirVal;
4394 icount -= timing.rep_scas16_count;
4403 inline void I86::_repne() /* Opcode 0xf2 */
4408 inline void I86::_repe() /* Opcode 0xf3 */
4413 inline void I86::_hlt() /* Opcode 0xf4 */
4420 inline void I86::_cmc() /* Opcode 0xf5 */
4422 icount -= timing.flag_ops;
4426 inline void I86::_f6pre() /* Opcode 0xf6 */
4428 unsigned ModRM = FETCH;
4429 unsigned tmp = (unsigned)GetRMByte(ModRM);
4432 switch((ModRM >> 3) & 7) {
4433 case 0: /* TEST Eb, data8 */
4435 icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8_ro;
4438 CarryVal = OverVal = AuxVal = 0;
4442 case 2: /* NOT Eb */
4443 icount -= (ModRM >= 0xc0) ? timing.negnot_r8 : timing.negnot_m8;
4444 PutbackRMByte(ModRM, ~tmp);
4447 case 3: /* NEG Eb */
4448 icount -= (ModRM >= 0xc0) ? timing.negnot_r8 : timing.negnot_m8;
4451 PutbackRMByte(ModRM, tmp2);
4454 case 4: /* MUL AL, Eb */
4455 icount -= (ModRM >= 0xc0) ? timing.mul_r8 : timing.mul_m8;
4464 result = (uint16)tmp2 * tmp;
4465 regs.w[AX] = (uint16)result;
4468 CarryVal = OverVal = (regs.b[AH] != 0);
4472 case 5: /* IMUL AL, Eb */
4473 icount -= (ModRM >= 0xc0) ? timing.imul_r8 : timing.imul_m8;
4477 tmp2 = (unsigned)regs.b[AL];
4482 result = (int16)((int8)tmp2) * (int16)((int8)tmp);
4483 regs.w[AX] = (uint16)result;
4486 CarryVal = OverVal = (result >> 7 != 0) && (result >> 7 != -1);
4490 case 6: /* DIV AL, Ew */
4491 icount -= (ModRM >= 0xc0) ? timing.div_r8 : timing.div_m8;
4495 result = regs.w[AX];
4498 if((result / tmp) > 0xff) {
4499 interrupt(DIVIDE_FAULT);
4502 regs.b[AH] = result % tmp;
4503 regs.b[AL] = result / tmp;
4506 interrupt(DIVIDE_FAULT);
4512 case 7: /* IDIV AL, Ew */
4513 icount -= (ModRM >= 0xc0) ? timing.idiv_r8 : timing.idiv_m8;
4517 result = regs.w[AX];
4520 tmp2 = result % (int16)((int8)tmp);
4522 if((result /= (int16)((int8)tmp)) > 0xff) {
4523 interrupt(DIVIDE_FAULT);
4526 regs.b[AL] = (uint8)result;
4530 interrupt(DIVIDE_FAULT);
4542 inline void I86::_f7pre() /* Opcode 0xf7 */
4544 unsigned ModRM = FETCH;
4545 unsigned tmp = GetRMWord(ModRM);
4548 switch((ModRM >> 3) & 7) {
4549 case 0: /* TEST Ew, data16 */
4551 icount -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16_ro;
4557 CarryVal = OverVal = AuxVal = 0;
4561 case 2: /* NOT Ew */
4562 icount -= (ModRM >= 0xc0) ? timing.negnot_r16 : timing.negnot_m16;
4564 PutbackRMWord(ModRM, tmp);
4567 case 3: /* NEG Ew */
4568 icount -= (ModRM >= 0xc0) ? timing.negnot_r16 : timing.negnot_m16;
4571 PutbackRMWord(ModRM, tmp2);
4574 case 4: /* MUL AX, Ew */
4575 icount -= (ModRM >= 0xc0) ? timing.mul_r16 : timing.mul_m16;
4583 result = (uint32)tmp2 * tmp;
4584 regs.w[AX] = (uint16)result;
4586 regs.w[DX] = result;
4588 SetZF(regs.w[AX] | regs.w[DX]);
4589 CarryVal = OverVal = (regs.w[DX] != 0);
4593 case 5: /* IMUL AX, Ew */
4594 icount -= (ModRM >= 0xc0) ? timing.imul_r16 : timing.imul_m16;
4603 result = (int32)((int16)tmp2) * (int32)((int16)tmp);
4604 CarryVal = OverVal = (result >> 15 != 0) && (result >> 15 != -1);
4606 regs.w[AX] = (uint16)result;
4607 result = (uint16)(result >> 16);
4608 regs.w[DX] = result;
4610 SetZF(regs.w[AX] | regs.w[DX]);
4614 case 6: /* DIV AX, Ew */
4615 icount -= (ModRM >= 0xc0) ? timing.div_r16 : timing.div_m16;
4619 result = (regs.w[DX] << 16) + regs.w[AX];
4622 tmp2 = result % tmp;
4623 if((result / tmp) > 0xffff) {
4624 interrupt(DIVIDE_FAULT);
4629 regs.w[AX] = result;
4632 interrupt(DIVIDE_FAULT);
4638 case 7: /* IDIV AX, Ew */
4639 icount -= (ModRM >= 0xc0) ? timing.idiv_r16 : timing.idiv_m16;
4643 result = (regs.w[DX] << 16) + regs.w[AX];
4646 tmp2 = result % (int32)((int16)tmp);
4647 if((result /= (int32)((int16)tmp)) > 0xffff) {
4648 interrupt(DIVIDE_FAULT);
4651 regs.w[AX] = result;
4655 interrupt(DIVIDE_FAULT);
4667 inline void I86::_clc() /* Opcode 0xf8 */
4669 icount -= timing.flag_ops;
4673 inline void I86::_stc() /* Opcode 0xf9 */
4675 icount -= timing.flag_ops;
4679 inline void I86::_cli() /* Opcode 0xfa */
4681 icount -= timing.flag_ops;
4685 inline void I86::_sti() /* Opcode 0xfb */
4687 icount -= timing.flag_ops;
4689 instruction(FETCHOP); /* no interrupt before next instruction */
4691 /* if an interrupt is pending, signal an interrupt */
4692 if(IF && (int_state & INT_REQ_BIT)) {
4697 inline void I86::_cld() /* Opcode 0xfc */
4699 icount -= timing.flag_ops;
4703 inline void I86::_std() /* Opcode 0xfd */
4705 icount -= timing.flag_ops;
4709 inline void I86::_fepre() /* Opcode 0xfe */
4711 unsigned ModRM = FETCH;
4712 unsigned tmp = GetRMByte(ModRM);
4715 icount -= (ModRM >= 0xc0) ? timing.incdec_r8 : timing.incdec_m8;
4716 if((ModRM & 0x38) == 0) {
4719 SetOFB_Add(tmp1, tmp, 1);
4723 SetOFB_Sub(tmp1, 1, tmp);
4725 SetAF(tmp1, tmp, 1);
4727 PutbackRMByte(ModRM, (uint8)tmp1);
4730 inline void I86::_ffpre() /* Opcode 0xff */
4732 unsigned ModRM = FETCHOP;
4737 switch((ModRM >> 3) & 7) {
4738 case 0: /* INC ew */
4739 icount -= (ModRM >= 0xc0) ? timing.incdec_r16 : timing.incdec_m16;
4740 tmp = GetRMWord(ModRM);
4742 SetOFW_Add(tmp1, tmp, 1);
4743 SetAF(tmp1, tmp, 1);
4745 PutbackRMWord(ModRM, (uint16)tmp1);
4747 case 1: /* DEC ew */
4748 icount -= (ModRM >= 0xc0) ? timing.incdec_r16 : timing.incdec_m16;
4749 tmp = GetRMWord(ModRM);
4751 SetOFW_Sub(tmp1, 1, tmp);
4752 SetAF(tmp1, tmp, 1);
4754 PutbackRMWord(ModRM, (uint16)tmp1);
4756 case 2: /* CALL ew */
4757 icount -= (ModRM >= 0xc0) ? timing.call_r16 : timing.call_m16;
4758 tmp = GetRMWord(ModRM);
4761 pc = (base[CS] + (uint16)tmp) & AMASK;
4762 #ifdef I86_PSEUDO_BIOS
4763 if(d_bios && d_bios->bios_call_i86(pc, regs.w, sregs, &ZeroVal, &CarryVal)) {
4769 case 3: /* CALL FAR ea */
4770 icount -= timing.call_m32;
4771 tmp = sregs[CS]; /* need to skip displacements of ea */
4772 tmp1 = GetRMWord(ModRM);
4776 sregs[CS] = GetNextRMWord;
4777 base[CS] = SegBase(CS);
4778 pc = (base[CS] + tmp1) & AMASK;
4779 #ifdef I86_PSEUDO_BIOS
4780 if(d_bios && d_bios->bios_call_i86(pc, regs.w, sregs, &ZeroVal, &CarryVal)) {
4786 case 4: /* JMP ea */
4787 icount -= (ModRM >= 0xc0) ? timing.jmp_r16 : timing.jmp_m16;
4788 ip = GetRMWord(ModRM);
4789 pc = (base[CS] + ip) & AMASK;
4791 case 5: /* JMP FAR ea */
4792 icount -= timing.jmp_m32;
4793 pc = GetRMWord(ModRM);
4794 sregs[CS] = GetNextRMWord;
4795 base[CS] = SegBase(CS);
4796 pc = (pc + base[CS]) & AMASK;
4798 case 6: /* PUSH ea */
4799 icount -= (ModRM >= 0xc0) ? timing.push_r16 : timing.push_m16;
4800 tmp = GetRMWord(ModRM);
4803 case 7: /* invalid ??? */
4812 inline void I86::_invalid()
4814 /* i8086/i8088 ignore an invalid opcode. */
4815 /* i80186/i80188 probably also ignore an invalid opcode. */
4820 NEC V-series Disassembler
4822 Originally Written for i386 by Ville Linde
4823 Converted to NEC-V by Aaron Giles
4828 PARAM_REG8 = 1, /* 8-bit register */
4829 PARAM_REG16, /* 16-bit register */
4830 PARAM_REG2_8, /* 8-bit register */
4831 PARAM_REG2_16, /* 16-bit register */
4832 PARAM_RM8, /* 8-bit memory or register */
4833 PARAM_RM16, /* 16-bit memory or register */
4834 PARAM_RMPTR8, /* 8-bit memory or register */
4835 PARAM_RMPTR16, /* 16-bit memory or register */
4836 PARAM_I3, /* 3-bit immediate */
4837 PARAM_I4, /* 4-bit immediate */
4838 PARAM_I8, /* 8-bit signed immediate */
4839 PARAM_I16, /* 16-bit signed immediate */
4840 PARAM_UI8, /* 8-bit unsigned immediate */
4841 PARAM_IMM, /* 16-bit immediate */
4842 PARAM_ADDR, /* 16:16 address */
4843 PARAM_REL8, /* 8-bit PC-relative displacement */
4844 PARAM_REL16, /* 16-bit PC-relative displacement */
4845 PARAM_MEM_OFFS, /* 16-bit mem offset */
4846 PARAM_SREG, /* segment register */
4847 PARAM_SFREG, /* V25/V35 special function register */
4848 PARAM_1, /* used by shift/rotate instructions */
4880 struct I386_OPCODE {
4891 const I386_OPCODE *opcode;
4894 static const UINT8 *opcode_ptr;
4895 static const UINT8 *opcode_ptr_base;
4897 static const I386_OPCODE necv_opcode_table1[256] =
4900 {"add", MODRM, PARAM_RM8, PARAM_REG8, 0 },
4901 {"add", MODRM, PARAM_RM16, PARAM_REG16, 0 },
4902 {"add", MODRM, PARAM_REG8, PARAM_RM8, 0 },
4903 {"add", MODRM, PARAM_REG16, PARAM_RM16, 0 },
4904 {"add", 0, PARAM_AL, PARAM_UI8, 0 },
4905 {"add", 0, PARAM_AW, PARAM_IMM, 0 },
4906 {"push ds1", 0, 0, 0, 0 },
4907 {"pop ds1", 0, 0, 0, 0 },
4908 {"or", MODRM, PARAM_RM8, PARAM_REG8, 0 },
4909 {"or", MODRM, PARAM_RM16, PARAM_REG16, 0 },
4910 {"or", MODRM, PARAM_REG8, PARAM_RM8, 0 },
4911 {"or", MODRM, PARAM_REG16, PARAM_RM16, 0 },
4912 {"or", 0, PARAM_AL, PARAM_UI8, 0 },
4913 {"or", 0, PARAM_AW, PARAM_IMM, 0 },
4914 {"push ps", 0, 0, 0, 0 },
4915 {"two_byte", TWO_BYTE, 0, 0, 0 },
4917 {"addc", MODRM, PARAM_RM8, PARAM_REG8, 0 },
4918 {"addc", MODRM, PARAM_RM16, PARAM_REG16, 0 },
4919 {"addc", MODRM, PARAM_REG8, PARAM_RM8, 0 },
4920 {"addc", MODRM, PARAM_REG16, PARAM_RM16, 0 },
4921 {"addc", 0, PARAM_AL, PARAM_UI8, 0 },
4922 {"addc", 0, PARAM_AW, PARAM_IMM, 0 },
4923 {"push ss", 0, 0, 0, 0 },
4924 {"pop ss", 0, 0, 0, 0 },
4925 {"subc", MODRM, PARAM_RM8, PARAM_REG8, 0 },
4926 {"subc", MODRM, PARAM_RM16, PARAM_REG16, 0 },
4927 {"subc", MODRM, PARAM_REG8, PARAM_RM8, 0 },
4928 {"subc", MODRM, PARAM_REG16, PARAM_RM16, 0 },
4929 {"subc", 0, PARAM_AL, PARAM_UI8, 0 },
4930 {"subc", 0, PARAM_AW, PARAM_IMM, 0 },
4931 {"push ds0", 0, 0, 0, 0 },
4932 {"pop ds0", 0, 0, 0, 0 },
4934 {"and", MODRM, PARAM_RM8, PARAM_REG8, 0 },
4935 {"and", MODRM, PARAM_RM16, PARAM_REG16, 0 },
4936 {"and", MODRM, PARAM_REG8, PARAM_RM8, 0 },
4937 {"and", MODRM, PARAM_REG16, PARAM_RM16, 0 },
4938 {"and", 0, PARAM_AL, PARAM_UI8, 0 },
4939 {"and", 0, PARAM_AW, PARAM_IMM, 0 },
4940 {"ds1:", SEG_DS1, 0, 0, 0 },
4941 {"adj4a", 0, 0, 0, 0 },
4942 {"sub", MODRM, PARAM_RM8, PARAM_REG8, 0 },
4943 {"sub", MODRM, PARAM_RM16, PARAM_REG16, 0 },
4944 {"sub", MODRM, PARAM_REG8, PARAM_RM8, 0 },
4945 {"sub", MODRM, PARAM_REG16, PARAM_RM16, 0 },
4946 {"sub", 0, PARAM_AL, PARAM_UI8, 0 },
4947 {"sub", 0, PARAM_AW, PARAM_IMM, 0 },
4948 {"ps:", SEG_PS, 0, 0, 0 },
4949 {"adj4s", 0, 0, 0, 0 },
4951 {"xor", MODRM, PARAM_RM8, PARAM_REG8, 0 },
4952 {"xor", MODRM, PARAM_RM16, PARAM_REG16, 0 },
4953 {"xor", MODRM, PARAM_REG8, PARAM_RM8, 0 },
4954 {"xor", MODRM, PARAM_REG16, PARAM_RM16, 0 },
4955 {"xor", 0, PARAM_AL, PARAM_UI8, 0 },
4956 {"xor", 0, PARAM_AW, PARAM_IMM, 0 },
4957 {"ss:", SEG_SS, 0, 0, 0 },
4958 {"adjba", 0, 0, 0, 0 },
4959 {"cmp", MODRM, PARAM_RM8, PARAM_REG8, 0 },
4960 {"cmp", MODRM, PARAM_RM16, PARAM_REG16, 0 },
4961 {"cmp", MODRM, PARAM_REG8, PARAM_RM8, 0 },
4962 {"cmp", MODRM, PARAM_REG16, PARAM_RM16, 0 },
4963 {"cmp", 0, PARAM_AL, PARAM_UI8, 0 },
4964 {"cmp", 0, PARAM_AW, PARAM_IMM, 0 },
4965 {"ds0:", SEG_DS0, 0, 0, 0 },
4966 {"adjbs", 0, 0, 0, 0 },
4968 {"inc", 0, PARAM_AW, 0, 0 },
4969 {"inc", 0, PARAM_CW, 0, 0 },
4970 {"inc", 0, PARAM_DW, 0, 0 },
4971 {"inc", 0, PARAM_BW, 0, 0 },
4972 {"inc", 0, PARAM_SP, 0, 0 },
4973 {"inc", 0, PARAM_BP, 0, 0 },
4974 {"inc", 0, PARAM_IX, 0, 0 },
4975 {"inc", 0, PARAM_IY, 0, 0 },
4976 {"dec", 0, PARAM_AW, 0, 0 },
4977 {"dec", 0, PARAM_CW, 0, 0 },
4978 {"dec", 0, PARAM_DW, 0, 0 },
4979 {"dec", 0, PARAM_BW, 0, 0 },
4980 {"dec", 0, PARAM_SP, 0, 0 },
4981 {"dec", 0, PARAM_BP, 0, 0 },
4982 {"dec", 0, PARAM_IX, 0, 0 },
4983 {"dec", 0, PARAM_IY, 0, 0 },
4985 {"push", 0, PARAM_AW, 0, 0 },
4986 {"push", 0, PARAM_CW, 0, 0 },
4987 {"push", 0, PARAM_DW, 0, 0 },
4988 {"push", 0, PARAM_BW, 0, 0 },
4989 {"push", 0, PARAM_SP, 0, 0 },
4990 {"push", 0, PARAM_BP, 0, 0 },
4991 {"push", 0, PARAM_IX, 0, 0 },
4992 {"push", 0, PARAM_IY, 0, 0 },
4993 {"pop", 0, PARAM_AW, 0, 0 },
4994 {"pop", 0, PARAM_CW, 0, 0 },
4995 {"pop", 0, PARAM_DW, 0, 0 },
4996 {"pop", 0, PARAM_BW, 0, 0 },
4997 {"pop", 0, PARAM_SP, 0, 0 },
4998 {"pop", 0, PARAM_BP, 0, 0 },
4999 {"pop", 0, PARAM_IX, 0, 0 },
5000 {"pop", 0, PARAM_IY, 0, 0 },
5002 {"push r", 0, 0, 0, 0 },
5003 {"pop r", 0, 0, 0, 0 },
5004 {"chkind", MODRM, PARAM_REG16, PARAM_RM16, 0 },
5005 {"brkn", 0, PARAM_UI8, 0, 0, DASMFLAG_STEP_OVER}, /* V25S/V35S only */
5006 {"repnc", PREFIX, 0, 0, 0 },
5007 {"repc", PREFIX, 0, 0, 0 },
5008 {"fpo2 0", 0, 0, 0, 0 }, /* for a coprocessor that was never made */
5009 {"fpo2 1", 0, 0, 0, 0 }, /* for a coprocessor that was never made */
5010 {"push", 0, PARAM_IMM, 0, 0 },
5011 {"mul", MODRM, PARAM_REG16, PARAM_RM16, PARAM_IMM },
5012 {"push", 0, PARAM_I8, 0, 0 },
5013 {"mul", MODRM, PARAM_REG16, PARAM_RM16, PARAM_I8 },
5014 {"inmb", 0, 0, 0, 0 },
5015 {"inmw", 0, 0, 0, 0 },
5016 {"outmb", 0, 0, 0, 0 },
5017 {"outmw", 0, 0, 0, 0 },
5019 {"bv", 0, PARAM_REL8, 0, 0 },
5020 {"bnv", 0, PARAM_REL8, 0, 0 },
5021 {"bc", 0, PARAM_REL8, 0, 0 },
5022 {"bnc", 0, PARAM_REL8, 0, 0 },
5023 {"be", 0, PARAM_REL8, 0, 0 },
5024 {"bne", 0, PARAM_REL8, 0, 0 },
5025 {"bnh", 0, PARAM_REL8, 0, 0 },
5026 {"bh", 0, PARAM_REL8, 0, 0 },
5027 {"bn", 0, PARAM_REL8, 0, 0 },
5028 {"bp", 0, PARAM_REL8, 0, 0 },
5029 {"bpe", 0, PARAM_REL8, 0, 0 },
5030 {"bpo", 0, PARAM_REL8, 0, 0 },
5031 {"blt", 0, PARAM_REL8, 0, 0 },
5032 {"bge", 0, PARAM_REL8, 0, 0 },
5033 {"ble", 0, PARAM_REL8, 0, 0 },
5034 {"bgt", 0, PARAM_REL8, 0, 0 },
5036 {"immb", GROUP, 0, 0, 0 },
5037 {"immw", GROUP, 0, 0, 0 },
5038 {"immb", GROUP, 0, 0, 0 },
5039 {"immws", GROUP, 0, 0, 0 },
5040 {"test", MODRM, PARAM_RM8, PARAM_REG8, 0 },
5041 {"test", MODRM, PARAM_RM16, PARAM_REG16, 0 },
5042 {"xch", MODRM, PARAM_REG8, PARAM_RM8, 0 },
5043 {"xch", MODRM, PARAM_REG16, PARAM_RM16, 0 },
5044 {"mov", MODRM, PARAM_RM8, PARAM_REG8, 0 },
5045 {"mov", MODRM, PARAM_RM16, PARAM_REG16, 0 },
5046 {"mov", MODRM, PARAM_REG8, PARAM_RM8, 0 },
5047 {"mov", MODRM, PARAM_REG16, PARAM_RM16, 0 },
5048 {"mov", MODRM, PARAM_RM16, PARAM_SREG, 0 },
5049 {"ldea", MODRM, PARAM_REG16, PARAM_RM16, 0 },
5050 {"mov", MODRM, PARAM_SREG, PARAM_RM16, 0 },
5051 {"pop", MODRM, PARAM_RM16, 0, 0 },
5053 {"nop", 0, 0, 0, 0 },
5054 {"xch", 0, PARAM_AW, PARAM_CW, 0 },
5055 {"xch", 0, PARAM_AW, PARAM_DW, 0 },
5056 {"xch", 0, PARAM_AW, PARAM_BW, 0 },
5057 {"xch", 0, PARAM_AW, PARAM_SP, 0 },
5058 {"xch", 0, PARAM_AW, PARAM_BP, 0 },
5059 {"xch", 0, PARAM_AW, PARAM_IX, 0 },
5060 {"xch", 0, PARAM_AW, PARAM_IY, 0 },
5061 {"cvtbw", 0, 0, 0, 0 },
5062 {"cvtwl", 0, 0, 0, 0 },
5063 {"call", 0, PARAM_ADDR, 0, 0, DASMFLAG_STEP_OVER},
5064 {"poll", 0, 0, 0, 0 },
5065 {"push psw", 0, 0, 0, 0 },
5066 {"pop psw", 0, 0, 0, 0 },
5067 {"mov psw,ah", 0, 0, 0, 0 },
5068 {"mov ah,psw", 0, 0, 0, 0 },
5070 {"mov", 0, PARAM_AL, PARAM_MEM_OFFS, 0 },
5071 {"mov", 0, PARAM_AW, PARAM_MEM_OFFS, 0 },
5072 {"mov", 0, PARAM_MEM_OFFS, PARAM_AL, 0 },
5073 {"mov", 0, PARAM_MEM_OFFS, PARAM_AW, 0 },
5074 {"movbkb", 0, 0, 0, 0 },
5075 {"movbkw", 0, 0, 0, 0 },
5076 {"cmpbkb", 0, 0, 0, 0 },
5077 {"cmpbkw", 0, 0, 0, 0 },
5078 {"test", 0, PARAM_AL, PARAM_UI8, 0 },
5079 {"test", 0, PARAM_AW, PARAM_IMM, 0 },
5080 {"stmb", 0, 0, 0, 0 },
5081 {"stmw", 0, 0, 0, 0 },
5082 {"ldmb", 0, 0, 0, 0 },
5083 {"ldmw", 0, 0, 0, 0 },
5084 {"cmpmb", 0, 0, 0, 0 },
5085 {"cmpmw", 0, 0, 0, 0 },
5087 {"mov", 0, PARAM_AL, PARAM_UI8, 0 },
5088 {"mov", 0, PARAM_CL, PARAM_UI8, 0 },
5089 {"mov", 0, PARAM_DL, PARAM_UI8, 0 },
5090 {"mov", 0, PARAM_BL, PARAM_UI8, 0 },
5091 {"mov", 0, PARAM_AH, PARAM_UI8, 0 },
5092 {"mov", 0, PARAM_CH, PARAM_UI8, 0 },
5093 {"mov", 0, PARAM_DH, PARAM_UI8, 0 },
5094 {"mov", 0, PARAM_BH, PARAM_UI8, 0 },
5095 {"mov", 0, PARAM_AW, PARAM_IMM, 0 },
5096 {"mov", 0, PARAM_CW, PARAM_IMM, 0 },
5097 {"mov", 0, PARAM_DW, PARAM_IMM, 0 },
5098 {"mov", 0, PARAM_BW, PARAM_IMM, 0 },
5099 {"mov", 0, PARAM_SP, PARAM_IMM, 0 },
5100 {"mov", 0, PARAM_BP, PARAM_IMM, 0 },
5101 {"mov", 0, PARAM_IX, PARAM_IMM, 0 },
5102 {"mov", 0, PARAM_IY, PARAM_IMM, 0 },
5104 {"shiftbi", GROUP, 0, 0, 0 },
5105 {"shiftwi", GROUP, 0, 0, 0 },
5106 {"ret", 0, PARAM_I16, 0, 0, DASMFLAG_STEP_OUT},
5107 {"ret", 0, 0, 0, 0, DASMFLAG_STEP_OUT},
5108 {"mov ds1,", MODRM, PARAM_REG16, PARAM_RM16, 0 },
5109 {"mov ds0,", MODRM, PARAM_REG16, PARAM_RM16, 0 },
5110 {"mov", MODRM, PARAM_RMPTR8, PARAM_UI8, 0 },
5111 {"mov", MODRM, PARAM_RMPTR16, PARAM_IMM, 0 },
5112 {"prepare", 0, PARAM_I16, PARAM_UI8, 0 },
5113 {"dispose", 0, 0, 0, 0 },
5114 {"retf", 0, PARAM_I16, 0, 0, DASMFLAG_STEP_OUT},
5115 {"retf", 0, 0, 0, 0, DASMFLAG_STEP_OUT},
5116 {"brk 3", 0, 0, 0, 0, DASMFLAG_STEP_OVER},
5117 {"brk", 0, PARAM_UI8, 0, 0, DASMFLAG_STEP_OVER},
5118 {"brkv", 0, 0, 0, 0 },
5119 {"reti", 0, 0, 0, 0, DASMFLAG_STEP_OUT},
5121 {"shiftb", GROUP, 0, 0, 0 },
5122 {"shiftw", GROUP, 0, 0, 0 },
5123 {"shiftbv", GROUP, 0, 0, 0 },
5124 {"shiftwv", GROUP, 0, 0, 0 },
5125 {"cvtbd", 0, PARAM_I8, 0, 0 },
5126 {"cvtdb", 0, PARAM_I8, 0, 0 },
5127 {"???", 0, 0, 0, 0 },
5128 {"trans", 0, 0, 0, 0 },
5129 {"escape", FPU, 0, 0, 0 },
5130 {"escape", FPU, 0, 0, 0 },
5131 {"escape", FPU, 0, 0, 0 },
5132 {"escape", FPU, 0, 0, 0 },
5133 {"escape", FPU, 0, 0, 0 },
5134 {"escape", FPU, 0, 0, 0 },
5135 {"escape", FPU, 0, 0, 0 },
5136 {"escape", FPU, 0, 0, 0 },
5138 {"dbnzne", 0, PARAM_REL8, 0, 0, DASMFLAG_STEP_OVER},
5139 {"dbnze", 0, PARAM_REL8, 0, 0, DASMFLAG_STEP_OVER},
5140 {"dbnz", 0, PARAM_REL8, 0, 0, DASMFLAG_STEP_OVER},
5141 {"bcwz", 0, PARAM_REL8, 0, 0 },
5142 {"in", 0, PARAM_AL, PARAM_UI8, 0 },
5143 {"in", 0, PARAM_AW, PARAM_UI8, 0 },
5144 {"out", 0, PARAM_UI8, PARAM_AL, 0 },
5145 {"out", 0, PARAM_UI8, PARAM_AW, 0 },
5146 {"call", 0, PARAM_REL16, 0, 0, DASMFLAG_STEP_OVER},
5147 {"br", 0, PARAM_REL16, 0, 0 },
5148 {"br", 0, PARAM_ADDR, 0, 0 },
5149 {"br", 0, PARAM_REL8, 0, 0 },
5150 {"in", 0, PARAM_AL, PARAM_DW, 0 },
5151 {"in", 0, PARAM_AW, PARAM_DW, 0 },
5152 {"out", 0, PARAM_DW, PARAM_AL, 0 },
5153 {"out", 0, PARAM_DW, PARAM_AW, 0 },
5155 {"buslock", PREFIX, 0, 0, 0 },
5156 {"brks", 0, PARAM_UI8, 0, 0, DASMFLAG_STEP_OVER}, /* V25S/V35S only */
5157 {"repne", PREFIX, 0, 0, 0 },
5158 {"rep", PREFIX, 0, 0, 0 },
5159 {"halt", 0, 0, 0, 0 },
5160 {"not1 cy", 0, 0, 0, 0 },
5161 {"group1b", GROUP, 0, 0, 0 },
5162 {"group1w", GROUP, 0, 0, 0 },
5163 {"clr1 cy", 0, 0, 0, 0 },
5164 {"set1 cy", 0, 0, 0, 0 },
5165 {"di", 0, 0, 0, 0 },
5166 {"ei", 0, 0, 0, 0 },
5167 {"clr1 dir", 0, 0, 0, 0 },
5168 {"set1 dir", 0, 0, 0, 0 },
5169 {"group2b", GROUP, 0, 0, 0 },
5170 {"group2w", GROUP, 0, 0, 0 }
5173 static const I386_OPCODE necv_opcode_table2[256] =
5176 {"???", 0, 0, 0, 0 },
5177 {"???", 0, 0, 0, 0 },
5178 {"???", 0, 0, 0, 0 },
5179 {"???", 0, 0, 0, 0 },
5180 {"???", 0, 0, 0, 0 },
5181 {"???", 0, 0, 0, 0 },
5182 {"???", 0, 0, 0, 0 },
5183 {"???", 0, 0, 0, 0 },
5184 {"???", 0, 0, 0, 0 },
5185 {"???", 0, 0, 0, 0 },
5186 {"???", 0, 0, 0, 0 },
5187 {"???", 0, 0, 0, 0 },
5188 {"???", 0, 0, 0, 0 },
5189 {"???", 0, 0, 0, 0 },
5190 {"???", 0, 0, 0, 0 },
5191 {"???", 0, 0, 0, 0 },
5193 {"test1", MODRM, PARAM_RMPTR8, PARAM_CL, 0 },
5194 {"test1", MODRM, PARAM_RMPTR16, PARAM_CL, 0 },
5195 {"clr1", MODRM, PARAM_RMPTR8, PARAM_CL, 0 },
5196 {"clr1", MODRM, PARAM_RMPTR16, PARAM_CL, 0 },
5197 {"set1", MODRM, PARAM_RMPTR8, PARAM_CL, 0 },
5198 {"set1", MODRM, PARAM_RMPTR16, PARAM_CL, 0 },
5199 {"not1", MODRM, PARAM_RMPTR8, PARAM_CL, 0 },
5200 {"not1", MODRM, PARAM_RMPTR16, PARAM_CL, 0 },
5201 {"test1", MODRM, PARAM_RMPTR8, PARAM_I3, 0 },
5202 {"test1", MODRM, PARAM_RMPTR16, PARAM_I4, 0 },
5203 {"clr1", MODRM, PARAM_RMPTR8, PARAM_I3, 0 },
5204 {"clr1", MODRM, PARAM_RMPTR16, PARAM_I4, 0 },
5205 {"set1", MODRM, PARAM_RMPTR8, PARAM_I3, 0 },
5206 {"set1", MODRM, PARAM_RMPTR16, PARAM_I4, 0 },
5207 {"not1", MODRM, PARAM_RMPTR8, PARAM_I3, 0 },
5208 {"not1", MODRM, PARAM_RMPTR16, PARAM_I4, 0 },
5210 {"add4s", 0, 0, 0, 0 },
5211 {"???", 0, 0, 0, 0 },
5212 {"sub4s", 0, 0, 0, 0 },
5213 {"???", 0, 0, 0, 0 },
5214 {"???", 0, 0, 0, 0 },
5215 {"movspa", 0, 0, 0, 0 }, /* V25/V35 only */
5216 {"cmp4s", 0, 0, 0, 0 },
5217 {"???", 0, 0, 0, 0 },
5218 {"rol4", MODRM, PARAM_RMPTR8, 0, 0 },
5219 {"???", 0, 0, 0, 0 },
5220 {"ror4", MODRM, PARAM_RMPTR8, 0, 0 },
5221 {"???", 0, 0, 0, 0 },
5222 {"???", 0, 0, 0, 0 },
5223 {"brkcs", MODRM, PARAM_REG2_16, 0, 0, DASMFLAG_STEP_OVER}, /* V25/V35 only */
5224 {"???", 0, 0, 0, 0 },
5225 {"???", 0, 0, 0, 0 },
5227 {"???", 0, 0, 0, 0 },
5228 {"ins", MODRM, PARAM_REG2_8, PARAM_REG8, 0 },
5229 {"???", 0, 0, 0, 0 },
5230 {"ext", MODRM, PARAM_REG2_8, PARAM_REG8, 0 },
5231 {"???", 0, 0, 0, 0 },
5232 {"???", 0, 0, 0, 0 },
5233 {"???", 0, 0, 0, 0 },
5234 {"???", 0, 0, 0, 0 },
5235 {"???", 0, 0, 0, 0 },
5236 {"ins", MODRM, PARAM_REG2_8, PARAM_I4, 0 },
5237 {"???", 0, 0, 0, 0 },
5238 {"ext", MODRM, PARAM_REG2_8, PARAM_I4, 0 },
5239 {"???", 0, 0, 0, 0 },
5240 {"???", 0, 0, 0, 0 },
5241 {"???", 0, 0, 0, 0 },
5242 {"???", 0, 0, 0, 0 },
5244 {"???", 0, 0, 0, 0 },
5245 {"???", 0, 0, 0, 0 },
5246 {"???", 0, 0, 0, 0 },
5247 {"???", 0, 0, 0, 0 },
5248 {"???", 0, 0, 0, 0 },
5249 {"???", 0, 0, 0, 0 },
5250 {"???", 0, 0, 0, 0 },
5251 {"???", 0, 0, 0, 0 },
5252 {"???", 0, 0, 0, 0 },
5253 {"???", 0, 0, 0, 0 },
5254 {"???", 0, 0, 0, 0 },
5255 {"???", 0, 0, 0, 0 },
5256 {"???", 0, 0, 0, 0 },
5257 {"???", 0, 0, 0, 0 },
5258 {"???", 0, 0, 0, 0 },
5259 {"???", 0, 0, 0, 0 },
5261 {"???", 0, 0, 0, 0 },
5262 {"???", 0, 0, 0, 0 },
5263 {"???", 0, 0, 0, 0 },
5264 {"???", 0, 0, 0, 0 },
5265 {"???", 0, 0, 0, 0 },
5266 {"???", 0, 0, 0, 0 },
5267 {"???", 0, 0, 0, 0 },
5268 {"???", 0, 0, 0, 0 },
5269 {"???", 0, 0, 0, 0 },
5270 {"???", 0, 0, 0, 0 },
5271 {"???", 0, 0, 0, 0 },
5272 {"???", 0, 0, 0, 0 },
5273 {"???", 0, 0, 0, 0 },
5274 {"???", 0, 0, 0, 0 },
5275 {"???", 0, 0, 0, 0 },
5276 {"???", 0, 0, 0, 0 },
5278 {"???", 0, 0, 0, 0 },
5279 {"???", 0, 0, 0, 0 },
5280 {"???", 0, 0, 0, 0 },
5281 {"???", 0, 0, 0, 0 },
5282 {"???", 0, 0, 0, 0 },
5283 {"???", 0, 0, 0, 0 },
5284 {"???", 0, 0, 0, 0 },
5285 {"???", 0, 0, 0, 0 },
5286 {"???", 0, 0, 0, 0 },
5287 {"???", 0, 0, 0, 0 },
5288 {"???", 0, 0, 0, 0 },
5289 {"???", 0, 0, 0, 0 },
5290 {"???", 0, 0, 0, 0 },
5291 {"???", 0, 0, 0, 0 },
5292 {"???", 0, 0, 0, 0 },
5293 {"???", 0, 0, 0, 0 },
5295 {"???", 0, 0, 0, 0 },
5296 {"???", 0, 0, 0, 0 },
5297 {"???", 0, 0, 0, 0 },
5298 {"???", 0, 0, 0, 0 },
5299 {"???", 0, 0, 0, 0 },
5300 {"???", 0, 0, 0, 0 },
5301 {"???", 0, 0, 0, 0 },
5302 {"???", 0, 0, 0, 0 },
5303 {"???", 0, 0, 0, 0 },
5304 {"???", 0, 0, 0, 0 },
5305 {"???", 0, 0, 0, 0 },
5306 {"???", 0, 0, 0, 0 },
5307 {"???", 0, 0, 0, 0 },
5308 {"???", 0, 0, 0, 0 },
5309 {"???", 0, 0, 0, 0 },
5310 {"???", 0, 0, 0, 0 },
5312 {"???", 0, 0, 0, 0 },
5313 {"???", 0, 0, 0, 0 },
5314 {"???", 0, 0, 0, 0 },
5315 {"???", 0, 0, 0, 0 },
5316 {"???", 0, 0, 0, 0 },
5317 {"???", 0, 0, 0, 0 },
5318 {"???", 0, 0, 0, 0 },
5319 {"???", 0, 0, 0, 0 },
5320 {"???", 0, 0, 0, 0 },
5321 {"???", 0, 0, 0, 0 },
5322 {"???", 0, 0, 0, 0 },
5323 {"???", 0, 0, 0, 0 },
5324 {"???", 0, 0, 0, 0 },
5325 {"???", 0, 0, 0, 0 },
5326 {"???", 0, 0, 0, 0 },
5327 {"???", 0, 0, 0, 0 },
5329 {"???", 0, 0, 0, 0 },
5330 {"retrbi", 0, 0, 0, 0 }, /* V25/V35 only */
5331 {"fint", 0, 0, 0, 0 }, /* V25/V35 only */
5332 {"???", 0, 0, 0, 0 },
5333 {"tsksw", MODRM, PARAM_REG2_16, 0, 0 }, /* V25/V35 only */
5334 {"movspb", MODRM, PARAM_REG2_16, 0, 0 }, /* V25/V35 only */
5335 {"???", 0, 0, 0, 0 },
5336 {"???", 0, 0, 0, 0 },
5337 {"???", 0, 0, 0, 0 },
5338 {"???", 0, 0, 0, 0 },
5339 {"???", 0, 0, 0, 0 },
5340 {"???", 0, 0, 0, 0 },
5341 {"btclr", 0, PARAM_SFREG, PARAM_I3, PARAM_REL8 }, /* V25/V35 only */
5342 {"???", 0, 0, 0, 0 },
5343 {"stop", 0, 0, 0, 0 }, /* V25/V35 only */
5344 {"???", 0, 0, 0, 0 },
5346 {"???", 0, 0, 0, 0 },
5347 {"???", 0, 0, 0, 0 },
5348 {"???", 0, 0, 0, 0 },
5349 {"???", 0, 0, 0, 0 },
5350 {"???", 0, 0, 0, 0 },
5351 {"???", 0, 0, 0, 0 },
5352 {"???", 0, 0, 0, 0 },
5353 {"???", 0, 0, 0, 0 },
5354 {"???", 0, 0, 0, 0 },
5355 {"???", 0, 0, 0, 0 },
5356 {"???", 0, 0, 0, 0 },
5357 {"???", 0, 0, 0, 0 },
5358 {"???", 0, 0, 0, 0 },
5359 {"???", 0, 0, 0, 0 },
5360 {"???", 0, 0, 0, 0 },
5361 {"???", 0, 0, 0, 0 },
5363 {"???", 0, 0, 0, 0 },
5364 {"???", 0, 0, 0, 0 },
5365 {"???", 0, 0, 0, 0 },
5366 {"???", 0, 0, 0, 0 },
5367 {"???", 0, 0, 0, 0 },
5368 {"???", 0, 0, 0, 0 },
5369 {"???", 0, 0, 0, 0 },
5370 {"???", 0, 0, 0, 0 },
5371 {"???", 0, 0, 0, 0 },
5372 {"???", 0, 0, 0, 0 },
5373 {"???", 0, 0, 0, 0 },
5374 {"???", 0, 0, 0, 0 },
5375 {"???", 0, 0, 0, 0 },
5376 {"???", 0, 0, 0, 0 },
5377 {"???", 0, 0, 0, 0 },
5378 {"???", 0, 0, 0, 0 },
5380 {"???", 0, 0, 0, 0 },
5381 {"???", 0, 0, 0, 0 },
5382 {"???", 0, 0, 0, 0 },
5383 {"???", 0, 0, 0, 0 },
5384 {"???", 0, 0, 0, 0 },
5385 {"???", 0, 0, 0, 0 },
5386 {"???", 0, 0, 0, 0 },
5387 {"???", 0, 0, 0, 0 },
5388 {"???", 0, 0, 0, 0 },
5389 {"???", 0, 0, 0, 0 },
5390 {"???", 0, 0, 0, 0 },
5391 {"???", 0, 0, 0, 0 },
5392 {"???", 0, 0, 0, 0 },
5393 {"???", 0, 0, 0, 0 },
5394 {"???", 0, 0, 0, 0 },
5395 {"???", 0, 0, 0, 0 },
5397 {"???", 0, 0, 0, 0 },
5398 {"???", 0, 0, 0, 0 },
5399 {"???", 0, 0, 0, 0 },
5400 {"???", 0, 0, 0, 0 },
5401 {"???", 0, 0, 0, 0 },
5402 {"???", 0, 0, 0, 0 },
5403 {"???", 0, 0, 0, 0 },
5404 {"???", 0, 0, 0, 0 },
5405 {"???", 0, 0, 0, 0 },
5406 {"???", 0, 0, 0, 0 },
5407 {"???", 0, 0, 0, 0 },
5408 {"???", 0, 0, 0, 0 },
5409 {"???", 0, 0, 0, 0 },
5410 {"???", 0, 0, 0, 0 },
5411 {"???", 0, 0, 0, 0 },
5412 {"???", 0, 0, 0, 0 },
5414 {"brkxa", 0, PARAM_UI8, 0, 0 }, /* V33,53 only */
5415 {"???", 0, 0, 0, 0 },
5416 {"???", 0, 0, 0, 0 },
5417 {"???", 0, 0, 0, 0 },
5418 {"???", 0, 0, 0, 0 },
5419 {"???", 0, 0, 0, 0 },
5420 {"???", 0, 0, 0, 0 },
5421 {"???", 0, 0, 0, 0 },
5422 {"???", 0, 0, 0, 0 },
5423 {"???", 0, 0, 0, 0 },
5424 {"???", 0, 0, 0, 0 },
5425 {"???", 0, 0, 0, 0 },
5426 {"???", 0, 0, 0, 0 },
5427 {"???", 0, 0, 0, 0 },
5428 {"???", 0, 0, 0, 0 },
5429 {"???", 0, 0, 0, 0 },
5431 {"retxa", 0, PARAM_UI8, 0, 0 }, /* V33,53 only */
5432 {"???", 0, 0, 0, 0 },
5433 {"???", 0, 0, 0, 0 },
5434 {"???", 0, 0, 0, 0 },
5435 {"???", 0, 0, 0, 0 },
5436 {"???", 0, 0, 0, 0 },
5437 {"???", 0, 0, 0, 0 },
5438 {"???", 0, 0, 0, 0 },
5439 {"???", 0, 0, 0, 0 },
5440 {"???", 0, 0, 0, 0 },
5441 {"???", 0, 0, 0, 0 },
5442 {"???", 0, 0, 0, 0 },
5443 {"???", 0, 0, 0, 0 },
5444 {"???", 0, 0, 0, 0 },
5445 {"???", 0, 0, 0, 0 },
5446 {"brkem", 0, PARAM_UI8, 0, 0 } /* V20,30,40,50 only */
5449 static const I386_OPCODE immb_table[8] =
5451 {"add", 0, PARAM_RMPTR8, PARAM_UI8, 0 },
5452 {"or", 0, PARAM_RMPTR8, PARAM_UI8, 0 },
5453 {"addc", 0, PARAM_RMPTR8, PARAM_UI8, 0 },
5454 {"subc", 0, PARAM_RMPTR8, PARAM_UI8, 0 },
5455 {"and", 0, PARAM_RMPTR8, PARAM_UI8, 0 },
5456 {"sub", 0, PARAM_RMPTR8, PARAM_UI8, 0 },
5457 {"xor", 0, PARAM_RMPTR8, PARAM_UI8, 0 },
5458 {"cmp", 0, PARAM_RMPTR8, PARAM_UI8, 0 }
5461 static const I386_OPCODE immw_table[8] =
5463 {"add", 0, PARAM_RMPTR16, PARAM_IMM, 0 },
5464 {"or", 0, PARAM_RMPTR16, PARAM_IMM, 0 },
5465 {"addc", 0, PARAM_RMPTR16, PARAM_IMM, 0 },
5466 {"subc", 0, PARAM_RMPTR16, PARAM_IMM, 0 },
5467 {"and", 0, PARAM_RMPTR16, PARAM_IMM, 0 },
5468 {"sub", 0, PARAM_RMPTR16, PARAM_IMM, 0 },
5469 {"xor", 0, PARAM_RMPTR16, PARAM_IMM, 0 },
5470 {"cmp", 0, PARAM_RMPTR16, PARAM_IMM, 0 }
5473 static const I386_OPCODE immws_table[8] =
5475 {"add", 0, PARAM_RMPTR16, PARAM_I8, 0 },
5476 {"or", 0, PARAM_RMPTR16, PARAM_I8, 0 },
5477 {"addc", 0, PARAM_RMPTR16, PARAM_I8, 0 },
5478 {"subc", 0, PARAM_RMPTR16, PARAM_I8, 0 },
5479 {"and", 0, PARAM_RMPTR16, PARAM_I8, 0 },
5480 {"sub", 0, PARAM_RMPTR16, PARAM_I8, 0 },
5481 {"xor", 0, PARAM_RMPTR16, PARAM_I8, 0 },
5482 {"cmp", 0, PARAM_RMPTR16, PARAM_I8, 0 }
5485 static const I386_OPCODE shiftbi_table[8] =
5487 {"rol", 0, PARAM_RMPTR8, PARAM_I8, 0 },
5488 {"ror", 0, PARAM_RMPTR8, PARAM_I8, 0 },
5489 {"rolc", 0, PARAM_RMPTR8, PARAM_I8, 0 },
5490 {"rorc", 0, PARAM_RMPTR8, PARAM_I8, 0 },
5491 {"shl", 0, PARAM_RMPTR8, PARAM_I8, 0 },
5492 {"shr", 0, PARAM_RMPTR8, PARAM_I8, 0 },
5493 {"???", 0, PARAM_RMPTR8, PARAM_I8, 0 },
5494 {"shra", 0, PARAM_RMPTR8, PARAM_I8, 0 }
5497 static const I386_OPCODE shiftwi_table[8] =
5499 {"rol", 0, PARAM_RMPTR16, PARAM_I8, 0 },
5500 {"ror", 0, PARAM_RMPTR16, PARAM_I8, 0 },
5501 {"rolc", 0, PARAM_RMPTR16, PARAM_I8, 0 },
5502 {"rorc", 0, PARAM_RMPTR16, PARAM_I8, 0 },
5503 {"shl", 0, PARAM_RMPTR16, PARAM_I8, 0 },
5504 {"shr", 0, PARAM_RMPTR16, PARAM_I8, 0 },
5505 {"???", 0, PARAM_RMPTR16, PARAM_I8, 0 },
5506 {"shra", 0, PARAM_RMPTR16, PARAM_I8, 0 }
5509 static const I386_OPCODE shiftb_table[8] =
5511 {"rol", 0, PARAM_RMPTR8, PARAM_1, 0 },
5512 {"ror", 0, PARAM_RMPTR8, PARAM_1, 0 },
5513 {"rolc", 0, PARAM_RMPTR8, PARAM_1, 0 },
5514 {"rorc", 0, PARAM_RMPTR8, PARAM_1, 0 },
5515 {"shl", 0, PARAM_RMPTR8, PARAM_1, 0 },
5516 {"shr", 0, PARAM_RMPTR8, PARAM_1, 0 },
5517 {"???", 0, PARAM_RMPTR8, PARAM_1, 0 },
5518 {"shra", 0, PARAM_RMPTR8, PARAM_1, 0 }
5521 static const I386_OPCODE shiftw_table[8] =
5523 {"rol", 0, PARAM_RMPTR16, PARAM_1, 0 },
5524 {"ror", 0, PARAM_RMPTR16, PARAM_1, 0 },
5525 {"rolc", 0, PARAM_RMPTR16, PARAM_1, 0 },
5526 {"rorc", 0, PARAM_RMPTR16, PARAM_1, 0 },
5527 {"shl", 0, PARAM_RMPTR16, PARAM_1, 0 },
5528 {"shr", 0, PARAM_RMPTR16, PARAM_1, 0 },
5529 {"???", 0, PARAM_RMPTR16, PARAM_1, 0 },
5530 {"shra", 0, PARAM_RMPTR16, PARAM_1, 0 }
5533 static const I386_OPCODE shiftbv_table[8] =
5535 {"rol", 0, PARAM_RMPTR8, PARAM_CL, 0 },
5536 {"ror", 0, PARAM_RMPTR8, PARAM_CL, 0 },
5537 {"rolc", 0, PARAM_RMPTR8, PARAM_CL, 0 },
5538 {"rorc", 0, PARAM_RMPTR8, PARAM_CL, 0 },
5539 {"shl", 0, PARAM_RMPTR8, PARAM_CL, 0 },
5540 {"shr", 0, PARAM_RMPTR8, PARAM_CL, 0 },
5541 {"???", 0, PARAM_RMPTR8, PARAM_CL, 0 },
5542 {"shra", 0, PARAM_RMPTR8, PARAM_CL, 0 }
5545 static const I386_OPCODE shiftwv_table[8] =
5547 {"rol", 0, PARAM_RMPTR16, PARAM_CL, 0 },
5548 {"ror", 0, PARAM_RMPTR16, PARAM_CL, 0 },
5549 {"rolc", 0, PARAM_RMPTR16, PARAM_CL, 0 },
5550 {"rorc", 0, PARAM_RMPTR16, PARAM_CL, 0 },
5551 {"shl", 0, PARAM_RMPTR16, PARAM_CL, 0 },
5552 {"shr", 0, PARAM_RMPTR16, PARAM_CL, 0 },
5553 {"???", 0, PARAM_RMPTR16, PARAM_CL, 0 },
5554 {"shra", 0, PARAM_RMPTR16, PARAM_CL, 0 }
5557 static const I386_OPCODE group1b_table[8] =
5559 {"test", 0, PARAM_RMPTR8, PARAM_UI8, 0 },
5560 {"???", 0, 0, 0, 0 },
5561 {"not", 0, PARAM_RMPTR8, 0, 0 },
5562 {"neg", 0, PARAM_RMPTR8, 0, 0 },
5563 {"mulu", 0, PARAM_RMPTR8, 0, 0 },
5564 {"mul", 0, PARAM_RMPTR8, 0, 0 },
5565 {"divu", 0, PARAM_RMPTR8, 0, 0 },
5566 {"div", 0, PARAM_RMPTR8, 0, 0 }
5569 static const I386_OPCODE group1w_table[8] =
5571 {"test", 0, PARAM_RMPTR16, PARAM_IMM, 0 },
5572 {"???", 0, 0, 0, 0 },
5573 {"not", 0, PARAM_RMPTR16, 0, 0 },
5574 {"neg", 0, PARAM_RMPTR16, 0, 0 },
5575 {"mulu", 0, PARAM_RMPTR16, 0, 0 },
5576 {"mul", 0, PARAM_RMPTR16, 0, 0 },
5577 {"divu", 0, PARAM_RMPTR16, 0, 0 },
5578 {"div", 0, PARAM_RMPTR16, 0, 0 }
5581 static const I386_OPCODE group2b_table[8] =
5583 {"inc", 0, PARAM_RMPTR8, 0, 0 },
5584 {"dec", 0, PARAM_RMPTR8, 0, 0 },
5585 {"???", 0, 0, 0, 0 },
5586 {"???", 0, 0, 0, 0 },
5587 {"???", 0, 0, 0, 0 },
5588 {"???", 0, 0, 0, 0 },
5589 {"???", 0, 0, 0, 0 },
5590 {"???", 0, 0, 0, 0 }
5593 static const I386_OPCODE group2w_table[8] =
5595 {"inc", 0, PARAM_RMPTR16, 0, 0 },
5596 {"dec", 0, PARAM_RMPTR16, 0, 0 },
5597 {"call", 0, PARAM_RMPTR16, 0, 0, DASMFLAG_STEP_OVER},
5598 {"call far ptr ",0, PARAM_RM16, 0, 0, DASMFLAG_STEP_OVER},
5599 {"br", 0, PARAM_RMPTR16, 0, 0 },
5600 {"br far ptr ",0, PARAM_RM16, 0, 0 },
5601 {"push", 0, PARAM_RMPTR16, 0, 0 },
5602 {"???", 0, 0, 0, 0 }
5605 static const GROUP_OP group_op_table[] =
5607 { "immb", immb_table },
5608 { "immw", immw_table },
5609 { "immws", immws_table },
5610 { "shiftbi", shiftbi_table },
5611 { "shiftwi", shiftwi_table },
5612 { "shiftb", shiftb_table },
5613 { "shiftw", shiftw_table },
5614 { "shiftbv", shiftbv_table },
5615 { "shiftwv", shiftwv_table },
5616 { "group1b", group1b_table },
5617 { "group1w", group1w_table },
5618 { "group2b", group2b_table },
5619 { "group2w", group2w_table }
5624 static const char *const nec_reg[8] = { "aw", "cw", "dw", "bw", "sp", "bp", "ix", "iy" };
5625 static const char *const nec_reg8[8] = { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh" };
5626 static const char *const nec_sreg[8] = { "ds1", "ps", "ss", "ds0", "???", "???", "???", "???" };
5627 static const char *const nec_sfreg[256] =
5630 "p0", "pm0", "pmc0", "???", "???", "???", "???", "???",
5631 "p1", "pm1", "pmc1", "???", "???", "???", "???", "???",
5633 "p2", "pm2", "pmc2", "???", "???", "???", "???", "???",
5634 "???", "???", "???", "???", "???", "???", "???", "???",
5636 "???", "???", "???", "???", "???", "???", "???", "???",
5637 "???", "???", "???", "???", "???", "???", "???", "???",
5639 "???", "???", "???", "???", "???", "???", "???", "???",
5640 "pt", "???", "???", "pmt", "???", "???", "???", "???",
5642 "intm", "???", "???", "???", "ems0", "ems1", "ems2", "???",
5643 "???", "???", "???", "???", "exic0","exic1","exic2","???",
5645 "???", "???", "???", "???", "???", "???", "???", "???",
5646 "???", "???", "???", "???", "???", "???", "???", "???",
5648 "rxb0", "???", "txb0", "???", "???", "srms0","stms0","???",
5649 "scm0", "scc0", "brg0", "scs0", "seic0","sric0","stic0","???",
5651 "rxb1", "???", "txb1", "???", "???", "srms1","stms1","???",
5652 "scm1", "scc1", "brg1", "scs1", "seic1","sric1","stic1","???",
5654 "tm0", "???", "md0", "???", "???", "???", "???", "???",
5655 "tm1", "???", "md1", "???", "???", "???", "???", "???",
5657 "tmc0", "tmc1", "???", "???", "tmms0","tmms1","tmms2","???",
5658 "???", "???", "???", "???", "tmic0","tmic1","tmic2","???",
5660 "dmac0","dmam0","dmac1","dmam1","???", "???", "???", "???",
5661 "???", "???", "???", "???", "dic0", "dic1", "???", "???",
5663 "???", "???", "???", "???", "???", "???", "???", "???",
5664 "???", "???", "???", "???", "???", "???", "???", "???",
5666 "sar0l","sar0m","sar0h","???", "dar0l","dar0m","dar0h","???",
5667 "tc0l", "tc0h", "???", "???", "???", "???", "???", "???",
5669 "sar1l","sar1m","sar1h","???", "dar1l","dar1m","dar1h","???",
5670 "tc1l", "tc1h", "???", "???", "???", "???", "???", "???",
5672 "stbc", "rfm", "???", "???", "???", "???", "???", "???",
5673 "wtc", "???", "flag", "prc", "tbic", "???", "???", "irqs",
5675 "???", "???", "???", "???", "???", "???", "???", "???",
5676 "???", "???", "???", "???", "ispr", "???", "???", "idb"
5681 static UINT32 segment;
5682 static offs_t dasm_flags;
5683 static char modrm_string[256];
5685 #define MODRM_REG1 ((modrm >> 3) & 0x7)
5686 #define MODRM_REG2 (modrm & 0x7)
5688 #define MAX_LENGTH 8
5690 INLINE UINT8 FETCHD(void)
5692 if ((opcode_ptr - opcode_ptr_base) + 1 > MAX_LENGTH)
5695 return *opcode_ptr++;
5698 INLINE UINT16 FETCHD16(void)
5701 if ((opcode_ptr - opcode_ptr_base) + 2 > MAX_LENGTH)
5703 d = opcode_ptr[0] | (opcode_ptr[1] << 8);
5709 static char *hexstring(UINT32 value, int digits)
5711 static char buffer[20];
5714 sprintf(&buffer[1], "%0*Xh", digits, value);
5716 sprintf(&buffer[1], "%Xh", value);
5718 return (buffer[1] >= '0' && buffer[1] <= '9') ? &buffer[1] : &buffer[0];
5721 static char *shexstring(UINT32 value, int digits, int always)
5723 static char buffer[20];
5724 if (value >= 0x80000000) {
5725 sprintf(buffer, "-%s", hexstring(-value, digits));
5726 } else if (always) {
5727 sprintf(buffer, "+%s", hexstring(value, digits));
5729 return hexstring(value, digits);
5734 static void handle_modrm(char* s)
5741 mod = (modrm >> 6) & 0x3;
5749 case SEG_PS: s += sprintf( s, "ps:" ); break;
5750 case SEG_DS0: s += sprintf( s, "ds0:" ); break;
5751 case SEG_DS1: s += sprintf( s, "ds1:" ); break;
5752 case SEG_SS: s += sprintf( s, "ss:" ); break;
5755 s += sprintf( s, "[" );
5758 case 0: s += sprintf( s, "bw+ix" ); break;
5759 case 1: s += sprintf( s, "bw+iy" ); break;
5760 case 2: s += sprintf( s, "bp+ix" ); break;
5761 case 3: s += sprintf( s, "bp+iy" ); break;
5762 case 4: s += sprintf( s, "ix" ); break;
5763 case 5: s += sprintf( s, "iy" ); break;
5766 disp16 = FETCHD16();
5767 s += sprintf( s, "%s", hexstring((unsigned) (UINT16) disp16, 0) );
5769 s += sprintf( s, "bp" );
5772 case 7: s += sprintf( s, "bw" ); break;
5776 s += sprintf( s, "%s", shexstring((INT32)disp8, 0, TRUE) );
5777 } else if( mod == 2 ) {
5778 disp16 = FETCHD16();
5779 s += sprintf( s, "%s", shexstring((INT32)disp16, 0, TRUE) );
5781 s += sprintf( s, "]" );
5784 static char* handle_param(char* s, UINT32 param)
5796 s += sprintf( s, "%s", nec_reg8[MODRM_REG1] );
5800 s += sprintf( s, "%s", nec_reg[MODRM_REG1] );
5804 s += sprintf( s, "%s", nec_reg8[MODRM_REG2] );
5808 s += sprintf( s, "%s", nec_reg[MODRM_REG2] );
5813 if( modrm >= 0xc0 ) {
5814 s += sprintf( s, "%s", nec_reg8[MODRM_REG2] );
5816 if (param == PARAM_RMPTR8)
5817 s += sprintf( s, "byte ptr " );
5818 s += sprintf( s, "%s", modrm_string );
5824 if( modrm >= 0xc0 ) {
5825 s += sprintf( s, "%s", nec_reg[MODRM_REG2] );
5827 if (param == PARAM_RMPTR16)
5828 s += sprintf( s, "word ptr " );
5829 s += sprintf( s, "%s", modrm_string );
5835 s += sprintf( s, "%d", i8 & 0x07 );
5840 s += sprintf( s, "%d", i8 & 0x0f );
5845 s += sprintf( s, "%s", shexstring((INT8)i8, 0, FALSE) );
5850 s += sprintf( s, "%s", shexstring((INT16)i16, 0, FALSE) );
5855 s += sprintf( s, "%s", shexstring((UINT8)i8, 0, FALSE) );
5860 s += sprintf( s, "%s", hexstring(i16, 0) );
5866 s += sprintf( s, "%s:", hexstring(ptr, 4) );
5867 s += sprintf( s, "%s", hexstring(addr, 0) );
5871 /* make sure to keep the relative offset within the segment */
5873 s += sprintf( s, "%s", hexstring((pc & 0xFFFF0000) | ((pc + d16) & 0x0000FFFF), 0) );
5878 s += sprintf( s, "%s", hexstring(pc + d8, 0) );
5881 case PARAM_MEM_OFFS:
5884 case SEG_PS: s += sprintf( s, "ps:" ); break;
5885 case SEG_DS0: s += sprintf( s, "ds0:" ); break;
5886 case SEG_DS1: s += sprintf( s, "ds1:" ); break;
5887 case SEG_SS: s += sprintf( s, "ss:" ); break;
5891 s += sprintf( s, "[%s]", hexstring(i16, 0) );
5895 s += sprintf( s, "%s", nec_sreg[MODRM_REG1] );
5900 s += sprintf( s, "%s", nec_sfreg[i8] );
5904 s += sprintf( s, "1" );
5907 case PARAM_AL: s += sprintf( s, "al" ); break;
5908 case PARAM_CL: s += sprintf( s, "cl" ); break;
5909 case PARAM_DL: s += sprintf( s, "dl" ); break;
5910 case PARAM_BL: s += sprintf( s, "bl" ); break;
5911 case PARAM_AH: s += sprintf( s, "ah" ); break;
5912 case PARAM_CH: s += sprintf( s, "ch" ); break;
5913 case PARAM_DH: s += sprintf( s, "dh" ); break;
5914 case PARAM_BH: s += sprintf( s, "bh" ); break;
5916 case PARAM_AW: s += sprintf( s, "aw" ); break;
5917 case PARAM_CW: s += sprintf( s, "cw" ); break;
5918 case PARAM_DW: s += sprintf( s, "dw" ); break;
5919 case PARAM_BW: s += sprintf( s, "bw" ); break;
5920 case PARAM_SP: s += sprintf( s, "sp" ); break;
5921 case PARAM_BP: s += sprintf( s, "bp" ); break;
5922 case PARAM_IX: s += sprintf( s, "ix" ); break;
5923 case PARAM_IY: s += sprintf( s, "iy" ); break;
5928 static void handle_fpu(char *s, UINT8 op1, UINT8 op2)
5936 pc--; // adjust fetch pointer, so modrm byte read again
5938 handle_modrm( modrm_string );
5939 switch ((op2 >> 3) & 0x7)
5941 case 0: sprintf(s, "fadd dword ptr %s", modrm_string); break;
5942 case 1: sprintf(s, "fmul dword ptr %s", modrm_string); break;
5943 case 2: sprintf(s, "fcom dword ptr %s", modrm_string); break;
5944 case 3: sprintf(s, "fcomp dword ptr %s", modrm_string); break;
5945 case 4: sprintf(s, "fsub dword ptr %s", modrm_string); break;
5946 case 5: sprintf(s, "fsubr dword ptr %s", modrm_string); break;
5947 case 6: sprintf(s, "fdiv dword ptr %s", modrm_string); break;
5948 case 7: sprintf(s, "fdivr dword ptr %s", modrm_string); break;
5951 switch ((op2 >> 3) & 0x7)
5953 case 0: sprintf(s, "fadd st(0),st(%d)", op2 & 0x7); break;
5954 case 1: sprintf(s, "fcom st(0),st(%d)", op2 & 0x7); break;
5955 case 2: sprintf(s, "fsub st(0),st(%d)", op2 & 0x7); break;
5956 case 3: sprintf(s, "fdiv st(0),st(%d)", op2 & 0x7); break;
5957 case 4: sprintf(s, "fmul st(0),st(%d)", op2 & 0x7); break;
5958 case 5: sprintf(s, "fcomp st(0),st(%d)", op2 & 0x7); break;
5959 case 6: sprintf(s, "fsubr st(0),st(%d)", op2 & 0x7); break;
5960 case 7: sprintf(s, "fdivr st(0),st(%d)", op2 & 0x7); break;
5970 pc--; // adjust fetch pointer, so modrm byte read again
5972 handle_modrm( modrm_string );
5973 switch ((op2 >> 3) & 0x7)
5975 case 0: sprintf(s, "fld dword ptr %s", modrm_string); break;
5976 case 1: sprintf(s, "??? (FPU)"); break;
5977 case 2: sprintf(s, "fst dword ptr %s", modrm_string); break;
5978 case 3: sprintf(s, "fstp dword ptr %s", modrm_string); break;
5979 case 4: sprintf(s, "fldenv word ptr %s", modrm_string); break;
5980 case 5: sprintf(s, "fldcw word ptr %s", modrm_string); break;
5981 case 6: sprintf(s, "fstenv word ptr %s", modrm_string); break;
5982 case 7: sprintf(s, "fstcw word ptr %s", modrm_string); break;
5987 case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
5988 sprintf(s, "fld st(0),st(%d)", op2 & 0x7); break;
5990 case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
5991 sprintf(s, "fxch st(0),st(%d)", op2 & 0x7); break;
5993 case 0x10: sprintf(s, "fnop"); break;
5994 case 0x20: sprintf(s, "fchs"); break;
5995 case 0x21: sprintf(s, "fabs"); break;
5996 case 0x24: sprintf(s, "ftst"); break;
5997 case 0x25: sprintf(s, "fxam"); break;
5998 case 0x28: sprintf(s, "fld1"); break;
5999 case 0x29: sprintf(s, "fldl2t"); break;
6000 case 0x2a: sprintf(s, "fldl2e"); break;
6001 case 0x2b: sprintf(s, "fldpi"); break;
6002 case 0x2c: sprintf(s, "fldlg2"); break;
6003 case 0x2d: sprintf(s, "fldln2"); break;
6004 case 0x2e: sprintf(s, "fldz"); break;
6005 case 0x30: sprintf(s, "f2xm1"); break;
6006 case 0x31: sprintf(s, "fyl2x"); break;
6007 case 0x32: sprintf(s, "fptan"); break;
6008 case 0x33: sprintf(s, "fpatan"); break;
6009 case 0x34: sprintf(s, "fxtract"); break;
6010 case 0x35: sprintf(s, "fprem1"); break;
6011 case 0x36: sprintf(s, "fdecstp"); break;
6012 case 0x37: sprintf(s, "fincstp"); break;
6013 case 0x38: sprintf(s, "fprem"); break;
6014 case 0x39: sprintf(s, "fyl2xp1"); break;
6015 case 0x3a: sprintf(s, "fsqrt"); break;
6016 case 0x3b: sprintf(s, "fsincos"); break;
6017 case 0x3c: sprintf(s, "frndint"); break;
6018 case 0x3d: sprintf(s, "fscale"); break;
6019 case 0x3e: sprintf(s, "fsin"); break;
6020 case 0x3f: sprintf(s, "fcos"); break;
6022 default: sprintf(s, "??? (FPU)"); break;
6032 pc--; // adjust fetch pointer, so modrm byte read again
6034 handle_modrm( modrm_string );
6035 switch ((op2 >> 3) & 0x7)
6037 case 0: sprintf(s, "fiadd dword ptr %s", modrm_string); break;
6038 case 1: sprintf(s, "fimul dword ptr %s", modrm_string); break;
6039 case 2: sprintf(s, "ficom dword ptr %s", modrm_string); break;
6040 case 3: sprintf(s, "ficomp dword ptr %s", modrm_string); break;
6041 case 4: sprintf(s, "fisub dword ptr %s", modrm_string); break;
6042 case 5: sprintf(s, "fisubr dword ptr %s", modrm_string); break;
6043 case 6: sprintf(s, "fidiv dword ptr %s", modrm_string); break;
6044 case 7: sprintf(s, "fidivr dword ptr %s", modrm_string); break;
6049 case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
6050 sprintf(s, "fcmovb st(0),st(%d)", op2 & 0x7); break;
6052 case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
6053 sprintf(s, "fcmove st(0),st(%d)", op2 & 0x7); break;
6055 case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
6056 sprintf(s, "fcmovbe st(0),st(%d)", op2 & 0x7); break;
6058 case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
6059 sprintf(s, "fcmovu st(0),st(%d)", op2 & 0x7); break;
6061 default: sprintf(s, "??? (FPU)"); break;
6072 pc--; // adjust fetch pointer, so modrm byte read again
6074 handle_modrm( modrm_string );
6075 switch ((op2 >> 3) & 0x7)
6077 case 0: sprintf(s, "fild dword ptr %s", modrm_string); break;
6078 case 1: sprintf(s, "??? (FPU)"); break;
6079 case 2: sprintf(s, "fist dword ptr %s", modrm_string); break;
6080 case 3: sprintf(s, "fistp dword ptr %s", modrm_string); break;
6081 case 4: sprintf(s, "??? (FPU)"); break;
6082 case 5: sprintf(s, "fld tword ptr %s", modrm_string); break;
6083 case 6: sprintf(s, "??? (FPU)"); break;
6084 case 7: sprintf(s, "fstp tword ptr %s", modrm_string); break;
6089 case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
6090 sprintf(s, "fcmovnb st(0),st(%d)", op2 & 0x7); break;
6092 case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
6093 sprintf(s, "fcmovne st(0),st(%d)", op2 & 0x7); break;
6095 case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
6096 sprintf(s, "fcmovnbe st(0),st(%d)", op2 & 0x7); break;
6098 case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
6099 sprintf(s, "fcmovnu st(0),st(%d)", op2 & 0x7); break;
6101 case 0x22: sprintf(s, "fclex"); break;
6102 case 0x23: sprintf(s, "finit"); break;
6104 case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
6105 sprintf(s, "fucomi st(0),st(%d)", op2 & 0x7); break;
6107 case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
6108 sprintf(s, "fcomi st(0),st(%d)", op2 & 0x7); break;
6110 default: sprintf(s, "??? (FPU)"); break;
6120 pc--; // adjust fetch pointer, so modrm byte read again
6122 handle_modrm( modrm_string );
6123 switch ((op2 >> 3) & 0x7)
6125 case 0: sprintf(s, "fadd qword ptr %s", modrm_string); break;
6126 case 1: sprintf(s, "fmul qword ptr %s", modrm_string); break;
6127 case 2: sprintf(s, "fcom qword ptr %s", modrm_string); break;
6128 case 3: sprintf(s, "fcomp qword ptr %s", modrm_string); break;
6129 case 4: sprintf(s, "fsub qword ptr %s", modrm_string); break;
6130 case 5: sprintf(s, "fsubr qword ptr %s", modrm_string); break;
6131 case 6: sprintf(s, "fdiv qword ptr %s", modrm_string); break;
6132 case 7: sprintf(s, "fdivr qword ptr %s", modrm_string); break;
6137 case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
6138 sprintf(s, "fadd st(%d),st(0)", op2 & 0x7); break;
6140 case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
6141 sprintf(s, "fmul st(%d),st(0)", op2 & 0x7); break;
6143 case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
6144 sprintf(s, "fsubr st(%d),st(0)", op2 & 0x7); break;
6146 case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
6147 sprintf(s, "fsub st(%d),st(0)", op2 & 0x7); break;
6149 case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
6150 sprintf(s, "fdivr st(%d),st(0)", op2 & 0x7); break;
6152 case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
6153 sprintf(s, "fdiv st(%d),st(0)", op2 & 0x7); break;
6155 default: sprintf(s, "??? (FPU)"); break;
6165 pc--; // adjust fetch pointer, so modrm byte read again
6167 handle_modrm( modrm_string );
6168 switch ((op2 >> 3) & 0x7)
6170 case 0: sprintf(s, "fld qword ptr %s", modrm_string); break;
6171 case 1: sprintf(s, "??? (FPU)"); break;
6172 case 2: sprintf(s, "fst qword ptr %s", modrm_string); break;
6173 case 3: sprintf(s, "fstp qword ptr %s", modrm_string); break;
6174 case 4: sprintf(s, "frstor %s", modrm_string); break;
6175 case 5: sprintf(s, "??? (FPU)"); break;
6176 case 6: sprintf(s, "fsave %s", modrm_string); break;
6177 case 7: sprintf(s, "fstsw word ptr %s", modrm_string); break;
6182 case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
6183 sprintf(s, "ffree st(%d)", op2 & 0x7); break;
6185 case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
6186 sprintf(s, "fst st(%d)", op2 & 0x7); break;
6188 case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
6189 sprintf(s, "fstp st(%d)", op2 & 0x7); break;
6191 case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
6192 sprintf(s, "fucom st(%d), st(0)", op2 & 0x7); break;
6194 case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
6195 sprintf(s, "fucomp st(%d)", op2 & 0x7); break;
6197 default: sprintf(s, "??? (FPU)"); break;
6207 pc--; // adjust fetch pointer, so modrm byte read again
6209 handle_modrm( modrm_string );
6210 switch ((op2 >> 3) & 0x7)
6212 case 0: sprintf(s, "fiadd word ptr %s", modrm_string); break;
6213 case 1: sprintf(s, "fimul word ptr %s", modrm_string); break;
6214 case 2: sprintf(s, "ficom word ptr %s", modrm_string); break;
6215 case 3: sprintf(s, "ficomp word ptr %s", modrm_string); break;
6216 case 4: sprintf(s, "fisub word ptr %s", modrm_string); break;
6217 case 5: sprintf(s, "fisubr word ptr %s", modrm_string); break;
6218 case 6: sprintf(s, "fidiv word ptr %s", modrm_string); break;
6219 case 7: sprintf(s, "fidivr word ptr %s", modrm_string); break;
6224 case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
6225 sprintf(s, "faddp st(%d)", op2 & 0x7); break;
6227 case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
6228 sprintf(s, "fmulp st(%d)", op2 & 0x7); break;
6230 case 0x19: sprintf(s, "fcompp"); break;
6232 case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
6233 sprintf(s, "fsubrp st(%d)", op2 & 0x7); break;
6235 case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
6236 sprintf(s, "fsubp st(%d)", op2 & 0x7); break;
6238 case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
6239 sprintf(s, "fdivrp st(%d), st(0)", op2 & 0x7); break;
6241 case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
6242 sprintf(s, "fdivp st(%d)", op2 & 0x7); break;
6244 default: sprintf(s, "??? (FPU)"); break;
6254 pc--; // adjust fetch pointer, so modrm byte read again
6256 handle_modrm( modrm_string );
6257 switch ((op2 >> 3) & 0x7)
6259 case 0: sprintf(s, "fild word ptr %s", modrm_string); break;
6260 case 1: sprintf(s, "??? (FPU)"); break;
6261 case 2: sprintf(s, "fist word ptr %s", modrm_string); break;
6262 case 3: sprintf(s, "fistp word ptr %s", modrm_string); break;
6263 case 4: sprintf(s, "fbld %s", modrm_string); break;
6264 case 5: sprintf(s, "fild qword ptr %s", modrm_string); break;
6265 case 6: sprintf(s, "fbstp %s", modrm_string); break;
6266 case 7: sprintf(s, "fistp qword ptr %s", modrm_string); break;
6271 case 0x20: sprintf(s, "fstsw aw"); break;
6273 case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
6274 sprintf(s, "fucomip st(%d)", op2 & 0x7); break;
6276 case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
6277 sprintf(s, "fcomip st(%d),st(0)", op2 & 0x7); break;
6279 default: sprintf(s, "??? (FPU)"); break;
6287 static void decode_opcode(char *s, const I386_OPCODE *op, UINT8 op1 )
6296 decode_opcode( s, &necv_opcode_table2[op2], op1 );
6303 segment = op->flags;
6305 decode_opcode( s, &necv_opcode_table1[op2], op1 );
6309 s += sprintf( s, "%-8s", op->mnemonic );
6311 decode_opcode( s, &necv_opcode_table1[op2], op1 );
6315 handle_modrm( modrm_string );
6316 for( i=0; i < ARRAY_LENGTH(group_op_table); i++ ) {
6317 if( strcmp(op->mnemonic, group_op_table[i].mnemonic) == 0 )
6319 decode_opcode( s, &group_op_table[i].opcode[MODRM_REG1], op1 );
6323 goto handle_unknown;
6327 handle_fpu( s, op1, op2);
6331 handle_modrm( modrm_string );
6335 s += sprintf( s, "%-8s", op->mnemonic );
6336 dasm_flags = op->dasm_flags;
6338 if( op->param1 != 0 ) {
6339 s = handle_param( s, op->param1 );
6342 if( op->param2 != 0 ) {
6343 s += sprintf( s, "," );
6344 s = handle_param( s, op->param2 );
6347 if( op->param3 != 0 ) {
6348 s += sprintf( s, "," );
6349 s = handle_param( s, op->param3 );
6357 int necv_dasm_one(char *buffer, UINT32 eip, const UINT8 *oprom)
6361 opcode_ptr = opcode_ptr_base = oprom;
6368 decode_opcode( buffer, &necv_opcode_table1[op], op );
6369 return (pc-eip) | dasm_flags | DASMFLAG_SUPPORTED;
6372 #define STATE_VERSION 1
6374 void I86::save_state(FILEIO* state_fio)
6376 state_fio->FputUint32(STATE_VERSION);
6377 state_fio->FputInt32(this_device_id);
6379 state_fio->Fwrite(®s, sizeof(regs), 1);
6380 state_fio->FputUint32(pc);
6381 state_fio->FputUint32(prevpc);
6382 state_fio->Fwrite(base, sizeof(base), 1);
6383 state_fio->Fwrite(sregs, sizeof(sregs), 1);
6384 state_fio->FputUint16(flags);
6385 state_fio->FputInt32(AuxVal);
6386 state_fio->FputInt32(OverVal);
6387 state_fio->FputInt32(SignVal);
6388 state_fio->FputInt32(ZeroVal);
6389 state_fio->FputInt32(CarryVal);
6390 state_fio->FputInt32(DirVal);
6391 state_fio->FputUint8(ParityVal);
6392 state_fio->FputUint8(TF);
6393 state_fio->FputUint8(IF);
6394 state_fio->FputUint8(MF);
6395 state_fio->FputInt32(int_state);
6396 state_fio->FputBool(test_state);
6397 state_fio->FputBool(busreq);
6398 state_fio->FputBool(halted);
6399 state_fio->FputInt32(icount);
6400 state_fio->FputInt32(extra_icount);
6401 state_fio->FputBool(seg_prefix);
6402 state_fio->FputUint8(prefix_seg);
6403 state_fio->FputUint32(ea);
6404 state_fio->FputUint16(eo);
6405 state_fio->FputUint8(ea_seg);
6408 bool I86::load_state(FILEIO* state_fio)
6410 if(state_fio->FgetUint32() != STATE_VERSION) {
6413 if(state_fio->FgetInt32() != this_device_id) {
6416 state_fio->Fread(®s, sizeof(regs), 1);
6417 pc = state_fio->FgetUint32();
6418 prevpc = state_fio->FgetUint32();
6419 state_fio->Fread(base, sizeof(base), 1);
6420 state_fio->Fread(sregs, sizeof(sregs), 1);
6421 flags = state_fio->FgetUint16();
6422 AuxVal = state_fio->FgetInt32();
6423 OverVal = state_fio->FgetInt32();
6424 SignVal = state_fio->FgetInt32();
6425 ZeroVal = state_fio->FgetInt32();
6426 CarryVal = state_fio->FgetInt32();
6427 DirVal = state_fio->FgetInt32();
6428 ParityVal = state_fio->FgetUint8();
6429 TF = state_fio->FgetUint8();
6430 IF = state_fio->FgetUint8();
6431 MF = state_fio->FgetUint8();
6432 int_state = state_fio->FgetInt32();
6433 test_state = state_fio->FgetBool();
6434 busreq = state_fio->FgetBool();
6435 halted = state_fio->FgetBool();
6436 icount = state_fio->FgetInt32();
6437 extra_icount = state_fio->FgetInt32();
6438 seg_prefix = state_fio->FgetBool();
6439 prefix_seg = state_fio->FgetUint8();
6440 ea = state_fio->FgetUint32();
6441 eo = state_fio->FgetUint16();
6442 ea_seg = state_fio->FgetUint8();