blob: 29c2a640543ae2a6e1a7c2077eea6edfd14ad6de [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/****************************************************************************
159 * REMARKS:
160 * Handles opcode 0x0f,0x32
161 * ****************************************************************************/
162static void x86emuOp2_rdmsr(u8 op2)
163{
164 /* dummy implementation, always return 0 */
165
166 START_OF_INSTR();
167 DECODE_PRINTF("RDMSR\n");
168 TRACE_AND_STEP();
169 M.x86.R_EDX = 0;
170 M.x86.R_EAX = 0;
171 DECODE_CLEAR_SEGOVR();
172 END_OF_INSTR();
Stefan Reinauer14e22772010-04-27 06:56:47 +0000173}
Stefan Reinauer7110d402009-11-03 14:59:43 +0000174
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000175#define xorl(a,b) (((a) && !(b)) || (!(a) && (b)))
176
177/****************************************************************************
178REMARKS:
179Handles opcode 0x0f,0x80-0x8F
180****************************************************************************/
181int x86emu_check_jump_condition(u8 op)
182{
183 switch (op) {
184 case 0x0:
185 DECODE_PRINTF("JO\t");
186 return ACCESS_FLAG(F_OF);
187 case 0x1:
188 DECODE_PRINTF("JNO\t");
189 return !ACCESS_FLAG(F_OF);
190 break;
191 case 0x2:
192 DECODE_PRINTF("JB\t");
193 return ACCESS_FLAG(F_CF);
194 break;
195 case 0x3:
196 DECODE_PRINTF("JNB\t");
197 return !ACCESS_FLAG(F_CF);
198 break;
199 case 0x4:
200 DECODE_PRINTF("JZ\t");
201 return ACCESS_FLAG(F_ZF);
202 break;
203 case 0x5:
204 DECODE_PRINTF("JNZ\t");
205 return !ACCESS_FLAG(F_ZF);
206 break;
207 case 0x6:
208 DECODE_PRINTF("JBE\t");
209 return ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF);
210 break;
211 case 0x7:
212 DECODE_PRINTF("JNBE\t");
213 return !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
214 break;
215 case 0x8:
216 DECODE_PRINTF("JS\t");
217 return ACCESS_FLAG(F_SF);
218 break;
219 case 0x9:
220 DECODE_PRINTF("JNS\t");
221 return !ACCESS_FLAG(F_SF);
222 break;
223 case 0xa:
224 DECODE_PRINTF("JP\t");
225 return ACCESS_FLAG(F_PF);
226 break;
227 case 0xb:
228 DECODE_PRINTF("JNP\t");
229 return !ACCESS_FLAG(F_PF);
230 break;
231 case 0xc:
232 DECODE_PRINTF("JL\t");
233 return xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
234 break;
235 case 0xd:
236 DECODE_PRINTF("JNL\t");
237 return !xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
238 break;
239 case 0xe:
240 DECODE_PRINTF("JLE\t");
241 return (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
242 ACCESS_FLAG(F_ZF));
243 break;
244 default:
245 DECODE_PRINTF("JNLE\t");
246 return !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
247 ACCESS_FLAG(F_ZF));
248 }
249}
250
Stefan Reinauer7110d402009-11-03 14:59:43 +0000251static void x86emuOp2_long_jump(u8 op2)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000252{
253 s32 target;
254 int cond;
255
256 /* conditional jump to word offset. */
257 START_OF_INSTR();
258 cond = x86emu_check_jump_condition(op2 & 0xF);
259 target = (s16) fetch_word_imm();
260 target += (s16) M.x86.R_IP;
261 DECODE_PRINTF2("%04x\n", target);
262 TRACE_AND_STEP();
263 if (cond) {
264 M.x86.R_IP = (u16)target;
265 JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, M.x86.R_IP, " LONG COND ");
266 }
267 DECODE_CLEAR_SEGOVR();
268 END_OF_INSTR();
269}
270
271/****************************************************************************
272REMARKS:
273Handles opcode 0x0f,0xC8-0xCF
274****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000275static s32 x86emu_bswap(s32 reg)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000276{
277 // perform the byte swap
278 s32 temp = reg;
Stefan Reinauer7110d402009-11-03 14:59:43 +0000279 reg = (temp & 0xFF000000) >> 24 |
280 (temp & 0xFF0000) >> 8 |
281 (temp & 0xFF00) << 8 |
282 (temp & 0xFF) << 24;
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000283 return reg;
284}
285
Stefan Reinauer7110d402009-11-03 14:59:43 +0000286static void x86emuOp2_bswap(u8 op2)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000287{
288 /* byte swap 32 bit register */
289 START_OF_INSTR();
290 DECODE_PRINTF("BSWAP\t");
291 switch (op2) {
292 case 0xc8:
293 DECODE_PRINTF("EAX\n");
294 M.x86.R_EAX = x86emu_bswap(M.x86.R_EAX);
295 break;
296 case 0xc9:
297 DECODE_PRINTF("ECX\n");
298 M.x86.R_ECX = x86emu_bswap(M.x86.R_ECX);
299 break;
300 case 0xca:
301 DECODE_PRINTF("EDX\n");
302 M.x86.R_EDX = x86emu_bswap(M.x86.R_EDX);
303 break;
304 case 0xcb:
305 DECODE_PRINTF("EBX\n");
306 M.x86.R_EBX = x86emu_bswap(M.x86.R_EBX);
307 break;
308 case 0xcc:
309 DECODE_PRINTF("ESP\n");
310 M.x86.R_ESP = x86emu_bswap(M.x86.R_ESP);
311 break;
312 case 0xcd:
313 DECODE_PRINTF("EBP\n");
314 M.x86.R_EBP = x86emu_bswap(M.x86.R_EBP);
315 break;
316 case 0xce:
317 DECODE_PRINTF("ESI\n");
318 M.x86.R_ESI = x86emu_bswap(M.x86.R_ESI);
319 break;
320 case 0xcf:
321 DECODE_PRINTF("EDI\n");
322 M.x86.R_EDI = x86emu_bswap(M.x86.R_EDI);
323 break;
324 }
325 TRACE_AND_STEP();
326 DECODE_CLEAR_SEGOVR();
327 END_OF_INSTR();
328}
329
330/****************************************************************************
331REMARKS:
332Handles opcode 0x0f,0x90-0x9F
333****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000334static void x86emuOp2_set_byte(u8 op2)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000335{
336 int mod, rl, rh;
337 uint destoffset;
338 u8 *destreg;
Stefan Reinauer48fcb532012-07-26 15:04:24 -0700339 const char *X86EMU_DEBUG_ONLY(name) = NULL;
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000340 int cond = 0;
341
342 START_OF_INSTR();
343 switch (op2) {
344 case 0x90:
345 name = "SETO\t";
346 cond = ACCESS_FLAG(F_OF);
347 break;
348 case 0x91:
349 name = "SETNO\t";
350 cond = !ACCESS_FLAG(F_OF);
351 break;
352 case 0x92:
353 name = "SETB\t";
354 cond = ACCESS_FLAG(F_CF);
355 break;
356 case 0x93:
357 name = "SETNB\t";
358 cond = !ACCESS_FLAG(F_CF);
359 break;
360 case 0x94:
361 name = "SETZ\t";
362 cond = ACCESS_FLAG(F_ZF);
363 break;
364 case 0x95:
365 name = "SETNZ\t";
366 cond = !ACCESS_FLAG(F_ZF);
367 break;
368 case 0x96:
369 name = "SETBE\t";
370 cond = ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF);
371 break;
372 case 0x97:
373 name = "SETNBE\t";
374 cond = !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
375 break;
376 case 0x98:
377 name = "SETS\t";
378 cond = ACCESS_FLAG(F_SF);
379 break;
380 case 0x99:
381 name = "SETNS\t";
382 cond = !ACCESS_FLAG(F_SF);
383 break;
384 case 0x9a:
385 name = "SETP\t";
386 cond = ACCESS_FLAG(F_PF);
387 break;
388 case 0x9b:
389 name = "SETNP\t";
390 cond = !ACCESS_FLAG(F_PF);
391 break;
392 case 0x9c:
393 name = "SETL\t";
394 cond = xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
395 break;
396 case 0x9d:
397 name = "SETNL\t";
398 cond = !xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
399 break;
400 case 0x9e:
401 name = "SETLE\t";
402 cond = (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
403 ACCESS_FLAG(F_ZF));
404 break;
405 case 0x9f:
406 name = "SETNLE\t";
407 cond = !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
408 ACCESS_FLAG(F_ZF));
409 break;
410 }
411 DECODE_PRINTF(name);
412 FETCH_DECODE_MODRM(mod, rh, rl);
413 if (mod < 3) {
414 destoffset = decode_rmXX_address(mod, rl);
415 TRACE_AND_STEP();
416 store_data_byte(destoffset, cond ? 0x01 : 0x00);
417 } else { /* register to register */
418 destreg = DECODE_RM_BYTE_REGISTER(rl);
419 TRACE_AND_STEP();
420 *destreg = cond ? 0x01 : 0x00;
421 }
422 DECODE_CLEAR_SEGOVR();
423 END_OF_INSTR();
424}
425
426/****************************************************************************
427REMARKS:
428Handles opcode 0x0f,0xa0
429****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000430static void x86emuOp2_push_FS(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000431{
432 START_OF_INSTR();
433 DECODE_PRINTF("PUSH\tFS\n");
434 TRACE_AND_STEP();
435 push_word(M.x86.R_FS);
436 DECODE_CLEAR_SEGOVR();
437 END_OF_INSTR();
438}
439
440/****************************************************************************
441REMARKS:
442Handles opcode 0x0f,0xa1
443****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000444static void x86emuOp2_pop_FS(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000445{
446 START_OF_INSTR();
447 DECODE_PRINTF("POP\tFS\n");
448 TRACE_AND_STEP();
449 M.x86.R_FS = pop_word();
450 DECODE_CLEAR_SEGOVR();
451 END_OF_INSTR();
452}
453
454/****************************************************************************
Stefan Reinauer7110d402009-11-03 14:59:43 +0000455REMARKS: CPUID takes EAX/ECX as inputs, writes EAX/EBX/ECX/EDX as output
456Handles opcode 0x0f,0xa2
457****************************************************************************/
458static void x86emuOp2_cpuid(u8 X86EMU_UNUSED(op2))
459{
460 START_OF_INSTR();
461 DECODE_PRINTF("CPUID\n");
462 TRACE_AND_STEP();
463 x86emu_cpuid();
464 DECODE_CLEAR_SEGOVR();
465 END_OF_INSTR();
466}
467
468/****************************************************************************
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000469REMARKS:
470Handles opcode 0x0f,0xa3
471****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000472static void x86emuOp2_bt_R(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000473{
474 int mod, rl, rh;
475 uint srcoffset;
476 int bit,disp;
477
478 START_OF_INSTR();
479 DECODE_PRINTF("BT\t");
480 FETCH_DECODE_MODRM(mod, rh, rl);
481 if (mod < 3) {
482 srcoffset = decode_rmXX_address(mod, rl);
483 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
484 u32 srcval;
485 u32 *shiftreg;
486
487 DECODE_PRINTF(",");
488 shiftreg = DECODE_RM_LONG_REGISTER(rh);
489 TRACE_AND_STEP();
490 bit = *shiftreg & 0x1F;
491 disp = (s16)*shiftreg >> 5;
492 srcval = fetch_data_long(srcoffset+disp);
493 CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF);
494 } else {
495 u16 srcval;
496 u16 *shiftreg;
497
498 DECODE_PRINTF(",");
499 shiftreg = DECODE_RM_WORD_REGISTER(rh);
500 TRACE_AND_STEP();
501 bit = *shiftreg & 0xF;
502 disp = (s16)*shiftreg >> 4;
503 srcval = fetch_data_word(srcoffset+disp);
504 CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF);
505 }
506 } else { /* register to register */
507 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
508 u32 *srcreg,*shiftreg;
509
510 srcreg = DECODE_RM_LONG_REGISTER(rl);
511 DECODE_PRINTF(",");
512 shiftreg = DECODE_RM_LONG_REGISTER(rh);
513 TRACE_AND_STEP();
514 bit = *shiftreg & 0x1F;
515 CONDITIONAL_SET_FLAG(*srcreg & (0x1 << bit),F_CF);
516 } else {
517 u16 *srcreg,*shiftreg;
518
519 srcreg = DECODE_RM_WORD_REGISTER(rl);
520 DECODE_PRINTF(",");
521 shiftreg = DECODE_RM_WORD_REGISTER(rh);
522 TRACE_AND_STEP();
523 bit = *shiftreg & 0xF;
524 CONDITIONAL_SET_FLAG(*srcreg & (0x1 << bit),F_CF);
525 }
526 }
527 DECODE_CLEAR_SEGOVR();
528 END_OF_INSTR();
529}
530
531/****************************************************************************
532REMARKS:
533Handles opcode 0x0f,0xa4
534****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000535static void x86emuOp2_shld_IMM(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000536{
537 int mod, rl, rh;
538 uint destoffset;
539 u8 shift;
540
541 START_OF_INSTR();
542 DECODE_PRINTF("SHLD\t");
543 FETCH_DECODE_MODRM(mod, rh, rl);
544 if (mod < 3) {
545 destoffset = decode_rmXX_address(mod, rl);
546 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
547 u32 destval;
548 u32 *shiftreg;
549
550 DECODE_PRINTF(",");
551 shiftreg = DECODE_RM_LONG_REGISTER(rh);
552 DECODE_PRINTF(",");
553 shift = fetch_byte_imm();
554 DECODE_PRINTF2("%d\n", shift);
555 TRACE_AND_STEP();
556 destval = fetch_data_long(destoffset);
557 destval = shld_long(destval,*shiftreg,shift);
558 store_data_long(destoffset, destval);
559 } else {
560 u16 destval;
561 u16 *shiftreg;
562
563 DECODE_PRINTF(",");
564 shiftreg = DECODE_RM_WORD_REGISTER(rh);
565 DECODE_PRINTF(",");
566 shift = fetch_byte_imm();
567 DECODE_PRINTF2("%d\n", shift);
568 TRACE_AND_STEP();
569 destval = fetch_data_word(destoffset);
570 destval = shld_word(destval,*shiftreg,shift);
571 store_data_word(destoffset, destval);
572 }
573 } else { /* register to register */
574 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
575 u32 *destreg,*shiftreg;
576
577 destreg = DECODE_RM_LONG_REGISTER(rl);
578 DECODE_PRINTF(",");
579 shiftreg = DECODE_RM_LONG_REGISTER(rh);
580 DECODE_PRINTF(",");
581 shift = fetch_byte_imm();
582 DECODE_PRINTF2("%d\n", shift);
583 TRACE_AND_STEP();
584 *destreg = shld_long(*destreg,*shiftreg,shift);
585 } else {
586 u16 *destreg,*shiftreg;
587
588 destreg = DECODE_RM_WORD_REGISTER(rl);
589 DECODE_PRINTF(",");
590 shiftreg = DECODE_RM_WORD_REGISTER(rh);
591 DECODE_PRINTF(",");
592 shift = fetch_byte_imm();
593 DECODE_PRINTF2("%d\n", shift);
594 TRACE_AND_STEP();
595 *destreg = shld_word(*destreg,*shiftreg,shift);
596 }
597 }
598 DECODE_CLEAR_SEGOVR();
599 END_OF_INSTR();
600}
601
602/****************************************************************************
603REMARKS:
604Handles opcode 0x0f,0xa5
605****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000606static void x86emuOp2_shld_CL(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000607{
608 int mod, rl, rh;
609 uint destoffset;
610
611 START_OF_INSTR();
612 DECODE_PRINTF("SHLD\t");
613 FETCH_DECODE_MODRM(mod, rh, rl);
614 if (mod < 3) {
615 destoffset = decode_rmXX_address(mod, rl);
616 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
617 u32 destval;
618 u32 *shiftreg;
619
620 DECODE_PRINTF(",");
621 shiftreg = DECODE_RM_LONG_REGISTER(rh);
622 DECODE_PRINTF(",CL\n");
623 TRACE_AND_STEP();
624 destval = fetch_data_long(destoffset);
625 destval = shld_long(destval,*shiftreg,M.x86.R_CL);
626 store_data_long(destoffset, destval);
627 } else {
628 u16 destval;
629 u16 *shiftreg;
630
631 DECODE_PRINTF(",");
632 shiftreg = DECODE_RM_WORD_REGISTER(rh);
633 DECODE_PRINTF(",CL\n");
634 TRACE_AND_STEP();
635 destval = fetch_data_word(destoffset);
636 destval = shld_word(destval,*shiftreg,M.x86.R_CL);
637 store_data_word(destoffset, destval);
638 }
639 } else { /* register to register */
640 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
641 u32 *destreg,*shiftreg;
642
643 destreg = DECODE_RM_LONG_REGISTER(rl);
644 DECODE_PRINTF(",");
645 shiftreg = DECODE_RM_LONG_REGISTER(rh);
646 DECODE_PRINTF(",CL\n");
647 TRACE_AND_STEP();
648 *destreg = shld_long(*destreg,*shiftreg,M.x86.R_CL);
649 } else {
650 u16 *destreg,*shiftreg;
651
652 destreg = DECODE_RM_WORD_REGISTER(rl);
653 DECODE_PRINTF(",");
654 shiftreg = DECODE_RM_WORD_REGISTER(rh);
655 DECODE_PRINTF(",CL\n");
656 TRACE_AND_STEP();
657 *destreg = shld_word(*destreg,*shiftreg,M.x86.R_CL);
658 }
659 }
660 DECODE_CLEAR_SEGOVR();
661 END_OF_INSTR();
662}
663
664/****************************************************************************
665REMARKS:
666Handles opcode 0x0f,0xa8
667****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000668static void x86emuOp2_push_GS(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000669{
670 START_OF_INSTR();
671 DECODE_PRINTF("PUSH\tGS\n");
672 TRACE_AND_STEP();
673 push_word(M.x86.R_GS);
674 DECODE_CLEAR_SEGOVR();
675 END_OF_INSTR();
676}
677
678/****************************************************************************
679REMARKS:
680Handles opcode 0x0f,0xa9
681****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000682static void x86emuOp2_pop_GS(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000683{
684 START_OF_INSTR();
685 DECODE_PRINTF("POP\tGS\n");
686 TRACE_AND_STEP();
687 M.x86.R_GS = pop_word();
688 DECODE_CLEAR_SEGOVR();
689 END_OF_INSTR();
690}
691
692/****************************************************************************
693REMARKS:
694Handles opcode 0x0f,0xaa
695****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000696static void x86emuOp2_bts_R(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000697{
698 int mod, rl, rh;
699 uint srcoffset;
700 int bit,disp;
701
702 START_OF_INSTR();
703 DECODE_PRINTF("BTS\t");
704 FETCH_DECODE_MODRM(mod, rh, rl);
705 if (mod < 3) {
706 srcoffset = decode_rmXX_address(mod, rl);
707 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
708 u32 srcval,mask;
709 u32 *shiftreg;
710
711 DECODE_PRINTF(",");
712 shiftreg = DECODE_RM_LONG_REGISTER(rh);
713 TRACE_AND_STEP();
714 bit = *shiftreg & 0x1F;
715 disp = (s16)*shiftreg >> 5;
716 srcval = fetch_data_long(srcoffset+disp);
717 mask = (0x1 << bit);
718 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
719 store_data_long(srcoffset+disp, srcval | mask);
720 } else {
721 u16 srcval,mask;
722 u16 *shiftreg;
723
724 DECODE_PRINTF(",");
725 shiftreg = DECODE_RM_WORD_REGISTER(rh);
726 TRACE_AND_STEP();
727 bit = *shiftreg & 0xF;
728 disp = (s16)*shiftreg >> 4;
729 srcval = fetch_data_word(srcoffset+disp);
730 mask = (u16)(0x1 << bit);
731 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
732 store_data_word(srcoffset+disp, srcval | mask);
733 }
734 } else { /* register to register */
735 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
736 u32 *srcreg,*shiftreg;
737 u32 mask;
738
739 srcreg = DECODE_RM_LONG_REGISTER(rl);
740 DECODE_PRINTF(",");
741 shiftreg = DECODE_RM_LONG_REGISTER(rh);
742 TRACE_AND_STEP();
743 bit = *shiftreg & 0x1F;
744 mask = (0x1 << bit);
745 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
746 *srcreg |= mask;
747 } else {
748 u16 *srcreg,*shiftreg;
749 u16 mask;
750
751 srcreg = DECODE_RM_WORD_REGISTER(rl);
752 DECODE_PRINTF(",");
753 shiftreg = DECODE_RM_WORD_REGISTER(rh);
754 TRACE_AND_STEP();
755 bit = *shiftreg & 0xF;
756 mask = (u16)(0x1 << bit);
757 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
758 *srcreg |= mask;
759 }
760 }
761 DECODE_CLEAR_SEGOVR();
762 END_OF_INSTR();
763}
764
765/****************************************************************************
766REMARKS:
767Handles opcode 0x0f,0xac
768****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000769static void x86emuOp2_shrd_IMM(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000770{
771 int mod, rl, rh;
772 uint destoffset;
773 u8 shift;
774
775 START_OF_INSTR();
776 DECODE_PRINTF("SHLD\t");
777 FETCH_DECODE_MODRM(mod, rh, rl);
778 if (mod < 3) {
779 destoffset = decode_rmXX_address(mod, rl);
780 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
781 u32 destval;
782 u32 *shiftreg;
783
784 DECODE_PRINTF(",");
785 shiftreg = DECODE_RM_LONG_REGISTER(rh);
786 DECODE_PRINTF(",");
787 shift = fetch_byte_imm();
788 DECODE_PRINTF2("%d\n", shift);
789 TRACE_AND_STEP();
790 destval = fetch_data_long(destoffset);
791 destval = shrd_long(destval,*shiftreg,shift);
792 store_data_long(destoffset, destval);
793 } else {
794 u16 destval;
795 u16 *shiftreg;
796
797 DECODE_PRINTF(",");
798 shiftreg = DECODE_RM_WORD_REGISTER(rh);
799 DECODE_PRINTF(",");
800 shift = fetch_byte_imm();
801 DECODE_PRINTF2("%d\n", shift);
802 TRACE_AND_STEP();
803 destval = fetch_data_word(destoffset);
804 destval = shrd_word(destval,*shiftreg,shift);
805 store_data_word(destoffset, destval);
806 }
807 } else { /* register to register */
808 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
809 u32 *destreg,*shiftreg;
810
811 destreg = DECODE_RM_LONG_REGISTER(rl);
812 DECODE_PRINTF(",");
813 shiftreg = DECODE_RM_LONG_REGISTER(rh);
814 DECODE_PRINTF(",");
815 shift = fetch_byte_imm();
816 DECODE_PRINTF2("%d\n", shift);
817 TRACE_AND_STEP();
818 *destreg = shrd_long(*destreg,*shiftreg,shift);
819 } else {
820 u16 *destreg,*shiftreg;
821
822 destreg = DECODE_RM_WORD_REGISTER(rl);
823 DECODE_PRINTF(",");
824 shiftreg = DECODE_RM_WORD_REGISTER(rh);
825 DECODE_PRINTF(",");
826 shift = fetch_byte_imm();
827 DECODE_PRINTF2("%d\n", shift);
828 TRACE_AND_STEP();
829 *destreg = shrd_word(*destreg,*shiftreg,shift);
830 }
831 }
832 DECODE_CLEAR_SEGOVR();
833 END_OF_INSTR();
834}
835
836/****************************************************************************
837REMARKS:
838Handles opcode 0x0f,0xad
839****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000840static void x86emuOp2_shrd_CL(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000841{
842 int mod, rl, rh;
843 uint destoffset;
844
845 START_OF_INSTR();
846 DECODE_PRINTF("SHLD\t");
847 FETCH_DECODE_MODRM(mod, rh, rl);
848 if (mod < 3) {
849 destoffset = decode_rmXX_address(mod, rl);
850 DECODE_PRINTF(",");
851 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
852 u32 destval;
853 u32 *shiftreg;
854
855 shiftreg = DECODE_RM_LONG_REGISTER(rh);
856 DECODE_PRINTF(",CL\n");
857 TRACE_AND_STEP();
858 destval = fetch_data_long(destoffset);
859 destval = shrd_long(destval,*shiftreg,M.x86.R_CL);
860 store_data_long(destoffset, destval);
861 } else {
862 u16 destval;
863 u16 *shiftreg;
864
865 shiftreg = DECODE_RM_WORD_REGISTER(rh);
866 DECODE_PRINTF(",CL\n");
867 TRACE_AND_STEP();
868 destval = fetch_data_word(destoffset);
869 destval = shrd_word(destval,*shiftreg,M.x86.R_CL);
870 store_data_word(destoffset, destval);
871 }
872 } else { /* register to register */
873 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
874 u32 *destreg,*shiftreg;
875
876 destreg = DECODE_RM_LONG_REGISTER(rl);
877 DECODE_PRINTF(",");
878 shiftreg = DECODE_RM_LONG_REGISTER(rh);
879 DECODE_PRINTF(",CL\n");
880 TRACE_AND_STEP();
881 *destreg = shrd_long(*destreg,*shiftreg,M.x86.R_CL);
882 } else {
883 u16 *destreg,*shiftreg;
884
885 destreg = DECODE_RM_WORD_REGISTER(rl);
886 DECODE_PRINTF(",");
887 shiftreg = DECODE_RM_WORD_REGISTER(rh);
888 DECODE_PRINTF(",CL\n");
889 TRACE_AND_STEP();
890 *destreg = shrd_word(*destreg,*shiftreg,M.x86.R_CL);
891 }
892 }
893 DECODE_CLEAR_SEGOVR();
894 END_OF_INSTR();
895}
896
897/****************************************************************************
898REMARKS:
899Handles opcode 0x0f,0xaf
900****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000901static void x86emuOp2_imul_R_RM(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000902{
903 int mod, rl, rh;
904 uint srcoffset;
905
906 START_OF_INSTR();
907 DECODE_PRINTF("IMUL\t");
908 FETCH_DECODE_MODRM(mod, rh, rl);
909 if (mod < 3) {
910 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
911 u32 *destreg;
912 u32 srcval;
913 u32 res_lo,res_hi;
914
915 destreg = DECODE_RM_LONG_REGISTER(rh);
916 DECODE_PRINTF(",");
917 srcoffset = decode_rmXX_address(mod, rl);
918 srcval = fetch_data_long(srcoffset);
919 TRACE_AND_STEP();
920 imul_long_direct(&res_lo,&res_hi,(s32)*destreg,(s32)srcval);
921 if (res_hi != 0) {
922 SET_FLAG(F_CF);
923 SET_FLAG(F_OF);
924 } else {
925 CLEAR_FLAG(F_CF);
926 CLEAR_FLAG(F_OF);
927 }
928 *destreg = (u32)res_lo;
929 } else {
930 u16 *destreg;
931 u16 srcval;
932 u32 res;
933
934 destreg = DECODE_RM_WORD_REGISTER(rh);
935 DECODE_PRINTF(",");
936 srcoffset = decode_rmXX_address(mod, rl);
937 srcval = fetch_data_word(srcoffset);
938 TRACE_AND_STEP();
939 res = (s16)*destreg * (s16)srcval;
940 if (res > 0xFFFF) {
941 SET_FLAG(F_CF);
942 SET_FLAG(F_OF);
943 } else {
944 CLEAR_FLAG(F_CF);
945 CLEAR_FLAG(F_OF);
946 }
947 *destreg = (u16)res;
948 }
949 } else { /* register to register */
950 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
951 u32 *destreg,*srcreg;
952 u32 res_lo,res_hi;
953
954 destreg = DECODE_RM_LONG_REGISTER(rh);
955 DECODE_PRINTF(",");
956 srcreg = DECODE_RM_LONG_REGISTER(rl);
957 TRACE_AND_STEP();
958 imul_long_direct(&res_lo,&res_hi,(s32)*destreg,(s32)*srcreg);
959 if (res_hi != 0) {
960 SET_FLAG(F_CF);
961 SET_FLAG(F_OF);
962 } else {
963 CLEAR_FLAG(F_CF);
964 CLEAR_FLAG(F_OF);
965 }
966 *destreg = (u32)res_lo;
967 } else {
968 u16 *destreg,*srcreg;
969 u32 res;
970
971 destreg = DECODE_RM_WORD_REGISTER(rh);
972 DECODE_PRINTF(",");
973 srcreg = DECODE_RM_WORD_REGISTER(rl);
974 res = (s16)*destreg * (s16)*srcreg;
975 if (res > 0xFFFF) {
976 SET_FLAG(F_CF);
977 SET_FLAG(F_OF);
978 } else {
979 CLEAR_FLAG(F_CF);
980 CLEAR_FLAG(F_OF);
981 }
982 *destreg = (u16)res;
983 }
984 }
985 DECODE_CLEAR_SEGOVR();
986 END_OF_INSTR();
987}
988
989/****************************************************************************
990REMARKS:
991Handles opcode 0x0f,0xb2
992****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +0000993static void x86emuOp2_lss_R_IMM(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000994{
995 int mod, rh, rl;
996 u16 *dstreg;
997 uint srcoffset;
998
999 START_OF_INSTR();
1000 DECODE_PRINTF("LSS\t");
1001 FETCH_DECODE_MODRM(mod, rh, rl);
1002 if (mod < 3) {
1003 dstreg = DECODE_RM_WORD_REGISTER(rh);
1004 DECODE_PRINTF(",");
1005 srcoffset = decode_rmXX_address(mod, rl);
1006 DECODE_PRINTF("\n");
1007 TRACE_AND_STEP();
1008 *dstreg = fetch_data_word(srcoffset);
1009 M.x86.R_SS = fetch_data_word(srcoffset + 2);
1010 } else { /* register to register */
1011 /* UNDEFINED! */
1012 TRACE_AND_STEP();
1013 }
1014 DECODE_CLEAR_SEGOVR();
1015 END_OF_INSTR();
1016}
1017
1018/****************************************************************************
1019REMARKS:
1020Handles opcode 0x0f,0xb3
1021****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001022static void x86emuOp2_btr_R(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001023{
1024 int mod, rl, rh;
1025 uint srcoffset;
1026 int bit,disp;
1027
1028 START_OF_INSTR();
1029 DECODE_PRINTF("BTR\t");
1030 FETCH_DECODE_MODRM(mod, rh, rl);
1031 if (mod < 3) {
1032 srcoffset = decode_rmXX_address(mod, rl);
1033 DECODE_PRINTF(",");
1034 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1035 u32 srcval,mask;
1036 u32 *shiftreg;
1037
1038 shiftreg = DECODE_RM_LONG_REGISTER(rh);
1039 TRACE_AND_STEP();
1040 bit = *shiftreg & 0x1F;
1041 disp = (s16)*shiftreg >> 5;
1042 srcval = fetch_data_long(srcoffset+disp);
1043 mask = (0x1 << bit);
1044 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1045 store_data_long(srcoffset+disp, srcval & ~mask);
1046 } else {
1047 u16 srcval,mask;
1048 u16 *shiftreg;
1049
1050 shiftreg = DECODE_RM_WORD_REGISTER(rh);
1051 TRACE_AND_STEP();
1052 bit = *shiftreg & 0xF;
1053 disp = (s16)*shiftreg >> 4;
1054 srcval = fetch_data_word(srcoffset+disp);
1055 mask = (u16)(0x1 << bit);
1056 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1057 store_data_word(srcoffset+disp, (u16)(srcval & ~mask));
1058 }
1059 } else { /* register to register */
1060 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1061 u32 *srcreg,*shiftreg;
1062 u32 mask;
1063
1064 srcreg = DECODE_RM_LONG_REGISTER(rl);
1065 DECODE_PRINTF(",");
1066 shiftreg = DECODE_RM_LONG_REGISTER(rh);
1067 TRACE_AND_STEP();
1068 bit = *shiftreg & 0x1F;
1069 mask = (0x1 << bit);
1070 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1071 *srcreg &= ~mask;
1072 } else {
1073 u16 *srcreg,*shiftreg;
1074 u16 mask;
1075
1076 srcreg = DECODE_RM_WORD_REGISTER(rl);
1077 DECODE_PRINTF(",");
1078 shiftreg = DECODE_RM_WORD_REGISTER(rh);
1079 TRACE_AND_STEP();
1080 bit = *shiftreg & 0xF;
1081 mask = (u16)(0x1 << bit);
1082 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1083 *srcreg &= ~mask;
1084 }
1085 }
1086 DECODE_CLEAR_SEGOVR();
1087 END_OF_INSTR();
1088}
1089
1090/****************************************************************************
1091REMARKS:
1092Handles opcode 0x0f,0xb4
1093****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001094static void x86emuOp2_lfs_R_IMM(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001095{
1096 int mod, rh, rl;
1097 u16 *dstreg;
1098 uint srcoffset;
1099
1100 START_OF_INSTR();
1101 DECODE_PRINTF("LFS\t");
1102 FETCH_DECODE_MODRM(mod, rh, rl);
1103 if (mod < 3) {
1104 dstreg = DECODE_RM_WORD_REGISTER(rh);
1105 DECODE_PRINTF(",");
1106 srcoffset = decode_rmXX_address(mod, rl);
1107 DECODE_PRINTF("\n");
1108 TRACE_AND_STEP();
1109 *dstreg = fetch_data_word(srcoffset);
1110 M.x86.R_FS = fetch_data_word(srcoffset + 2);
1111 } else { /* register to register */
1112 /* UNDEFINED! */
1113 TRACE_AND_STEP();
1114 }
1115 DECODE_CLEAR_SEGOVR();
1116 END_OF_INSTR();
1117}
1118
1119/****************************************************************************
1120REMARKS:
1121Handles opcode 0x0f,0xb5
1122****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001123static void x86emuOp2_lgs_R_IMM(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001124{
1125 int mod, rh, rl;
1126 u16 *dstreg;
1127 uint srcoffset;
1128
1129 START_OF_INSTR();
1130 DECODE_PRINTF("LGS\t");
1131 FETCH_DECODE_MODRM(mod, rh, rl);
1132 if (mod < 3) {
1133 dstreg = DECODE_RM_WORD_REGISTER(rh);
1134 DECODE_PRINTF(",");
1135 srcoffset = decode_rmXX_address(mod, rl);
1136 DECODE_PRINTF("\n");
1137 TRACE_AND_STEP();
1138 *dstreg = fetch_data_word(srcoffset);
1139 M.x86.R_GS = fetch_data_word(srcoffset + 2);
1140 } else { /* register to register */
1141 /* UNDEFINED! */
1142 TRACE_AND_STEP();
1143 }
1144 DECODE_CLEAR_SEGOVR();
1145 END_OF_INSTR();
1146}
1147
1148/****************************************************************************
1149REMARKS:
1150Handles opcode 0x0f,0xb6
1151****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001152static void x86emuOp2_movzx_byte_R_RM(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001153{
1154 int mod, rl, rh;
1155 uint srcoffset;
1156
1157 START_OF_INSTR();
1158 DECODE_PRINTF("MOVZX\t");
1159 FETCH_DECODE_MODRM(mod, rh, rl);
1160 if (mod < 3) {
1161 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1162 u32 *destreg;
1163 u32 srcval;
1164
1165 destreg = DECODE_RM_LONG_REGISTER(rh);
1166 DECODE_PRINTF(",");
1167 srcoffset = decode_rmXX_address(mod, rl);
1168 srcval = fetch_data_byte(srcoffset);
1169 DECODE_PRINTF("\n");
1170 TRACE_AND_STEP();
1171 *destreg = srcval;
1172 } else {
1173 u16 *destreg;
1174 u16 srcval;
1175
1176 destreg = DECODE_RM_WORD_REGISTER(rh);
1177 DECODE_PRINTF(",");
1178 srcoffset = decode_rmXX_address(mod, rl);
1179 srcval = fetch_data_byte(srcoffset);
1180 DECODE_PRINTF("\n");
1181 TRACE_AND_STEP();
1182 *destreg = srcval;
1183 }
1184 } else { /* register to register */
1185 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1186 u32 *destreg;
1187 u8 *srcreg;
1188
1189 destreg = DECODE_RM_LONG_REGISTER(rh);
1190 DECODE_PRINTF(",");
1191 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1192 DECODE_PRINTF("\n");
1193 TRACE_AND_STEP();
1194 *destreg = *srcreg;
1195 } else {
1196 u16 *destreg;
1197 u8 *srcreg;
1198
1199 destreg = DECODE_RM_WORD_REGISTER(rh);
1200 DECODE_PRINTF(",");
1201 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1202 DECODE_PRINTF("\n");
1203 TRACE_AND_STEP();
1204 *destreg = *srcreg;
1205 }
1206 }
1207 DECODE_CLEAR_SEGOVR();
1208 END_OF_INSTR();
1209}
1210
1211/****************************************************************************
1212REMARKS:
1213Handles opcode 0x0f,0xb7
1214****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001215static void x86emuOp2_movzx_word_R_RM(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001216{
1217 int mod, rl, rh;
1218 uint srcoffset;
1219 u32 *destreg;
1220 u32 srcval;
1221 u16 *srcreg;
1222
1223 START_OF_INSTR();
1224 DECODE_PRINTF("MOVZX\t");
1225 FETCH_DECODE_MODRM(mod, rh, rl);
1226 if (mod < 3) {
1227 destreg = DECODE_RM_LONG_REGISTER(rh);
1228 DECODE_PRINTF(",");
1229 srcoffset = decode_rmXX_address(mod, rl);
1230 srcval = fetch_data_word(srcoffset);
1231 DECODE_PRINTF("\n");
1232 TRACE_AND_STEP();
1233 *destreg = srcval;
1234 } else { /* register to register */
1235 destreg = DECODE_RM_LONG_REGISTER(rh);
1236 DECODE_PRINTF(",");
1237 srcreg = DECODE_RM_WORD_REGISTER(rl);
1238 DECODE_PRINTF("\n");
1239 TRACE_AND_STEP();
1240 *destreg = *srcreg;
1241 }
1242 DECODE_CLEAR_SEGOVR();
1243 END_OF_INSTR();
1244}
1245
1246/****************************************************************************
1247REMARKS:
1248Handles opcode 0x0f,0xba
1249****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001250static void x86emuOp2_btX_I(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001251{
1252 int mod, rl, rh;
1253 uint srcoffset;
1254 u8 shift;
1255 int bit;
1256
1257 START_OF_INSTR();
1258 FETCH_DECODE_MODRM(mod, rh, rl);
1259 switch (rh) {
1260 case 4:
1261 DECODE_PRINTF("BT\t");
1262 break;
1263 case 5:
1264 DECODE_PRINTF("BTS\t");
1265 break;
1266 case 6:
1267 DECODE_PRINTF("BTR\t");
1268 break;
1269 case 7:
1270 DECODE_PRINTF("BTC\t");
1271 break;
1272 default:
1273 DECODE_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n");
1274 TRACE_REGS();
Uwe Hermann01ce6012010-03-05 10:03:50 +00001275 printf("%04x:%04x: %02X%02X ILLEGAL EXTENDED X86 OPCODE EXTENSION!\n",
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001276 M.x86.R_CS, M.x86.R_IP-3,op2, (mod<<6)|(rh<<3)|rl);
1277 HALT_SYS();
1278 }
1279 if (mod < 3) {
1280
1281 srcoffset = decode_rmXX_address(mod, rl);
1282 shift = fetch_byte_imm();
1283 DECODE_PRINTF2(",%d\n", shift);
1284 TRACE_AND_STEP();
1285
1286 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1287 u32 srcval, mask;
1288
1289 bit = shift & 0x1F;
1290 srcval = fetch_data_long(srcoffset);
1291 mask = (0x1 << bit);
1292 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1293 switch (rh) {
1294 case 5:
1295 store_data_long(srcoffset, srcval | mask);
1296 break;
1297 case 6:
1298 store_data_long(srcoffset, srcval & ~mask);
1299 break;
1300 case 7:
1301 store_data_long(srcoffset, srcval ^ mask);
1302 break;
1303 default:
1304 break;
1305 }
1306 } else {
1307 u16 srcval, mask;
1308
1309 bit = shift & 0xF;
1310 srcval = fetch_data_word(srcoffset);
1311 mask = (0x1 << bit);
1312 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1313 switch (rh) {
1314 case 5:
1315 store_data_word(srcoffset, srcval | mask);
1316 break;
1317 case 6:
1318 store_data_word(srcoffset, srcval & ~mask);
1319 break;
1320 case 7:
1321 store_data_word(srcoffset, srcval ^ mask);
1322 break;
1323 default:
1324 break;
1325 }
1326 }
1327 } else { /* register to register */
1328 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1329 u32 *srcreg;
1330 u32 mask;
1331
1332 srcreg = DECODE_RM_LONG_REGISTER(rl);
1333 shift = fetch_byte_imm();
1334 DECODE_PRINTF2(",%d\n", shift);
1335 TRACE_AND_STEP();
1336 bit = shift & 0x1F;
1337 mask = (0x1 << bit);
1338 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1339 switch (rh) {
1340 case 5:
1341 *srcreg |= mask;
1342 break;
1343 case 6:
1344 *srcreg &= ~mask;
1345 break;
1346 case 7:
1347 *srcreg ^= mask;
1348 break;
1349 default:
1350 break;
1351 }
1352 } else {
1353 u16 *srcreg;
1354 u16 mask;
1355
1356 srcreg = DECODE_RM_WORD_REGISTER(rl);
1357 shift = fetch_byte_imm();
1358 DECODE_PRINTF2(",%d\n", shift);
1359 TRACE_AND_STEP();
1360 bit = shift & 0xF;
1361 mask = (0x1 << bit);
1362 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1363 switch (rh) {
1364 case 5:
1365 *srcreg |= mask;
1366 break;
1367 case 6:
1368 *srcreg &= ~mask;
1369 break;
1370 case 7:
1371 *srcreg ^= mask;
1372 break;
1373 default:
1374 break;
1375 }
1376 }
1377 }
1378 DECODE_CLEAR_SEGOVR();
1379 END_OF_INSTR();
1380}
1381
1382/****************************************************************************
1383REMARKS:
1384Handles opcode 0x0f,0xbb
1385****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001386static void x86emuOp2_btc_R(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001387{
1388 int mod, rl, rh;
1389 uint srcoffset;
1390 int bit,disp;
1391
1392 START_OF_INSTR();
1393 DECODE_PRINTF("BTC\t");
1394 FETCH_DECODE_MODRM(mod, rh, rl);
1395 if (mod < 3) {
1396 srcoffset = decode_rmXX_address(mod, rl);
1397 DECODE_PRINTF(",");
1398 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1399 u32 srcval,mask;
1400 u32 *shiftreg;
1401
1402 shiftreg = DECODE_RM_LONG_REGISTER(rh);
1403 TRACE_AND_STEP();
1404 bit = *shiftreg & 0x1F;
1405 disp = (s16)*shiftreg >> 5;
1406 srcval = fetch_data_long(srcoffset+disp);
1407 mask = (0x1 << bit);
1408 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1409 store_data_long(srcoffset+disp, srcval ^ mask);
1410 } else {
1411 u16 srcval,mask;
1412 u16 *shiftreg;
1413
1414 shiftreg = DECODE_RM_WORD_REGISTER(rh);
1415 TRACE_AND_STEP();
1416 bit = *shiftreg & 0xF;
1417 disp = (s16)*shiftreg >> 4;
1418 srcval = fetch_data_word(srcoffset+disp);
1419 mask = (u16)(0x1 << bit);
1420 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1421 store_data_word(srcoffset+disp, (u16)(srcval ^ mask));
1422 }
1423 } else { /* register to register */
1424 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1425 u32 *srcreg,*shiftreg;
1426 u32 mask;
1427
1428 srcreg = DECODE_RM_LONG_REGISTER(rl);
1429 DECODE_PRINTF(",");
1430 shiftreg = DECODE_RM_LONG_REGISTER(rh);
1431 TRACE_AND_STEP();
1432 bit = *shiftreg & 0x1F;
1433 mask = (0x1 << bit);
1434 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1435 *srcreg ^= mask;
1436 } else {
1437 u16 *srcreg,*shiftreg;
1438 u16 mask;
1439
1440 srcreg = DECODE_RM_WORD_REGISTER(rl);
1441 DECODE_PRINTF(",");
1442 shiftreg = DECODE_RM_WORD_REGISTER(rh);
1443 TRACE_AND_STEP();
1444 bit = *shiftreg & 0xF;
1445 mask = (u16)(0x1 << bit);
1446 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1447 *srcreg ^= mask;
1448 }
1449 }
1450 DECODE_CLEAR_SEGOVR();
1451 END_OF_INSTR();
1452}
1453
1454/****************************************************************************
1455REMARKS:
1456Handles opcode 0x0f,0xbc
1457****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001458static void x86emuOp2_bsf(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001459{
1460 int mod, rl, rh;
1461 uint srcoffset;
1462
1463 START_OF_INSTR();
1464 DECODE_PRINTF("BSF\n");
1465 FETCH_DECODE_MODRM(mod, rh, rl);
1466 if (mod < 3) {
1467 srcoffset = decode_rmXX_address(mod, rl);
1468 DECODE_PRINTF(",");
1469 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1470 u32 srcval, *dstreg;
1471
1472 dstreg = DECODE_RM_LONG_REGISTER(rh);
1473 TRACE_AND_STEP();
1474 srcval = fetch_data_long(srcoffset);
1475 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
1476 for(*dstreg = 0; *dstreg < 32; (*dstreg)++)
1477 if ((srcval >> *dstreg) & 1) break;
1478 } else {
1479 u16 srcval, *dstreg;
1480
1481 dstreg = DECODE_RM_WORD_REGISTER(rh);
1482 TRACE_AND_STEP();
1483 srcval = fetch_data_word(srcoffset);
1484 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
1485 for(*dstreg = 0; *dstreg < 16; (*dstreg)++)
1486 if ((srcval >> *dstreg) & 1) break;
1487 }
1488 } else { /* register to register */
1489 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1490 u32 *srcreg, *dstreg;
1491
1492 srcreg = DECODE_RM_LONG_REGISTER(rl);
1493 DECODE_PRINTF(",");
1494 dstreg = DECODE_RM_LONG_REGISTER(rh);
1495 TRACE_AND_STEP();
1496 CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF);
1497 for(*dstreg = 0; *dstreg < 32; (*dstreg)++)
1498 if ((*srcreg >> *dstreg) & 1) break;
1499 } else {
1500 u16 *srcreg, *dstreg;
1501
1502 srcreg = DECODE_RM_WORD_REGISTER(rl);
1503 DECODE_PRINTF(",");
1504 dstreg = DECODE_RM_WORD_REGISTER(rh);
1505 TRACE_AND_STEP();
1506 CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF);
1507 for(*dstreg = 0; *dstreg < 16; (*dstreg)++)
1508 if ((*srcreg >> *dstreg) & 1) break;
1509 }
1510 }
1511 DECODE_CLEAR_SEGOVR();
1512 END_OF_INSTR();
1513}
1514
1515/****************************************************************************
1516REMARKS:
1517Handles opcode 0x0f,0xbd
1518****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001519static void x86emuOp2_bsr(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001520{
1521 int mod, rl, rh;
1522 uint srcoffset;
1523
1524 START_OF_INSTR();
1525 DECODE_PRINTF("BSF\n");
1526 FETCH_DECODE_MODRM(mod, rh, rl);
1527 if (mod < 3) {
1528 srcoffset = decode_rmXX_address(mod, rl);
1529 DECODE_PRINTF(",");
1530 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1531 u32 srcval, *dstreg;
1532
1533 dstreg = DECODE_RM_LONG_REGISTER(rh);
1534 TRACE_AND_STEP();
1535 srcval = fetch_data_long(srcoffset);
1536 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
1537 for(*dstreg = 31; *dstreg > 0; (*dstreg)--)
1538 if ((srcval >> *dstreg) & 1) break;
1539 } else {
1540 u16 srcval, *dstreg;
1541
1542 dstreg = DECODE_RM_WORD_REGISTER(rh);
1543 TRACE_AND_STEP();
1544 srcval = fetch_data_word(srcoffset);
1545 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
1546 for(*dstreg = 15; *dstreg > 0; (*dstreg)--)
1547 if ((srcval >> *dstreg) & 1) break;
1548 }
1549 } else { /* register to register */
1550 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1551 u32 *srcreg, *dstreg;
1552
1553 srcreg = DECODE_RM_LONG_REGISTER(rl);
1554 DECODE_PRINTF(",");
1555 dstreg = DECODE_RM_LONG_REGISTER(rh);
1556 TRACE_AND_STEP();
1557 CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF);
1558 for(*dstreg = 31; *dstreg > 0; (*dstreg)--)
1559 if ((*srcreg >> *dstreg) & 1) break;
1560 } else {
1561 u16 *srcreg, *dstreg;
1562
1563 srcreg = DECODE_RM_WORD_REGISTER(rl);
1564 DECODE_PRINTF(",");
1565 dstreg = DECODE_RM_WORD_REGISTER(rh);
1566 TRACE_AND_STEP();
1567 CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF);
1568 for(*dstreg = 15; *dstreg > 0; (*dstreg)--)
1569 if ((*srcreg >> *dstreg) & 1) break;
1570 }
1571 }
1572 DECODE_CLEAR_SEGOVR();
1573 END_OF_INSTR();
1574}
1575
1576/****************************************************************************
1577REMARKS:
1578Handles opcode 0x0f,0xbe
1579****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001580static void x86emuOp2_movsx_byte_R_RM(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001581{
1582 int mod, rl, rh;
1583 uint srcoffset;
1584
1585 START_OF_INSTR();
1586 DECODE_PRINTF("MOVSX\t");
1587 FETCH_DECODE_MODRM(mod, rh, rl);
1588 if (mod < 3) {
1589 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1590 u32 *destreg;
1591 u32 srcval;
1592
1593 destreg = DECODE_RM_LONG_REGISTER(rh);
1594 DECODE_PRINTF(",");
1595 srcoffset = decode_rmXX_address(mod, rl);
1596 srcval = (s32)((s8)fetch_data_byte(srcoffset));
1597 DECODE_PRINTF("\n");
1598 TRACE_AND_STEP();
1599 *destreg = srcval;
1600 } else {
1601 u16 *destreg;
1602 u16 srcval;
1603
1604 destreg = DECODE_RM_WORD_REGISTER(rh);
1605 DECODE_PRINTF(",");
1606 srcoffset = decode_rmXX_address(mod, rl);
1607 srcval = (s16)((s8)fetch_data_byte(srcoffset));
1608 DECODE_PRINTF("\n");
1609 TRACE_AND_STEP();
1610 *destreg = srcval;
1611 }
1612 } else { /* register to register */
1613 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1614 u32 *destreg;
1615 u8 *srcreg;
1616
1617 destreg = DECODE_RM_LONG_REGISTER(rh);
1618 DECODE_PRINTF(",");
1619 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1620 DECODE_PRINTF("\n");
1621 TRACE_AND_STEP();
1622 *destreg = (s32)((s8)*srcreg);
1623 } else {
1624 u16 *destreg;
1625 u8 *srcreg;
1626
1627 destreg = DECODE_RM_WORD_REGISTER(rh);
1628 DECODE_PRINTF(",");
1629 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1630 DECODE_PRINTF("\n");
1631 TRACE_AND_STEP();
1632 *destreg = (s16)((s8)*srcreg);
1633 }
1634 }
1635 DECODE_CLEAR_SEGOVR();
1636 END_OF_INSTR();
1637}
1638
1639/****************************************************************************
1640REMARKS:
1641Handles opcode 0x0f,0xbf
1642****************************************************************************/
Stefan Reinauer7110d402009-11-03 14:59:43 +00001643static void x86emuOp2_movsx_word_R_RM(u8 X86EMU_UNUSED(op2))
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001644{
1645 int mod, rl, rh;
1646 uint srcoffset;
1647 u32 *destreg;
1648 u32 srcval;
1649 u16 *srcreg;
1650
1651 START_OF_INSTR();
1652 DECODE_PRINTF("MOVSX\t");
1653 FETCH_DECODE_MODRM(mod, rh, rl);
1654 if (mod < 3) {
1655 destreg = DECODE_RM_LONG_REGISTER(rh);
1656 DECODE_PRINTF(",");
1657 srcoffset = decode_rmXX_address(mod, rl);
1658 srcval = (s32)((s16)fetch_data_word(srcoffset));
1659 DECODE_PRINTF("\n");
1660 TRACE_AND_STEP();
1661 *destreg = srcval;
1662 } else { /* register to register */
1663 destreg = DECODE_RM_LONG_REGISTER(rh);
1664 DECODE_PRINTF(",");
1665 srcreg = DECODE_RM_WORD_REGISTER(rl);
1666 DECODE_PRINTF("\n");
1667 TRACE_AND_STEP();
1668 *destreg = (s32)((s16)*srcreg);
1669 }
1670 DECODE_CLEAR_SEGOVR();
1671 END_OF_INSTR();
1672}
1673
1674/***************************************************************************
1675 * Double byte operation code table:
1676 **************************************************************************/
1677void (*x86emu_optab2[256])(u8) =
1678{
1679/* 0x00 */ x86emuOp2_illegal_op, /* Group F (ring 0 PM) */
Stefan Reinauer7110d402009-11-03 14:59:43 +00001680/* 0x01 */ x86emuOp2_opc_01, /* Group G (ring 0 PM) */
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001681/* 0x02 */ x86emuOp2_illegal_op, /* lar (ring 0 PM) */
1682/* 0x03 */ x86emuOp2_illegal_op, /* lsl (ring 0 PM) */
1683/* 0x04 */ x86emuOp2_illegal_op,
1684/* 0x05 */ x86emuOp2_illegal_op, /* loadall (undocumented) */
1685/* 0x06 */ x86emuOp2_illegal_op, /* clts (ring 0 PM) */
1686/* 0x07 */ x86emuOp2_illegal_op, /* loadall (undocumented) */
Stefan Reinauer7110d402009-11-03 14:59:43 +00001687/* 0x08 */ x86emuOp2_invd, /* invd (ring 0 PM) */
1688/* 0x09 */ x86emuOp2_wbinvd, /* wbinvd (ring 0 PM) */
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001689/* 0x0a */ x86emuOp2_illegal_op,
1690/* 0x0b */ x86emuOp2_illegal_op,
1691/* 0x0c */ x86emuOp2_illegal_op,
1692/* 0x0d */ x86emuOp2_illegal_op,
1693/* 0x0e */ x86emuOp2_illegal_op,
1694/* 0x0f */ x86emuOp2_illegal_op,
1695
1696/* 0x10 */ x86emuOp2_illegal_op,
1697/* 0x11 */ x86emuOp2_illegal_op,
1698/* 0x12 */ x86emuOp2_illegal_op,
1699/* 0x13 */ x86emuOp2_illegal_op,
1700/* 0x14 */ x86emuOp2_illegal_op,
1701/* 0x15 */ x86emuOp2_illegal_op,
1702/* 0x16 */ x86emuOp2_illegal_op,
1703/* 0x17 */ x86emuOp2_illegal_op,
1704/* 0x18 */ x86emuOp2_illegal_op,
1705/* 0x19 */ x86emuOp2_illegal_op,
1706/* 0x1a */ x86emuOp2_illegal_op,
1707/* 0x1b */ x86emuOp2_illegal_op,
1708/* 0x1c */ x86emuOp2_illegal_op,
1709/* 0x1d */ x86emuOp2_illegal_op,
1710/* 0x1e */ x86emuOp2_illegal_op,
1711/* 0x1f */ x86emuOp2_illegal_op,
1712
1713/* 0x20 */ x86emuOp2_illegal_op, /* mov reg32,creg (ring 0 PM) */
1714/* 0x21 */ x86emuOp2_illegal_op, /* mov reg32,dreg (ring 0 PM) */
1715/* 0x22 */ x86emuOp2_illegal_op, /* mov creg,reg32 (ring 0 PM) */
1716/* 0x23 */ x86emuOp2_illegal_op, /* mov dreg,reg32 (ring 0 PM) */
1717/* 0x24 */ x86emuOp2_illegal_op, /* mov reg32,treg (ring 0 PM) */
1718/* 0x25 */ x86emuOp2_illegal_op,
1719/* 0x26 */ x86emuOp2_illegal_op, /* mov treg,reg32 (ring 0 PM) */
1720/* 0x27 */ x86emuOp2_illegal_op,
1721/* 0x28 */ x86emuOp2_illegal_op,
1722/* 0x29 */ x86emuOp2_illegal_op,
1723/* 0x2a */ x86emuOp2_illegal_op,
1724/* 0x2b */ x86emuOp2_illegal_op,
1725/* 0x2c */ x86emuOp2_illegal_op,
1726/* 0x2d */ x86emuOp2_illegal_op,
1727/* 0x2e */ x86emuOp2_illegal_op,
1728/* 0x2f */ x86emuOp2_illegal_op,
1729
Stefan Reinauer7110d402009-11-03 14:59:43 +00001730/* 0x30 */ x86emuOp2_wrmsr,
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001731/* 0x31 */ x86emuOp2_illegal_op,
Stefan Reinauer7110d402009-11-03 14:59:43 +00001732/* 0x32 */ x86emuOp2_rdmsr,
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001733/* 0x33 */ x86emuOp2_illegal_op,
1734/* 0x34 */ x86emuOp2_illegal_op,
1735/* 0x35 */ x86emuOp2_illegal_op,
1736/* 0x36 */ x86emuOp2_illegal_op,
1737/* 0x37 */ x86emuOp2_illegal_op,
1738/* 0x38 */ x86emuOp2_illegal_op,
1739/* 0x39 */ x86emuOp2_illegal_op,
1740/* 0x3a */ x86emuOp2_illegal_op,
1741/* 0x3b */ x86emuOp2_illegal_op,
1742/* 0x3c */ x86emuOp2_illegal_op,
1743/* 0x3d */ x86emuOp2_illegal_op,
1744/* 0x3e */ x86emuOp2_illegal_op,
1745/* 0x3f */ x86emuOp2_illegal_op,
1746
1747/* 0x40 */ x86emuOp2_illegal_op,
1748/* 0x41 */ x86emuOp2_illegal_op,
1749/* 0x42 */ x86emuOp2_illegal_op,
1750/* 0x43 */ x86emuOp2_illegal_op,
1751/* 0x44 */ x86emuOp2_illegal_op,
1752/* 0x45 */ x86emuOp2_illegal_op,
1753/* 0x46 */ x86emuOp2_illegal_op,
1754/* 0x47 */ x86emuOp2_illegal_op,
1755/* 0x48 */ x86emuOp2_illegal_op,
1756/* 0x49 */ x86emuOp2_illegal_op,
1757/* 0x4a */ x86emuOp2_illegal_op,
1758/* 0x4b */ x86emuOp2_illegal_op,
1759/* 0x4c */ x86emuOp2_illegal_op,
1760/* 0x4d */ x86emuOp2_illegal_op,
1761/* 0x4e */ x86emuOp2_illegal_op,
1762/* 0x4f */ x86emuOp2_illegal_op,
1763
1764/* 0x50 */ x86emuOp2_illegal_op,
1765/* 0x51 */ x86emuOp2_illegal_op,
1766/* 0x52 */ x86emuOp2_illegal_op,
1767/* 0x53 */ x86emuOp2_illegal_op,
1768/* 0x54 */ x86emuOp2_illegal_op,
1769/* 0x55 */ x86emuOp2_illegal_op,
1770/* 0x56 */ x86emuOp2_illegal_op,
1771/* 0x57 */ x86emuOp2_illegal_op,
1772/* 0x58 */ x86emuOp2_illegal_op,
1773/* 0x59 */ x86emuOp2_illegal_op,
1774/* 0x5a */ x86emuOp2_illegal_op,
1775/* 0x5b */ x86emuOp2_illegal_op,
1776/* 0x5c */ x86emuOp2_illegal_op,
1777/* 0x5d */ x86emuOp2_illegal_op,
1778/* 0x5e */ x86emuOp2_illegal_op,
1779/* 0x5f */ x86emuOp2_illegal_op,
1780
1781/* 0x60 */ x86emuOp2_illegal_op,
1782/* 0x61 */ x86emuOp2_illegal_op,
1783/* 0x62 */ x86emuOp2_illegal_op,
1784/* 0x63 */ x86emuOp2_illegal_op,
1785/* 0x64 */ x86emuOp2_illegal_op,
1786/* 0x65 */ x86emuOp2_illegal_op,
1787/* 0x66 */ x86emuOp2_illegal_op,
1788/* 0x67 */ x86emuOp2_illegal_op,
1789/* 0x68 */ x86emuOp2_illegal_op,
1790/* 0x69 */ x86emuOp2_illegal_op,
1791/* 0x6a */ x86emuOp2_illegal_op,
1792/* 0x6b */ x86emuOp2_illegal_op,
1793/* 0x6c */ x86emuOp2_illegal_op,
1794/* 0x6d */ x86emuOp2_illegal_op,
1795/* 0x6e */ x86emuOp2_illegal_op,
1796/* 0x6f */ x86emuOp2_illegal_op,
1797
1798/* 0x70 */ x86emuOp2_illegal_op,
1799/* 0x71 */ x86emuOp2_illegal_op,
1800/* 0x72 */ x86emuOp2_illegal_op,
1801/* 0x73 */ x86emuOp2_illegal_op,
1802/* 0x74 */ x86emuOp2_illegal_op,
1803/* 0x75 */ x86emuOp2_illegal_op,
1804/* 0x76 */ x86emuOp2_illegal_op,
1805/* 0x77 */ x86emuOp2_illegal_op,
1806/* 0x78 */ x86emuOp2_illegal_op,
1807/* 0x79 */ x86emuOp2_illegal_op,
1808/* 0x7a */ x86emuOp2_illegal_op,
1809/* 0x7b */ x86emuOp2_illegal_op,
1810/* 0x7c */ x86emuOp2_illegal_op,
1811/* 0x7d */ x86emuOp2_illegal_op,
1812/* 0x7e */ x86emuOp2_illegal_op,
1813/* 0x7f */ x86emuOp2_illegal_op,
1814
1815/* 0x80 */ x86emuOp2_long_jump,
1816/* 0x81 */ x86emuOp2_long_jump,
1817/* 0x82 */ x86emuOp2_long_jump,
1818/* 0x83 */ x86emuOp2_long_jump,
1819/* 0x84 */ x86emuOp2_long_jump,
1820/* 0x85 */ x86emuOp2_long_jump,
1821/* 0x86 */ x86emuOp2_long_jump,
1822/* 0x87 */ x86emuOp2_long_jump,
1823/* 0x88 */ x86emuOp2_long_jump,
1824/* 0x89 */ x86emuOp2_long_jump,
1825/* 0x8a */ x86emuOp2_long_jump,
1826/* 0x8b */ x86emuOp2_long_jump,
1827/* 0x8c */ x86emuOp2_long_jump,
1828/* 0x8d */ x86emuOp2_long_jump,
1829/* 0x8e */ x86emuOp2_long_jump,
1830/* 0x8f */ x86emuOp2_long_jump,
1831
1832/* 0x90 */ x86emuOp2_set_byte,
1833/* 0x91 */ x86emuOp2_set_byte,
1834/* 0x92 */ x86emuOp2_set_byte,
1835/* 0x93 */ x86emuOp2_set_byte,
1836/* 0x94 */ x86emuOp2_set_byte,
1837/* 0x95 */ x86emuOp2_set_byte,
1838/* 0x96 */ x86emuOp2_set_byte,
1839/* 0x97 */ x86emuOp2_set_byte,
1840/* 0x98 */ x86emuOp2_set_byte,
1841/* 0x99 */ x86emuOp2_set_byte,
1842/* 0x9a */ x86emuOp2_set_byte,
1843/* 0x9b */ x86emuOp2_set_byte,
1844/* 0x9c */ x86emuOp2_set_byte,
1845/* 0x9d */ x86emuOp2_set_byte,
1846/* 0x9e */ x86emuOp2_set_byte,
1847/* 0x9f */ x86emuOp2_set_byte,
1848
1849/* 0xa0 */ x86emuOp2_push_FS,
1850/* 0xa1 */ x86emuOp2_pop_FS,
Stefan Reinauer7110d402009-11-03 14:59:43 +00001851/* 0xa2 */ x86emuOp2_cpuid,
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001852/* 0xa3 */ x86emuOp2_bt_R,
1853/* 0xa4 */ x86emuOp2_shld_IMM,
1854/* 0xa5 */ x86emuOp2_shld_CL,
1855/* 0xa6 */ x86emuOp2_illegal_op,
1856/* 0xa7 */ x86emuOp2_illegal_op,
1857/* 0xa8 */ x86emuOp2_push_GS,
1858/* 0xa9 */ x86emuOp2_pop_GS,
1859/* 0xaa */ x86emuOp2_illegal_op,
Stefan Reinauer7110d402009-11-03 14:59:43 +00001860/* 0xab */ x86emuOp2_bts_R,
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001861/* 0xac */ x86emuOp2_shrd_IMM,
1862/* 0xad */ x86emuOp2_shrd_CL,
1863/* 0xae */ x86emuOp2_illegal_op,
1864/* 0xaf */ x86emuOp2_imul_R_RM,
1865
1866/* 0xb0 */ x86emuOp2_illegal_op, /* TODO: cmpxchg */
1867/* 0xb1 */ x86emuOp2_illegal_op, /* TODO: cmpxchg */
1868/* 0xb2 */ x86emuOp2_lss_R_IMM,
1869/* 0xb3 */ x86emuOp2_btr_R,
1870/* 0xb4 */ x86emuOp2_lfs_R_IMM,
1871/* 0xb5 */ x86emuOp2_lgs_R_IMM,
1872/* 0xb6 */ x86emuOp2_movzx_byte_R_RM,
1873/* 0xb7 */ x86emuOp2_movzx_word_R_RM,
1874/* 0xb8 */ x86emuOp2_illegal_op,
1875/* 0xb9 */ x86emuOp2_illegal_op,
1876/* 0xba */ x86emuOp2_btX_I,
1877/* 0xbb */ x86emuOp2_btc_R,
1878/* 0xbc */ x86emuOp2_bsf,
1879/* 0xbd */ x86emuOp2_bsr,
1880/* 0xbe */ x86emuOp2_movsx_byte_R_RM,
1881/* 0xbf */ x86emuOp2_movsx_word_R_RM,
1882
1883/* 0xc0 */ x86emuOp2_illegal_op, /* TODO: xadd */
1884/* 0xc1 */ x86emuOp2_illegal_op, /* TODO: xadd */
1885/* 0xc2 */ x86emuOp2_illegal_op,
1886/* 0xc3 */ x86emuOp2_illegal_op,
1887/* 0xc4 */ x86emuOp2_illegal_op,
1888/* 0xc5 */ x86emuOp2_illegal_op,
1889/* 0xc6 */ x86emuOp2_illegal_op,
1890/* 0xc7 */ x86emuOp2_illegal_op,
1891/* 0xc8 */ x86emuOp2_bswap,
1892/* 0xc9 */ x86emuOp2_bswap,
1893/* 0xca */ x86emuOp2_bswap,
1894/* 0xcb */ x86emuOp2_bswap,
1895/* 0xcc */ x86emuOp2_bswap,
1896/* 0xcd */ x86emuOp2_bswap,
1897/* 0xce */ x86emuOp2_bswap,
1898/* 0xcf */ x86emuOp2_bswap,
1899
1900/* 0xd0 */ x86emuOp2_illegal_op,
1901/* 0xd1 */ x86emuOp2_illegal_op,
1902/* 0xd2 */ x86emuOp2_illegal_op,
1903/* 0xd3 */ x86emuOp2_illegal_op,
1904/* 0xd4 */ x86emuOp2_illegal_op,
1905/* 0xd5 */ x86emuOp2_illegal_op,
1906/* 0xd6 */ x86emuOp2_illegal_op,
1907/* 0xd7 */ x86emuOp2_illegal_op,
1908/* 0xd8 */ x86emuOp2_illegal_op,
1909/* 0xd9 */ x86emuOp2_illegal_op,
1910/* 0xda */ x86emuOp2_illegal_op,
1911/* 0xdb */ x86emuOp2_illegal_op,
1912/* 0xdc */ x86emuOp2_illegal_op,
1913/* 0xdd */ x86emuOp2_illegal_op,
1914/* 0xde */ x86emuOp2_illegal_op,
1915/* 0xdf */ x86emuOp2_illegal_op,
1916
1917/* 0xe0 */ x86emuOp2_illegal_op,
1918/* 0xe1 */ x86emuOp2_illegal_op,
1919/* 0xe2 */ x86emuOp2_illegal_op,
1920/* 0xe3 */ x86emuOp2_illegal_op,
1921/* 0xe4 */ x86emuOp2_illegal_op,
1922/* 0xe5 */ x86emuOp2_illegal_op,
1923/* 0xe6 */ x86emuOp2_illegal_op,
1924/* 0xe7 */ x86emuOp2_illegal_op,
1925/* 0xe8 */ x86emuOp2_illegal_op,
1926/* 0xe9 */ x86emuOp2_illegal_op,
1927/* 0xea */ x86emuOp2_illegal_op,
1928/* 0xeb */ x86emuOp2_illegal_op,
1929/* 0xec */ x86emuOp2_illegal_op,
1930/* 0xed */ x86emuOp2_illegal_op,
1931/* 0xee */ x86emuOp2_illegal_op,
1932/* 0xef */ x86emuOp2_illegal_op,
1933
1934/* 0xf0 */ x86emuOp2_illegal_op,
1935/* 0xf1 */ x86emuOp2_illegal_op,
1936/* 0xf2 */ x86emuOp2_illegal_op,
1937/* 0xf3 */ x86emuOp2_illegal_op,
1938/* 0xf4 */ x86emuOp2_illegal_op,
1939/* 0xf5 */ x86emuOp2_illegal_op,
1940/* 0xf6 */ x86emuOp2_illegal_op,
1941/* 0xf7 */ x86emuOp2_illegal_op,
1942/* 0xf8 */ x86emuOp2_illegal_op,
1943/* 0xf9 */ x86emuOp2_illegal_op,
1944/* 0xfa */ x86emuOp2_illegal_op,
1945/* 0xfb */ x86emuOp2_illegal_op,
1946/* 0xfc */ x86emuOp2_illegal_op,
1947/* 0xfd */ x86emuOp2_illegal_op,
1948/* 0xfe */ x86emuOp2_illegal_op,
1949/* 0xff */ x86emuOp2_illegal_op,
1950};