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 )
20 #include "../fileio.h"
22 #define DIVIDE_FAULT 0
23 #define NMI_INT_VECTOR 2
24 #define OVERFLOW_TRAP 4
25 #define BOUNDS_CHECK_FAULT 5
26 #define ILLEGAL_INSTRUCTION 6
27 #define GENERAL_PROTECTION_FAULT 13
32 typedef enum { ES, CS, SS, DS } SREGS;
33 typedef enum { AX, CX, DX, BX, SP, BP, SI, DI } WREGS;
37 AH, AL, CH, CL, DH, DL, BH, BL,
38 SPH, SPL, BPH, BPL, SIH, SIL, DIH, DIL,
40 AL, AH, CL, CH, DL, DH, BL, BH,
41 SPL, SPH, BPL, BPH, SIL, SIH, DIL, DIH,
56 static const uint8 parity_table[256] = {
57 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
58 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
59 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
60 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
61 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
62 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
63 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
64 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
65 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
66 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
67 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
68 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
69 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
70 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
71 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
72 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
75 /************************************************************************/
77 struct i80x86_timing {
78 uint8 exception, iret; /* exception, IRET */
79 uint8 int3, int_imm, into_nt, into_t; /* INTs */
80 uint8 override; /* segment overrides */
81 uint8 flag_ops, lahf, sahf; /* flag operations */
82 uint8 aaa, aas, aam, aad; /* arithmetic adjusts */
83 uint8 daa, das; /* decimal adjusts */
84 uint8 cbw, cwd; /* sign extension */
85 uint8 hlt, load_ptr, lea, nop, wait, xlat; /* misc */
87 uint8 jmp_short, jmp_near, jmp_far; /* direct JMPs */
88 uint8 jmp_r16, jmp_m16, jmp_m32; /* indirect JMPs */
89 uint8 call_near, call_far; /* direct CALLs */
90 uint8 call_r16, call_m16, call_m32; /* indirect CALLs */
91 uint8 ret_near, ret_far, ret_near_imm, ret_far_imm; /* returns */
92 uint8 jcc_nt, jcc_t, jcxz_nt, jcxz_t; /* conditional JMPs */
93 uint8 loop_nt, loop_t, loope_nt, loope_t; /* loops */
95 uint8 in_imm8, in_imm16, in_dx8, in_dx16; /* port reads */
96 uint8 out_imm8, out_imm16, out_dx8, out_dx16; /* port writes */
98 uint8 mov_rr8, mov_rm8, mov_mr8; /* move, 8-bit */
99 uint8 mov_ri8, mov_mi8; /* move, 8-bit immediate */
100 uint8 mov_rr16, mov_rm16, mov_mr16; /* move, 16-bit */
101 uint8 mov_ri16, mov_mi16; /* move, 16-bit immediate */
102 uint8 mov_am8, mov_am16, mov_ma8, mov_ma16; /* move, AL/AX memory */
103 uint8 mov_sr, mov_sm, mov_rs, mov_ms; /* move, segment registers */
104 uint8 xchg_rr8, xchg_rm8; /* exchange, 8-bit */
105 uint8 xchg_rr16, xchg_rm16, xchg_ar16; /* exchange, 16-bit */
107 uint8 push_r16, push_m16, push_seg, pushf; /* pushes */
108 uint8 pop_r16, pop_m16, pop_seg, popf; /* pops */
110 uint8 alu_rr8, alu_rm8, alu_mr8; /* ALU ops, 8-bit */
111 uint8 alu_ri8, alu_mi8, alu_mi8_ro; /* ALU ops, 8-bit immediate */
112 uint8 alu_rr16, alu_rm16, alu_mr16; /* ALU ops, 16-bit */
113 uint8 alu_ri16, alu_mi16, alu_mi16_ro; /* ALU ops, 16-bit immediate */
114 uint8 alu_r16i8, alu_m16i8, alu_m16i8_ro; /* ALU ops, 16-bit w/8-bit immediate */
115 uint8 mul_r8, mul_r16, mul_m8, mul_m16; /* MUL */
116 uint8 imul_r8, imul_r16, imul_m8, imul_m16; /* IMUL */
117 uint8 div_r8, div_r16, div_m8, div_m16; /* DIV */
118 uint8 idiv_r8, idiv_r16, idiv_m8, idiv_m16; /* IDIV */
119 uint8 incdec_r8, incdec_r16, incdec_m8, incdec_m16; /* INC/DEC */
120 uint8 negnot_r8, negnot_r16, negnot_m8, negnot_m16; /* NEG/NOT */
122 uint8 rot_reg_1, rot_reg_base, rot_reg_bit; /* reg shift/rotate */
123 uint8 rot_m8_1, rot_m8_base, rot_m8_bit; /* m8 shift/rotate */
124 uint8 rot_m16_1, rot_m16_base, rot_m16_bit; /* m16 shift/rotate */
126 uint8 cmps8, rep_cmps8_base, rep_cmps8_count; /* CMPS 8-bit */
127 uint8 cmps16, rep_cmps16_base, rep_cmps16_count; /* CMPS 16-bit */
128 uint8 scas8, rep_scas8_base, rep_scas8_count; /* SCAS 8-bit */
129 uint8 scas16, rep_scas16_base, rep_scas16_count; /* SCAS 16-bit */
130 uint8 lods8, rep_lods8_base, rep_lods8_count; /* LODS 8-bit */
131 uint8 lods16, rep_lods16_base, rep_lods16_count; /* LODS 16-bit */
132 uint8 stos8, rep_stos8_base, rep_stos8_count; /* STOS 8-bit */
133 uint8 stos16, rep_stos16_base, rep_stos16_count; /* STOS 16-bit */
134 uint8 movs8, rep_movs8_base, rep_movs8_count; /* MOVS 8-bit */
135 uint8 movs16, rep_movs16_base, rep_movs16_count; /* MOVS 16-bit */
137 uint8 ins8, rep_ins8_base, rep_ins8_count; /* (80186) INS 8-bit */
138 uint8 ins16, rep_ins16_base, rep_ins16_count; /* (80186) INS 16-bit */
139 uint8 outs8, rep_outs8_base, rep_outs8_count; /* (80186) OUTS 8-bit */
140 uint8 outs16, rep_outs16_base, rep_outs16_count; /* (80186) OUTS 16-bit */
141 uint8 push_imm, pusha, popa; /* (80186) PUSH immediate, PUSHA/POPA */
142 uint8 imul_rri8, imul_rmi8; /* (80186) IMUL immediate 8-bit */
143 uint8 imul_rri16, imul_rmi16; /* (80186) IMUL immediate 16-bit */
144 uint8 enter0, enter1, enter_base, enter_count, leave; /* (80186) ENTER/LEAVE */
145 uint8 bound; /* (80186) BOUND */
149 /* these come from the 8088 timings in OPCODE.LST, but with the
150 penalty for 16-bit memory accesses removed wherever possible */
151 static const struct i80x86_timing timing = {
152 51, 32, /* exception, IRET */
153 2, 0, 4, 2, /* INTs */
154 2, /* segment overrides */
155 2, 4, 4, /* flag operations */
156 4, 4, 83, 60, /* arithmetic adjusts */
157 4, 4, /* decimal adjusts */
158 2, 5, /* sign extension */
159 2, 24, 2, 2, 3, 11, /* misc */
161 15, 15, 15, /* direct JMPs */
162 11, 18, 24, /* indirect JMPs */
163 19, 28, /* direct CALLs */
164 16, 21, 37, /* indirect CALLs */
165 20, 32, 24, 31, /* returns */
166 4, 16, 6, 18, /* conditional JMPs */
167 5, 17, 6, 18, /* loops */
169 10, 14, 8, 12, /* port reads */
170 10, 14, 8, 12, /* port writes */
172 2, 8, 9, /* move, 8-bit */
173 4, 10, /* move, 8-bit immediate */
174 2, 8, 9, /* move, 16-bit */
175 4, 10, /* move, 16-bit immediate */
176 10, 10, 10, 10, /* move, AL/AX memory */
177 2, 8, 2, 9, /* move, segment registers */
178 4, 17, /* exchange, 8-bit */
179 4, 17, 3, /* exchange, 16-bit */
181 15, 24, 14, 14, /* pushes */
182 12, 25, 12, 12, /* pops */
184 3, 9, 16, /* ALU ops, 8-bit */
185 4, 17, 10, /* ALU ops, 8-bit immediate */
186 3, 9, 16, /* ALU ops, 16-bit */
187 4, 17, 10, /* ALU ops, 16-bit immediate */
188 4, 17, 10, /* ALU ops, 16-bit w/8-bit immediate */
189 70, 118, 76, 128, /* MUL */
190 80, 128, 86, 138, /* IMUL */
191 80, 144, 86, 154, /* DIV */
192 101, 165, 107, 175, /* IDIV */
193 3, 2, 15, 15, /* INC/DEC */
194 3, 3, 16, 16, /* NEG/NOT */
196 2, 8, 4, /* reg shift/rotate */
197 15, 20, 4, /* m8 shift/rotate */
198 15, 20, 4, /* m16 shift/rotate */
200 22, 9, 21, /* CMPS 8-bit */
201 22, 9, 21, /* CMPS 16-bit */
202 15, 9, 14, /* SCAS 8-bit */
203 15, 9, 14, /* SCAS 16-bit */
204 12, 9, 11, /* LODS 8-bit */
205 12, 9, 11, /* LODS 16-bit */
206 11, 9, 10, /* STOS 8-bit */
207 11, 9, 10, /* STOS 16-bit */
208 18, 9, 17, /* MOVS 8-bit */
209 18, 9, 17, /* MOVS 16-bit */
212 /* these come from the Intel 80186 datasheet */
213 static const struct i80x86_timing timing = {
214 45, 28, /* exception, IRET */
215 0, 2, 4, 3, /* INTs */
216 2, /* segment overrides */
217 2, 2, 3, /* flag operations */
218 8, 7, 19, 15, /* arithmetic adjusts */
219 4, 4, /* decimal adjusts */
220 2, 4, /* sign extension */
221 2, 18, 6, 2, 6, 11, /* misc */
223 14, 14, 14, /* direct JMPs */
224 11, 17, 26, /* indirect JMPs */
225 15, 23, /* direct CALLs */
226 13, 19, 38, /* indirect CALLs */
227 16, 22, 18, 25, /* returns */
228 4, 13, 5, 15, /* conditional JMPs */
229 6, 16, 6, 16, /* loops */
231 10, 10, 8, 8, /* port reads */
232 9, 9, 7, 7, /* port writes */
234 2, 9, 12, /* move, 8-bit */
235 3, 12, /* move, 8-bit immediate */
236 2, 9, 12, /* move, 16-bit */
237 4, 13, /* move, 16-bit immediate */
238 8, 8, 9, 9, /* move, AL/AX memory */
239 2, 11, 2, 11, /* move, segment registers */
240 4, 17, /* exchange, 8-bit */
241 4, 17, 3, /* exchange, 16-bit */
243 10, 16, 9, 9, /* pushes */
244 10, 20, 8, 8, /* pops */
246 3, 10, 10, /* ALU ops, 8-bit */
247 4, 16, 10, /* ALU ops, 8-bit immediate */
248 3, 10, 10, /* ALU ops, 16-bit */
249 4, 16, 10, /* ALU ops, 16-bit immediate */
250 4, 16, 10, /* ALU ops, 16-bit w/8-bit immediate */
251 26, 35, 32, 41, /* MUL */
252 25, 34, 31, 40, /* IMUL */
253 29, 38, 35, 44, /* DIV */
254 44, 53, 50, 59, /* IDIV */
255 3, 3, 15, 15, /* INC/DEC */
256 3, 3, 10, 10, /* NEG/NOT */
258 2, 5, 1, /* reg shift/rotate */
259 15, 17, 1, /* m8 shift/rotate */
260 15, 17, 1, /* m16 shift/rotate */
262 22, 5, 22, /* CMPS 8-bit */
263 22, 5, 22, /* CMPS 16-bit */
264 15, 5, 15, /* SCAS 8-bit */
265 15, 5, 15, /* SCAS 16-bit */
266 12, 6, 11, /* LODS 8-bit */
267 12, 6, 11, /* LODS 16-bit */
268 10, 6, 9, /* STOS 8-bit */
269 10, 6, 9, /* STOS 16-bit */
270 14, 8, 8, /* MOVS 8-bit */
271 14, 8, 8, /* MOVS 16-bit */
273 14, 8, 8, /* (80186) INS 8-bit */
274 14, 8, 8, /* (80186) INS 16-bit */
275 14, 8, 8, /* (80186) OUTS 8-bit */
276 14, 8, 8, /* (80186) OUTS 16-bit */
277 14, 68, 83, /* (80186) PUSH immediate, PUSHA/POPA */
278 22, 29, /* (80186) IMUL immediate 8-bit */
279 25, 32, /* (80186) IMUL immediate 16-bit */
280 15, 25, 4, 16, 8, /* (80186) ENTER/LEAVE */
281 33, /* (80186) BOUND */
285 /************************************************************************/
287 #define SetTF(x) (TF = (x))
288 #define SetIF(x) (IF = (x))
289 #define SetDF(x) (DirVal = (x) ? -1 : 1)
290 #define SetMD(x) (MF = (x))
292 #define SetOFW_Add(x, y, z) (OverVal = ((x) ^ (y)) & ((x) ^ (z)) & 0x8000)
293 #define SetOFB_Add(x, y, z) (OverVal = ((x) ^ (y)) & ((x) ^ (z)) & 0x80)
294 #define SetOFW_Sub(x, y, z) (OverVal = ((z) ^ (y)) & ((z) ^ (x)) & 0x8000)
295 #define SetOFB_Sub(x, y, z) (OverVal = ((z) ^ (y)) & ((z) ^ (x)) & 0x80)
297 #define SetCFB(x) (CarryVal = (x) & 0x100)
298 #define SetCFW(x) (CarryVal = (x) & 0x10000)
299 #define SetAF(x, y, z) (AuxVal = ((x) ^ ((y) ^ (z))) & 0x10)
300 #define SetSF(x) (SignVal = (x))
301 #define SetZF(x) (ZeroVal = (x))
302 #define SetPF(x) (ParityVal = (x))
304 #define SetSZPF_Byte(x) (ParityVal = SignVal = ZeroVal = (int8)(x))
305 #define SetSZPF_Word(x) (ParityVal = SignVal = ZeroVal = (int16)(x))
307 #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; }
308 #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; }
310 #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; }
311 #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; }
313 #define ORB(dst, src) dst |= (src); CarryVal = OverVal = AuxVal = 0; SetSZPF_Byte(dst)
314 #define ORW(dst, src) dst |= (src); CarryVal = OverVal = AuxVal = 0; SetSZPF_Word(dst)
316 #define ANDB(dst, src) dst &= (src); CarryVal = OverVal = AuxVal = 0; SetSZPF_Byte(dst)
317 #define ANDW(dst, src) dst &= (src); CarryVal = OverVal = AuxVal = 0; SetSZPF_Word(dst)
319 #define XORB(dst, src) dst ^= (src); CarryVal = OverVal = AuxVal = 0; SetSZPF_Byte(dst)
320 #define XORW(dst, src) dst ^= (src); CarryVal = OverVal = AuxVal = 0; SetSZPF_Word(dst)
322 #define CF (CarryVal != 0)
323 #define SF (SignVal < 0)
324 #define ZF (ZeroVal == 0)
325 #define PF parity_table[ParityVal]
326 #define AF (AuxVal != 0)
327 #define OF (OverVal != 0)
328 #define DF (DirVal < 0)
331 /************************************************************************/
333 #define AMASK 0xfffff
335 #define read_mem_byte(a) d_mem->read_data8((a) & AMASK)
336 #define read_mem_word(a) d_mem->read_data16((a) & AMASK)
337 #define write_mem_byte(a, d) d_mem->write_data8((a) & AMASK, (d))
338 #define write_mem_word(a, d) d_mem->write_data16((a) & AMASK, (d))
340 #define read_port_byte(a) d_io->read_io8(a)
341 #define read_port_word(a) d_io->read_io16(a)
342 #define write_port_byte(a, d) d_io->write_io8((a), (d))
343 #define write_port_word(a, d) d_io->write_io16((a), (d))
345 /************************************************************************/
347 #define SegBase(Seg) (sregs[Seg] << 4)
349 #define DefaultSeg(Seg) ((seg_prefix && (Seg == DS || Seg == SS)) ? prefix_seg : Seg)
350 #define DefaultBase(Seg) ((seg_prefix && (Seg == DS || Seg == SS)) ? base[prefix_seg] : base[Seg])
352 #define GetMemB(Seg, Off) (read_mem_byte((DefaultBase(Seg) + (Off)) & AMASK))
353 #define GetMemW(Seg, Off) (read_mem_word((DefaultBase(Seg) + (Off)) & AMASK))
354 #define PutMemB(Seg, Off, x) write_mem_byte((DefaultBase(Seg) + (Off)) & AMASK, (x))
355 #define PutMemW(Seg, Off, x) write_mem_word((DefaultBase(Seg) + (Off)) & AMASK, (x))
357 #define ReadByte(ea) (read_mem_byte((ea) & AMASK))
358 #define ReadWord(ea) (read_mem_word((ea) & AMASK))
359 #define WriteByte(ea, val) write_mem_byte((ea) & AMASK, val);
360 #define WriteWord(ea, val) write_mem_word((ea) & AMASK, val);
362 #define FETCH read_mem_byte(pc++)
363 #define FETCHOP read_mem_byte(pc++)
364 #define FETCHWORD(var) { var = read_mem_word(pc); pc += 2; }
365 #define PUSH(val) { regs.w[SP] -= 2; WriteWord(((base[SS] + regs.w[SP]) & AMASK), val); }
366 #define POP(var) { regs.w[SP] += 2; var = ReadWord(((base[SS] + ((regs.w[SP]-2) & 0xffff)) & AMASK)); }
368 /************************************************************************/
370 #define CompressFlags() (uint16)(CF | (PF << 2) | (AF << 4) | (ZF << 6) | (SF << 7) | (TF << 8) | (IF << 9) | (DF << 10) | (OF << 11) | (MD << 15))
372 #define ExpandFlags(f) { \
373 CarryVal = (f) & 1; \
374 ParityVal = !((f) & 4); \
375 AuxVal = (f) & 0x10; \
376 ZeroVal = !((f) & 0x40); \
377 SignVal = ((f) & 0x80) ? -1 : 0; \
378 TF = ((f) & 0x100) >> 8; \
379 IF = ((f) & 0x200) >> 9; \
380 MF = ((f) & 0x8000) >> 15; \
381 DirVal = ((f) & 0x400) ? -1 : 1; \
382 OverVal = (f) & 0x800; \
385 /************************************************************************/
387 #define RegWord(ModRM) regs.w[Mod_RM.reg.w[ModRM]]
388 #define RegByte(ModRM) regs.b[Mod_RM.reg.b[ModRM]]
390 #define GetRMWord(ModRM) \
391 ((ModRM) >= 0xc0 ? regs.w[Mod_RM.RM.w[ModRM]] : (GetEA(ModRM), ReadWord(ea)))
393 #define PutbackRMWord(ModRM, val) { \
394 if (ModRM >= 0xc0) { \
395 regs.w[Mod_RM.RM.w[ModRM]] = val; \
397 WriteWord(ea, val); \
401 #define GetNextRMWord ( \
405 #define GetRMWordOffset(offs) ( \
406 ReadWord(ea - eo + (uint16)(eo + offs)) \
409 #define GetRMByteOffset(offs) ( \
410 ReadByte(ea - eo + (uint16)(eo + offs)) \
413 #define PutRMWord(ModRM, val) { \
414 if (ModRM >= 0xc0) { \
415 regs.w[Mod_RM.RM.w[ModRM]] = val; \
418 WriteWord(ea, val); \
422 #define PutRMWordOffset(offs, val) \
423 WriteWord(ea - eo + (uint16)(eo + offs), val)
425 #define PutRMByteOffset(offs, val) \
426 WriteByte(ea - eo + (uint16)(eo + offs), val)
428 #define PutImmRMWord(ModRM) { \
430 if (ModRM >= 0xc0) { \
431 FETCHWORD(regs.w[Mod_RM.RM.w[ModRM]]) \
435 WriteWord(ea, val); \
439 #define GetRMByte(ModRM) \
440 ((ModRM) >= 0xc0 ? regs.b[Mod_RM.RM.b[ModRM]] : (GetEA(ModRM), ReadByte(ea)))
442 #define PutRMByte(ModRM, val) { \
443 if (ModRM >= 0xc0) { \
444 regs.b[Mod_RM.RM.b[ModRM]] = val; \
447 WriteByte(ea, val); \
451 #define PutImmRMByte(ModRM) { \
452 if (ModRM >= 0xc0) { \
453 regs.b[Mod_RM.RM.b[ModRM]] = FETCH; \
456 WriteByte(ea, FETCH); \
460 #define PutbackRMByte(ModRM, val) { \
461 if (ModRM >= 0xc0) { \
462 regs.b[Mod_RM.RM.b[ModRM]] = val; \
464 WriteByte(ea, val); \
468 #define DEF_br8(dst, src) \
469 unsigned ModRM = FETCHOP; \
470 unsigned src = RegByte(ModRM); \
471 unsigned dst = GetRMByte(ModRM)
473 #define DEF_wr16(dst, src) \
474 unsigned ModRM = FETCHOP; \
475 unsigned src = RegWord(ModRM); \
476 unsigned dst = GetRMWord(ModRM)
478 #define DEF_r8b(dst, src) \
479 unsigned ModRM = FETCHOP; \
480 unsigned dst = RegByte(ModRM); \
481 unsigned src = GetRMByte(ModRM)
483 #define DEF_r16w(dst, src) \
484 unsigned ModRM = FETCHOP; \
485 unsigned dst = RegWord(ModRM); \
486 unsigned src = GetRMWord(ModRM)
488 #define DEF_ald8(dst, src) \
489 unsigned src = FETCHOP; \
490 unsigned dst = regs.b[AL]
492 #define DEF_axd16(dst, src) \
493 unsigned src = FETCHOP; \
494 unsigned dst = regs.w[AX]; \
497 /************************************************************************/
500 #define INLINE inline
503 #define offs_t UINT32
505 // Disassembler constants
506 const UINT32 DASMFLAG_SUPPORTED = 0x80000000; // are disassembly flags supported?
507 const UINT32 DASMFLAG_STEP_OUT = 0x40000000; // this instruction should be the end of a step out sequence
508 const UINT32 DASMFLAG_STEP_OVER = 0x20000000; // this instruction should be stepped over by setting a breakpoint afterwards
509 const UINT32 DASMFLAG_OVERINSTMASK = 0x18000000; // number of extra instructions to skip when stepping over
510 const UINT32 DASMFLAG_OVERINSTSHIFT = 27; // bits to shift after masking to get the value
511 const UINT32 DASMFLAG_LENGTHMASK = 0x0000ffff; // the low 16-bits contain the actual length
513 /* Highly useful macro for compile-time knowledge of an array size */
514 #define ARRAY_LENGTH(x) (sizeof(x) / sizeof(x[0]))
516 int necv_dasm_one(char *buffer, UINT32 eip, const UINT8 *oprom);
518 void I86::initialize()
520 static const BREGS reg_name[8] = {AL, CL, DL, BL, AH, CH, DH, BH};
522 for(int i = 0; i < 256; i++) {
523 Mod_RM.reg.b[i] = reg_name[(i & 0x38) >> 3];
524 Mod_RM.reg.w[i] = (WREGS)((i & 0x38) >> 3);
526 for(int i = 0xc0; i < 0x100; i++) {
527 Mod_RM.RM.w[i] = (WREGS)(i & 7);
528 Mod_RM.RM.b[i] = (BREGS)reg_name[i & 7];
531 d_mem_stored = d_mem;
533 d_debugger->set_context_mem(d_mem);
534 d_debugger->set_context_io(d_io);
540 for(int i = 0; i < 8; i++) {
544 sregs[SS] = sregs[DS] = sregs[ES] = 0;
546 base[CS] = SegBase(CS);
547 base[SS] = base[DS] = base[ES] = 0;
551 AuxVal = OverVal = SignVal = ZeroVal = CarryVal = 0;
553 ParityVal = TF = IF = MF = 0;
555 icount = extra_icount = 0;
560 pc = 0xffff0 & AMASK;
569 int I86::run(int clock)
571 /* return now if BUSREQ */
573 #ifdef SINGLE_MODE_DMA
578 int passed_icount = max(1, extra_icount);
579 icount = extra_icount = 0;
580 return passed_icount;
585 // run only one opcode
586 icount = -extra_icount;
589 run_one_opecode_debugger();
595 /* run cpu while given clocks */
597 int first_icount = icount;
598 icount -= extra_icount;
601 while(icount > 0 && !busreq) {
603 run_one_opecode_debugger();
608 int passed_icount = first_icount - icount;
609 if(busreq && icount > 0) {
612 return passed_icount;
617 void I86::run_one_opecode_debugger()
619 bool now_debugging = d_debugger->now_debugging;
621 d_debugger->check_break_points(pc);
622 if(d_debugger->now_suspended) {
624 while(d_debugger->now_debugging && d_debugger->now_suspended) {
628 if(d_debugger->now_debugging) {
629 d_mem = d_io = d_debugger;
631 now_debugging = false;
636 if(!d_debugger->now_going) {
637 d_debugger->now_suspended = true;
639 d_mem = d_mem_stored;
648 void I86::run_one_opecode()
652 // ugly patch for PC/JX hardware diagnostics :-(
654 if(pc == 0xff040) pc = 0xff04a;
655 if(pc == 0xff17d) pc = 0xff18f;
658 if(pc == 0xfa909) { regs.b[BH] = read_port_byte(0xa1); pc = 0xfa97c; }
659 if(pc == 0xff6e1) { regs.b[AL] = 0x0d; pc += 2; }
662 instruction(FETCHOP);
663 if(int_state & NMI_REQ_BIT) {
668 int_state &= ~NMI_REQ_BIT;
669 interrupt(NMI_INT_VECTOR);
670 } else if((int_state & INT_REQ_BIT) && IF) {
677 #ifdef SINGLE_MODE_DMA
682 icount -= extra_icount;
686 void I86::write_signal(int id, uint32 data, uint32 mask)
688 if(id == SIG_CPU_NMI) {
690 int_state |= NMI_REQ_BIT;
692 int_state &= ~NMI_REQ_BIT;
694 } else if(id == SIG_CPU_BUSREQ) {
695 busreq = ((data & mask) != 0);
696 } else if(id == SIG_I86_TEST) {
697 test_state = ((data & mask) != 0);
701 void I86::set_intr_line(bool line, bool pending, uint32 bit)
704 int_state |= INT_REQ_BIT;
706 int_state &= ~INT_REQ_BIT;
711 void I86::debug_write_data8(uint32 addr, uint32 data)
714 d_mem_stored->write_data8w(addr, data, &wait);
717 uint32 I86::debug_read_data8(uint32 addr)
720 return d_mem_stored->read_data8w(addr, &wait);
723 void I86::debug_write_data16(uint32 addr, uint32 data)
726 d_mem_stored->write_data16w(addr, data, &wait);
729 uint32 I86::debug_read_data16(uint32 addr)
732 return d_mem_stored->read_data16w(addr, &wait);
735 void I86::debug_write_io8(uint32 addr, uint32 data)
738 d_io_stored->write_io8w(addr, data, &wait);
741 uint32 I86::debug_read_io8(uint32 addr) {
743 return d_io_stored->read_io8w(addr, &wait);
746 void I86::debug_write_io16(uint32 addr, uint32 data)
749 d_io_stored->write_io16w(addr, data, &wait);
752 uint32 I86::debug_read_io16(uint32 addr) {
754 return d_io_stored->read_io16w(addr, &wait);
757 bool I86::debug_write_reg(_TCHAR *reg, uint32 data)
759 if(_tcsicmp(reg, _T("IP")) == 0) {
760 pc = ((data & 0xffff) + base[CS]) & AMASK;
761 } else if(_tcsicmp(reg, _T("AX")) == 0) {
763 } else if(_tcsicmp(reg, _T("BX")) == 0) {
765 } else if(_tcsicmp(reg, _T("CX")) == 0) {
767 } else if(_tcsicmp(reg, _T("DX")) == 0) {
769 } else if(_tcsicmp(reg, _T("SP")) == 0) {
771 } else if(_tcsicmp(reg, _T("BP")) == 0) {
773 } else if(_tcsicmp(reg, _T("SI")) == 0) {
775 } else if(_tcsicmp(reg, _T("DI")) == 0) {
777 } else if(_tcsicmp(reg, _T("AL")) == 0) {
779 } else if(_tcsicmp(reg, _T("AH")) == 0) {
781 } else if(_tcsicmp(reg, _T("BL")) == 0) {
783 } else if(_tcsicmp(reg, _T("BH")) == 0) {
785 } else if(_tcsicmp(reg, _T("CL")) == 0) {
787 } else if(_tcsicmp(reg, _T("CH")) == 0) {
789 } else if(_tcsicmp(reg, _T("DL")) == 0) {
791 } else if(_tcsicmp(reg, _T("DH")) == 0) {
799 void I86::debug_regs_info(_TCHAR *buffer, size_t buffer_len)
801 _stprintf_s(buffer, buffer_len,
802 _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]"),
803 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]),
804 OF ? _T('O') : _T('-'), DF ? _T('D') : _T('-'), IF ? _T('I') : _T('-'), TF ? _T('T') : _T('-'),
805 SF ? _T('S') : _T('-'), ZF ? _T('Z') : _T('-'), AF ? _T('A') : _T('-'), PF ? _T('P') : _T('-'), CF ? _T('C') : _T('-'));
808 int I86::debug_dasm(uint32 pc, _TCHAR *buffer, size_t buffer_len)
810 UINT32 eip = (UINT32)(uint16)(pc - base[CS]);
812 for(int i = 0; i < 16; i++) {
814 ops[i] = d_mem->read_data8w(pc + i, &wait);
816 return necv_dasm_one(buffer, eip, ops) & DASMFLAG_LENGTHMASK;
820 void I86::interrupt(int int_num)
822 unsigned dest_seg, dest_off;
823 uint16 ip = pc - base[CS];
826 int_num = d_pic->intr_ack() & 0xff;
827 int_state &= ~INT_REQ_BIT;
829 dest_off = ReadWord(int_num * 4);
830 dest_seg = ReadWord(int_num * 4 + 2);
836 sregs[CS] = (uint16)dest_seg;
837 base[CS] = SegBase(CS);
838 pc = (base[CS] + dest_off) & AMASK;
839 icount -= timing.exception;
844 instruction(FETCHOP);
848 unsigned I86::GetEA(unsigned ModRM)
851 case 0x00: case 0x08: case 0x10: case 0x18: case 0x20: case 0x28: case 0x30: case 0x38:
852 icount -= 7; eo = (uint16)(regs.w[BX] + regs.w[SI]); ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
853 case 0x01: case 0x09: case 0x11: case 0x19: case 0x21: case 0x29: case 0x31: case 0x39:
854 icount -= 8; eo = (uint16)(regs.w[BX] + regs.w[DI]); ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
855 case 0x02: case 0x0a: case 0x12: case 0x1a: case 0x22: case 0x2a: case 0x32: case 0x3a:
856 icount -= 8; eo = (uint16)(regs.w[BP] + regs.w[SI]); ea_seg = DefaultSeg(SS); ea = DefaultBase(SS) + eo; return ea;
857 case 0x03: case 0x0b: case 0x13: case 0x1b: case 0x23: case 0x2b: case 0x33: case 0x3b:
858 icount -= 7; eo = (uint16)(regs.w[BP] + regs.w[DI]); ea_seg = DefaultSeg(SS); ea = DefaultBase(SS) + eo; return ea;
859 case 0x04: case 0x0c: case 0x14: case 0x1c: case 0x24: case 0x2c: case 0x34: case 0x3c:
860 icount -= 5; eo = regs.w[SI]; ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
861 case 0x05: case 0x0d: case 0x15: case 0x1d: case 0x25: case 0x2d: case 0x35: case 0x3d:
862 icount -= 5; eo = regs.w[DI]; ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
863 case 0x06: case 0x0e: case 0x16: case 0x1e: case 0x26: case 0x2e: case 0x36: case 0x3e:
864 icount -= 6; eo = FETCHOP; eo += FETCHOP << 8; ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
865 case 0x07: case 0x0f: case 0x17: case 0x1f: case 0x27: case 0x2f: case 0x37: case 0x3f:
866 icount -= 5; eo = regs.w[BX]; ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
868 case 0x40: case 0x48: case 0x50: case 0x58: case 0x60: case 0x68: case 0x70: case 0x78:
869 icount -= 11; eo = (uint16)(regs.w[BX] + regs.w[SI] + (int8)FETCHOP); ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
870 case 0x41: case 0x49: case 0x51: case 0x59: case 0x61: case 0x69: case 0x71: case 0x79:
871 icount -= 12; eo = (uint16)(regs.w[BX] + regs.w[DI] + (int8)FETCHOP); ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
872 case 0x42: case 0x4a: case 0x52: case 0x5a: case 0x62: case 0x6a: case 0x72: case 0x7a:
873 icount -= 12; eo = (uint16)(regs.w[BP] + regs.w[SI] + (int8)FETCHOP); ea_seg = DefaultSeg(SS); ea = DefaultBase(SS) + eo; return ea;
874 case 0x43: case 0x4b: case 0x53: case 0x5b: case 0x63: case 0x6b: case 0x73: case 0x7b:
875 icount -= 11; eo = (uint16)(regs.w[BP] + regs.w[DI] + (int8)FETCHOP); ea_seg = DefaultSeg(SS); ea = DefaultBase(SS) + eo; return ea;
876 case 0x44: case 0x4c: case 0x54: case 0x5c: case 0x64: case 0x6c: case 0x74: case 0x7c:
877 icount -= 9; eo = (uint16)(regs.w[SI] + (int8)FETCHOP); ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
878 case 0x45: case 0x4d: case 0x55: case 0x5d: case 0x65: case 0x6d: case 0x75: case 0x7d:
879 icount -= 9; eo = (uint16)(regs.w[DI] + (int8)FETCHOP); ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
880 case 0x46: case 0x4e: case 0x56: case 0x5e: case 0x66: case 0x6e: case 0x76: case 0x7e:
881 icount -= 9; eo = (uint16)(regs.w[BP] + (int8)FETCHOP); ea_seg = DefaultSeg(SS); ea = DefaultBase(SS) + eo; return ea;
882 case 0x47: case 0x4f: case 0x57: case 0x5f: case 0x67: case 0x6f: case 0x77: case 0x7f:
883 icount -= 9; eo = (uint16)(regs.w[BX] + (int8)FETCHOP); ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
885 case 0x80: case 0x88: case 0x90: case 0x98: case 0xa0: case 0xa8: case 0xb0: case 0xb8:
886 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;
887 case 0x81: case 0x89: case 0x91: case 0x99: case 0xa1: case 0xa9: case 0xb1: case 0xb9:
888 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;
889 case 0x82: case 0x8a: case 0x92: case 0x9a: case 0xa2: case 0xaa: case 0xb2: case 0xba:
890 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;
891 case 0x83: case 0x8b: case 0x93: case 0x9b: case 0xa3: case 0xab: case 0xb3: case 0xbb:
892 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;
893 case 0x84: case 0x8c: case 0x94: case 0x9c: case 0xa4: case 0xac: case 0xb4: case 0xbc:
894 icount -= 9; eo = FETCHOP; eo += FETCHOP << 8; eo += regs.w[SI]; ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + (uint16)eo; return ea;
895 case 0x85: case 0x8d: case 0x95: case 0x9d: case 0xa5: case 0xad: case 0xb5: case 0xbd:
896 icount -= 9; eo = FETCHOP; eo += FETCHOP << 8; eo += regs.w[DI]; ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + (uint16)eo; return ea;
897 case 0x86: case 0x8e: case 0x96: case 0x9e: case 0xa6: case 0xae: case 0xb6: case 0xbe:
898 icount -= 9; eo = FETCHOP; eo += FETCHOP << 8; eo += regs.w[BP]; ea_seg = DefaultSeg(SS); ea = DefaultBase(SS) + (uint16)eo; return ea;
899 case 0x87: case 0x8f: case 0x97: case 0x9f: case 0xa7: case 0xaf: case 0xb7: case 0xbf:
900 icount -= 9; eo = FETCHOP; eo += FETCHOP << 8; eo += regs.w[BX]; ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + (uint16)eo; return ea;
905 void I86::rotate_shift_byte(unsigned ModRM, unsigned count)
907 unsigned src = (unsigned)GetRMByte(ModRM);
911 icount -= (ModRM >= 0xc0) ? timing.rot_reg_base : timing.rot_m8_base;
912 } else if(count == 1) {
913 icount -= (ModRM >= 0xc0) ? timing.rot_reg_1 : timing.rot_m8_1;
915 switch((ModRM >> 3) & 7) {
916 case 0: /* ROL eb, 1 */
917 CarryVal = src & 0x80;
918 dst = (src << 1) + CF;
919 PutbackRMByte(ModRM, dst);
920 OverVal = (src ^ dst) & 0x80;
922 case 1: /* ROR eb, 1 */
923 CarryVal = src & 0x01;
924 dst = ((CF << 8) + src) >> 1;
925 PutbackRMByte(ModRM, dst);
926 OverVal = (src ^ dst) & 0x80;
928 case 2: /* RCL eb, 1 */
929 dst = (src << 1) + CF;
930 PutbackRMByte(ModRM, dst);
932 OverVal = (src ^ dst) & 0x80;
934 case 3: /* RCR eb, 1 */
935 dst = ((CF << 8) + src) >> 1;
936 PutbackRMByte(ModRM, dst);
937 CarryVal = src & 0x01;
938 OverVal = (src ^ dst) & 0x80;
940 case 4: /* SHL eb, 1 */
943 PutbackRMByte(ModRM, dst);
945 OverVal = (src ^ dst) & 0x80;
949 case 5: /* SHR eb, 1 */
951 PutbackRMByte(ModRM, dst);
952 CarryVal = src & 0x01;
953 OverVal = src & 0x80;
957 case 7: /* SAR eb, 1 */
958 dst = ((int8)src) >> 1;
959 PutbackRMByte(ModRM, dst);
960 CarryVal = src & 0x01;
965 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
975 icount -= (ModRM >= 0xc0) ? timing.rot_reg_base + timing.rot_reg_bit : timing.rot_m8_base + timing.rot_m8_bit;
977 switch((ModRM >> 3) & 7) {
978 case 0: /* ROL eb, count */
979 for(; count > 0; count--) {
980 CarryVal = dst & 0x80;
981 dst = (dst << 1) + CF;
983 PutbackRMByte(ModRM, (uint8)dst);
985 case 1: /* ROR eb, count */
986 for(; count > 0; count--) {
987 CarryVal = dst & 0x01;
988 dst = (dst >> 1) + (CF << 7);
990 PutbackRMByte(ModRM, (uint8)dst);
992 case 2: /* RCL eb, count */
993 for(; count > 0; count--) {
994 dst = (dst << 1) + CF;
997 PutbackRMByte(ModRM, (uint8)dst);
999 case 3: /* RCR eb, count */
1000 for(; count > 0; count--) {
1001 dst = (CF << 8) + dst;
1002 CarryVal = dst & 0x01;
1005 PutbackRMByte(ModRM, (uint8)dst);
1007 case 4: /* SHL eb, count */
1013 PutbackRMByte(ModRM, (uint8)dst);
1015 case 5: /* SHR eb, count */
1017 CarryVal = dst & 0x01;
1021 PutbackRMByte(ModRM, (uint8)dst);
1023 case 7: /* SAR eb, count */
1024 dst = ((int8)dst) >> (count - 1);
1025 CarryVal = dst & 0x01;
1026 dst = ((int8)((uint8)dst)) >> 1;
1029 PutbackRMByte(ModRM, (uint8)dst);
1031 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
1043 void I86::rotate_shift_word(unsigned ModRM, unsigned count)
1045 unsigned src = GetRMWord(ModRM);
1049 icount -= (ModRM >= 0xc0) ? timing.rot_reg_base : timing.rot_m16_base;
1050 } else if(count == 1) {
1051 icount -= (ModRM >= 0xc0) ? timing.rot_reg_1 : timing.rot_m16_1;
1053 switch((ModRM >> 3) & 7) {
1054 case 0: /* ROL ew, 1 */
1055 CarryVal = src & 0x8000;
1056 dst = (src << 1) + CF;
1057 PutbackRMWord(ModRM, dst);
1058 OverVal = (src ^ dst) & 0x8000;
1060 case 1: /* ROR ew, 1 */
1061 CarryVal = src & 0x01;
1062 dst = ((CF << 16) + src) >> 1;
1063 PutbackRMWord(ModRM, dst);
1064 OverVal = (src ^ dst) & 0x8000;
1066 case 2: /* RCL ew, 1 */
1067 dst = (src << 1) + CF;
1068 PutbackRMWord(ModRM, dst);
1070 OverVal = (src ^ dst) & 0x8000;
1072 case 3: /* RCR ew, 1 */
1073 dst = ((CF << 16) + src) >> 1;
1074 PutbackRMWord(ModRM, dst);
1075 CarryVal = src & 0x01;
1076 OverVal = (src ^ dst) & 0x8000;
1078 case 4: /* SHL ew, 1 */
1081 PutbackRMWord(ModRM, dst);
1083 OverVal = (src ^ dst) & 0x8000;
1087 case 5: /* SHR ew, 1 */
1089 PutbackRMWord(ModRM, dst);
1090 CarryVal = src & 0x01;
1091 OverVal = src & 0x8000;
1095 case 7: /* SAR ew, 1 */
1096 dst = ((int16)src) >> 1;
1097 PutbackRMWord(ModRM, dst);
1098 CarryVal = src & 0x01;
1103 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
1113 icount -= (ModRM >= 0xc0) ? timing.rot_reg_base + timing.rot_reg_bit : timing.rot_m8_base + timing.rot_m16_bit;
1115 switch((ModRM >> 3) & 7) {
1116 case 0: /* ROL ew, count */
1117 for(; count > 0; count--) {
1118 CarryVal = dst & 0x8000;
1119 dst = (dst << 1) + CF;
1121 PutbackRMWord(ModRM, dst);
1123 case 1: /* ROR ew, count */
1124 for(; count > 0; count--) {
1125 CarryVal = dst & 0x01;
1126 dst = (dst >> 1) + (CF << 15);
1128 PutbackRMWord(ModRM, dst);
1130 case 2: /* RCL ew, count */
1131 for(; count > 0; count--) {
1132 dst = (dst << 1) + CF;
1135 PutbackRMWord(ModRM, dst);
1137 case 3: /* RCR ew, count */
1138 for(; count > 0; count--) {
1139 dst = dst + (CF << 16);
1140 CarryVal = dst & 0x01;
1143 PutbackRMWord(ModRM, dst);
1145 case 4: /* SHL ew, count */
1151 PutbackRMWord(ModRM, dst);
1153 case 5: /* SHR ew, count */
1155 CarryVal = dst & 0x01;
1159 PutbackRMWord(ModRM, dst);
1161 case 7: /* SAR ew, count */
1162 dst = ((int16)dst) >> (count - 1);
1163 CarryVal = dst & 0x01;
1164 dst = ((int16)((uint16)dst)) >> 1;
1167 PutbackRMWord(ModRM, dst);
1176 void I86::instruction(uint8 code)
1181 case 0x00: _add_br8(); break;
1182 case 0x01: _add_wr16(); break;
1183 case 0x02: _add_r8b(); break;
1184 case 0x03: _add_r16w(); break;
1185 case 0x04: _add_ald8(); break;
1186 case 0x05: _add_axd16(); break;
1187 case 0x06: _push_es(); break;
1188 case 0x07: _pop_es(); break;
1189 case 0x08: _or_br8(); break;
1190 case 0x09: _or_wr16(); break;
1191 case 0x0a: _or_r8b(); break;
1192 case 0x0b: _or_r16w(); break;
1193 case 0x0c: _or_ald8(); break;
1194 case 0x0d: _or_axd16(); break;
1195 case 0x0e: _push_cs(); break;
1196 #if defined(HAS_V30)
1197 case 0x0f: _0fpre(); break;
1199 case 0x0f: _invalid(); break;
1201 case 0x10: _adc_br8(); break;
1202 case 0x11: _adc_wr16(); break;
1203 case 0x12: _adc_r8b(); break;
1204 case 0x13: _adc_r16w(); break;
1205 case 0x14: _adc_ald8(); break;
1206 case 0x15: _adc_axd16(); break;
1207 case 0x16: _push_ss(); break;
1208 case 0x17: _pop_ss(); break;
1209 case 0x18: _sbb_br8(); break;
1210 case 0x19: _sbb_wr16(); break;
1211 case 0x1a: _sbb_r8b(); break;
1212 case 0x1b: _sbb_r16w(); break;
1213 case 0x1c: _sbb_ald8(); break;
1214 case 0x1d: _sbb_axd16(); break;
1215 case 0x1e: _push_ds(); break;
1216 case 0x1f: _pop_ds(); break;
1217 case 0x20: _and_br8(); break;
1218 case 0x21: _and_wr16(); break;
1219 case 0x22: _and_r8b(); break;
1220 case 0x23: _and_r16w(); break;
1221 case 0x24: _and_ald8(); break;
1222 case 0x25: _and_axd16(); break;
1223 case 0x26: _es(); break;
1224 case 0x27: _daa(); break;
1225 case 0x28: _sub_br8(); break;
1226 case 0x29: _sub_wr16(); break;
1227 case 0x2a: _sub_r8b(); break;
1228 case 0x2b: _sub_r16w(); break;
1229 case 0x2c: _sub_ald8(); break;
1230 case 0x2d: _sub_axd16(); break;
1231 case 0x2e: _cs(); break;
1232 case 0x2f: _das(); break;
1233 case 0x30: _xor_br8(); break;
1234 case 0x31: _xor_wr16(); break;
1235 case 0x32: _xor_r8b(); break;
1236 case 0x33: _xor_r16w(); break;
1237 case 0x34: _xor_ald8(); break;
1238 case 0x35: _xor_axd16(); break;
1239 case 0x36: _ss(); break;
1240 case 0x37: _aaa(); break;
1241 case 0x38: _cmp_br8(); break;
1242 case 0x39: _cmp_wr16(); break;
1243 case 0x3a: _cmp_r8b(); break;
1244 case 0x3b: _cmp_r16w(); break;
1245 case 0x3c: _cmp_ald8(); break;
1246 case 0x3d: _cmp_axd16(); break;
1247 case 0x3e: _ds(); break;
1248 case 0x3f: _aas(); break;
1249 case 0x40: _inc_ax(); break;
1250 case 0x41: _inc_cx(); break;
1251 case 0x42: _inc_dx(); break;
1252 case 0x43: _inc_bx(); break;
1253 case 0x44: _inc_sp(); break;
1254 case 0x45: _inc_bp(); break;
1255 case 0x46: _inc_si(); break;
1256 case 0x47: _inc_di(); break;
1257 case 0x48: _dec_ax(); break;
1258 case 0x49: _dec_cx(); break;
1259 case 0x4a: _dec_dx(); break;
1260 case 0x4b: _dec_bx(); break;
1261 case 0x4c: _dec_sp(); break;
1262 case 0x4d: _dec_bp(); break;
1263 case 0x4e: _dec_si(); break;
1264 case 0x4f: _dec_di(); break;
1265 case 0x50: _push_ax(); break;
1266 case 0x51: _push_cx(); break;
1267 case 0x52: _push_dx(); break;
1268 case 0x53: _push_bx(); break;
1269 case 0x54: _push_sp(); break;
1270 case 0x55: _push_bp(); break;
1271 case 0x56: _push_si(); break;
1272 case 0x57: _push_di(); break;
1273 case 0x58: _pop_ax(); break;
1274 case 0x59: _pop_cx(); break;
1275 case 0x5a: _pop_dx(); break;
1276 case 0x5b: _pop_bx(); break;
1277 case 0x5c: _pop_sp(); break;
1278 case 0x5d: _pop_bp(); break;
1279 case 0x5e: _pop_si(); break;
1280 case 0x5f: _pop_di(); break;
1281 #if defined(HAS_V30)
1282 case 0x60: _pusha(); break;
1283 case 0x61: _popa(); break;
1284 case 0x62: _bound(); break;
1286 case 0x60: _invalid(); break;
1287 case 0x61: _invalid(); break;
1288 case 0x62: _invalid(); break;
1290 case 0x63: _invalid(); break;
1291 #if defined(HAS_V30)
1292 case 0x64: _repc(0); break;
1293 case 0x65: _repc(1); break;
1295 case 0x64: _invalid(); break;
1296 case 0x65: _invalid(); break;
1298 case 0x66: _invalid(); break;
1299 case 0x67: _invalid(); break;
1300 #if defined(HAS_V30)
1301 case 0x68: _push_d16(); break;
1302 case 0x69: _imul_d16(); break;
1303 case 0x6a: _push_d8(); break;
1304 case 0x6b: _imul_d8(); break;
1305 case 0x6c: _insb(); break;
1306 case 0x6d: _insw(); break;
1307 case 0x6e: _outsb(); break;
1308 case 0x6f: _outsw(); break;
1310 case 0x68: _invalid(); break;
1311 case 0x69: _invalid(); break;
1312 case 0x6a: _invalid(); break;
1313 case 0x6b: _invalid(); break;
1314 case 0x6c: _invalid(); break;
1315 case 0x6d: _invalid(); break;
1316 case 0x6e: _invalid(); break;
1317 case 0x6f: _invalid(); break;
1319 case 0x70: _jo(); break;
1320 case 0x71: _jno(); break;
1321 case 0x72: _jb(); break;
1322 case 0x73: _jnb(); break;
1323 case 0x74: _jz(); break;
1324 case 0x75: _jnz(); break;
1325 case 0x76: _jbe(); break;
1326 case 0x77: _jnbe(); break;
1327 case 0x78: _js(); break;
1328 case 0x79: _jns(); break;
1329 case 0x7a: _jp(); break;
1330 case 0x7b: _jnp(); break;
1331 case 0x7c: _jl(); break;
1332 case 0x7d: _jnl(); break;
1333 case 0x7e: _jle(); break;
1334 case 0x7f: _jnle(); break;
1335 case 0x80: _80pre(); break;
1336 case 0x81: _81pre(); break;
1337 case 0x82: _82pre(); break;
1338 case 0x83: _83pre(); break;
1339 case 0x84: _test_br8(); break;
1340 case 0x85: _test_wr16(); break;
1341 case 0x86: _xchg_br8(); break;
1342 case 0x87: _xchg_wr16(); break;
1343 case 0x88: _mov_br8(); break;
1344 case 0x89: _mov_wr16(); break;
1345 case 0x8a: _mov_r8b(); break;
1346 case 0x8b: _mov_r16w(); break;
1347 case 0x8c: _mov_wsreg(); break;
1348 case 0x8d: _lea(); break;
1349 case 0x8e: _mov_sregw(); break;
1350 case 0x8f: _popw(); break;
1351 case 0x90: _nop(); break;
1352 case 0x91: _xchg_axcx(); break;
1353 case 0x92: _xchg_axdx(); break;
1354 case 0x93: _xchg_axbx(); break;
1355 case 0x94: _xchg_axsp(); break;
1356 case 0x95: _xchg_axbp(); break;
1357 case 0x96: _xchg_axsi(); break;
1358 case 0x97: _xchg_axdi(); break;
1359 case 0x98: _cbw(); break;
1360 case 0x99: _cwd(); break;
1361 case 0x9a: _call_far(); break;
1362 case 0x9b: _wait(); break;
1363 case 0x9c: _pushf(); break;
1364 case 0x9d: _popf(); break;
1365 case 0x9e: _sahf(); break;
1366 case 0x9f: _lahf(); break;
1367 case 0xa0: _mov_aldisp(); break;
1368 case 0xa1: _mov_axdisp(); break;
1369 case 0xa2: _mov_dispal(); break;
1370 case 0xa3: _mov_dispax(); break;
1371 case 0xa4: _movsb(); break;
1372 case 0xa5: _movsw(); break;
1373 case 0xa6: _cmpsb(); break;
1374 case 0xa7: _cmpsw(); break;
1375 case 0xa8: _test_ald8(); break;
1376 case 0xa9: _test_axd16(); break;
1377 case 0xaa: _stosb(); break;
1378 case 0xab: _stosw(); break;
1379 case 0xac: _lodsb(); break;
1380 case 0xad: _lodsw(); break;
1381 case 0xae: _scasb(); break;
1382 case 0xaf: _scasw(); break;
1383 case 0xb0: _mov_ald8(); break;
1384 case 0xb1: _mov_cld8(); break;
1385 case 0xb2: _mov_dld8(); break;
1386 case 0xb3: _mov_bld8(); break;
1387 case 0xb4: _mov_ahd8(); break;
1388 case 0xb5: _mov_chd8(); break;
1389 case 0xb6: _mov_dhd8(); break;
1390 case 0xb7: _mov_bhd8(); break;
1391 case 0xb8: _mov_axd16(); break;
1392 case 0xb9: _mov_cxd16(); break;
1393 case 0xba: _mov_dxd16(); break;
1394 case 0xbb: _mov_bxd16(); break;
1395 case 0xbc: _mov_spd16(); break;
1396 case 0xbd: _mov_bpd16(); break;
1397 case 0xbe: _mov_sid16(); break;
1398 case 0xbf: _mov_did16(); break;
1399 #if defined(HAS_V30)
1400 case 0xc0: _rotshft_bd8(); break;
1401 case 0xc1: _rotshft_wd8(); break;
1403 case 0xc0: _invalid(); break;
1404 case 0xc1: _invalid(); break;
1406 case 0xc2: _ret_d16(); break;
1407 case 0xc3: _ret(); break;
1408 case 0xc4: _les_dw(); break;
1409 case 0xc5: _lds_dw(); break;
1410 case 0xc6: _mov_bd8(); break;
1411 case 0xc7: _mov_wd16(); break;
1412 #if defined(HAS_V30)
1413 case 0xc8: _enter(); break;
1414 case 0xc9: _leav(); break; /* _leave() */
1416 case 0xc8: _invalid(); break;
1417 case 0xc9: _invalid(); break;
1419 case 0xca: _retf_d16(); break;
1420 case 0xcb: _retf(); break;
1421 case 0xcc: _int3(); break;
1422 case 0xcd: _int(); break;
1423 case 0xce: _into(); break;
1424 case 0xcf: _iret(); break;
1425 case 0xd0: _rotshft_b(); break;
1426 case 0xd1: _rotshft_w(); break;
1427 case 0xd2: _rotshft_bcl(); break;
1428 case 0xd3: _rotshft_wcl(); break;
1429 case 0xd4: _aam(); break;
1430 case 0xd5: _aad(); break;
1431 #if defined(HAS_V30)
1432 case 0xd6: _setalc(); break;
1434 case 0xd6: _invalid(); break;
1436 case 0xd7: _xlat(); break;
1437 case 0xd8: _escape(); break;
1438 case 0xd9: _escape(); break;
1439 case 0xda: _escape(); break;
1440 case 0xdb: _escape(); break;
1441 case 0xdc: _escape(); break;
1442 case 0xdd: _escape(); break;
1443 case 0xde: _escape(); break;
1444 case 0xdf: _escape(); break;
1445 case 0xe0: _loopne(); break;
1446 case 0xe1: _loope(); break;
1447 case 0xe2: _loop(); break;
1448 case 0xe3: _jcxz(); break;
1449 case 0xe4: _inal(); break;
1450 case 0xe5: _inax(); break;
1451 case 0xe6: _outal(); break;
1452 case 0xe7: _outax(); break;
1453 case 0xe8: _call_d16(); break;
1454 case 0xe9: _jmp_d16(); break;
1455 case 0xea: _jmp_far(); break;
1456 case 0xeb: _jmp_d8(); break;
1457 case 0xec: _inaldx(); break;
1458 case 0xed: _inaxdx(); break;
1459 case 0xee: _outdxal(); break;
1460 case 0xef: _outdxax(); break;
1461 case 0xf0: _lock(); break;
1462 case 0xf1: _invalid(); break;
1463 case 0xf2: _repne(); break;
1464 case 0xf3: _repe(); break;
1465 case 0xf4: _hlt(); break;
1466 case 0xf5: _cmc(); break;
1467 case 0xf6: _f6pre(); break;
1468 case 0xf7: _f7pre(); break;
1469 case 0xf8: _clc(); break;
1470 case 0xf9: _stc(); break;
1471 case 0xfa: _cli(); break;
1472 case 0xfb: _sti(); break;
1473 case 0xfc: _cld(); break;
1474 case 0xfd: _std(); break;
1475 case 0xfe: _fepre(); break;
1476 case 0xff: _ffpre(); break;
1477 default: _add_br8(); break;
1478 //default: __assume(0);
1482 inline void I86::_add_br8() /* Opcode 0x00 */
1485 icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
1487 PutbackRMByte(ModRM, dst);
1490 inline void I86::_add_wr16() /* Opcode 0x01 */
1493 icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
1495 PutbackRMWord(ModRM, dst);
1498 inline void I86::_add_r8b() /* Opcode 0x02 */
1501 icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
1503 RegByte(ModRM) = dst;
1506 inline void I86::_add_r16w() /* Opcode 0x03 */
1509 icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
1511 RegWord(ModRM) = dst;
1514 inline void I86::_add_ald8() /* Opcode 0x04 */
1517 icount -= timing.alu_ri8;
1522 inline void I86::_add_axd16() /* Opcode 0x05 */
1524 DEF_axd16(dst, src);
1525 icount -= timing.alu_ri16;
1530 inline void I86::_push_es() /* Opcode 0x06 */
1532 icount -= timing.push_seg;
1536 inline void I86::_pop_es() /* Opcode 0x07 */
1539 base[ES] = SegBase(ES);
1540 icount -= timing.pop_seg;
1543 inline void I86::_or_br8() /* Opcode 0x08 */
1546 icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
1548 PutbackRMByte(ModRM, dst);
1551 inline void I86::_or_wr16() /* Opcode 0x09 */
1554 icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
1556 PutbackRMWord(ModRM, dst);
1559 inline void I86::_or_r8b() /* Opcode 0x0a */
1562 icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
1564 RegByte(ModRM) = dst;
1567 inline void I86::_or_r16w() /* Opcode 0x0b */
1570 icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
1572 RegWord(ModRM) = dst;
1575 inline void I86::_or_ald8() /* Opcode 0x0c */
1578 icount -= timing.alu_ri8;
1583 inline void I86::_or_axd16() /* Opcode 0x0d */
1585 DEF_axd16(dst, src);
1586 icount -= timing.alu_ri16;
1591 inline void I86::_push_cs() /* Opcode 0x0e */
1593 icount -= timing.push_seg;
1597 #if defined(HAS_V30)
1598 inline void I86::_0fpre() /* Opcode 0x0f */
1600 static const uint16 bytes[] = {
1601 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768
1603 unsigned code = FETCH;
1609 case 0x10: /* 0F 10 47 30 - TEST1 [bx+30h], cl */
1612 tmp = regs.b[Mod_RM.RM.b[ModRM]];
1620 tmp2 = regs.b[CL] & 7;
1621 SetZF(tmp & bytes[tmp2]);
1623 case 0x11: /* 0F 11 47 30 - TEST1 [bx+30h], cl */
1626 tmp = regs.w[Mod_RM.RM.w[ModRM]];
1634 tmp2 = regs.b[CL] & 0xf;
1635 SetZF(tmp & bytes[tmp2]);
1637 case 0x12: /* 0F 12 [mod:000:r/m] - CLR1 reg/m8, cl */
1640 tmp = regs.b[Mod_RM.RM.b[ModRM]];
1648 tmp2 = regs.b[CL] & 7;
1649 tmp &= ~bytes[tmp2];
1650 PutbackRMByte(ModRM, tmp);
1652 case 0x13: /* 0F 13 [mod:000:r/m] - CLR1 reg/m16, cl */
1655 tmp = regs.w[Mod_RM.RM.w[ModRM]];
1663 tmp2 = regs.b[CL] & 0xf;
1664 tmp &= ~bytes[tmp2];
1665 PutbackRMWord(ModRM, tmp);
1667 case 0x14: /* 0F 14 47 30 - SET1 [bx+30h], cl */
1670 tmp = regs.b[Mod_RM.RM.b[ModRM]];
1678 tmp2 = regs.b[CL] & 7;
1680 PutbackRMByte(ModRM, tmp);
1682 case 0x15: /* 0F 15 C6 - SET1 si, cl */
1685 tmp = regs.w[Mod_RM.RM.w[ModRM]];
1693 tmp2 = regs.b[CL] & 0xf;
1695 PutbackRMWord(ModRM, tmp);
1697 case 0x16: /* 0F 16 C6 - NOT1 si, cl */
1700 tmp = regs.b[Mod_RM.RM.b[ModRM]];
1708 tmp2 = regs.b[CL] & 7;
1709 if(tmp & bytes[tmp2]) {
1710 tmp &= ~bytes[tmp2];
1714 PutbackRMByte(ModRM, tmp);
1716 case 0x17: /* 0F 17 C6 - NOT1 si, cl */
1719 tmp = regs.w[Mod_RM.RM.w[ModRM]];
1727 tmp2 = regs.b[CL] & 0xf;
1728 if(tmp & bytes[tmp2]) {
1729 tmp &= ~bytes[tmp2];
1733 PutbackRMWord(ModRM, tmp);
1735 case 0x18: /* 0F 18 XX - TEST1 [bx+30h], 07 */
1738 tmp = regs.b[Mod_RM.RM.b[ModRM]];
1748 SetZF(tmp & bytes[tmp2]);
1750 case 0x19: /* 0F 19 XX - TEST1 [bx+30h], 07 */
1753 tmp = regs.w[Mod_RM.RM.w[ModRM]];
1763 SetZF(tmp & bytes[tmp2]);
1765 case 0x1a: /* 0F 1A 06 - CLR1 si, cl */
1768 tmp = regs.b[Mod_RM.RM.b[ModRM]];
1778 tmp &= ~bytes[tmp2];
1779 PutbackRMByte(ModRM, tmp);
1781 case 0x1B: /* 0F 1B 06 - CLR1 si, cl */
1784 tmp = regs.w[Mod_RM.RM.w[ModRM]];
1794 tmp &= ~bytes[tmp2];
1795 PutbackRMWord(ModRM, tmp);
1797 case 0x1C: /* 0F 1C 47 30 - SET1 [bx+30h], cl */
1800 tmp = regs.b[Mod_RM.RM.b[ModRM]];
1811 PutbackRMByte(ModRM, tmp);
1813 case 0x1D: /* 0F 1D C6 - SET1 si, cl */
1816 tmp = regs.w[Mod_RM.RM.w[ModRM]];
1827 PutbackRMWord(ModRM, tmp);
1829 case 0x1e: /* 0F 1e C6 - NOT1 si, 07 */
1832 tmp = regs.b[Mod_RM.RM.b[ModRM]];
1842 if(tmp & bytes[tmp2]) {
1843 tmp &= ~bytes[tmp2];
1847 PutbackRMByte(ModRM, tmp);
1849 case 0x1f: /* 0F 1f C6 - NOT1 si, 07 */
1852 tmp = regs.w[Mod_RM.RM.w[ModRM]];
1862 if(tmp & bytes[tmp2]) {
1863 tmp &= ~bytes[tmp2];
1867 PutbackRMWord(ModRM, tmp);
1869 case 0x20: /* 0F 20 59 - add4s */
1871 /* length in words ! */
1872 int count = (regs.b[CL] + 1) / 2;
1873 unsigned di = regs.w[DI];
1874 unsigned si = regs.w[SI];
1877 CarryVal = 0; /* NOT ADC */
1878 for(int i = 0; i < count; i++) {
1879 tmp = GetMemB(DS, si);
1880 tmp2 = GetMemB(ES, di);
1881 int v1 = (tmp >> 4) * 10 + (tmp & 0xf);
1882 int v2 = (tmp2 >> 4) * 10 + (tmp2 & 0xf);
1883 int result = v1 + v2 + CarryVal;
1884 CarryVal = result > 99 ? 1 : 0;
1885 result = result % 100;
1886 v1 = ((result / 10) << 4) | (result % 10);
1887 PutMemB(ES, di, v1);
1895 icount -= 7 + 19 * count;
1898 case 0x22: /* 0F 22 59 - sub4s */
1900 int count = (regs.b[CL] + 1) / 2;
1901 unsigned di = regs.w[DI];
1902 unsigned si = regs.w[SI];
1905 CarryVal = 0; /* NOT ADC */
1906 for(int i = 0; i < count; i++) {
1907 tmp = GetMemB(ES, di);
1908 tmp2 = GetMemB(DS, si);
1909 int v1 = (tmp >> 4) * 10 + (tmp & 0xf);
1910 int v2 = (tmp2 >> 4) * 10 + (tmp2 & 0xf), result;
1911 if(v1 < (v2 + CarryVal)) {
1913 result = v1 - (v2 + CarryVal);
1916 result = v1 - (v2 + CarryVal);
1919 v1 = ((result / 10) << 4) | (result % 10);
1920 PutMemB(ES, di, v1);
1928 icount -= 7 + 19 * count;
1934 case 0x26: /* 0F 22 59 - cmp4s */
1936 int count = (regs.b[CL] + 1) / 2;
1937 unsigned di = regs.w[DI];
1938 unsigned si = regs.w[SI];
1941 CarryVal = 0; /* NOT ADC */
1942 for(int i = 0; i < count; i++) {
1943 tmp = GetMemB(ES, di);
1944 tmp2 = GetMemB(DS, si);
1945 int v1 = (tmp >> 4) * 10 + (tmp & 0xf);
1946 int v2 = (tmp2 >> 4) * 10 + (tmp2 & 0xf), result;
1947 if(v1 < (v2 + CarryVal)) {
1949 result = v1 - (v2 + CarryVal);
1952 result = v1 - (v2 + CarryVal);
1955 v1 = ((result / 10) << 4) | (result % 10);
1956 /* PutMemB(ES, di, v1); /* no store, only compare */
1964 icount -= 7 + 19 * (regs.b[CL] + 1);
1967 case 0x28: /* 0F 28 C7 - ROL4 bh */
1970 tmp = regs.b[Mod_RM.RM.b[ModRM]];
1979 tmp |= regs.b[AL] & 0xf;
1980 regs.b[AL] = (regs.b[AL] & 0xf0) | ((tmp >> 8) & 0xf);
1982 PutbackRMByte(ModRM, tmp);
1984 case 0x29: /* 0F 29 C7 - ROL4 bx */
1987 case 0x2A: /* 0F 2a c2 - ROR4 bh */
1990 tmp = regs.b[Mod_RM.RM.b[ModRM]];
1998 tmp2 = (regs.b[AL] & 0xf) << 4;
1999 regs.b[AL] = (regs.b[AL] & 0xf0) | (tmp & 0xf);
2000 tmp = tmp2 | (tmp >> 4);
2001 PutbackRMByte(ModRM, tmp);
2003 case 0x2B: /* 0F 2b c2 - ROR4 bx */
2006 case 0x2D: /* 0Fh 2Dh < 1111 1RRR> */
2010 case 0x31: /* 0F 31 [mod:reg:r/m] - INS reg8, reg8 or INS reg8, imm4 */
2013 tmp = regs.b[Mod_RM.RM.b[ModRM]];
2022 case 0x33: /* 0F 33 [mod:reg:r/m] - EXT reg8, reg8 or EXT reg8, imm4 */
2025 tmp = regs.b[Mod_RM.RM.b[ModRM]];
2056 case 0xff: /* 0F ff imm8 - BRKEM */
2065 inline void I86::_adc_br8() /* Opcode 0x10 */
2068 icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
2071 PutbackRMByte(ModRM, dst);
2074 inline void I86::_adc_wr16() /* Opcode 0x11 */
2077 icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
2080 PutbackRMWord(ModRM, dst);
2083 inline void I86::_adc_r8b() /* Opcode 0x12 */
2086 icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
2089 RegByte(ModRM) = dst;
2092 inline void I86::_adc_r16w() /* Opcode 0x13 */
2095 icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
2098 RegWord(ModRM) = dst;
2101 inline void I86::_adc_ald8() /* Opcode 0x14 */
2104 icount -= timing.alu_ri8;
2110 inline void I86::_adc_axd16() /* Opcode 0x15 */
2112 DEF_axd16(dst, src);
2113 icount -= timing.alu_ri16;
2119 inline void I86::_push_ss() /* Opcode 0x16 */
2122 icount -= timing.push_seg;
2125 inline void I86::_pop_ss() /* Opcode 0x17 */
2128 base[SS] = SegBase(SS);
2129 icount -= timing.pop_seg;
2130 instruction(FETCHOP); /* no interrupt before next instruction */
2133 inline void I86::_sbb_br8() /* Opcode 0x18 */
2136 icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
2139 PutbackRMByte(ModRM, dst);
2142 inline void I86::_sbb_wr16() /* Opcode 0x19 */
2145 icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
2148 PutbackRMWord(ModRM, dst);
2151 inline void I86::_sbb_r8b() /* Opcode 0x1a */
2154 icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
2157 RegByte(ModRM) = dst;
2160 inline void I86::_sbb_r16w() /* Opcode 0x1b */
2163 icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
2166 RegWord(ModRM) = dst;
2169 inline void I86::_sbb_ald8() /* Opcode 0x1c */
2172 icount -= timing.alu_ri8;
2178 inline void I86::_sbb_axd16() /* Opcode 0x1d */
2180 DEF_axd16(dst, src);
2181 icount -= timing.alu_ri16;
2187 inline void I86::_push_ds() /* Opcode 0x1e */
2190 icount -= timing.push_seg;
2193 inline void I86::_pop_ds() /* Opcode 0x1f */
2196 base[DS] = SegBase(DS);
2197 icount -= timing.push_seg;
2200 inline void I86::_and_br8() /* Opcode 0x20 */
2203 icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
2205 PutbackRMByte(ModRM, dst);
2208 inline void I86::_and_wr16() /* Opcode 0x21 */
2211 icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
2213 PutbackRMWord(ModRM, dst);
2216 inline void I86::_and_r8b() /* Opcode 0x22 */
2219 icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
2221 RegByte(ModRM) = dst;
2224 inline void I86::_and_r16w() /* Opcode 0x23 */
2227 icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
2229 RegWord(ModRM) = dst;
2232 inline void I86::_and_ald8() /* Opcode 0x24 */
2235 icount -= timing.alu_ri8;
2240 inline void I86::_and_axd16() /* Opcode 0x25 */
2242 DEF_axd16(dst, src);
2243 icount -= timing.alu_ri16;
2248 inline void I86::_es() /* Opcode 0x26 */
2252 icount -= timing.override;
2253 instruction(FETCHOP);
2256 inline void I86::_daa() /* Opcode 0x27 */
2258 if(AF || ((regs.b[AL] & 0xf) > 9)) {
2260 regs.b[AL] = tmp = regs.b[AL] + 6;
2262 CarryVal |= tmp & 0x100;
2265 if(CF || (regs.b[AL] > 0x9f)) {
2270 SetSZPF_Byte(regs.b[AL]);
2271 icount -= timing.daa;
2274 inline void I86::_sub_br8() /* Opcode 0x28 */
2277 icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
2279 PutbackRMByte(ModRM, dst);
2282 inline void I86::_sub_wr16() /* Opcode 0x29 */
2285 icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
2287 PutbackRMWord(ModRM, dst);
2290 inline void I86::_sub_r8b() /* Opcode 0x2a */
2293 icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
2295 RegByte(ModRM) = dst;
2298 inline void I86::_sub_r16w() /* Opcode 0x2b */
2301 icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
2303 RegWord(ModRM) = dst;
2306 inline void I86::_sub_ald8() /* Opcode 0x2c */
2309 icount -= timing.alu_ri8;
2314 inline void I86::_sub_axd16() /* Opcode 0x2d */
2316 DEF_axd16(dst, src);
2317 icount -= timing.alu_ri16;
2322 inline void I86::_cs() /* Opcode 0x2e */
2326 icount -= timing.override;
2327 instruction(FETCHOP);
2330 inline void I86::_das() /* Opcode 0x2f */
2332 uint8 tmpAL = regs.b[AL];
2333 if(AF || ((regs.b[AL] & 0xf) > 9)) {
2335 regs.b[AL] = tmp = regs.b[AL] - 6;
2337 CarryVal |= tmp & 0x100;
2340 if(CF || (tmpAL > 0x9f)) {
2345 SetSZPF_Byte(regs.b[AL]);
2346 icount -= timing.das;
2349 inline void I86::_xor_br8() /* Opcode 0x30 */
2352 icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
2354 PutbackRMByte(ModRM, dst);
2357 inline void I86::_xor_wr16() /* Opcode 0x31 */
2360 icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
2362 PutbackRMWord(ModRM, dst);
2365 inline void I86::_xor_r8b() /* Opcode 0x32 */
2368 icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
2370 RegByte(ModRM) = dst;
2373 inline void I86::_xor_r16w() /* Opcode 0x33 */
2376 icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
2378 RegWord(ModRM) = dst;
2381 inline void I86::_xor_ald8() /* Opcode 0x34 */
2384 icount -= timing.alu_ri8;
2389 inline void I86::_xor_axd16() /* Opcode 0x35 */
2391 DEF_axd16(dst, src);
2392 icount -= timing.alu_ri16;
2397 inline void I86::_ss() /* Opcode 0x36 */
2401 icount -= timing.override;
2402 instruction(FETCHOP);
2405 inline void I86::_aaa() /* Opcode 0x37 */
2408 if(regs.b[AL]>0xf9) {
2411 if(AF || ((regs.b[AL] & 0xf) > 9)) {
2413 regs.b[AH] += ALcarry;
2421 icount -= timing.aaa;
2424 inline void I86::_cmp_br8() /* Opcode 0x38 */
2427 icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
2431 inline void I86::_cmp_wr16() /* Opcode 0x39 */
2434 icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
2438 inline void I86::_cmp_r8b() /* Opcode 0x3a */
2441 icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
2445 inline void I86::_cmp_r16w() /* Opcode 0x3b */
2448 icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
2452 inline void I86::_cmp_ald8() /* Opcode 0x3c */
2455 icount -= timing.alu_ri8;
2459 inline void I86::_cmp_axd16() /* Opcode 0x3d */
2461 DEF_axd16(dst, src);
2462 icount -= timing.alu_ri16;
2466 inline void I86::_ds() /* Opcode 0x3e */
2470 icount -= timing.override;
2471 instruction(FETCHOP);
2474 inline void I86::_aas() /* Opcode 0x3f */
2477 if(regs.b[AL] > 0xf9) {
2480 if(AF || ((regs.b[AL] & 0xf) > 9)) {
2490 icount -= timing.aas;
2493 #define IncWordReg(Reg) { \
2494 unsigned tmp = (unsigned)regs.w[Reg]; \
2495 unsigned tmp1 = tmp + 1; \
2496 SetOFW_Add(tmp1, tmp, 1); \
2497 SetAF(tmp1, tmp, 1); \
2498 SetSZPF_Word(tmp1); \
2499 regs.w[Reg] = tmp1; \
2500 icount -= timing.incdec_r16; \
2503 inline void I86::_inc_ax() /* Opcode 0x40 */
2508 inline void I86::_inc_cx() /* Opcode 0x41 */
2513 inline void I86::_inc_dx() /* Opcode 0x42 */
2518 inline void I86::_inc_bx() /* Opcode 0x43 */
2523 inline void I86::_inc_sp() /* Opcode 0x44 */
2528 inline void I86::_inc_bp() /* Opcode 0x45 */
2533 inline void I86::_inc_si() /* Opcode 0x46 */
2538 inline void I86::_inc_di() /* Opcode 0x47 */
2543 #define DecWordReg(Reg) { \
2544 unsigned tmp = (unsigned)regs.w[Reg]; \
2545 unsigned tmp1 = tmp - 1; \
2546 SetOFW_Sub(tmp1, 1, tmp); \
2547 SetAF(tmp1, tmp, 1); \
2548 SetSZPF_Word(tmp1); \
2549 regs.w[Reg] = tmp1; \
2550 icount -= timing.incdec_r16; \
2553 inline void I86::_dec_ax() /* Opcode 0x48 */
2558 inline void I86::_dec_cx() /* Opcode 0x49 */
2563 inline void I86::_dec_dx() /* Opcode 0x4a */
2568 inline void I86::_dec_bx() /* Opcode 0x4b */
2573 inline void I86::_dec_sp() /* Opcode 0x4c */
2578 inline void I86::_dec_bp() /* Opcode 0x4d */
2583 inline void I86::_dec_si() /* Opcode 0x4e */
2588 inline void I86::_dec_di() /* Opcode 0x4f */
2593 inline void I86::_push_ax() /* Opcode 0x50 */
2595 icount -= timing.push_r16;
2599 inline void I86::_push_cx() /* Opcode 0x51 */
2601 icount -= timing.push_r16;
2605 inline void I86::_push_dx() /* Opcode 0x52 */
2607 icount -= timing.push_r16;
2611 inline void I86::_push_bx() /* Opcode 0x53 */
2613 icount -= timing.push_r16;
2617 inline void I86::_push_sp() /* Opcode 0x54 */
2619 unsigned tmp = regs.w[SP];
2621 icount -= timing.push_r16;
2625 inline void I86::_push_bp() /* Opcode 0x55 */
2627 icount -= timing.push_r16;
2631 inline void I86::_push_si() /* Opcode 0x56 */
2633 icount -= timing.push_r16;
2637 inline void I86::_push_di() /* Opcode 0x57 */
2639 icount -= timing.push_r16;
2643 inline void I86::_pop_ax() /* Opcode 0x58 */
2645 icount -= timing.pop_r16;
2649 inline void I86::_pop_cx() /* Opcode 0x59 */
2651 icount -= timing.pop_r16;
2655 inline void I86::_pop_dx() /* Opcode 0x5a */
2657 icount -= timing.pop_r16;
2661 inline void I86::_pop_bx() /* Opcode 0x5b */
2663 icount -= timing.pop_r16;
2667 inline void I86::_pop_sp() /* Opcode 0x5c */
2671 icount -= timing.pop_r16;
2676 inline void I86::_pop_bp() /* Opcode 0x5d */
2678 icount -= timing.pop_r16;
2682 inline void I86::_pop_si() /* Opcode 0x5e */
2684 icount -= timing.pop_r16;
2688 inline void I86::_pop_di() /* Opcode 0x5f */
2690 icount -= timing.pop_r16;
2694 inline void I86::_pusha() /* Opcode 0x60 */
2696 unsigned tmp = regs.w[SP];
2698 icount -= timing.pusha;
2709 inline void I86::_popa() /* Opcode 0x61 */
2713 icount -= timing.popa;
2724 inline void I86::_bound() /* Opcode 0x62 */
2726 unsigned ModRM = FETCHOP;
2727 int low = (int16)GetRMWord(ModRM);
2728 int high = (int16)GetNextRMWord;
2729 int tmp = (int16)RegWord(ModRM);
2730 if(tmp < low || tmp>high) {
2731 pc -= (seg_prefix ? 3 : 2);
2732 interrupt(BOUNDS_CHECK_FAULT);
2734 icount -= timing.bound;
2737 inline void I86::_repc(int flagval)
2740 unsigned next = FETCHOP;
2741 unsigned count = regs.w[CX];
2744 case 0x26: /* ES: */
2750 case 0x2e: /* CS: */
2756 case 0x36: /* SS: */
2762 case 0x3e: /* DS: */
2768 case 0x6c: /* REP INSB */
2769 icount -= 9 - count;
2770 for(; (CF == flagval) && (count > 0); count--) {
2775 case 0x6d: /* REP INSW */
2776 icount -= 9 - count;
2777 for(; (CF == flagval) && (count > 0); count--) {
2782 case 0x6e: /* REP OUTSB */
2783 icount -= 9 - count;
2784 for(; (CF == flagval) && (count > 0); count--) {
2789 case 0x6f: /* REP OUTSW */
2790 icount -= 9 - count;
2791 for(; (CF == flagval) && (count > 0); count--) {
2796 case 0xa4: /* REP MOVSB */
2797 icount -= 9 - count;
2798 for(; (CF == flagval) && (count > 0); count--) {
2803 case 0xa5: /* REP MOVSW */
2804 icount -= 9 - count;
2805 for(; (CF == flagval) && (count > 0); count--) {
2810 case 0xa6: /* REP(N)E CMPSB */
2812 for(ZeroVal = !flagval; (ZF == flagval) && (CF == flagval) && (count > 0); count--) {
2817 case 0xa7: /* REP(N)E CMPSW */
2819 for(ZeroVal = !flagval; (ZF == flagval) && (CF == flagval) && (count > 0); count--) {
2824 case 0xaa: /* REP STOSB */
2825 icount -= 9 - count;
2826 for(; (CF == flagval) && (count > 0); count--) {
2831 case 0xab: /* REP STOSW */
2832 icount -= 9 - count;
2833 for(; (CF == flagval) && (count > 0); count--) {
2838 case 0xac: /* REP LODSB */
2840 for(; (CF == flagval) && (count > 0); count--) {
2845 case 0xad: /* REP LODSW */
2847 for(; (CF == flagval) && (count > 0); count--) {
2852 case 0xae: /* REP(N)E SCASB */
2854 for(ZeroVal = !flagval; (ZF == flagval) && (CF == flagval) && (count > 0); count--) {
2859 case 0xaf: /* REP(N)E SCASW */
2861 for(ZeroVal = !flagval; (ZF == flagval) && (CF == flagval) && (count > 0); count--) {
2872 inline void I86::_push_d16() /* Opcode 0x68 */
2874 unsigned tmp = FETCH;
2875 icount -= timing.push_imm;
2880 inline void I86::_imul_d16() /* Opcode 0x69 */
2883 unsigned src2 = FETCH;
2884 src += (FETCH << 8);
2885 icount -= (ModRM >= 0xc0) ? timing.imul_rri16 : timing.imul_rmi16;
2886 dst = (int32)((int16)src) * (int32)((int16)src2);
2887 CarryVal = OverVal = (((int32)dst) >> 15 != 0) && (((int32)dst) >> 15 != -1);
2888 RegWord(ModRM) = (uint16)dst;
2891 inline void I86::_push_d8() /* Opcode 0x6a */
2893 unsigned tmp = (uint16)((int16)((int8)FETCH));
2894 icount -= timing.push_imm;
2898 inline void I86::_imul_d8() /* Opcode 0x6b */
2901 unsigned src2 = (uint16)((int16)((int8)FETCH));
2902 icount -= (ModRM >= 0xc0) ? timing.imul_rri8 : timing.imul_rmi8;
2903 dst = (int32)((int16)src) * (int32)((int16)src2);
2904 CarryVal = OverVal = (((int32)dst) >> 15 != 0) && (((int32)dst) >> 15 != -1);
2905 RegWord(ModRM) = (uint16)dst;
2908 inline void I86::_insb() /* Opcode 0x6c */
2910 icount -= timing.ins8;
2911 PutMemB(ES, regs.w[DI], read_port_byte(regs.w[DX]));
2912 regs.w[DI] += DirVal;
2915 inline void I86::_insw() /* Opcode 0x6d */
2917 icount -= timing.ins16;
2918 PutMemW(ES, regs.w[DI], read_port_word(regs.w[DX]));
2919 regs.w[DI] += 2 * DirVal;
2922 inline void I86::_outsb() /* Opcode 0x6e */
2924 icount -= timing.outs8;
2925 write_port_byte(regs.w[DX], GetMemB(DS, regs.w[SI]));
2926 regs.w[SI] += DirVal; /* GOL 11/27/01 */
2929 inline void I86::_outsw() /* Opcode 0x6f */
2931 icount -= timing.outs16;
2932 write_port_word(regs.w[DX], GetMemW(DS, regs.w[SI]));
2933 regs.w[SI] += 2 * DirVal; /* GOL 11/27/01 */
2936 inline void I86::_jo() /* Opcode 0x70 */
2938 int tmp = (int)((int8)FETCH);
2941 icount -= timing.jcc_t;
2943 icount -= timing.jcc_nt;
2947 inline void I86::_jno() /* Opcode 0x71 */
2949 int tmp = (int)((int8)FETCH);
2952 icount -= timing.jcc_t;
2954 icount -= timing.jcc_nt;
2958 inline void I86::_jb() /* Opcode 0x72 */
2960 int tmp = (int)((int8)FETCH);
2963 icount -= timing.jcc_t;
2965 icount -= timing.jcc_nt;
2969 inline void I86::_jnb() /* Opcode 0x73 */
2971 int tmp = (int)((int8)FETCH);
2974 icount -= timing.jcc_t;
2976 icount -= timing.jcc_nt;
2980 inline void I86::_jz() /* Opcode 0x74 */
2982 int tmp = (int)((int8)FETCH);
2985 icount -= timing.jcc_t;
2987 icount -= timing.jcc_nt;
2991 inline void I86::_jnz() /* Opcode 0x75 */
2993 int tmp = (int)((int8)FETCH);
2996 icount -= timing.jcc_t;
2998 icount -= timing.jcc_nt;
3002 inline void I86::_jbe() /* Opcode 0x76 */
3004 int tmp = (int)((int8)FETCH);
3007 icount -= timing.jcc_t;
3009 icount -= timing.jcc_nt;
3013 inline void I86::_jnbe() /* Opcode 0x77 */
3015 int tmp = (int)((int8)FETCH);
3018 icount -= timing.jcc_t;
3020 icount -= timing.jcc_nt;
3024 inline void I86::_js() /* Opcode 0x78 */
3026 int tmp = (int)((int8)FETCH);
3029 icount -= timing.jcc_t;
3031 icount -= timing.jcc_nt;
3035 inline void I86::_jns() /* Opcode 0x79 */
3037 int tmp = (int)((int8)FETCH);
3040 icount -= timing.jcc_t;
3042 icount -= timing.jcc_nt;
3046 inline void I86::_jp() /* Opcode 0x7a */
3048 int tmp = (int)((int8)FETCH);
3051 icount -= timing.jcc_t;
3053 icount -= timing.jcc_nt;
3057 inline void I86::_jnp() /* Opcode 0x7b */
3059 int tmp = (int)((int8)FETCH);
3062 icount -= timing.jcc_t;
3064 icount -= timing.jcc_nt;
3068 inline void I86::_jl() /* Opcode 0x7c */
3070 int tmp = (int)((int8)FETCH);
3071 if((SF!= OF) && !ZF) {
3073 icount -= timing.jcc_t;
3075 icount -= timing.jcc_nt;
3079 inline void I86::_jnl() /* Opcode 0x7d */
3081 int tmp = (int)((int8)FETCH);
3082 if(ZF || (SF == OF)) {
3084 icount -= timing.jcc_t;
3086 icount -= timing.jcc_nt;
3090 inline void I86::_jle() /* Opcode 0x7e */
3092 int tmp = (int)((int8)FETCH);
3093 if(ZF || (SF!= OF)) {
3095 icount -= timing.jcc_t;
3097 icount -= timing.jcc_nt;
3101 inline void I86::_jnle() /* Opcode 0x7f */
3103 int tmp = (int)((int8)FETCH);
3104 if((SF == OF) && !ZF) {
3106 icount -= timing.jcc_t;
3108 icount -= timing.jcc_nt;
3112 inline void I86::_80pre() /* Opcode 0x80 */
3114 unsigned ModRM = FETCHOP;
3115 unsigned dst = GetRMByte(ModRM);
3116 unsigned src = FETCH;
3118 switch((ModRM >> 3) & 7) {
3119 case 0: /* ADD eb, d8 */
3121 PutbackRMByte(ModRM, dst);
3122 icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
3124 case 1: /* OR eb, d8 */
3126 PutbackRMByte(ModRM, dst);
3127 icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
3129 case 2: /* ADC eb, d8 */
3132 PutbackRMByte(ModRM, dst);
3133 icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
3135 case 3: /* SBB eb, b8 */
3138 PutbackRMByte(ModRM, dst);
3139 icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
3141 case 4: /* AND eb, d8 */
3143 PutbackRMByte(ModRM, dst);
3144 icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
3146 case 5: /* SUB eb, d8 */
3148 PutbackRMByte(ModRM, dst);
3149 icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
3151 case 6: /* XOR eb, d8 */
3153 PutbackRMByte(ModRM, dst);
3154 icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
3156 case 7: /* CMP eb, d8 */
3158 icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8_ro;
3166 inline void I86::_81pre() /* Opcode 0x81 */
3168 unsigned ModRM = FETCH;
3169 unsigned dst = GetRMWord(ModRM);
3170 unsigned src = FETCH;
3171 src += (FETCH << 8);
3173 switch((ModRM >> 3) & 7) {
3174 case 0: /* ADD ew, d16 */
3176 PutbackRMWord(ModRM, dst);
3177 icount -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
3179 case 1: /* OR ew, d16 */
3181 PutbackRMWord(ModRM, dst);
3182 icount -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
3184 case 2: /* ADC ew, d16 */
3187 PutbackRMWord(ModRM, dst);
3188 icount -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
3190 case 3: /* SBB ew, d16 */
3193 PutbackRMWord(ModRM, dst);
3194 icount -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
3196 case 4: /* AND ew, d16 */
3198 PutbackRMWord(ModRM, dst);
3199 icount -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
3201 case 5: /* SUB ew, d16 */
3203 PutbackRMWord(ModRM, dst);
3204 icount -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
3206 case 6: /* XOR ew, d16 */
3208 PutbackRMWord(ModRM, dst);
3209 icount -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
3211 case 7: /* CMP ew, d16 */
3213 icount -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16_ro;
3221 inline void I86::_82pre() /* Opcode 0x82 */
3223 unsigned ModRM = FETCH;
3224 unsigned dst = GetRMByte(ModRM);
3225 unsigned src = FETCH;
3227 switch((ModRM >> 3) & 7) {
3228 case 0: /* ADD eb, d8 */
3230 PutbackRMByte(ModRM, dst);
3231 icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
3233 case 1: /* OR eb, d8 */
3235 PutbackRMByte(ModRM, dst);
3236 icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
3238 case 2: /* ADC eb, d8 */
3241 PutbackRMByte(ModRM, dst);
3242 icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
3244 case 3: /* SBB eb, d8 */
3247 PutbackRMByte(ModRM, dst);
3248 icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
3250 case 4: /* AND eb, d8 */
3252 PutbackRMByte(ModRM, dst);
3253 icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
3255 case 5: /* SUB eb, d8 */
3257 PutbackRMByte(ModRM, dst);
3258 icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
3260 case 6: /* XOR eb, d8 */
3262 PutbackRMByte(ModRM, dst);
3263 icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
3265 case 7: /* CMP eb, d8 */
3267 icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8_ro;
3275 inline void I86::_83pre() /* Opcode 0x83 */
3277 unsigned ModRM = FETCH;
3278 unsigned dst = GetRMWord(ModRM);
3279 unsigned src = (uint16)((int16)((int8)FETCH));
3281 switch((ModRM >> 3) & 7) {
3282 case 0: /* ADD ew, d16 */
3284 PutbackRMWord(ModRM, dst);
3285 icount -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
3287 case 1: /* OR ew, d16 */
3289 PutbackRMWord(ModRM, dst);
3290 icount -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
3292 case 2: /* ADC ew, d16 */
3295 PutbackRMWord(ModRM, dst);
3296 icount -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
3298 case 3: /* SBB ew, d16 */
3301 PutbackRMWord(ModRM, dst);
3302 icount -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
3304 case 4: /* AND ew, d16 */
3306 PutbackRMWord(ModRM, dst);
3307 icount -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
3309 case 5: /* SUB ew, d16 */
3311 PutbackRMWord(ModRM, dst);
3312 icount -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
3314 case 6: /* XOR ew, d16 */
3316 PutbackRMWord(ModRM, dst);
3317 icount -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
3319 case 7: /* CMP ew, d16 */
3321 icount -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8_ro;
3329 inline void I86::_test_br8() /* Opcode 0x84 */
3332 icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
3336 inline void I86::_test_wr16() /* Opcode 0x85 */
3339 icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
3343 inline void I86::_xchg_br8() /* Opcode 0x86 */
3346 icount -= (ModRM >= 0xc0) ? timing.xchg_rr8 : timing.xchg_rm8;
3347 RegByte(ModRM) = dst;
3348 PutbackRMByte(ModRM, src);
3351 inline void I86::_xchg_wr16() /* Opcode 0x87 */
3354 icount -= (ModRM >= 0xc0) ? timing.xchg_rr16 : timing.xchg_rm16;
3355 RegWord(ModRM) = dst;
3356 PutbackRMWord(ModRM, src);
3359 inline void I86::_mov_br8() /* Opcode 0x88 */
3361 unsigned ModRM = FETCH;
3362 uint8 src = RegByte(ModRM);
3363 icount -= (ModRM >= 0xc0) ? timing.mov_rr8 : timing.mov_mr8;
3364 PutRMByte(ModRM, src);
3367 inline void I86::_mov_wr16() /* Opcode 0x89 */
3369 unsigned ModRM = FETCH;
3370 uint16 src = RegWord(ModRM);
3371 icount -= (ModRM >= 0xc0) ? timing.mov_rr16 : timing.mov_mr16;
3372 PutRMWord(ModRM, src);
3375 inline void I86::_mov_r8b() /* Opcode 0x8a */
3377 unsigned ModRM = FETCH;
3378 uint8 src = GetRMByte(ModRM);
3379 icount -= (ModRM >= 0xc0) ? timing.mov_rr8 : timing.mov_rm8;
3380 RegByte(ModRM) = src;
3383 inline void I86::_mov_r16w() /* Opcode 0x8b */
3385 unsigned ModRM = FETCH;
3386 uint16 src = GetRMWord(ModRM);
3387 icount -= (ModRM >= 0xc0) ? timing.mov_rr8 : timing.mov_rm16;
3388 RegWord(ModRM) = src;
3391 inline void I86::_mov_wsreg() /* Opcode 0x8c */
3393 unsigned ModRM = FETCH;
3394 icount -= (ModRM >= 0xc0) ? timing.mov_rs : timing.mov_ms;
3396 return; /* 1xx is invalid */
3398 PutRMWord(ModRM, sregs[(ModRM & 0x38) >> 3]);
3401 inline void I86::_lea() /* Opcode 0x8d */
3403 unsigned ModRM = FETCH;
3404 icount -= timing.lea;
3406 RegWord(ModRM) = eo; /* effective offset (no segment part) */
3409 inline void I86::_mov_sregw() /* Opcode 0x8e */
3411 unsigned ModRM = FETCH;
3412 uint16 src = GetRMWord(ModRM);
3414 icount -= (ModRM >= 0xc0) ? timing.mov_sr : timing.mov_sm;
3415 switch((ModRM >> 3) & 7) {
3416 case 0: /* mov es, ew */
3418 base[ES] = SegBase(ES);
3420 case 1: /* mov cs, ew */
3421 break; /* doesn't do a jump far */
3422 case 2: /* mov ss, ew */
3424 base[SS] = SegBase(SS); /* no interrupt allowed before next instr */
3425 instruction(FETCHOP);
3427 case 3: /* mov ds, ew */
3429 base[DS] = SegBase(DS);
3442 inline void I86::_popw() /* Opcode 0x8f */
3444 unsigned ModRM = FETCH;
3447 icount -= (ModRM >= 0xc0) ? timing.pop_r16 : timing.pop_m16;
3448 PutRMWord(ModRM, tmp);
3451 #define XchgAXReg(Reg) { \
3453 tmp = regs.w[Reg]; \
3454 regs.w[Reg] = regs.w[AX]; \
3456 icount -= timing.xchg_ar16; \
3459 inline void I86::_nop() /* Opcode 0x90 */
3461 /* this is XchgAXReg(AX); */
3462 icount -= timing.nop;
3465 inline void I86::_xchg_axcx() /* Opcode 0x91 */
3470 inline void I86::_xchg_axdx() /* Opcode 0x92 */
3475 inline void I86::_xchg_axbx() /* Opcode 0x93 */
3480 inline void I86::_xchg_axsp() /* Opcode 0x94 */
3485 inline void I86::_xchg_axbp() /* Opcode 0x95 */
3490 inline void I86::_xchg_axsi() /* Opcode 0x96 */
3495 inline void I86::_xchg_axdi() /* Opcode 0x97 */
3500 inline void I86::_cbw() /* Opcode 0x98 */
3502 icount -= timing.cbw;
3503 regs.b[AH] = (regs.b[AL] & 0x80) ? 0xff : 0;
3506 inline void I86::_cwd() /* Opcode 0x99 */
3508 icount -= timing.cwd;
3509 regs.w[DX] = (regs.b[AH] & 0x80) ? 0xffff : 0;
3512 inline void I86::_call_far() /* Opcode 0x9a */
3526 sregs[CS] = (uint16)tmp2;
3527 base[CS] = SegBase(CS);
3528 pc = (base[CS] + (uint16)tmp) & AMASK;
3529 #ifdef I86_BIOS_CALL
3530 if(d_bios && d_bios->bios_call_i86(pc, regs.w, sregs, &ZeroVal, &CarryVal)) {
3535 icount -= timing.call_far;
3538 inline void I86::_wait() /* Opcode 0x9b */
3543 icount -= timing.wait;
3546 inline void I86::_pushf() /* Opcode 0x9c */
3549 icount -= timing.pushf;
3551 tmp = CompressFlags();
3555 inline void I86::_popf() /* Opcode 0x9d */
3559 icount -= timing.popf;
3566 /* if the IF is set, and an interrupt is pending, signal an interrupt */
3567 if(IF && (int_state & INT_REQ_BIT)) {
3572 inline void I86::_sahf() /* Opcode 0x9e */
3574 unsigned tmp = (CompressFlags() & 0xff00) | (regs.b[AH] & 0xd5);
3575 icount -= timing.sahf;
3579 inline void I86::_lahf() /* Opcode 0x9f */
3581 regs.b[AH] = CompressFlags() & 0xff;
3582 icount -= timing.lahf;
3585 inline void I86::_mov_aldisp() /* Opcode 0xa0 */
3592 icount -= timing.mov_am8;
3593 regs.b[AL] = GetMemB(DS, addr);
3596 inline void I86::_mov_axdisp() /* Opcode 0xa1 */
3603 icount -= timing.mov_am16;
3604 regs.w[AX] = GetMemW(DS, addr);
3607 inline void I86::_mov_dispal() /* Opcode 0xa2 */
3614 icount -= timing.mov_ma8;
3615 PutMemB(DS, addr, regs.b[AL]);
3618 inline void I86::_mov_dispax() /* Opcode 0xa3 */
3625 icount -= timing.mov_ma16;
3626 PutMemW(DS, addr, regs.w[AX]);
3629 inline void I86::_movsb() /* Opcode 0xa4 */
3631 uint8 tmp = GetMemB(DS, regs.w[SI]);
3632 PutMemB(ES, regs.w[DI], tmp);
3633 regs.w[DI] += DirVal;
3634 regs.w[SI] += DirVal;
3635 icount -= timing.movs8;
3638 inline void I86::_movsw() /* Opcode 0xa5 */
3640 uint16 tmp = GetMemW(DS, regs.w[SI]);
3641 PutMemW(ES, regs.w[DI], tmp);
3642 regs.w[DI] += 2 * DirVal;
3643 regs.w[SI] += 2 * DirVal;
3644 icount -= timing.movs16;
3647 inline void I86::_cmpsb() /* Opcode 0xa6 */
3649 unsigned dst = GetMemB(ES, regs.w[DI]);
3650 unsigned src = GetMemB(DS, regs.w[SI]);
3651 SUBB(src, dst); /* opposite of the usual convention */
3652 regs.w[DI] += DirVal;
3653 regs.w[SI] += DirVal;
3654 icount -= timing.cmps8;
3657 inline void I86::_cmpsw() /* Opcode 0xa7 */
3659 unsigned dst = GetMemW(ES, regs.w[DI]);
3660 unsigned src = GetMemW(DS, regs.w[SI]);
3661 SUBW(src, dst); /* opposite of the usual convention */
3662 regs.w[DI] += 2 * DirVal;
3663 regs.w[SI] += 2 * DirVal;
3664 icount -= timing.cmps16;
3667 inline void I86::_test_ald8() /* Opcode 0xa8 */
3670 icount -= timing.alu_ri8;
3674 inline void I86::_test_axd16() /* Opcode 0xa9 */
3676 DEF_axd16(dst, src);
3677 icount -= timing.alu_ri16;
3681 inline void I86::_stosb() /* Opcode 0xaa */
3683 PutMemB(ES, regs.w[DI], regs.b[AL]);
3684 regs.w[DI] += DirVal;
3685 icount -= timing.stos8;
3688 inline void I86::_stosw() /* Opcode 0xab */
3690 PutMemW(ES, regs.w[DI], regs.w[AX]);
3691 regs.w[DI] += 2 * DirVal;
3692 icount -= timing.stos16;
3695 inline void I86::_lodsb() /* Opcode 0xac */
3697 regs.b[AL] = GetMemB(DS, regs.w[SI]);
3698 regs.w[SI] += DirVal;
3699 icount -= timing.lods8;
3702 inline void I86::_lodsw() /* Opcode 0xad */
3704 regs.w[AX] = GetMemW(DS, regs.w[SI]);
3705 regs.w[SI] += 2 * DirVal;
3706 icount -= timing.lods16;
3709 inline void I86::_scasb() /* Opcode 0xae */
3711 unsigned src = GetMemB(ES, regs.w[DI]);
3712 unsigned dst = regs.b[AL];
3714 regs.w[DI] += DirVal;
3715 icount -= timing.scas8;
3718 inline void I86::_scasw() /* Opcode 0xaf */
3720 unsigned src = GetMemW(ES, regs.w[DI]);
3721 unsigned dst = regs.w[AX];
3723 regs.w[DI] += 2 * DirVal;
3724 icount -= timing.scas16;
3727 inline void I86::_mov_ald8() /* Opcode 0xb0 */
3730 icount -= timing.mov_ri8;
3733 inline void I86::_mov_cld8() /* Opcode 0xb1 */
3736 icount -= timing.mov_ri8;
3739 inline void I86::_mov_dld8() /* Opcode 0xb2 */
3742 icount -= timing.mov_ri8;
3745 inline void I86::_mov_bld8() /* Opcode 0xb3 */
3748 icount -= timing.mov_ri8;
3751 inline void I86::_mov_ahd8() /* Opcode 0xb4 */
3754 icount -= timing.mov_ri8;
3757 inline void I86::_mov_chd8() /* Opcode 0xb5 */
3760 icount -= timing.mov_ri8;
3763 inline void I86::_mov_dhd8() /* Opcode 0xb6 */
3766 icount -= timing.mov_ri8;
3769 inline void I86::_mov_bhd8() /* Opcode 0xb7 */
3772 icount -= timing.mov_ri8;
3775 inline void I86::_mov_axd16() /* Opcode 0xb8 */
3779 icount -= timing.mov_ri16;
3782 inline void I86::_mov_cxd16() /* Opcode 0xb9 */
3786 icount -= timing.mov_ri16;
3789 inline void I86::_mov_dxd16() /* Opcode 0xba */
3793 icount -= timing.mov_ri16;
3796 inline void I86::_mov_bxd16() /* Opcode 0xbb */
3800 icount -= timing.mov_ri16;
3803 inline void I86::_mov_spd16() /* Opcode 0xbc */
3805 regs.b[SPL] = FETCH;
3806 regs.b[SPH] = FETCH;
3807 icount -= timing.mov_ri16;
3810 inline void I86::_mov_bpd16() /* Opcode 0xbd */
3812 regs.b[BPL] = FETCH;
3813 regs.b[BPH] = FETCH;
3814 icount -= timing.mov_ri16;
3817 inline void I86::_mov_sid16() /* Opcode 0xbe */
3819 regs.b[SIL] = FETCH;
3820 regs.b[SIH] = FETCH;
3821 icount -= timing.mov_ri16;
3824 inline void I86::_mov_did16() /* Opcode 0xbf */
3826 regs.b[DIL] = FETCH;
3827 regs.b[DIH] = FETCH;
3828 icount -= timing.mov_ri16;
3831 inline void I86::_rotshft_bd8() /* Opcode 0xc0 */
3833 unsigned ModRM = FETCH;
3834 unsigned count = FETCH;
3836 rotate_shift_byte(ModRM, count);
3839 inline void I86::_rotshft_wd8() /* Opcode 0xc1 */
3841 unsigned ModRM = FETCH;
3842 unsigned count = FETCH;
3844 rotate_shift_word(ModRM, count);
3847 inline void I86::_ret_d16() /* Opcode 0xc2 */
3849 unsigned count = FETCH;
3850 count += FETCH << 8;
3852 pc = (pc + base[CS]) & AMASK;
3853 regs.w[SP] += count;
3854 icount -= timing.ret_near_imm;
3857 inline void I86::_ret() /* Opcode 0xc3 */
3860 pc = (pc + base[CS]) & AMASK;
3861 icount -= timing.ret_near;
3864 inline void I86::_les_dw() /* Opcode 0xc4 */
3866 unsigned ModRM = FETCH;
3867 uint16 tmp = GetRMWord(ModRM);
3868 RegWord(ModRM) = tmp;
3869 sregs[ES] = GetNextRMWord;
3870 base[ES] = SegBase(ES);
3871 icount -= timing.load_ptr;
3874 inline void I86::_lds_dw() /* Opcode 0xc5 */
3876 unsigned ModRM = FETCH;
3877 uint16 tmp = GetRMWord(ModRM);
3878 RegWord(ModRM) = tmp;
3879 sregs[DS] = GetNextRMWord;
3880 base[DS] = SegBase(DS);
3881 icount -= timing.load_ptr;
3884 inline void I86::_mov_bd8() /* Opcode 0xc6 */
3886 unsigned ModRM = FETCH;
3887 icount -= (ModRM >= 0xc0) ? timing.mov_ri8 : timing.mov_mi8;
3888 PutImmRMByte(ModRM);
3891 inline void I86::_mov_wd16() /* Opcode 0xc7 */
3893 unsigned ModRM = FETCH;
3894 icount -= (ModRM >= 0xc0) ? timing.mov_ri16 : timing.mov_mi16;
3895 PutImmRMWord(ModRM);
3898 inline void I86::_enter() /* Opcode 0xc8 */
3900 unsigned nb = FETCH;
3905 icount -= (level == 0) ? timing.enter0 : (level == 1) ? timing.enter1 : timing.enter_base + level * timing.enter_count;
3907 regs.w[BP] = regs.w[SP];
3909 for(i = 1; i < level; i++) {
3910 PUSH(GetMemW(SS, regs.w[BP] - i * 2));
3917 inline void I86::_leav() /* Opcode 0xc9 */
3919 icount -= timing.leave;
3920 regs.w[SP] = regs.w[BP];
3924 inline void I86::_retf_d16() /* Opcode 0xca */
3926 unsigned count = FETCH;
3927 count += FETCH << 8;
3930 base[CS] = SegBase(CS);
3931 pc = (pc + base[CS]) & AMASK;
3932 regs.w[SP] += count;
3933 icount -= timing.ret_far_imm;
3936 inline void I86::_retf() /* Opcode 0xcb */
3940 base[CS] = SegBase(CS);
3941 pc = (pc + base[CS]) & AMASK;
3942 icount -= timing.ret_far;
3945 inline void I86::_int3() /* Opcode 0xcc */
3947 icount -= timing.int3;
3951 inline void I86::_int() /* Opcode 0xcd */
3953 unsigned int_num = FETCH;
3954 icount -= timing.int_imm;
3955 #ifdef I86_BIOS_CALL
3956 if(d_bios && d_bios->bios_int_i86(int_num, regs.w, sregs, &ZeroVal, &CarryVal)) {
3964 inline void I86::_into() /* Opcode 0xce */
3967 icount -= timing.into_t;
3968 interrupt(OVERFLOW_TRAP);
3970 icount -= timing.into_nt;
3974 inline void I86::_iret() /* Opcode 0xcf */
3976 icount -= timing.iret;
3979 base[CS] = SegBase(CS);
3980 pc = (pc + base[CS]) & AMASK;
3983 /* if the IF is set, and an interrupt is pending, signal an interrupt */
3984 if(IF && (int_state & INT_REQ_BIT)) {
3989 inline void I86::_rotshft_b() /* Opcode 0xd0 */
3991 rotate_shift_byte(FETCHOP, 1);
3994 inline void I86::_rotshft_w() /* Opcode 0xd1 */
3996 rotate_shift_word(FETCHOP, 1);
3999 inline void I86::_rotshft_bcl() /* Opcode 0xd2 */
4001 rotate_shift_byte(FETCHOP, regs.b[CL]);
4004 inline void I86::_rotshft_wcl() /* Opcode 0xd3 */
4006 rotate_shift_word(FETCHOP, regs.b[CL]);
4009 /* OB: Opcode works on NEC V-Series but not the Variants */
4010 /* one could specify any byte value as operand but the NECs */
4011 /* always substitute 0x0a. */
4012 inline void I86::_aam() /* Opcode 0xd4 */
4014 unsigned mult = FETCH;
4015 icount -= timing.aam;
4017 interrupt(DIVIDE_FAULT);
4019 regs.b[AH] = regs.b[AL] / mult;
4021 SetSZPF_Word(regs.w[AX]);
4025 inline void I86::_aad() /* Opcode 0xd5 */
4027 unsigned mult = FETCH;
4028 icount -= timing.aad;
4029 regs.b[AL] = regs.b[AH] * mult + regs.b[AL];
4036 inline void I86::_setalc() /* Opcode 0xd6 */
4038 regs.b[AL] = (CF) ? 0xff : 0x00;
4042 inline void I86::_xlat() /* Opcode 0xd7 */
4044 unsigned dest = regs.w[BX] + regs.b[AL];
4045 icount -= timing.xlat;
4046 regs.b[AL] = GetMemB(DS, dest);
4049 inline void I86::_escape() /* Opcodes 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde and 0xdf */
4051 unsigned ModRM = FETCH;
4052 icount -= timing.nop;
4056 inline void I86::_loopne() /* Opcode 0xe0 */
4058 int disp = (int)((int8)FETCH);
4059 unsigned tmp = regs.w[CX] - 1;
4062 icount -= timing.loop_t;
4065 icount -= timing.loop_nt;
4069 inline void I86::_loope() /* Opcode 0xe1 */
4071 int disp = (int)((int8)FETCH);
4072 unsigned tmp = regs.w[CX] - 1;
4075 icount -= timing.loope_t;
4078 icount -= timing.loope_nt;
4082 inline void I86::_loop() /* Opcode 0xe2 */
4084 int disp = (int)((int8)FETCH);
4085 unsigned tmp = regs.w[CX] - 1;
4088 icount -= timing.loop_t;
4091 icount -= timing.loop_nt;
4095 inline void I86::_jcxz() /* Opcode 0xe3 */
4097 int disp = (int)((int8)FETCH);
4098 if(regs.w[CX] == 0) {
4099 icount -= timing.jcxz_t;
4102 icount -= timing.jcxz_nt;
4106 inline void I86::_inal() /* Opcode 0xe4 */
4108 unsigned port = FETCH;
4109 icount -= timing.in_imm8;
4110 regs.b[AL] = read_port_byte(port);
4113 inline void I86::_inax() /* Opcode 0xe5 */
4115 unsigned port = FETCH;
4116 icount -= timing.in_imm16;
4117 regs.w[AX] = read_port_word(port);
4120 inline void I86::_outal() /* Opcode 0xe6 */
4122 unsigned port = FETCH;
4123 icount -= timing.out_imm8;
4124 write_port_byte(port, regs.b[AL]);
4127 inline void I86::_outax() /* Opcode 0xe7 */
4129 unsigned port = FETCH;
4130 icount -= timing.out_imm16;
4131 write_port_word(port, regs.w[AX]);
4134 inline void I86::_call_d16() /* Opcode 0xe8 */
4142 pc = (ip + base[CS]) & AMASK;
4143 #ifdef I86_BIOS_CALL
4144 if(d_bios && d_bios->bios_call_i86(pc, regs.w, sregs, &ZeroVal, &CarryVal)) {
4149 icount -= timing.call_near;
4152 inline void I86::_jmp_d16() /* Opcode 0xe9 */
4157 ip = pc - base[CS] + tmp;
4158 pc = (ip + base[CS]) & AMASK;
4159 icount -= timing.jmp_near;
4162 inline void I86::_jmp_far() /* Opcode 0xea */
4172 sregs[CS] = (uint16)tmp1;
4173 base[CS] = SegBase(CS);
4174 pc = (base[CS] + tmp) & AMASK;
4175 icount -= timing.jmp_far;
4178 inline void I86::_jmp_d8() /* Opcode 0xeb */
4180 int tmp = (int)((int8)FETCH);
4182 icount -= timing.jmp_short;
4185 inline void I86::_inaldx() /* Opcode 0xec */
4187 icount -= timing.in_dx8;
4188 regs.b[AL] = read_port_byte(regs.w[DX]);
4191 inline void I86::_inaxdx() /* Opcode 0xed */
4193 unsigned port = regs.w[DX];
4194 icount -= timing.in_dx16;
4195 regs.w[AX] = read_port_word(port);
4198 inline void I86::_outdxal() /* Opcode 0xee */
4200 icount -= timing.out_dx8;
4201 write_port_byte(regs.w[DX], regs.b[AL]);
4204 inline void I86::_outdxax() /* Opcode 0xef */
4206 unsigned port = regs.w[DX];
4207 icount -= timing.out_dx16;
4208 write_port_word(port, regs.w[AX]);
4211 /* I think thats not a V20 instruction...*/
4212 inline void I86::_lock() /* Opcode 0xf0 */
4214 icount -= timing.nop;
4215 instruction(FETCHOP); /* un-interruptible */
4218 inline void I86::_rep(int flagval)
4220 /* Handles rep- and repnz- prefixes. flagval is the value of ZF for the
4221 loop to continue for CMPS and SCAS instructions. */
4223 unsigned next = FETCHOP;
4224 unsigned count = regs.w[CX];
4227 case 0x26: /* ES: */
4230 icount -= timing.override;
4233 case 0x2e: /* CS: */
4236 icount -= timing.override;
4239 case 0x36: /* SS: */
4242 icount -= timing.override;
4245 case 0x3e: /* DS: */
4248 icount -= timing.override;
4252 case 0x6c: /* REP INSB */
4253 icount -= timing.rep_ins8_base;
4254 for(; count > 0; count--) {
4255 PutMemB(ES, regs.w[DI], read_port_byte(regs.w[DX]));
4256 regs.w[DI] += DirVal;
4257 icount -= timing.rep_ins8_count;
4261 case 0x6d: /* REP INSW */
4262 icount -= timing.rep_ins16_base;
4263 for(; count > 0; count--) {
4264 PutMemW(ES, regs.w[DI], read_port_word(regs.w[DX]));
4265 regs.w[DI] += 2 * DirVal;
4266 icount -= timing.rep_ins16_count;
4270 case 0x6e: /* REP OUTSB */
4271 icount -= timing.rep_outs8_base;
4272 for(; count > 0; count--) {
4273 write_port_byte(regs.w[DX], GetMemB(DS, regs.w[SI]));
4274 regs.w[SI] += DirVal; /* GOL 11/27/01 */
4275 icount -= timing.rep_outs8_count;
4279 case 0x6f: /* REP OUTSW */
4280 icount -= timing.rep_outs16_base;
4281 for(; count > 0; count--) {
4282 write_port_word(regs.w[DX], GetMemW(DS, regs.w[SI]));
4283 regs.w[SI] += 2 * DirVal; /* GOL 11/27/01 */
4284 icount -= timing.rep_outs16_count;
4289 case 0xa4: /* REP MOVSB */
4290 icount -= timing.rep_movs8_base;
4291 for(; count > 0; count--) {
4293 tmp = GetMemB(DS, regs.w[SI]);
4294 PutMemB(ES, regs.w[DI], tmp);
4295 regs.w[DI] += DirVal;
4296 regs.w[SI] += DirVal;
4297 icount -= timing.rep_movs8_count;
4301 case 0xa5: /* REP MOVSW */
4302 icount -= timing.rep_movs16_base;
4303 for(; count > 0; count--) {
4305 tmp = GetMemW(DS, regs.w[SI]);
4306 PutMemW(ES, regs.w[DI], tmp);
4307 regs.w[DI] += 2 * DirVal;
4308 regs.w[SI] += 2 * DirVal;
4309 icount -= timing.rep_movs16_count;
4313 case 0xa6: /* REP(N)E CMPSB */
4314 icount -= timing.rep_cmps8_base;
4315 for(ZeroVal = !flagval; (ZF == flagval) && (count > 0); count--) {
4317 dst = GetMemB(ES, regs.w[DI]);
4318 src = GetMemB(DS, regs.w[SI]);
4319 SUBB(src, dst); /* opposite of the usual convention */
4320 regs.w[DI] += DirVal;
4321 regs.w[SI] += DirVal;
4322 icount -= timing.rep_cmps8_count;
4326 case 0xa7: /* REP(N)E CMPSW */
4327 icount -= timing.rep_cmps16_base;
4328 for(ZeroVal = !flagval; (ZF == flagval) && (count > 0); count--) {
4330 dst = GetMemW(ES, regs.w[DI]);
4331 src = GetMemW(DS, regs.w[SI]);
4332 SUBW(src, dst); /* opposite of the usual convention */
4333 regs.w[DI] += 2 * DirVal;
4334 regs.w[SI] += 2 * DirVal;
4335 icount -= timing.rep_cmps16_count;
4339 case 0xaa: /* REP STOSB */
4340 icount -= timing.rep_stos8_base;
4341 for(; count > 0; count--) {
4342 PutMemB(ES, regs.w[DI], regs.b[AL]);
4343 regs.w[DI] += DirVal;
4344 icount -= timing.rep_stos8_count;
4348 case 0xab: /* REP STOSW */
4349 icount -= timing.rep_stos16_base;
4350 for(; count > 0; count--) {
4351 PutMemW(ES, regs.w[DI], regs.w[AX]);
4352 regs.w[DI] += 2 * DirVal;
4353 icount -= timing.rep_stos16_count;
4357 case 0xac: /* REP LODSB */
4358 icount -= timing.rep_lods8_base;
4359 for(; count > 0; count--) {
4360 regs.b[AL] = GetMemB(DS, regs.w[SI]);
4361 regs.w[SI] += DirVal;
4362 icount -= timing.rep_lods8_count;
4366 case 0xad: /* REP LODSW */
4367 icount -= timing.rep_lods16_base;
4368 for(; count > 0; count--) {
4369 regs.w[AX] = GetMemW(DS, regs.w[SI]);
4370 regs.w[SI] += 2 * DirVal;
4371 icount -= timing.rep_lods16_count;
4375 case 0xae: /* REP(N)E SCASB */
4376 icount -= timing.rep_scas8_base;
4377 for(ZeroVal = !flagval; (ZF == flagval) && (count > 0); count--) {
4379 src = GetMemB(ES, regs.w[DI]);
4382 regs.w[DI] += DirVal;
4383 icount -= timing.rep_scas8_count;
4387 case 0xaf: /* REP(N)E SCASW */
4388 icount -= timing.rep_scas16_base;
4389 for(ZeroVal = !flagval; (ZF == flagval) && (count > 0); count--) {
4391 src = GetMemW(ES, regs.w[DI]);
4394 regs.w[DI] += 2 * DirVal;
4395 icount -= timing.rep_scas16_count;
4404 inline void I86::_repne() /* Opcode 0xf2 */
4409 inline void I86::_repe() /* Opcode 0xf3 */
4414 inline void I86::_hlt() /* Opcode 0xf4 */
4421 inline void I86::_cmc() /* Opcode 0xf5 */
4423 icount -= timing.flag_ops;
4427 inline void I86::_f6pre() /* Opcode 0xf6 */
4429 unsigned ModRM = FETCH;
4430 unsigned tmp = (unsigned)GetRMByte(ModRM);
4433 switch((ModRM >> 3) & 7) {
4434 case 0: /* TEST Eb, data8 */
4436 icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8_ro;
4439 CarryVal = OverVal = AuxVal = 0;
4443 case 2: /* NOT Eb */
4444 icount -= (ModRM >= 0xc0) ? timing.negnot_r8 : timing.negnot_m8;
4445 PutbackRMByte(ModRM, ~tmp);
4448 case 3: /* NEG Eb */
4449 icount -= (ModRM >= 0xc0) ? timing.negnot_r8 : timing.negnot_m8;
4452 PutbackRMByte(ModRM, tmp2);
4455 case 4: /* MUL AL, Eb */
4456 icount -= (ModRM >= 0xc0) ? timing.mul_r8 : timing.mul_m8;
4465 result = (uint16)tmp2 * tmp;
4466 regs.w[AX] = (uint16)result;
4469 CarryVal = OverVal = (regs.b[AH] != 0);
4473 case 5: /* IMUL AL, Eb */
4474 icount -= (ModRM >= 0xc0) ? timing.imul_r8 : timing.imul_m8;
4478 tmp2 = (unsigned)regs.b[AL];
4483 result = (int16)((int8)tmp2) * (int16)((int8)tmp);
4484 regs.w[AX] = (uint16)result;
4487 CarryVal = OverVal = (result >> 7 != 0) && (result >> 7 != -1);
4491 case 6: /* DIV AL, Ew */
4492 icount -= (ModRM >= 0xc0) ? timing.div_r8 : timing.div_m8;
4496 result = regs.w[AX];
4499 if((result / tmp) > 0xff) {
4500 interrupt(DIVIDE_FAULT);
4503 regs.b[AH] = result % tmp;
4504 regs.b[AL] = result / tmp;
4507 interrupt(DIVIDE_FAULT);
4513 case 7: /* IDIV AL, Ew */
4514 icount -= (ModRM >= 0xc0) ? timing.idiv_r8 : timing.idiv_m8;
4518 result = regs.w[AX];
4521 tmp2 = result % (int16)((int8)tmp);
4523 if((result /= (int16)((int8)tmp)) > 0xff) {
4524 interrupt(DIVIDE_FAULT);
4527 regs.b[AL] = (uint8)result;
4531 interrupt(DIVIDE_FAULT);
4543 inline void I86::_f7pre() /* Opcode 0xf7 */
4545 unsigned ModRM = FETCH;
4546 unsigned tmp = GetRMWord(ModRM);
4549 switch((ModRM >> 3) & 7) {
4550 case 0: /* TEST Ew, data16 */
4552 icount -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16_ro;
4558 CarryVal = OverVal = AuxVal = 0;
4562 case 2: /* NOT Ew */
4563 icount -= (ModRM >= 0xc0) ? timing.negnot_r16 : timing.negnot_m16;
4565 PutbackRMWord(ModRM, tmp);
4568 case 3: /* NEG Ew */
4569 icount -= (ModRM >= 0xc0) ? timing.negnot_r16 : timing.negnot_m16;
4572 PutbackRMWord(ModRM, tmp2);
4575 case 4: /* MUL AX, Ew */
4576 icount -= (ModRM >= 0xc0) ? timing.mul_r16 : timing.mul_m16;
4584 result = (uint32)tmp2 * tmp;
4585 regs.w[AX] = (uint16)result;
4587 regs.w[DX] = result;
4589 SetZF(regs.w[AX] | regs.w[DX]);
4590 CarryVal = OverVal = (regs.w[DX] != 0);
4594 case 5: /* IMUL AX, Ew */
4595 icount -= (ModRM >= 0xc0) ? timing.imul_r16 : timing.imul_m16;
4604 result = (int32)((int16)tmp2) * (int32)((int16)tmp);
4605 CarryVal = OverVal = (result >> 15 != 0) && (result >> 15 != -1);
4607 regs.w[AX] = (uint16)result;
4608 result = (uint16)(result >> 16);
4609 regs.w[DX] = result;
4611 SetZF(regs.w[AX] | regs.w[DX]);
4615 case 6: /* DIV AX, Ew */
4616 icount -= (ModRM >= 0xc0) ? timing.div_r16 : timing.div_m16;
4620 result = (regs.w[DX] << 16) + regs.w[AX];
4623 tmp2 = result % tmp;
4624 if((result / tmp) > 0xffff) {
4625 interrupt(DIVIDE_FAULT);
4630 regs.w[AX] = result;
4633 interrupt(DIVIDE_FAULT);
4639 case 7: /* IDIV AX, Ew */
4640 icount -= (ModRM >= 0xc0) ? timing.idiv_r16 : timing.idiv_m16;
4644 result = (regs.w[DX] << 16) + regs.w[AX];
4647 tmp2 = result % (int32)((int16)tmp);
4648 if((result /= (int32)((int16)tmp)) > 0xffff) {
4649 interrupt(DIVIDE_FAULT);
4652 regs.w[AX] = result;
4656 interrupt(DIVIDE_FAULT);
4668 inline void I86::_clc() /* Opcode 0xf8 */
4670 icount -= timing.flag_ops;
4674 inline void I86::_stc() /* Opcode 0xf9 */
4676 icount -= timing.flag_ops;
4680 inline void I86::_cli() /* Opcode 0xfa */
4682 icount -= timing.flag_ops;
4686 inline void I86::_sti() /* Opcode 0xfb */
4688 icount -= timing.flag_ops;
4690 instruction(FETCHOP); /* no interrupt before next instruction */
4692 /* if an interrupt is pending, signal an interrupt */
4693 if(IF && (int_state & INT_REQ_BIT)) {
4698 inline void I86::_cld() /* Opcode 0xfc */
4700 icount -= timing.flag_ops;
4704 inline void I86::_std() /* Opcode 0xfd */
4706 icount -= timing.flag_ops;
4710 inline void I86::_fepre() /* Opcode 0xfe */
4712 unsigned ModRM = FETCH;
4713 unsigned tmp = GetRMByte(ModRM);
4716 icount -= (ModRM >= 0xc0) ? timing.incdec_r8 : timing.incdec_m8;
4717 if((ModRM & 0x38) == 0) {
4720 SetOFB_Add(tmp1, tmp, 1);
4724 SetOFB_Sub(tmp1, 1, tmp);
4726 SetAF(tmp1, tmp, 1);
4728 PutbackRMByte(ModRM, (uint8)tmp1);
4731 inline void I86::_ffpre() /* Opcode 0xff */
4733 unsigned ModRM = FETCHOP;
4738 switch((ModRM >> 3) & 7) {
4739 case 0: /* INC ew */
4740 icount -= (ModRM >= 0xc0) ? timing.incdec_r16 : timing.incdec_m16;
4741 tmp = GetRMWord(ModRM);
4743 SetOFW_Add(tmp1, tmp, 1);
4744 SetAF(tmp1, tmp, 1);
4746 PutbackRMWord(ModRM, (uint16)tmp1);
4748 case 1: /* DEC ew */
4749 icount -= (ModRM >= 0xc0) ? timing.incdec_r16 : timing.incdec_m16;
4750 tmp = GetRMWord(ModRM);
4752 SetOFW_Sub(tmp1, 1, tmp);
4753 SetAF(tmp1, tmp, 1);
4755 PutbackRMWord(ModRM, (uint16)tmp1);
4757 case 2: /* CALL ew */
4758 icount -= (ModRM >= 0xc0) ? timing.call_r16 : timing.call_m16;
4759 tmp = GetRMWord(ModRM);
4762 pc = (base[CS] + (uint16)tmp) & AMASK;
4763 #ifdef I86_BIOS_CALL
4764 if(d_bios && d_bios->bios_call_i86(pc, regs.w, sregs, &ZeroVal, &CarryVal)) {
4770 case 3: /* CALL FAR ea */
4771 icount -= timing.call_m32;
4772 tmp = sregs[CS]; /* need to skip displacements of ea */
4773 tmp1 = GetRMWord(ModRM);
4777 sregs[CS] = GetNextRMWord;
4778 base[CS] = SegBase(CS);
4779 pc = (base[CS] + tmp1) & AMASK;
4780 #ifdef I86_BIOS_CALL
4781 if(d_bios && d_bios->bios_call_i86(pc, regs.w, sregs, &ZeroVal, &CarryVal)) {
4787 case 4: /* JMP ea */
4788 icount -= (ModRM >= 0xc0) ? timing.jmp_r16 : timing.jmp_m16;
4789 ip = GetRMWord(ModRM);
4790 pc = (base[CS] + ip) & AMASK;
4792 case 5: /* JMP FAR ea */
4793 icount -= timing.jmp_m32;
4794 pc = GetRMWord(ModRM);
4795 sregs[CS] = GetNextRMWord;
4796 base[CS] = SegBase(CS);
4797 pc = (pc + base[CS]) & AMASK;
4799 case 6: /* PUSH ea */
4800 icount -= (ModRM >= 0xc0) ? timing.push_r16 : timing.push_m16;
4801 tmp = GetRMWord(ModRM);
4804 case 7: /* invalid ??? */
4813 inline void I86::_invalid()
4815 /* i8086/i8088 ignore an invalid opcode. */
4816 /* i80186/i80188 probably also ignore an invalid opcode. */
4821 NEC V-series Disassembler
4823 Originally Written for i386 by Ville Linde
4824 Converted to NEC-V by Aaron Giles
4829 PARAM_REG8 = 1, /* 8-bit register */
4830 PARAM_REG16, /* 16-bit register */
4831 PARAM_REG2_8, /* 8-bit register */
4832 PARAM_REG2_16, /* 16-bit register */
4833 PARAM_RM8, /* 8-bit memory or register */
4834 PARAM_RM16, /* 16-bit memory or register */
4835 PARAM_RMPTR8, /* 8-bit memory or register */
4836 PARAM_RMPTR16, /* 16-bit memory or register */
4837 PARAM_I3, /* 3-bit immediate */
4838 PARAM_I4, /* 4-bit immediate */
4839 PARAM_I8, /* 8-bit signed immediate */
4840 PARAM_I16, /* 16-bit signed immediate */
4841 PARAM_UI8, /* 8-bit unsigned immediate */
4842 PARAM_IMM, /* 16-bit immediate */
4843 PARAM_ADDR, /* 16:16 address */
4844 PARAM_REL8, /* 8-bit PC-relative displacement */
4845 PARAM_REL16, /* 16-bit PC-relative displacement */
4846 PARAM_MEM_OFFS, /* 16-bit mem offset */
4847 PARAM_SREG, /* segment register */
4848 PARAM_SFREG, /* V25/V35 special function register */
4849 PARAM_1, /* used by shift/rotate instructions */
4881 struct I386_OPCODE {
4892 const I386_OPCODE *opcode;
4895 static const UINT8 *opcode_ptr;
4896 static const UINT8 *opcode_ptr_base;
4898 static const I386_OPCODE necv_opcode_table1[256] =
4901 {"add", MODRM, PARAM_RM8, PARAM_REG8, 0 },
4902 {"add", MODRM, PARAM_RM16, PARAM_REG16, 0 },
4903 {"add", MODRM, PARAM_REG8, PARAM_RM8, 0 },
4904 {"add", MODRM, PARAM_REG16, PARAM_RM16, 0 },
4905 {"add", 0, PARAM_AL, PARAM_UI8, 0 },
4906 {"add", 0, PARAM_AW, PARAM_IMM, 0 },
4907 {"push ds1", 0, 0, 0, 0 },
4908 {"pop ds1", 0, 0, 0, 0 },
4909 {"or", MODRM, PARAM_RM8, PARAM_REG8, 0 },
4910 {"or", MODRM, PARAM_RM16, PARAM_REG16, 0 },
4911 {"or", MODRM, PARAM_REG8, PARAM_RM8, 0 },
4912 {"or", MODRM, PARAM_REG16, PARAM_RM16, 0 },
4913 {"or", 0, PARAM_AL, PARAM_UI8, 0 },
4914 {"or", 0, PARAM_AW, PARAM_IMM, 0 },
4915 {"push ps", 0, 0, 0, 0 },
4916 {"two_byte", TWO_BYTE, 0, 0, 0 },
4918 {"addc", MODRM, PARAM_RM8, PARAM_REG8, 0 },
4919 {"addc", MODRM, PARAM_RM16, PARAM_REG16, 0 },
4920 {"addc", MODRM, PARAM_REG8, PARAM_RM8, 0 },
4921 {"addc", MODRM, PARAM_REG16, PARAM_RM16, 0 },
4922 {"addc", 0, PARAM_AL, PARAM_UI8, 0 },
4923 {"addc", 0, PARAM_AW, PARAM_IMM, 0 },
4924 {"push ss", 0, 0, 0, 0 },
4925 {"pop ss", 0, 0, 0, 0 },
4926 {"subc", MODRM, PARAM_RM8, PARAM_REG8, 0 },
4927 {"subc", MODRM, PARAM_RM16, PARAM_REG16, 0 },
4928 {"subc", MODRM, PARAM_REG8, PARAM_RM8, 0 },
4929 {"subc", MODRM, PARAM_REG16, PARAM_RM16, 0 },
4930 {"subc", 0, PARAM_AL, PARAM_UI8, 0 },
4931 {"subc", 0, PARAM_AW, PARAM_IMM, 0 },
4932 {"push ds0", 0, 0, 0, 0 },
4933 {"pop ds0", 0, 0, 0, 0 },
4935 {"and", MODRM, PARAM_RM8, PARAM_REG8, 0 },
4936 {"and", MODRM, PARAM_RM16, PARAM_REG16, 0 },
4937 {"and", MODRM, PARAM_REG8, PARAM_RM8, 0 },
4938 {"and", MODRM, PARAM_REG16, PARAM_RM16, 0 },
4939 {"and", 0, PARAM_AL, PARAM_UI8, 0 },
4940 {"and", 0, PARAM_AW, PARAM_IMM, 0 },
4941 {"ds1:", SEG_DS1, 0, 0, 0 },
4942 {"adj4a", 0, 0, 0, 0 },
4943 {"sub", MODRM, PARAM_RM8, PARAM_REG8, 0 },
4944 {"sub", MODRM, PARAM_RM16, PARAM_REG16, 0 },
4945 {"sub", MODRM, PARAM_REG8, PARAM_RM8, 0 },
4946 {"sub", MODRM, PARAM_REG16, PARAM_RM16, 0 },
4947 {"sub", 0, PARAM_AL, PARAM_UI8, 0 },
4948 {"sub", 0, PARAM_AW, PARAM_IMM, 0 },
4949 {"ps:", SEG_PS, 0, 0, 0 },
4950 {"adj4s", 0, 0, 0, 0 },
4952 {"xor", MODRM, PARAM_RM8, PARAM_REG8, 0 },
4953 {"xor", MODRM, PARAM_RM16, PARAM_REG16, 0 },
4954 {"xor", MODRM, PARAM_REG8, PARAM_RM8, 0 },
4955 {"xor", MODRM, PARAM_REG16, PARAM_RM16, 0 },
4956 {"xor", 0, PARAM_AL, PARAM_UI8, 0 },
4957 {"xor", 0, PARAM_AW, PARAM_IMM, 0 },
4958 {"ss:", SEG_SS, 0, 0, 0 },
4959 {"adjba", 0, 0, 0, 0 },
4960 {"cmp", MODRM, PARAM_RM8, PARAM_REG8, 0 },
4961 {"cmp", MODRM, PARAM_RM16, PARAM_REG16, 0 },
4962 {"cmp", MODRM, PARAM_REG8, PARAM_RM8, 0 },
4963 {"cmp", MODRM, PARAM_REG16, PARAM_RM16, 0 },
4964 {"cmp", 0, PARAM_AL, PARAM_UI8, 0 },
4965 {"cmp", 0, PARAM_AW, PARAM_IMM, 0 },
4966 {"ds0:", SEG_DS0, 0, 0, 0 },
4967 {"adjbs", 0, 0, 0, 0 },
4969 {"inc", 0, PARAM_AW, 0, 0 },
4970 {"inc", 0, PARAM_CW, 0, 0 },
4971 {"inc", 0, PARAM_DW, 0, 0 },
4972 {"inc", 0, PARAM_BW, 0, 0 },
4973 {"inc", 0, PARAM_SP, 0, 0 },
4974 {"inc", 0, PARAM_BP, 0, 0 },
4975 {"inc", 0, PARAM_IX, 0, 0 },
4976 {"inc", 0, PARAM_IY, 0, 0 },
4977 {"dec", 0, PARAM_AW, 0, 0 },
4978 {"dec", 0, PARAM_CW, 0, 0 },
4979 {"dec", 0, PARAM_DW, 0, 0 },
4980 {"dec", 0, PARAM_BW, 0, 0 },
4981 {"dec", 0, PARAM_SP, 0, 0 },
4982 {"dec", 0, PARAM_BP, 0, 0 },
4983 {"dec", 0, PARAM_IX, 0, 0 },
4984 {"dec", 0, PARAM_IY, 0, 0 },
4986 {"push", 0, PARAM_AW, 0, 0 },
4987 {"push", 0, PARAM_CW, 0, 0 },
4988 {"push", 0, PARAM_DW, 0, 0 },
4989 {"push", 0, PARAM_BW, 0, 0 },
4990 {"push", 0, PARAM_SP, 0, 0 },
4991 {"push", 0, PARAM_BP, 0, 0 },
4992 {"push", 0, PARAM_IX, 0, 0 },
4993 {"push", 0, PARAM_IY, 0, 0 },
4994 {"pop", 0, PARAM_AW, 0, 0 },
4995 {"pop", 0, PARAM_CW, 0, 0 },
4996 {"pop", 0, PARAM_DW, 0, 0 },
4997 {"pop", 0, PARAM_BW, 0, 0 },
4998 {"pop", 0, PARAM_SP, 0, 0 },
4999 {"pop", 0, PARAM_BP, 0, 0 },
5000 {"pop", 0, PARAM_IX, 0, 0 },
5001 {"pop", 0, PARAM_IY, 0, 0 },
5003 {"push r", 0, 0, 0, 0 },
5004 {"pop r", 0, 0, 0, 0 },
5005 {"chkind", MODRM, PARAM_REG16, PARAM_RM16, 0 },
5006 {"brkn", 0, PARAM_UI8, 0, 0, DASMFLAG_STEP_OVER}, /* V25S/V35S only */
5007 {"repnc", PREFIX, 0, 0, 0 },
5008 {"repc", PREFIX, 0, 0, 0 },
5009 {"fpo2 0", 0, 0, 0, 0 }, /* for a coprocessor that was never made */
5010 {"fpo2 1", 0, 0, 0, 0 }, /* for a coprocessor that was never made */
5011 {"push", 0, PARAM_IMM, 0, 0 },
5012 {"mul", MODRM, PARAM_REG16, PARAM_RM16, PARAM_IMM },
5013 {"push", 0, PARAM_I8, 0, 0 },
5014 {"mul", MODRM, PARAM_REG16, PARAM_RM16, PARAM_I8 },
5015 {"inmb", 0, 0, 0, 0 },
5016 {"inmw", 0, 0, 0, 0 },
5017 {"outmb", 0, 0, 0, 0 },
5018 {"outmw", 0, 0, 0, 0 },
5020 {"bv", 0, PARAM_REL8, 0, 0 },
5021 {"bnv", 0, PARAM_REL8, 0, 0 },
5022 {"bc", 0, PARAM_REL8, 0, 0 },
5023 {"bnc", 0, PARAM_REL8, 0, 0 },
5024 {"be", 0, PARAM_REL8, 0, 0 },
5025 {"bne", 0, PARAM_REL8, 0, 0 },
5026 {"bnh", 0, PARAM_REL8, 0, 0 },
5027 {"bh", 0, PARAM_REL8, 0, 0 },
5028 {"bn", 0, PARAM_REL8, 0, 0 },
5029 {"bp", 0, PARAM_REL8, 0, 0 },
5030 {"bpe", 0, PARAM_REL8, 0, 0 },
5031 {"bpo", 0, PARAM_REL8, 0, 0 },
5032 {"blt", 0, PARAM_REL8, 0, 0 },
5033 {"bge", 0, PARAM_REL8, 0, 0 },
5034 {"ble", 0, PARAM_REL8, 0, 0 },
5035 {"bgt", 0, PARAM_REL8, 0, 0 },
5037 {"immb", GROUP, 0, 0, 0 },
5038 {"immw", GROUP, 0, 0, 0 },
5039 {"immb", GROUP, 0, 0, 0 },
5040 {"immws", GROUP, 0, 0, 0 },
5041 {"test", MODRM, PARAM_RM8, PARAM_REG8, 0 },
5042 {"test", MODRM, PARAM_RM16, PARAM_REG16, 0 },
5043 {"xch", MODRM, PARAM_REG8, PARAM_RM8, 0 },
5044 {"xch", MODRM, PARAM_REG16, PARAM_RM16, 0 },
5045 {"mov", MODRM, PARAM_RM8, PARAM_REG8, 0 },
5046 {"mov", MODRM, PARAM_RM16, PARAM_REG16, 0 },
5047 {"mov", MODRM, PARAM_REG8, PARAM_RM8, 0 },
5048 {"mov", MODRM, PARAM_REG16, PARAM_RM16, 0 },
5049 {"mov", MODRM, PARAM_RM16, PARAM_SREG, 0 },
5050 {"ldea", MODRM, PARAM_REG16, PARAM_RM16, 0 },
5051 {"mov", MODRM, PARAM_SREG, PARAM_RM16, 0 },
5052 {"pop", MODRM, PARAM_RM16, 0, 0 },
5054 {"nop", 0, 0, 0, 0 },
5055 {"xch", 0, PARAM_AW, PARAM_CW, 0 },
5056 {"xch", 0, PARAM_AW, PARAM_DW, 0 },
5057 {"xch", 0, PARAM_AW, PARAM_BW, 0 },
5058 {"xch", 0, PARAM_AW, PARAM_SP, 0 },
5059 {"xch", 0, PARAM_AW, PARAM_BP, 0 },
5060 {"xch", 0, PARAM_AW, PARAM_IX, 0 },
5061 {"xch", 0, PARAM_AW, PARAM_IY, 0 },
5062 {"cvtbw", 0, 0, 0, 0 },
5063 {"cvtwl", 0, 0, 0, 0 },
5064 {"call", 0, PARAM_ADDR, 0, 0, DASMFLAG_STEP_OVER},
5065 {"poll", 0, 0, 0, 0 },
5066 {"push psw", 0, 0, 0, 0 },
5067 {"pop psw", 0, 0, 0, 0 },
5068 {"mov psw,ah", 0, 0, 0, 0 },
5069 {"mov ah,psw", 0, 0, 0, 0 },
5071 {"mov", 0, PARAM_AL, PARAM_MEM_OFFS, 0 },
5072 {"mov", 0, PARAM_AW, PARAM_MEM_OFFS, 0 },
5073 {"mov", 0, PARAM_MEM_OFFS, PARAM_AL, 0 },
5074 {"mov", 0, PARAM_MEM_OFFS, PARAM_AW, 0 },
5075 {"movbkb", 0, 0, 0, 0 },
5076 {"movbkw", 0, 0, 0, 0 },
5077 {"cmpbkb", 0, 0, 0, 0 },
5078 {"cmpbkw", 0, 0, 0, 0 },
5079 {"test", 0, PARAM_AL, PARAM_UI8, 0 },
5080 {"test", 0, PARAM_AW, PARAM_IMM, 0 },
5081 {"stmb", 0, 0, 0, 0 },
5082 {"stmw", 0, 0, 0, 0 },
5083 {"ldmb", 0, 0, 0, 0 },
5084 {"ldmw", 0, 0, 0, 0 },
5085 {"cmpmb", 0, 0, 0, 0 },
5086 {"cmpmw", 0, 0, 0, 0 },
5088 {"mov", 0, PARAM_AL, PARAM_UI8, 0 },
5089 {"mov", 0, PARAM_CL, PARAM_UI8, 0 },
5090 {"mov", 0, PARAM_DL, PARAM_UI8, 0 },
5091 {"mov", 0, PARAM_BL, PARAM_UI8, 0 },
5092 {"mov", 0, PARAM_AH, PARAM_UI8, 0 },
5093 {"mov", 0, PARAM_CH, PARAM_UI8, 0 },
5094 {"mov", 0, PARAM_DH, PARAM_UI8, 0 },
5095 {"mov", 0, PARAM_BH, PARAM_UI8, 0 },
5096 {"mov", 0, PARAM_AW, PARAM_IMM, 0 },
5097 {"mov", 0, PARAM_CW, PARAM_IMM, 0 },
5098 {"mov", 0, PARAM_DW, PARAM_IMM, 0 },
5099 {"mov", 0, PARAM_BW, PARAM_IMM, 0 },
5100 {"mov", 0, PARAM_SP, PARAM_IMM, 0 },
5101 {"mov", 0, PARAM_BP, PARAM_IMM, 0 },
5102 {"mov", 0, PARAM_IX, PARAM_IMM, 0 },
5103 {"mov", 0, PARAM_IY, PARAM_IMM, 0 },
5105 {"shiftbi", GROUP, 0, 0, 0 },
5106 {"shiftwi", GROUP, 0, 0, 0 },
5107 {"ret", 0, PARAM_I16, 0, 0, DASMFLAG_STEP_OUT},
5108 {"ret", 0, 0, 0, 0, DASMFLAG_STEP_OUT},
5109 {"mov ds1,", MODRM, PARAM_REG16, PARAM_RM16, 0 },
5110 {"mov ds0,", MODRM, PARAM_REG16, PARAM_RM16, 0 },
5111 {"mov", MODRM, PARAM_RMPTR8, PARAM_UI8, 0 },
5112 {"mov", MODRM, PARAM_RMPTR16, PARAM_IMM, 0 },
5113 {"prepare", 0, PARAM_I16, PARAM_UI8, 0 },
5114 {"dispose", 0, 0, 0, 0 },
5115 {"retf", 0, PARAM_I16, 0, 0, DASMFLAG_STEP_OUT},
5116 {"retf", 0, 0, 0, 0, DASMFLAG_STEP_OUT},
5117 {"brk 3", 0, 0, 0, 0, DASMFLAG_STEP_OVER},
5118 {"brk", 0, PARAM_UI8, 0, 0, DASMFLAG_STEP_OVER},
5119 {"brkv", 0, 0, 0, 0 },
5120 {"reti", 0, 0, 0, 0, DASMFLAG_STEP_OUT},
5122 {"shiftb", GROUP, 0, 0, 0 },
5123 {"shiftw", GROUP, 0, 0, 0 },
5124 {"shiftbv", GROUP, 0, 0, 0 },
5125 {"shiftwv", GROUP, 0, 0, 0 },
5126 {"cvtbd", 0, PARAM_I8, 0, 0 },
5127 {"cvtdb", 0, PARAM_I8, 0, 0 },
5128 {"???", 0, 0, 0, 0 },
5129 {"trans", 0, 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 },
5137 {"escape", FPU, 0, 0, 0 },
5139 {"dbnzne", 0, PARAM_REL8, 0, 0, DASMFLAG_STEP_OVER},
5140 {"dbnze", 0, PARAM_REL8, 0, 0, DASMFLAG_STEP_OVER},
5141 {"dbnz", 0, PARAM_REL8, 0, 0, DASMFLAG_STEP_OVER},
5142 {"bcwz", 0, PARAM_REL8, 0, 0 },
5143 {"in", 0, PARAM_AL, PARAM_UI8, 0 },
5144 {"in", 0, PARAM_AW, PARAM_UI8, 0 },
5145 {"out", 0, PARAM_UI8, PARAM_AL, 0 },
5146 {"out", 0, PARAM_UI8, PARAM_AW, 0 },
5147 {"call", 0, PARAM_REL16, 0, 0, DASMFLAG_STEP_OVER},
5148 {"br", 0, PARAM_REL16, 0, 0 },
5149 {"br", 0, PARAM_ADDR, 0, 0 },
5150 {"br", 0, PARAM_REL8, 0, 0 },
5151 {"in", 0, PARAM_AL, PARAM_DW, 0 },
5152 {"in", 0, PARAM_AW, PARAM_DW, 0 },
5153 {"out", 0, PARAM_DW, PARAM_AL, 0 },
5154 {"out", 0, PARAM_DW, PARAM_AW, 0 },
5156 {"buslock", PREFIX, 0, 0, 0 },
5157 {"brks", 0, PARAM_UI8, 0, 0, DASMFLAG_STEP_OVER}, /* V25S/V35S only */
5158 {"repne", PREFIX, 0, 0, 0 },
5159 {"rep", PREFIX, 0, 0, 0 },
5160 {"halt", 0, 0, 0, 0 },
5161 {"not1 cy", 0, 0, 0, 0 },
5162 {"group1b", GROUP, 0, 0, 0 },
5163 {"group1w", GROUP, 0, 0, 0 },
5164 {"clr1 cy", 0, 0, 0, 0 },
5165 {"set1 cy", 0, 0, 0, 0 },
5166 {"di", 0, 0, 0, 0 },
5167 {"ei", 0, 0, 0, 0 },
5168 {"clr1 dir", 0, 0, 0, 0 },
5169 {"set1 dir", 0, 0, 0, 0 },
5170 {"group2b", GROUP, 0, 0, 0 },
5171 {"group2w", GROUP, 0, 0, 0 }
5174 static const I386_OPCODE necv_opcode_table2[256] =
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 },
5192 {"???", 0, 0, 0, 0 },
5194 {"test1", MODRM, PARAM_RMPTR8, PARAM_CL, 0 },
5195 {"test1", MODRM, PARAM_RMPTR16, PARAM_CL, 0 },
5196 {"clr1", MODRM, PARAM_RMPTR8, PARAM_CL, 0 },
5197 {"clr1", MODRM, PARAM_RMPTR16, PARAM_CL, 0 },
5198 {"set1", MODRM, PARAM_RMPTR8, PARAM_CL, 0 },
5199 {"set1", MODRM, PARAM_RMPTR16, PARAM_CL, 0 },
5200 {"not1", MODRM, PARAM_RMPTR8, PARAM_CL, 0 },
5201 {"not1", MODRM, PARAM_RMPTR16, PARAM_CL, 0 },
5202 {"test1", MODRM, PARAM_RMPTR8, PARAM_I3, 0 },
5203 {"test1", MODRM, PARAM_RMPTR16, PARAM_I4, 0 },
5204 {"clr1", MODRM, PARAM_RMPTR8, PARAM_I3, 0 },
5205 {"clr1", MODRM, PARAM_RMPTR16, PARAM_I4, 0 },
5206 {"set1", MODRM, PARAM_RMPTR8, PARAM_I3, 0 },
5207 {"set1", MODRM, PARAM_RMPTR16, PARAM_I4, 0 },
5208 {"not1", MODRM, PARAM_RMPTR8, PARAM_I3, 0 },
5209 {"not1", MODRM, PARAM_RMPTR16, PARAM_I4, 0 },
5211 {"add4s", 0, 0, 0, 0 },
5212 {"???", 0, 0, 0, 0 },
5213 {"sub4s", 0, 0, 0, 0 },
5214 {"???", 0, 0, 0, 0 },
5215 {"???", 0, 0, 0, 0 },
5216 {"movspa", 0, 0, 0, 0 }, /* V25/V35 only */
5217 {"cmp4s", 0, 0, 0, 0 },
5218 {"???", 0, 0, 0, 0 },
5219 {"rol4", MODRM, PARAM_RMPTR8, 0, 0 },
5220 {"???", 0, 0, 0, 0 },
5221 {"ror4", MODRM, PARAM_RMPTR8, 0, 0 },
5222 {"???", 0, 0, 0, 0 },
5223 {"???", 0, 0, 0, 0 },
5224 {"brkcs", MODRM, PARAM_REG2_16, 0, 0, DASMFLAG_STEP_OVER}, /* V25/V35 only */
5225 {"???", 0, 0, 0, 0 },
5226 {"???", 0, 0, 0, 0 },
5228 {"???", 0, 0, 0, 0 },
5229 {"ins", MODRM, PARAM_REG2_8, PARAM_REG8, 0 },
5230 {"???", 0, 0, 0, 0 },
5231 {"ext", MODRM, PARAM_REG2_8, PARAM_REG8, 0 },
5232 {"???", 0, 0, 0, 0 },
5233 {"???", 0, 0, 0, 0 },
5234 {"???", 0, 0, 0, 0 },
5235 {"???", 0, 0, 0, 0 },
5236 {"???", 0, 0, 0, 0 },
5237 {"ins", MODRM, PARAM_REG2_8, PARAM_I4, 0 },
5238 {"???", 0, 0, 0, 0 },
5239 {"ext", MODRM, PARAM_REG2_8, PARAM_I4, 0 },
5240 {"???", 0, 0, 0, 0 },
5241 {"???", 0, 0, 0, 0 },
5242 {"???", 0, 0, 0, 0 },
5243 {"???", 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 },
5260 {"???", 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 },
5277 {"???", 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 },
5294 {"???", 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 },
5311 {"???", 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 },
5328 {"???", 0, 0, 0, 0 },
5330 {"???", 0, 0, 0, 0 },
5331 {"retrbi", 0, 0, 0, 0 }, /* V25/V35 only */
5332 {"fint", 0, 0, 0, 0 }, /* V25/V35 only */
5333 {"???", 0, 0, 0, 0 },
5334 {"tsksw", MODRM, PARAM_REG2_16, 0, 0 }, /* V25/V35 only */
5335 {"movspb", MODRM, PARAM_REG2_16, 0, 0 }, /* V25/V35 only */
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 {"???", 0, 0, 0, 0 },
5342 {"btclr", 0, PARAM_SFREG, PARAM_I3, PARAM_REL8 }, /* V25/V35 only */
5343 {"???", 0, 0, 0, 0 },
5344 {"stop", 0, 0, 0, 0 }, /* V25/V35 only */
5345 {"???", 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 },
5362 {"???", 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 },
5379 {"???", 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 },
5396 {"???", 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 },
5413 {"???", 0, 0, 0, 0 },
5415 {"brkxa", 0, PARAM_UI8, 0, 0 }, /* V33,53 only */
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 },
5430 {"???", 0, 0, 0, 0 },
5432 {"retxa", 0, PARAM_UI8, 0, 0 }, /* V33,53 only */
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 {"???", 0, 0, 0, 0 },
5447 {"brkem", 0, PARAM_UI8, 0, 0 } /* V20,30,40,50 only */
5450 static const I386_OPCODE immb_table[8] =
5452 {"add", 0, PARAM_RMPTR8, PARAM_UI8, 0 },
5453 {"or", 0, PARAM_RMPTR8, PARAM_UI8, 0 },
5454 {"addc", 0, PARAM_RMPTR8, PARAM_UI8, 0 },
5455 {"subc", 0, PARAM_RMPTR8, PARAM_UI8, 0 },
5456 {"and", 0, PARAM_RMPTR8, PARAM_UI8, 0 },
5457 {"sub", 0, PARAM_RMPTR8, PARAM_UI8, 0 },
5458 {"xor", 0, PARAM_RMPTR8, PARAM_UI8, 0 },
5459 {"cmp", 0, PARAM_RMPTR8, PARAM_UI8, 0 }
5462 static const I386_OPCODE immw_table[8] =
5464 {"add", 0, PARAM_RMPTR16, PARAM_IMM, 0 },
5465 {"or", 0, PARAM_RMPTR16, PARAM_IMM, 0 },
5466 {"addc", 0, PARAM_RMPTR16, PARAM_IMM, 0 },
5467 {"subc", 0, PARAM_RMPTR16, PARAM_IMM, 0 },
5468 {"and", 0, PARAM_RMPTR16, PARAM_IMM, 0 },
5469 {"sub", 0, PARAM_RMPTR16, PARAM_IMM, 0 },
5470 {"xor", 0, PARAM_RMPTR16, PARAM_IMM, 0 },
5471 {"cmp", 0, PARAM_RMPTR16, PARAM_IMM, 0 }
5474 static const I386_OPCODE immws_table[8] =
5476 {"add", 0, PARAM_RMPTR16, PARAM_I8, 0 },
5477 {"or", 0, PARAM_RMPTR16, PARAM_I8, 0 },
5478 {"addc", 0, PARAM_RMPTR16, PARAM_I8, 0 },
5479 {"subc", 0, PARAM_RMPTR16, PARAM_I8, 0 },
5480 {"and", 0, PARAM_RMPTR16, PARAM_I8, 0 },
5481 {"sub", 0, PARAM_RMPTR16, PARAM_I8, 0 },
5482 {"xor", 0, PARAM_RMPTR16, PARAM_I8, 0 },
5483 {"cmp", 0, PARAM_RMPTR16, PARAM_I8, 0 }
5486 static const I386_OPCODE shiftbi_table[8] =
5488 {"rol", 0, PARAM_RMPTR8, PARAM_I8, 0 },
5489 {"ror", 0, PARAM_RMPTR8, PARAM_I8, 0 },
5490 {"rolc", 0, PARAM_RMPTR8, PARAM_I8, 0 },
5491 {"rorc", 0, PARAM_RMPTR8, PARAM_I8, 0 },
5492 {"shl", 0, PARAM_RMPTR8, PARAM_I8, 0 },
5493 {"shr", 0, PARAM_RMPTR8, PARAM_I8, 0 },
5494 {"???", 0, PARAM_RMPTR8, PARAM_I8, 0 },
5495 {"shra", 0, PARAM_RMPTR8, PARAM_I8, 0 }
5498 static const I386_OPCODE shiftwi_table[8] =
5500 {"rol", 0, PARAM_RMPTR16, PARAM_I8, 0 },
5501 {"ror", 0, PARAM_RMPTR16, PARAM_I8, 0 },
5502 {"rolc", 0, PARAM_RMPTR16, PARAM_I8, 0 },
5503 {"rorc", 0, PARAM_RMPTR16, PARAM_I8, 0 },
5504 {"shl", 0, PARAM_RMPTR16, PARAM_I8, 0 },
5505 {"shr", 0, PARAM_RMPTR16, PARAM_I8, 0 },
5506 {"???", 0, PARAM_RMPTR16, PARAM_I8, 0 },
5507 {"shra", 0, PARAM_RMPTR16, PARAM_I8, 0 }
5510 static const I386_OPCODE shiftb_table[8] =
5512 {"rol", 0, PARAM_RMPTR8, PARAM_1, 0 },
5513 {"ror", 0, PARAM_RMPTR8, PARAM_1, 0 },
5514 {"rolc", 0, PARAM_RMPTR8, PARAM_1, 0 },
5515 {"rorc", 0, PARAM_RMPTR8, PARAM_1, 0 },
5516 {"shl", 0, PARAM_RMPTR8, PARAM_1, 0 },
5517 {"shr", 0, PARAM_RMPTR8, PARAM_1, 0 },
5518 {"???", 0, PARAM_RMPTR8, PARAM_1, 0 },
5519 {"shra", 0, PARAM_RMPTR8, PARAM_1, 0 }
5522 static const I386_OPCODE shiftw_table[8] =
5524 {"rol", 0, PARAM_RMPTR16, PARAM_1, 0 },
5525 {"ror", 0, PARAM_RMPTR16, PARAM_1, 0 },
5526 {"rolc", 0, PARAM_RMPTR16, PARAM_1, 0 },
5527 {"rorc", 0, PARAM_RMPTR16, PARAM_1, 0 },
5528 {"shl", 0, PARAM_RMPTR16, PARAM_1, 0 },
5529 {"shr", 0, PARAM_RMPTR16, PARAM_1, 0 },
5530 {"???", 0, PARAM_RMPTR16, PARAM_1, 0 },
5531 {"shra", 0, PARAM_RMPTR16, PARAM_1, 0 }
5534 static const I386_OPCODE shiftbv_table[8] =
5536 {"rol", 0, PARAM_RMPTR8, PARAM_CL, 0 },
5537 {"ror", 0, PARAM_RMPTR8, PARAM_CL, 0 },
5538 {"rolc", 0, PARAM_RMPTR8, PARAM_CL, 0 },
5539 {"rorc", 0, PARAM_RMPTR8, PARAM_CL, 0 },
5540 {"shl", 0, PARAM_RMPTR8, PARAM_CL, 0 },
5541 {"shr", 0, PARAM_RMPTR8, PARAM_CL, 0 },
5542 {"???", 0, PARAM_RMPTR8, PARAM_CL, 0 },
5543 {"shra", 0, PARAM_RMPTR8, PARAM_CL, 0 }
5546 static const I386_OPCODE shiftwv_table[8] =
5548 {"rol", 0, PARAM_RMPTR16, PARAM_CL, 0 },
5549 {"ror", 0, PARAM_RMPTR16, PARAM_CL, 0 },
5550 {"rolc", 0, PARAM_RMPTR16, PARAM_CL, 0 },
5551 {"rorc", 0, PARAM_RMPTR16, PARAM_CL, 0 },
5552 {"shl", 0, PARAM_RMPTR16, PARAM_CL, 0 },
5553 {"shr", 0, PARAM_RMPTR16, PARAM_CL, 0 },
5554 {"???", 0, PARAM_RMPTR16, PARAM_CL, 0 },
5555 {"shra", 0, PARAM_RMPTR16, PARAM_CL, 0 }
5558 static const I386_OPCODE group1b_table[8] =
5560 {"test", 0, PARAM_RMPTR8, PARAM_UI8, 0 },
5561 {"???", 0, 0, 0, 0 },
5562 {"not", 0, PARAM_RMPTR8, 0, 0 },
5563 {"neg", 0, PARAM_RMPTR8, 0, 0 },
5564 {"mulu", 0, PARAM_RMPTR8, 0, 0 },
5565 {"mul", 0, PARAM_RMPTR8, 0, 0 },
5566 {"divu", 0, PARAM_RMPTR8, 0, 0 },
5567 {"div", 0, PARAM_RMPTR8, 0, 0 }
5570 static const I386_OPCODE group1w_table[8] =
5572 {"test", 0, PARAM_RMPTR16, PARAM_IMM, 0 },
5573 {"???", 0, 0, 0, 0 },
5574 {"not", 0, PARAM_RMPTR16, 0, 0 },
5575 {"neg", 0, PARAM_RMPTR16, 0, 0 },
5576 {"mulu", 0, PARAM_RMPTR16, 0, 0 },
5577 {"mul", 0, PARAM_RMPTR16, 0, 0 },
5578 {"divu", 0, PARAM_RMPTR16, 0, 0 },
5579 {"div", 0, PARAM_RMPTR16, 0, 0 }
5582 static const I386_OPCODE group2b_table[8] =
5584 {"inc", 0, PARAM_RMPTR8, 0, 0 },
5585 {"dec", 0, PARAM_RMPTR8, 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 },
5591 {"???", 0, 0, 0, 0 }
5594 static const I386_OPCODE group2w_table[8] =
5596 {"inc", 0, PARAM_RMPTR16, 0, 0 },
5597 {"dec", 0, PARAM_RMPTR16, 0, 0 },
5598 {"call", 0, PARAM_RMPTR16, 0, 0, DASMFLAG_STEP_OVER},
5599 {"call far ptr ",0, PARAM_RM16, 0, 0, DASMFLAG_STEP_OVER},
5600 {"br", 0, PARAM_RMPTR16, 0, 0 },
5601 {"br far ptr ",0, PARAM_RM16, 0, 0 },
5602 {"push", 0, PARAM_RMPTR16, 0, 0 },
5603 {"???", 0, 0, 0, 0 }
5606 static const GROUP_OP group_op_table[] =
5608 { "immb", immb_table },
5609 { "immw", immw_table },
5610 { "immws", immws_table },
5611 { "shiftbi", shiftbi_table },
5612 { "shiftwi", shiftwi_table },
5613 { "shiftb", shiftb_table },
5614 { "shiftw", shiftw_table },
5615 { "shiftbv", shiftbv_table },
5616 { "shiftwv", shiftwv_table },
5617 { "group1b", group1b_table },
5618 { "group1w", group1w_table },
5619 { "group2b", group2b_table },
5620 { "group2w", group2w_table }
5625 static const char *const nec_reg[8] = { "aw", "cw", "dw", "bw", "sp", "bp", "ix", "iy" };
5626 static const char *const nec_reg8[8] = { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh" };
5627 static const char *const nec_sreg[8] = { "ds1", "ps", "ss", "ds0", "???", "???", "???", "???" };
5628 static const char *const nec_sfreg[256] =
5631 "p0", "pm0", "pmc0", "???", "???", "???", "???", "???",
5632 "p1", "pm1", "pmc1", "???", "???", "???", "???", "???",
5634 "p2", "pm2", "pmc2", "???", "???", "???", "???", "???",
5635 "???", "???", "???", "???", "???", "???", "???", "???",
5637 "???", "???", "???", "???", "???", "???", "???", "???",
5638 "???", "???", "???", "???", "???", "???", "???", "???",
5640 "???", "???", "???", "???", "???", "???", "???", "???",
5641 "pt", "???", "???", "pmt", "???", "???", "???", "???",
5643 "intm", "???", "???", "???", "ems0", "ems1", "ems2", "???",
5644 "???", "???", "???", "???", "exic0","exic1","exic2","???",
5646 "???", "???", "???", "???", "???", "???", "???", "???",
5647 "???", "???", "???", "???", "???", "???", "???", "???",
5649 "rxb0", "???", "txb0", "???", "???", "srms0","stms0","???",
5650 "scm0", "scc0", "brg0", "scs0", "seic0","sric0","stic0","???",
5652 "rxb1", "???", "txb1", "???", "???", "srms1","stms1","???",
5653 "scm1", "scc1", "brg1", "scs1", "seic1","sric1","stic1","???",
5655 "tm0", "???", "md0", "???", "???", "???", "???", "???",
5656 "tm1", "???", "md1", "???", "???", "???", "???", "???",
5658 "tmc0", "tmc1", "???", "???", "tmms0","tmms1","tmms2","???",
5659 "???", "???", "???", "???", "tmic0","tmic1","tmic2","???",
5661 "dmac0","dmam0","dmac1","dmam1","???", "???", "???", "???",
5662 "???", "???", "???", "???", "dic0", "dic1", "???", "???",
5664 "???", "???", "???", "???", "???", "???", "???", "???",
5665 "???", "???", "???", "???", "???", "???", "???", "???",
5667 "sar0l","sar0m","sar0h","???", "dar0l","dar0m","dar0h","???",
5668 "tc0l", "tc0h", "???", "???", "???", "???", "???", "???",
5670 "sar1l","sar1m","sar1h","???", "dar1l","dar1m","dar1h","???",
5671 "tc1l", "tc1h", "???", "???", "???", "???", "???", "???",
5673 "stbc", "rfm", "???", "???", "???", "???", "???", "???",
5674 "wtc", "???", "flag", "prc", "tbic", "???", "???", "irqs",
5676 "???", "???", "???", "???", "???", "???", "???", "???",
5677 "???", "???", "???", "???", "ispr", "???", "???", "idb"
5682 static UINT32 segment;
5683 static offs_t dasm_flags;
5684 static char modrm_string[256];
5686 #define MODRM_REG1 ((modrm >> 3) & 0x7)
5687 #define MODRM_REG2 (modrm & 0x7)
5689 #define MAX_LENGTH 8
5691 INLINE UINT8 FETCHD(void)
5693 if ((opcode_ptr - opcode_ptr_base) + 1 > MAX_LENGTH)
5696 return *opcode_ptr++;
5699 INLINE UINT16 FETCHD16(void)
5702 if ((opcode_ptr - opcode_ptr_base) + 2 > MAX_LENGTH)
5704 d = opcode_ptr[0] | (opcode_ptr[1] << 8);
5710 static char *hexstring(UINT32 value, int digits)
5712 static char buffer[20];
5715 sprintf(&buffer[1], "%0*Xh", digits, value);
5717 sprintf(&buffer[1], "%Xh", value);
5719 return (buffer[1] >= '0' && buffer[1] <= '9') ? &buffer[1] : &buffer[0];
5722 static char *shexstring(UINT32 value, int digits, int always)
5724 static char buffer[20];
5725 if (value >= 0x80000000) {
5726 sprintf(buffer, "-%s", hexstring(-value, digits));
5727 } else if (always) {
5728 sprintf(buffer, "+%s", hexstring(value, digits));
5730 return hexstring(value, digits);
5735 static void handle_modrm(char* s)
5742 mod = (modrm >> 6) & 0x3;
5750 case SEG_PS: s += sprintf( s, "ps:" ); break;
5751 case SEG_DS0: s += sprintf( s, "ds0:" ); break;
5752 case SEG_DS1: s += sprintf( s, "ds1:" ); break;
5753 case SEG_SS: s += sprintf( s, "ss:" ); break;
5756 s += sprintf( s, "[" );
5759 case 0: s += sprintf( s, "bw+ix" ); break;
5760 case 1: s += sprintf( s, "bw+iy" ); break;
5761 case 2: s += sprintf( s, "bp+ix" ); break;
5762 case 3: s += sprintf( s, "bp+iy" ); break;
5763 case 4: s += sprintf( s, "ix" ); break;
5764 case 5: s += sprintf( s, "iy" ); break;
5767 disp16 = FETCHD16();
5768 s += sprintf( s, "%s", hexstring((unsigned) (UINT16) disp16, 0) );
5770 s += sprintf( s, "bp" );
5773 case 7: s += sprintf( s, "bw" ); break;
5777 s += sprintf( s, "%s", shexstring((INT32)disp8, 0, TRUE) );
5778 } else if( mod == 2 ) {
5779 disp16 = FETCHD16();
5780 s += sprintf( s, "%s", shexstring((INT32)disp16, 0, TRUE) );
5782 s += sprintf( s, "]" );
5785 static char* handle_param(char* s, UINT32 param)
5797 s += sprintf( s, "%s", nec_reg8[MODRM_REG1] );
5801 s += sprintf( s, "%s", nec_reg[MODRM_REG1] );
5805 s += sprintf( s, "%s", nec_reg8[MODRM_REG2] );
5809 s += sprintf( s, "%s", nec_reg[MODRM_REG2] );
5814 if( modrm >= 0xc0 ) {
5815 s += sprintf( s, "%s", nec_reg8[MODRM_REG2] );
5817 if (param == PARAM_RMPTR8)
5818 s += sprintf( s, "byte ptr " );
5819 s += sprintf( s, "%s", modrm_string );
5825 if( modrm >= 0xc0 ) {
5826 s += sprintf( s, "%s", nec_reg[MODRM_REG2] );
5828 if (param == PARAM_RMPTR16)
5829 s += sprintf( s, "word ptr " );
5830 s += sprintf( s, "%s", modrm_string );
5836 s += sprintf( s, "%d", i8 & 0x07 );
5841 s += sprintf( s, "%d", i8 & 0x0f );
5846 s += sprintf( s, "%s", shexstring((INT8)i8, 0, FALSE) );
5851 s += sprintf( s, "%s", shexstring((INT16)i16, 0, FALSE) );
5856 s += sprintf( s, "%s", shexstring((UINT8)i8, 0, FALSE) );
5861 s += sprintf( s, "%s", hexstring(i16, 0) );
5867 s += sprintf( s, "%s:", hexstring(ptr, 4) );
5868 s += sprintf( s, "%s", hexstring(addr, 0) );
5872 /* make sure to keep the relative offset within the segment */
5874 s += sprintf( s, "%s", hexstring((pc & 0xFFFF0000) | ((pc + d16) & 0x0000FFFF), 0) );
5879 s += sprintf( s, "%s", hexstring(pc + d8, 0) );
5882 case PARAM_MEM_OFFS:
5885 case SEG_PS: s += sprintf( s, "ps:" ); break;
5886 case SEG_DS0: s += sprintf( s, "ds0:" ); break;
5887 case SEG_DS1: s += sprintf( s, "ds1:" ); break;
5888 case SEG_SS: s += sprintf( s, "ss:" ); break;
5892 s += sprintf( s, "[%s]", hexstring(i16, 0) );
5896 s += sprintf( s, "%s", nec_sreg[MODRM_REG1] );
5901 s += sprintf( s, "%s", nec_sfreg[i8] );
5905 s += sprintf( s, "1" );
5908 case PARAM_AL: s += sprintf( s, "al" ); break;
5909 case PARAM_CL: s += sprintf( s, "cl" ); break;
5910 case PARAM_DL: s += sprintf( s, "dl" ); break;
5911 case PARAM_BL: s += sprintf( s, "bl" ); break;
5912 case PARAM_AH: s += sprintf( s, "ah" ); break;
5913 case PARAM_CH: s += sprintf( s, "ch" ); break;
5914 case PARAM_DH: s += sprintf( s, "dh" ); break;
5915 case PARAM_BH: s += sprintf( s, "bh" ); break;
5917 case PARAM_AW: s += sprintf( s, "aw" ); break;
5918 case PARAM_CW: s += sprintf( s, "cw" ); break;
5919 case PARAM_DW: s += sprintf( s, "dw" ); break;
5920 case PARAM_BW: s += sprintf( s, "bw" ); break;
5921 case PARAM_SP: s += sprintf( s, "sp" ); break;
5922 case PARAM_BP: s += sprintf( s, "bp" ); break;
5923 case PARAM_IX: s += sprintf( s, "ix" ); break;
5924 case PARAM_IY: s += sprintf( s, "iy" ); break;
5929 static void handle_fpu(char *s, UINT8 op1, UINT8 op2)
5937 pc--; // adjust fetch pointer, so modrm byte read again
5939 handle_modrm( modrm_string );
5940 switch ((op2 >> 3) & 0x7)
5942 case 0: sprintf(s, "fadd dword ptr %s", modrm_string); break;
5943 case 1: sprintf(s, "fmul dword ptr %s", modrm_string); break;
5944 case 2: sprintf(s, "fcom dword ptr %s", modrm_string); break;
5945 case 3: sprintf(s, "fcomp dword ptr %s", modrm_string); break;
5946 case 4: sprintf(s, "fsub dword ptr %s", modrm_string); break;
5947 case 5: sprintf(s, "fsubr dword ptr %s", modrm_string); break;
5948 case 6: sprintf(s, "fdiv dword ptr %s", modrm_string); break;
5949 case 7: sprintf(s, "fdivr dword ptr %s", modrm_string); break;
5952 switch ((op2 >> 3) & 0x7)
5954 case 0: sprintf(s, "fadd st(0),st(%d)", op2 & 0x7); break;
5955 case 1: sprintf(s, "fcom st(0),st(%d)", op2 & 0x7); break;
5956 case 2: sprintf(s, "fsub st(0),st(%d)", op2 & 0x7); break;
5957 case 3: sprintf(s, "fdiv st(0),st(%d)", op2 & 0x7); break;
5958 case 4: sprintf(s, "fmul st(0),st(%d)", op2 & 0x7); break;
5959 case 5: sprintf(s, "fcomp st(0),st(%d)", op2 & 0x7); break;
5960 case 6: sprintf(s, "fsubr st(0),st(%d)", op2 & 0x7); break;
5961 case 7: sprintf(s, "fdivr st(0),st(%d)", op2 & 0x7); break;
5971 pc--; // adjust fetch pointer, so modrm byte read again
5973 handle_modrm( modrm_string );
5974 switch ((op2 >> 3) & 0x7)
5976 case 0: sprintf(s, "fld dword ptr %s", modrm_string); break;
5977 case 1: sprintf(s, "??? (FPU)"); break;
5978 case 2: sprintf(s, "fst dword ptr %s", modrm_string); break;
5979 case 3: sprintf(s, "fstp dword ptr %s", modrm_string); break;
5980 case 4: sprintf(s, "fldenv word ptr %s", modrm_string); break;
5981 case 5: sprintf(s, "fldcw word ptr %s", modrm_string); break;
5982 case 6: sprintf(s, "fstenv word ptr %s", modrm_string); break;
5983 case 7: sprintf(s, "fstcw word ptr %s", modrm_string); break;
5988 case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
5989 sprintf(s, "fld st(0),st(%d)", op2 & 0x7); break;
5991 case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
5992 sprintf(s, "fxch st(0),st(%d)", op2 & 0x7); break;
5994 case 0x10: sprintf(s, "fnop"); break;
5995 case 0x20: sprintf(s, "fchs"); break;
5996 case 0x21: sprintf(s, "fabs"); break;
5997 case 0x24: sprintf(s, "ftst"); break;
5998 case 0x25: sprintf(s, "fxam"); break;
5999 case 0x28: sprintf(s, "fld1"); break;
6000 case 0x29: sprintf(s, "fldl2t"); break;
6001 case 0x2a: sprintf(s, "fldl2e"); break;
6002 case 0x2b: sprintf(s, "fldpi"); break;
6003 case 0x2c: sprintf(s, "fldlg2"); break;
6004 case 0x2d: sprintf(s, "fldln2"); break;
6005 case 0x2e: sprintf(s, "fldz"); break;
6006 case 0x30: sprintf(s, "f2xm1"); break;
6007 case 0x31: sprintf(s, "fyl2x"); break;
6008 case 0x32: sprintf(s, "fptan"); break;
6009 case 0x33: sprintf(s, "fpatan"); break;
6010 case 0x34: sprintf(s, "fxtract"); break;
6011 case 0x35: sprintf(s, "fprem1"); break;
6012 case 0x36: sprintf(s, "fdecstp"); break;
6013 case 0x37: sprintf(s, "fincstp"); break;
6014 case 0x38: sprintf(s, "fprem"); break;
6015 case 0x39: sprintf(s, "fyl2xp1"); break;
6016 case 0x3a: sprintf(s, "fsqrt"); break;
6017 case 0x3b: sprintf(s, "fsincos"); break;
6018 case 0x3c: sprintf(s, "frndint"); break;
6019 case 0x3d: sprintf(s, "fscale"); break;
6020 case 0x3e: sprintf(s, "fsin"); break;
6021 case 0x3f: sprintf(s, "fcos"); break;
6023 default: sprintf(s, "??? (FPU)"); break;
6033 pc--; // adjust fetch pointer, so modrm byte read again
6035 handle_modrm( modrm_string );
6036 switch ((op2 >> 3) & 0x7)
6038 case 0: sprintf(s, "fiadd dword ptr %s", modrm_string); break;
6039 case 1: sprintf(s, "fimul dword ptr %s", modrm_string); break;
6040 case 2: sprintf(s, "ficom dword ptr %s", modrm_string); break;
6041 case 3: sprintf(s, "ficomp dword ptr %s", modrm_string); break;
6042 case 4: sprintf(s, "fisub dword ptr %s", modrm_string); break;
6043 case 5: sprintf(s, "fisubr dword ptr %s", modrm_string); break;
6044 case 6: sprintf(s, "fidiv dword ptr %s", modrm_string); break;
6045 case 7: sprintf(s, "fidivr dword ptr %s", modrm_string); break;
6050 case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
6051 sprintf(s, "fcmovb st(0),st(%d)", op2 & 0x7); break;
6053 case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
6054 sprintf(s, "fcmove st(0),st(%d)", op2 & 0x7); break;
6056 case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
6057 sprintf(s, "fcmovbe st(0),st(%d)", op2 & 0x7); break;
6059 case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
6060 sprintf(s, "fcmovu st(0),st(%d)", op2 & 0x7); break;
6062 default: sprintf(s, "??? (FPU)"); break;
6073 pc--; // adjust fetch pointer, so modrm byte read again
6075 handle_modrm( modrm_string );
6076 switch ((op2 >> 3) & 0x7)
6078 case 0: sprintf(s, "fild dword ptr %s", modrm_string); break;
6079 case 1: sprintf(s, "??? (FPU)"); break;
6080 case 2: sprintf(s, "fist dword ptr %s", modrm_string); break;
6081 case 3: sprintf(s, "fistp dword ptr %s", modrm_string); break;
6082 case 4: sprintf(s, "??? (FPU)"); break;
6083 case 5: sprintf(s, "fld tword ptr %s", modrm_string); break;
6084 case 6: sprintf(s, "??? (FPU)"); break;
6085 case 7: sprintf(s, "fstp tword ptr %s", modrm_string); break;
6090 case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
6091 sprintf(s, "fcmovnb st(0),st(%d)", op2 & 0x7); break;
6093 case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
6094 sprintf(s, "fcmovne st(0),st(%d)", op2 & 0x7); break;
6096 case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
6097 sprintf(s, "fcmovnbe st(0),st(%d)", op2 & 0x7); break;
6099 case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
6100 sprintf(s, "fcmovnu st(0),st(%d)", op2 & 0x7); break;
6102 case 0x22: sprintf(s, "fclex"); break;
6103 case 0x23: sprintf(s, "finit"); break;
6105 case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
6106 sprintf(s, "fucomi st(0),st(%d)", op2 & 0x7); break;
6108 case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
6109 sprintf(s, "fcomi st(0),st(%d)", op2 & 0x7); break;
6111 default: sprintf(s, "??? (FPU)"); break;
6121 pc--; // adjust fetch pointer, so modrm byte read again
6123 handle_modrm( modrm_string );
6124 switch ((op2 >> 3) & 0x7)
6126 case 0: sprintf(s, "fadd qword ptr %s", modrm_string); break;
6127 case 1: sprintf(s, "fmul qword ptr %s", modrm_string); break;
6128 case 2: sprintf(s, "fcom qword ptr %s", modrm_string); break;
6129 case 3: sprintf(s, "fcomp qword ptr %s", modrm_string); break;
6130 case 4: sprintf(s, "fsub qword ptr %s", modrm_string); break;
6131 case 5: sprintf(s, "fsubr qword ptr %s", modrm_string); break;
6132 case 6: sprintf(s, "fdiv qword ptr %s", modrm_string); break;
6133 case 7: sprintf(s, "fdivr qword ptr %s", modrm_string); break;
6138 case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
6139 sprintf(s, "fadd st(%d),st(0)", op2 & 0x7); break;
6141 case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
6142 sprintf(s, "fmul st(%d),st(0)", op2 & 0x7); break;
6144 case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
6145 sprintf(s, "fsubr st(%d),st(0)", op2 & 0x7); break;
6147 case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
6148 sprintf(s, "fsub st(%d),st(0)", op2 & 0x7); break;
6150 case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
6151 sprintf(s, "fdivr st(%d),st(0)", op2 & 0x7); break;
6153 case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
6154 sprintf(s, "fdiv st(%d),st(0)", op2 & 0x7); break;
6156 default: sprintf(s, "??? (FPU)"); break;
6166 pc--; // adjust fetch pointer, so modrm byte read again
6168 handle_modrm( modrm_string );
6169 switch ((op2 >> 3) & 0x7)
6171 case 0: sprintf(s, "fld qword ptr %s", modrm_string); break;
6172 case 1: sprintf(s, "??? (FPU)"); break;
6173 case 2: sprintf(s, "fst qword ptr %s", modrm_string); break;
6174 case 3: sprintf(s, "fstp qword ptr %s", modrm_string); break;
6175 case 4: sprintf(s, "frstor %s", modrm_string); break;
6176 case 5: sprintf(s, "??? (FPU)"); break;
6177 case 6: sprintf(s, "fsave %s", modrm_string); break;
6178 case 7: sprintf(s, "fstsw word ptr %s", modrm_string); break;
6183 case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
6184 sprintf(s, "ffree st(%d)", op2 & 0x7); break;
6186 case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
6187 sprintf(s, "fst st(%d)", op2 & 0x7); break;
6189 case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
6190 sprintf(s, "fstp st(%d)", op2 & 0x7); break;
6192 case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
6193 sprintf(s, "fucom st(%d), st(0)", op2 & 0x7); break;
6195 case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
6196 sprintf(s, "fucomp st(%d)", op2 & 0x7); break;
6198 default: sprintf(s, "??? (FPU)"); break;
6208 pc--; // adjust fetch pointer, so modrm byte read again
6210 handle_modrm( modrm_string );
6211 switch ((op2 >> 3) & 0x7)
6213 case 0: sprintf(s, "fiadd word ptr %s", modrm_string); break;
6214 case 1: sprintf(s, "fimul word ptr %s", modrm_string); break;
6215 case 2: sprintf(s, "ficom word ptr %s", modrm_string); break;
6216 case 3: sprintf(s, "ficomp word ptr %s", modrm_string); break;
6217 case 4: sprintf(s, "fisub word ptr %s", modrm_string); break;
6218 case 5: sprintf(s, "fisubr word ptr %s", modrm_string); break;
6219 case 6: sprintf(s, "fidiv word ptr %s", modrm_string); break;
6220 case 7: sprintf(s, "fidivr word ptr %s", modrm_string); break;
6225 case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
6226 sprintf(s, "faddp st(%d)", op2 & 0x7); break;
6228 case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
6229 sprintf(s, "fmulp st(%d)", op2 & 0x7); break;
6231 case 0x19: sprintf(s, "fcompp"); break;
6233 case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
6234 sprintf(s, "fsubrp st(%d)", op2 & 0x7); break;
6236 case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
6237 sprintf(s, "fsubp st(%d)", op2 & 0x7); break;
6239 case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
6240 sprintf(s, "fdivrp st(%d), st(0)", op2 & 0x7); break;
6242 case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
6243 sprintf(s, "fdivp st(%d)", op2 & 0x7); break;
6245 default: sprintf(s, "??? (FPU)"); break;
6255 pc--; // adjust fetch pointer, so modrm byte read again
6257 handle_modrm( modrm_string );
6258 switch ((op2 >> 3) & 0x7)
6260 case 0: sprintf(s, "fild word ptr %s", modrm_string); break;
6261 case 1: sprintf(s, "??? (FPU)"); break;
6262 case 2: sprintf(s, "fist word ptr %s", modrm_string); break;
6263 case 3: sprintf(s, "fistp word ptr %s", modrm_string); break;
6264 case 4: sprintf(s, "fbld %s", modrm_string); break;
6265 case 5: sprintf(s, "fild qword ptr %s", modrm_string); break;
6266 case 6: sprintf(s, "fbstp %s", modrm_string); break;
6267 case 7: sprintf(s, "fistp qword ptr %s", modrm_string); break;
6272 case 0x20: sprintf(s, "fstsw aw"); break;
6274 case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
6275 sprintf(s, "fucomip st(%d)", op2 & 0x7); break;
6277 case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
6278 sprintf(s, "fcomip st(%d),st(0)", op2 & 0x7); break;
6280 default: sprintf(s, "??? (FPU)"); break;
6288 static void decode_opcode(char *s, const I386_OPCODE *op, UINT8 op1 )
6297 decode_opcode( s, &necv_opcode_table2[op2], op1 );
6304 segment = op->flags;
6306 decode_opcode( s, &necv_opcode_table1[op2], op1 );
6310 s += sprintf( s, "%-8s", op->mnemonic );
6312 decode_opcode( s, &necv_opcode_table1[op2], op1 );
6316 handle_modrm( modrm_string );
6317 for( i=0; i < ARRAY_LENGTH(group_op_table); i++ ) {
6318 if( strcmp(op->mnemonic, group_op_table[i].mnemonic) == 0 )
6320 decode_opcode( s, &group_op_table[i].opcode[MODRM_REG1], op1 );
6324 goto handle_unknown;
6328 handle_fpu( s, op1, op2);
6332 handle_modrm( modrm_string );
6336 s += sprintf( s, "%-8s", op->mnemonic );
6337 dasm_flags = op->dasm_flags;
6339 if( op->param1 != 0 ) {
6340 s = handle_param( s, op->param1 );
6343 if( op->param2 != 0 ) {
6344 s += sprintf( s, "," );
6345 s = handle_param( s, op->param2 );
6348 if( op->param3 != 0 ) {
6349 s += sprintf( s, "," );
6350 s = handle_param( s, op->param3 );
6358 int necv_dasm_one(char *buffer, UINT32 eip, const UINT8 *oprom)
6362 opcode_ptr = opcode_ptr_base = oprom;
6369 decode_opcode( buffer, &necv_opcode_table1[op], op );
6370 return (pc-eip) | dasm_flags | DASMFLAG_SUPPORTED;
6373 #define STATE_VERSION 1
6375 void I86::save_state(FILEIO* state_fio)
6377 state_fio->FputUint32(STATE_VERSION);
6378 state_fio->FputInt32(this_device_id);
6380 state_fio->Fwrite(®s, sizeof(regs), 1);
6381 state_fio->FputUint32(pc);
6382 state_fio->FputUint32(prevpc);
6383 state_fio->Fwrite(base, sizeof(base), 1);
6384 state_fio->Fwrite(sregs, sizeof(sregs), 1);
6385 state_fio->FputUint16(flags);
6386 state_fio->FputInt32(AuxVal);
6387 state_fio->FputInt32(OverVal);
6388 state_fio->FputInt32(SignVal);
6389 state_fio->FputInt32(ZeroVal);
6390 state_fio->FputInt32(CarryVal);
6391 state_fio->FputInt32(DirVal);
6392 state_fio->FputUint8(ParityVal);
6393 state_fio->FputUint8(TF);
6394 state_fio->FputUint8(IF);
6395 state_fio->FputUint8(MF);
6396 state_fio->FputInt32(int_state);
6397 state_fio->FputBool(test_state);
6398 state_fio->FputBool(busreq);
6399 state_fio->FputBool(halted);
6400 state_fio->FputInt32(icount);
6401 state_fio->FputInt32(extra_icount);
6402 state_fio->FputBool(seg_prefix);
6403 state_fio->FputUint8(prefix_seg);
6404 state_fio->FputUint32(ea);
6405 state_fio->FputUint16(eo);
6406 state_fio->FputUint8(ea_seg);
6409 bool I86::load_state(FILEIO* state_fio)
6411 if(state_fio->FgetUint32() != STATE_VERSION) {
6414 if(state_fio->FgetInt32() != this_device_id) {
6417 state_fio->Fread(®s, sizeof(regs), 1);
6418 pc = state_fio->FgetUint32();
6419 prevpc = state_fio->FgetUint32();
6420 state_fio->Fread(base, sizeof(base), 1);
6421 state_fio->Fread(sregs, sizeof(sregs), 1);
6422 flags = state_fio->FgetUint16();
6423 AuxVal = state_fio->FgetInt32();
6424 OverVal = state_fio->FgetInt32();
6425 SignVal = state_fio->FgetInt32();
6426 ZeroVal = state_fio->FgetInt32();
6427 CarryVal = state_fio->FgetInt32();
6428 DirVal = state_fio->FgetInt32();
6429 ParityVal = state_fio->FgetUint8();
6430 TF = state_fio->FgetUint8();
6431 IF = state_fio->FgetUint8();
6432 MF = state_fio->FgetUint8();
6433 int_state = state_fio->FgetInt32();
6434 test_state = state_fio->FgetBool();
6435 busreq = state_fio->FgetBool();
6436 halted = state_fio->FgetBool();
6437 icount = state_fio->FgetInt32();
6438 extra_icount = state_fio->FgetInt32();
6439 seg_prefix = state_fio->FgetBool();
6440 prefix_seg = state_fio->FgetUint8();
6441 ea = state_fio->FgetUint32();
6442 eo = state_fio->FgetUint16();
6443 ea_seg = state_fio->FgetUint8();