]>
Commit | Line | Data |
---|---|---|
ece92f85 JJ |
1 | /**************************************************************************** |
2 | * Realmode X86 Emulator Library | |
3 | * | |
4c2e3da8 | 4 | * Copyright (C) 2007 Freescale Semiconductor, Inc. |
ece92f85 JJ |
5 | * Jason Jin <Jason.jin@freescale.com> |
6 | * | |
9c7e4b06 WD |
7 | * Copyright (C) 1991-2004 SciTech Software, Inc. |
8 | * Copyright (C) David Mosberger-Tang | |
9 | * Copyright (C) 1999 Egbert Eich | |
ece92f85 JJ |
10 | * |
11 | * ======================================================================== | |
12 | * | |
13 | * Permission to use, copy, modify, distribute, and sell this software and | |
14 | * its documentation for any purpose is hereby granted without fee, | |
15 | * provided that the above copyright notice appear in all copies and that | |
16 | * both that copyright notice and this permission notice appear in | |
17 | * supporting documentation, and that the name of the authors not be used | |
18 | * in advertising or publicity pertaining to distribution of the software | |
9c7e4b06 | 19 | * without specific, written prior permission. The authors makes no |
ece92f85 JJ |
20 | * representations about the suitability of this software for any purpose. |
21 | * It is provided "as is" without express or implied warranty. | |
22 | * | |
23 | * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | |
24 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | |
25 | * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR | |
26 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF | |
27 | * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR | |
28 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | |
29 | * PERFORMANCE OF THIS SOFTWARE. | |
30 | * | |
31 | * ======================================================================== | |
32 | * | |
33 | * Language: ANSI C | |
34 | * Environment: Any | |
9c7e4b06 | 35 | * Developer: Kendall Bennett |
ece92f85 | 36 | * |
9c7e4b06 WD |
37 | * Description: This file includes subroutines to implement the decoding |
38 | * and emulation of all the x86 processor instructions. | |
ece92f85 JJ |
39 | * |
40 | * There are approximately 250 subroutines in here, which correspond | |
9c7e4b06 | 41 | * to the 256 byte-"opcodes" found on the 8086. The table which |
ece92f85 JJ |
42 | * dispatches this is found in the files optab.[ch]. |
43 | * | |
fc0b5948 | 44 | * Each opcode proc has a comment preceding it which gives it's table |
ece92f85 JJ |
45 | * address. Several opcodes are missing (undefined) in the table. |
46 | * | |
47 | * Each proc includes information for decoding (DECODE_PRINTF and | |
48 | * DECODE_PRINTF2), debugging (TRACE_REGS, SINGLE_STEP), and misc | |
49 | * functions (START_OF_INSTR, END_OF_INSTR). | |
50 | * | |
9c7e4b06 | 51 | * Many of the procedures are *VERY* similar in coding. This has |
ece92f85 JJ |
52 | * allowed for a very large amount of code to be generated in a fairly |
53 | * short amount of time (i.e. cut, paste, and modify). The result is | |
54 | * that much of the code below could have been folded into subroutines | |
55 | * for a large reduction in size of this file. The downside would be | |
56 | * that there would be a penalty in execution speed. The file could | |
57 | * also have been *MUCH* larger by inlining certain functions which | |
9c7e4b06 | 58 | * were called. This could have resulted even faster execution. The |
ece92f85 JJ |
59 | * prime directive I used to decide whether to inline the code or to |
60 | * modularize it, was basically: 1) no unnecessary subroutine calls, | |
61 | * 2) no routines more than about 200 lines in size, and 3) modularize | |
62 | * any code that I might not get right the first time. The fetch_* | |
63 | * subroutines fall into the latter category. The The decode_* fall | |
64 | * into the second category. The coding of the "switch(mod){ .... }" | |
65 | * in many of the subroutines below falls into the first category. | |
66 | * Especially, the coding of {add,and,or,sub,...}_{byte,word} | |
67 | * subroutines are an especially glaring case of the third guideline. | |
68 | * Since so much of the code is cloned from other modules (compare | |
69 | * opcode #00 to opcode #01), making the basic operations subroutine | |
70 | * calls is especially important; otherwise mistakes in coding an | |
71 | * "add" would represent a nightmare in maintenance. | |
72 | * | |
ece92f85 JJ |
73 | ****************************************************************************/ |
74 | ||
d678a59d | 75 | #include <common.h> |
1e94b46f | 76 | #include <linux/printk.h> |
5b4de930 MS |
77 | #include "x86emu/x86emui.h" |
78 | ||
ece92f85 JJ |
79 | /*----------------------------- Implementation ----------------------------*/ |
80 | ||
81 | /* constant arrays to do several instructions in just one function */ | |
82 | ||
b3521f2e | 83 | #ifdef CONFIG_X86EMU_DEBUG |
ece92f85 JJ |
84 | static char *x86emu_GenOpName[8] = { |
85 | "ADD", "OR", "ADC", "SBB", "AND", "SUB", "XOR", "CMP"}; | |
86 | #endif | |
87 | ||
88 | /* used by several opcodes */ | |
285870f7 | 89 | static u8 (*genop_byte_operation[])(u8 d, u8 s) = |
ece92f85 | 90 | { |
9c7e4b06 WD |
91 | add_byte, /* 00 */ |
92 | or_byte, /* 01 */ | |
93 | adc_byte, /* 02 */ | |
94 | sbb_byte, /* 03 */ | |
95 | and_byte, /* 04 */ | |
96 | sub_byte, /* 05 */ | |
97 | xor_byte, /* 06 */ | |
98 | cmp_byte, /* 07 */ | |
ece92f85 JJ |
99 | }; |
100 | ||
285870f7 | 101 | static u16 (*genop_word_operation[])(u16 d, u16 s) = |
ece92f85 | 102 | { |
9c7e4b06 WD |
103 | add_word, /*00 */ |
104 | or_word, /*01 */ | |
105 | adc_word, /*02 */ | |
106 | sbb_word, /*03 */ | |
107 | and_word, /*04 */ | |
108 | sub_word, /*05 */ | |
109 | xor_word, /*06 */ | |
110 | cmp_word, /*07 */ | |
ece92f85 JJ |
111 | }; |
112 | ||
285870f7 | 113 | static u32 (*genop_long_operation[])(u32 d, u32 s) = |
ece92f85 | 114 | { |
9c7e4b06 WD |
115 | add_long, /*00 */ |
116 | or_long, /*01 */ | |
117 | adc_long, /*02 */ | |
118 | sbb_long, /*03 */ | |
119 | and_long, /*04 */ | |
120 | sub_long, /*05 */ | |
121 | xor_long, /*06 */ | |
122 | cmp_long, /*07 */ | |
ece92f85 JJ |
123 | }; |
124 | ||
125 | /* used by opcodes 80, c0, d0, and d2. */ | |
285870f7 | 126 | static u8(*opcD0_byte_operation[])(u8 d, u8 s) = |
ece92f85 JJ |
127 | { |
128 | rol_byte, | |
129 | ror_byte, | |
130 | rcl_byte, | |
131 | rcr_byte, | |
132 | shl_byte, | |
133 | shr_byte, | |
9c7e4b06 | 134 | shl_byte, /* sal_byte === shl_byte by definition */ |
ece92f85 JJ |
135 | sar_byte, |
136 | }; | |
137 | ||
138 | /* used by opcodes c1, d1, and d3. */ | |
285870f7 | 139 | static u16(*opcD1_word_operation[])(u16 s, u8 d) = |
ece92f85 JJ |
140 | { |
141 | rol_word, | |
142 | ror_word, | |
143 | rcl_word, | |
144 | rcr_word, | |
145 | shl_word, | |
146 | shr_word, | |
9c7e4b06 | 147 | shl_word, /* sal_byte === shl_byte by definition */ |
ece92f85 JJ |
148 | sar_word, |
149 | }; | |
150 | ||
151 | /* used by opcodes c1, d1, and d3. */ | |
285870f7 | 152 | static u32 (*opcD1_long_operation[])(u32 s, u8 d) = |
ece92f85 JJ |
153 | { |
154 | rol_long, | |
155 | ror_long, | |
156 | rcl_long, | |
157 | rcr_long, | |
158 | shl_long, | |
159 | shr_long, | |
9c7e4b06 | 160 | shl_long, /* sal_byte === shl_byte by definition */ |
ece92f85 JJ |
161 | sar_long, |
162 | }; | |
163 | ||
b3521f2e | 164 | #ifdef CONFIG_X86EMU_DEBUG |
ece92f85 JJ |
165 | |
166 | static char *opF6_names[8] = | |
167 | { "TEST\t", "", "NOT\t", "NEG\t", "MUL\t", "IMUL\t", "DIV\t", "IDIV\t" }; | |
168 | ||
169 | #endif | |
170 | ||
171 | /**************************************************************************** | |
172 | PARAMETERS: | |
173 | op1 - Instruction op code | |
174 | ||
175 | REMARKS: | |
176 | Handles illegal opcodes. | |
177 | ****************************************************************************/ | |
178 | void x86emuOp_illegal_op( | |
179 | u8 op1) | |
180 | { | |
181 | START_OF_INSTR(); | |
182 | if (M.x86.R_SP != 0) { | |
e78dd869 | 183 | DB(printf("ILLEGAL X86 OPCODE\n")); |
9c7e4b06 WD |
184 | TRACE_REGS(); |
185 | DB( printk("%04x:%04x: %02X ILLEGAL X86 OPCODE!\n", | |
186 | M.x86.R_CS, M.x86.R_IP-1,op1)); | |
187 | HALT_SYS(); | |
188 | } | |
ece92f85 | 189 | else { |
9c7e4b06 WD |
190 | /* If we get here, it means the stack pointer is back to zero |
191 | * so we are just returning from an emulator service call | |
192 | * so therte is no need to display an error message. We trap | |
193 | * the emulator with an 0xF1 opcode to finish the service | |
194 | * call. | |
195 | */ | |
196 | X86EMU_halt_sys(); | |
197 | } | |
ece92f85 JJ |
198 | END_OF_INSTR(); |
199 | } | |
200 | ||
201 | /**************************************************************************** | |
202 | REMARKS: | |
203 | Handles opcodes 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38 | |
204 | ****************************************************************************/ | |
205 | void x86emuOp_genop_byte_RM_R(u8 op1) | |
206 | { | |
207 | int mod, rl, rh; | |
208 | uint destoffset; | |
209 | u8 *destreg, *srcreg; | |
210 | u8 destval; | |
211 | ||
212 | op1 = (op1 >> 3) & 0x7; | |
213 | ||
214 | START_OF_INSTR(); | |
215 | DECODE_PRINTF(x86emu_GenOpName[op1]); | |
216 | DECODE_PRINTF("\t"); | |
217 | FETCH_DECODE_MODRM(mod, rh, rl); | |
218 | if(mod<3) | |
9c7e4b06 WD |
219 | { destoffset = decode_rmXX_address(mod,rl); |
220 | DECODE_PRINTF(","); | |
221 | destval = fetch_data_byte(destoffset); | |
222 | srcreg = DECODE_RM_BYTE_REGISTER(rh); | |
223 | DECODE_PRINTF("\n"); | |
224 | TRACE_AND_STEP(); | |
225 | destval = genop_byte_operation[op1](destval, *srcreg); | |
226 | store_data_byte(destoffset, destval); | |
227 | } | |
ece92f85 | 228 | else |
9c7e4b06 WD |
229 | { /* register to register */ |
230 | destreg = DECODE_RM_BYTE_REGISTER(rl); | |
231 | DECODE_PRINTF(","); | |
232 | srcreg = DECODE_RM_BYTE_REGISTER(rh); | |
233 | DECODE_PRINTF("\n"); | |
234 | TRACE_AND_STEP(); | |
235 | *destreg = genop_byte_operation[op1](*destreg, *srcreg); | |
236 | } | |
ece92f85 JJ |
237 | DECODE_CLEAR_SEGOVR(); |
238 | END_OF_INSTR(); | |
239 | } | |
240 | ||
241 | /**************************************************************************** | |
242 | REMARKS: | |
243 | Handles opcodes 0x01, 0x09, 0x11, 0x19, 0x21, 0x29, 0x31, 0x39 | |
244 | ****************************************************************************/ | |
245 | void x86emuOp_genop_word_RM_R(u8 op1) | |
246 | { | |
247 | int mod, rl, rh; | |
248 | uint destoffset; | |
249 | ||
250 | op1 = (op1 >> 3) & 0x7; | |
251 | ||
252 | START_OF_INSTR(); | |
253 | DECODE_PRINTF(x86emu_GenOpName[op1]); | |
254 | DECODE_PRINTF("\t"); | |
255 | FETCH_DECODE_MODRM(mod, rh, rl); | |
256 | ||
257 | if(mod<3) { | |
9c7e4b06 WD |
258 | destoffset = decode_rmXX_address(mod,rl); |
259 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
260 | u32 destval; | |
261 | u32 *srcreg; | |
262 | ||
263 | DECODE_PRINTF(","); | |
264 | destval = fetch_data_long(destoffset); | |
265 | srcreg = DECODE_RM_LONG_REGISTER(rh); | |
266 | DECODE_PRINTF("\n"); | |
267 | TRACE_AND_STEP(); | |
268 | destval = genop_long_operation[op1](destval, *srcreg); | |
269 | store_data_long(destoffset, destval); | |
270 | } else { | |
271 | u16 destval; | |
272 | u16 *srcreg; | |
273 | ||
274 | DECODE_PRINTF(","); | |
275 | destval = fetch_data_word(destoffset); | |
276 | srcreg = DECODE_RM_WORD_REGISTER(rh); | |
277 | DECODE_PRINTF("\n"); | |
278 | TRACE_AND_STEP(); | |
279 | destval = genop_word_operation[op1](destval, *srcreg); | |
280 | store_data_word(destoffset, destval); | |
281 | } | |
282 | } else { /* register to register */ | |
283 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
284 | u32 *destreg,*srcreg; | |
285 | ||
286 | destreg = DECODE_RM_LONG_REGISTER(rl); | |
287 | DECODE_PRINTF(","); | |
288 | srcreg = DECODE_RM_LONG_REGISTER(rh); | |
289 | DECODE_PRINTF("\n"); | |
290 | TRACE_AND_STEP(); | |
291 | *destreg = genop_long_operation[op1](*destreg, *srcreg); | |
292 | } else { | |
293 | u16 *destreg,*srcreg; | |
294 | ||
295 | destreg = DECODE_RM_WORD_REGISTER(rl); | |
296 | DECODE_PRINTF(","); | |
297 | srcreg = DECODE_RM_WORD_REGISTER(rh); | |
298 | DECODE_PRINTF("\n"); | |
299 | TRACE_AND_STEP(); | |
300 | *destreg = genop_word_operation[op1](*destreg, *srcreg); | |
301 | } | |
ece92f85 JJ |
302 | } |
303 | DECODE_CLEAR_SEGOVR(); | |
304 | END_OF_INSTR(); | |
305 | } | |
306 | ||
307 | /**************************************************************************** | |
308 | REMARKS: | |
309 | Handles opcodes 0x02, 0x0a, 0x12, 0x1a, 0x22, 0x2a, 0x32, 0x3a | |
310 | ****************************************************************************/ | |
311 | void x86emuOp_genop_byte_R_RM(u8 op1) | |
312 | { | |
313 | int mod, rl, rh; | |
314 | u8 *destreg, *srcreg; | |
315 | uint srcoffset; | |
316 | u8 srcval; | |
317 | ||
318 | op1 = (op1 >> 3) & 0x7; | |
319 | ||
320 | START_OF_INSTR(); | |
321 | DECODE_PRINTF(x86emu_GenOpName[op1]); | |
322 | DECODE_PRINTF("\t"); | |
323 | FETCH_DECODE_MODRM(mod, rh, rl); | |
324 | if (mod < 3) { | |
9c7e4b06 WD |
325 | destreg = DECODE_RM_BYTE_REGISTER(rh); |
326 | DECODE_PRINTF(","); | |
327 | srcoffset = decode_rmXX_address(mod,rl); | |
328 | srcval = fetch_data_byte(srcoffset); | |
329 | } else { /* register to register */ | |
330 | destreg = DECODE_RM_BYTE_REGISTER(rh); | |
331 | DECODE_PRINTF(","); | |
332 | srcreg = DECODE_RM_BYTE_REGISTER(rl); | |
333 | srcval = *srcreg; | |
ece92f85 JJ |
334 | } |
335 | DECODE_PRINTF("\n"); | |
336 | TRACE_AND_STEP(); | |
337 | *destreg = genop_byte_operation[op1](*destreg, srcval); | |
338 | ||
339 | DECODE_CLEAR_SEGOVR(); | |
340 | END_OF_INSTR(); | |
341 | } | |
342 | ||
343 | /**************************************************************************** | |
344 | REMARKS: | |
345 | Handles opcodes 0x03, 0x0b, 0x13, 0x1b, 0x23, 0x2b, 0x33, 0x3b | |
346 | ****************************************************************************/ | |
347 | void x86emuOp_genop_word_R_RM(u8 op1) | |
348 | { | |
349 | int mod, rl, rh; | |
350 | uint srcoffset; | |
351 | u32 *destreg32, srcval; | |
352 | u16 *destreg; | |
353 | ||
354 | op1 = (op1 >> 3) & 0x7; | |
355 | ||
356 | START_OF_INSTR(); | |
357 | DECODE_PRINTF(x86emu_GenOpName[op1]); | |
358 | DECODE_PRINTF("\t"); | |
359 | FETCH_DECODE_MODRM(mod, rh, rl); | |
360 | if (mod < 3) { | |
9c7e4b06 WD |
361 | srcoffset = decode_rmXX_address(mod,rl); |
362 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
363 | destreg32 = DECODE_RM_LONG_REGISTER(rh); | |
364 | DECODE_PRINTF(","); | |
365 | srcval = fetch_data_long(srcoffset); | |
366 | DECODE_PRINTF("\n"); | |
367 | TRACE_AND_STEP(); | |
368 | *destreg32 = genop_long_operation[op1](*destreg32, srcval); | |
369 | } else { | |
370 | destreg = DECODE_RM_WORD_REGISTER(rh); | |
371 | DECODE_PRINTF(","); | |
372 | srcval = fetch_data_word(srcoffset); | |
373 | DECODE_PRINTF("\n"); | |
374 | TRACE_AND_STEP(); | |
375 | *destreg = genop_word_operation[op1](*destreg, srcval); | |
376 | } | |
377 | } else { /* register to register */ | |
378 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
379 | u32 *srcreg; | |
380 | destreg32 = DECODE_RM_LONG_REGISTER(rh); | |
381 | DECODE_PRINTF(","); | |
382 | srcreg = DECODE_RM_LONG_REGISTER(rl); | |
383 | DECODE_PRINTF("\n"); | |
384 | TRACE_AND_STEP(); | |
385 | *destreg32 = genop_long_operation[op1](*destreg32, *srcreg); | |
386 | } else { | |
387 | u16 *srcreg; | |
388 | destreg = DECODE_RM_WORD_REGISTER(rh); | |
389 | DECODE_PRINTF(","); | |
390 | srcreg = DECODE_RM_WORD_REGISTER(rl); | |
391 | DECODE_PRINTF("\n"); | |
392 | TRACE_AND_STEP(); | |
393 | *destreg = genop_word_operation[op1](*destreg, *srcreg); | |
394 | } | |
ece92f85 JJ |
395 | } |
396 | DECODE_CLEAR_SEGOVR(); | |
397 | END_OF_INSTR(); | |
398 | } | |
399 | ||
400 | /**************************************************************************** | |
401 | REMARKS: | |
402 | Handles opcodes 0x04, 0x0c, 0x14, 0x1c, 0x24, 0x2c, 0x34, 0x3c | |
403 | ****************************************************************************/ | |
404 | void x86emuOp_genop_byte_AL_IMM(u8 op1) | |
405 | { | |
406 | u8 srcval; | |
407 | ||
408 | op1 = (op1 >> 3) & 0x7; | |
409 | ||
410 | START_OF_INSTR(); | |
411 | DECODE_PRINTF(x86emu_GenOpName[op1]); | |
412 | DECODE_PRINTF("\tAL,"); | |
413 | srcval = fetch_byte_imm(); | |
414 | DECODE_PRINTF2("%x\n", srcval); | |
415 | TRACE_AND_STEP(); | |
416 | M.x86.R_AL = genop_byte_operation[op1](M.x86.R_AL, srcval); | |
417 | DECODE_CLEAR_SEGOVR(); | |
418 | END_OF_INSTR(); | |
419 | } | |
420 | ||
421 | /**************************************************************************** | |
422 | REMARKS: | |
423 | Handles opcodes 0x05, 0x0d, 0x15, 0x1d, 0x25, 0x2d, 0x35, 0x3d | |
424 | ****************************************************************************/ | |
425 | void x86emuOp_genop_word_AX_IMM(u8 op1) | |
426 | { | |
427 | u32 srcval; | |
428 | ||
429 | op1 = (op1 >> 3) & 0x7; | |
430 | ||
431 | START_OF_INSTR(); | |
432 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 WD |
433 | DECODE_PRINTF(x86emu_GenOpName[op1]); |
434 | DECODE_PRINTF("\tEAX,"); | |
435 | srcval = fetch_long_imm(); | |
ece92f85 | 436 | } else { |
9c7e4b06 WD |
437 | DECODE_PRINTF(x86emu_GenOpName[op1]); |
438 | DECODE_PRINTF("\tAX,"); | |
439 | srcval = fetch_word_imm(); | |
ece92f85 JJ |
440 | } |
441 | DECODE_PRINTF2("%x\n", srcval); | |
442 | TRACE_AND_STEP(); | |
443 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 | 444 | M.x86.R_EAX = genop_long_operation[op1](M.x86.R_EAX, srcval); |
ece92f85 | 445 | } else { |
9c7e4b06 | 446 | M.x86.R_AX = genop_word_operation[op1](M.x86.R_AX, (u16)srcval); |
ece92f85 JJ |
447 | } |
448 | DECODE_CLEAR_SEGOVR(); | |
449 | END_OF_INSTR(); | |
450 | } | |
451 | ||
452 | /**************************************************************************** | |
453 | REMARKS: | |
454 | Handles opcode 0x06 | |
455 | ****************************************************************************/ | |
456 | void x86emuOp_push_ES(u8 X86EMU_UNUSED(op1)) | |
457 | { | |
458 | START_OF_INSTR(); | |
459 | DECODE_PRINTF("PUSH\tES\n"); | |
460 | TRACE_AND_STEP(); | |
461 | push_word(M.x86.R_ES); | |
462 | DECODE_CLEAR_SEGOVR(); | |
463 | END_OF_INSTR(); | |
464 | } | |
465 | ||
466 | /**************************************************************************** | |
467 | REMARKS: | |
468 | Handles opcode 0x07 | |
469 | ****************************************************************************/ | |
470 | void x86emuOp_pop_ES(u8 X86EMU_UNUSED(op1)) | |
471 | { | |
472 | START_OF_INSTR(); | |
473 | DECODE_PRINTF("POP\tES\n"); | |
474 | TRACE_AND_STEP(); | |
475 | M.x86.R_ES = pop_word(); | |
476 | DECODE_CLEAR_SEGOVR(); | |
477 | END_OF_INSTR(); | |
478 | } | |
479 | ||
480 | /**************************************************************************** | |
481 | REMARKS: | |
482 | Handles opcode 0x0e | |
483 | ****************************************************************************/ | |
484 | void x86emuOp_push_CS(u8 X86EMU_UNUSED(op1)) | |
485 | { | |
486 | START_OF_INSTR(); | |
487 | DECODE_PRINTF("PUSH\tCS\n"); | |
488 | TRACE_AND_STEP(); | |
489 | push_word(M.x86.R_CS); | |
490 | DECODE_CLEAR_SEGOVR(); | |
491 | END_OF_INSTR(); | |
492 | } | |
493 | ||
494 | /**************************************************************************** | |
495 | REMARKS: | |
496 | Handles opcode 0x0f. Escape for two-byte opcode (286 or better) | |
497 | ****************************************************************************/ | |
498 | void x86emuOp_two_byte(u8 X86EMU_UNUSED(op1)) | |
499 | { | |
500 | u8 op2 = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++)); | |
501 | INC_DECODED_INST_LEN(1); | |
502 | (*x86emu_optab2[op2])(op2); | |
503 | } | |
504 | ||
505 | /**************************************************************************** | |
506 | REMARKS: | |
507 | Handles opcode 0x16 | |
508 | ****************************************************************************/ | |
509 | void x86emuOp_push_SS(u8 X86EMU_UNUSED(op1)) | |
510 | { | |
511 | START_OF_INSTR(); | |
512 | DECODE_PRINTF("PUSH\tSS\n"); | |
513 | TRACE_AND_STEP(); | |
514 | push_word(M.x86.R_SS); | |
515 | DECODE_CLEAR_SEGOVR(); | |
516 | END_OF_INSTR(); | |
517 | } | |
518 | ||
519 | /**************************************************************************** | |
520 | REMARKS: | |
521 | Handles opcode 0x17 | |
522 | ****************************************************************************/ | |
523 | void x86emuOp_pop_SS(u8 X86EMU_UNUSED(op1)) | |
524 | { | |
525 | START_OF_INSTR(); | |
526 | DECODE_PRINTF("POP\tSS\n"); | |
527 | TRACE_AND_STEP(); | |
528 | M.x86.R_SS = pop_word(); | |
529 | DECODE_CLEAR_SEGOVR(); | |
530 | END_OF_INSTR(); | |
531 | } | |
532 | ||
533 | /**************************************************************************** | |
534 | REMARKS: | |
535 | Handles opcode 0x1e | |
536 | ****************************************************************************/ | |
537 | void x86emuOp_push_DS(u8 X86EMU_UNUSED(op1)) | |
538 | { | |
539 | START_OF_INSTR(); | |
540 | DECODE_PRINTF("PUSH\tDS\n"); | |
541 | TRACE_AND_STEP(); | |
542 | push_word(M.x86.R_DS); | |
543 | DECODE_CLEAR_SEGOVR(); | |
544 | END_OF_INSTR(); | |
545 | } | |
546 | ||
547 | /**************************************************************************** | |
548 | REMARKS: | |
549 | Handles opcode 0x1f | |
550 | ****************************************************************************/ | |
551 | void x86emuOp_pop_DS(u8 X86EMU_UNUSED(op1)) | |
552 | { | |
553 | START_OF_INSTR(); | |
554 | DECODE_PRINTF("POP\tDS\n"); | |
555 | TRACE_AND_STEP(); | |
556 | M.x86.R_DS = pop_word(); | |
557 | DECODE_CLEAR_SEGOVR(); | |
558 | END_OF_INSTR(); | |
559 | } | |
560 | ||
561 | /**************************************************************************** | |
562 | REMARKS: | |
563 | Handles opcode 0x26 | |
564 | ****************************************************************************/ | |
565 | void x86emuOp_segovr_ES(u8 X86EMU_UNUSED(op1)) | |
566 | { | |
567 | START_OF_INSTR(); | |
568 | DECODE_PRINTF("ES:\n"); | |
569 | TRACE_AND_STEP(); | |
570 | M.x86.mode |= SYSMODE_SEGOVR_ES; | |
571 | /* | |
572 | * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4 | |
573 | * opcode subroutines we do not want to do this. | |
574 | */ | |
575 | END_OF_INSTR(); | |
576 | } | |
577 | ||
578 | /**************************************************************************** | |
579 | REMARKS: | |
580 | Handles opcode 0x27 | |
581 | ****************************************************************************/ | |
582 | void x86emuOp_daa(u8 X86EMU_UNUSED(op1)) | |
583 | { | |
584 | START_OF_INSTR(); | |
585 | DECODE_PRINTF("DAA\n"); | |
586 | TRACE_AND_STEP(); | |
587 | M.x86.R_AL = daa_byte(M.x86.R_AL); | |
588 | DECODE_CLEAR_SEGOVR(); | |
589 | END_OF_INSTR(); | |
590 | } | |
591 | ||
592 | /**************************************************************************** | |
593 | REMARKS: | |
594 | Handles opcode 0x2e | |
595 | ****************************************************************************/ | |
596 | void x86emuOp_segovr_CS(u8 X86EMU_UNUSED(op1)) | |
597 | { | |
598 | START_OF_INSTR(); | |
599 | DECODE_PRINTF("CS:\n"); | |
600 | TRACE_AND_STEP(); | |
601 | M.x86.mode |= SYSMODE_SEGOVR_CS; | |
602 | /* note no DECODE_CLEAR_SEGOVR here. */ | |
603 | END_OF_INSTR(); | |
604 | } | |
605 | ||
606 | /**************************************************************************** | |
607 | REMARKS: | |
608 | Handles opcode 0x2f | |
609 | ****************************************************************************/ | |
610 | void x86emuOp_das(u8 X86EMU_UNUSED(op1)) | |
611 | { | |
612 | START_OF_INSTR(); | |
613 | DECODE_PRINTF("DAS\n"); | |
614 | TRACE_AND_STEP(); | |
615 | M.x86.R_AL = das_byte(M.x86.R_AL); | |
616 | DECODE_CLEAR_SEGOVR(); | |
617 | END_OF_INSTR(); | |
618 | } | |
619 | ||
620 | /**************************************************************************** | |
621 | REMARKS: | |
622 | Handles opcode 0x36 | |
623 | ****************************************************************************/ | |
624 | void x86emuOp_segovr_SS(u8 X86EMU_UNUSED(op1)) | |
625 | { | |
626 | START_OF_INSTR(); | |
627 | DECODE_PRINTF("SS:\n"); | |
628 | TRACE_AND_STEP(); | |
629 | M.x86.mode |= SYSMODE_SEGOVR_SS; | |
630 | /* no DECODE_CLEAR_SEGOVR ! */ | |
631 | END_OF_INSTR(); | |
632 | } | |
633 | ||
634 | /**************************************************************************** | |
635 | REMARKS: | |
636 | Handles opcode 0x37 | |
637 | ****************************************************************************/ | |
638 | void x86emuOp_aaa(u8 X86EMU_UNUSED(op1)) | |
639 | { | |
640 | START_OF_INSTR(); | |
641 | DECODE_PRINTF("AAA\n"); | |
642 | TRACE_AND_STEP(); | |
643 | M.x86.R_AX = aaa_word(M.x86.R_AX); | |
644 | DECODE_CLEAR_SEGOVR(); | |
645 | END_OF_INSTR(); | |
646 | } | |
647 | ||
648 | /**************************************************************************** | |
649 | REMARKS: | |
650 | Handles opcode 0x3e | |
651 | ****************************************************************************/ | |
652 | void x86emuOp_segovr_DS(u8 X86EMU_UNUSED(op1)) | |
653 | { | |
654 | START_OF_INSTR(); | |
655 | DECODE_PRINTF("DS:\n"); | |
656 | TRACE_AND_STEP(); | |
657 | M.x86.mode |= SYSMODE_SEGOVR_DS; | |
658 | /* NO DECODE_CLEAR_SEGOVR! */ | |
659 | END_OF_INSTR(); | |
660 | } | |
661 | ||
662 | /**************************************************************************** | |
663 | REMARKS: | |
664 | Handles opcode 0x3f | |
665 | ****************************************************************************/ | |
666 | void x86emuOp_aas(u8 X86EMU_UNUSED(op1)) | |
667 | { | |
668 | START_OF_INSTR(); | |
669 | DECODE_PRINTF("AAS\n"); | |
670 | TRACE_AND_STEP(); | |
671 | M.x86.R_AX = aas_word(M.x86.R_AX); | |
672 | DECODE_CLEAR_SEGOVR(); | |
673 | END_OF_INSTR(); | |
674 | } | |
675 | ||
676 | /**************************************************************************** | |
677 | REMARKS: | |
678 | Handles opcode 0x40 - 0x47 | |
679 | ****************************************************************************/ | |
680 | void x86emuOp_inc_register(u8 op1) | |
681 | { | |
682 | START_OF_INSTR(); | |
683 | op1 &= 0x7; | |
684 | DECODE_PRINTF("INC\t"); | |
685 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 WD |
686 | u32 *reg; |
687 | reg = DECODE_RM_LONG_REGISTER(op1); | |
688 | DECODE_PRINTF("\n"); | |
689 | TRACE_AND_STEP(); | |
690 | *reg = inc_long(*reg); | |
ece92f85 | 691 | } else { |
9c7e4b06 WD |
692 | u16 *reg; |
693 | reg = DECODE_RM_WORD_REGISTER(op1); | |
694 | DECODE_PRINTF("\n"); | |
695 | TRACE_AND_STEP(); | |
696 | *reg = inc_word(*reg); | |
ece92f85 JJ |
697 | } |
698 | DECODE_CLEAR_SEGOVR(); | |
699 | END_OF_INSTR(); | |
700 | } | |
701 | ||
702 | /**************************************************************************** | |
703 | REMARKS: | |
704 | Handles opcode 0x48 - 0x4F | |
705 | ****************************************************************************/ | |
706 | void x86emuOp_dec_register(u8 op1) | |
707 | { | |
708 | START_OF_INSTR(); | |
709 | op1 &= 0x7; | |
710 | DECODE_PRINTF("DEC\t"); | |
711 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 WD |
712 | u32 *reg; |
713 | reg = DECODE_RM_LONG_REGISTER(op1); | |
714 | DECODE_PRINTF("\n"); | |
715 | TRACE_AND_STEP(); | |
716 | *reg = dec_long(*reg); | |
ece92f85 | 717 | } else { |
9c7e4b06 WD |
718 | u16 *reg; |
719 | reg = DECODE_RM_WORD_REGISTER(op1); | |
720 | DECODE_PRINTF("\n"); | |
721 | TRACE_AND_STEP(); | |
722 | *reg = dec_word(*reg); | |
ece92f85 JJ |
723 | } |
724 | DECODE_CLEAR_SEGOVR(); | |
725 | END_OF_INSTR(); | |
726 | } | |
727 | ||
728 | /**************************************************************************** | |
729 | REMARKS: | |
730 | Handles opcode 0x50 - 0x57 | |
731 | ****************************************************************************/ | |
732 | void x86emuOp_push_register(u8 op1) | |
733 | { | |
734 | START_OF_INSTR(); | |
735 | op1 &= 0x7; | |
736 | DECODE_PRINTF("PUSH\t"); | |
737 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 WD |
738 | u32 *reg; |
739 | reg = DECODE_RM_LONG_REGISTER(op1); | |
740 | DECODE_PRINTF("\n"); | |
741 | TRACE_AND_STEP(); | |
742 | push_long(*reg); | |
ece92f85 | 743 | } else { |
9c7e4b06 WD |
744 | u16 *reg; |
745 | reg = DECODE_RM_WORD_REGISTER(op1); | |
746 | DECODE_PRINTF("\n"); | |
747 | TRACE_AND_STEP(); | |
748 | push_word(*reg); | |
ece92f85 JJ |
749 | } |
750 | DECODE_CLEAR_SEGOVR(); | |
751 | END_OF_INSTR(); | |
752 | } | |
753 | ||
754 | /**************************************************************************** | |
755 | REMARKS: | |
756 | Handles opcode 0x58 - 0x5F | |
757 | ****************************************************************************/ | |
758 | void x86emuOp_pop_register(u8 op1) | |
759 | { | |
760 | START_OF_INSTR(); | |
761 | op1 &= 0x7; | |
762 | DECODE_PRINTF("POP\t"); | |
763 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 WD |
764 | u32 *reg; |
765 | reg = DECODE_RM_LONG_REGISTER(op1); | |
766 | DECODE_PRINTF("\n"); | |
767 | TRACE_AND_STEP(); | |
768 | *reg = pop_long(); | |
ece92f85 | 769 | } else { |
9c7e4b06 WD |
770 | u16 *reg; |
771 | reg = DECODE_RM_WORD_REGISTER(op1); | |
772 | DECODE_PRINTF("\n"); | |
773 | TRACE_AND_STEP(); | |
774 | *reg = pop_word(); | |
ece92f85 JJ |
775 | } |
776 | DECODE_CLEAR_SEGOVR(); | |
777 | END_OF_INSTR(); | |
778 | } | |
779 | ||
780 | /**************************************************************************** | |
781 | REMARKS: | |
782 | Handles opcode 0x60 | |
783 | ****************************************************************************/ | |
784 | void x86emuOp_push_all(u8 X86EMU_UNUSED(op1)) | |
785 | { | |
786 | START_OF_INSTR(); | |
787 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 | 788 | DECODE_PRINTF("PUSHAD\n"); |
ece92f85 | 789 | } else { |
9c7e4b06 | 790 | DECODE_PRINTF("PUSHA\n"); |
ece92f85 JJ |
791 | } |
792 | TRACE_AND_STEP(); | |
793 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 WD |
794 | u32 old_sp = M.x86.R_ESP; |
795 | ||
796 | push_long(M.x86.R_EAX); | |
797 | push_long(M.x86.R_ECX); | |
798 | push_long(M.x86.R_EDX); | |
799 | push_long(M.x86.R_EBX); | |
800 | push_long(old_sp); | |
801 | push_long(M.x86.R_EBP); | |
802 | push_long(M.x86.R_ESI); | |
803 | push_long(M.x86.R_EDI); | |
ece92f85 | 804 | } else { |
9c7e4b06 WD |
805 | u16 old_sp = M.x86.R_SP; |
806 | ||
807 | push_word(M.x86.R_AX); | |
808 | push_word(M.x86.R_CX); | |
809 | push_word(M.x86.R_DX); | |
810 | push_word(M.x86.R_BX); | |
811 | push_word(old_sp); | |
812 | push_word(M.x86.R_BP); | |
813 | push_word(M.x86.R_SI); | |
814 | push_word(M.x86.R_DI); | |
ece92f85 JJ |
815 | } |
816 | DECODE_CLEAR_SEGOVR(); | |
817 | END_OF_INSTR(); | |
818 | } | |
819 | ||
820 | /**************************************************************************** | |
821 | REMARKS: | |
822 | Handles opcode 0x61 | |
823 | ****************************************************************************/ | |
824 | void x86emuOp_pop_all(u8 X86EMU_UNUSED(op1)) | |
825 | { | |
826 | START_OF_INSTR(); | |
827 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 | 828 | DECODE_PRINTF("POPAD\n"); |
ece92f85 | 829 | } else { |
9c7e4b06 | 830 | DECODE_PRINTF("POPA\n"); |
ece92f85 JJ |
831 | } |
832 | TRACE_AND_STEP(); | |
833 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 WD |
834 | M.x86.R_EDI = pop_long(); |
835 | M.x86.R_ESI = pop_long(); | |
836 | M.x86.R_EBP = pop_long(); | |
837 | M.x86.R_ESP += 4; /* skip ESP */ | |
838 | M.x86.R_EBX = pop_long(); | |
839 | M.x86.R_EDX = pop_long(); | |
840 | M.x86.R_ECX = pop_long(); | |
841 | M.x86.R_EAX = pop_long(); | |
ece92f85 | 842 | } else { |
9c7e4b06 WD |
843 | M.x86.R_DI = pop_word(); |
844 | M.x86.R_SI = pop_word(); | |
845 | M.x86.R_BP = pop_word(); | |
846 | M.x86.R_SP += 2; /* skip SP */ | |
847 | M.x86.R_BX = pop_word(); | |
848 | M.x86.R_DX = pop_word(); | |
849 | M.x86.R_CX = pop_word(); | |
850 | M.x86.R_AX = pop_word(); | |
ece92f85 JJ |
851 | } |
852 | DECODE_CLEAR_SEGOVR(); | |
853 | END_OF_INSTR(); | |
854 | } | |
855 | ||
9c7e4b06 WD |
856 | /*opcode 0x62 ILLEGAL OP, calls x86emuOp_illegal_op() */ |
857 | /*opcode 0x63 ILLEGAL OP, calls x86emuOp_illegal_op() */ | |
ece92f85 JJ |
858 | |
859 | /**************************************************************************** | |
860 | REMARKS: | |
861 | Handles opcode 0x64 | |
862 | ****************************************************************************/ | |
863 | void x86emuOp_segovr_FS(u8 X86EMU_UNUSED(op1)) | |
864 | { | |
865 | START_OF_INSTR(); | |
866 | DECODE_PRINTF("FS:\n"); | |
867 | TRACE_AND_STEP(); | |
868 | M.x86.mode |= SYSMODE_SEGOVR_FS; | |
869 | /* | |
870 | * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4 | |
871 | * opcode subroutines we do not want to do this. | |
872 | */ | |
873 | END_OF_INSTR(); | |
874 | } | |
875 | ||
876 | /**************************************************************************** | |
877 | REMARKS: | |
878 | Handles opcode 0x65 | |
879 | ****************************************************************************/ | |
880 | void x86emuOp_segovr_GS(u8 X86EMU_UNUSED(op1)) | |
881 | { | |
882 | START_OF_INSTR(); | |
883 | DECODE_PRINTF("GS:\n"); | |
884 | TRACE_AND_STEP(); | |
885 | M.x86.mode |= SYSMODE_SEGOVR_GS; | |
886 | /* | |
887 | * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4 | |
888 | * opcode subroutines we do not want to do this. | |
889 | */ | |
890 | END_OF_INSTR(); | |
891 | } | |
892 | ||
893 | /**************************************************************************** | |
894 | REMARKS: | |
895 | Handles opcode 0x66 - prefix for 32-bit register | |
896 | ****************************************************************************/ | |
897 | void x86emuOp_prefix_data(u8 X86EMU_UNUSED(op1)) | |
898 | { | |
899 | START_OF_INSTR(); | |
900 | DECODE_PRINTF("DATA:\n"); | |
901 | TRACE_AND_STEP(); | |
902 | M.x86.mode |= SYSMODE_PREFIX_DATA; | |
903 | /* note no DECODE_CLEAR_SEGOVR here. */ | |
904 | END_OF_INSTR(); | |
905 | } | |
906 | ||
907 | /**************************************************************************** | |
908 | REMARKS: | |
909 | Handles opcode 0x67 - prefix for 32-bit address | |
910 | ****************************************************************************/ | |
911 | void x86emuOp_prefix_addr(u8 X86EMU_UNUSED(op1)) | |
912 | { | |
913 | START_OF_INSTR(); | |
914 | DECODE_PRINTF("ADDR:\n"); | |
915 | TRACE_AND_STEP(); | |
916 | M.x86.mode |= SYSMODE_PREFIX_ADDR; | |
917 | /* note no DECODE_CLEAR_SEGOVR here. */ | |
918 | END_OF_INSTR(); | |
919 | } | |
920 | ||
921 | /**************************************************************************** | |
922 | REMARKS: | |
923 | Handles opcode 0x68 | |
924 | ****************************************************************************/ | |
925 | void x86emuOp_push_word_IMM(u8 X86EMU_UNUSED(op1)) | |
926 | { | |
927 | u32 imm; | |
928 | ||
929 | START_OF_INSTR(); | |
930 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 | 931 | imm = fetch_long_imm(); |
ece92f85 | 932 | } else { |
9c7e4b06 | 933 | imm = fetch_word_imm(); |
ece92f85 JJ |
934 | } |
935 | DECODE_PRINTF2("PUSH\t%x\n", imm); | |
936 | TRACE_AND_STEP(); | |
937 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 | 938 | push_long(imm); |
ece92f85 | 939 | } else { |
9c7e4b06 | 940 | push_word((u16)imm); |
ece92f85 JJ |
941 | } |
942 | DECODE_CLEAR_SEGOVR(); | |
943 | END_OF_INSTR(); | |
944 | } | |
945 | ||
946 | /**************************************************************************** | |
947 | REMARKS: | |
948 | Handles opcode 0x69 | |
949 | ****************************************************************************/ | |
950 | void x86emuOp_imul_word_IMM(u8 X86EMU_UNUSED(op1)) | |
951 | { | |
952 | int mod, rl, rh; | |
953 | uint srcoffset; | |
954 | ||
955 | START_OF_INSTR(); | |
956 | DECODE_PRINTF("IMUL\t"); | |
957 | FETCH_DECODE_MODRM(mod, rh, rl); | |
958 | if (mod < 3) { | |
9c7e4b06 WD |
959 | srcoffset = decode_rmXX_address(mod, rl); |
960 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
961 | u32 *destreg; | |
962 | u32 srcval; | |
963 | u32 res_lo,res_hi; | |
964 | s32 imm; | |
965 | ||
966 | destreg = DECODE_RM_LONG_REGISTER(rh); | |
967 | DECODE_PRINTF(","); | |
968 | srcval = fetch_data_long(srcoffset); | |
969 | imm = fetch_long_imm(); | |
970 | DECODE_PRINTF2(",%d\n", (s32)imm); | |
971 | TRACE_AND_STEP(); | |
972 | imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm); | |
973 | if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) || | |
974 | (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) { | |
975 | CLEAR_FLAG(F_CF); | |
976 | CLEAR_FLAG(F_OF); | |
977 | } else { | |
978 | SET_FLAG(F_CF); | |
979 | SET_FLAG(F_OF); | |
980 | } | |
981 | *destreg = (u32)res_lo; | |
982 | } else { | |
983 | u16 *destreg; | |
984 | u16 srcval; | |
985 | u32 res; | |
986 | s16 imm; | |
987 | ||
988 | destreg = DECODE_RM_WORD_REGISTER(rh); | |
989 | DECODE_PRINTF(","); | |
990 | srcval = fetch_data_word(srcoffset); | |
991 | imm = fetch_word_imm(); | |
992 | DECODE_PRINTF2(",%d\n", (s32)imm); | |
993 | TRACE_AND_STEP(); | |
994 | res = (s16)srcval * (s16)imm; | |
995 | if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) || | |
996 | (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) { | |
997 | CLEAR_FLAG(F_CF); | |
998 | CLEAR_FLAG(F_OF); | |
999 | } else { | |
1000 | SET_FLAG(F_CF); | |
1001 | SET_FLAG(F_OF); | |
1002 | } | |
1003 | *destreg = (u16)res; | |
1004 | } | |
1005 | } else { /* register to register */ | |
1006 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
1007 | u32 *destreg,*srcreg; | |
1008 | u32 res_lo,res_hi; | |
1009 | s32 imm; | |
1010 | ||
1011 | destreg = DECODE_RM_LONG_REGISTER(rh); | |
1012 | DECODE_PRINTF(","); | |
1013 | srcreg = DECODE_RM_LONG_REGISTER(rl); | |
1014 | imm = fetch_long_imm(); | |
1015 | DECODE_PRINTF2(",%d\n", (s32)imm); | |
1016 | TRACE_AND_STEP(); | |
1017 | imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm); | |
1018 | if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) || | |
1019 | (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) { | |
1020 | CLEAR_FLAG(F_CF); | |
1021 | CLEAR_FLAG(F_OF); | |
1022 | } else { | |
1023 | SET_FLAG(F_CF); | |
1024 | SET_FLAG(F_OF); | |
1025 | } | |
1026 | *destreg = (u32)res_lo; | |
1027 | } else { | |
1028 | u16 *destreg,*srcreg; | |
1029 | u32 res; | |
1030 | s16 imm; | |
1031 | ||
1032 | destreg = DECODE_RM_WORD_REGISTER(rh); | |
1033 | DECODE_PRINTF(","); | |
1034 | srcreg = DECODE_RM_WORD_REGISTER(rl); | |
1035 | imm = fetch_word_imm(); | |
1036 | DECODE_PRINTF2(",%d\n", (s32)imm); | |
1037 | res = (s16)*srcreg * (s16)imm; | |
1038 | if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) || | |
1039 | (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) { | |
1040 | CLEAR_FLAG(F_CF); | |
1041 | CLEAR_FLAG(F_OF); | |
1042 | } else { | |
1043 | SET_FLAG(F_CF); | |
1044 | SET_FLAG(F_OF); | |
1045 | } | |
1046 | *destreg = (u16)res; | |
1047 | } | |
ece92f85 JJ |
1048 | } |
1049 | DECODE_CLEAR_SEGOVR(); | |
1050 | END_OF_INSTR(); | |
1051 | } | |
1052 | ||
1053 | /**************************************************************************** | |
1054 | REMARKS: | |
1055 | Handles opcode 0x6a | |
1056 | ****************************************************************************/ | |
1057 | void x86emuOp_push_byte_IMM(u8 X86EMU_UNUSED(op1)) | |
1058 | { | |
1059 | s16 imm; | |
1060 | ||
1061 | START_OF_INSTR(); | |
1062 | imm = (s8)fetch_byte_imm(); | |
1063 | DECODE_PRINTF2("PUSH\t%d\n", imm); | |
1064 | TRACE_AND_STEP(); | |
1065 | push_word(imm); | |
1066 | DECODE_CLEAR_SEGOVR(); | |
1067 | END_OF_INSTR(); | |
1068 | } | |
1069 | ||
1070 | /**************************************************************************** | |
1071 | REMARKS: | |
1072 | Handles opcode 0x6b | |
1073 | ****************************************************************************/ | |
1074 | void x86emuOp_imul_byte_IMM(u8 X86EMU_UNUSED(op1)) | |
1075 | { | |
1076 | int mod, rl, rh; | |
1077 | uint srcoffset; | |
9c7e4b06 | 1078 | s8 imm; |
ece92f85 JJ |
1079 | |
1080 | START_OF_INSTR(); | |
1081 | DECODE_PRINTF("IMUL\t"); | |
1082 | FETCH_DECODE_MODRM(mod, rh, rl); | |
1083 | if (mod < 3) { | |
9c7e4b06 WD |
1084 | srcoffset = decode_rmXX_address(mod, rl); |
1085 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
1086 | u32 *destreg; | |
1087 | u32 srcval; | |
1088 | u32 res_lo,res_hi; | |
1089 | ||
1090 | destreg = DECODE_RM_LONG_REGISTER(rh); | |
1091 | DECODE_PRINTF(","); | |
1092 | srcval = fetch_data_long(srcoffset); | |
1093 | imm = fetch_byte_imm(); | |
1094 | DECODE_PRINTF2(",%d\n", (s32)imm); | |
1095 | TRACE_AND_STEP(); | |
1096 | imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm); | |
1097 | if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) || | |
1098 | (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) { | |
1099 | CLEAR_FLAG(F_CF); | |
1100 | CLEAR_FLAG(F_OF); | |
1101 | } else { | |
1102 | SET_FLAG(F_CF); | |
1103 | SET_FLAG(F_OF); | |
1104 | } | |
1105 | *destreg = (u32)res_lo; | |
1106 | } else { | |
1107 | u16 *destreg; | |
1108 | u16 srcval; | |
1109 | u32 res; | |
1110 | ||
1111 | destreg = DECODE_RM_WORD_REGISTER(rh); | |
1112 | DECODE_PRINTF(","); | |
1113 | srcval = fetch_data_word(srcoffset); | |
1114 | imm = fetch_byte_imm(); | |
1115 | DECODE_PRINTF2(",%d\n", (s32)imm); | |
1116 | TRACE_AND_STEP(); | |
1117 | res = (s16)srcval * (s16)imm; | |
1118 | if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) || | |
1119 | (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) { | |
1120 | CLEAR_FLAG(F_CF); | |
1121 | CLEAR_FLAG(F_OF); | |
1122 | } else { | |
1123 | SET_FLAG(F_CF); | |
1124 | SET_FLAG(F_OF); | |
1125 | } | |
1126 | *destreg = (u16)res; | |
1127 | } | |
1128 | } else { /* register to register */ | |
1129 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
1130 | u32 *destreg,*srcreg; | |
1131 | u32 res_lo,res_hi; | |
1132 | ||
1133 | destreg = DECODE_RM_LONG_REGISTER(rh); | |
1134 | DECODE_PRINTF(","); | |
1135 | srcreg = DECODE_RM_LONG_REGISTER(rl); | |
1136 | imm = fetch_byte_imm(); | |
1137 | DECODE_PRINTF2(",%d\n", (s32)imm); | |
1138 | TRACE_AND_STEP(); | |
1139 | imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm); | |
1140 | if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) || | |
1141 | (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) { | |
1142 | CLEAR_FLAG(F_CF); | |
1143 | CLEAR_FLAG(F_OF); | |
1144 | } else { | |
1145 | SET_FLAG(F_CF); | |
1146 | SET_FLAG(F_OF); | |
1147 | } | |
1148 | *destreg = (u32)res_lo; | |
1149 | } else { | |
1150 | u16 *destreg,*srcreg; | |
1151 | u32 res; | |
1152 | ||
1153 | destreg = DECODE_RM_WORD_REGISTER(rh); | |
1154 | DECODE_PRINTF(","); | |
1155 | srcreg = DECODE_RM_WORD_REGISTER(rl); | |
1156 | imm = fetch_byte_imm(); | |
1157 | DECODE_PRINTF2(",%d\n", (s32)imm); | |
1158 | TRACE_AND_STEP(); | |
1159 | res = (s16)*srcreg * (s16)imm; | |
1160 | if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) || | |
1161 | (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) { | |
1162 | CLEAR_FLAG(F_CF); | |
1163 | CLEAR_FLAG(F_OF); | |
1164 | } else { | |
1165 | SET_FLAG(F_CF); | |
1166 | SET_FLAG(F_OF); | |
1167 | } | |
1168 | *destreg = (u16)res; | |
1169 | } | |
ece92f85 JJ |
1170 | } |
1171 | DECODE_CLEAR_SEGOVR(); | |
1172 | END_OF_INSTR(); | |
1173 | } | |
1174 | ||
1175 | /**************************************************************************** | |
1176 | REMARKS: | |
1177 | Handles opcode 0x6c | |
1178 | ****************************************************************************/ | |
1179 | void x86emuOp_ins_byte(u8 X86EMU_UNUSED(op1)) | |
1180 | { | |
1181 | START_OF_INSTR(); | |
1182 | DECODE_PRINTF("INSB\n"); | |
1183 | ins(1); | |
1184 | TRACE_AND_STEP(); | |
1185 | DECODE_CLEAR_SEGOVR(); | |
1186 | END_OF_INSTR(); | |
1187 | } | |
1188 | ||
1189 | /**************************************************************************** | |
1190 | REMARKS: | |
1191 | Handles opcode 0x6d | |
1192 | ****************************************************************************/ | |
1193 | void x86emuOp_ins_word(u8 X86EMU_UNUSED(op1)) | |
1194 | { | |
1195 | START_OF_INSTR(); | |
1196 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 WD |
1197 | DECODE_PRINTF("INSD\n"); |
1198 | ins(4); | |
ece92f85 | 1199 | } else { |
9c7e4b06 WD |
1200 | DECODE_PRINTF("INSW\n"); |
1201 | ins(2); | |
ece92f85 JJ |
1202 | } |
1203 | TRACE_AND_STEP(); | |
1204 | DECODE_CLEAR_SEGOVR(); | |
1205 | END_OF_INSTR(); | |
1206 | } | |
1207 | ||
1208 | /**************************************************************************** | |
1209 | REMARKS: | |
1210 | Handles opcode 0x6e | |
1211 | ****************************************************************************/ | |
1212 | void x86emuOp_outs_byte(u8 X86EMU_UNUSED(op1)) | |
1213 | { | |
1214 | START_OF_INSTR(); | |
1215 | DECODE_PRINTF("OUTSB\n"); | |
1216 | outs(1); | |
1217 | TRACE_AND_STEP(); | |
1218 | DECODE_CLEAR_SEGOVR(); | |
1219 | END_OF_INSTR(); | |
1220 | } | |
1221 | ||
1222 | /**************************************************************************** | |
1223 | REMARKS: | |
1224 | Handles opcode 0x6f | |
1225 | ****************************************************************************/ | |
1226 | void x86emuOp_outs_word(u8 X86EMU_UNUSED(op1)) | |
1227 | { | |
1228 | START_OF_INSTR(); | |
1229 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 WD |
1230 | DECODE_PRINTF("OUTSD\n"); |
1231 | outs(4); | |
ece92f85 | 1232 | } else { |
9c7e4b06 WD |
1233 | DECODE_PRINTF("OUTSW\n"); |
1234 | outs(2); | |
ece92f85 JJ |
1235 | } |
1236 | TRACE_AND_STEP(); | |
1237 | DECODE_CLEAR_SEGOVR(); | |
1238 | END_OF_INSTR(); | |
1239 | } | |
1240 | ||
1241 | /**************************************************************************** | |
1242 | REMARKS: | |
1243 | Handles opcode 0x70 - 0x7F | |
1244 | ****************************************************************************/ | |
1245 | int x86emu_check_jump_condition(u8 op); | |
1246 | ||
1247 | void x86emuOp_jump_near_cond(u8 op1) | |
1248 | { | |
1249 | s8 offset; | |
1250 | u16 target; | |
1251 | int cond; | |
1252 | ||
1253 | /* jump to byte offset if overflow flag is set */ | |
1254 | START_OF_INSTR(); | |
1255 | cond = x86emu_check_jump_condition(op1 & 0xF); | |
1256 | offset = (s8)fetch_byte_imm(); | |
1257 | target = (u16)(M.x86.R_IP + (s16)offset); | |
1258 | DECODE_PRINTF2("%x\n", target); | |
1259 | TRACE_AND_STEP(); | |
1260 | if (cond) | |
9c7e4b06 | 1261 | M.x86.R_IP = target; |
ece92f85 JJ |
1262 | DECODE_CLEAR_SEGOVR(); |
1263 | END_OF_INSTR(); | |
1264 | } | |
1265 | ||
1266 | /**************************************************************************** | |
1267 | REMARKS: | |
1268 | Handles opcode 0x80 | |
1269 | ****************************************************************************/ | |
1270 | void x86emuOp_opc80_byte_RM_IMM(u8 X86EMU_UNUSED(op1)) | |
1271 | { | |
1272 | int mod, rl, rh; | |
1273 | u8 *destreg; | |
1274 | uint destoffset; | |
1275 | u8 imm; | |
1276 | u8 destval; | |
1277 | ||
1278 | /* | |
9c7e4b06 | 1279 | * Weirdo special case instruction format. Part of the opcode |
ece92f85 JJ |
1280 | * held below in "RH". Doubly nested case would result, except |
1281 | * that the decoded instruction | |
1282 | */ | |
1283 | START_OF_INSTR(); | |
1284 | FETCH_DECODE_MODRM(mod, rh, rl); | |
b3521f2e | 1285 | #ifdef CONFIG_X86EMU_DEBUG |
ece92f85 | 1286 | if (DEBUG_DECODE()) { |
9c7e4b06 WD |
1287 | /* XXX DECODE_PRINTF may be changed to something more |
1288 | general, so that it is important to leave the strings | |
1289 | in the same format, even though the result is that the | |
1290 | above test is done twice. */ | |
1291 | ||
1292 | switch (rh) { | |
1293 | case 0: | |
1294 | DECODE_PRINTF("ADD\t"); | |
1295 | break; | |
1296 | case 1: | |
1297 | DECODE_PRINTF("OR\t"); | |
1298 | break; | |
1299 | case 2: | |
1300 | DECODE_PRINTF("ADC\t"); | |
1301 | break; | |
1302 | case 3: | |
1303 | DECODE_PRINTF("SBB\t"); | |
1304 | break; | |
1305 | case 4: | |
1306 | DECODE_PRINTF("AND\t"); | |
1307 | break; | |
1308 | case 5: | |
1309 | DECODE_PRINTF("SUB\t"); | |
1310 | break; | |
1311 | case 6: | |
1312 | DECODE_PRINTF("XOR\t"); | |
1313 | break; | |
1314 | case 7: | |
1315 | DECODE_PRINTF("CMP\t"); | |
1316 | break; | |
1317 | } | |
ece92f85 JJ |
1318 | } |
1319 | #endif | |
1320 | /* know operation, decode the mod byte to find the addressing | |
1321 | mode. */ | |
1322 | if (mod < 3) { | |
9c7e4b06 WD |
1323 | DECODE_PRINTF("BYTE PTR "); |
1324 | destoffset = decode_rmXX_address(mod, rl); | |
1325 | DECODE_PRINTF(","); | |
1326 | destval = fetch_data_byte(destoffset); | |
1327 | imm = fetch_byte_imm(); | |
1328 | DECODE_PRINTF2("%x\n", imm); | |
1329 | TRACE_AND_STEP(); | |
1330 | destval = (*genop_byte_operation[rh]) (destval, imm); | |
1331 | if (rh != 7) | |
1332 | store_data_byte(destoffset, destval); | |
1333 | } else { /* register to register */ | |
1334 | destreg = DECODE_RM_BYTE_REGISTER(rl); | |
1335 | DECODE_PRINTF(","); | |
1336 | imm = fetch_byte_imm(); | |
1337 | DECODE_PRINTF2("%x\n", imm); | |
1338 | TRACE_AND_STEP(); | |
1339 | destval = (*genop_byte_operation[rh]) (*destreg, imm); | |
1340 | if (rh != 7) | |
1341 | *destreg = destval; | |
ece92f85 JJ |
1342 | } |
1343 | DECODE_CLEAR_SEGOVR(); | |
1344 | END_OF_INSTR(); | |
1345 | } | |
1346 | ||
1347 | /**************************************************************************** | |
1348 | REMARKS: | |
1349 | Handles opcode 0x81 | |
1350 | ****************************************************************************/ | |
1351 | void x86emuOp_opc81_word_RM_IMM(u8 X86EMU_UNUSED(op1)) | |
1352 | { | |
1353 | int mod, rl, rh; | |
1354 | uint destoffset; | |
1355 | ||
1356 | /* | |
9c7e4b06 | 1357 | * Weirdo special case instruction format. Part of the opcode |
ece92f85 JJ |
1358 | * held below in "RH". Doubly nested case would result, except |
1359 | * that the decoded instruction | |
1360 | */ | |
1361 | START_OF_INSTR(); | |
1362 | FETCH_DECODE_MODRM(mod, rh, rl); | |
b3521f2e | 1363 | #ifdef CONFIG_X86EMU_DEBUG |
ece92f85 | 1364 | if (DEBUG_DECODE()) { |
9c7e4b06 WD |
1365 | /* XXX DECODE_PRINTF may be changed to something more |
1366 | general, so that it is important to leave the strings | |
1367 | in the same format, even though the result is that the | |
1368 | above test is done twice. */ | |
1369 | ||
1370 | switch (rh) { | |
1371 | case 0: | |
1372 | DECODE_PRINTF("ADD\t"); | |
1373 | break; | |
1374 | case 1: | |
1375 | DECODE_PRINTF("OR\t"); | |
1376 | break; | |
1377 | case 2: | |
1378 | DECODE_PRINTF("ADC\t"); | |
1379 | break; | |
1380 | case 3: | |
1381 | DECODE_PRINTF("SBB\t"); | |
1382 | break; | |
1383 | case 4: | |
1384 | DECODE_PRINTF("AND\t"); | |
1385 | break; | |
1386 | case 5: | |
1387 | DECODE_PRINTF("SUB\t"); | |
1388 | break; | |
1389 | case 6: | |
1390 | DECODE_PRINTF("XOR\t"); | |
1391 | break; | |
1392 | case 7: | |
1393 | DECODE_PRINTF("CMP\t"); | |
1394 | break; | |
1395 | } | |
ece92f85 JJ |
1396 | } |
1397 | #endif | |
1398 | /* | |
1399 | * Know operation, decode the mod byte to find the addressing | |
1400 | * mode. | |
1401 | */ | |
1402 | if (mod < 3) { | |
9c7e4b06 WD |
1403 | DECODE_PRINTF("DWORD PTR "); |
1404 | destoffset = decode_rmXX_address(mod, rl); | |
1405 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
1406 | u32 destval,imm; | |
1407 | ||
1408 | DECODE_PRINTF(","); | |
1409 | destval = fetch_data_long(destoffset); | |
1410 | imm = fetch_long_imm(); | |
1411 | DECODE_PRINTF2("%x\n", imm); | |
1412 | TRACE_AND_STEP(); | |
1413 | destval = (*genop_long_operation[rh]) (destval, imm); | |
1414 | if (rh != 7) | |
1415 | store_data_long(destoffset, destval); | |
1416 | } else { | |
1417 | u16 destval,imm; | |
1418 | ||
1419 | DECODE_PRINTF(","); | |
1420 | destval = fetch_data_word(destoffset); | |
1421 | imm = fetch_word_imm(); | |
1422 | DECODE_PRINTF2("%x\n", imm); | |
1423 | TRACE_AND_STEP(); | |
1424 | destval = (*genop_word_operation[rh]) (destval, imm); | |
1425 | if (rh != 7) | |
1426 | store_data_word(destoffset, destval); | |
1427 | } | |
1428 | } else { /* register to register */ | |
1429 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
1430 | u32 *destreg; | |
1431 | u32 destval,imm; | |
1432 | ||
1433 | destreg = DECODE_RM_LONG_REGISTER(rl); | |
1434 | DECODE_PRINTF(","); | |
1435 | imm = fetch_long_imm(); | |
1436 | DECODE_PRINTF2("%x\n", imm); | |
1437 | TRACE_AND_STEP(); | |
1438 | destval = (*genop_long_operation[rh]) (*destreg, imm); | |
1439 | if (rh != 7) | |
1440 | *destreg = destval; | |
1441 | } else { | |
1442 | u16 *destreg; | |
1443 | u16 destval,imm; | |
1444 | ||
1445 | destreg = DECODE_RM_WORD_REGISTER(rl); | |
1446 | DECODE_PRINTF(","); | |
1447 | imm = fetch_word_imm(); | |
1448 | DECODE_PRINTF2("%x\n", imm); | |
1449 | TRACE_AND_STEP(); | |
1450 | destval = (*genop_word_operation[rh]) (*destreg, imm); | |
1451 | if (rh != 7) | |
1452 | *destreg = destval; | |
1453 | } | |
ece92f85 JJ |
1454 | } |
1455 | DECODE_CLEAR_SEGOVR(); | |
1456 | END_OF_INSTR(); | |
1457 | } | |
1458 | ||
1459 | /**************************************************************************** | |
1460 | REMARKS: | |
1461 | Handles opcode 0x82 | |
1462 | ****************************************************************************/ | |
1463 | void x86emuOp_opc82_byte_RM_IMM(u8 X86EMU_UNUSED(op1)) | |
1464 | { | |
1465 | int mod, rl, rh; | |
1466 | u8 *destreg; | |
1467 | uint destoffset; | |
1468 | u8 imm; | |
1469 | u8 destval; | |
1470 | ||
1471 | /* | |
9c7e4b06 | 1472 | * Weirdo special case instruction format. Part of the opcode |
ece92f85 JJ |
1473 | * held below in "RH". Doubly nested case would result, except |
1474 | * that the decoded instruction Similar to opcode 81, except that | |
1475 | * the immediate byte is sign extended to a word length. | |
1476 | */ | |
1477 | START_OF_INSTR(); | |
1478 | FETCH_DECODE_MODRM(mod, rh, rl); | |
b3521f2e | 1479 | #ifdef CONFIG_X86EMU_DEBUG |
ece92f85 | 1480 | if (DEBUG_DECODE()) { |
9c7e4b06 WD |
1481 | /* XXX DECODE_PRINTF may be changed to something more |
1482 | general, so that it is important to leave the strings | |
1483 | in the same format, even though the result is that the | |
1484 | above test is done twice. */ | |
1485 | switch (rh) { | |
1486 | case 0: | |
1487 | DECODE_PRINTF("ADD\t"); | |
1488 | break; | |
1489 | case 1: | |
1490 | DECODE_PRINTF("OR\t"); | |
1491 | break; | |
1492 | case 2: | |
1493 | DECODE_PRINTF("ADC\t"); | |
1494 | break; | |
1495 | case 3: | |
1496 | DECODE_PRINTF("SBB\t"); | |
1497 | break; | |
1498 | case 4: | |
1499 | DECODE_PRINTF("AND\t"); | |
1500 | break; | |
1501 | case 5: | |
1502 | DECODE_PRINTF("SUB\t"); | |
1503 | break; | |
1504 | case 6: | |
1505 | DECODE_PRINTF("XOR\t"); | |
1506 | break; | |
1507 | case 7: | |
1508 | DECODE_PRINTF("CMP\t"); | |
1509 | break; | |
1510 | } | |
ece92f85 JJ |
1511 | } |
1512 | #endif | |
1513 | /* know operation, decode the mod byte to find the addressing | |
1514 | mode. */ | |
1515 | if (mod < 3) { | |
9c7e4b06 WD |
1516 | DECODE_PRINTF("BYTE PTR "); |
1517 | destoffset = decode_rmXX_address(mod, rl); | |
1518 | destval = fetch_data_byte(destoffset); | |
1519 | imm = fetch_byte_imm(); | |
1520 | DECODE_PRINTF2(",%x\n", imm); | |
1521 | TRACE_AND_STEP(); | |
1522 | destval = (*genop_byte_operation[rh]) (destval, imm); | |
1523 | if (rh != 7) | |
1524 | store_data_byte(destoffset, destval); | |
1525 | } else { /* register to register */ | |
1526 | destreg = DECODE_RM_BYTE_REGISTER(rl); | |
1527 | imm = fetch_byte_imm(); | |
1528 | DECODE_PRINTF2(",%x\n", imm); | |
1529 | TRACE_AND_STEP(); | |
1530 | destval = (*genop_byte_operation[rh]) (*destreg, imm); | |
1531 | if (rh != 7) | |
1532 | *destreg = destval; | |
ece92f85 JJ |
1533 | } |
1534 | DECODE_CLEAR_SEGOVR(); | |
1535 | END_OF_INSTR(); | |
1536 | } | |
1537 | ||
1538 | /**************************************************************************** | |
1539 | REMARKS: | |
1540 | Handles opcode 0x83 | |
1541 | ****************************************************************************/ | |
1542 | void x86emuOp_opc83_word_RM_IMM(u8 X86EMU_UNUSED(op1)) | |
1543 | { | |
1544 | int mod, rl, rh; | |
1545 | uint destoffset; | |
1546 | ||
1547 | /* | |
9c7e4b06 | 1548 | * Weirdo special case instruction format. Part of the opcode |
ece92f85 JJ |
1549 | * held below in "RH". Doubly nested case would result, except |
1550 | * that the decoded instruction Similar to opcode 81, except that | |
1551 | * the immediate byte is sign extended to a word length. | |
1552 | */ | |
1553 | START_OF_INSTR(); | |
1554 | FETCH_DECODE_MODRM(mod, rh, rl); | |
b3521f2e | 1555 | #ifdef CONFIG_X86EMU_DEBUG |
ece92f85 | 1556 | if (DEBUG_DECODE()) { |
9c7e4b06 WD |
1557 | /* XXX DECODE_PRINTF may be changed to something more |
1558 | general, so that it is important to leave the strings | |
1559 | in the same format, even though the result is that the | |
1560 | above test is done twice. */ | |
ece92f85 | 1561 | switch (rh) { |
9c7e4b06 WD |
1562 | case 0: |
1563 | DECODE_PRINTF("ADD\t"); | |
1564 | break; | |
1565 | case 1: | |
1566 | DECODE_PRINTF("OR\t"); | |
1567 | break; | |
1568 | case 2: | |
1569 | DECODE_PRINTF("ADC\t"); | |
1570 | break; | |
1571 | case 3: | |
1572 | DECODE_PRINTF("SBB\t"); | |
1573 | break; | |
1574 | case 4: | |
1575 | DECODE_PRINTF("AND\t"); | |
1576 | break; | |
1577 | case 5: | |
1578 | DECODE_PRINTF("SUB\t"); | |
1579 | break; | |
1580 | case 6: | |
1581 | DECODE_PRINTF("XOR\t"); | |
1582 | break; | |
1583 | case 7: | |
1584 | DECODE_PRINTF("CMP\t"); | |
1585 | break; | |
1586 | } | |
ece92f85 JJ |
1587 | } |
1588 | #endif | |
1589 | /* know operation, decode the mod byte to find the addressing | |
1590 | mode. */ | |
1591 | if (mod < 3) { | |
9c7e4b06 WD |
1592 | DECODE_PRINTF("DWORD PTR "); |
1593 | destoffset = decode_rmXX_address(mod,rl); | |
1594 | ||
1595 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
1596 | u32 destval,imm; | |
1597 | ||
1598 | destval = fetch_data_long(destoffset); | |
1599 | imm = (s8) fetch_byte_imm(); | |
1600 | DECODE_PRINTF2(",%x\n", imm); | |
1601 | TRACE_AND_STEP(); | |
1602 | destval = (*genop_long_operation[rh]) (destval, imm); | |
1603 | if (rh != 7) | |
1604 | store_data_long(destoffset, destval); | |
1605 | } else { | |
1606 | u16 destval,imm; | |
1607 | ||
1608 | destval = fetch_data_word(destoffset); | |
1609 | imm = (s8) fetch_byte_imm(); | |
1610 | DECODE_PRINTF2(",%x\n", imm); | |
1611 | TRACE_AND_STEP(); | |
1612 | destval = (*genop_word_operation[rh]) (destval, imm); | |
1613 | if (rh != 7) | |
1614 | store_data_word(destoffset, destval); | |
1615 | } | |
1616 | } else { /* register to register */ | |
1617 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
1618 | u32 *destreg; | |
1619 | u32 destval,imm; | |
1620 | ||
1621 | destreg = DECODE_RM_LONG_REGISTER(rl); | |
1622 | imm = (s8) fetch_byte_imm(); | |
1623 | DECODE_PRINTF2(",%x\n", imm); | |
1624 | TRACE_AND_STEP(); | |
1625 | destval = (*genop_long_operation[rh]) (*destreg, imm); | |
1626 | if (rh != 7) | |
1627 | *destreg = destval; | |
1628 | } else { | |
1629 | u16 *destreg; | |
1630 | u16 destval,imm; | |
1631 | ||
1632 | destreg = DECODE_RM_WORD_REGISTER(rl); | |
1633 | imm = (s8) fetch_byte_imm(); | |
1634 | DECODE_PRINTF2(",%x\n", imm); | |
1635 | TRACE_AND_STEP(); | |
1636 | destval = (*genop_word_operation[rh]) (*destreg, imm); | |
1637 | if (rh != 7) | |
1638 | *destreg = destval; | |
1639 | } | |
ece92f85 JJ |
1640 | } |
1641 | DECODE_CLEAR_SEGOVR(); | |
1642 | END_OF_INSTR(); | |
1643 | } | |
1644 | ||
1645 | /**************************************************************************** | |
1646 | REMARKS: | |
1647 | Handles opcode 0x84 | |
1648 | ****************************************************************************/ | |
1649 | void x86emuOp_test_byte_RM_R(u8 X86EMU_UNUSED(op1)) | |
1650 | { | |
1651 | int mod, rl, rh; | |
1652 | u8 *destreg, *srcreg; | |
1653 | uint destoffset; | |
1654 | u8 destval; | |
1655 | ||
1656 | START_OF_INSTR(); | |
1657 | DECODE_PRINTF("TEST\t"); | |
1658 | FETCH_DECODE_MODRM(mod, rh, rl); | |
1659 | if (mod < 3) { | |
9c7e4b06 WD |
1660 | destoffset = decode_rmXX_address(mod, rl); |
1661 | DECODE_PRINTF(","); | |
1662 | destval = fetch_data_byte(destoffset); | |
1663 | srcreg = DECODE_RM_BYTE_REGISTER(rh); | |
1664 | DECODE_PRINTF("\n"); | |
1665 | TRACE_AND_STEP(); | |
1666 | test_byte(destval, *srcreg); | |
1667 | } else { /* register to register */ | |
1668 | destreg = DECODE_RM_BYTE_REGISTER(rl); | |
1669 | DECODE_PRINTF(","); | |
1670 | srcreg = DECODE_RM_BYTE_REGISTER(rh); | |
1671 | DECODE_PRINTF("\n"); | |
1672 | TRACE_AND_STEP(); | |
1673 | test_byte(*destreg, *srcreg); | |
ece92f85 JJ |
1674 | } |
1675 | DECODE_CLEAR_SEGOVR(); | |
1676 | END_OF_INSTR(); | |
1677 | } | |
1678 | ||
1679 | /**************************************************************************** | |
1680 | REMARKS: | |
1681 | Handles opcode 0x85 | |
1682 | ****************************************************************************/ | |
1683 | void x86emuOp_test_word_RM_R(u8 X86EMU_UNUSED(op1)) | |
1684 | { | |
1685 | int mod, rl, rh; | |
1686 | uint destoffset; | |
1687 | ||
1688 | START_OF_INSTR(); | |
1689 | DECODE_PRINTF("TEST\t"); | |
1690 | FETCH_DECODE_MODRM(mod, rh, rl); | |
1691 | if (mod < 3) { | |
9c7e4b06 WD |
1692 | destoffset = decode_rmXX_address(mod, rl); |
1693 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
1694 | u32 destval; | |
1695 | u32 *srcreg; | |
1696 | ||
1697 | DECODE_PRINTF(","); | |
1698 | destval = fetch_data_long(destoffset); | |
1699 | srcreg = DECODE_RM_LONG_REGISTER(rh); | |
1700 | DECODE_PRINTF("\n"); | |
1701 | TRACE_AND_STEP(); | |
1702 | test_long(destval, *srcreg); | |
1703 | } else { | |
1704 | u16 destval; | |
1705 | u16 *srcreg; | |
1706 | ||
1707 | DECODE_PRINTF(","); | |
1708 | destval = fetch_data_word(destoffset); | |
1709 | srcreg = DECODE_RM_WORD_REGISTER(rh); | |
1710 | DECODE_PRINTF("\n"); | |
1711 | TRACE_AND_STEP(); | |
1712 | test_word(destval, *srcreg); | |
1713 | } | |
1714 | } else { /* register to register */ | |
1715 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
1716 | u32 *destreg,*srcreg; | |
1717 | ||
1718 | destreg = DECODE_RM_LONG_REGISTER(rl); | |
1719 | DECODE_PRINTF(","); | |
1720 | srcreg = DECODE_RM_LONG_REGISTER(rh); | |
1721 | DECODE_PRINTF("\n"); | |
1722 | TRACE_AND_STEP(); | |
1723 | test_long(*destreg, *srcreg); | |
1724 | } else { | |
1725 | u16 *destreg,*srcreg; | |
1726 | ||
1727 | destreg = DECODE_RM_WORD_REGISTER(rl); | |
1728 | DECODE_PRINTF(","); | |
1729 | srcreg = DECODE_RM_WORD_REGISTER(rh); | |
1730 | DECODE_PRINTF("\n"); | |
1731 | TRACE_AND_STEP(); | |
1732 | test_word(*destreg, *srcreg); | |
1733 | } | |
ece92f85 JJ |
1734 | } |
1735 | DECODE_CLEAR_SEGOVR(); | |
1736 | END_OF_INSTR(); | |
1737 | } | |
1738 | ||
1739 | /**************************************************************************** | |
1740 | REMARKS: | |
1741 | Handles opcode 0x86 | |
1742 | ****************************************************************************/ | |
1743 | void x86emuOp_xchg_byte_RM_R(u8 X86EMU_UNUSED(op1)) | |
1744 | { | |
1745 | int mod, rl, rh; | |
1746 | u8 *destreg, *srcreg; | |
1747 | uint destoffset; | |
1748 | u8 destval; | |
1749 | u8 tmp; | |
1750 | ||
1751 | START_OF_INSTR(); | |
1752 | DECODE_PRINTF("XCHG\t"); | |
1753 | FETCH_DECODE_MODRM(mod, rh, rl); | |
1754 | if (mod < 3) { | |
9c7e4b06 WD |
1755 | destoffset = decode_rmXX_address(mod, rl); |
1756 | DECODE_PRINTF(","); | |
1757 | destval = fetch_data_byte(destoffset); | |
1758 | srcreg = DECODE_RM_BYTE_REGISTER(rh); | |
1759 | DECODE_PRINTF("\n"); | |
1760 | TRACE_AND_STEP(); | |
1761 | tmp = *srcreg; | |
1762 | *srcreg = destval; | |
1763 | destval = tmp; | |
1764 | store_data_byte(destoffset, destval); | |
1765 | } else { /* register to register */ | |
1766 | destreg = DECODE_RM_BYTE_REGISTER(rl); | |
1767 | DECODE_PRINTF(","); | |
1768 | srcreg = DECODE_RM_BYTE_REGISTER(rh); | |
1769 | DECODE_PRINTF("\n"); | |
1770 | TRACE_AND_STEP(); | |
1771 | tmp = *srcreg; | |
1772 | *srcreg = *destreg; | |
1773 | *destreg = tmp; | |
ece92f85 JJ |
1774 | } |
1775 | DECODE_CLEAR_SEGOVR(); | |
1776 | END_OF_INSTR(); | |
1777 | } | |
1778 | ||
1779 | /**************************************************************************** | |
1780 | REMARKS: | |
1781 | Handles opcode 0x87 | |
1782 | ****************************************************************************/ | |
1783 | void x86emuOp_xchg_word_RM_R(u8 X86EMU_UNUSED(op1)) | |
1784 | { | |
1785 | int mod, rl, rh; | |
1786 | uint destoffset; | |
1787 | ||
1788 | START_OF_INSTR(); | |
1789 | DECODE_PRINTF("XCHG\t"); | |
1790 | FETCH_DECODE_MODRM(mod, rh, rl); | |
1791 | if (mod < 3) { | |
9c7e4b06 WD |
1792 | destoffset = decode_rmXX_address(mod, rl); |
1793 | DECODE_PRINTF(","); | |
1794 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
1795 | u32 *srcreg; | |
1796 | u32 destval,tmp; | |
1797 | ||
1798 | destval = fetch_data_long(destoffset); | |
1799 | srcreg = DECODE_RM_LONG_REGISTER(rh); | |
1800 | DECODE_PRINTF("\n"); | |
1801 | TRACE_AND_STEP(); | |
1802 | tmp = *srcreg; | |
1803 | *srcreg = destval; | |
1804 | destval = tmp; | |
1805 | store_data_long(destoffset, destval); | |
1806 | } else { | |
1807 | u16 *srcreg; | |
1808 | u16 destval,tmp; | |
1809 | ||
1810 | destval = fetch_data_word(destoffset); | |
1811 | srcreg = DECODE_RM_WORD_REGISTER(rh); | |
1812 | DECODE_PRINTF("\n"); | |
1813 | TRACE_AND_STEP(); | |
1814 | tmp = *srcreg; | |
1815 | *srcreg = destval; | |
1816 | destval = tmp; | |
1817 | store_data_word(destoffset, destval); | |
1818 | } | |
1819 | } else { /* register to register */ | |
1820 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
1821 | u32 *destreg,*srcreg; | |
1822 | u32 tmp; | |
1823 | ||
1824 | destreg = DECODE_RM_LONG_REGISTER(rl); | |
1825 | DECODE_PRINTF(","); | |
1826 | srcreg = DECODE_RM_LONG_REGISTER(rh); | |
1827 | DECODE_PRINTF("\n"); | |
1828 | TRACE_AND_STEP(); | |
1829 | tmp = *srcreg; | |
1830 | *srcreg = *destreg; | |
1831 | *destreg = tmp; | |
1832 | } else { | |
1833 | u16 *destreg,*srcreg; | |
1834 | u16 tmp; | |
1835 | ||
1836 | destreg = DECODE_RM_WORD_REGISTER(rl); | |
1837 | DECODE_PRINTF(","); | |
1838 | srcreg = DECODE_RM_WORD_REGISTER(rh); | |
1839 | DECODE_PRINTF("\n"); | |
1840 | TRACE_AND_STEP(); | |
1841 | tmp = *srcreg; | |
1842 | *srcreg = *destreg; | |
1843 | *destreg = tmp; | |
1844 | } | |
ece92f85 JJ |
1845 | } |
1846 | DECODE_CLEAR_SEGOVR(); | |
1847 | END_OF_INSTR(); | |
1848 | } | |
1849 | ||
1850 | /**************************************************************************** | |
1851 | REMARKS: | |
1852 | Handles opcode 0x88 | |
1853 | ****************************************************************************/ | |
1854 | void x86emuOp_mov_byte_RM_R(u8 X86EMU_UNUSED(op1)) | |
1855 | { | |
1856 | int mod, rl, rh; | |
1857 | u8 *destreg, *srcreg; | |
1858 | uint destoffset; | |
1859 | ||
1860 | START_OF_INSTR(); | |
1861 | DECODE_PRINTF("MOV\t"); | |
1862 | FETCH_DECODE_MODRM(mod, rh, rl); | |
1863 | if (mod < 3) { | |
9c7e4b06 WD |
1864 | destoffset = decode_rmXX_address(mod, rl); |
1865 | DECODE_PRINTF(","); | |
1866 | srcreg = DECODE_RM_BYTE_REGISTER(rh); | |
1867 | DECODE_PRINTF("\n"); | |
1868 | TRACE_AND_STEP(); | |
1869 | store_data_byte(destoffset, *srcreg); | |
1870 | } else { /* register to register */ | |
1871 | destreg = DECODE_RM_BYTE_REGISTER(rl); | |
1872 | DECODE_PRINTF(","); | |
1873 | srcreg = DECODE_RM_BYTE_REGISTER(rh); | |
1874 | DECODE_PRINTF("\n"); | |
1875 | TRACE_AND_STEP(); | |
1876 | *destreg = *srcreg; | |
ece92f85 JJ |
1877 | } |
1878 | DECODE_CLEAR_SEGOVR(); | |
1879 | END_OF_INSTR(); | |
1880 | } | |
1881 | ||
1882 | /**************************************************************************** | |
1883 | REMARKS: | |
1884 | Handles opcode 0x89 | |
1885 | ****************************************************************************/ | |
1886 | void x86emuOp_mov_word_RM_R(u8 X86EMU_UNUSED(op1)) | |
1887 | { | |
1888 | int mod, rl, rh; | |
1889 | uint destoffset; | |
1890 | ||
1891 | START_OF_INSTR(); | |
1892 | DECODE_PRINTF("MOV\t"); | |
1893 | FETCH_DECODE_MODRM(mod, rh, rl); | |
1894 | if (mod < 3) { | |
9c7e4b06 WD |
1895 | destoffset = decode_rmXX_address(mod, rl); |
1896 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
1897 | u32 *srcreg; | |
1898 | ||
1899 | DECODE_PRINTF(","); | |
1900 | srcreg = DECODE_RM_LONG_REGISTER(rh); | |
1901 | DECODE_PRINTF("\n"); | |
1902 | TRACE_AND_STEP(); | |
1903 | store_data_long(destoffset, *srcreg); | |
1904 | } else { | |
1905 | u16 *srcreg; | |
1906 | ||
1907 | DECODE_PRINTF(","); | |
1908 | srcreg = DECODE_RM_WORD_REGISTER(rh); | |
1909 | DECODE_PRINTF("\n"); | |
1910 | TRACE_AND_STEP(); | |
1911 | store_data_word(destoffset, *srcreg); | |
1912 | } | |
1913 | } else { /* register to register */ | |
1914 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
1915 | u32 *destreg,*srcreg; | |
1916 | ||
1917 | destreg = DECODE_RM_LONG_REGISTER(rl); | |
1918 | DECODE_PRINTF(","); | |
1919 | srcreg = DECODE_RM_LONG_REGISTER(rh); | |
1920 | DECODE_PRINTF("\n"); | |
1921 | TRACE_AND_STEP(); | |
1922 | *destreg = *srcreg; | |
1923 | } else { | |
1924 | u16 *destreg,*srcreg; | |
1925 | ||
1926 | destreg = DECODE_RM_WORD_REGISTER(rl); | |
1927 | DECODE_PRINTF(","); | |
1928 | srcreg = DECODE_RM_WORD_REGISTER(rh); | |
1929 | DECODE_PRINTF("\n"); | |
1930 | TRACE_AND_STEP(); | |
1931 | *destreg = *srcreg; | |
1932 | } | |
ece92f85 JJ |
1933 | } |
1934 | DECODE_CLEAR_SEGOVR(); | |
1935 | END_OF_INSTR(); | |
1936 | } | |
1937 | ||
1938 | /**************************************************************************** | |
1939 | REMARKS: | |
1940 | Handles opcode 0x8a | |
1941 | ****************************************************************************/ | |
1942 | void x86emuOp_mov_byte_R_RM(u8 X86EMU_UNUSED(op1)) | |
1943 | { | |
1944 | int mod, rl, rh; | |
1945 | u8 *destreg, *srcreg; | |
1946 | uint srcoffset; | |
1947 | u8 srcval; | |
1948 | ||
1949 | START_OF_INSTR(); | |
1950 | DECODE_PRINTF("MOV\t"); | |
1951 | FETCH_DECODE_MODRM(mod, rh, rl); | |
1952 | if (mod < 3) { | |
9c7e4b06 WD |
1953 | destreg = DECODE_RM_BYTE_REGISTER(rh); |
1954 | DECODE_PRINTF(","); | |
1955 | srcoffset = decode_rmXX_address(mod, rl); | |
1956 | srcval = fetch_data_byte(srcoffset); | |
1957 | DECODE_PRINTF("\n"); | |
1958 | TRACE_AND_STEP(); | |
1959 | *destreg = srcval; | |
1960 | } else { /* register to register */ | |
1961 | destreg = DECODE_RM_BYTE_REGISTER(rh); | |
1962 | DECODE_PRINTF(","); | |
1963 | srcreg = DECODE_RM_BYTE_REGISTER(rl); | |
1964 | DECODE_PRINTF("\n"); | |
1965 | TRACE_AND_STEP(); | |
1966 | *destreg = *srcreg; | |
ece92f85 JJ |
1967 | } |
1968 | DECODE_CLEAR_SEGOVR(); | |
1969 | END_OF_INSTR(); | |
1970 | } | |
1971 | ||
1972 | /**************************************************************************** | |
1973 | REMARKS: | |
1974 | Handles opcode 0x8b | |
1975 | ****************************************************************************/ | |
1976 | void x86emuOp_mov_word_R_RM(u8 X86EMU_UNUSED(op1)) | |
1977 | { | |
1978 | int mod, rl, rh; | |
1979 | uint srcoffset; | |
1980 | ||
1981 | START_OF_INSTR(); | |
1982 | DECODE_PRINTF("MOV\t"); | |
1983 | FETCH_DECODE_MODRM(mod, rh, rl); | |
1984 | if (mod < 3) { | |
9c7e4b06 WD |
1985 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { |
1986 | u32 *destreg; | |
1987 | u32 srcval; | |
1988 | ||
1989 | destreg = DECODE_RM_LONG_REGISTER(rh); | |
1990 | DECODE_PRINTF(","); | |
1991 | srcoffset = decode_rmXX_address(mod, rl); | |
1992 | srcval = fetch_data_long(srcoffset); | |
1993 | DECODE_PRINTF("\n"); | |
1994 | TRACE_AND_STEP(); | |
1995 | *destreg = srcval; | |
1996 | } else { | |
1997 | u16 *destreg; | |
1998 | u16 srcval; | |
1999 | ||
2000 | destreg = DECODE_RM_WORD_REGISTER(rh); | |
2001 | DECODE_PRINTF(","); | |
2002 | srcoffset = decode_rmXX_address(mod, rl); | |
2003 | srcval = fetch_data_word(srcoffset); | |
2004 | DECODE_PRINTF("\n"); | |
2005 | TRACE_AND_STEP(); | |
2006 | *destreg = srcval; | |
2007 | } | |
2008 | } else { /* register to register */ | |
2009 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
2010 | u32 *destreg, *srcreg; | |
2011 | ||
2012 | destreg = DECODE_RM_LONG_REGISTER(rh); | |
2013 | DECODE_PRINTF(","); | |
2014 | srcreg = DECODE_RM_LONG_REGISTER(rl); | |
2015 | DECODE_PRINTF("\n"); | |
2016 | TRACE_AND_STEP(); | |
2017 | *destreg = *srcreg; | |
2018 | } else { | |
2019 | u16 *destreg, *srcreg; | |
2020 | ||
2021 | destreg = DECODE_RM_WORD_REGISTER(rh); | |
2022 | DECODE_PRINTF(","); | |
2023 | srcreg = DECODE_RM_WORD_REGISTER(rl); | |
2024 | DECODE_PRINTF("\n"); | |
2025 | TRACE_AND_STEP(); | |
2026 | *destreg = *srcreg; | |
2027 | } | |
ece92f85 JJ |
2028 | } |
2029 | DECODE_CLEAR_SEGOVR(); | |
2030 | END_OF_INSTR(); | |
2031 | } | |
2032 | ||
2033 | /**************************************************************************** | |
2034 | REMARKS: | |
2035 | Handles opcode 0x8c | |
2036 | ****************************************************************************/ | |
2037 | void x86emuOp_mov_word_RM_SR(u8 X86EMU_UNUSED(op1)) | |
2038 | { | |
2039 | int mod, rl, rh; | |
2040 | u16 *destreg, *srcreg; | |
2041 | uint destoffset; | |
2042 | u16 destval; | |
2043 | ||
2044 | START_OF_INSTR(); | |
2045 | DECODE_PRINTF("MOV\t"); | |
2046 | FETCH_DECODE_MODRM(mod, rh, rl); | |
2047 | if (mod < 3) { | |
9c7e4b06 WD |
2048 | destoffset = decode_rmXX_address(mod, rl); |
2049 | DECODE_PRINTF(","); | |
2050 | srcreg = decode_rm_seg_register(rh); | |
2051 | DECODE_PRINTF("\n"); | |
2052 | TRACE_AND_STEP(); | |
2053 | destval = *srcreg; | |
2054 | store_data_word(destoffset, destval); | |
2055 | } else { /* register to register */ | |
2056 | destreg = DECODE_RM_WORD_REGISTER(rl); | |
2057 | DECODE_PRINTF(","); | |
2058 | srcreg = decode_rm_seg_register(rh); | |
2059 | DECODE_PRINTF("\n"); | |
2060 | TRACE_AND_STEP(); | |
2061 | *destreg = *srcreg; | |
ece92f85 JJ |
2062 | } |
2063 | DECODE_CLEAR_SEGOVR(); | |
2064 | END_OF_INSTR(); | |
2065 | } | |
2066 | ||
2067 | /**************************************************************************** | |
2068 | REMARKS: | |
2069 | Handles opcode 0x8d | |
2070 | ****************************************************************************/ | |
2071 | void x86emuOp_lea_word_R_M(u8 X86EMU_UNUSED(op1)) | |
2072 | { | |
2073 | int mod, rl, rh; | |
2074 | u16 *srcreg; | |
2075 | uint destoffset; | |
2076 | ||
2077 | /* | |
2078 | * TODO: Need to handle address size prefix! | |
2079 | * | |
9c7e4b06 | 2080 | * lea eax,[eax+ebx*2] ?? |
ece92f85 JJ |
2081 | */ |
2082 | ||
2083 | START_OF_INSTR(); | |
2084 | DECODE_PRINTF("LEA\t"); | |
2085 | FETCH_DECODE_MODRM(mod, rh, rl); | |
2086 | if (mod < 3) { | |
9c7e4b06 WD |
2087 | srcreg = DECODE_RM_WORD_REGISTER(rh); |
2088 | DECODE_PRINTF(","); | |
2089 | destoffset = decode_rmXX_address(mod, rl); | |
2090 | DECODE_PRINTF("\n"); | |
2091 | TRACE_AND_STEP(); | |
2092 | *srcreg = (u16)destoffset; | |
2093 | } | |
ece92f85 JJ |
2094 | /* } else { undefined. Do nothing. } */ |
2095 | DECODE_CLEAR_SEGOVR(); | |
2096 | END_OF_INSTR(); | |
2097 | } | |
2098 | ||
2099 | /**************************************************************************** | |
2100 | REMARKS: | |
2101 | Handles opcode 0x8e | |
2102 | ****************************************************************************/ | |
2103 | void x86emuOp_mov_word_SR_RM(u8 X86EMU_UNUSED(op1)) | |
2104 | { | |
2105 | int mod, rl, rh; | |
2106 | u16 *destreg, *srcreg; | |
2107 | uint srcoffset; | |
2108 | u16 srcval; | |
2109 | ||
2110 | START_OF_INSTR(); | |
2111 | DECODE_PRINTF("MOV\t"); | |
2112 | FETCH_DECODE_MODRM(mod, rh, rl); | |
2113 | if (mod < 3) { | |
9c7e4b06 WD |
2114 | destreg = decode_rm_seg_register(rh); |
2115 | DECODE_PRINTF(","); | |
2116 | srcoffset = decode_rmXX_address(mod, rl); | |
2117 | srcval = fetch_data_word(srcoffset); | |
2118 | DECODE_PRINTF("\n"); | |
2119 | TRACE_AND_STEP(); | |
2120 | *destreg = srcval; | |
2121 | } else { /* register to register */ | |
2122 | destreg = decode_rm_seg_register(rh); | |
2123 | DECODE_PRINTF(","); | |
2124 | srcreg = DECODE_RM_WORD_REGISTER(rl); | |
2125 | DECODE_PRINTF("\n"); | |
2126 | TRACE_AND_STEP(); | |
2127 | *destreg = *srcreg; | |
ece92f85 JJ |
2128 | } |
2129 | /* | |
2130 | * Clean up, and reset all the R_xSP pointers to the correct | |
2131 | * locations. This is about 3x too much overhead (doing all the | |
2132 | * segreg ptrs when only one is needed, but this instruction | |
2133 | * *cannot* be that common, and this isn't too much work anyway. | |
2134 | */ | |
2135 | DECODE_CLEAR_SEGOVR(); | |
2136 | END_OF_INSTR(); | |
2137 | } | |
2138 | ||
2139 | /**************************************************************************** | |
2140 | REMARKS: | |
2141 | Handles opcode 0x8f | |
2142 | ****************************************************************************/ | |
2143 | void x86emuOp_pop_RM(u8 X86EMU_UNUSED(op1)) | |
2144 | { | |
2145 | int mod, rl, rh; | |
2146 | uint destoffset; | |
2147 | ||
2148 | START_OF_INSTR(); | |
2149 | DECODE_PRINTF("POP\t"); | |
2150 | FETCH_DECODE_MODRM(mod, rh, rl); | |
2151 | if (rh != 0) { | |
8c6ec412 | 2152 | ERR_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n"); |
9c7e4b06 | 2153 | HALT_SYS(); |
ece92f85 JJ |
2154 | } |
2155 | if (mod < 3) { | |
9c7e4b06 WD |
2156 | destoffset = decode_rmXX_address(mod, rl); |
2157 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
2158 | u32 destval; | |
2159 | ||
2160 | DECODE_PRINTF("\n"); | |
2161 | TRACE_AND_STEP(); | |
2162 | destval = pop_long(); | |
2163 | store_data_long(destoffset, destval); | |
2164 | } else { | |
2165 | u16 destval; | |
2166 | ||
2167 | DECODE_PRINTF("\n"); | |
2168 | TRACE_AND_STEP(); | |
2169 | destval = pop_word(); | |
2170 | store_data_word(destoffset, destval); | |
2171 | } | |
2172 | } else { /* register to register */ | |
2173 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
2174 | u32 *destreg; | |
2175 | ||
2176 | destreg = DECODE_RM_LONG_REGISTER(rl); | |
2177 | DECODE_PRINTF("\n"); | |
2178 | TRACE_AND_STEP(); | |
2179 | *destreg = pop_long(); | |
2180 | } else { | |
2181 | u16 *destreg; | |
2182 | ||
2183 | destreg = DECODE_RM_WORD_REGISTER(rl); | |
2184 | DECODE_PRINTF("\n"); | |
2185 | TRACE_AND_STEP(); | |
2186 | *destreg = pop_word(); | |
2187 | } | |
ece92f85 JJ |
2188 | } |
2189 | DECODE_CLEAR_SEGOVR(); | |
2190 | END_OF_INSTR(); | |
2191 | } | |
2192 | ||
2193 | /**************************************************************************** | |
2194 | REMARKS: | |
2195 | Handles opcode 0x90 | |
2196 | ****************************************************************************/ | |
2197 | void x86emuOp_nop(u8 X86EMU_UNUSED(op1)) | |
2198 | { | |
2199 | START_OF_INSTR(); | |
2200 | DECODE_PRINTF("NOP\n"); | |
2201 | TRACE_AND_STEP(); | |
2202 | DECODE_CLEAR_SEGOVR(); | |
2203 | END_OF_INSTR(); | |
2204 | } | |
2205 | ||
2206 | /**************************************************************************** | |
2207 | REMARKS: | |
2208 | Handles opcode 0x91-0x97 | |
2209 | ****************************************************************************/ | |
2210 | void x86emuOp_xchg_word_AX_register(u8 X86EMU_UNUSED(op1)) | |
2211 | { | |
2212 | u32 tmp; | |
2213 | ||
2214 | op1 &= 0x7; | |
2215 | ||
2216 | START_OF_INSTR(); | |
2217 | ||
2218 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 WD |
2219 | u32 *reg32; |
2220 | DECODE_PRINTF("XCHG\tEAX,"); | |
2221 | reg32 = DECODE_RM_LONG_REGISTER(op1); | |
2222 | DECODE_PRINTF("\n"); | |
2223 | TRACE_AND_STEP(); | |
2224 | tmp = M.x86.R_EAX; | |
2225 | M.x86.R_EAX = *reg32; | |
2226 | *reg32 = tmp; | |
ece92f85 | 2227 | } else { |
9c7e4b06 WD |
2228 | u16 *reg16; |
2229 | DECODE_PRINTF("XCHG\tAX,"); | |
2230 | reg16 = DECODE_RM_WORD_REGISTER(op1); | |
2231 | DECODE_PRINTF("\n"); | |
2232 | TRACE_AND_STEP(); | |
2233 | tmp = M.x86.R_AX; | |
2234 | M.x86.R_EAX = *reg16; | |
2235 | *reg16 = (u16)tmp; | |
ece92f85 JJ |
2236 | } |
2237 | DECODE_CLEAR_SEGOVR(); | |
2238 | END_OF_INSTR(); | |
2239 | } | |
2240 | ||
2241 | /**************************************************************************** | |
2242 | REMARKS: | |
2243 | Handles opcode 0x98 | |
2244 | ****************************************************************************/ | |
2245 | void x86emuOp_cbw(u8 X86EMU_UNUSED(op1)) | |
2246 | { | |
2247 | START_OF_INSTR(); | |
2248 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 | 2249 | DECODE_PRINTF("CWDE\n"); |
ece92f85 | 2250 | } else { |
9c7e4b06 | 2251 | DECODE_PRINTF("CBW\n"); |
ece92f85 JJ |
2252 | } |
2253 | TRACE_AND_STEP(); | |
2254 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 WD |
2255 | if (M.x86.R_AX & 0x8000) { |
2256 | M.x86.R_EAX |= 0xffff0000; | |
2257 | } else { | |
2258 | M.x86.R_EAX &= 0x0000ffff; | |
2259 | } | |
ece92f85 | 2260 | } else { |
9c7e4b06 WD |
2261 | if (M.x86.R_AL & 0x80) { |
2262 | M.x86.R_AH = 0xff; | |
2263 | } else { | |
2264 | M.x86.R_AH = 0x0; | |
2265 | } | |
ece92f85 JJ |
2266 | } |
2267 | DECODE_CLEAR_SEGOVR(); | |
2268 | END_OF_INSTR(); | |
2269 | } | |
2270 | ||
2271 | /**************************************************************************** | |
2272 | REMARKS: | |
2273 | Handles opcode 0x99 | |
2274 | ****************************************************************************/ | |
2275 | void x86emuOp_cwd(u8 X86EMU_UNUSED(op1)) | |
2276 | { | |
2277 | START_OF_INSTR(); | |
2278 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 | 2279 | DECODE_PRINTF("CDQ\n"); |
ece92f85 | 2280 | } else { |
9c7e4b06 | 2281 | DECODE_PRINTF("CWD\n"); |
ece92f85 JJ |
2282 | } |
2283 | DECODE_PRINTF("CWD\n"); | |
2284 | TRACE_AND_STEP(); | |
2285 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 WD |
2286 | if (M.x86.R_EAX & 0x80000000) { |
2287 | M.x86.R_EDX = 0xffffffff; | |
2288 | } else { | |
2289 | M.x86.R_EDX = 0x0; | |
2290 | } | |
ece92f85 | 2291 | } else { |
9c7e4b06 WD |
2292 | if (M.x86.R_AX & 0x8000) { |
2293 | M.x86.R_DX = 0xffff; | |
2294 | } else { | |
2295 | M.x86.R_DX = 0x0; | |
2296 | } | |
ece92f85 JJ |
2297 | } |
2298 | DECODE_CLEAR_SEGOVR(); | |
2299 | END_OF_INSTR(); | |
2300 | } | |
2301 | ||
2302 | /**************************************************************************** | |
2303 | REMARKS: | |
2304 | Handles opcode 0x9a | |
2305 | ****************************************************************************/ | |
2306 | void x86emuOp_call_far_IMM(u8 X86EMU_UNUSED(op1)) | |
2307 | { | |
2308 | u16 farseg, faroff; | |
2309 | ||
2310 | START_OF_INSTR(); | |
2311 | DECODE_PRINTF("CALL\t"); | |
2312 | faroff = fetch_word_imm(); | |
2313 | farseg = fetch_word_imm(); | |
2314 | DECODE_PRINTF2("%04x:", farseg); | |
2315 | DECODE_PRINTF2("%04x\n", faroff); | |
2316 | CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, farseg, faroff, "FAR "); | |
2317 | ||
2318 | /* XXX | |
2319 | * | |
2320 | * Hooked interrupt vectors calling into our "BIOS" will cause | |
2321 | * problems unless all intersegment stuff is checked for BIOS | |
9c7e4b06 | 2322 | * access. Check needed here. For moment, let it alone. |
ece92f85 JJ |
2323 | */ |
2324 | TRACE_AND_STEP(); | |
2325 | push_word(M.x86.R_CS); | |
2326 | M.x86.R_CS = farseg; | |
2327 | push_word(M.x86.R_IP); | |
2328 | M.x86.R_IP = faroff; | |
2329 | DECODE_CLEAR_SEGOVR(); | |
2330 | END_OF_INSTR(); | |
2331 | } | |
2332 | ||
2333 | /**************************************************************************** | |
2334 | REMARKS: | |
2335 | Handles opcode 0x9b | |
2336 | ****************************************************************************/ | |
2337 | void x86emuOp_wait(u8 X86EMU_UNUSED(op1)) | |
2338 | { | |
2339 | START_OF_INSTR(); | |
2340 | DECODE_PRINTF("WAIT"); | |
2341 | TRACE_AND_STEP(); | |
2342 | /* NADA. */ | |
2343 | DECODE_CLEAR_SEGOVR(); | |
2344 | END_OF_INSTR(); | |
2345 | } | |
2346 | ||
2347 | /**************************************************************************** | |
2348 | REMARKS: | |
2349 | Handles opcode 0x9c | |
2350 | ****************************************************************************/ | |
2351 | void x86emuOp_pushf_word(u8 X86EMU_UNUSED(op1)) | |
2352 | { | |
2353 | u32 flags; | |
2354 | ||
2355 | START_OF_INSTR(); | |
2356 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 | 2357 | DECODE_PRINTF("PUSHFD\n"); |
ece92f85 | 2358 | } else { |
9c7e4b06 | 2359 | DECODE_PRINTF("PUSHF\n"); |
ece92f85 JJ |
2360 | } |
2361 | TRACE_AND_STEP(); | |
2362 | ||
2363 | /* clear out *all* bits not representing flags, and turn on real bits */ | |
2364 | flags = (M.x86.R_EFLG & F_MSK) | F_ALWAYS_ON; | |
2365 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 | 2366 | push_long(flags); |
ece92f85 | 2367 | } else { |
9c7e4b06 | 2368 | push_word((u16)flags); |
ece92f85 JJ |
2369 | } |
2370 | DECODE_CLEAR_SEGOVR(); | |
2371 | END_OF_INSTR(); | |
2372 | } | |
2373 | ||
2374 | /**************************************************************************** | |
2375 | REMARKS: | |
2376 | Handles opcode 0x9d | |
2377 | ****************************************************************************/ | |
2378 | void x86emuOp_popf_word(u8 X86EMU_UNUSED(op1)) | |
2379 | { | |
2380 | START_OF_INSTR(); | |
2381 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 | 2382 | DECODE_PRINTF("POPFD\n"); |
ece92f85 | 2383 | } else { |
9c7e4b06 | 2384 | DECODE_PRINTF("POPF\n"); |
ece92f85 JJ |
2385 | } |
2386 | TRACE_AND_STEP(); | |
2387 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 | 2388 | M.x86.R_EFLG = pop_long(); |
ece92f85 | 2389 | } else { |
9c7e4b06 | 2390 | M.x86.R_FLG = pop_word(); |
ece92f85 JJ |
2391 | } |
2392 | DECODE_CLEAR_SEGOVR(); | |
2393 | END_OF_INSTR(); | |
2394 | } | |
2395 | ||
2396 | /**************************************************************************** | |
2397 | REMARKS: | |
2398 | Handles opcode 0x9e | |
2399 | ****************************************************************************/ | |
2400 | void x86emuOp_sahf(u8 X86EMU_UNUSED(op1)) | |
2401 | { | |
2402 | START_OF_INSTR(); | |
2403 | DECODE_PRINTF("SAHF\n"); | |
2404 | TRACE_AND_STEP(); | |
2405 | /* clear the lower bits of the flag register */ | |
2406 | M.x86.R_FLG &= 0xffffff00; | |
2407 | /* or in the AH register into the flags register */ | |
2408 | M.x86.R_FLG |= M.x86.R_AH; | |
2409 | DECODE_CLEAR_SEGOVR(); | |
2410 | END_OF_INSTR(); | |
2411 | } | |
2412 | ||
2413 | /**************************************************************************** | |
2414 | REMARKS: | |
2415 | Handles opcode 0x9f | |
2416 | ****************************************************************************/ | |
2417 | void x86emuOp_lahf(u8 X86EMU_UNUSED(op1)) | |
2418 | { | |
2419 | START_OF_INSTR(); | |
2420 | DECODE_PRINTF("LAHF\n"); | |
2421 | TRACE_AND_STEP(); | |
2422 | M.x86.R_AH = (u8)(M.x86.R_FLG & 0xff); | |
2423 | /*undocumented TC++ behavior??? Nope. It's documented, but | |
2424 | you have too look real hard to notice it. */ | |
2425 | M.x86.R_AH |= 0x2; | |
2426 | DECODE_CLEAR_SEGOVR(); | |
2427 | END_OF_INSTR(); | |
2428 | } | |
2429 | ||
2430 | /**************************************************************************** | |
2431 | REMARKS: | |
2432 | Handles opcode 0xa0 | |
2433 | ****************************************************************************/ | |
2434 | void x86emuOp_mov_AL_M_IMM(u8 X86EMU_UNUSED(op1)) | |
2435 | { | |
2436 | u16 offset; | |
2437 | ||
2438 | START_OF_INSTR(); | |
2439 | DECODE_PRINTF("MOV\tAL,"); | |
2440 | offset = fetch_word_imm(); | |
2441 | DECODE_PRINTF2("[%04x]\n", offset); | |
2442 | TRACE_AND_STEP(); | |
2443 | M.x86.R_AL = fetch_data_byte(offset); | |
2444 | DECODE_CLEAR_SEGOVR(); | |
2445 | END_OF_INSTR(); | |
2446 | } | |
2447 | ||
2448 | /**************************************************************************** | |
2449 | REMARKS: | |
2450 | Handles opcode 0xa1 | |
2451 | ****************************************************************************/ | |
2452 | void x86emuOp_mov_AX_M_IMM(u8 X86EMU_UNUSED(op1)) | |
2453 | { | |
2454 | u16 offset; | |
2455 | ||
2456 | START_OF_INSTR(); | |
2457 | offset = fetch_word_imm(); | |
2458 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 | 2459 | DECODE_PRINTF2("MOV\tEAX,[%04x]\n", offset); |
ece92f85 | 2460 | } else { |
9c7e4b06 | 2461 | DECODE_PRINTF2("MOV\tAX,[%04x]\n", offset); |
ece92f85 JJ |
2462 | } |
2463 | TRACE_AND_STEP(); | |
2464 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 | 2465 | M.x86.R_EAX = fetch_data_long(offset); |
ece92f85 | 2466 | } else { |
9c7e4b06 | 2467 | M.x86.R_AX = fetch_data_word(offset); |
ece92f85 JJ |
2468 | } |
2469 | DECODE_CLEAR_SEGOVR(); | |
2470 | END_OF_INSTR(); | |
2471 | } | |
2472 | ||
2473 | /**************************************************************************** | |
2474 | REMARKS: | |
2475 | Handles opcode 0xa2 | |
2476 | ****************************************************************************/ | |
2477 | void x86emuOp_mov_M_AL_IMM(u8 X86EMU_UNUSED(op1)) | |
2478 | { | |
2479 | u16 offset; | |
2480 | ||
2481 | START_OF_INSTR(); | |
2482 | DECODE_PRINTF("MOV\t"); | |
2483 | offset = fetch_word_imm(); | |
2484 | DECODE_PRINTF2("[%04x],AL\n", offset); | |
2485 | TRACE_AND_STEP(); | |
2486 | store_data_byte(offset, M.x86.R_AL); | |
2487 | DECODE_CLEAR_SEGOVR(); | |
2488 | END_OF_INSTR(); | |
2489 | } | |
2490 | ||
2491 | /**************************************************************************** | |
2492 | REMARKS: | |
2493 | Handles opcode 0xa3 | |
2494 | ****************************************************************************/ | |
2495 | void x86emuOp_mov_M_AX_IMM(u8 X86EMU_UNUSED(op1)) | |
2496 | { | |
2497 | u16 offset; | |
2498 | ||
2499 | START_OF_INSTR(); | |
2500 | offset = fetch_word_imm(); | |
2501 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 | 2502 | DECODE_PRINTF2("MOV\t[%04x],EAX\n", offset); |
ece92f85 | 2503 | } else { |
9c7e4b06 | 2504 | DECODE_PRINTF2("MOV\t[%04x],AX\n", offset); |
ece92f85 JJ |
2505 | } |
2506 | TRACE_AND_STEP(); | |
2507 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 | 2508 | store_data_long(offset, M.x86.R_EAX); |
ece92f85 | 2509 | } else { |
9c7e4b06 | 2510 | store_data_word(offset, M.x86.R_AX); |
ece92f85 JJ |
2511 | } |
2512 | DECODE_CLEAR_SEGOVR(); | |
2513 | END_OF_INSTR(); | |
2514 | } | |
2515 | ||
2516 | /**************************************************************************** | |
2517 | REMARKS: | |
2518 | Handles opcode 0xa4 | |
2519 | ****************************************************************************/ | |
2520 | void x86emuOp_movs_byte(u8 X86EMU_UNUSED(op1)) | |
2521 | { | |
9c7e4b06 | 2522 | u8 val; |
ece92f85 JJ |
2523 | u32 count; |
2524 | int inc; | |
2525 | ||
2526 | START_OF_INSTR(); | |
2527 | DECODE_PRINTF("MOVS\tBYTE\n"); | |
2528 | if (ACCESS_FLAG(F_DF)) /* down */ | |
9c7e4b06 | 2529 | inc = -1; |
ece92f85 | 2530 | else |
9c7e4b06 | 2531 | inc = 1; |
ece92f85 JJ |
2532 | TRACE_AND_STEP(); |
2533 | count = 1; | |
2534 | if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { | |
9c7e4b06 WD |
2535 | /* dont care whether REPE or REPNE */ |
2536 | /* move them until CX is ZERO. */ | |
2537 | count = M.x86.R_CX; | |
2538 | M.x86.R_CX = 0; | |
2539 | M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); | |
ece92f85 JJ |
2540 | } |
2541 | while (count--) { | |
9c7e4b06 WD |
2542 | val = fetch_data_byte(M.x86.R_SI); |
2543 | store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, val); | |
2544 | M.x86.R_SI += inc; | |
2545 | M.x86.R_DI += inc; | |
ece92f85 JJ |
2546 | } |
2547 | DECODE_CLEAR_SEGOVR(); | |
2548 | END_OF_INSTR(); | |
2549 | } | |
2550 | ||
2551 | /**************************************************************************** | |
2552 | REMARKS: | |
2553 | Handles opcode 0xa5 | |
2554 | ****************************************************************************/ | |
2555 | void x86emuOp_movs_word(u8 X86EMU_UNUSED(op1)) | |
2556 | { | |
2557 | u32 val; | |
2558 | int inc; | |
2559 | u32 count; | |
2560 | ||
2561 | START_OF_INSTR(); | |
2562 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 WD |
2563 | DECODE_PRINTF("MOVS\tDWORD\n"); |
2564 | if (ACCESS_FLAG(F_DF)) /* down */ | |
2565 | inc = -4; | |
2566 | else | |
2567 | inc = 4; | |
ece92f85 | 2568 | } else { |
9c7e4b06 WD |
2569 | DECODE_PRINTF("MOVS\tWORD\n"); |
2570 | if (ACCESS_FLAG(F_DF)) /* down */ | |
2571 | inc = -2; | |
2572 | else | |
2573 | inc = 2; | |
ece92f85 JJ |
2574 | } |
2575 | TRACE_AND_STEP(); | |
2576 | count = 1; | |
2577 | if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { | |
9c7e4b06 WD |
2578 | /* dont care whether REPE or REPNE */ |
2579 | /* move them until CX is ZERO. */ | |
2580 | count = M.x86.R_CX; | |
2581 | M.x86.R_CX = 0; | |
2582 | M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); | |
ece92f85 JJ |
2583 | } |
2584 | while (count--) { | |
9c7e4b06 WD |
2585 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { |
2586 | val = fetch_data_long(M.x86.R_SI); | |
2587 | store_data_long_abs(M.x86.R_ES, M.x86.R_DI, val); | |
2588 | } else { | |
2589 | val = fetch_data_word(M.x86.R_SI); | |
2590 | store_data_word_abs(M.x86.R_ES, M.x86.R_DI, (u16)val); | |
2591 | } | |
2592 | M.x86.R_SI += inc; | |
2593 | M.x86.R_DI += inc; | |
ece92f85 JJ |
2594 | } |
2595 | DECODE_CLEAR_SEGOVR(); | |
2596 | END_OF_INSTR(); | |
2597 | } | |
2598 | ||
2599 | /**************************************************************************** | |
2600 | REMARKS: | |
2601 | Handles opcode 0xa6 | |
2602 | ****************************************************************************/ | |
2603 | void x86emuOp_cmps_byte(u8 X86EMU_UNUSED(op1)) | |
2604 | { | |
2605 | s8 val1, val2; | |
2606 | int inc; | |
2607 | ||
2608 | START_OF_INSTR(); | |
2609 | DECODE_PRINTF("CMPS\tBYTE\n"); | |
2610 | TRACE_AND_STEP(); | |
2611 | if (ACCESS_FLAG(F_DF)) /* down */ | |
9c7e4b06 | 2612 | inc = -1; |
ece92f85 | 2613 | else |
9c7e4b06 | 2614 | inc = 1; |
ece92f85 JJ |
2615 | |
2616 | if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { | |
9c7e4b06 WD |
2617 | /* REPE */ |
2618 | /* move them until CX is ZERO. */ | |
2619 | while (M.x86.R_CX != 0) { | |
2620 | val1 = fetch_data_byte(M.x86.R_SI); | |
2621 | val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI); | |
2622 | cmp_byte(val1, val2); | |
2623 | M.x86.R_CX -= 1; | |
2624 | M.x86.R_SI += inc; | |
2625 | M.x86.R_DI += inc; | |
2626 | if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && (ACCESS_FLAG(F_ZF) == 0) ) break; | |
2627 | if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break; | |
2628 | } | |
2629 | M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); | |
ece92f85 | 2630 | } else { |
9c7e4b06 WD |
2631 | val1 = fetch_data_byte(M.x86.R_SI); |
2632 | val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI); | |
2633 | cmp_byte(val1, val2); | |
2634 | M.x86.R_SI += inc; | |
2635 | M.x86.R_DI += inc; | |
ece92f85 JJ |
2636 | } |
2637 | DECODE_CLEAR_SEGOVR(); | |
2638 | END_OF_INSTR(); | |
2639 | } | |
2640 | ||
2641 | /**************************************************************************** | |
2642 | REMARKS: | |
2643 | Handles opcode 0xa7 | |
2644 | ****************************************************************************/ | |
2645 | void x86emuOp_cmps_word(u8 X86EMU_UNUSED(op1)) | |
2646 | { | |
2647 | u32 val1,val2; | |
2648 | int inc; | |
2649 | ||
2650 | START_OF_INSTR(); | |
2651 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 WD |
2652 | DECODE_PRINTF("CMPS\tDWORD\n"); |
2653 | inc = 4; | |
ece92f85 | 2654 | } else { |
9c7e4b06 WD |
2655 | DECODE_PRINTF("CMPS\tWORD\n"); |
2656 | inc = 2; | |
ece92f85 JJ |
2657 | } |
2658 | if (ACCESS_FLAG(F_DF)) /* down */ | |
9c7e4b06 | 2659 | inc = -inc; |
ece92f85 JJ |
2660 | |
2661 | TRACE_AND_STEP(); | |
2662 | if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { | |
9c7e4b06 WD |
2663 | /* REPE */ |
2664 | /* move them until CX is ZERO. */ | |
2665 | while (M.x86.R_CX != 0) { | |
2666 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
2667 | val1 = fetch_data_long(M.x86.R_SI); | |
2668 | val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI); | |
2669 | cmp_long(val1, val2); | |
2670 | } else { | |
2671 | val1 = fetch_data_word(M.x86.R_SI); | |
2672 | val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI); | |
2673 | cmp_word((u16)val1, (u16)val2); | |
2674 | } | |
2675 | M.x86.R_CX -= 1; | |
2676 | M.x86.R_SI += inc; | |
2677 | M.x86.R_DI += inc; | |
2678 | if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && ACCESS_FLAG(F_ZF) == 0 ) break; | |
2679 | if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break; | |
2680 | } | |
2681 | M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); | |
ece92f85 | 2682 | } else { |
9c7e4b06 WD |
2683 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { |
2684 | val1 = fetch_data_long(M.x86.R_SI); | |
2685 | val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI); | |
2686 | cmp_long(val1, val2); | |
2687 | } else { | |
2688 | val1 = fetch_data_word(M.x86.R_SI); | |
2689 | val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI); | |
2690 | cmp_word((u16)val1, (u16)val2); | |
2691 | } | |
2692 | M.x86.R_SI += inc; | |
2693 | M.x86.R_DI += inc; | |
ece92f85 JJ |
2694 | } |
2695 | DECODE_CLEAR_SEGOVR(); | |
2696 | END_OF_INSTR(); | |
2697 | } | |
2698 | ||
2699 | /**************************************************************************** | |
2700 | REMARKS: | |
2701 | Handles opcode 0xa8 | |
2702 | ****************************************************************************/ | |
2703 | void x86emuOp_test_AL_IMM(u8 X86EMU_UNUSED(op1)) | |
2704 | { | |
2705 | int imm; | |
2706 | ||
2707 | START_OF_INSTR(); | |
2708 | DECODE_PRINTF("TEST\tAL,"); | |
2709 | imm = fetch_byte_imm(); | |
2710 | DECODE_PRINTF2("%04x\n", imm); | |
2711 | TRACE_AND_STEP(); | |
2712 | test_byte(M.x86.R_AL, (u8)imm); | |
2713 | DECODE_CLEAR_SEGOVR(); | |
2714 | END_OF_INSTR(); | |
2715 | } | |
2716 | ||
2717 | /**************************************************************************** | |
2718 | REMARKS: | |
2719 | Handles opcode 0xa9 | |
2720 | ****************************************************************************/ | |
2721 | void x86emuOp_test_AX_IMM(u8 X86EMU_UNUSED(op1)) | |
2722 | { | |
2723 | u32 srcval; | |
2724 | ||
2725 | START_OF_INSTR(); | |
2726 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 WD |
2727 | DECODE_PRINTF("TEST\tEAX,"); |
2728 | srcval = fetch_long_imm(); | |
ece92f85 | 2729 | } else { |
9c7e4b06 WD |
2730 | DECODE_PRINTF("TEST\tAX,"); |
2731 | srcval = fetch_word_imm(); | |
ece92f85 JJ |
2732 | } |
2733 | DECODE_PRINTF2("%x\n", srcval); | |
2734 | TRACE_AND_STEP(); | |
2735 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 | 2736 | test_long(M.x86.R_EAX, srcval); |
ece92f85 | 2737 | } else { |
9c7e4b06 | 2738 | test_word(M.x86.R_AX, (u16)srcval); |
ece92f85 JJ |
2739 | } |
2740 | DECODE_CLEAR_SEGOVR(); | |
2741 | END_OF_INSTR(); | |
2742 | } | |
2743 | ||
2744 | /**************************************************************************** | |
2745 | REMARKS: | |
2746 | Handles opcode 0xaa | |
2747 | ****************************************************************************/ | |
2748 | void x86emuOp_stos_byte(u8 X86EMU_UNUSED(op1)) | |
2749 | { | |
2750 | int inc; | |
2751 | ||
2752 | START_OF_INSTR(); | |
2753 | DECODE_PRINTF("STOS\tBYTE\n"); | |
2754 | if (ACCESS_FLAG(F_DF)) /* down */ | |
9c7e4b06 | 2755 | inc = -1; |
ece92f85 | 2756 | else |
9c7e4b06 | 2757 | inc = 1; |
ece92f85 JJ |
2758 | TRACE_AND_STEP(); |
2759 | if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { | |
9c7e4b06 WD |
2760 | /* dont care whether REPE or REPNE */ |
2761 | /* move them until CX is ZERO. */ | |
2762 | while (M.x86.R_CX != 0) { | |
2763 | store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL); | |
2764 | M.x86.R_CX -= 1; | |
2765 | M.x86.R_DI += inc; | |
2766 | } | |
2767 | M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); | |
ece92f85 | 2768 | } else { |
9c7e4b06 WD |
2769 | store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL); |
2770 | M.x86.R_DI += inc; | |
ece92f85 JJ |
2771 | } |
2772 | DECODE_CLEAR_SEGOVR(); | |
2773 | END_OF_INSTR(); | |
2774 | } | |
2775 | ||
2776 | /**************************************************************************** | |
2777 | REMARKS: | |
2778 | Handles opcode 0xab | |
2779 | ****************************************************************************/ | |
2780 | void x86emuOp_stos_word(u8 X86EMU_UNUSED(op1)) | |
2781 | { | |
2782 | int inc; | |
2783 | u32 count; | |
2784 | ||
2785 | START_OF_INSTR(); | |
2786 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 WD |
2787 | DECODE_PRINTF("STOS\tDWORD\n"); |
2788 | if (ACCESS_FLAG(F_DF)) /* down */ | |
2789 | inc = -4; | |
2790 | else | |
2791 | inc = 4; | |
ece92f85 | 2792 | } else { |
9c7e4b06 WD |
2793 | DECODE_PRINTF("STOS\tWORD\n"); |
2794 | if (ACCESS_FLAG(F_DF)) /* down */ | |
2795 | inc = -2; | |
2796 | else | |
2797 | inc = 2; | |
ece92f85 JJ |
2798 | } |
2799 | TRACE_AND_STEP(); | |
2800 | count = 1; | |
2801 | if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { | |
9c7e4b06 WD |
2802 | /* dont care whether REPE or REPNE */ |
2803 | /* move them until CX is ZERO. */ | |
2804 | count = M.x86.R_CX; | |
2805 | M.x86.R_CX = 0; | |
2806 | M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); | |
ece92f85 JJ |
2807 | } |
2808 | while (count--) { | |
9c7e4b06 WD |
2809 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { |
2810 | store_data_long_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_EAX); | |
2811 | } else { | |
2812 | store_data_word_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AX); | |
2813 | } | |
2814 | M.x86.R_DI += inc; | |
ece92f85 JJ |
2815 | } |
2816 | DECODE_CLEAR_SEGOVR(); | |
2817 | END_OF_INSTR(); | |
2818 | } | |
2819 | ||
2820 | /**************************************************************************** | |
2821 | REMARKS: | |
2822 | Handles opcode 0xac | |
2823 | ****************************************************************************/ | |
2824 | void x86emuOp_lods_byte(u8 X86EMU_UNUSED(op1)) | |
2825 | { | |
2826 | int inc; | |
2827 | ||
2828 | START_OF_INSTR(); | |
2829 | DECODE_PRINTF("LODS\tBYTE\n"); | |
2830 | TRACE_AND_STEP(); | |
2831 | if (ACCESS_FLAG(F_DF)) /* down */ | |
9c7e4b06 | 2832 | inc = -1; |
ece92f85 | 2833 | else |
9c7e4b06 | 2834 | inc = 1; |
ece92f85 | 2835 | if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { |
9c7e4b06 WD |
2836 | /* dont care whether REPE or REPNE */ |
2837 | /* move them until CX is ZERO. */ | |
2838 | while (M.x86.R_CX != 0) { | |
2839 | M.x86.R_AL = fetch_data_byte(M.x86.R_SI); | |
2840 | M.x86.R_CX -= 1; | |
2841 | M.x86.R_SI += inc; | |
2842 | } | |
2843 | M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); | |
ece92f85 | 2844 | } else { |
9c7e4b06 WD |
2845 | M.x86.R_AL = fetch_data_byte(M.x86.R_SI); |
2846 | M.x86.R_SI += inc; | |
ece92f85 JJ |
2847 | } |
2848 | DECODE_CLEAR_SEGOVR(); | |
2849 | END_OF_INSTR(); | |
2850 | } | |
2851 | ||
2852 | /**************************************************************************** | |
2853 | REMARKS: | |
2854 | Handles opcode 0xad | |
2855 | ****************************************************************************/ | |
2856 | void x86emuOp_lods_word(u8 X86EMU_UNUSED(op1)) | |
2857 | { | |
2858 | int inc; | |
2859 | u32 count; | |
2860 | ||
2861 | START_OF_INSTR(); | |
2862 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 WD |
2863 | DECODE_PRINTF("LODS\tDWORD\n"); |
2864 | if (ACCESS_FLAG(F_DF)) /* down */ | |
2865 | inc = -4; | |
2866 | else | |
2867 | inc = 4; | |
ece92f85 | 2868 | } else { |
9c7e4b06 WD |
2869 | DECODE_PRINTF("LODS\tWORD\n"); |
2870 | if (ACCESS_FLAG(F_DF)) /* down */ | |
2871 | inc = -2; | |
2872 | else | |
2873 | inc = 2; | |
ece92f85 JJ |
2874 | } |
2875 | TRACE_AND_STEP(); | |
2876 | count = 1; | |
2877 | if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { | |
9c7e4b06 WD |
2878 | /* dont care whether REPE or REPNE */ |
2879 | /* move them until CX is ZERO. */ | |
2880 | count = M.x86.R_CX; | |
2881 | M.x86.R_CX = 0; | |
2882 | M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); | |
ece92f85 JJ |
2883 | } |
2884 | while (count--) { | |
9c7e4b06 WD |
2885 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { |
2886 | M.x86.R_EAX = fetch_data_long(M.x86.R_SI); | |
2887 | } else { | |
2888 | M.x86.R_AX = fetch_data_word(M.x86.R_SI); | |
2889 | } | |
2890 | M.x86.R_SI += inc; | |
ece92f85 JJ |
2891 | } |
2892 | DECODE_CLEAR_SEGOVR(); | |
2893 | END_OF_INSTR(); | |
2894 | } | |
2895 | ||
2896 | /**************************************************************************** | |
2897 | REMARKS: | |
2898 | Handles opcode 0xae | |
2899 | ****************************************************************************/ | |
2900 | void x86emuOp_scas_byte(u8 X86EMU_UNUSED(op1)) | |
2901 | { | |
2902 | s8 val2; | |
2903 | int inc; | |
2904 | ||
2905 | START_OF_INSTR(); | |
2906 | DECODE_PRINTF("SCAS\tBYTE\n"); | |
2907 | TRACE_AND_STEP(); | |
2908 | if (ACCESS_FLAG(F_DF)) /* down */ | |
9c7e4b06 | 2909 | inc = -1; |
ece92f85 | 2910 | else |
9c7e4b06 | 2911 | inc = 1; |
ece92f85 | 2912 | if (M.x86.mode & SYSMODE_PREFIX_REPE) { |
9c7e4b06 WD |
2913 | /* REPE */ |
2914 | /* move them until CX is ZERO. */ | |
2915 | while (M.x86.R_CX != 0) { | |
2916 | val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI); | |
2917 | cmp_byte(M.x86.R_AL, val2); | |
2918 | M.x86.R_CX -= 1; | |
2919 | M.x86.R_DI += inc; | |
2920 | if (ACCESS_FLAG(F_ZF) == 0) | |
2921 | break; | |
2922 | } | |
2923 | M.x86.mode &= ~SYSMODE_PREFIX_REPE; | |
ece92f85 | 2924 | } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) { |
9c7e4b06 WD |
2925 | /* REPNE */ |
2926 | /* move them until CX is ZERO. */ | |
2927 | while (M.x86.R_CX != 0) { | |
2928 | val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI); | |
2929 | cmp_byte(M.x86.R_AL, val2); | |
2930 | M.x86.R_CX -= 1; | |
2931 | M.x86.R_DI += inc; | |
2932 | if (ACCESS_FLAG(F_ZF)) | |
2933 | break; /* zero flag set means equal */ | |
2934 | } | |
2935 | M.x86.mode &= ~SYSMODE_PREFIX_REPNE; | |
ece92f85 | 2936 | } else { |
9c7e4b06 WD |
2937 | val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI); |
2938 | cmp_byte(M.x86.R_AL, val2); | |
2939 | M.x86.R_DI += inc; | |
ece92f85 JJ |
2940 | } |
2941 | DECODE_CLEAR_SEGOVR(); | |
2942 | END_OF_INSTR(); | |
2943 | } | |
2944 | ||
2945 | /**************************************************************************** | |
2946 | REMARKS: | |
2947 | Handles opcode 0xaf | |
2948 | ****************************************************************************/ | |
2949 | void x86emuOp_scas_word(u8 X86EMU_UNUSED(op1)) | |
2950 | { | |
2951 | int inc; | |
2952 | u32 val; | |
2953 | ||
2954 | START_OF_INSTR(); | |
2955 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 WD |
2956 | DECODE_PRINTF("SCAS\tDWORD\n"); |
2957 | if (ACCESS_FLAG(F_DF)) /* down */ | |
2958 | inc = -4; | |
2959 | else | |
2960 | inc = 4; | |
ece92f85 | 2961 | } else { |
9c7e4b06 WD |
2962 | DECODE_PRINTF("SCAS\tWORD\n"); |
2963 | if (ACCESS_FLAG(F_DF)) /* down */ | |
2964 | inc = -2; | |
2965 | else | |
2966 | inc = 2; | |
ece92f85 JJ |
2967 | } |
2968 | TRACE_AND_STEP(); | |
2969 | if (M.x86.mode & SYSMODE_PREFIX_REPE) { | |
9c7e4b06 WD |
2970 | /* REPE */ |
2971 | /* move them until CX is ZERO. */ | |
2972 | while (M.x86.R_CX != 0) { | |
2973 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
2974 | val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI); | |
2975 | cmp_long(M.x86.R_EAX, val); | |
2976 | } else { | |
2977 | val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI); | |
2978 | cmp_word(M.x86.R_AX, (u16)val); | |
2979 | } | |
2980 | M.x86.R_CX -= 1; | |
2981 | M.x86.R_DI += inc; | |
2982 | if (ACCESS_FLAG(F_ZF) == 0) | |
2983 | break; | |
2984 | } | |
2985 | M.x86.mode &= ~SYSMODE_PREFIX_REPE; | |
ece92f85 | 2986 | } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) { |
9c7e4b06 WD |
2987 | /* REPNE */ |
2988 | /* move them until CX is ZERO. */ | |
2989 | while (M.x86.R_CX != 0) { | |
2990 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
2991 | val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI); | |
2992 | cmp_long(M.x86.R_EAX, val); | |
2993 | } else { | |
2994 | val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI); | |
2995 | cmp_word(M.x86.R_AX, (u16)val); | |
2996 | } | |
2997 | M.x86.R_CX -= 1; | |
2998 | M.x86.R_DI += inc; | |
2999 | if (ACCESS_FLAG(F_ZF)) | |
3000 | break; /* zero flag set means equal */ | |
3001 | } | |
3002 | M.x86.mode &= ~SYSMODE_PREFIX_REPNE; | |
ece92f85 | 3003 | } else { |
9c7e4b06 WD |
3004 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { |
3005 | val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI); | |
3006 | cmp_long(M.x86.R_EAX, val); | |
3007 | } else { | |
3008 | val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI); | |
3009 | cmp_word(M.x86.R_AX, (u16)val); | |
3010 | } | |
3011 | M.x86.R_DI += inc; | |
ece92f85 JJ |
3012 | } |
3013 | DECODE_CLEAR_SEGOVR(); | |
3014 | END_OF_INSTR(); | |
3015 | } | |
3016 | ||
3017 | /**************************************************************************** | |
3018 | REMARKS: | |
3019 | Handles opcode 0xb0 - 0xb7 | |
3020 | ****************************************************************************/ | |
3021 | void x86emuOp_mov_byte_register_IMM(u8 op1) | |
3022 | { | |
3023 | u8 imm, *ptr; | |
3024 | ||
3025 | START_OF_INSTR(); | |
3026 | DECODE_PRINTF("MOV\t"); | |
3027 | ptr = DECODE_RM_BYTE_REGISTER(op1 & 0x7); | |
3028 | DECODE_PRINTF(","); | |
3029 | imm = fetch_byte_imm(); | |
3030 | DECODE_PRINTF2("%x\n", imm); | |
3031 | TRACE_AND_STEP(); | |
3032 | *ptr = imm; | |
3033 | DECODE_CLEAR_SEGOVR(); | |
3034 | END_OF_INSTR(); | |
3035 | } | |
3036 | ||
3037 | /**************************************************************************** | |
3038 | REMARKS: | |
3039 | Handles opcode 0xb8 - 0xbf | |
3040 | ****************************************************************************/ | |
3041 | void x86emuOp_mov_word_register_IMM(u8 X86EMU_UNUSED(op1)) | |
3042 | { | |
3043 | u32 srcval; | |
3044 | ||
3045 | op1 &= 0x7; | |
3046 | ||
3047 | START_OF_INSTR(); | |
3048 | DECODE_PRINTF("MOV\t"); | |
3049 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 WD |
3050 | u32 *reg32; |
3051 | reg32 = DECODE_RM_LONG_REGISTER(op1); | |
3052 | srcval = fetch_long_imm(); | |
3053 | DECODE_PRINTF2(",%x\n", srcval); | |
3054 | TRACE_AND_STEP(); | |
3055 | *reg32 = srcval; | |
ece92f85 | 3056 | } else { |
9c7e4b06 WD |
3057 | u16 *reg16; |
3058 | reg16 = DECODE_RM_WORD_REGISTER(op1); | |
3059 | srcval = fetch_word_imm(); | |
3060 | DECODE_PRINTF2(",%x\n", srcval); | |
3061 | TRACE_AND_STEP(); | |
3062 | *reg16 = (u16)srcval; | |
ece92f85 JJ |
3063 | } |
3064 | DECODE_CLEAR_SEGOVR(); | |
3065 | END_OF_INSTR(); | |
3066 | } | |
3067 | ||
3068 | /**************************************************************************** | |
3069 | REMARKS: | |
3070 | Handles opcode 0xc0 | |
3071 | ****************************************************************************/ | |
3072 | void x86emuOp_opcC0_byte_RM_MEM(u8 X86EMU_UNUSED(op1)) | |
3073 | { | |
3074 | int mod, rl, rh; | |
3075 | u8 *destreg; | |
3076 | uint destoffset; | |
3077 | u8 destval; | |
3078 | u8 amt; | |
3079 | ||
3080 | /* | |
3081 | * Yet another weirdo special case instruction format. Part of | |
3082 | * the opcode held below in "RH". Doubly nested case would | |
3083 | * result, except that the decoded instruction | |
3084 | */ | |
3085 | START_OF_INSTR(); | |
3086 | FETCH_DECODE_MODRM(mod, rh, rl); | |
b3521f2e | 3087 | #ifdef CONFIG_X86EMU_DEBUG |
ece92f85 | 3088 | if (DEBUG_DECODE()) { |
9c7e4b06 WD |
3089 | /* XXX DECODE_PRINTF may be changed to something more |
3090 | general, so that it is important to leave the strings | |
3091 | in the same format, even though the result is that the | |
3092 | above test is done twice. */ | |
3093 | ||
3094 | switch (rh) { | |
3095 | case 0: | |
3096 | DECODE_PRINTF("ROL\t"); | |
3097 | break; | |
3098 | case 1: | |
3099 | DECODE_PRINTF("ROR\t"); | |
3100 | break; | |
3101 | case 2: | |
3102 | DECODE_PRINTF("RCL\t"); | |
3103 | break; | |
3104 | case 3: | |
3105 | DECODE_PRINTF("RCR\t"); | |
3106 | break; | |
3107 | case 4: | |
3108 | DECODE_PRINTF("SHL\t"); | |
3109 | break; | |
3110 | case 5: | |
3111 | DECODE_PRINTF("SHR\t"); | |
3112 | break; | |
3113 | case 6: | |
3114 | DECODE_PRINTF("SAL\t"); | |
3115 | break; | |
3116 | case 7: | |
3117 | DECODE_PRINTF("SAR\t"); | |
3118 | break; | |
3119 | } | |
ece92f85 JJ |
3120 | } |
3121 | #endif | |
3122 | /* know operation, decode the mod byte to find the addressing | |
3123 | mode. */ | |
3124 | if (mod < 3) { | |
9c7e4b06 WD |
3125 | DECODE_PRINTF("BYTE PTR "); |
3126 | destoffset = decode_rmXX_address(mod, rl); | |
3127 | amt = fetch_byte_imm(); | |
3128 | DECODE_PRINTF2(",%x\n", amt); | |
3129 | destval = fetch_data_byte(destoffset); | |
3130 | TRACE_AND_STEP(); | |
3131 | destval = (*opcD0_byte_operation[rh]) (destval, amt); | |
3132 | store_data_byte(destoffset, destval); | |
3133 | } else { /* register to register */ | |
3134 | destreg = DECODE_RM_BYTE_REGISTER(rl); | |
3135 | amt = fetch_byte_imm(); | |
3136 | DECODE_PRINTF2(",%x\n", amt); | |
3137 | TRACE_AND_STEP(); | |
3138 | destval = (*opcD0_byte_operation[rh]) (*destreg, amt); | |
3139 | *destreg = destval; | |
ece92f85 JJ |
3140 | } |
3141 | DECODE_CLEAR_SEGOVR(); | |
3142 | END_OF_INSTR(); | |
3143 | } | |
3144 | ||
3145 | /**************************************************************************** | |
3146 | REMARKS: | |
3147 | Handles opcode 0xc1 | |
3148 | ****************************************************************************/ | |
3149 | void x86emuOp_opcC1_word_RM_MEM(u8 X86EMU_UNUSED(op1)) | |
3150 | { | |
3151 | int mod, rl, rh; | |
3152 | uint destoffset; | |
3153 | u8 amt; | |
3154 | ||
3155 | /* | |
3156 | * Yet another weirdo special case instruction format. Part of | |
3157 | * the opcode held below in "RH". Doubly nested case would | |
3158 | * result, except that the decoded instruction | |
3159 | */ | |
3160 | START_OF_INSTR(); | |
3161 | FETCH_DECODE_MODRM(mod, rh, rl); | |
b3521f2e | 3162 | #ifdef CONFIG_X86EMU_DEBUG |
ece92f85 | 3163 | if (DEBUG_DECODE()) { |
9c7e4b06 WD |
3164 | /* XXX DECODE_PRINTF may be changed to something more |
3165 | general, so that it is important to leave the strings | |
3166 | in the same format, even though the result is that the | |
3167 | above test is done twice. */ | |
3168 | ||
3169 | switch (rh) { | |
3170 | case 0: | |
3171 | DECODE_PRINTF("ROL\t"); | |
3172 | break; | |
3173 | case 1: | |
3174 | DECODE_PRINTF("ROR\t"); | |
3175 | break; | |
3176 | case 2: | |
3177 | DECODE_PRINTF("RCL\t"); | |
3178 | break; | |
3179 | case 3: | |
3180 | DECODE_PRINTF("RCR\t"); | |
3181 | break; | |
3182 | case 4: | |
3183 | DECODE_PRINTF("SHL\t"); | |
3184 | break; | |
3185 | case 5: | |
3186 | DECODE_PRINTF("SHR\t"); | |
3187 | break; | |
3188 | case 6: | |
3189 | DECODE_PRINTF("SAL\t"); | |
3190 | break; | |
3191 | case 7: | |
3192 | DECODE_PRINTF("SAR\t"); | |
3193 | break; | |
3194 | } | |
ece92f85 JJ |
3195 | } |
3196 | #endif | |
3197 | /* know operation, decode the mod byte to find the addressing | |
3198 | mode. */ | |
3199 | if (mod < 3) { | |
9c7e4b06 WD |
3200 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { |
3201 | u32 destval; | |
3202 | ||
3203 | DECODE_PRINTF("DWORD PTR "); | |
3204 | destoffset = decode_rmXX_address(mod, rl); | |
3205 | amt = fetch_byte_imm(); | |
3206 | DECODE_PRINTF2(",%x\n", amt); | |
3207 | destval = fetch_data_long(destoffset); | |
3208 | TRACE_AND_STEP(); | |
3209 | destval = (*opcD1_long_operation[rh]) (destval, amt); | |
3210 | store_data_long(destoffset, destval); | |
3211 | } else { | |
3212 | u16 destval; | |
3213 | ||
3214 | DECODE_PRINTF("WORD PTR "); | |
3215 | destoffset = decode_rmXX_address(mod, rl); | |
3216 | amt = fetch_byte_imm(); | |
3217 | DECODE_PRINTF2(",%x\n", amt); | |
3218 | destval = fetch_data_word(destoffset); | |
3219 | TRACE_AND_STEP(); | |
3220 | destval = (*opcD1_word_operation[rh]) (destval, amt); | |
3221 | store_data_word(destoffset, destval); | |
3222 | } | |
3223 | } else { /* register to register */ | |
3224 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
3225 | u32 *destreg; | |
3226 | ||
3227 | destreg = DECODE_RM_LONG_REGISTER(rl); | |
3228 | amt = fetch_byte_imm(); | |
3229 | DECODE_PRINTF2(",%x\n", amt); | |
3230 | TRACE_AND_STEP(); | |
3231 | *destreg = (*opcD1_long_operation[rh]) (*destreg, amt); | |
3232 | } else { | |
3233 | u16 *destreg; | |
3234 | ||
3235 | destreg = DECODE_RM_WORD_REGISTER(rl); | |
3236 | amt = fetch_byte_imm(); | |
3237 | DECODE_PRINTF2(",%x\n", amt); | |
3238 | TRACE_AND_STEP(); | |
3239 | *destreg = (*opcD1_word_operation[rh]) (*destreg, amt); | |
3240 | } | |
ece92f85 JJ |
3241 | } |
3242 | DECODE_CLEAR_SEGOVR(); | |
3243 | END_OF_INSTR(); | |
3244 | } | |
3245 | ||
3246 | /**************************************************************************** | |
3247 | REMARKS: | |
3248 | Handles opcode 0xc2 | |
3249 | ****************************************************************************/ | |
3250 | void x86emuOp_ret_near_IMM(u8 X86EMU_UNUSED(op1)) | |
3251 | { | |
3252 | u16 imm; | |
3253 | ||
3254 | START_OF_INSTR(); | |
3255 | DECODE_PRINTF("RET\t"); | |
3256 | imm = fetch_word_imm(); | |
3257 | DECODE_PRINTF2("%x\n", imm); | |
3258 | RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip); | |
3259 | TRACE_AND_STEP(); | |
3260 | M.x86.R_IP = pop_word(); | |
3261 | M.x86.R_SP += imm; | |
3262 | DECODE_CLEAR_SEGOVR(); | |
3263 | END_OF_INSTR(); | |
3264 | } | |
3265 | ||
3266 | /**************************************************************************** | |
3267 | REMARKS: | |
3268 | Handles opcode 0xc3 | |
3269 | ****************************************************************************/ | |
3270 | void x86emuOp_ret_near(u8 X86EMU_UNUSED(op1)) | |
3271 | { | |
3272 | START_OF_INSTR(); | |
3273 | DECODE_PRINTF("RET\n"); | |
3274 | RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip); | |
3275 | TRACE_AND_STEP(); | |
3276 | M.x86.R_IP = pop_word(); | |
3277 | DECODE_CLEAR_SEGOVR(); | |
3278 | END_OF_INSTR(); | |
3279 | } | |
3280 | ||
3281 | /**************************************************************************** | |
3282 | REMARKS: | |
3283 | Handles opcode 0xc4 | |
3284 | ****************************************************************************/ | |
3285 | void x86emuOp_les_R_IMM(u8 X86EMU_UNUSED(op1)) | |
3286 | { | |
3287 | int mod, rh, rl; | |
3288 | u16 *dstreg; | |
3289 | uint srcoffset; | |
3290 | ||
3291 | START_OF_INSTR(); | |
3292 | DECODE_PRINTF("LES\t"); | |
3293 | FETCH_DECODE_MODRM(mod, rh, rl); | |
3294 | if (mod < 3) { | |
9c7e4b06 WD |
3295 | dstreg = DECODE_RM_WORD_REGISTER(rh); |
3296 | DECODE_PRINTF(","); | |
3297 | srcoffset = decode_rmXX_address(mod, rl); | |
3298 | DECODE_PRINTF("\n"); | |
3299 | TRACE_AND_STEP(); | |
3300 | *dstreg = fetch_data_word(srcoffset); | |
3301 | M.x86.R_ES = fetch_data_word(srcoffset + 2); | |
ece92f85 | 3302 | } |
9c7e4b06 | 3303 | /* else UNDEFINED! register to register */ |
ece92f85 JJ |
3304 | |
3305 | DECODE_CLEAR_SEGOVR(); | |
3306 | END_OF_INSTR(); | |
3307 | } | |
3308 | ||
3309 | /**************************************************************************** | |
3310 | REMARKS: | |
3311 | Handles opcode 0xc5 | |
3312 | ****************************************************************************/ | |
3313 | void x86emuOp_lds_R_IMM(u8 X86EMU_UNUSED(op1)) | |
3314 | { | |
3315 | int mod, rh, rl; | |
3316 | u16 *dstreg; | |
3317 | uint srcoffset; | |
3318 | ||
3319 | START_OF_INSTR(); | |
3320 | DECODE_PRINTF("LDS\t"); | |
3321 | FETCH_DECODE_MODRM(mod, rh, rl); | |
3322 | if (mod < 3) { | |
9c7e4b06 WD |
3323 | dstreg = DECODE_RM_WORD_REGISTER(rh); |
3324 | DECODE_PRINTF(","); | |
3325 | srcoffset = decode_rmXX_address(mod, rl); | |
3326 | DECODE_PRINTF("\n"); | |
3327 | TRACE_AND_STEP(); | |
3328 | *dstreg = fetch_data_word(srcoffset); | |
3329 | M.x86.R_DS = fetch_data_word(srcoffset + 2); | |
ece92f85 JJ |
3330 | } |
3331 | /* else UNDEFINED! */ | |
3332 | DECODE_CLEAR_SEGOVR(); | |
3333 | END_OF_INSTR(); | |
3334 | } | |
3335 | ||
3336 | /**************************************************************************** | |
3337 | REMARKS: | |
3338 | Handles opcode 0xc6 | |
3339 | ****************************************************************************/ | |
3340 | void x86emuOp_mov_byte_RM_IMM(u8 X86EMU_UNUSED(op1)) | |
3341 | { | |
3342 | int mod, rl, rh; | |
3343 | u8 *destreg; | |
3344 | uint destoffset; | |
3345 | u8 imm; | |
3346 | ||
3347 | START_OF_INSTR(); | |
3348 | DECODE_PRINTF("MOV\t"); | |
3349 | FETCH_DECODE_MODRM(mod, rh, rl); | |
3350 | if (rh != 0) { | |
8c6ec412 | 3351 | ERR_PRINTF("ILLEGAL DECODE OF OPCODE c6\n"); |
9c7e4b06 | 3352 | HALT_SYS(); |
ece92f85 JJ |
3353 | } |
3354 | if (mod < 3) { | |
9c7e4b06 WD |
3355 | DECODE_PRINTF("BYTE PTR "); |
3356 | destoffset = decode_rmXX_address(mod, rl); | |
3357 | imm = fetch_byte_imm(); | |
3358 | DECODE_PRINTF2(",%2x\n", imm); | |
3359 | TRACE_AND_STEP(); | |
3360 | store_data_byte(destoffset, imm); | |
3361 | } else { /* register to register */ | |
3362 | destreg = DECODE_RM_BYTE_REGISTER(rl); | |
3363 | imm = fetch_byte_imm(); | |
3364 | DECODE_PRINTF2(",%2x\n", imm); | |
3365 | TRACE_AND_STEP(); | |
3366 | *destreg = imm; | |
ece92f85 JJ |
3367 | } |
3368 | DECODE_CLEAR_SEGOVR(); | |
3369 | END_OF_INSTR(); | |
3370 | } | |
3371 | ||
3372 | /**************************************************************************** | |
3373 | REMARKS: | |
3374 | Handles opcode 0xc7 | |
3375 | ****************************************************************************/ | |
3376 | void x86emuOp_mov_word_RM_IMM(u8 X86EMU_UNUSED(op1)) | |
3377 | { | |
3378 | int mod, rl, rh; | |
3379 | uint destoffset; | |
3380 | ||
3381 | START_OF_INSTR(); | |
3382 | DECODE_PRINTF("MOV\t"); | |
3383 | FETCH_DECODE_MODRM(mod, rh, rl); | |
3384 | if (rh != 0) { | |
8c6ec412 | 3385 | ERR_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n"); |
9c7e4b06 | 3386 | HALT_SYS(); |
ece92f85 JJ |
3387 | } |
3388 | if (mod < 3) { | |
9c7e4b06 WD |
3389 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { |
3390 | u32 imm; | |
3391 | ||
3392 | DECODE_PRINTF("DWORD PTR "); | |
3393 | destoffset = decode_rmXX_address(mod, rl); | |
3394 | imm = fetch_long_imm(); | |
3395 | DECODE_PRINTF2(",%x\n", imm); | |
3396 | TRACE_AND_STEP(); | |
3397 | store_data_long(destoffset, imm); | |
3398 | } else { | |
3399 | u16 imm; | |
3400 | ||
3401 | DECODE_PRINTF("WORD PTR "); | |
3402 | destoffset = decode_rmXX_address(mod, rl); | |
3403 | imm = fetch_word_imm(); | |
3404 | DECODE_PRINTF2(",%x\n", imm); | |
3405 | TRACE_AND_STEP(); | |
3406 | store_data_word(destoffset, imm); | |
3407 | } | |
3408 | } else { /* register to register */ | |
3409 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
ece92f85 JJ |
3410 | u32 *destreg; |
3411 | u32 imm; | |
3412 | ||
9c7e4b06 WD |
3413 | destreg = DECODE_RM_LONG_REGISTER(rl); |
3414 | imm = fetch_long_imm(); | |
3415 | DECODE_PRINTF2(",%x\n", imm); | |
3416 | TRACE_AND_STEP(); | |
3417 | *destreg = imm; | |
3418 | } else { | |
ece92f85 JJ |
3419 | u16 *destreg; |
3420 | u16 imm; | |
3421 | ||
9c7e4b06 WD |
3422 | destreg = DECODE_RM_WORD_REGISTER(rl); |
3423 | imm = fetch_word_imm(); | |
3424 | DECODE_PRINTF2(",%x\n", imm); | |
3425 | TRACE_AND_STEP(); | |
3426 | *destreg = imm; | |
3427 | } | |
ece92f85 JJ |
3428 | } |
3429 | DECODE_CLEAR_SEGOVR(); | |
3430 | END_OF_INSTR(); | |
3431 | } | |
3432 | ||
3433 | /**************************************************************************** | |
3434 | REMARKS: | |
3435 | Handles opcode 0xc8 | |
3436 | ****************************************************************************/ | |
3437 | void x86emuOp_enter(u8 X86EMU_UNUSED(op1)) | |
3438 | { | |
3439 | u16 local,frame_pointer; | |
9c7e4b06 | 3440 | u8 nesting; |
ece92f85 JJ |
3441 | int i; |
3442 | ||
3443 | START_OF_INSTR(); | |
3444 | local = fetch_word_imm(); | |
3445 | nesting = fetch_byte_imm(); | |
3446 | DECODE_PRINTF2("ENTER %x\n", local); | |
3447 | DECODE_PRINTF2(",%x\n", nesting); | |
3448 | TRACE_AND_STEP(); | |
3449 | push_word(M.x86.R_BP); | |
3450 | frame_pointer = M.x86.R_SP; | |
3451 | if (nesting > 0) { | |
9c7e4b06 WD |
3452 | for (i = 1; i < nesting; i++) { |
3453 | M.x86.R_BP -= 2; | |
3454 | push_word(fetch_data_word_abs(M.x86.R_SS, M.x86.R_BP)); | |
3455 | } | |
3456 | push_word(frame_pointer); | |
3457 | } | |
ece92f85 JJ |
3458 | M.x86.R_BP = frame_pointer; |
3459 | M.x86.R_SP = (u16)(M.x86.R_SP - local); | |
3460 | DECODE_CLEAR_SEGOVR(); | |
3461 | END_OF_INSTR(); | |
3462 | } | |
3463 | ||
3464 | /**************************************************************************** | |
3465 | REMARKS: | |
3466 | Handles opcode 0xc9 | |
3467 | ****************************************************************************/ | |
3468 | void x86emuOp_leave(u8 X86EMU_UNUSED(op1)) | |
3469 | { | |
3470 | START_OF_INSTR(); | |
3471 | DECODE_PRINTF("LEAVE\n"); | |
3472 | TRACE_AND_STEP(); | |
3473 | M.x86.R_SP = M.x86.R_BP; | |
3474 | M.x86.R_BP = pop_word(); | |
3475 | DECODE_CLEAR_SEGOVR(); | |
3476 | END_OF_INSTR(); | |
3477 | } | |
3478 | ||
3479 | /**************************************************************************** | |
3480 | REMARKS: | |
3481 | Handles opcode 0xca | |
3482 | ****************************************************************************/ | |
3483 | void x86emuOp_ret_far_IMM(u8 X86EMU_UNUSED(op1)) | |
3484 | { | |
3485 | u16 imm; | |
3486 | ||
3487 | START_OF_INSTR(); | |
3488 | DECODE_PRINTF("RETF\t"); | |
3489 | imm = fetch_word_imm(); | |
3490 | DECODE_PRINTF2("%x\n", imm); | |
3491 | RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip); | |
3492 | TRACE_AND_STEP(); | |
3493 | M.x86.R_IP = pop_word(); | |
3494 | M.x86.R_CS = pop_word(); | |
3495 | M.x86.R_SP += imm; | |
3496 | DECODE_CLEAR_SEGOVR(); | |
3497 | END_OF_INSTR(); | |
3498 | } | |
3499 | ||
3500 | /**************************************************************************** | |
3501 | REMARKS: | |
3502 | Handles opcode 0xcb | |
3503 | ****************************************************************************/ | |
3504 | void x86emuOp_ret_far(u8 X86EMU_UNUSED(op1)) | |
3505 | { | |
3506 | START_OF_INSTR(); | |
3507 | DECODE_PRINTF("RETF\n"); | |
3508 | RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip); | |
3509 | TRACE_AND_STEP(); | |
3510 | M.x86.R_IP = pop_word(); | |
3511 | M.x86.R_CS = pop_word(); | |
3512 | DECODE_CLEAR_SEGOVR(); | |
3513 | END_OF_INSTR(); | |
3514 | } | |
3515 | ||
3516 | /**************************************************************************** | |
3517 | REMARKS: | |
3518 | Handles opcode 0xcc | |
3519 | ****************************************************************************/ | |
3520 | void x86emuOp_int3(u8 X86EMU_UNUSED(op1)) | |
3521 | { | |
ece92f85 JJ |
3522 | START_OF_INSTR(); |
3523 | DECODE_PRINTF("INT 3\n"); | |
755cf792 | 3524 | (void)mem_access_word(3 * 4 + 2); |
ece92f85 JJ |
3525 | /* access the segment register */ |
3526 | TRACE_AND_STEP(); | |
3527 | if (_X86EMU_intrTab[3]) { | |
3528 | (*_X86EMU_intrTab[3])(3); | |
3529 | } else { | |
9c7e4b06 WD |
3530 | push_word((u16)M.x86.R_FLG); |
3531 | CLEAR_FLAG(F_IF); | |
3532 | CLEAR_FLAG(F_TF); | |
3533 | push_word(M.x86.R_CS); | |
3534 | M.x86.R_CS = mem_access_word(3 * 4 + 2); | |
3535 | push_word(M.x86.R_IP); | |
3536 | M.x86.R_IP = mem_access_word(3 * 4); | |
ece92f85 JJ |
3537 | } |
3538 | DECODE_CLEAR_SEGOVR(); | |
3539 | END_OF_INSTR(); | |
3540 | } | |
3541 | ||
3542 | /**************************************************************************** | |
3543 | REMARKS: | |
3544 | Handles opcode 0xcd | |
3545 | ****************************************************************************/ | |
3546 | void x86emuOp_int_IMM(u8 X86EMU_UNUSED(op1)) | |
3547 | { | |
ece92f85 JJ |
3548 | u8 intnum; |
3549 | ||
3550 | START_OF_INSTR(); | |
3551 | DECODE_PRINTF("INT\t"); | |
3552 | intnum = fetch_byte_imm(); | |
3553 | DECODE_PRINTF2("%x\n", intnum); | |
755cf792 | 3554 | (void)mem_access_word(intnum * 4 + 2); |
ece92f85 JJ |
3555 | TRACE_AND_STEP(); |
3556 | if (_X86EMU_intrTab[intnum]) { | |
3557 | (*_X86EMU_intrTab[intnum])(intnum); | |
3558 | } else { | |
9c7e4b06 WD |
3559 | push_word((u16)M.x86.R_FLG); |
3560 | CLEAR_FLAG(F_IF); | |
3561 | CLEAR_FLAG(F_TF); | |
3562 | push_word(M.x86.R_CS); | |
3563 | M.x86.R_CS = mem_access_word(intnum * 4 + 2); | |
3564 | push_word(M.x86.R_IP); | |
3565 | M.x86.R_IP = mem_access_word(intnum * 4); | |
ece92f85 JJ |
3566 | } |
3567 | DECODE_CLEAR_SEGOVR(); | |
3568 | END_OF_INSTR(); | |
3569 | } | |
3570 | ||
3571 | /**************************************************************************** | |
3572 | REMARKS: | |
3573 | Handles opcode 0xce | |
3574 | ****************************************************************************/ | |
3575 | void x86emuOp_into(u8 X86EMU_UNUSED(op1)) | |
3576 | { | |
ece92f85 JJ |
3577 | START_OF_INSTR(); |
3578 | DECODE_PRINTF("INTO\n"); | |
3579 | TRACE_AND_STEP(); | |
3580 | if (ACCESS_FLAG(F_OF)) { | |
755cf792 | 3581 | (void)mem_access_word(4 * 4 + 2); |
ece92f85 JJ |
3582 | if (_X86EMU_intrTab[4]) { |
3583 | (*_X86EMU_intrTab[4])(4); | |
9c7e4b06 WD |
3584 | } else { |
3585 | push_word((u16)M.x86.R_FLG); | |
3586 | CLEAR_FLAG(F_IF); | |
3587 | CLEAR_FLAG(F_TF); | |
3588 | push_word(M.x86.R_CS); | |
3589 | M.x86.R_CS = mem_access_word(4 * 4 + 2); | |
3590 | push_word(M.x86.R_IP); | |
3591 | M.x86.R_IP = mem_access_word(4 * 4); | |
3592 | } | |
ece92f85 JJ |
3593 | } |
3594 | DECODE_CLEAR_SEGOVR(); | |
3595 | END_OF_INSTR(); | |
3596 | } | |
3597 | ||
3598 | /**************************************************************************** | |
3599 | REMARKS: | |
3600 | Handles opcode 0xcf | |
3601 | ****************************************************************************/ | |
3602 | void x86emuOp_iret(u8 X86EMU_UNUSED(op1)) | |
3603 | { | |
3604 | START_OF_INSTR(); | |
3605 | DECODE_PRINTF("IRET\n"); | |
3606 | ||
3607 | TRACE_AND_STEP(); | |
3608 | ||
3609 | M.x86.R_IP = pop_word(); | |
3610 | M.x86.R_CS = pop_word(); | |
3611 | M.x86.R_FLG = pop_word(); | |
3612 | DECODE_CLEAR_SEGOVR(); | |
3613 | END_OF_INSTR(); | |
3614 | } | |
3615 | ||
3616 | /**************************************************************************** | |
3617 | REMARKS: | |
3618 | Handles opcode 0xd0 | |
3619 | ****************************************************************************/ | |
3620 | void x86emuOp_opcD0_byte_RM_1(u8 X86EMU_UNUSED(op1)) | |
3621 | { | |
3622 | int mod, rl, rh; | |
3623 | u8 *destreg; | |
3624 | uint destoffset; | |
3625 | u8 destval; | |
3626 | ||
3627 | /* | |
3628 | * Yet another weirdo special case instruction format. Part of | |
3629 | * the opcode held below in "RH". Doubly nested case would | |
3630 | * result, except that the decoded instruction | |
3631 | */ | |
3632 | START_OF_INSTR(); | |
3633 | FETCH_DECODE_MODRM(mod, rh, rl); | |
b3521f2e | 3634 | #ifdef CONFIG_X86EMU_DEBUG |
ece92f85 | 3635 | if (DEBUG_DECODE()) { |
9c7e4b06 WD |
3636 | /* XXX DECODE_PRINTF may be changed to something more |
3637 | general, so that it is important to leave the strings | |
3638 | in the same format, even though the result is that the | |
3639 | above test is done twice. */ | |
3640 | switch (rh) { | |
3641 | case 0: | |
3642 | DECODE_PRINTF("ROL\t"); | |
3643 | break; | |
3644 | case 1: | |
3645 | DECODE_PRINTF("ROR\t"); | |
3646 | break; | |
3647 | case 2: | |
3648 | DECODE_PRINTF("RCL\t"); | |
3649 | break; | |
3650 | case 3: | |
3651 | DECODE_PRINTF("RCR\t"); | |
3652 | break; | |
3653 | case 4: | |
3654 | DECODE_PRINTF("SHL\t"); | |
3655 | break; | |
3656 | case 5: | |
3657 | DECODE_PRINTF("SHR\t"); | |
3658 | break; | |
3659 | case 6: | |
3660 | DECODE_PRINTF("SAL\t"); | |
3661 | break; | |
3662 | case 7: | |
3663 | DECODE_PRINTF("SAR\t"); | |
3664 | break; | |
3665 | } | |
ece92f85 JJ |
3666 | } |
3667 | #endif | |
3668 | /* know operation, decode the mod byte to find the addressing | |
3669 | mode. */ | |
3670 | if (mod < 3) { | |
9c7e4b06 WD |
3671 | DECODE_PRINTF("BYTE PTR "); |
3672 | destoffset = decode_rmXX_address(mod, rl); | |
3673 | DECODE_PRINTF(",1\n"); | |
3674 | destval = fetch_data_byte(destoffset); | |
3675 | TRACE_AND_STEP(); | |
3676 | destval = (*opcD0_byte_operation[rh]) (destval, 1); | |
3677 | store_data_byte(destoffset, destval); | |
3678 | } else { /* register to register */ | |
3679 | destreg = DECODE_RM_BYTE_REGISTER(rl); | |
3680 | DECODE_PRINTF(",1\n"); | |
3681 | TRACE_AND_STEP(); | |
3682 | destval = (*opcD0_byte_operation[rh]) (*destreg, 1); | |
3683 | *destreg = destval; | |
ece92f85 JJ |
3684 | } |
3685 | DECODE_CLEAR_SEGOVR(); | |
3686 | END_OF_INSTR(); | |
3687 | } | |
3688 | ||
3689 | /**************************************************************************** | |
3690 | REMARKS: | |
3691 | Handles opcode 0xd1 | |
3692 | ****************************************************************************/ | |
3693 | void x86emuOp_opcD1_word_RM_1(u8 X86EMU_UNUSED(op1)) | |
3694 | { | |
3695 | int mod, rl, rh; | |
3696 | uint destoffset; | |
3697 | ||
3698 | /* | |
3699 | * Yet another weirdo special case instruction format. Part of | |
3700 | * the opcode held below in "RH". Doubly nested case would | |
3701 | * result, except that the decoded instruction | |
3702 | */ | |
3703 | START_OF_INSTR(); | |
3704 | FETCH_DECODE_MODRM(mod, rh, rl); | |
b3521f2e | 3705 | #ifdef CONFIG_X86EMU_DEBUG |
ece92f85 | 3706 | if (DEBUG_DECODE()) { |
9c7e4b06 WD |
3707 | /* XXX DECODE_PRINTF may be changed to something more |
3708 | general, so that it is important to leave the strings | |
3709 | in the same format, even though the result is that the | |
3710 | above test is done twice. */ | |
3711 | switch (rh) { | |
3712 | case 0: | |
3713 | DECODE_PRINTF("ROL\t"); | |
3714 | break; | |
3715 | case 1: | |
3716 | DECODE_PRINTF("ROR\t"); | |
3717 | break; | |
3718 | case 2: | |
3719 | DECODE_PRINTF("RCL\t"); | |
3720 | break; | |
3721 | case 3: | |
3722 | DECODE_PRINTF("RCR\t"); | |
3723 | break; | |
3724 | case 4: | |
3725 | DECODE_PRINTF("SHL\t"); | |
3726 | break; | |
3727 | case 5: | |
3728 | DECODE_PRINTF("SHR\t"); | |
3729 | break; | |
3730 | case 6: | |
3731 | DECODE_PRINTF("SAL\t"); | |
3732 | break; | |
3733 | case 7: | |
3734 | DECODE_PRINTF("SAR\t"); | |
3735 | break; | |
3736 | } | |
ece92f85 JJ |
3737 | } |
3738 | #endif | |
3739 | /* know operation, decode the mod byte to find the addressing | |
3740 | mode. */ | |
3741 | if (mod < 3) { | |
9c7e4b06 WD |
3742 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { |
3743 | u32 destval; | |
3744 | ||
3745 | DECODE_PRINTF("DWORD PTR "); | |
3746 | destoffset = decode_rmXX_address(mod, rl); | |
3747 | DECODE_PRINTF(",1\n"); | |
3748 | destval = fetch_data_long(destoffset); | |
3749 | TRACE_AND_STEP(); | |
3750 | destval = (*opcD1_long_operation[rh]) (destval, 1); | |
3751 | store_data_long(destoffset, destval); | |
3752 | } else { | |
3753 | u16 destval; | |
3754 | ||
3755 | DECODE_PRINTF("WORD PTR "); | |
3756 | destoffset = decode_rmXX_address(mod, rl); | |
3757 | DECODE_PRINTF(",1\n"); | |
3758 | destval = fetch_data_word(destoffset); | |
3759 | TRACE_AND_STEP(); | |
3760 | destval = (*opcD1_word_operation[rh]) (destval, 1); | |
3761 | store_data_word(destoffset, destval); | |
3762 | } | |
3763 | } else { /* register to register */ | |
3764 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
ece92f85 JJ |
3765 | u32 destval; |
3766 | u32 *destreg; | |
3767 | ||
9c7e4b06 WD |
3768 | destreg = DECODE_RM_LONG_REGISTER(rl); |
3769 | DECODE_PRINTF(",1\n"); | |
3770 | TRACE_AND_STEP(); | |
3771 | destval = (*opcD1_long_operation[rh]) (*destreg, 1); | |
3772 | *destreg = destval; | |
3773 | } else { | |
ece92f85 JJ |
3774 | u16 destval; |
3775 | u16 *destreg; | |
3776 | ||
9c7e4b06 WD |
3777 | destreg = DECODE_RM_WORD_REGISTER(rl); |
3778 | DECODE_PRINTF(",1\n"); | |
3779 | TRACE_AND_STEP(); | |
3780 | destval = (*opcD1_word_operation[rh]) (*destreg, 1); | |
3781 | *destreg = destval; | |
3782 | } | |
ece92f85 JJ |
3783 | } |
3784 | DECODE_CLEAR_SEGOVR(); | |
3785 | END_OF_INSTR(); | |
3786 | } | |
3787 | ||
3788 | /**************************************************************************** | |
3789 | REMARKS: | |
3790 | Handles opcode 0xd2 | |
3791 | ****************************************************************************/ | |
3792 | void x86emuOp_opcD2_byte_RM_CL(u8 X86EMU_UNUSED(op1)) | |
3793 | { | |
3794 | int mod, rl, rh; | |
3795 | u8 *destreg; | |
3796 | uint destoffset; | |
3797 | u8 destval; | |
3798 | u8 amt; | |
3799 | ||
3800 | /* | |
3801 | * Yet another weirdo special case instruction format. Part of | |
3802 | * the opcode held below in "RH". Doubly nested case would | |
3803 | * result, except that the decoded instruction | |
3804 | */ | |
3805 | START_OF_INSTR(); | |
3806 | FETCH_DECODE_MODRM(mod, rh, rl); | |
b3521f2e | 3807 | #ifdef CONFIG_X86EMU_DEBUG |
ece92f85 | 3808 | if (DEBUG_DECODE()) { |
9c7e4b06 WD |
3809 | /* XXX DECODE_PRINTF may be changed to something more |
3810 | general, so that it is important to leave the strings | |
3811 | in the same format, even though the result is that the | |
3812 | above test is done twice. */ | |
3813 | switch (rh) { | |
3814 | case 0: | |
3815 | DECODE_PRINTF("ROL\t"); | |
3816 | break; | |
3817 | case 1: | |
3818 | DECODE_PRINTF("ROR\t"); | |
3819 | break; | |
3820 | case 2: | |
3821 | DECODE_PRINTF("RCL\t"); | |
3822 | break; | |
3823 | case 3: | |
3824 | DECODE_PRINTF("RCR\t"); | |
3825 | break; | |
3826 | case 4: | |
3827 | DECODE_PRINTF("SHL\t"); | |
3828 | break; | |
3829 | case 5: | |
3830 | DECODE_PRINTF("SHR\t"); | |
3831 | break; | |
3832 | case 6: | |
3833 | DECODE_PRINTF("SAL\t"); | |
3834 | break; | |
3835 | case 7: | |
3836 | DECODE_PRINTF("SAR\t"); | |
3837 | break; | |
3838 | } | |
ece92f85 JJ |
3839 | } |
3840 | #endif | |
3841 | /* know operation, decode the mod byte to find the addressing | |
3842 | mode. */ | |
3843 | amt = M.x86.R_CL; | |
3844 | if (mod < 3) { | |
9c7e4b06 WD |
3845 | DECODE_PRINTF("BYTE PTR "); |
3846 | destoffset = decode_rmXX_address(mod, rl); | |
3847 | DECODE_PRINTF(",CL\n"); | |
3848 | destval = fetch_data_byte(destoffset); | |
3849 | TRACE_AND_STEP(); | |
3850 | destval = (*opcD0_byte_operation[rh]) (destval, amt); | |
3851 | store_data_byte(destoffset, destval); | |
3852 | } else { /* register to register */ | |
3853 | destreg = DECODE_RM_BYTE_REGISTER(rl); | |
3854 | DECODE_PRINTF(",CL\n"); | |
3855 | TRACE_AND_STEP(); | |
3856 | destval = (*opcD0_byte_operation[rh]) (*destreg, amt); | |
3857 | *destreg = destval; | |
ece92f85 JJ |
3858 | } |
3859 | DECODE_CLEAR_SEGOVR(); | |
3860 | END_OF_INSTR(); | |
3861 | } | |
3862 | ||
3863 | /**************************************************************************** | |
3864 | REMARKS: | |
3865 | Handles opcode 0xd3 | |
3866 | ****************************************************************************/ | |
3867 | void x86emuOp_opcD3_word_RM_CL(u8 X86EMU_UNUSED(op1)) | |
3868 | { | |
3869 | int mod, rl, rh; | |
3870 | uint destoffset; | |
3871 | u8 amt; | |
3872 | ||
3873 | /* | |
3874 | * Yet another weirdo special case instruction format. Part of | |
3875 | * the opcode held below in "RH". Doubly nested case would | |
3876 | * result, except that the decoded instruction | |
3877 | */ | |
3878 | START_OF_INSTR(); | |
3879 | FETCH_DECODE_MODRM(mod, rh, rl); | |
b3521f2e | 3880 | #ifdef CONFIG_X86EMU_DEBUG |
ece92f85 | 3881 | if (DEBUG_DECODE()) { |
9c7e4b06 WD |
3882 | /* XXX DECODE_PRINTF may be changed to something more |
3883 | general, so that it is important to leave the strings | |
3884 | in the same format, even though the result is that the | |
3885 | above test is done twice. */ | |
3886 | switch (rh) { | |
3887 | case 0: | |
3888 | DECODE_PRINTF("ROL\t"); | |
3889 | break; | |
3890 | case 1: | |
3891 | DECODE_PRINTF("ROR\t"); | |
3892 | break; | |
3893 | case 2: | |
3894 | DECODE_PRINTF("RCL\t"); | |
3895 | break; | |
3896 | case 3: | |
3897 | DECODE_PRINTF("RCR\t"); | |
3898 | break; | |
3899 | case 4: | |
3900 | DECODE_PRINTF("SHL\t"); | |
3901 | break; | |
3902 | case 5: | |
3903 | DECODE_PRINTF("SHR\t"); | |
3904 | break; | |
3905 | case 6: | |
3906 | DECODE_PRINTF("SAL\t"); | |
3907 | break; | |
3908 | case 7: | |
3909 | DECODE_PRINTF("SAR\t"); | |
3910 | break; | |
3911 | } | |
ece92f85 JJ |
3912 | } |
3913 | #endif | |
3914 | /* know operation, decode the mod byte to find the addressing | |
3915 | mode. */ | |
3916 | amt = M.x86.R_CL; | |
3917 | if (mod < 3) { | |
9c7e4b06 WD |
3918 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { |
3919 | u32 destval; | |
3920 | ||
3921 | DECODE_PRINTF("DWORD PTR "); | |
3922 | destoffset = decode_rmXX_address(mod, rl); | |
3923 | DECODE_PRINTF(",CL\n"); | |
3924 | destval = fetch_data_long(destoffset); | |
3925 | TRACE_AND_STEP(); | |
3926 | destval = (*opcD1_long_operation[rh]) (destval, amt); | |
3927 | store_data_long(destoffset, destval); | |
3928 | } else { | |
3929 | u16 destval; | |
3930 | ||
3931 | DECODE_PRINTF("WORD PTR "); | |
3932 | destoffset = decode_rmXX_address(mod, rl); | |
3933 | DECODE_PRINTF(",CL\n"); | |
3934 | destval = fetch_data_word(destoffset); | |
3935 | TRACE_AND_STEP(); | |
3936 | destval = (*opcD1_word_operation[rh]) (destval, amt); | |
3937 | store_data_word(destoffset, destval); | |
3938 | } | |
3939 | } else { /* register to register */ | |
3940 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
3941 | u32 *destreg; | |
3942 | ||
3943 | destreg = DECODE_RM_LONG_REGISTER(rl); | |
3944 | DECODE_PRINTF(",CL\n"); | |
3945 | TRACE_AND_STEP(); | |
3946 | *destreg = (*opcD1_long_operation[rh]) (*destreg, amt); | |
3947 | } else { | |
3948 | u16 *destreg; | |
3949 | ||
3950 | destreg = DECODE_RM_WORD_REGISTER(rl); | |
3951 | DECODE_PRINTF(",CL\n"); | |
3952 | TRACE_AND_STEP(); | |
3953 | *destreg = (*opcD1_word_operation[rh]) (*destreg, amt); | |
3954 | } | |
ece92f85 JJ |
3955 | } |
3956 | DECODE_CLEAR_SEGOVR(); | |
3957 | END_OF_INSTR(); | |
3958 | } | |
3959 | ||
3960 | /**************************************************************************** | |
3961 | REMARKS: | |
3962 | Handles opcode 0xd4 | |
3963 | ****************************************************************************/ | |
3964 | void x86emuOp_aam(u8 X86EMU_UNUSED(op1)) | |
3965 | { | |
3966 | u8 a; | |
3967 | ||
3968 | START_OF_INSTR(); | |
3969 | DECODE_PRINTF("AAM\n"); | |
3970 | a = fetch_byte_imm(); /* this is a stupid encoding. */ | |
3971 | if (a != 10) { | |
8c6ec412 | 3972 | ERR_PRINTF("ERROR DECODING AAM\n"); |
9c7e4b06 WD |
3973 | TRACE_REGS(); |
3974 | HALT_SYS(); | |
ece92f85 JJ |
3975 | } |
3976 | TRACE_AND_STEP(); | |
3977 | /* note the type change here --- returning AL and AH in AX. */ | |
3978 | M.x86.R_AX = aam_word(M.x86.R_AL); | |
3979 | DECODE_CLEAR_SEGOVR(); | |
3980 | END_OF_INSTR(); | |
3981 | } | |
3982 | ||
3983 | /**************************************************************************** | |
3984 | REMARKS: | |
3985 | Handles opcode 0xd5 | |
3986 | ****************************************************************************/ | |
3987 | void x86emuOp_aad(u8 X86EMU_UNUSED(op1)) | |
3988 | { | |
ece92f85 JJ |
3989 | START_OF_INSTR(); |
3990 | DECODE_PRINTF("AAD\n"); | |
755cf792 | 3991 | (void)fetch_byte_imm(); |
ece92f85 JJ |
3992 | TRACE_AND_STEP(); |
3993 | M.x86.R_AX = aad_word(M.x86.R_AX); | |
3994 | DECODE_CLEAR_SEGOVR(); | |
3995 | END_OF_INSTR(); | |
3996 | } | |
3997 | ||
3998 | /* opcode 0xd6 ILLEGAL OPCODE */ | |
3999 | ||
4000 | /**************************************************************************** | |
4001 | REMARKS: | |
4002 | Handles opcode 0xd7 | |
4003 | ****************************************************************************/ | |
4004 | void x86emuOp_xlat(u8 X86EMU_UNUSED(op1)) | |
4005 | { | |
4006 | u16 addr; | |
4007 | ||
4008 | START_OF_INSTR(); | |
4009 | DECODE_PRINTF("XLAT\n"); | |
4010 | TRACE_AND_STEP(); | |
4011 | addr = (u16)(M.x86.R_BX + (u8)M.x86.R_AL); | |
4012 | M.x86.R_AL = fetch_data_byte(addr); | |
4013 | DECODE_CLEAR_SEGOVR(); | |
4014 | END_OF_INSTR(); | |
4015 | } | |
4016 | ||
9c7e4b06 | 4017 | /* instuctions D8 .. DF are in i87_ops.c */ |
ece92f85 JJ |
4018 | |
4019 | /**************************************************************************** | |
4020 | REMARKS: | |
4021 | Handles opcode 0xe0 | |
4022 | ****************************************************************************/ | |
4023 | void x86emuOp_loopne(u8 X86EMU_UNUSED(op1)) | |
4024 | { | |
4025 | s16 ip; | |
4026 | ||
4027 | START_OF_INSTR(); | |
4028 | DECODE_PRINTF("LOOPNE\t"); | |
4029 | ip = (s8) fetch_byte_imm(); | |
4030 | ip += (s16) M.x86.R_IP; | |
4031 | DECODE_PRINTF2("%04x\n", ip); | |
4032 | TRACE_AND_STEP(); | |
4033 | M.x86.R_CX -= 1; | |
9c7e4b06 WD |
4034 | if (M.x86.R_CX != 0 && !ACCESS_FLAG(F_ZF)) /* CX != 0 and !ZF */ |
4035 | M.x86.R_IP = ip; | |
ece92f85 JJ |
4036 | DECODE_CLEAR_SEGOVR(); |
4037 | END_OF_INSTR(); | |
4038 | } | |
4039 | ||
4040 | /**************************************************************************** | |
4041 | REMARKS: | |
4042 | Handles opcode 0xe1 | |
4043 | ****************************************************************************/ | |
4044 | void x86emuOp_loope(u8 X86EMU_UNUSED(op1)) | |
4045 | { | |
4046 | s16 ip; | |
4047 | ||
4048 | START_OF_INSTR(); | |
4049 | DECODE_PRINTF("LOOPE\t"); | |
4050 | ip = (s8) fetch_byte_imm(); | |
4051 | ip += (s16) M.x86.R_IP; | |
4052 | DECODE_PRINTF2("%04x\n", ip); | |
4053 | TRACE_AND_STEP(); | |
4054 | M.x86.R_CX -= 1; | |
9c7e4b06 WD |
4055 | if (M.x86.R_CX != 0 && ACCESS_FLAG(F_ZF)) /* CX != 0 and ZF */ |
4056 | M.x86.R_IP = ip; | |
ece92f85 JJ |
4057 | DECODE_CLEAR_SEGOVR(); |
4058 | END_OF_INSTR(); | |
4059 | } | |
4060 | ||
4061 | /**************************************************************************** | |
4062 | REMARKS: | |
4063 | Handles opcode 0xe2 | |
4064 | ****************************************************************************/ | |
4065 | void x86emuOp_loop(u8 X86EMU_UNUSED(op1)) | |
4066 | { | |
4067 | s16 ip; | |
4068 | ||
4069 | START_OF_INSTR(); | |
4070 | DECODE_PRINTF("LOOP\t"); | |
4071 | ip = (s8) fetch_byte_imm(); | |
4072 | ip += (s16) M.x86.R_IP; | |
4073 | DECODE_PRINTF2("%04x\n", ip); | |
4074 | TRACE_AND_STEP(); | |
4075 | M.x86.R_CX -= 1; | |
4076 | if (M.x86.R_CX != 0) | |
9c7e4b06 | 4077 | M.x86.R_IP = ip; |
ece92f85 JJ |
4078 | DECODE_CLEAR_SEGOVR(); |
4079 | END_OF_INSTR(); | |
4080 | } | |
4081 | ||
4082 | /**************************************************************************** | |
4083 | REMARKS: | |
4084 | Handles opcode 0xe3 | |
4085 | ****************************************************************************/ | |
4086 | void x86emuOp_jcxz(u8 X86EMU_UNUSED(op1)) | |
4087 | { | |
4088 | u16 target; | |
9c7e4b06 | 4089 | s8 offset; |
ece92f85 JJ |
4090 | |
4091 | /* jump to byte offset if overflow flag is set */ | |
4092 | START_OF_INSTR(); | |
4093 | DECODE_PRINTF("JCXZ\t"); | |
4094 | offset = (s8)fetch_byte_imm(); | |
4095 | target = (u16)(M.x86.R_IP + offset); | |
4096 | DECODE_PRINTF2("%x\n", target); | |
4097 | TRACE_AND_STEP(); | |
4098 | if (M.x86.R_CX == 0) | |
9c7e4b06 | 4099 | M.x86.R_IP = target; |
ece92f85 JJ |
4100 | DECODE_CLEAR_SEGOVR(); |
4101 | END_OF_INSTR(); | |
4102 | } | |
4103 | ||
4104 | /**************************************************************************** | |
4105 | REMARKS: | |
4106 | Handles opcode 0xe4 | |
4107 | ****************************************************************************/ | |
4108 | void x86emuOp_in_byte_AL_IMM(u8 X86EMU_UNUSED(op1)) | |
4109 | { | |
4110 | u8 port; | |
4111 | ||
4112 | START_OF_INSTR(); | |
4113 | DECODE_PRINTF("IN\t"); | |
4114 | port = (u8) fetch_byte_imm(); | |
4115 | DECODE_PRINTF2("%x,AL\n", port); | |
4116 | TRACE_AND_STEP(); | |
4117 | M.x86.R_AL = (*sys_inb)(port); | |
4118 | DECODE_CLEAR_SEGOVR(); | |
4119 | END_OF_INSTR(); | |
4120 | } | |
4121 | ||
4122 | /**************************************************************************** | |
4123 | REMARKS: | |
4124 | Handles opcode 0xe5 | |
4125 | ****************************************************************************/ | |
4126 | void x86emuOp_in_word_AX_IMM(u8 X86EMU_UNUSED(op1)) | |
4127 | { | |
4128 | u8 port; | |
4129 | ||
4130 | START_OF_INSTR(); | |
4131 | DECODE_PRINTF("IN\t"); | |
4132 | port = (u8) fetch_byte_imm(); | |
4133 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 | 4134 | DECODE_PRINTF2("EAX,%x\n", port); |
ece92f85 | 4135 | } else { |
9c7e4b06 | 4136 | DECODE_PRINTF2("AX,%x\n", port); |
ece92f85 JJ |
4137 | } |
4138 | TRACE_AND_STEP(); | |
4139 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 | 4140 | M.x86.R_EAX = (*sys_inl)(port); |
ece92f85 | 4141 | } else { |
9c7e4b06 | 4142 | M.x86.R_AX = (*sys_inw)(port); |
ece92f85 JJ |
4143 | } |
4144 | DECODE_CLEAR_SEGOVR(); | |
4145 | END_OF_INSTR(); | |
4146 | } | |
4147 | ||
4148 | /**************************************************************************** | |
4149 | REMARKS: | |
4150 | Handles opcode 0xe6 | |
4151 | ****************************************************************************/ | |
4152 | void x86emuOp_out_byte_IMM_AL(u8 X86EMU_UNUSED(op1)) | |
4153 | { | |
4154 | u8 port; | |
4155 | ||
4156 | START_OF_INSTR(); | |
4157 | DECODE_PRINTF("OUT\t"); | |
4158 | port = (u8) fetch_byte_imm(); | |
4159 | DECODE_PRINTF2("%x,AL\n", port); | |
4160 | TRACE_AND_STEP(); | |
4161 | (*sys_outb)(port, M.x86.R_AL); | |
4162 | DECODE_CLEAR_SEGOVR(); | |
4163 | END_OF_INSTR(); | |
4164 | } | |
4165 | ||
4166 | /**************************************************************************** | |
4167 | REMARKS: | |
4168 | Handles opcode 0xe7 | |
4169 | ****************************************************************************/ | |
4170 | void x86emuOp_out_word_IMM_AX(u8 X86EMU_UNUSED(op1)) | |
4171 | { | |
4172 | u8 port; | |
4173 | ||
4174 | START_OF_INSTR(); | |
4175 | DECODE_PRINTF("OUT\t"); | |
4176 | port = (u8) fetch_byte_imm(); | |
4177 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 | 4178 | DECODE_PRINTF2("%x,EAX\n", port); |
ece92f85 | 4179 | } else { |
9c7e4b06 | 4180 | DECODE_PRINTF2("%x,AX\n", port); |
ece92f85 JJ |
4181 | } |
4182 | TRACE_AND_STEP(); | |
4183 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 | 4184 | (*sys_outl)(port, M.x86.R_EAX); |
ece92f85 | 4185 | } else { |
9c7e4b06 | 4186 | (*sys_outw)(port, M.x86.R_AX); |
ece92f85 JJ |
4187 | } |
4188 | DECODE_CLEAR_SEGOVR(); | |
4189 | END_OF_INSTR(); | |
4190 | } | |
4191 | ||
4192 | /**************************************************************************** | |
4193 | REMARKS: | |
4194 | Handles opcode 0xe8 | |
4195 | ****************************************************************************/ | |
4196 | void x86emuOp_call_near_IMM(u8 X86EMU_UNUSED(op1)) | |
4197 | { | |
4198 | s16 ip; | |
4199 | ||
4200 | START_OF_INSTR(); | |
4201 | DECODE_PRINTF("CALL\t"); | |
4202 | ip = (s16) fetch_word_imm(); | |
9c7e4b06 | 4203 | ip += (s16) M.x86.R_IP; /* CHECK SIGN */ |
ece92f85 JJ |
4204 | DECODE_PRINTF2("%04x\n", ip); |
4205 | CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip, ""); | |
4206 | TRACE_AND_STEP(); | |
4207 | push_word(M.x86.R_IP); | |
4208 | M.x86.R_IP = ip; | |
4209 | DECODE_CLEAR_SEGOVR(); | |
4210 | END_OF_INSTR(); | |
4211 | } | |
4212 | ||
4213 | /**************************************************************************** | |
4214 | REMARKS: | |
4215 | Handles opcode 0xe9 | |
4216 | ****************************************************************************/ | |
4217 | void x86emuOp_jump_near_IMM(u8 X86EMU_UNUSED(op1)) | |
4218 | { | |
4219 | int ip; | |
4220 | ||
4221 | START_OF_INSTR(); | |
4222 | DECODE_PRINTF("JMP\t"); | |
4223 | ip = (s16)fetch_word_imm(); | |
4224 | ip += (s16)M.x86.R_IP; | |
4225 | DECODE_PRINTF2("%04x\n", ip); | |
4226 | TRACE_AND_STEP(); | |
4227 | M.x86.R_IP = (u16)ip; | |
4228 | DECODE_CLEAR_SEGOVR(); | |
4229 | END_OF_INSTR(); | |
4230 | } | |
4231 | ||
4232 | /**************************************************************************** | |
4233 | REMARKS: | |
4234 | Handles opcode 0xea | |
4235 | ****************************************************************************/ | |
4236 | void x86emuOp_jump_far_IMM(u8 X86EMU_UNUSED(op1)) | |
4237 | { | |
4238 | u16 cs, ip; | |
4239 | ||
4240 | START_OF_INSTR(); | |
4241 | DECODE_PRINTF("JMP\tFAR "); | |
4242 | ip = fetch_word_imm(); | |
4243 | cs = fetch_word_imm(); | |
4244 | DECODE_PRINTF2("%04x:", cs); | |
4245 | DECODE_PRINTF2("%04x\n", ip); | |
4246 | TRACE_AND_STEP(); | |
4247 | M.x86.R_IP = ip; | |
4248 | M.x86.R_CS = cs; | |
4249 | DECODE_CLEAR_SEGOVR(); | |
4250 | END_OF_INSTR(); | |
4251 | } | |
4252 | ||
4253 | /**************************************************************************** | |
4254 | REMARKS: | |
4255 | Handles opcode 0xeb | |
4256 | ****************************************************************************/ | |
4257 | void x86emuOp_jump_byte_IMM(u8 X86EMU_UNUSED(op1)) | |
4258 | { | |
4259 | u16 target; | |
4260 | s8 offset; | |
4261 | ||
4262 | START_OF_INSTR(); | |
4263 | DECODE_PRINTF("JMP\t"); | |
4264 | offset = (s8)fetch_byte_imm(); | |
4265 | target = (u16)(M.x86.R_IP + offset); | |
4266 | DECODE_PRINTF2("%x\n", target); | |
4267 | TRACE_AND_STEP(); | |
4268 | M.x86.R_IP = target; | |
4269 | DECODE_CLEAR_SEGOVR(); | |
4270 | END_OF_INSTR(); | |
4271 | } | |
4272 | ||
4273 | /**************************************************************************** | |
4274 | REMARKS: | |
4275 | Handles opcode 0xec | |
4276 | ****************************************************************************/ | |
4277 | void x86emuOp_in_byte_AL_DX(u8 X86EMU_UNUSED(op1)) | |
4278 | { | |
4279 | START_OF_INSTR(); | |
4280 | DECODE_PRINTF("IN\tAL,DX\n"); | |
4281 | TRACE_AND_STEP(); | |
4282 | M.x86.R_AL = (*sys_inb)(M.x86.R_DX); | |
4283 | DECODE_CLEAR_SEGOVR(); | |
4284 | END_OF_INSTR(); | |
4285 | } | |
4286 | ||
4287 | /**************************************************************************** | |
4288 | REMARKS: | |
4289 | Handles opcode 0xed | |
4290 | ****************************************************************************/ | |
4291 | void x86emuOp_in_word_AX_DX(u8 X86EMU_UNUSED(op1)) | |
4292 | { | |
4293 | START_OF_INSTR(); | |
4294 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 | 4295 | DECODE_PRINTF("IN\tEAX,DX\n"); |
ece92f85 | 4296 | } else { |
9c7e4b06 | 4297 | DECODE_PRINTF("IN\tAX,DX\n"); |
ece92f85 JJ |
4298 | } |
4299 | TRACE_AND_STEP(); | |
4300 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 | 4301 | M.x86.R_EAX = (*sys_inl)(M.x86.R_DX); |
ece92f85 | 4302 | } else { |
9c7e4b06 | 4303 | M.x86.R_AX = (*sys_inw)(M.x86.R_DX); |
ece92f85 JJ |
4304 | } |
4305 | DECODE_CLEAR_SEGOVR(); | |
4306 | END_OF_INSTR(); | |
4307 | } | |
4308 | ||
4309 | /**************************************************************************** | |
4310 | REMARKS: | |
4311 | Handles opcode 0xee | |
4312 | ****************************************************************************/ | |
4313 | void x86emuOp_out_byte_DX_AL(u8 X86EMU_UNUSED(op1)) | |
4314 | { | |
4315 | START_OF_INSTR(); | |
4316 | DECODE_PRINTF("OUT\tDX,AL\n"); | |
4317 | TRACE_AND_STEP(); | |
4318 | (*sys_outb)(M.x86.R_DX, M.x86.R_AL); | |
4319 | DECODE_CLEAR_SEGOVR(); | |
4320 | END_OF_INSTR(); | |
4321 | } | |
4322 | ||
4323 | /**************************************************************************** | |
4324 | REMARKS: | |
4325 | Handles opcode 0xef | |
4326 | ****************************************************************************/ | |
4327 | void x86emuOp_out_word_DX_AX(u8 X86EMU_UNUSED(op1)) | |
4328 | { | |
4329 | START_OF_INSTR(); | |
4330 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 | 4331 | DECODE_PRINTF("OUT\tDX,EAX\n"); |
ece92f85 | 4332 | } else { |
9c7e4b06 | 4333 | DECODE_PRINTF("OUT\tDX,AX\n"); |
ece92f85 JJ |
4334 | } |
4335 | TRACE_AND_STEP(); | |
4336 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
9c7e4b06 | 4337 | (*sys_outl)(M.x86.R_DX, M.x86.R_EAX); |
ece92f85 | 4338 | } else { |
9c7e4b06 | 4339 | (*sys_outw)(M.x86.R_DX, M.x86.R_AX); |
ece92f85 JJ |
4340 | } |
4341 | DECODE_CLEAR_SEGOVR(); | |
4342 | END_OF_INSTR(); | |
4343 | } | |
4344 | ||
4345 | /**************************************************************************** | |
4346 | REMARKS: | |
4347 | Handles opcode 0xf0 | |
4348 | ****************************************************************************/ | |
4349 | void x86emuOp_lock(u8 X86EMU_UNUSED(op1)) | |
4350 | { | |
4351 | START_OF_INSTR(); | |
4352 | DECODE_PRINTF("LOCK:\n"); | |
4353 | TRACE_AND_STEP(); | |
4354 | DECODE_CLEAR_SEGOVR(); | |
4355 | END_OF_INSTR(); | |
4356 | } | |
4357 | ||
4358 | /*opcode 0xf1 ILLEGAL OPERATION */ | |
4359 | ||
4360 | /**************************************************************************** | |
4361 | REMARKS: | |
4362 | Handles opcode 0xf2 | |
4363 | ****************************************************************************/ | |
4364 | void x86emuOp_repne(u8 X86EMU_UNUSED(op1)) | |
4365 | { | |
4366 | START_OF_INSTR(); | |
4367 | DECODE_PRINTF("REPNE\n"); | |
4368 | TRACE_AND_STEP(); | |
4369 | M.x86.mode |= SYSMODE_PREFIX_REPNE; | |
4370 | DECODE_CLEAR_SEGOVR(); | |
4371 | END_OF_INSTR(); | |
4372 | } | |
4373 | ||
4374 | /**************************************************************************** | |
4375 | REMARKS: | |
4376 | Handles opcode 0xf3 | |
4377 | ****************************************************************************/ | |
4378 | void x86emuOp_repe(u8 X86EMU_UNUSED(op1)) | |
4379 | { | |
4380 | START_OF_INSTR(); | |
4381 | DECODE_PRINTF("REPE\n"); | |
4382 | TRACE_AND_STEP(); | |
4383 | M.x86.mode |= SYSMODE_PREFIX_REPE; | |
4384 | DECODE_CLEAR_SEGOVR(); | |
4385 | END_OF_INSTR(); | |
4386 | } | |
4387 | ||
4388 | /**************************************************************************** | |
4389 | REMARKS: | |
4390 | Handles opcode 0xf4 | |
4391 | ****************************************************************************/ | |
4392 | void x86emuOp_halt(u8 X86EMU_UNUSED(op1)) | |
4393 | { | |
4394 | START_OF_INSTR(); | |
4395 | DECODE_PRINTF("HALT\n"); | |
4396 | TRACE_AND_STEP(); | |
4397 | HALT_SYS(); | |
4398 | DECODE_CLEAR_SEGOVR(); | |
4399 | END_OF_INSTR(); | |
4400 | } | |
4401 | ||
4402 | /**************************************************************************** | |
4403 | REMARKS: | |
4404 | Handles opcode 0xf5 | |
4405 | ****************************************************************************/ | |
4406 | void x86emuOp_cmc(u8 X86EMU_UNUSED(op1)) | |
4407 | { | |
4408 | /* complement the carry flag. */ | |
4409 | START_OF_INSTR(); | |
4410 | DECODE_PRINTF("CMC\n"); | |
4411 | TRACE_AND_STEP(); | |
4412 | TOGGLE_FLAG(F_CF); | |
4413 | DECODE_CLEAR_SEGOVR(); | |
4414 | END_OF_INSTR(); | |
4415 | } | |
4416 | ||
4417 | /**************************************************************************** | |
4418 | REMARKS: | |
4419 | Handles opcode 0xf6 | |
4420 | ****************************************************************************/ | |
4421 | void x86emuOp_opcF6_byte_RM(u8 X86EMU_UNUSED(op1)) | |
4422 | { | |
4423 | int mod, rl, rh; | |
4424 | u8 *destreg; | |
4425 | uint destoffset; | |
4426 | u8 destval, srcval; | |
4427 | ||
4428 | /* long, drawn out code follows. Double switch for a total | |
4429 | of 32 cases. */ | |
4430 | START_OF_INSTR(); | |
4431 | FETCH_DECODE_MODRM(mod, rh, rl); | |
4432 | DECODE_PRINTF(opF6_names[rh]); | |
4433 | if (mod < 3) { | |
9c7e4b06 WD |
4434 | DECODE_PRINTF("BYTE PTR "); |
4435 | destoffset = decode_rmXX_address(mod, rl); | |
4436 | destval = fetch_data_byte(destoffset); | |
4437 | ||
4438 | switch (rh) { | |
4439 | case 0: /* test byte imm */ | |
4440 | DECODE_PRINTF(","); | |
4441 | srcval = fetch_byte_imm(); | |
4442 | DECODE_PRINTF2("%02x\n", srcval); | |
4443 | TRACE_AND_STEP(); | |
4444 | test_byte(destval, srcval); | |
4445 | break; | |
4446 | case 1: | |
8c6ec412 | 4447 | ERR_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n"); |
9c7e4b06 WD |
4448 | HALT_SYS(); |
4449 | break; | |
4450 | case 2: | |
4451 | DECODE_PRINTF("\n"); | |
4452 | TRACE_AND_STEP(); | |
4453 | destval = not_byte(destval); | |
4454 | store_data_byte(destoffset, destval); | |
4455 | break; | |
4456 | case 3: | |
4457 | DECODE_PRINTF("\n"); | |
4458 | TRACE_AND_STEP(); | |
4459 | destval = neg_byte(destval); | |
4460 | store_data_byte(destoffset, destval); | |
4461 | break; | |
4462 | case 4: | |
4463 | DECODE_PRINTF("\n"); | |
4464 | TRACE_AND_STEP(); | |
4465 | mul_byte(destval); | |
4466 | break; | |
4467 | case 5: | |
4468 | DECODE_PRINTF("\n"); | |
4469 | TRACE_AND_STEP(); | |
4470 | imul_byte(destval); | |
4471 | break; | |
4472 | case 6: | |
4473 | DECODE_PRINTF("\n"); | |
4474 | TRACE_AND_STEP(); | |
4475 | div_byte(destval); | |
4476 | break; | |
4477 | default: | |
4478 | DECODE_PRINTF("\n"); | |
4479 | TRACE_AND_STEP(); | |
4480 | idiv_byte(destval); | |
4481 | break; | |
4482 | } | |
4483 | } else { /* mod=11 */ | |
4484 | destreg = DECODE_RM_BYTE_REGISTER(rl); | |
4485 | switch (rh) { | |
4486 | case 0: /* test byte imm */ | |
4487 | DECODE_PRINTF(","); | |
4488 | srcval = fetch_byte_imm(); | |
4489 | DECODE_PRINTF2("%02x\n", srcval); | |
4490 | TRACE_AND_STEP(); | |
4491 | test_byte(*destreg, srcval); | |
4492 | break; | |
4493 | case 1: | |
8c6ec412 | 4494 | ERR_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n"); |
9c7e4b06 WD |
4495 | HALT_SYS(); |
4496 | break; | |
4497 | case 2: | |
4498 | DECODE_PRINTF("\n"); | |
4499 | TRACE_AND_STEP(); | |
4500 | *destreg = not_byte(*destreg); | |
4501 | break; | |
4502 | case 3: | |
4503 | DECODE_PRINTF("\n"); | |
4504 | TRACE_AND_STEP(); | |
4505 | *destreg = neg_byte(*destreg); | |
4506 | break; | |
4507 | case 4: | |
4508 | DECODE_PRINTF("\n"); | |
4509 | TRACE_AND_STEP(); | |
4510 | mul_byte(*destreg); /*!!! */ | |
4511 | break; | |
4512 | case 5: | |
4513 | DECODE_PRINTF("\n"); | |
4514 | TRACE_AND_STEP(); | |
4515 | imul_byte(*destreg); | |
4516 | break; | |
4517 | case 6: | |
4518 | DECODE_PRINTF("\n"); | |
4519 | TRACE_AND_STEP(); | |
4520 | div_byte(*destreg); | |
4521 | break; | |
4522 | default: | |
4523 | DECODE_PRINTF("\n"); | |
4524 | TRACE_AND_STEP(); | |
4525 | idiv_byte(*destreg); | |
4526 | break; | |
4527 | } | |
ece92f85 JJ |
4528 | } |
4529 | DECODE_CLEAR_SEGOVR(); | |
4530 | END_OF_INSTR(); | |
4531 | } | |
4532 | ||
4533 | /**************************************************************************** | |
4534 | REMARKS: | |
4535 | Handles opcode 0xf7 | |
4536 | ****************************************************************************/ | |
4537 | void x86emuOp_opcF7_word_RM(u8 X86EMU_UNUSED(op1)) | |
4538 | { | |
4539 | int mod, rl, rh; | |
4540 | uint destoffset; | |
4541 | ||
4542 | START_OF_INSTR(); | |
4543 | FETCH_DECODE_MODRM(mod, rh, rl); | |
4544 | DECODE_PRINTF(opF6_names[rh]); | |
4545 | if (mod < 3) { | |
4546 | ||
9c7e4b06 WD |
4547 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { |
4548 | u32 destval, srcval; | |
4549 | ||
4550 | DECODE_PRINTF("DWORD PTR "); | |
4551 | destoffset = decode_rmXX_address(mod, rl); | |
4552 | destval = fetch_data_long(destoffset); | |
4553 | ||
4554 | switch (rh) { | |
4555 | case 0: | |
4556 | DECODE_PRINTF(","); | |
4557 | srcval = fetch_long_imm(); | |
4558 | DECODE_PRINTF2("%x\n", srcval); | |
4559 | TRACE_AND_STEP(); | |
4560 | test_long(destval, srcval); | |
4561 | break; | |
4562 | case 1: | |
8c6ec412 | 4563 | ERR_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n"); |
9c7e4b06 WD |
4564 | HALT_SYS(); |
4565 | break; | |
4566 | case 2: | |
4567 | DECODE_PRINTF("\n"); | |
4568 | TRACE_AND_STEP(); | |
4569 | destval = not_long(destval); | |
4570 | store_data_long(destoffset, destval); | |
4571 | break; | |
4572 | case 3: | |
4573 | DECODE_PRINTF("\n"); | |
4574 | TRACE_AND_STEP(); | |
4575 | destval = neg_long(destval); | |
4576 | store_data_long(destoffset, destval); | |
4577 | break; | |
4578 | case 4: | |
4579 | DECODE_PRINTF("\n"); | |
4580 | TRACE_AND_STEP(); | |
4581 | mul_long(destval); | |
4582 | break; | |
4583 | case 5: | |
4584 | DECODE_PRINTF("\n"); | |
4585 | TRACE_AND_STEP(); | |
4586 | imul_long(destval); | |
4587 | break; | |
4588 | case 6: | |
4589 | DECODE_PRINTF("\n"); | |
4590 | TRACE_AND_STEP(); | |
4591 | div_long(destval); | |
4592 | break; | |
4593 | case 7: | |
4594 | DECODE_PRINTF("\n"); | |
4595 | TRACE_AND_STEP(); | |
4596 | idiv_long(destval); | |
4597 | break; | |
4598 | } | |
4599 | } else { | |
4600 | u16 destval, srcval; | |
4601 | ||
4602 | DECODE_PRINTF("WORD PTR "); | |
4603 | destoffset = decode_rmXX_address(mod, rl); | |
4604 | destval = fetch_data_word(destoffset); | |
4605 | ||
4606 | switch (rh) { | |
4607 | case 0: /* test word imm */ | |
4608 | DECODE_PRINTF(","); | |
4609 | srcval = fetch_word_imm(); | |
4610 | DECODE_PRINTF2("%x\n", srcval); | |
4611 | TRACE_AND_STEP(); | |
4612 | test_word(destval, srcval); | |
4613 | break; | |
4614 | case 1: | |
8c6ec412 | 4615 | ERR_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n"); |
9c7e4b06 WD |
4616 | HALT_SYS(); |
4617 | break; | |
4618 | case 2: | |
4619 | DECODE_PRINTF("\n"); | |
4620 | TRACE_AND_STEP(); | |
4621 | destval = not_word(destval); | |
4622 | store_data_word(destoffset, destval); | |
4623 | break; | |
4624 | case 3: | |
4625 | DECODE_PRINTF("\n"); | |
4626 | TRACE_AND_STEP(); | |
4627 | destval = neg_word(destval); | |
4628 | store_data_word(destoffset, destval); | |
4629 | break; | |
4630 | case 4: | |
4631 | DECODE_PRINTF("\n"); | |
4632 | TRACE_AND_STEP(); | |
4633 | mul_word(destval); | |
4634 | break; | |
4635 | case 5: | |
4636 | DECODE_PRINTF("\n"); | |
4637 | TRACE_AND_STEP(); | |
4638 | imul_word(destval); | |
4639 | break; | |
4640 | case 6: | |
4641 | DECODE_PRINTF("\n"); | |
4642 | TRACE_AND_STEP(); | |
4643 | div_word(destval); | |
4644 | break; | |
4645 | case 7: | |
4646 | DECODE_PRINTF("\n"); | |
4647 | TRACE_AND_STEP(); | |
4648 | idiv_word(destval); | |
4649 | break; | |
4650 | } | |
4651 | } | |
4652 | ||
4653 | } else { /* mod=11 */ | |
4654 | ||
4655 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
4656 | u32 *destreg; | |
4657 | u32 srcval; | |
4658 | ||
4659 | destreg = DECODE_RM_LONG_REGISTER(rl); | |
4660 | ||
4661 | switch (rh) { | |
4662 | case 0: /* test word imm */ | |
4663 | DECODE_PRINTF(","); | |
4664 | srcval = fetch_long_imm(); | |
4665 | DECODE_PRINTF2("%x\n", srcval); | |
4666 | TRACE_AND_STEP(); | |
4667 | test_long(*destreg, srcval); | |
4668 | break; | |
4669 | case 1: | |
8c6ec412 | 4670 | ERR_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n"); |
9c7e4b06 WD |
4671 | HALT_SYS(); |
4672 | break; | |
4673 | case 2: | |
4674 | DECODE_PRINTF("\n"); | |
4675 | TRACE_AND_STEP(); | |
4676 | *destreg = not_long(*destreg); | |
4677 | break; | |
4678 | case 3: | |
4679 | DECODE_PRINTF("\n"); | |
4680 | TRACE_AND_STEP(); | |
4681 | *destreg = neg_long(*destreg); | |
4682 | break; | |
4683 | case 4: | |
4684 | DECODE_PRINTF("\n"); | |
4685 | TRACE_AND_STEP(); | |
4686 | mul_long(*destreg); /*!!! */ | |
4687 | break; | |
4688 | case 5: | |
4689 | DECODE_PRINTF("\n"); | |
4690 | TRACE_AND_STEP(); | |
4691 | imul_long(*destreg); | |
4692 | break; | |
4693 | case 6: | |
4694 | DECODE_PRINTF("\n"); | |
4695 | TRACE_AND_STEP(); | |
4696 | div_long(*destreg); | |
4697 | break; | |
4698 | case 7: | |
4699 | DECODE_PRINTF("\n"); | |
4700 | TRACE_AND_STEP(); | |
4701 | idiv_long(*destreg); | |
4702 | break; | |
4703 | } | |
4704 | } else { | |
4705 | u16 *destreg; | |
4706 | u16 srcval; | |
4707 | ||
4708 | destreg = DECODE_RM_WORD_REGISTER(rl); | |
4709 | ||
4710 | switch (rh) { | |
4711 | case 0: /* test word imm */ | |
4712 | DECODE_PRINTF(","); | |
4713 | srcval = fetch_word_imm(); | |
4714 | DECODE_PRINTF2("%x\n", srcval); | |
4715 | TRACE_AND_STEP(); | |
4716 | test_word(*destreg, srcval); | |
4717 | break; | |
4718 | case 1: | |
8c6ec412 | 4719 | ERR_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n"); |
9c7e4b06 WD |
4720 | HALT_SYS(); |
4721 | break; | |
4722 | case 2: | |
4723 | DECODE_PRINTF("\n"); | |
4724 | TRACE_AND_STEP(); | |
4725 | *destreg = not_word(*destreg); | |
4726 | break; | |
4727 | case 3: | |
4728 | DECODE_PRINTF("\n"); | |
4729 | TRACE_AND_STEP(); | |
4730 | *destreg = neg_word(*destreg); | |
4731 | break; | |
4732 | case 4: | |
4733 | DECODE_PRINTF("\n"); | |
4734 | TRACE_AND_STEP(); | |
4735 | mul_word(*destreg); /*!!! */ | |
4736 | break; | |
4737 | case 5: | |
4738 | DECODE_PRINTF("\n"); | |
4739 | TRACE_AND_STEP(); | |
4740 | imul_word(*destreg); | |
4741 | break; | |
4742 | case 6: | |
4743 | DECODE_PRINTF("\n"); | |
4744 | TRACE_AND_STEP(); | |
4745 | div_word(*destreg); | |
4746 | break; | |
4747 | case 7: | |
4748 | DECODE_PRINTF("\n"); | |
4749 | TRACE_AND_STEP(); | |
4750 | idiv_word(*destreg); | |
4751 | break; | |
4752 | } | |
4753 | } | |
ece92f85 JJ |
4754 | } |
4755 | DECODE_CLEAR_SEGOVR(); | |
4756 | END_OF_INSTR(); | |
4757 | } | |
4758 | ||
4759 | /**************************************************************************** | |
4760 | REMARKS: | |
4761 | Handles opcode 0xf8 | |
4762 | ****************************************************************************/ | |
4763 | void x86emuOp_clc(u8 X86EMU_UNUSED(op1)) | |
4764 | { | |
4765 | /* clear the carry flag. */ | |
4766 | START_OF_INSTR(); | |
4767 | DECODE_PRINTF("CLC\n"); | |
4768 | TRACE_AND_STEP(); | |
4769 | CLEAR_FLAG(F_CF); | |
4770 | DECODE_CLEAR_SEGOVR(); | |
4771 | END_OF_INSTR(); | |
4772 | } | |
4773 | ||
4774 | /**************************************************************************** | |
4775 | REMARKS: | |
4776 | Handles opcode 0xf9 | |
4777 | ****************************************************************************/ | |
4778 | void x86emuOp_stc(u8 X86EMU_UNUSED(op1)) | |
4779 | { | |
4780 | /* set the carry flag. */ | |
4781 | START_OF_INSTR(); | |
4782 | DECODE_PRINTF("STC\n"); | |
4783 | TRACE_AND_STEP(); | |
4784 | SET_FLAG(F_CF); | |
4785 | DECODE_CLEAR_SEGOVR(); | |
4786 | END_OF_INSTR(); | |
4787 | } | |
4788 | ||
4789 | /**************************************************************************** | |
4790 | REMARKS: | |
4791 | Handles opcode 0xfa | |
4792 | ****************************************************************************/ | |
4793 | void x86emuOp_cli(u8 X86EMU_UNUSED(op1)) | |
4794 | { | |
4795 | /* clear interrupts. */ | |
4796 | START_OF_INSTR(); | |
4797 | DECODE_PRINTF("CLI\n"); | |
4798 | TRACE_AND_STEP(); | |
4799 | CLEAR_FLAG(F_IF); | |
4800 | DECODE_CLEAR_SEGOVR(); | |
4801 | END_OF_INSTR(); | |
4802 | } | |
4803 | ||
4804 | /**************************************************************************** | |
4805 | REMARKS: | |
4806 | Handles opcode 0xfb | |
4807 | ****************************************************************************/ | |
4808 | void x86emuOp_sti(u8 X86EMU_UNUSED(op1)) | |
4809 | { | |
4810 | /* enable interrupts. */ | |
4811 | START_OF_INSTR(); | |
4812 | DECODE_PRINTF("STI\n"); | |
4813 | TRACE_AND_STEP(); | |
4814 | SET_FLAG(F_IF); | |
4815 | DECODE_CLEAR_SEGOVR(); | |
4816 | END_OF_INSTR(); | |
4817 | } | |
4818 | ||
4819 | /**************************************************************************** | |
4820 | REMARKS: | |
4821 | Handles opcode 0xfc | |
4822 | ****************************************************************************/ | |
4823 | void x86emuOp_cld(u8 X86EMU_UNUSED(op1)) | |
4824 | { | |
4825 | /* clear interrupts. */ | |
4826 | START_OF_INSTR(); | |
4827 | DECODE_PRINTF("CLD\n"); | |
4828 | TRACE_AND_STEP(); | |
4829 | CLEAR_FLAG(F_DF); | |
4830 | DECODE_CLEAR_SEGOVR(); | |
4831 | END_OF_INSTR(); | |
4832 | } | |
4833 | ||
4834 | /**************************************************************************** | |
4835 | REMARKS: | |
4836 | Handles opcode 0xfd | |
4837 | ****************************************************************************/ | |
4838 | void x86emuOp_std(u8 X86EMU_UNUSED(op1)) | |
4839 | { | |
4840 | /* clear interrupts. */ | |
4841 | START_OF_INSTR(); | |
4842 | DECODE_PRINTF("STD\n"); | |
4843 | TRACE_AND_STEP(); | |
4844 | SET_FLAG(F_DF); | |
4845 | DECODE_CLEAR_SEGOVR(); | |
4846 | END_OF_INSTR(); | |
4847 | } | |
4848 | ||
4849 | /**************************************************************************** | |
4850 | REMARKS: | |
4851 | Handles opcode 0xfe | |
4852 | ****************************************************************************/ | |
4853 | void x86emuOp_opcFE_byte_RM(u8 X86EMU_UNUSED(op1)) | |
4854 | { | |
4855 | int mod, rh, rl; | |
4856 | u8 destval; | |
4857 | uint destoffset; | |
4858 | u8 *destreg; | |
4859 | ||
4860 | /* Yet another special case instruction. */ | |
4861 | START_OF_INSTR(); | |
4862 | FETCH_DECODE_MODRM(mod, rh, rl); | |
b3521f2e | 4863 | #ifdef CONFIG_X86EMU_DEBUG |
ece92f85 | 4864 | if (DEBUG_DECODE()) { |
9c7e4b06 WD |
4865 | /* XXX DECODE_PRINTF may be changed to something more |
4866 | general, so that it is important to leave the strings | |
4867 | in the same format, even though the result is that the | |
4868 | above test is done twice. */ | |
4869 | ||
4870 | switch (rh) { | |
4871 | case 0: | |
4872 | DECODE_PRINTF("INC\t"); | |
4873 | break; | |
4874 | case 1: | |
4875 | DECODE_PRINTF("DEC\t"); | |
4876 | break; | |
4877 | case 2: | |
4878 | case 3: | |
4879 | case 4: | |
4880 | case 5: | |
4881 | case 6: | |
4882 | case 7: | |
8c6ec412 | 4883 | ERR_PRINTF2("ILLEGAL OP MAJOR OP 0xFE MINOR OP %x\n", mod); |
9c7e4b06 WD |
4884 | HALT_SYS(); |
4885 | break; | |
4886 | } | |
ece92f85 JJ |
4887 | } |
4888 | #endif | |
4889 | if (mod < 3) { | |
9c7e4b06 WD |
4890 | DECODE_PRINTF("BYTE PTR "); |
4891 | destoffset = decode_rmXX_address(mod, rl); | |
4892 | DECODE_PRINTF("\n"); | |
4893 | destval = fetch_data_byte(destoffset); | |
4894 | TRACE_AND_STEP(); | |
4895 | if (rh == 0) | |
4896 | destval = inc_byte(destval); | |
4897 | else | |
4898 | destval = dec_byte(destval); | |
4899 | store_data_byte(destoffset, destval); | |
ece92f85 | 4900 | } else { |
9c7e4b06 WD |
4901 | destreg = DECODE_RM_BYTE_REGISTER(rl); |
4902 | DECODE_PRINTF("\n"); | |
4903 | TRACE_AND_STEP(); | |
4904 | if (rh == 0) | |
4905 | *destreg = inc_byte(*destreg); | |
4906 | else | |
4907 | *destreg = dec_byte(*destreg); | |
ece92f85 JJ |
4908 | } |
4909 | DECODE_CLEAR_SEGOVR(); | |
4910 | END_OF_INSTR(); | |
4911 | } | |
4912 | ||
4913 | /**************************************************************************** | |
4914 | REMARKS: | |
4915 | Handles opcode 0xff | |
4916 | ****************************************************************************/ | |
4917 | void x86emuOp_opcFF_word_RM(u8 X86EMU_UNUSED(op1)) | |
4918 | { | |
4919 | int mod, rh, rl; | |
4920 | uint destoffset = 0; | |
4921 | u16 *destreg; | |
4922 | u16 destval,destval2; | |
4923 | ||
4924 | /* Yet another special case instruction. */ | |
4925 | START_OF_INSTR(); | |
4926 | FETCH_DECODE_MODRM(mod, rh, rl); | |
b3521f2e | 4927 | #ifdef CONFIG_X86EMU_DEBUG |
ece92f85 | 4928 | if (DEBUG_DECODE()) { |
9c7e4b06 WD |
4929 | /* XXX DECODE_PRINTF may be changed to something more |
4930 | general, so that it is important to leave the strings | |
4931 | in the same format, even though the result is that the | |
4932 | above test is done twice. */ | |
4933 | ||
4934 | switch (rh) { | |
4935 | case 0: | |
4936 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
4937 | DECODE_PRINTF("INC\tDWORD PTR "); | |
4938 | } else { | |
4939 | DECODE_PRINTF("INC\tWORD PTR "); | |
4940 | } | |
4941 | break; | |
4942 | case 1: | |
4943 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
4944 | DECODE_PRINTF("DEC\tDWORD PTR "); | |
4945 | } else { | |
4946 | DECODE_PRINTF("DEC\tWORD PTR "); | |
4947 | } | |
4948 | break; | |
4949 | case 2: | |
4950 | DECODE_PRINTF("CALL\t "); | |
4951 | break; | |
4952 | case 3: | |
4953 | DECODE_PRINTF("CALL\tFAR "); | |
4954 | break; | |
4955 | case 4: | |
4956 | DECODE_PRINTF("JMP\t"); | |
4957 | break; | |
4958 | case 5: | |
4959 | DECODE_PRINTF("JMP\tFAR "); | |
4960 | break; | |
4961 | case 6: | |
4962 | DECODE_PRINTF("PUSH\t"); | |
4963 | break; | |
4964 | case 7: | |
8c6ec412 | 4965 | ERR_PRINTF("ILLEGAL DECODING OF OPCODE FF\t"); |
9c7e4b06 WD |
4966 | HALT_SYS(); |
4967 | break; | |
4968 | } | |
ece92f85 JJ |
4969 | } |
4970 | #endif | |
4971 | if (mod < 3) { | |
9c7e4b06 WD |
4972 | destoffset = decode_rmXX_address(mod, rl); |
4973 | DECODE_PRINTF("\n"); | |
4974 | switch (rh) { | |
4975 | case 0: /* inc word ptr ... */ | |
4976 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
4977 | u32 destval; | |
4978 | ||
4979 | destval = fetch_data_long(destoffset); | |
4980 | TRACE_AND_STEP(); | |
4981 | destval = inc_long(destval); | |
4982 | store_data_long(destoffset, destval); | |
4983 | } else { | |
4984 | u16 destval; | |
4985 | ||
4986 | destval = fetch_data_word(destoffset); | |
4987 | TRACE_AND_STEP(); | |
4988 | destval = inc_word(destval); | |
4989 | store_data_word(destoffset, destval); | |
4990 | } | |
4991 | break; | |
4992 | case 1: /* dec word ptr ... */ | |
4993 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
4994 | u32 destval; | |
4995 | ||
4996 | destval = fetch_data_long(destoffset); | |
4997 | TRACE_AND_STEP(); | |
4998 | destval = dec_long(destval); | |
4999 | store_data_long(destoffset, destval); | |
5000 | } else { | |
5001 | u16 destval; | |
5002 | ||
5003 | destval = fetch_data_word(destoffset); | |
5004 | TRACE_AND_STEP(); | |
5005 | destval = dec_word(destval); | |
5006 | store_data_word(destoffset, destval); | |
5007 | } | |
5008 | break; | |
5009 | case 2: /* call word ptr ... */ | |
5010 | destval = fetch_data_word(destoffset); | |
5011 | TRACE_AND_STEP(); | |
5012 | push_word(M.x86.R_IP); | |
5013 | M.x86.R_IP = destval; | |
5014 | break; | |
5015 | case 3: /* call far ptr ... */ | |
5016 | destval = fetch_data_word(destoffset); | |
5017 | destval2 = fetch_data_word(destoffset + 2); | |
5018 | TRACE_AND_STEP(); | |
5019 | push_word(M.x86.R_CS); | |
5020 | M.x86.R_CS = destval2; | |
5021 | push_word(M.x86.R_IP); | |
5022 | M.x86.R_IP = destval; | |
5023 | break; | |
5024 | case 4: /* jmp word ptr ... */ | |
5025 | destval = fetch_data_word(destoffset); | |
5026 | TRACE_AND_STEP(); | |
5027 | M.x86.R_IP = destval; | |
5028 | break; | |
5029 | case 5: /* jmp far ptr ... */ | |
5030 | destval = fetch_data_word(destoffset); | |
5031 | destval2 = fetch_data_word(destoffset + 2); | |
5032 | TRACE_AND_STEP(); | |
5033 | M.x86.R_IP = destval; | |
5034 | M.x86.R_CS = destval2; | |
5035 | break; | |
5036 | case 6: /* push word ptr ... */ | |
5037 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
5038 | u32 destval; | |
5039 | ||
5040 | destval = fetch_data_long(destoffset); | |
5041 | TRACE_AND_STEP(); | |
5042 | push_long(destval); | |
5043 | } else { | |
5044 | u16 destval; | |
5045 | ||
5046 | destval = fetch_data_word(destoffset); | |
5047 | TRACE_AND_STEP(); | |
5048 | push_word(destval); | |
5049 | } | |
5050 | break; | |
5051 | } | |
ece92f85 | 5052 | } else { |
9c7e4b06 WD |
5053 | switch (rh) { |
5054 | case 0: | |
5055 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
5056 | u32 *destreg; | |
5057 | ||
5058 | destreg = DECODE_RM_LONG_REGISTER(rl); | |
5059 | DECODE_PRINTF("\n"); | |
5060 | TRACE_AND_STEP(); | |
5061 | *destreg = inc_long(*destreg); | |
5062 | } else { | |
5063 | u16 *destreg; | |
5064 | ||
5065 | destreg = DECODE_RM_WORD_REGISTER(rl); | |
5066 | DECODE_PRINTF("\n"); | |
5067 | TRACE_AND_STEP(); | |
5068 | *destreg = inc_word(*destreg); | |
5069 | } | |
5070 | break; | |
5071 | case 1: | |
5072 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
5073 | u32 *destreg; | |
5074 | ||
5075 | destreg = DECODE_RM_LONG_REGISTER(rl); | |
5076 | DECODE_PRINTF("\n"); | |
5077 | TRACE_AND_STEP(); | |
5078 | *destreg = dec_long(*destreg); | |
5079 | } else { | |
5080 | u16 *destreg; | |
5081 | ||
5082 | destreg = DECODE_RM_WORD_REGISTER(rl); | |
5083 | DECODE_PRINTF("\n"); | |
5084 | TRACE_AND_STEP(); | |
5085 | *destreg = dec_word(*destreg); | |
5086 | } | |
5087 | break; | |
5088 | case 2: /* call word ptr ... */ | |
5089 | destreg = DECODE_RM_WORD_REGISTER(rl); | |
5090 | DECODE_PRINTF("\n"); | |
5091 | TRACE_AND_STEP(); | |
5092 | push_word(M.x86.R_IP); | |
5093 | M.x86.R_IP = *destreg; | |
5094 | break; | |
5095 | case 3: /* jmp far ptr ... */ | |
8c6ec412 | 5096 | ERR_PRINTF("OPERATION UNDEFINED 0XFF\n"); |
9c7e4b06 WD |
5097 | TRACE_AND_STEP(); |
5098 | HALT_SYS(); | |
5099 | break; | |
5100 | ||
5101 | case 4: /* jmp ... */ | |
5102 | destreg = DECODE_RM_WORD_REGISTER(rl); | |
5103 | DECODE_PRINTF("\n"); | |
5104 | TRACE_AND_STEP(); | |
5105 | M.x86.R_IP = (u16) (*destreg); | |
5106 | break; | |
5107 | case 5: /* jmp far ptr ... */ | |
8c6ec412 | 5108 | ERR_PRINTF("OPERATION UNDEFINED 0XFF\n"); |
9c7e4b06 WD |
5109 | TRACE_AND_STEP(); |
5110 | HALT_SYS(); | |
5111 | break; | |
5112 | case 6: | |
5113 | if (M.x86.mode & SYSMODE_PREFIX_DATA) { | |
5114 | u32 *destreg; | |
5115 | ||
5116 | destreg = DECODE_RM_LONG_REGISTER(rl); | |
5117 | DECODE_PRINTF("\n"); | |
5118 | TRACE_AND_STEP(); | |
5119 | push_long(*destreg); | |
5120 | } else { | |
5121 | u16 *destreg; | |
5122 | ||
5123 | destreg = DECODE_RM_WORD_REGISTER(rl); | |
5124 | DECODE_PRINTF("\n"); | |
5125 | TRACE_AND_STEP(); | |
5126 | push_word(*destreg); | |
5127 | } | |
5128 | break; | |
5129 | } | |
ece92f85 JJ |
5130 | } |
5131 | DECODE_CLEAR_SEGOVR(); | |
5132 | END_OF_INSTR(); | |
5133 | } | |
5134 | ||
5135 | /*************************************************************************** | |
5136 | * Single byte operation code table: | |
5137 | **************************************************************************/ | |
285870f7 | 5138 | void (*x86emu_optab[256])(u8) = |
ece92f85 JJ |
5139 | { |
5140 | /* 0x00 */ x86emuOp_genop_byte_RM_R, | |
5141 | /* 0x01 */ x86emuOp_genop_word_RM_R, | |
5142 | /* 0x02 */ x86emuOp_genop_byte_R_RM, | |
5143 | /* 0x03 */ x86emuOp_genop_word_R_RM, | |
5144 | /* 0x04 */ x86emuOp_genop_byte_AL_IMM, | |
5145 | /* 0x05 */ x86emuOp_genop_word_AX_IMM, | |
5146 | /* 0x06 */ x86emuOp_push_ES, | |
5147 | /* 0x07 */ x86emuOp_pop_ES, | |
5148 | ||
5149 | /* 0x08 */ x86emuOp_genop_byte_RM_R, | |
5150 | /* 0x09 */ x86emuOp_genop_word_RM_R, | |
5151 | /* 0x0a */ x86emuOp_genop_byte_R_RM, | |
5152 | /* 0x0b */ x86emuOp_genop_word_R_RM, | |
5153 | /* 0x0c */ x86emuOp_genop_byte_AL_IMM, | |
5154 | /* 0x0d */ x86emuOp_genop_word_AX_IMM, | |
5155 | /* 0x0e */ x86emuOp_push_CS, | |
5156 | /* 0x0f */ x86emuOp_two_byte, | |
5157 | ||
5158 | /* 0x10 */ x86emuOp_genop_byte_RM_R, | |
5159 | /* 0x11 */ x86emuOp_genop_word_RM_R, | |
5160 | /* 0x12 */ x86emuOp_genop_byte_R_RM, | |
5161 | /* 0x13 */ x86emuOp_genop_word_R_RM, | |
5162 | /* 0x14 */ x86emuOp_genop_byte_AL_IMM, | |
5163 | /* 0x15 */ x86emuOp_genop_word_AX_IMM, | |
5164 | /* 0x16 */ x86emuOp_push_SS, | |
5165 | /* 0x17 */ x86emuOp_pop_SS, | |
5166 | ||
5167 | /* 0x18 */ x86emuOp_genop_byte_RM_R, | |
5168 | /* 0x19 */ x86emuOp_genop_word_RM_R, | |
5169 | /* 0x1a */ x86emuOp_genop_byte_R_RM, | |
5170 | /* 0x1b */ x86emuOp_genop_word_R_RM, | |
5171 | /* 0x1c */ x86emuOp_genop_byte_AL_IMM, | |
5172 | /* 0x1d */ x86emuOp_genop_word_AX_IMM, | |
5173 | /* 0x1e */ x86emuOp_push_DS, | |
5174 | /* 0x1f */ x86emuOp_pop_DS, | |
5175 | ||
5176 | /* 0x20 */ x86emuOp_genop_byte_RM_R, | |
5177 | /* 0x21 */ x86emuOp_genop_word_RM_R, | |
5178 | /* 0x22 */ x86emuOp_genop_byte_R_RM, | |
5179 | /* 0x23 */ x86emuOp_genop_word_R_RM, | |
5180 | /* 0x24 */ x86emuOp_genop_byte_AL_IMM, | |
5181 | /* 0x25 */ x86emuOp_genop_word_AX_IMM, | |
5182 | /* 0x26 */ x86emuOp_segovr_ES, | |
5183 | /* 0x27 */ x86emuOp_daa, | |
5184 | ||
5185 | /* 0x28 */ x86emuOp_genop_byte_RM_R, | |
5186 | /* 0x29 */ x86emuOp_genop_word_RM_R, | |
5187 | /* 0x2a */ x86emuOp_genop_byte_R_RM, | |
5188 | /* 0x2b */ x86emuOp_genop_word_R_RM, | |
5189 | /* 0x2c */ x86emuOp_genop_byte_AL_IMM, | |
5190 | /* 0x2d */ x86emuOp_genop_word_AX_IMM, | |
5191 | /* 0x2e */ x86emuOp_segovr_CS, | |
5192 | /* 0x2f */ x86emuOp_das, | |
5193 | ||
5194 | /* 0x30 */ x86emuOp_genop_byte_RM_R, | |
5195 | /* 0x31 */ x86emuOp_genop_word_RM_R, | |
5196 | /* 0x32 */ x86emuOp_genop_byte_R_RM, | |
5197 | /* 0x33 */ x86emuOp_genop_word_R_RM, | |
5198 | /* 0x34 */ x86emuOp_genop_byte_AL_IMM, | |
5199 | /* 0x35 */ x86emuOp_genop_word_AX_IMM, | |
5200 | /* 0x36 */ x86emuOp_segovr_SS, | |
5201 | /* 0x37 */ x86emuOp_aaa, | |
5202 | ||
5203 | /* 0x38 */ x86emuOp_genop_byte_RM_R, | |
5204 | /* 0x39 */ x86emuOp_genop_word_RM_R, | |
5205 | /* 0x3a */ x86emuOp_genop_byte_R_RM, | |
5206 | /* 0x3b */ x86emuOp_genop_word_R_RM, | |
5207 | /* 0x3c */ x86emuOp_genop_byte_AL_IMM, | |
5208 | /* 0x3d */ x86emuOp_genop_word_AX_IMM, | |
5209 | /* 0x3e */ x86emuOp_segovr_DS, | |
5210 | /* 0x3f */ x86emuOp_aas, | |
5211 | ||
5212 | /* 0x40 */ x86emuOp_inc_register, | |
5213 | /* 0x41 */ x86emuOp_inc_register, | |
5214 | /* 0x42 */ x86emuOp_inc_register, | |
5215 | /* 0x43 */ x86emuOp_inc_register, | |
5216 | /* 0x44 */ x86emuOp_inc_register, | |
5217 | /* 0x45 */ x86emuOp_inc_register, | |
5218 | /* 0x46 */ x86emuOp_inc_register, | |
5219 | /* 0x47 */ x86emuOp_inc_register, | |
5220 | ||
5221 | /* 0x48 */ x86emuOp_dec_register, | |
5222 | /* 0x49 */ x86emuOp_dec_register, | |
5223 | /* 0x4a */ x86emuOp_dec_register, | |
5224 | /* 0x4b */ x86emuOp_dec_register, | |
5225 | /* 0x4c */ x86emuOp_dec_register, | |
5226 | /* 0x4d */ x86emuOp_dec_register, | |
5227 | /* 0x4e */ x86emuOp_dec_register, | |
5228 | /* 0x4f */ x86emuOp_dec_register, | |
5229 | ||
5230 | /* 0x50 */ x86emuOp_push_register, | |
5231 | /* 0x51 */ x86emuOp_push_register, | |
5232 | /* 0x52 */ x86emuOp_push_register, | |
5233 | /* 0x53 */ x86emuOp_push_register, | |
5234 | /* 0x54 */ x86emuOp_push_register, | |
5235 | /* 0x55 */ x86emuOp_push_register, | |
5236 | /* 0x56 */ x86emuOp_push_register, | |
5237 | /* 0x57 */ x86emuOp_push_register, | |
5238 | ||
5239 | /* 0x58 */ x86emuOp_pop_register, | |
5240 | /* 0x59 */ x86emuOp_pop_register, | |
5241 | /* 0x5a */ x86emuOp_pop_register, | |
5242 | /* 0x5b */ x86emuOp_pop_register, | |
5243 | /* 0x5c */ x86emuOp_pop_register, | |
5244 | /* 0x5d */ x86emuOp_pop_register, | |
5245 | /* 0x5e */ x86emuOp_pop_register, | |
5246 | /* 0x5f */ x86emuOp_pop_register, | |
5247 | ||
5248 | /* 0x60 */ x86emuOp_push_all, | |
5249 | /* 0x61 */ x86emuOp_pop_all, | |
5250 | /* 0x62 */ x86emuOp_illegal_op, /* bound */ | |
5251 | /* 0x63 */ x86emuOp_illegal_op, /* arpl */ | |
5252 | /* 0x64 */ x86emuOp_segovr_FS, | |
5253 | /* 0x65 */ x86emuOp_segovr_GS, | |
5254 | /* 0x66 */ x86emuOp_prefix_data, | |
5255 | /* 0x67 */ x86emuOp_prefix_addr, | |
5256 | ||
5257 | /* 0x68 */ x86emuOp_push_word_IMM, | |
5258 | /* 0x69 */ x86emuOp_imul_word_IMM, | |
5259 | /* 0x6a */ x86emuOp_push_byte_IMM, | |
5260 | /* 0x6b */ x86emuOp_imul_byte_IMM, | |
5261 | /* 0x6c */ x86emuOp_ins_byte, | |
5262 | /* 0x6d */ x86emuOp_ins_word, | |
5263 | /* 0x6e */ x86emuOp_outs_byte, | |
5264 | /* 0x6f */ x86emuOp_outs_word, | |
5265 | ||
5266 | /* 0x70 */ x86emuOp_jump_near_cond, | |
5267 | /* 0x71 */ x86emuOp_jump_near_cond, | |
5268 | /* 0x72 */ x86emuOp_jump_near_cond, | |
5269 | /* 0x73 */ x86emuOp_jump_near_cond, | |
5270 | /* 0x74 */ x86emuOp_jump_near_cond, | |
5271 | /* 0x75 */ x86emuOp_jump_near_cond, | |
5272 | /* 0x76 */ x86emuOp_jump_near_cond, | |
5273 | /* 0x77 */ x86emuOp_jump_near_cond, | |
5274 | ||
5275 | /* 0x78 */ x86emuOp_jump_near_cond, | |
5276 | /* 0x79 */ x86emuOp_jump_near_cond, | |
5277 | /* 0x7a */ x86emuOp_jump_near_cond, | |
5278 | /* 0x7b */ x86emuOp_jump_near_cond, | |
5279 | /* 0x7c */ x86emuOp_jump_near_cond, | |
5280 | /* 0x7d */ x86emuOp_jump_near_cond, | |
5281 | /* 0x7e */ x86emuOp_jump_near_cond, | |
5282 | /* 0x7f */ x86emuOp_jump_near_cond, | |
5283 | ||
5284 | /* 0x80 */ x86emuOp_opc80_byte_RM_IMM, | |
5285 | /* 0x81 */ x86emuOp_opc81_word_RM_IMM, | |
5286 | /* 0x82 */ x86emuOp_opc82_byte_RM_IMM, | |
5287 | /* 0x83 */ x86emuOp_opc83_word_RM_IMM, | |
5288 | /* 0x84 */ x86emuOp_test_byte_RM_R, | |
5289 | /* 0x85 */ x86emuOp_test_word_RM_R, | |
5290 | /* 0x86 */ x86emuOp_xchg_byte_RM_R, | |
5291 | /* 0x87 */ x86emuOp_xchg_word_RM_R, | |
5292 | ||
5293 | /* 0x88 */ x86emuOp_mov_byte_RM_R, | |
5294 | /* 0x89 */ x86emuOp_mov_word_RM_R, | |
5295 | /* 0x8a */ x86emuOp_mov_byte_R_RM, | |
5296 | /* 0x8b */ x86emuOp_mov_word_R_RM, | |
5297 | /* 0x8c */ x86emuOp_mov_word_RM_SR, | |
5298 | /* 0x8d */ x86emuOp_lea_word_R_M, | |
5299 | /* 0x8e */ x86emuOp_mov_word_SR_RM, | |
5300 | /* 0x8f */ x86emuOp_pop_RM, | |
5301 | ||
5302 | /* 0x90 */ x86emuOp_nop, | |
5303 | /* 0x91 */ x86emuOp_xchg_word_AX_register, | |
5304 | /* 0x92 */ x86emuOp_xchg_word_AX_register, | |
5305 | /* 0x93 */ x86emuOp_xchg_word_AX_register, | |
5306 | /* 0x94 */ x86emuOp_xchg_word_AX_register, | |
5307 | /* 0x95 */ x86emuOp_xchg_word_AX_register, | |
5308 | /* 0x96 */ x86emuOp_xchg_word_AX_register, | |
5309 | /* 0x97 */ x86emuOp_xchg_word_AX_register, | |
5310 | ||
5311 | /* 0x98 */ x86emuOp_cbw, | |
5312 | /* 0x99 */ x86emuOp_cwd, | |
5313 | /* 0x9a */ x86emuOp_call_far_IMM, | |
5314 | /* 0x9b */ x86emuOp_wait, | |
5315 | /* 0x9c */ x86emuOp_pushf_word, | |
5316 | /* 0x9d */ x86emuOp_popf_word, | |
5317 | /* 0x9e */ x86emuOp_sahf, | |
5318 | /* 0x9f */ x86emuOp_lahf, | |
5319 | ||
5320 | /* 0xa0 */ x86emuOp_mov_AL_M_IMM, | |
5321 | /* 0xa1 */ x86emuOp_mov_AX_M_IMM, | |
5322 | /* 0xa2 */ x86emuOp_mov_M_AL_IMM, | |
5323 | /* 0xa3 */ x86emuOp_mov_M_AX_IMM, | |
5324 | /* 0xa4 */ x86emuOp_movs_byte, | |
5325 | /* 0xa5 */ x86emuOp_movs_word, | |
5326 | /* 0xa6 */ x86emuOp_cmps_byte, | |
5327 | /* 0xa7 */ x86emuOp_cmps_word, | |
5328 | /* 0xa8 */ x86emuOp_test_AL_IMM, | |
5329 | /* 0xa9 */ x86emuOp_test_AX_IMM, | |
5330 | /* 0xaa */ x86emuOp_stos_byte, | |
5331 | /* 0xab */ x86emuOp_stos_word, | |
5332 | /* 0xac */ x86emuOp_lods_byte, | |
5333 | /* 0xad */ x86emuOp_lods_word, | |
5334 | /* 0xac */ x86emuOp_scas_byte, | |
5335 | /* 0xad */ x86emuOp_scas_word, | |
5336 | ||
5337 | /* 0xb0 */ x86emuOp_mov_byte_register_IMM, | |
5338 | /* 0xb1 */ x86emuOp_mov_byte_register_IMM, | |
5339 | /* 0xb2 */ x86emuOp_mov_byte_register_IMM, | |
5340 | /* 0xb3 */ x86emuOp_mov_byte_register_IMM, | |
5341 | /* 0xb4 */ x86emuOp_mov_byte_register_IMM, | |
5342 | /* 0xb5 */ x86emuOp_mov_byte_register_IMM, | |
5343 | /* 0xb6 */ x86emuOp_mov_byte_register_IMM, | |
5344 | /* 0xb7 */ x86emuOp_mov_byte_register_IMM, | |
5345 | ||
5346 | /* 0xb8 */ x86emuOp_mov_word_register_IMM, | |
5347 | /* 0xb9 */ x86emuOp_mov_word_register_IMM, | |
5348 | /* 0xba */ x86emuOp_mov_word_register_IMM, | |
5349 | /* 0xbb */ x86emuOp_mov_word_register_IMM, | |
5350 | /* 0xbc */ x86emuOp_mov_word_register_IMM, | |
5351 | /* 0xbd */ x86emuOp_mov_word_register_IMM, | |
5352 | /* 0xbe */ x86emuOp_mov_word_register_IMM, | |
5353 | /* 0xbf */ x86emuOp_mov_word_register_IMM, | |
5354 | ||
5355 | /* 0xc0 */ x86emuOp_opcC0_byte_RM_MEM, | |
5356 | /* 0xc1 */ x86emuOp_opcC1_word_RM_MEM, | |
5357 | /* 0xc2 */ x86emuOp_ret_near_IMM, | |
5358 | /* 0xc3 */ x86emuOp_ret_near, | |
5359 | /* 0xc4 */ x86emuOp_les_R_IMM, | |
5360 | /* 0xc5 */ x86emuOp_lds_R_IMM, | |
5361 | /* 0xc6 */ x86emuOp_mov_byte_RM_IMM, | |
5362 | /* 0xc7 */ x86emuOp_mov_word_RM_IMM, | |
5363 | /* 0xc8 */ x86emuOp_enter, | |
5364 | /* 0xc9 */ x86emuOp_leave, | |
5365 | /* 0xca */ x86emuOp_ret_far_IMM, | |
5366 | /* 0xcb */ x86emuOp_ret_far, | |
5367 | /* 0xcc */ x86emuOp_int3, | |
5368 | /* 0xcd */ x86emuOp_int_IMM, | |
5369 | /* 0xce */ x86emuOp_into, | |
5370 | /* 0xcf */ x86emuOp_iret, | |
5371 | ||
5372 | /* 0xd0 */ x86emuOp_opcD0_byte_RM_1, | |
5373 | /* 0xd1 */ x86emuOp_opcD1_word_RM_1, | |
5374 | /* 0xd2 */ x86emuOp_opcD2_byte_RM_CL, | |
5375 | /* 0xd3 */ x86emuOp_opcD3_word_RM_CL, | |
5376 | /* 0xd4 */ x86emuOp_aam, | |
5377 | /* 0xd5 */ x86emuOp_aad, | |
5378 | /* 0xd6 */ x86emuOp_illegal_op, /* Undocumented SETALC instruction */ | |
5379 | /* 0xd7 */ x86emuOp_xlat, | |
5380 | /* 0xd8 */ NULL, /*x86emuOp_esc_coprocess_d8,*/ | |
5381 | /* 0xd9 */ NULL, /*x86emuOp_esc_coprocess_d9,*/ | |
5382 | /* 0xda */ NULL, /*x86emuOp_esc_coprocess_da,*/ | |
5383 | /* 0xdb */ NULL, /*x86emuOp_esc_coprocess_db,*/ | |
5384 | /* 0xdc */ NULL, /*x86emuOp_esc_coprocess_dc,*/ | |
5385 | /* 0xdd */ NULL, /*x86emuOp_esc_coprocess_dd,*/ | |
5386 | /* 0xde */ NULL, /*x86emuOp_esc_coprocess_de,*/ | |
5387 | /* 0xdf */ NULL, /*x86emuOp_esc_coprocess_df,*/ | |
5388 | ||
5389 | /* 0xe0 */ x86emuOp_loopne, | |
5390 | /* 0xe1 */ x86emuOp_loope, | |
5391 | /* 0xe2 */ x86emuOp_loop, | |
5392 | /* 0xe3 */ x86emuOp_jcxz, | |
5393 | /* 0xe4 */ x86emuOp_in_byte_AL_IMM, | |
5394 | /* 0xe5 */ x86emuOp_in_word_AX_IMM, | |
5395 | /* 0xe6 */ x86emuOp_out_byte_IMM_AL, | |
5396 | /* 0xe7 */ x86emuOp_out_word_IMM_AX, | |
5397 | ||
5398 | /* 0xe8 */ x86emuOp_call_near_IMM, | |
5399 | /* 0xe9 */ x86emuOp_jump_near_IMM, | |
5400 | /* 0xea */ x86emuOp_jump_far_IMM, | |
5401 | /* 0xeb */ x86emuOp_jump_byte_IMM, | |
5402 | /* 0xec */ x86emuOp_in_byte_AL_DX, | |
5403 | /* 0xed */ x86emuOp_in_word_AX_DX, | |
5404 | /* 0xee */ x86emuOp_out_byte_DX_AL, | |
5405 | /* 0xef */ x86emuOp_out_word_DX_AX, | |
5406 | ||
5407 | /* 0xf0 */ x86emuOp_lock, | |
5408 | /* 0xf1 */ x86emuOp_illegal_op, | |
5409 | /* 0xf2 */ x86emuOp_repne, | |
5410 | /* 0xf3 */ x86emuOp_repe, | |
5411 | /* 0xf4 */ x86emuOp_halt, | |
5412 | /* 0xf5 */ x86emuOp_cmc, | |
5413 | /* 0xf6 */ x86emuOp_opcF6_byte_RM, | |
5414 | /* 0xf7 */ x86emuOp_opcF7_word_RM, | |
5415 | ||
5416 | /* 0xf8 */ x86emuOp_clc, | |
5417 | /* 0xf9 */ x86emuOp_stc, | |
5418 | /* 0xfa */ x86emuOp_cli, | |
5419 | /* 0xfb */ x86emuOp_sti, | |
5420 | /* 0xfc */ x86emuOp_cld, | |
5421 | /* 0xfd */ x86emuOp_std, | |
5422 | /* 0xfe */ x86emuOp_opcFE_byte_RM, | |
5423 | /* 0xff */ x86emuOp_opcFF_word_RM, | |
5424 | }; |