blob: 6089b1f53b167663b77ba9cda58784e8a3eb0303 [file] [log] [blame]
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001/****************************************************************************
2*
3* Realmode X86 Emulator Library
4*
5* Copyright (C) 1991-2004 SciTech Software, Inc.
6* Copyright (C) David Mosberger-Tang
7* Copyright (C) 1999 Egbert Eich
8*
9* ========================================================================
10*
11* Permission to use, copy, modify, distribute, and sell this software and
12* its documentation for any purpose is hereby granted without fee,
13* provided that the above copyright notice appear in all copies and that
14* both that copyright notice and this permission notice appear in
15* supporting documentation, and that the name of the authors not be used
16* in advertising or publicity pertaining to distribution of the software
17* without specific, written prior permission. The authors makes no
18* representations about the suitability of this software for any purpose.
19* It is provided "as is" without express or implied warranty.
20*
21* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
22* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
23* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
24* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
25* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
26* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
27* PERFORMANCE OF THIS SOFTWARE.
28*
29* ========================================================================
30*
31* Language: ANSI C
32* Environment: Any
33* Developer: Kendall Bennett
34*
35* Description: This file includes subroutines to implement the decoding
36* and emulation of all the x86 extended two-byte processor
37* instructions.
38*
39****************************************************************************/
40
41#include "x86emui.h"
42
43/*----------------------------- Implementation ----------------------------*/
44
45/****************************************************************************
46PARAMETERS:
47op1 - Instruction op code
48
49REMARKS:
50Handles illegal opcodes.
51****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +000052static void x86emuOp2_illegal_op(u8 op2)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000053{
54 START_OF_INSTR();
55 DECODE_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n");
56 TRACE_REGS();
Uwe Hermann01ce6012010-03-05 10:03:50 +000057 printf("%04x:%04x: %02X ILLEGAL EXTENDED X86 OPCODE!\n",
Stefan Reinauer7110d402009-11-03 14:59:43 +000058 M.x86.R_CS, M.x86.R_IP-2, op2);
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000059 HALT_SYS();
60 END_OF_INSTR();
61}
62
Stefan Reinauer7110d402009-11-03 14:59:43 +000063/****************************************************************************
64 * REMARKS:
65 * Handles opcode 0x0f,0x01
66 * ****************************************************************************/
67
68static void x86emuOp2_opc_01(u8 op2)
69{
70 int mod, rl, rh;
71 u16 *destreg;
72 uint destoffset;
73
74 START_OF_INSTR();
75 FETCH_DECODE_MODRM(mod, rh, rl);
76
77 switch(rh) {
78 case 4: // SMSW (Store Machine Status Word)
79 // Decode the mod byte to find the addressing
80 // Dummy implementation: Always returns 0x10 (initial value as per intel manual volume 3, figure 8-1)
81#define SMSW_INITIAL_VALUE 0x10
82 DECODE_PRINTF("SMSW\t");
83 switch (mod) {
84 case 0:
85 destoffset = decode_rm00_address(rl);
86 store_data_word(destoffset, SMSW_INITIAL_VALUE);
87 break;
88 case 1:
89 destoffset = decode_rm01_address(rl);
90 store_data_word(destoffset, SMSW_INITIAL_VALUE);
91 break;
92 case 2:
93 destoffset = decode_rm10_address(rl);
94 store_data_word(destoffset, SMSW_INITIAL_VALUE);
95 break;
96 case 3:
97 destreg = DECODE_RM_WORD_REGISTER(rl);
98 *destreg = SMSW_INITIAL_VALUE;
99 break;
100 }
101 TRACE_AND_STEP();
102 DECODE_CLEAR_SEGOVR();
103 DECODE_PRINTF("\n");
104 break;
105 default:
106 DECODE_PRINTF("ILLEGAL EXTENDED X86 OPCODE IN 0F 01\n");
107 TRACE_REGS();
Uwe Hermann01ce6012010-03-05 10:03:50 +0000108 printf("%04x:%04x: %02X ILLEGAL EXTENDED X86 OPCODE!\n",
Stefan Reinauer7110d402009-11-03 14:59:43 +0000109 M.x86.R_CS, M.x86.R_IP-2, op2);
110 HALT_SYS();
111 break;
112 }
113
114 END_OF_INSTR();
115}
116
117/****************************************************************************
118 * REMARKS:
119 * Handles opcode 0x0f,0x08
120 * ****************************************************************************/
121static void x86emuOp2_invd(u8 op2)
122{
123 START_OF_INSTR();
124 DECODE_PRINTF("INVD\n");
125 TRACE_AND_STEP();
126 DECODE_CLEAR_SEGOVR();
127 END_OF_INSTR();
128}
129
130/****************************************************************************
131 * REMARKS:
132 * Handles opcode 0x0f,0x09
133 * ****************************************************************************/
134static void x86emuOp2_wbinvd(u8 op2)
135{
136 START_OF_INSTR();
137 DECODE_PRINTF("WBINVD\n");
138 TRACE_AND_STEP();
139 DECODE_CLEAR_SEGOVR();
140 END_OF_INSTR();
141}
142
143/****************************************************************************
144 * REMARKS:
145 * Handles opcode 0x0f,0x30
146 * ****************************************************************************/
147static void x86emuOp2_wrmsr(u8 op2)
148{
149 /* dummy implementation, does nothing */
150
151 START_OF_INSTR();
152 DECODE_PRINTF("WRMSR\n");
153 TRACE_AND_STEP();
154 DECODE_CLEAR_SEGOVR();
155 END_OF_INSTR();
156}
157
158/****************************************************************************
Stefan Reinauer911f4462012-07-26 15:15:38 -0700159REMARKS:
160Handles opcode 0x0f,0x31
161****************************************************************************/
162static void x86emuOp2_rdtsc(u8 X86EMU_UNUSED(op2))
163{
164#ifdef __HAS_LONG_LONG__
165 static u64 counter = 0;
166#else
167 static u32 counter = 0;
168#endif
169
170 counter += 0x10000;
171
172 /* read timestamp counter */
173 /*
174 * Note that instead of actually trying to accurately measure this, we just
175 * increase the counter by a fixed amount every time we hit one of these
176 * instructions. Feel free to come up with a better method.
177 */
178 START_OF_INSTR();
179 DECODE_PRINTF("RDTSC\n");
180 TRACE_AND_STEP();
181#ifdef __HAS_LONG_LONG__
182 M.x86.R_EAX = counter & 0xffffffff;
183 M.x86.R_EDX = counter >> 32;
184#else
185 M.x86.R_EAX = counter;
186 M.x86.R_EDX = 0;
187#endif
188 DECODE_CLEAR_SEGOVR();
189 END_OF_INSTR();
190}
191
192/****************************************************************************
Stefan Reinauer7110d402009-11-03 14:59:43 +0000193 * REMARKS:
194 * Handles opcode 0x0f,0x32
195 * ****************************************************************************/
196static void x86emuOp2_rdmsr(u8 op2)
197{
198 /* dummy implementation, always return 0 */
199
200 START_OF_INSTR();
201 DECODE_PRINTF("RDMSR\n");
202 TRACE_AND_STEP();
203 M.x86.R_EDX = 0;
204 M.x86.R_EAX = 0;
205 DECODE_CLEAR_SEGOVR();
206 END_OF_INSTR();
Stefan Reinauer14e22772010-04-27 06:56:47 +0000207}
Stefan Reinauer7110d402009-11-03 14:59:43 +0000208
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000209#define xorl(a,b) (((a) && !(b)) || (!(a) && (b)))
210
211/****************************************************************************
212REMARKS:
213Handles opcode 0x0f,0x80-0x8F
214****************************************************************************/
215int x86emu_check_jump_condition(u8 op)
216{
217 switch (op) {
218 case 0x0:
219 DECODE_PRINTF("JO\t");
220 return ACCESS_FLAG(F_OF);
221 case 0x1:
222 DECODE_PRINTF("JNO\t");
223 return !ACCESS_FLAG(F_OF);
224 break;
225 case 0x2:
226 DECODE_PRINTF("JB\t");
227 return ACCESS_FLAG(F_CF);
228 break;
229 case 0x3:
230 DECODE_PRINTF("JNB\t");
231 return !ACCESS_FLAG(F_CF);
232 break;
233 case 0x4:
234 DECODE_PRINTF("JZ\t");
235 return ACCESS_FLAG(F_ZF);
236 break;
237 case 0x5:
238 DECODE_PRINTF("JNZ\t");
239 return !ACCESS_FLAG(F_ZF);
240 break;
241 case 0x6:
242 DECODE_PRINTF("JBE\t");
243 return ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF);
244 break;
245 case 0x7:
246 DECODE_PRINTF("JNBE\t");
247 return !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
248 break;
249 case 0x8:
250 DECODE_PRINTF("JS\t");
251 return ACCESS_FLAG(F_SF);
252 break;
253 case 0x9:
254 DECODE_PRINTF("JNS\t");
255 return !ACCESS_FLAG(F_SF);
256 break;
257 case 0xa:
258 DECODE_PRINTF("JP\t");
259 return ACCESS_FLAG(F_PF);
260 break;
261 case 0xb:
262 DECODE_PRINTF("JNP\t");
263 return !ACCESS_FLAG(F_PF);
264 break;
265 case 0xc:
266 DECODE_PRINTF("JL\t");
267 return xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
268 break;
269 case 0xd:
270 DECODE_PRINTF("JNL\t");
271 return !xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
272 break;
273 case 0xe:
274 DECODE_PRINTF("JLE\t");
275 return (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
276 ACCESS_FLAG(F_ZF));
277 break;
278 default:
279 DECODE_PRINTF("JNLE\t");
280 return !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
281 ACCESS_FLAG(F_ZF));
282 }
283}
284
Stefan Reinauer7110d402009-11-03 14:59:43 +0000285static void x86emuOp2_long_jump(u8 op2)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000286{
287 s32 target;
288 int cond;
289
290 /* conditional jump to word offset. */
291 START_OF_INSTR();
292 cond = x86emu_check_jump_condition(op2 & 0xF);
293 target = (s16) fetch_word_imm();
294 target += (s16) M.x86.R_IP;
295 DECODE_PRINTF2("%04x\n", target);
296 TRACE_AND_STEP();
297 if (cond) {
298 M.x86.R_IP = (u16)target;
299 JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, M.x86.R_IP, " LONG COND ");
300 }
301 DECODE_CLEAR_SEGOVR();
302 END_OF_INSTR();
303}
304
305/****************************************************************************
306REMARKS:
307Handles opcode 0x0f,0xC8-0xCF
308****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000309static s32 x86emu_bswap(s32 reg)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000310{
311 // perform the byte swap
312 s32 temp = reg;
Stefan Reinauer7110d402009-11-03 14:59:43 +0000313 reg = (temp & 0xFF000000) >> 24 |
314 (temp & 0xFF0000) >> 8 |
315 (temp & 0xFF00) << 8 |
316 (temp & 0xFF) << 24;
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000317 return reg;
318}
319
Stefan Reinauer7110d402009-11-03 14:59:43 +0000320static void x86emuOp2_bswap(u8 op2)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000321{
322 /* byte swap 32 bit register */
323 START_OF_INSTR();
324 DECODE_PRINTF("BSWAP\t");
325 switch (op2) {
326 case 0xc8:
327 DECODE_PRINTF("EAX\n");
328 M.x86.R_EAX = x86emu_bswap(M.x86.R_EAX);
329 break;
330 case 0xc9:
331 DECODE_PRINTF("ECX\n");
332 M.x86.R_ECX = x86emu_bswap(M.x86.R_ECX);
333 break;
334 case 0xca:
335 DECODE_PRINTF("EDX\n");
336 M.x86.R_EDX = x86emu_bswap(M.x86.R_EDX);
337 break;
338 case 0xcb:
339 DECODE_PRINTF("EBX\n");
340 M.x86.R_EBX = x86emu_bswap(M.x86.R_EBX);
341 break;
342 case 0xcc:
343 DECODE_PRINTF("ESP\n");
344 M.x86.R_ESP = x86emu_bswap(M.x86.R_ESP);
345 break;
346 case 0xcd:
347 DECODE_PRINTF("EBP\n");
348 M.x86.R_EBP = x86emu_bswap(M.x86.R_EBP);
349 break;
350 case 0xce:
351 DECODE_PRINTF("ESI\n");
352 M.x86.R_ESI = x86emu_bswap(M.x86.R_ESI);
353 break;
354 case 0xcf:
355 DECODE_PRINTF("EDI\n");
356 M.x86.R_EDI = x86emu_bswap(M.x86.R_EDI);
357 break;
358 }
359 TRACE_AND_STEP();
360 DECODE_CLEAR_SEGOVR();
361 END_OF_INSTR();
362}
363
364/****************************************************************************
365REMARKS:
366Handles opcode 0x0f,0x90-0x9F
367****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000368static void x86emuOp2_set_byte(u8 op2)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000369{
370 int mod, rl, rh;
371 uint destoffset;
372 u8 *destreg;
Stefan Reinauer48fcb532012-07-26 15:04:24 -0700373 const char *X86EMU_DEBUG_ONLY(name) = NULL;
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000374 int cond = 0;
375
376 START_OF_INSTR();
377 switch (op2) {
378 case 0x90:
379 name = "SETO\t";
380 cond = ACCESS_FLAG(F_OF);
381 break;
382 case 0x91:
383 name = "SETNO\t";
384 cond = !ACCESS_FLAG(F_OF);
385 break;
386 case 0x92:
387 name = "SETB\t";
388 cond = ACCESS_FLAG(F_CF);
389 break;
390 case 0x93:
391 name = "SETNB\t";
392 cond = !ACCESS_FLAG(F_CF);
393 break;
394 case 0x94:
395 name = "SETZ\t";
396 cond = ACCESS_FLAG(F_ZF);
397 break;
398 case 0x95:
399 name = "SETNZ\t";
400 cond = !ACCESS_FLAG(F_ZF);
401 break;
402 case 0x96:
403 name = "SETBE\t";
404 cond = ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF);
405 break;
406 case 0x97:
407 name = "SETNBE\t";
408 cond = !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
409 break;
410 case 0x98:
411 name = "SETS\t";
412 cond = ACCESS_FLAG(F_SF);
413 break;
414 case 0x99:
415 name = "SETNS\t";
416 cond = !ACCESS_FLAG(F_SF);
417 break;
418 case 0x9a:
419 name = "SETP\t";
420 cond = ACCESS_FLAG(F_PF);
421 break;
422 case 0x9b:
423 name = "SETNP\t";
424 cond = !ACCESS_FLAG(F_PF);
425 break;
426 case 0x9c:
427 name = "SETL\t";
428 cond = xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
429 break;
430 case 0x9d:
431 name = "SETNL\t";
432 cond = !xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
433 break;
434 case 0x9e:
435 name = "SETLE\t";
436 cond = (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
437 ACCESS_FLAG(F_ZF));
438 break;
439 case 0x9f:
440 name = "SETNLE\t";
441 cond = !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
442 ACCESS_FLAG(F_ZF));
443 break;
444 }
445 DECODE_PRINTF(name);
446 FETCH_DECODE_MODRM(mod, rh, rl);
447 if (mod < 3) {
448 destoffset = decode_rmXX_address(mod, rl);
449 TRACE_AND_STEP();
450 store_data_byte(destoffset, cond ? 0x01 : 0x00);
451 } else { /* register to register */
452 destreg = DECODE_RM_BYTE_REGISTER(rl);
453 TRACE_AND_STEP();
454 *destreg = cond ? 0x01 : 0x00;
455 }
456 DECODE_CLEAR_SEGOVR();
457 END_OF_INSTR();
458}
459
460/****************************************************************************
461REMARKS:
462Handles opcode 0x0f,0xa0
463****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000464static void x86emuOp2_push_FS(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000465{
466 START_OF_INSTR();
467 DECODE_PRINTF("PUSH\tFS\n");
468 TRACE_AND_STEP();
469 push_word(M.x86.R_FS);
470 DECODE_CLEAR_SEGOVR();
471 END_OF_INSTR();
472}
473
474/****************************************************************************
475REMARKS:
476Handles opcode 0x0f,0xa1
477****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000478static void x86emuOp2_pop_FS(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000479{
480 START_OF_INSTR();
481 DECODE_PRINTF("POP\tFS\n");
482 TRACE_AND_STEP();
483 M.x86.R_FS = pop_word();
484 DECODE_CLEAR_SEGOVR();
485 END_OF_INSTR();
486}
487
488/****************************************************************************
Stefan Reinauer7110d402009-11-03 14:59:43 +0000489REMARKS: CPUID takes EAX/ECX as inputs, writes EAX/EBX/ECX/EDX as output
490Handles opcode 0x0f,0xa2
491****************************************************************************/
492static void x86emuOp2_cpuid(u8 X86EMU_UNUSED(op2))
493{
494 START_OF_INSTR();
495 DECODE_PRINTF("CPUID\n");
496 TRACE_AND_STEP();
497 x86emu_cpuid();
498 DECODE_CLEAR_SEGOVR();
499 END_OF_INSTR();
500}
501
502/****************************************************************************
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000503REMARKS:
504Handles opcode 0x0f,0xa3
505****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000506static void x86emuOp2_bt_R(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000507{
508 int mod, rl, rh;
509 uint srcoffset;
510 int bit,disp;
511
512 START_OF_INSTR();
513 DECODE_PRINTF("BT\t");
514 FETCH_DECODE_MODRM(mod, rh, rl);
515 if (mod < 3) {
516 srcoffset = decode_rmXX_address(mod, rl);
517 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
518 u32 srcval;
519 u32 *shiftreg;
520
521 DECODE_PRINTF(",");
522 shiftreg = DECODE_RM_LONG_REGISTER(rh);
523 TRACE_AND_STEP();
524 bit = *shiftreg & 0x1F;
525 disp = (s16)*shiftreg >> 5;
526 srcval = fetch_data_long(srcoffset+disp);
527 CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF);
528 } else {
529 u16 srcval;
530 u16 *shiftreg;
531
532 DECODE_PRINTF(",");
533 shiftreg = DECODE_RM_WORD_REGISTER(rh);
534 TRACE_AND_STEP();
535 bit = *shiftreg & 0xF;
536 disp = (s16)*shiftreg >> 4;
537 srcval = fetch_data_word(srcoffset+disp);
538 CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF);
539 }
540 } else { /* register to register */
541 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
542 u32 *srcreg,*shiftreg;
543
544 srcreg = DECODE_RM_LONG_REGISTER(rl);
545 DECODE_PRINTF(",");
546 shiftreg = DECODE_RM_LONG_REGISTER(rh);
547 TRACE_AND_STEP();
548 bit = *shiftreg & 0x1F;
549 CONDITIONAL_SET_FLAG(*srcreg & (0x1 << bit),F_CF);
550 } else {
551 u16 *srcreg,*shiftreg;
552
553 srcreg = DECODE_RM_WORD_REGISTER(rl);
554 DECODE_PRINTF(",");
555 shiftreg = DECODE_RM_WORD_REGISTER(rh);
556 TRACE_AND_STEP();
557 bit = *shiftreg & 0xF;
558 CONDITIONAL_SET_FLAG(*srcreg & (0x1 << bit),F_CF);
559 }
560 }
561 DECODE_CLEAR_SEGOVR();
562 END_OF_INSTR();
563}
564
565/****************************************************************************
566REMARKS:
567Handles opcode 0x0f,0xa4
568****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000569static void x86emuOp2_shld_IMM(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000570{
571 int mod, rl, rh;
572 uint destoffset;
573 u8 shift;
574
575 START_OF_INSTR();
576 DECODE_PRINTF("SHLD\t");
577 FETCH_DECODE_MODRM(mod, rh, rl);
578 if (mod < 3) {
579 destoffset = decode_rmXX_address(mod, rl);
580 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
581 u32 destval;
582 u32 *shiftreg;
583
584 DECODE_PRINTF(",");
585 shiftreg = DECODE_RM_LONG_REGISTER(rh);
586 DECODE_PRINTF(",");
587 shift = fetch_byte_imm();
588 DECODE_PRINTF2("%d\n", shift);
589 TRACE_AND_STEP();
590 destval = fetch_data_long(destoffset);
591 destval = shld_long(destval,*shiftreg,shift);
592 store_data_long(destoffset, destval);
593 } else {
594 u16 destval;
595 u16 *shiftreg;
596
597 DECODE_PRINTF(",");
598 shiftreg = DECODE_RM_WORD_REGISTER(rh);
599 DECODE_PRINTF(",");
600 shift = fetch_byte_imm();
601 DECODE_PRINTF2("%d\n", shift);
602 TRACE_AND_STEP();
603 destval = fetch_data_word(destoffset);
604 destval = shld_word(destval,*shiftreg,shift);
605 store_data_word(destoffset, destval);
606 }
607 } else { /* register to register */
608 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
609 u32 *destreg,*shiftreg;
610
611 destreg = DECODE_RM_LONG_REGISTER(rl);
612 DECODE_PRINTF(",");
613 shiftreg = DECODE_RM_LONG_REGISTER(rh);
614 DECODE_PRINTF(",");
615 shift = fetch_byte_imm();
616 DECODE_PRINTF2("%d\n", shift);
617 TRACE_AND_STEP();
618 *destreg = shld_long(*destreg,*shiftreg,shift);
619 } else {
620 u16 *destreg,*shiftreg;
621
622 destreg = DECODE_RM_WORD_REGISTER(rl);
623 DECODE_PRINTF(",");
624 shiftreg = DECODE_RM_WORD_REGISTER(rh);
625 DECODE_PRINTF(",");
626 shift = fetch_byte_imm();
627 DECODE_PRINTF2("%d\n", shift);
628 TRACE_AND_STEP();
629 *destreg = shld_word(*destreg,*shiftreg,shift);
630 }
631 }
632 DECODE_CLEAR_SEGOVR();
633 END_OF_INSTR();
634}
635
636/****************************************************************************
637REMARKS:
638Handles opcode 0x0f,0xa5
639****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000640static void x86emuOp2_shld_CL(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000641{
642 int mod, rl, rh;
643 uint destoffset;
644
645 START_OF_INSTR();
646 DECODE_PRINTF("SHLD\t");
647 FETCH_DECODE_MODRM(mod, rh, rl);
648 if (mod < 3) {
649 destoffset = decode_rmXX_address(mod, rl);
650 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
651 u32 destval;
652 u32 *shiftreg;
653
654 DECODE_PRINTF(",");
655 shiftreg = DECODE_RM_LONG_REGISTER(rh);
656 DECODE_PRINTF(",CL\n");
657 TRACE_AND_STEP();
658 destval = fetch_data_long(destoffset);
659 destval = shld_long(destval,*shiftreg,M.x86.R_CL);
660 store_data_long(destoffset, destval);
661 } else {
662 u16 destval;
663 u16 *shiftreg;
664
665 DECODE_PRINTF(",");
666 shiftreg = DECODE_RM_WORD_REGISTER(rh);
667 DECODE_PRINTF(",CL\n");
668 TRACE_AND_STEP();
669 destval = fetch_data_word(destoffset);
670 destval = shld_word(destval,*shiftreg,M.x86.R_CL);
671 store_data_word(destoffset, destval);
672 }
673 } else { /* register to register */
674 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
675 u32 *destreg,*shiftreg;
676
677 destreg = DECODE_RM_LONG_REGISTER(rl);
678 DECODE_PRINTF(",");
679 shiftreg = DECODE_RM_LONG_REGISTER(rh);
680 DECODE_PRINTF(",CL\n");
681 TRACE_AND_STEP();
682 *destreg = shld_long(*destreg,*shiftreg,M.x86.R_CL);
683 } else {
684 u16 *destreg,*shiftreg;
685
686 destreg = DECODE_RM_WORD_REGISTER(rl);
687 DECODE_PRINTF(",");
688 shiftreg = DECODE_RM_WORD_REGISTER(rh);
689 DECODE_PRINTF(",CL\n");
690 TRACE_AND_STEP();
691 *destreg = shld_word(*destreg,*shiftreg,M.x86.R_CL);
692 }
693 }
694 DECODE_CLEAR_SEGOVR();
695 END_OF_INSTR();
696}
697
698/****************************************************************************
699REMARKS:
700Handles opcode 0x0f,0xa8
701****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000702static void x86emuOp2_push_GS(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000703{
704 START_OF_INSTR();
705 DECODE_PRINTF("PUSH\tGS\n");
706 TRACE_AND_STEP();
707 push_word(M.x86.R_GS);
708 DECODE_CLEAR_SEGOVR();
709 END_OF_INSTR();
710}
711
712/****************************************************************************
713REMARKS:
714Handles opcode 0x0f,0xa9
715****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000716static void x86emuOp2_pop_GS(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000717{
718 START_OF_INSTR();
719 DECODE_PRINTF("POP\tGS\n");
720 TRACE_AND_STEP();
721 M.x86.R_GS = pop_word();
722 DECODE_CLEAR_SEGOVR();
723 END_OF_INSTR();
724}
725
726/****************************************************************************
727REMARKS:
Stefan Reinauer26e441f2012-07-26 15:20:13 -0700728Handles opcode 0x0f,0xab
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000729****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000730static void x86emuOp2_bts_R(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000731{
732 int mod, rl, rh;
733 uint srcoffset;
734 int bit,disp;
735
736 START_OF_INSTR();
737 DECODE_PRINTF("BTS\t");
738 FETCH_DECODE_MODRM(mod, rh, rl);
739 if (mod < 3) {
740 srcoffset = decode_rmXX_address(mod, rl);
741 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
742 u32 srcval,mask;
743 u32 *shiftreg;
744
745 DECODE_PRINTF(",");
746 shiftreg = DECODE_RM_LONG_REGISTER(rh);
747 TRACE_AND_STEP();
748 bit = *shiftreg & 0x1F;
749 disp = (s16)*shiftreg >> 5;
750 srcval = fetch_data_long(srcoffset+disp);
751 mask = (0x1 << bit);
752 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
753 store_data_long(srcoffset+disp, srcval | mask);
754 } else {
755 u16 srcval,mask;
756 u16 *shiftreg;
757
758 DECODE_PRINTF(",");
759 shiftreg = DECODE_RM_WORD_REGISTER(rh);
760 TRACE_AND_STEP();
761 bit = *shiftreg & 0xF;
762 disp = (s16)*shiftreg >> 4;
763 srcval = fetch_data_word(srcoffset+disp);
764 mask = (u16)(0x1 << bit);
765 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
766 store_data_word(srcoffset+disp, srcval | mask);
767 }
768 } else { /* register to register */
769 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
770 u32 *srcreg,*shiftreg;
771 u32 mask;
772
773 srcreg = DECODE_RM_LONG_REGISTER(rl);
774 DECODE_PRINTF(",");
775 shiftreg = DECODE_RM_LONG_REGISTER(rh);
776 TRACE_AND_STEP();
777 bit = *shiftreg & 0x1F;
778 mask = (0x1 << bit);
779 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
780 *srcreg |= mask;
781 } else {
782 u16 *srcreg,*shiftreg;
783 u16 mask;
784
785 srcreg = DECODE_RM_WORD_REGISTER(rl);
786 DECODE_PRINTF(",");
787 shiftreg = DECODE_RM_WORD_REGISTER(rh);
788 TRACE_AND_STEP();
789 bit = *shiftreg & 0xF;
790 mask = (u16)(0x1 << bit);
791 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
792 *srcreg |= mask;
793 }
794 }
795 DECODE_CLEAR_SEGOVR();
796 END_OF_INSTR();
797}
798
799/****************************************************************************
800REMARKS:
801Handles opcode 0x0f,0xac
802****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000803static void x86emuOp2_shrd_IMM(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000804{
805 int mod, rl, rh;
806 uint destoffset;
807 u8 shift;
808
809 START_OF_INSTR();
810 DECODE_PRINTF("SHLD\t");
811 FETCH_DECODE_MODRM(mod, rh, rl);
812 if (mod < 3) {
813 destoffset = decode_rmXX_address(mod, rl);
814 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
815 u32 destval;
816 u32 *shiftreg;
817
818 DECODE_PRINTF(",");
819 shiftreg = DECODE_RM_LONG_REGISTER(rh);
820 DECODE_PRINTF(",");
821 shift = fetch_byte_imm();
822 DECODE_PRINTF2("%d\n", shift);
823 TRACE_AND_STEP();
824 destval = fetch_data_long(destoffset);
825 destval = shrd_long(destval,*shiftreg,shift);
826 store_data_long(destoffset, destval);
827 } else {
828 u16 destval;
829 u16 *shiftreg;
830
831 DECODE_PRINTF(",");
832 shiftreg = DECODE_RM_WORD_REGISTER(rh);
833 DECODE_PRINTF(",");
834 shift = fetch_byte_imm();
835 DECODE_PRINTF2("%d\n", shift);
836 TRACE_AND_STEP();
837 destval = fetch_data_word(destoffset);
838 destval = shrd_word(destval,*shiftreg,shift);
839 store_data_word(destoffset, destval);
840 }
841 } else { /* register to register */
842 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
843 u32 *destreg,*shiftreg;
844
845 destreg = DECODE_RM_LONG_REGISTER(rl);
846 DECODE_PRINTF(",");
847 shiftreg = DECODE_RM_LONG_REGISTER(rh);
848 DECODE_PRINTF(",");
849 shift = fetch_byte_imm();
850 DECODE_PRINTF2("%d\n", shift);
851 TRACE_AND_STEP();
852 *destreg = shrd_long(*destreg,*shiftreg,shift);
853 } else {
854 u16 *destreg,*shiftreg;
855
856 destreg = DECODE_RM_WORD_REGISTER(rl);
857 DECODE_PRINTF(",");
858 shiftreg = DECODE_RM_WORD_REGISTER(rh);
859 DECODE_PRINTF(",");
860 shift = fetch_byte_imm();
861 DECODE_PRINTF2("%d\n", shift);
862 TRACE_AND_STEP();
863 *destreg = shrd_word(*destreg,*shiftreg,shift);
864 }
865 }
866 DECODE_CLEAR_SEGOVR();
867 END_OF_INSTR();
868}
869
870/****************************************************************************
871REMARKS:
872Handles opcode 0x0f,0xad
873****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000874static void x86emuOp2_shrd_CL(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000875{
876 int mod, rl, rh;
877 uint destoffset;
878
879 START_OF_INSTR();
880 DECODE_PRINTF("SHLD\t");
881 FETCH_DECODE_MODRM(mod, rh, rl);
882 if (mod < 3) {
883 destoffset = decode_rmXX_address(mod, rl);
884 DECODE_PRINTF(",");
885 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
886 u32 destval;
887 u32 *shiftreg;
888
889 shiftreg = DECODE_RM_LONG_REGISTER(rh);
890 DECODE_PRINTF(",CL\n");
891 TRACE_AND_STEP();
892 destval = fetch_data_long(destoffset);
893 destval = shrd_long(destval,*shiftreg,M.x86.R_CL);
894 store_data_long(destoffset, destval);
895 } else {
896 u16 destval;
897 u16 *shiftreg;
898
899 shiftreg = DECODE_RM_WORD_REGISTER(rh);
900 DECODE_PRINTF(",CL\n");
901 TRACE_AND_STEP();
902 destval = fetch_data_word(destoffset);
903 destval = shrd_word(destval,*shiftreg,M.x86.R_CL);
904 store_data_word(destoffset, destval);
905 }
906 } else { /* register to register */
907 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
908 u32 *destreg,*shiftreg;
909
910 destreg = DECODE_RM_LONG_REGISTER(rl);
911 DECODE_PRINTF(",");
912 shiftreg = DECODE_RM_LONG_REGISTER(rh);
913 DECODE_PRINTF(",CL\n");
914 TRACE_AND_STEP();
915 *destreg = shrd_long(*destreg,*shiftreg,M.x86.R_CL);
916 } else {
917 u16 *destreg,*shiftreg;
918
919 destreg = DECODE_RM_WORD_REGISTER(rl);
920 DECODE_PRINTF(",");
921 shiftreg = DECODE_RM_WORD_REGISTER(rh);
922 DECODE_PRINTF(",CL\n");
923 TRACE_AND_STEP();
924 *destreg = shrd_word(*destreg,*shiftreg,M.x86.R_CL);
925 }
926 }
927 DECODE_CLEAR_SEGOVR();
928 END_OF_INSTR();
929}
930
931/****************************************************************************
932REMARKS:
933Handles opcode 0x0f,0xaf
934****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000935static void x86emuOp2_imul_R_RM(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000936{
937 int mod, rl, rh;
938 uint srcoffset;
939
940 START_OF_INSTR();
941 DECODE_PRINTF("IMUL\t");
942 FETCH_DECODE_MODRM(mod, rh, rl);
943 if (mod < 3) {
944 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
945 u32 *destreg;
946 u32 srcval;
947 u32 res_lo,res_hi;
948
949 destreg = DECODE_RM_LONG_REGISTER(rh);
950 DECODE_PRINTF(",");
951 srcoffset = decode_rmXX_address(mod, rl);
952 srcval = fetch_data_long(srcoffset);
953 TRACE_AND_STEP();
954 imul_long_direct(&res_lo,&res_hi,(s32)*destreg,(s32)srcval);
955 if (res_hi != 0) {
956 SET_FLAG(F_CF);
957 SET_FLAG(F_OF);
958 } else {
959 CLEAR_FLAG(F_CF);
960 CLEAR_FLAG(F_OF);
961 }
962 *destreg = (u32)res_lo;
963 } else {
964 u16 *destreg;
965 u16 srcval;
966 u32 res;
967
968 destreg = DECODE_RM_WORD_REGISTER(rh);
969 DECODE_PRINTF(",");
970 srcoffset = decode_rmXX_address(mod, rl);
971 srcval = fetch_data_word(srcoffset);
972 TRACE_AND_STEP();
973 res = (s16)*destreg * (s16)srcval;
974 if (res > 0xFFFF) {
975 SET_FLAG(F_CF);
976 SET_FLAG(F_OF);
977 } else {
978 CLEAR_FLAG(F_CF);
979 CLEAR_FLAG(F_OF);
980 }
981 *destreg = (u16)res;
982 }
983 } else { /* register to register */
984 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
985 u32 *destreg,*srcreg;
986 u32 res_lo,res_hi;
987
988 destreg = DECODE_RM_LONG_REGISTER(rh);
989 DECODE_PRINTF(",");
990 srcreg = DECODE_RM_LONG_REGISTER(rl);
991 TRACE_AND_STEP();
992 imul_long_direct(&res_lo,&res_hi,(s32)*destreg,(s32)*srcreg);
993 if (res_hi != 0) {
994 SET_FLAG(F_CF);
995 SET_FLAG(F_OF);
996 } else {
997 CLEAR_FLAG(F_CF);
998 CLEAR_FLAG(F_OF);
999 }
1000 *destreg = (u32)res_lo;
1001 } else {
1002 u16 *destreg,*srcreg;
1003 u32 res;
1004
1005 destreg = DECODE_RM_WORD_REGISTER(rh);
1006 DECODE_PRINTF(",");
1007 srcreg = DECODE_RM_WORD_REGISTER(rl);
1008 res = (s16)*destreg * (s16)*srcreg;
1009 if (res > 0xFFFF) {
1010 SET_FLAG(F_CF);
1011 SET_FLAG(F_OF);
1012 } else {
1013 CLEAR_FLAG(F_CF);
1014 CLEAR_FLAG(F_OF);
1015 }
1016 *destreg = (u16)res;
1017 }
1018 }
1019 DECODE_CLEAR_SEGOVR();
1020 END_OF_INSTR();
1021}
1022
1023/****************************************************************************
1024REMARKS:
1025Handles opcode 0x0f,0xb2
1026****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001027static void x86emuOp2_lss_R_IMM(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001028{
1029 int mod, rh, rl;
1030 u16 *dstreg;
1031 uint srcoffset;
1032
1033 START_OF_INSTR();
1034 DECODE_PRINTF("LSS\t");
1035 FETCH_DECODE_MODRM(mod, rh, rl);
1036 if (mod < 3) {
1037 dstreg = DECODE_RM_WORD_REGISTER(rh);
1038 DECODE_PRINTF(",");
1039 srcoffset = decode_rmXX_address(mod, rl);
1040 DECODE_PRINTF("\n");
1041 TRACE_AND_STEP();
1042 *dstreg = fetch_data_word(srcoffset);
1043 M.x86.R_SS = fetch_data_word(srcoffset + 2);
1044 } else { /* register to register */
1045 /* UNDEFINED! */
1046 TRACE_AND_STEP();
1047 }
1048 DECODE_CLEAR_SEGOVR();
1049 END_OF_INSTR();
1050}
1051
1052/****************************************************************************
1053REMARKS:
1054Handles opcode 0x0f,0xb3
1055****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001056static void x86emuOp2_btr_R(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001057{
1058 int mod, rl, rh;
1059 uint srcoffset;
1060 int bit,disp;
1061
1062 START_OF_INSTR();
1063 DECODE_PRINTF("BTR\t");
1064 FETCH_DECODE_MODRM(mod, rh, rl);
1065 if (mod < 3) {
1066 srcoffset = decode_rmXX_address(mod, rl);
1067 DECODE_PRINTF(",");
1068 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1069 u32 srcval,mask;
1070 u32 *shiftreg;
1071
1072 shiftreg = DECODE_RM_LONG_REGISTER(rh);
1073 TRACE_AND_STEP();
1074 bit = *shiftreg & 0x1F;
1075 disp = (s16)*shiftreg >> 5;
1076 srcval = fetch_data_long(srcoffset+disp);
1077 mask = (0x1 << bit);
1078 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1079 store_data_long(srcoffset+disp, srcval & ~mask);
1080 } else {
1081 u16 srcval,mask;
1082 u16 *shiftreg;
1083
1084 shiftreg = DECODE_RM_WORD_REGISTER(rh);
1085 TRACE_AND_STEP();
1086 bit = *shiftreg & 0xF;
1087 disp = (s16)*shiftreg >> 4;
1088 srcval = fetch_data_word(srcoffset+disp);
1089 mask = (u16)(0x1 << bit);
1090 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1091 store_data_word(srcoffset+disp, (u16)(srcval & ~mask));
1092 }
1093 } else { /* register to register */
1094 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1095 u32 *srcreg,*shiftreg;
1096 u32 mask;
1097
1098 srcreg = DECODE_RM_LONG_REGISTER(rl);
1099 DECODE_PRINTF(",");
1100 shiftreg = DECODE_RM_LONG_REGISTER(rh);
1101 TRACE_AND_STEP();
1102 bit = *shiftreg & 0x1F;
1103 mask = (0x1 << bit);
1104 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1105 *srcreg &= ~mask;
1106 } else {
1107 u16 *srcreg,*shiftreg;
1108 u16 mask;
1109
1110 srcreg = DECODE_RM_WORD_REGISTER(rl);
1111 DECODE_PRINTF(",");
1112 shiftreg = DECODE_RM_WORD_REGISTER(rh);
1113 TRACE_AND_STEP();
1114 bit = *shiftreg & 0xF;
1115 mask = (u16)(0x1 << bit);
1116 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1117 *srcreg &= ~mask;
1118 }
1119 }
1120 DECODE_CLEAR_SEGOVR();
1121 END_OF_INSTR();
1122}
1123
1124/****************************************************************************
1125REMARKS:
1126Handles opcode 0x0f,0xb4
1127****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001128static void x86emuOp2_lfs_R_IMM(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001129{
1130 int mod, rh, rl;
1131 u16 *dstreg;
1132 uint srcoffset;
1133
1134 START_OF_INSTR();
1135 DECODE_PRINTF("LFS\t");
1136 FETCH_DECODE_MODRM(mod, rh, rl);
1137 if (mod < 3) {
1138 dstreg = DECODE_RM_WORD_REGISTER(rh);
1139 DECODE_PRINTF(",");
1140 srcoffset = decode_rmXX_address(mod, rl);
1141 DECODE_PRINTF("\n");
1142 TRACE_AND_STEP();
1143 *dstreg = fetch_data_word(srcoffset);
1144 M.x86.R_FS = fetch_data_word(srcoffset + 2);
1145 } else { /* register to register */
1146 /* UNDEFINED! */
1147 TRACE_AND_STEP();
1148 }
1149 DECODE_CLEAR_SEGOVR();
1150 END_OF_INSTR();
1151}
1152
1153/****************************************************************************
1154REMARKS:
1155Handles opcode 0x0f,0xb5
1156****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001157static void x86emuOp2_lgs_R_IMM(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001158{
1159 int mod, rh, rl;
1160 u16 *dstreg;
1161 uint srcoffset;
1162
1163 START_OF_INSTR();
1164 DECODE_PRINTF("LGS\t");
1165 FETCH_DECODE_MODRM(mod, rh, rl);
1166 if (mod < 3) {
1167 dstreg = DECODE_RM_WORD_REGISTER(rh);
1168 DECODE_PRINTF(",");
1169 srcoffset = decode_rmXX_address(mod, rl);
1170 DECODE_PRINTF("\n");
1171 TRACE_AND_STEP();
1172 *dstreg = fetch_data_word(srcoffset);
1173 M.x86.R_GS = fetch_data_word(srcoffset + 2);
1174 } else { /* register to register */
1175 /* UNDEFINED! */
1176 TRACE_AND_STEP();
1177 }
1178 DECODE_CLEAR_SEGOVR();
1179 END_OF_INSTR();
1180}
1181
1182/****************************************************************************
1183REMARKS:
1184Handles opcode 0x0f,0xb6
1185****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001186static void x86emuOp2_movzx_byte_R_RM(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001187{
1188 int mod, rl, rh;
1189 uint srcoffset;
1190
1191 START_OF_INSTR();
1192 DECODE_PRINTF("MOVZX\t");
1193 FETCH_DECODE_MODRM(mod, rh, rl);
1194 if (mod < 3) {
1195 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1196 u32 *destreg;
1197 u32 srcval;
1198
1199 destreg = DECODE_RM_LONG_REGISTER(rh);
1200 DECODE_PRINTF(",");
1201 srcoffset = decode_rmXX_address(mod, rl);
1202 srcval = fetch_data_byte(srcoffset);
1203 DECODE_PRINTF("\n");
1204 TRACE_AND_STEP();
1205 *destreg = srcval;
1206 } else {
1207 u16 *destreg;
1208 u16 srcval;
1209
1210 destreg = DECODE_RM_WORD_REGISTER(rh);
1211 DECODE_PRINTF(",");
1212 srcoffset = decode_rmXX_address(mod, rl);
1213 srcval = fetch_data_byte(srcoffset);
1214 DECODE_PRINTF("\n");
1215 TRACE_AND_STEP();
1216 *destreg = srcval;
1217 }
1218 } else { /* register to register */
1219 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1220 u32 *destreg;
1221 u8 *srcreg;
1222
1223 destreg = DECODE_RM_LONG_REGISTER(rh);
1224 DECODE_PRINTF(",");
1225 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1226 DECODE_PRINTF("\n");
1227 TRACE_AND_STEP();
1228 *destreg = *srcreg;
1229 } else {
1230 u16 *destreg;
1231 u8 *srcreg;
1232
1233 destreg = DECODE_RM_WORD_REGISTER(rh);
1234 DECODE_PRINTF(",");
1235 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1236 DECODE_PRINTF("\n");
1237 TRACE_AND_STEP();
1238 *destreg = *srcreg;
1239 }
1240 }
1241 DECODE_CLEAR_SEGOVR();
1242 END_OF_INSTR();
1243}
1244
1245/****************************************************************************
1246REMARKS:
1247Handles opcode 0x0f,0xb7
1248****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001249static void x86emuOp2_movzx_word_R_RM(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001250{
1251 int mod, rl, rh;
1252 uint srcoffset;
1253 u32 *destreg;
1254 u32 srcval;
1255 u16 *srcreg;
1256
1257 START_OF_INSTR();
1258 DECODE_PRINTF("MOVZX\t");
1259 FETCH_DECODE_MODRM(mod, rh, rl);
1260 if (mod < 3) {
1261 destreg = DECODE_RM_LONG_REGISTER(rh);
1262 DECODE_PRINTF(",");
1263 srcoffset = decode_rmXX_address(mod, rl);
1264 srcval = fetch_data_word(srcoffset);
1265 DECODE_PRINTF("\n");
1266 TRACE_AND_STEP();
1267 *destreg = srcval;
1268 } else { /* register to register */
1269 destreg = DECODE_RM_LONG_REGISTER(rh);
1270 DECODE_PRINTF(",");
1271 srcreg = DECODE_RM_WORD_REGISTER(rl);
1272 DECODE_PRINTF("\n");
1273 TRACE_AND_STEP();
1274 *destreg = *srcreg;
1275 }
1276 DECODE_CLEAR_SEGOVR();
1277 END_OF_INSTR();
1278}
1279
1280/****************************************************************************
1281REMARKS:
1282Handles opcode 0x0f,0xba
1283****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001284static void x86emuOp2_btX_I(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001285{
1286 int mod, rl, rh;
1287 uint srcoffset;
1288 u8 shift;
1289 int bit;
1290
1291 START_OF_INSTR();
1292 FETCH_DECODE_MODRM(mod, rh, rl);
1293 switch (rh) {
1294 case 4:
1295 DECODE_PRINTF("BT\t");
1296 break;
1297 case 5:
1298 DECODE_PRINTF("BTS\t");
1299 break;
1300 case 6:
1301 DECODE_PRINTF("BTR\t");
1302 break;
1303 case 7:
1304 DECODE_PRINTF("BTC\t");
1305 break;
1306 default:
1307 DECODE_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n");
1308 TRACE_REGS();
Uwe Hermann01ce6012010-03-05 10:03:50 +00001309 printf("%04x:%04x: %02X%02X ILLEGAL EXTENDED X86 OPCODE EXTENSION!\n",
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001310 M.x86.R_CS, M.x86.R_IP-3,op2, (mod<<6)|(rh<<3)|rl);
1311 HALT_SYS();
1312 }
1313 if (mod < 3) {
1314
1315 srcoffset = decode_rmXX_address(mod, rl);
1316 shift = fetch_byte_imm();
1317 DECODE_PRINTF2(",%d\n", shift);
1318 TRACE_AND_STEP();
1319
1320 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1321 u32 srcval, mask;
1322
1323 bit = shift & 0x1F;
1324 srcval = fetch_data_long(srcoffset);
1325 mask = (0x1 << bit);
1326 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1327 switch (rh) {
1328 case 5:
1329 store_data_long(srcoffset, srcval | mask);
1330 break;
1331 case 6:
1332 store_data_long(srcoffset, srcval & ~mask);
1333 break;
1334 case 7:
1335 store_data_long(srcoffset, srcval ^ mask);
1336 break;
1337 default:
1338 break;
1339 }
1340 } else {
1341 u16 srcval, mask;
1342
1343 bit = shift & 0xF;
1344 srcval = fetch_data_word(srcoffset);
1345 mask = (0x1 << bit);
1346 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1347 switch (rh) {
1348 case 5:
1349 store_data_word(srcoffset, srcval | mask);
1350 break;
1351 case 6:
1352 store_data_word(srcoffset, srcval & ~mask);
1353 break;
1354 case 7:
1355 store_data_word(srcoffset, srcval ^ mask);
1356 break;
1357 default:
1358 break;
1359 }
1360 }
1361 } else { /* register to register */
1362 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1363 u32 *srcreg;
1364 u32 mask;
1365
1366 srcreg = DECODE_RM_LONG_REGISTER(rl);
1367 shift = fetch_byte_imm();
1368 DECODE_PRINTF2(",%d\n", shift);
1369 TRACE_AND_STEP();
1370 bit = shift & 0x1F;
1371 mask = (0x1 << bit);
1372 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1373 switch (rh) {
1374 case 5:
1375 *srcreg |= mask;
1376 break;
1377 case 6:
1378 *srcreg &= ~mask;
1379 break;
1380 case 7:
1381 *srcreg ^= mask;
1382 break;
1383 default:
1384 break;
1385 }
1386 } else {
1387 u16 *srcreg;
1388 u16 mask;
1389
1390 srcreg = DECODE_RM_WORD_REGISTER(rl);
1391 shift = fetch_byte_imm();
1392 DECODE_PRINTF2(",%d\n", shift);
1393 TRACE_AND_STEP();
1394 bit = shift & 0xF;
1395 mask = (0x1 << bit);
1396 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1397 switch (rh) {
1398 case 5:
1399 *srcreg |= mask;
1400 break;
1401 case 6:
1402 *srcreg &= ~mask;
1403 break;
1404 case 7:
1405 *srcreg ^= mask;
1406 break;
1407 default:
1408 break;
1409 }
1410 }
1411 }
1412 DECODE_CLEAR_SEGOVR();
1413 END_OF_INSTR();
1414}
1415
1416/****************************************************************************
1417REMARKS:
1418Handles opcode 0x0f,0xbb
1419****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001420static void x86emuOp2_btc_R(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001421{
1422 int mod, rl, rh;
1423 uint srcoffset;
1424 int bit,disp;
1425
1426 START_OF_INSTR();
1427 DECODE_PRINTF("BTC\t");
1428 FETCH_DECODE_MODRM(mod, rh, rl);
1429 if (mod < 3) {
1430 srcoffset = decode_rmXX_address(mod, rl);
1431 DECODE_PRINTF(",");
1432 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1433 u32 srcval,mask;
1434 u32 *shiftreg;
1435
1436 shiftreg = DECODE_RM_LONG_REGISTER(rh);
1437 TRACE_AND_STEP();
1438 bit = *shiftreg & 0x1F;
1439 disp = (s16)*shiftreg >> 5;
1440 srcval = fetch_data_long(srcoffset+disp);
1441 mask = (0x1 << bit);
1442 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1443 store_data_long(srcoffset+disp, srcval ^ mask);
1444 } else {
1445 u16 srcval,mask;
1446 u16 *shiftreg;
1447
1448 shiftreg = DECODE_RM_WORD_REGISTER(rh);
1449 TRACE_AND_STEP();
1450 bit = *shiftreg & 0xF;
1451 disp = (s16)*shiftreg >> 4;
1452 srcval = fetch_data_word(srcoffset+disp);
1453 mask = (u16)(0x1 << bit);
1454 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1455 store_data_word(srcoffset+disp, (u16)(srcval ^ mask));
1456 }
1457 } else { /* register to register */
1458 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1459 u32 *srcreg,*shiftreg;
1460 u32 mask;
1461
1462 srcreg = DECODE_RM_LONG_REGISTER(rl);
1463 DECODE_PRINTF(",");
1464 shiftreg = DECODE_RM_LONG_REGISTER(rh);
1465 TRACE_AND_STEP();
1466 bit = *shiftreg & 0x1F;
1467 mask = (0x1 << bit);
1468 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1469 *srcreg ^= mask;
1470 } else {
1471 u16 *srcreg,*shiftreg;
1472 u16 mask;
1473
1474 srcreg = DECODE_RM_WORD_REGISTER(rl);
1475 DECODE_PRINTF(",");
1476 shiftreg = DECODE_RM_WORD_REGISTER(rh);
1477 TRACE_AND_STEP();
1478 bit = *shiftreg & 0xF;
1479 mask = (u16)(0x1 << bit);
1480 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1481 *srcreg ^= mask;
1482 }
1483 }
1484 DECODE_CLEAR_SEGOVR();
1485 END_OF_INSTR();
1486}
1487
1488/****************************************************************************
1489REMARKS:
1490Handles opcode 0x0f,0xbc
1491****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001492static void x86emuOp2_bsf(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001493{
1494 int mod, rl, rh;
1495 uint srcoffset;
1496
1497 START_OF_INSTR();
Stefan Reinauer4b80cd42012-07-26 15:02:49 -07001498 DECODE_PRINTF("BSF\t");
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001499 FETCH_DECODE_MODRM(mod, rh, rl);
1500 if (mod < 3) {
1501 srcoffset = decode_rmXX_address(mod, rl);
1502 DECODE_PRINTF(",");
1503 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1504 u32 srcval, *dstreg;
1505
1506 dstreg = DECODE_RM_LONG_REGISTER(rh);
1507 TRACE_AND_STEP();
1508 srcval = fetch_data_long(srcoffset);
1509 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
Elyes HAOUASf772f9c2016-08-21 18:28:17 +02001510 for (*dstreg = 0; *dstreg < 32; (*dstreg)++)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001511 if ((srcval >> *dstreg) & 1) break;
1512 } else {
1513 u16 srcval, *dstreg;
1514
1515 dstreg = DECODE_RM_WORD_REGISTER(rh);
1516 TRACE_AND_STEP();
1517 srcval = fetch_data_word(srcoffset);
1518 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
Elyes HAOUASf772f9c2016-08-21 18:28:17 +02001519 for (*dstreg = 0; *dstreg < 16; (*dstreg)++)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001520 if ((srcval >> *dstreg) & 1) break;
1521 }
1522 } else { /* register to register */
1523 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Stefan Reinauer4b80cd42012-07-26 15:02:49 -07001524 u32 srcval, *dstreg;
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001525
Stefan Reinauer4b80cd42012-07-26 15:02:49 -07001526 srcval = *DECODE_RM_LONG_REGISTER(rl);
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001527 DECODE_PRINTF(",");
1528 dstreg = DECODE_RM_LONG_REGISTER(rh);
1529 TRACE_AND_STEP();
Stefan Reinauer4b80cd42012-07-26 15:02:49 -07001530 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
Elyes HAOUASf772f9c2016-08-21 18:28:17 +02001531 for (*dstreg = 0; *dstreg < 32; (*dstreg)++)
Stefan Reinauer4b80cd42012-07-26 15:02:49 -07001532 if ((srcval >> *dstreg) & 1) break;
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001533 } else {
Stefan Reinauer4b80cd42012-07-26 15:02:49 -07001534 u16 srcval, *dstreg;
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001535
Stefan Reinauer4b80cd42012-07-26 15:02:49 -07001536 srcval = *DECODE_RM_WORD_REGISTER(rl);
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001537 DECODE_PRINTF(",");
1538 dstreg = DECODE_RM_WORD_REGISTER(rh);
1539 TRACE_AND_STEP();
Stefan Reinauer4b80cd42012-07-26 15:02:49 -07001540 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
Elyes HAOUASf772f9c2016-08-21 18:28:17 +02001541 for (*dstreg = 0; *dstreg < 16; (*dstreg)++)
Stefan Reinauer4b80cd42012-07-26 15:02:49 -07001542 if ((srcval >> *dstreg) & 1) break;
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001543 }
1544 }
1545 DECODE_CLEAR_SEGOVR();
1546 END_OF_INSTR();
1547}
1548
1549/****************************************************************************
1550REMARKS:
1551Handles opcode 0x0f,0xbd
1552****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001553static void x86emuOp2_bsr(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001554{
1555 int mod, rl, rh;
1556 uint srcoffset;
1557
1558 START_OF_INSTR();
Stefan Reinauer4b80cd42012-07-26 15:02:49 -07001559 DECODE_PRINTF("BSR\t");
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001560 FETCH_DECODE_MODRM(mod, rh, rl);
1561 if (mod < 3) {
1562 srcoffset = decode_rmXX_address(mod, rl);
1563 DECODE_PRINTF(",");
1564 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1565 u32 srcval, *dstreg;
1566
1567 dstreg = DECODE_RM_LONG_REGISTER(rh);
1568 TRACE_AND_STEP();
1569 srcval = fetch_data_long(srcoffset);
1570 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
Elyes HAOUASf772f9c2016-08-21 18:28:17 +02001571 for (*dstreg = 31; *dstreg > 0; (*dstreg)--)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001572 if ((srcval >> *dstreg) & 1) break;
1573 } else {
1574 u16 srcval, *dstreg;
1575
1576 dstreg = DECODE_RM_WORD_REGISTER(rh);
1577 TRACE_AND_STEP();
1578 srcval = fetch_data_word(srcoffset);
1579 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
Elyes HAOUASf772f9c2016-08-21 18:28:17 +02001580 for (*dstreg = 15; *dstreg > 0; (*dstreg)--)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001581 if ((srcval >> *dstreg) & 1) break;
1582 }
1583 } else { /* register to register */
1584 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
Stefan Reinauer4b80cd42012-07-26 15:02:49 -07001585 u32 srcval, *dstreg;
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001586
Stefan Reinauer4b80cd42012-07-26 15:02:49 -07001587 srcval = *DECODE_RM_LONG_REGISTER(rl);
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001588 DECODE_PRINTF(",");
1589 dstreg = DECODE_RM_LONG_REGISTER(rh);
1590 TRACE_AND_STEP();
Stefan Reinauer4b80cd42012-07-26 15:02:49 -07001591 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
Elyes HAOUASf772f9c2016-08-21 18:28:17 +02001592 for (*dstreg = 31; *dstreg > 0; (*dstreg)--)
Stefan Reinauer4b80cd42012-07-26 15:02:49 -07001593 if ((srcval >> *dstreg) & 1) break;
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001594 } else {
Stefan Reinauer4b80cd42012-07-26 15:02:49 -07001595 u16 srcval, *dstreg;
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001596
Stefan Reinauer4b80cd42012-07-26 15:02:49 -07001597 srcval = *DECODE_RM_WORD_REGISTER(rl);
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001598 DECODE_PRINTF(",");
1599 dstreg = DECODE_RM_WORD_REGISTER(rh);
1600 TRACE_AND_STEP();
Stefan Reinauer4b80cd42012-07-26 15:02:49 -07001601 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
Elyes HAOUASf772f9c2016-08-21 18:28:17 +02001602 for (*dstreg = 15; *dstreg > 0; (*dstreg)--)
Stefan Reinauer4b80cd42012-07-26 15:02:49 -07001603 if ((srcval >> *dstreg) & 1) break;
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001604 }
1605 }
1606 DECODE_CLEAR_SEGOVR();
1607 END_OF_INSTR();
1608}
1609
1610/****************************************************************************
1611REMARKS:
1612Handles opcode 0x0f,0xbe
1613****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001614static void x86emuOp2_movsx_byte_R_RM(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001615{
1616 int mod, rl, rh;
1617 uint srcoffset;
1618
1619 START_OF_INSTR();
1620 DECODE_PRINTF("MOVSX\t");
1621 FETCH_DECODE_MODRM(mod, rh, rl);
1622 if (mod < 3) {
1623 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1624 u32 *destreg;
1625 u32 srcval;
1626
1627 destreg = DECODE_RM_LONG_REGISTER(rh);
1628 DECODE_PRINTF(",");
1629 srcoffset = decode_rmXX_address(mod, rl);
1630 srcval = (s32)((s8)fetch_data_byte(srcoffset));
1631 DECODE_PRINTF("\n");
1632 TRACE_AND_STEP();
1633 *destreg = srcval;
1634 } else {
1635 u16 *destreg;
1636 u16 srcval;
1637
1638 destreg = DECODE_RM_WORD_REGISTER(rh);
1639 DECODE_PRINTF(",");
1640 srcoffset = decode_rmXX_address(mod, rl);
1641 srcval = (s16)((s8)fetch_data_byte(srcoffset));
1642 DECODE_PRINTF("\n");
1643 TRACE_AND_STEP();
1644 *destreg = srcval;
1645 }
1646 } else { /* register to register */
1647 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1648 u32 *destreg;
1649 u8 *srcreg;
1650
1651 destreg = DECODE_RM_LONG_REGISTER(rh);
1652 DECODE_PRINTF(",");
1653 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1654 DECODE_PRINTF("\n");
1655 TRACE_AND_STEP();
1656 *destreg = (s32)((s8)*srcreg);
1657 } else {
1658 u16 *destreg;
1659 u8 *srcreg;
1660
1661 destreg = DECODE_RM_WORD_REGISTER(rh);
1662 DECODE_PRINTF(",");
1663 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1664 DECODE_PRINTF("\n");
1665 TRACE_AND_STEP();
1666 *destreg = (s16)((s8)*srcreg);
1667 }
1668 }
1669 DECODE_CLEAR_SEGOVR();
1670 END_OF_INSTR();
1671}
1672
1673/****************************************************************************
1674REMARKS:
1675Handles opcode 0x0f,0xbf
1676****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001677static void x86emuOp2_movsx_word_R_RM(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001678{
1679 int mod, rl, rh;
1680 uint srcoffset;
1681 u32 *destreg;
1682 u32 srcval;
1683 u16 *srcreg;
1684
1685 START_OF_INSTR();
1686 DECODE_PRINTF("MOVSX\t");
1687 FETCH_DECODE_MODRM(mod, rh, rl);
1688 if (mod < 3) {
1689 destreg = DECODE_RM_LONG_REGISTER(rh);
1690 DECODE_PRINTF(",");
1691 srcoffset = decode_rmXX_address(mod, rl);
1692 srcval = (s32)((s16)fetch_data_word(srcoffset));
1693 DECODE_PRINTF("\n");
1694 TRACE_AND_STEP();
1695 *destreg = srcval;
1696 } else { /* register to register */
1697 destreg = DECODE_RM_LONG_REGISTER(rh);
1698 DECODE_PRINTF(",");
1699 srcreg = DECODE_RM_WORD_REGISTER(rl);
1700 DECODE_PRINTF("\n");
1701 TRACE_AND_STEP();
1702 *destreg = (s32)((s16)*srcreg);
1703 }
1704 DECODE_CLEAR_SEGOVR();
1705 END_OF_INSTR();
1706}
1707
1708/***************************************************************************
1709 * Double byte operation code table:
1710 **************************************************************************/
1711void (*x86emu_optab2[256])(u8) =
1712{
1713/* 0x00 */ x86emuOp2_illegal_op, /* Group F (ring 0 PM) */
Stefan Reinauer7110d402009-11-03 14:59:43 +00001714/* 0x01 */ x86emuOp2_opc_01, /* Group G (ring 0 PM) */
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001715/* 0x02 */ x86emuOp2_illegal_op, /* lar (ring 0 PM) */
1716/* 0x03 */ x86emuOp2_illegal_op, /* lsl (ring 0 PM) */
1717/* 0x04 */ x86emuOp2_illegal_op,
1718/* 0x05 */ x86emuOp2_illegal_op, /* loadall (undocumented) */
1719/* 0x06 */ x86emuOp2_illegal_op, /* clts (ring 0 PM) */
1720/* 0x07 */ x86emuOp2_illegal_op, /* loadall (undocumented) */
Stefan Reinauer7110d402009-11-03 14:59:43 +00001721/* 0x08 */ x86emuOp2_invd, /* invd (ring 0 PM) */
1722/* 0x09 */ x86emuOp2_wbinvd, /* wbinvd (ring 0 PM) */
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001723/* 0x0a */ x86emuOp2_illegal_op,
1724/* 0x0b */ x86emuOp2_illegal_op,
1725/* 0x0c */ x86emuOp2_illegal_op,
1726/* 0x0d */ x86emuOp2_illegal_op,
1727/* 0x0e */ x86emuOp2_illegal_op,
1728/* 0x0f */ x86emuOp2_illegal_op,
1729
1730/* 0x10 */ x86emuOp2_illegal_op,
1731/* 0x11 */ x86emuOp2_illegal_op,
1732/* 0x12 */ x86emuOp2_illegal_op,
1733/* 0x13 */ x86emuOp2_illegal_op,
1734/* 0x14 */ x86emuOp2_illegal_op,
1735/* 0x15 */ x86emuOp2_illegal_op,
1736/* 0x16 */ x86emuOp2_illegal_op,
1737/* 0x17 */ x86emuOp2_illegal_op,
1738/* 0x18 */ x86emuOp2_illegal_op,
1739/* 0x19 */ x86emuOp2_illegal_op,
1740/* 0x1a */ x86emuOp2_illegal_op,
1741/* 0x1b */ x86emuOp2_illegal_op,
1742/* 0x1c */ x86emuOp2_illegal_op,
1743/* 0x1d */ x86emuOp2_illegal_op,
1744/* 0x1e */ x86emuOp2_illegal_op,
1745/* 0x1f */ x86emuOp2_illegal_op,
1746
1747/* 0x20 */ x86emuOp2_illegal_op, /* mov reg32,creg (ring 0 PM) */
1748/* 0x21 */ x86emuOp2_illegal_op, /* mov reg32,dreg (ring 0 PM) */
1749/* 0x22 */ x86emuOp2_illegal_op, /* mov creg,reg32 (ring 0 PM) */
1750/* 0x23 */ x86emuOp2_illegal_op, /* mov dreg,reg32 (ring 0 PM) */
1751/* 0x24 */ x86emuOp2_illegal_op, /* mov reg32,treg (ring 0 PM) */
1752/* 0x25 */ x86emuOp2_illegal_op,
1753/* 0x26 */ x86emuOp2_illegal_op, /* mov treg,reg32 (ring 0 PM) */
1754/* 0x27 */ x86emuOp2_illegal_op,
1755/* 0x28 */ x86emuOp2_illegal_op,
1756/* 0x29 */ x86emuOp2_illegal_op,
1757/* 0x2a */ x86emuOp2_illegal_op,
1758/* 0x2b */ x86emuOp2_illegal_op,
1759/* 0x2c */ x86emuOp2_illegal_op,
1760/* 0x2d */ x86emuOp2_illegal_op,
1761/* 0x2e */ x86emuOp2_illegal_op,
1762/* 0x2f */ x86emuOp2_illegal_op,
1763
Stefan Reinauer7110d402009-11-03 14:59:43 +00001764/* 0x30 */ x86emuOp2_wrmsr,
Stefan Reinauer911f4462012-07-26 15:15:38 -07001765/* 0x31 */ x86emuOp2_rdtsc,
Stefan Reinauer7110d402009-11-03 14:59:43 +00001766/* 0x32 */ x86emuOp2_rdmsr,
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001767/* 0x33 */ x86emuOp2_illegal_op,
1768/* 0x34 */ x86emuOp2_illegal_op,
1769/* 0x35 */ x86emuOp2_illegal_op,
1770/* 0x36 */ x86emuOp2_illegal_op,
1771/* 0x37 */ x86emuOp2_illegal_op,
1772/* 0x38 */ x86emuOp2_illegal_op,
1773/* 0x39 */ x86emuOp2_illegal_op,
1774/* 0x3a */ x86emuOp2_illegal_op,
1775/* 0x3b */ x86emuOp2_illegal_op,
1776/* 0x3c */ x86emuOp2_illegal_op,
1777/* 0x3d */ x86emuOp2_illegal_op,
1778/* 0x3e */ x86emuOp2_illegal_op,
1779/* 0x3f */ x86emuOp2_illegal_op,
1780
1781/* 0x40 */ x86emuOp2_illegal_op,
1782/* 0x41 */ x86emuOp2_illegal_op,
1783/* 0x42 */ x86emuOp2_illegal_op,
1784/* 0x43 */ x86emuOp2_illegal_op,
1785/* 0x44 */ x86emuOp2_illegal_op,
1786/* 0x45 */ x86emuOp2_illegal_op,
1787/* 0x46 */ x86emuOp2_illegal_op,
1788/* 0x47 */ x86emuOp2_illegal_op,
1789/* 0x48 */ x86emuOp2_illegal_op,
1790/* 0x49 */ x86emuOp2_illegal_op,
1791/* 0x4a */ x86emuOp2_illegal_op,
1792/* 0x4b */ x86emuOp2_illegal_op,
1793/* 0x4c */ x86emuOp2_illegal_op,
1794/* 0x4d */ x86emuOp2_illegal_op,
1795/* 0x4e */ x86emuOp2_illegal_op,
1796/* 0x4f */ x86emuOp2_illegal_op,
1797
1798/* 0x50 */ x86emuOp2_illegal_op,
1799/* 0x51 */ x86emuOp2_illegal_op,
1800/* 0x52 */ x86emuOp2_illegal_op,
1801/* 0x53 */ x86emuOp2_illegal_op,
1802/* 0x54 */ x86emuOp2_illegal_op,
1803/* 0x55 */ x86emuOp2_illegal_op,
1804/* 0x56 */ x86emuOp2_illegal_op,
1805/* 0x57 */ x86emuOp2_illegal_op,
1806/* 0x58 */ x86emuOp2_illegal_op,
1807/* 0x59 */ x86emuOp2_illegal_op,
1808/* 0x5a */ x86emuOp2_illegal_op,
1809/* 0x5b */ x86emuOp2_illegal_op,
1810/* 0x5c */ x86emuOp2_illegal_op,
1811/* 0x5d */ x86emuOp2_illegal_op,
1812/* 0x5e */ x86emuOp2_illegal_op,
1813/* 0x5f */ x86emuOp2_illegal_op,
1814
1815/* 0x60 */ x86emuOp2_illegal_op,
1816/* 0x61 */ x86emuOp2_illegal_op,
1817/* 0x62 */ x86emuOp2_illegal_op,
1818/* 0x63 */ x86emuOp2_illegal_op,
1819/* 0x64 */ x86emuOp2_illegal_op,
1820/* 0x65 */ x86emuOp2_illegal_op,
1821/* 0x66 */ x86emuOp2_illegal_op,
1822/* 0x67 */ x86emuOp2_illegal_op,
1823/* 0x68 */ x86emuOp2_illegal_op,
1824/* 0x69 */ x86emuOp2_illegal_op,
1825/* 0x6a */ x86emuOp2_illegal_op,
1826/* 0x6b */ x86emuOp2_illegal_op,
1827/* 0x6c */ x86emuOp2_illegal_op,
1828/* 0x6d */ x86emuOp2_illegal_op,
1829/* 0x6e */ x86emuOp2_illegal_op,
1830/* 0x6f */ x86emuOp2_illegal_op,
1831
1832/* 0x70 */ x86emuOp2_illegal_op,
1833/* 0x71 */ x86emuOp2_illegal_op,
1834/* 0x72 */ x86emuOp2_illegal_op,
1835/* 0x73 */ x86emuOp2_illegal_op,
1836/* 0x74 */ x86emuOp2_illegal_op,
1837/* 0x75 */ x86emuOp2_illegal_op,
1838/* 0x76 */ x86emuOp2_illegal_op,
1839/* 0x77 */ x86emuOp2_illegal_op,
1840/* 0x78 */ x86emuOp2_illegal_op,
1841/* 0x79 */ x86emuOp2_illegal_op,
1842/* 0x7a */ x86emuOp2_illegal_op,
1843/* 0x7b */ x86emuOp2_illegal_op,
1844/* 0x7c */ x86emuOp2_illegal_op,
1845/* 0x7d */ x86emuOp2_illegal_op,
1846/* 0x7e */ x86emuOp2_illegal_op,
1847/* 0x7f */ x86emuOp2_illegal_op,
1848
1849/* 0x80 */ x86emuOp2_long_jump,
1850/* 0x81 */ x86emuOp2_long_jump,
1851/* 0x82 */ x86emuOp2_long_jump,
1852/* 0x83 */ x86emuOp2_long_jump,
1853/* 0x84 */ x86emuOp2_long_jump,
1854/* 0x85 */ x86emuOp2_long_jump,
1855/* 0x86 */ x86emuOp2_long_jump,
1856/* 0x87 */ x86emuOp2_long_jump,
1857/* 0x88 */ x86emuOp2_long_jump,
1858/* 0x89 */ x86emuOp2_long_jump,
1859/* 0x8a */ x86emuOp2_long_jump,
1860/* 0x8b */ x86emuOp2_long_jump,
1861/* 0x8c */ x86emuOp2_long_jump,
1862/* 0x8d */ x86emuOp2_long_jump,
1863/* 0x8e */ x86emuOp2_long_jump,
1864/* 0x8f */ x86emuOp2_long_jump,
1865
1866/* 0x90 */ x86emuOp2_set_byte,
1867/* 0x91 */ x86emuOp2_set_byte,
1868/* 0x92 */ x86emuOp2_set_byte,
1869/* 0x93 */ x86emuOp2_set_byte,
1870/* 0x94 */ x86emuOp2_set_byte,
1871/* 0x95 */ x86emuOp2_set_byte,
1872/* 0x96 */ x86emuOp2_set_byte,
1873/* 0x97 */ x86emuOp2_set_byte,
1874/* 0x98 */ x86emuOp2_set_byte,
1875/* 0x99 */ x86emuOp2_set_byte,
1876/* 0x9a */ x86emuOp2_set_byte,
1877/* 0x9b */ x86emuOp2_set_byte,
1878/* 0x9c */ x86emuOp2_set_byte,
1879/* 0x9d */ x86emuOp2_set_byte,
1880/* 0x9e */ x86emuOp2_set_byte,
1881/* 0x9f */ x86emuOp2_set_byte,
1882
1883/* 0xa0 */ x86emuOp2_push_FS,
1884/* 0xa1 */ x86emuOp2_pop_FS,
Stefan Reinauer7110d402009-11-03 14:59:43 +00001885/* 0xa2 */ x86emuOp2_cpuid,
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001886/* 0xa3 */ x86emuOp2_bt_R,
1887/* 0xa4 */ x86emuOp2_shld_IMM,
1888/* 0xa5 */ x86emuOp2_shld_CL,
1889/* 0xa6 */ x86emuOp2_illegal_op,
1890/* 0xa7 */ x86emuOp2_illegal_op,
1891/* 0xa8 */ x86emuOp2_push_GS,
1892/* 0xa9 */ x86emuOp2_pop_GS,
1893/* 0xaa */ x86emuOp2_illegal_op,
Stefan Reinauer7110d402009-11-03 14:59:43 +00001894/* 0xab */ x86emuOp2_bts_R,
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001895/* 0xac */ x86emuOp2_shrd_IMM,
1896/* 0xad */ x86emuOp2_shrd_CL,
1897/* 0xae */ x86emuOp2_illegal_op,
1898/* 0xaf */ x86emuOp2_imul_R_RM,
1899
1900/* 0xb0 */ x86emuOp2_illegal_op, /* TODO: cmpxchg */
1901/* 0xb1 */ x86emuOp2_illegal_op, /* TODO: cmpxchg */
1902/* 0xb2 */ x86emuOp2_lss_R_IMM,
1903/* 0xb3 */ x86emuOp2_btr_R,
1904/* 0xb4 */ x86emuOp2_lfs_R_IMM,
1905/* 0xb5 */ x86emuOp2_lgs_R_IMM,
1906/* 0xb6 */ x86emuOp2_movzx_byte_R_RM,
1907/* 0xb7 */ x86emuOp2_movzx_word_R_RM,
1908/* 0xb8 */ x86emuOp2_illegal_op,
1909/* 0xb9 */ x86emuOp2_illegal_op,
1910/* 0xba */ x86emuOp2_btX_I,
1911/* 0xbb */ x86emuOp2_btc_R,
1912/* 0xbc */ x86emuOp2_bsf,
1913/* 0xbd */ x86emuOp2_bsr,
1914/* 0xbe */ x86emuOp2_movsx_byte_R_RM,
1915/* 0xbf */ x86emuOp2_movsx_word_R_RM,
1916
1917/* 0xc0 */ x86emuOp2_illegal_op, /* TODO: xadd */
1918/* 0xc1 */ x86emuOp2_illegal_op, /* TODO: xadd */
1919/* 0xc2 */ x86emuOp2_illegal_op,
1920/* 0xc3 */ x86emuOp2_illegal_op,
1921/* 0xc4 */ x86emuOp2_illegal_op,
1922/* 0xc5 */ x86emuOp2_illegal_op,
1923/* 0xc6 */ x86emuOp2_illegal_op,
1924/* 0xc7 */ x86emuOp2_illegal_op,
1925/* 0xc8 */ x86emuOp2_bswap,
1926/* 0xc9 */ x86emuOp2_bswap,
1927/* 0xca */ x86emuOp2_bswap,
1928/* 0xcb */ x86emuOp2_bswap,
1929/* 0xcc */ x86emuOp2_bswap,
1930/* 0xcd */ x86emuOp2_bswap,
1931/* 0xce */ x86emuOp2_bswap,
1932/* 0xcf */ x86emuOp2_bswap,
1933
1934/* 0xd0 */ x86emuOp2_illegal_op,
1935/* 0xd1 */ x86emuOp2_illegal_op,
1936/* 0xd2 */ x86emuOp2_illegal_op,
1937/* 0xd3 */ x86emuOp2_illegal_op,
1938/* 0xd4 */ x86emuOp2_illegal_op,
1939/* 0xd5 */ x86emuOp2_illegal_op,
1940/* 0xd6 */ x86emuOp2_illegal_op,
1941/* 0xd7 */ x86emuOp2_illegal_op,
1942/* 0xd8 */ x86emuOp2_illegal_op,
1943/* 0xd9 */ x86emuOp2_illegal_op,
1944/* 0xda */ x86emuOp2_illegal_op,
1945/* 0xdb */ x86emuOp2_illegal_op,
1946/* 0xdc */ x86emuOp2_illegal_op,
1947/* 0xdd */ x86emuOp2_illegal_op,
1948/* 0xde */ x86emuOp2_illegal_op,
1949/* 0xdf */ x86emuOp2_illegal_op,
1950
1951/* 0xe0 */ x86emuOp2_illegal_op,
1952/* 0xe1 */ x86emuOp2_illegal_op,
1953/* 0xe2 */ x86emuOp2_illegal_op,
1954/* 0xe3 */ x86emuOp2_illegal_op,
1955/* 0xe4 */ x86emuOp2_illegal_op,
1956/* 0xe5 */ x86emuOp2_illegal_op,
1957/* 0xe6 */ x86emuOp2_illegal_op,
1958/* 0xe7 */ x86emuOp2_illegal_op,
1959/* 0xe8 */ x86emuOp2_illegal_op,
1960/* 0xe9 */ x86emuOp2_illegal_op,
1961/* 0xea */ x86emuOp2_illegal_op,
1962/* 0xeb */ x86emuOp2_illegal_op,
1963/* 0xec */ x86emuOp2_illegal_op,
1964/* 0xed */ x86emuOp2_illegal_op,
1965/* 0xee */ x86emuOp2_illegal_op,
1966/* 0xef */ x86emuOp2_illegal_op,
1967
1968/* 0xf0 */ x86emuOp2_illegal_op,
1969/* 0xf1 */ x86emuOp2_illegal_op,
1970/* 0xf2 */ x86emuOp2_illegal_op,
1971/* 0xf3 */ x86emuOp2_illegal_op,
1972/* 0xf4 */ x86emuOp2_illegal_op,
1973/* 0xf5 */ x86emuOp2_illegal_op,
1974/* 0xf6 */ x86emuOp2_illegal_op,
1975/* 0xf7 */ x86emuOp2_illegal_op,
1976/* 0xf8 */ x86emuOp2_illegal_op,
1977/* 0xf9 */ x86emuOp2_illegal_op,
1978/* 0xfa */ x86emuOp2_illegal_op,
1979/* 0xfb */ x86emuOp2_illegal_op,
1980/* 0xfc */ x86emuOp2_illegal_op,
1981/* 0xfd */ x86emuOp2_illegal_op,
1982/* 0xfe */ x86emuOp2_illegal_op,
1983/* 0xff */ x86emuOp2_illegal_op,
1984};