blob: 59dbb422dd40d28595e0f77eef264e3a742f9b40 [file] [log] [blame]
Jason Jinece92f82007-07-06 08:34:56 +08001/****************************************************************************
2*
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003* Realmode X86 Emulator Library
Jason Jinece92f82007-07-06 08:34:56 +08004*
Kumar Gala4c2e3da2009-07-28 21:49:52 -05005* Copyright (C) 2007 Freescale Semiconductor, Inc.
Jason Jinece92f82007-07-06 08:34:56 +08006* Jason Jin <Jason.jin@freescale.com>
7*
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02008* Copyright (C) 1991-2004 SciTech Software, Inc.
9* Copyright (C) David Mosberger-Tang
10* Copyright (C) 1999 Egbert Eich
Jason Jinece92f82007-07-06 08:34:56 +080011*
12* ========================================================================
13*
14* Permission to use, copy, modify, distribute, and sell this software and
15* its documentation for any purpose is hereby granted without fee,
16* provided that the above copyright notice appear in all copies and that
17* both that copyright notice and this permission notice appear in
18* supporting documentation, and that the name of the authors not be used
19* in advertising or publicity pertaining to distribution of the software
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +020020* without specific, written prior permission. The authors makes no
Jason Jinece92f82007-07-06 08:34:56 +080021* representations about the suitability of this software for any purpose.
22* It is provided "as is" without express or implied warranty.
23*
24* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
25* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
26* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
27* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
28* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
29* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
30* PERFORMANCE OF THIS SOFTWARE.
31*
32* ========================================================================
33*
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +020034* Language: ANSI C
35* Environment: Any
36* Developer: Kendall Bennett
Jason Jinece92f82007-07-06 08:34:56 +080037*
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +020038* Description: This file includes subroutines to implement the decoding
39* and emulation of all the x86 extended two-byte processor
40* instructions.
Jason Jinece92f82007-07-06 08:34:56 +080041*
Jason Jinece92f82007-07-06 08:34:56 +080042****************************************************************************/
43
Michal Simek78cff502007-08-16 10:46:28 +020044#include <common.h>
Kumar Galad90a5b12011-11-23 06:31:04 +000045#include <linux/compiler.h>
Michal Simek5b4de932007-08-15 21:15:05 +020046#include "x86emu/x86emui.h"
47
Jason Jinece92f82007-07-06 08:34:56 +080048/*----------------------------- Implementation ----------------------------*/
49
50/****************************************************************************
51PARAMETERS:
52op1 - Instruction op code
53
54REMARKS:
55Handles illegal opcodes.
56****************************************************************************/
57void x86emuOp2_illegal_op(
58 u8 op2)
59{
60 START_OF_INSTR();
61 DECODE_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n");
62 TRACE_REGS();
63 printk("%04x:%04x: %02X ILLEGAL EXTENDED X86 OPCODE!\n",
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +020064 M.x86.R_CS, M.x86.R_IP-2,op2);
Jason Jinece92f82007-07-06 08:34:56 +080065 HALT_SYS();
66 END_OF_INSTR();
67}
68
69#define xorl(a,b) ((a) && !(b)) || (!(a) && (b))
70
71/****************************************************************************
72REMARKS:
73Handles opcode 0x0f,0x80-0x8F
74****************************************************************************/
75int x86emu_check_jump_condition(u8 op)
76{
77 switch (op) {
78 case 0x0:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +020079 DECODE_PRINTF("JO\t");
80 return ACCESS_FLAG(F_OF);
Jason Jinece92f82007-07-06 08:34:56 +080081 case 0x1:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +020082 DECODE_PRINTF("JNO\t");
83 return !ACCESS_FLAG(F_OF);
84 break;
Jason Jinece92f82007-07-06 08:34:56 +080085 case 0x2:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +020086 DECODE_PRINTF("JB\t");
87 return ACCESS_FLAG(F_CF);
88 break;
Jason Jinece92f82007-07-06 08:34:56 +080089 case 0x3:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +020090 DECODE_PRINTF("JNB\t");
91 return !ACCESS_FLAG(F_CF);
92 break;
Jason Jinece92f82007-07-06 08:34:56 +080093 case 0x4:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +020094 DECODE_PRINTF("JZ\t");
95 return ACCESS_FLAG(F_ZF);
96 break;
Jason Jinece92f82007-07-06 08:34:56 +080097 case 0x5:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +020098 DECODE_PRINTF("JNZ\t");
99 return !ACCESS_FLAG(F_ZF);
100 break;
Jason Jinece92f82007-07-06 08:34:56 +0800101 case 0x6:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200102 DECODE_PRINTF("JBE\t");
103 return ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF);
104 break;
Jason Jinece92f82007-07-06 08:34:56 +0800105 case 0x7:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200106 DECODE_PRINTF("JNBE\t");
107 return !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
108 break;
Jason Jinece92f82007-07-06 08:34:56 +0800109 case 0x8:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200110 DECODE_PRINTF("JS\t");
111 return ACCESS_FLAG(F_SF);
112 break;
Jason Jinece92f82007-07-06 08:34:56 +0800113 case 0x9:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200114 DECODE_PRINTF("JNS\t");
115 return !ACCESS_FLAG(F_SF);
116 break;
Jason Jinece92f82007-07-06 08:34:56 +0800117 case 0xa:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200118 DECODE_PRINTF("JP\t");
119 return ACCESS_FLAG(F_PF);
120 break;
Jason Jinece92f82007-07-06 08:34:56 +0800121 case 0xb:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200122 DECODE_PRINTF("JNP\t");
123 return !ACCESS_FLAG(F_PF);
124 break;
Jason Jinece92f82007-07-06 08:34:56 +0800125 case 0xc:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200126 DECODE_PRINTF("JL\t");
127 return xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
128 break;
Jason Jinece92f82007-07-06 08:34:56 +0800129 case 0xd:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200130 DECODE_PRINTF("JNL\t");
131 return !xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
132 break;
Jason Jinece92f82007-07-06 08:34:56 +0800133 case 0xe:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200134 DECODE_PRINTF("JLE\t");
135 return (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
136 ACCESS_FLAG(F_ZF));
137 break;
Jason Jinece92f82007-07-06 08:34:56 +0800138 default:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200139 DECODE_PRINTF("JNLE\t");
140 return !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
141 ACCESS_FLAG(F_ZF));
Jason Jinece92f82007-07-06 08:34:56 +0800142 }
143}
144
145void x86emuOp2_long_jump(u8 op2)
146{
147 s32 target;
148 int cond;
149
150 /* conditional jump to word offset. */
151 START_OF_INSTR();
152 cond = x86emu_check_jump_condition(op2 & 0xF);
153 target = (s16) fetch_word_imm();
154 target += (s16) M.x86.R_IP;
155 DECODE_PRINTF2("%04x\n", target);
156 TRACE_AND_STEP();
157 if (cond)
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200158 M.x86.R_IP = (u16)target;
Jason Jinece92f82007-07-06 08:34:56 +0800159 DECODE_CLEAR_SEGOVR();
160 END_OF_INSTR();
161}
162
163/****************************************************************************
164REMARKS:
165Handles opcode 0x0f,0x90-0x9F
166****************************************************************************/
167void x86emuOp2_set_byte(u8 op2)
168{
169 int mod, rl, rh;
170 uint destoffset;
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200171 u8 *destreg;
Kumar Galad90a5b12011-11-23 06:31:04 +0000172 __maybe_unused char *name = 0;
Jason Jinece92f82007-07-06 08:34:56 +0800173 int cond = 0;
174
175 START_OF_INSTR();
176 switch (op2) {
177 case 0x90:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200178 name = "SETO\t";
179 cond = ACCESS_FLAG(F_OF);
180 break;
Jason Jinece92f82007-07-06 08:34:56 +0800181 case 0x91:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200182 name = "SETNO\t";
183 cond = !ACCESS_FLAG(F_OF);
184 break;
Jason Jinece92f82007-07-06 08:34:56 +0800185 case 0x92:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200186 name = "SETB\t";
187 cond = ACCESS_FLAG(F_CF);
188 break;
Jason Jinece92f82007-07-06 08:34:56 +0800189 case 0x93:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200190 name = "SETNB\t";
191 cond = !ACCESS_FLAG(F_CF);
192 break;
Jason Jinece92f82007-07-06 08:34:56 +0800193 case 0x94:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200194 name = "SETZ\t";
195 cond = ACCESS_FLAG(F_ZF);
196 break;
Jason Jinece92f82007-07-06 08:34:56 +0800197 case 0x95:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200198 name = "SETNZ\t";
199 cond = !ACCESS_FLAG(F_ZF);
200 break;
Jason Jinece92f82007-07-06 08:34:56 +0800201 case 0x96:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200202 name = "SETBE\t";
203 cond = ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF);
204 break;
Jason Jinece92f82007-07-06 08:34:56 +0800205 case 0x97:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200206 name = "SETNBE\t";
207 cond = !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
208 break;
Jason Jinece92f82007-07-06 08:34:56 +0800209 case 0x98:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200210 name = "SETS\t";
211 cond = ACCESS_FLAG(F_SF);
212 break;
Jason Jinece92f82007-07-06 08:34:56 +0800213 case 0x99:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200214 name = "SETNS\t";
215 cond = !ACCESS_FLAG(F_SF);
216 break;
Jason Jinece92f82007-07-06 08:34:56 +0800217 case 0x9a:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200218 name = "SETP\t";
219 cond = ACCESS_FLAG(F_PF);
220 break;
Jason Jinece92f82007-07-06 08:34:56 +0800221 case 0x9b:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200222 name = "SETNP\t";
223 cond = !ACCESS_FLAG(F_PF);
224 break;
Jason Jinece92f82007-07-06 08:34:56 +0800225 case 0x9c:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200226 name = "SETL\t";
227 cond = xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
228 break;
Jason Jinece92f82007-07-06 08:34:56 +0800229 case 0x9d:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200230 name = "SETNL\t";
231 cond = !xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
232 break;
Jason Jinece92f82007-07-06 08:34:56 +0800233 case 0x9e:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200234 name = "SETLE\t";
235 cond = (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
236 ACCESS_FLAG(F_ZF));
237 break;
Jason Jinece92f82007-07-06 08:34:56 +0800238 case 0x9f:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200239 name = "SETNLE\t";
240 cond = !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
241 ACCESS_FLAG(F_ZF));
242 break;
Jason Jinece92f82007-07-06 08:34:56 +0800243 }
244 DECODE_PRINTF(name);
245 FETCH_DECODE_MODRM(mod, rh, rl);
246 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200247 destoffset = decode_rmXX_address(mod, rl);
248 TRACE_AND_STEP();
249 store_data_byte(destoffset, cond ? 0x01 : 0x00);
250 } else { /* register to register */
251 destreg = DECODE_RM_BYTE_REGISTER(rl);
252 TRACE_AND_STEP();
253 *destreg = cond ? 0x01 : 0x00;
Jason Jinece92f82007-07-06 08:34:56 +0800254 }
255 DECODE_CLEAR_SEGOVR();
256 END_OF_INSTR();
257}
258
259/****************************************************************************
260REMARKS:
261Handles opcode 0x0f,0xa0
262****************************************************************************/
263void x86emuOp2_push_FS(u8 X86EMU_UNUSED(op2))
264{
265 START_OF_INSTR();
266 DECODE_PRINTF("PUSH\tFS\n");
267 TRACE_AND_STEP();
268 push_word(M.x86.R_FS);
269 DECODE_CLEAR_SEGOVR();
270 END_OF_INSTR();
271}
272
273/****************************************************************************
274REMARKS:
275Handles opcode 0x0f,0xa1
276****************************************************************************/
277void x86emuOp2_pop_FS(u8 X86EMU_UNUSED(op2))
278{
279 START_OF_INSTR();
280 DECODE_PRINTF("POP\tFS\n");
281 TRACE_AND_STEP();
282 M.x86.R_FS = pop_word();
283 DECODE_CLEAR_SEGOVR();
284 END_OF_INSTR();
285}
286
287/****************************************************************************
288REMARKS:
289Handles opcode 0x0f,0xa3
290****************************************************************************/
291void x86emuOp2_bt_R(u8 X86EMU_UNUSED(op2))
292{
293 int mod, rl, rh;
294 uint srcoffset;
295 int bit,disp;
296
297 START_OF_INSTR();
298 DECODE_PRINTF("BT\t");
299 FETCH_DECODE_MODRM(mod, rh, rl);
300 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200301 srcoffset = decode_rmXX_address(mod, rl);
302 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
303 u32 srcval;
304 u32 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800305
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200306 DECODE_PRINTF(",");
307 shiftreg = DECODE_RM_LONG_REGISTER(rh);
308 TRACE_AND_STEP();
309 bit = *shiftreg & 0x1F;
310 disp = (s16)*shiftreg >> 5;
311 srcval = fetch_data_long(srcoffset+disp);
312 CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF);
313 } else {
314 u16 srcval;
315 u16 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800316
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200317 DECODE_PRINTF(",");
318 shiftreg = DECODE_RM_WORD_REGISTER(rh);
319 TRACE_AND_STEP();
320 bit = *shiftreg & 0xF;
321 disp = (s16)*shiftreg >> 4;
322 srcval = fetch_data_word(srcoffset+disp);
323 CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF);
324 }
325 } else { /* register to register */
326 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
327 u32 *srcreg,*shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800328
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200329 srcreg = DECODE_RM_LONG_REGISTER(rl);
330 DECODE_PRINTF(",");
331 shiftreg = DECODE_RM_LONG_REGISTER(rh);
332 TRACE_AND_STEP();
333 bit = *shiftreg & 0x1F;
334 CONDITIONAL_SET_FLAG(*srcreg & (0x1 << bit),F_CF);
335 } else {
336 u16 *srcreg,*shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800337
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200338 srcreg = DECODE_RM_WORD_REGISTER(rl);
339 DECODE_PRINTF(",");
340 shiftreg = DECODE_RM_WORD_REGISTER(rh);
341 TRACE_AND_STEP();
342 bit = *shiftreg & 0xF;
343 CONDITIONAL_SET_FLAG(*srcreg & (0x1 << bit),F_CF);
344 }
Jason Jinece92f82007-07-06 08:34:56 +0800345 }
346 DECODE_CLEAR_SEGOVR();
347 END_OF_INSTR();
348}
349
350/****************************************************************************
351REMARKS:
352Handles opcode 0x0f,0xa4
353****************************************************************************/
354void x86emuOp2_shld_IMM(u8 X86EMU_UNUSED(op2))
355{
356 int mod, rl, rh;
357 uint destoffset;
358 u8 shift;
359
360 START_OF_INSTR();
361 DECODE_PRINTF("SHLD\t");
362 FETCH_DECODE_MODRM(mod, rh, rl);
363 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200364 destoffset = decode_rmXX_address(mod, rl);
365 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
366 u32 destval;
367 u32 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800368
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200369 DECODE_PRINTF(",");
370 shiftreg = DECODE_RM_LONG_REGISTER(rh);
371 DECODE_PRINTF(",");
372 shift = fetch_byte_imm();
373 DECODE_PRINTF2("%d\n", shift);
374 TRACE_AND_STEP();
375 destval = fetch_data_long(destoffset);
376 destval = shld_long(destval,*shiftreg,shift);
377 store_data_long(destoffset, destval);
378 } else {
379 u16 destval;
380 u16 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800381
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200382 DECODE_PRINTF(",");
383 shiftreg = DECODE_RM_WORD_REGISTER(rh);
384 DECODE_PRINTF(",");
385 shift = fetch_byte_imm();
386 DECODE_PRINTF2("%d\n", shift);
387 TRACE_AND_STEP();
388 destval = fetch_data_word(destoffset);
389 destval = shld_word(destval,*shiftreg,shift);
390 store_data_word(destoffset, destval);
391 }
392 } else { /* register to register */
393 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
394 u32 *destreg,*shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800395
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200396 destreg = DECODE_RM_LONG_REGISTER(rl);
397 DECODE_PRINTF(",");
398 shiftreg = DECODE_RM_LONG_REGISTER(rh);
399 DECODE_PRINTF(",");
400 shift = fetch_byte_imm();
401 DECODE_PRINTF2("%d\n", shift);
402 TRACE_AND_STEP();
403 *destreg = shld_long(*destreg,*shiftreg,shift);
404 } else {
405 u16 *destreg,*shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800406
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200407 destreg = DECODE_RM_WORD_REGISTER(rl);
408 DECODE_PRINTF(",");
409 shiftreg = DECODE_RM_WORD_REGISTER(rh);
410 DECODE_PRINTF(",");
411 shift = fetch_byte_imm();
412 DECODE_PRINTF2("%d\n", shift);
413 TRACE_AND_STEP();
414 *destreg = shld_word(*destreg,*shiftreg,shift);
415 }
Jason Jinece92f82007-07-06 08:34:56 +0800416 }
417 DECODE_CLEAR_SEGOVR();
418 END_OF_INSTR();
419}
420
421/****************************************************************************
422REMARKS:
423Handles opcode 0x0f,0xa5
424****************************************************************************/
425void x86emuOp2_shld_CL(u8 X86EMU_UNUSED(op2))
426{
427 int mod, rl, rh;
428 uint destoffset;
429
430 START_OF_INSTR();
431 DECODE_PRINTF("SHLD\t");
432 FETCH_DECODE_MODRM(mod, rh, rl);
433 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200434 destoffset = decode_rmXX_address(mod, rl);
435 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
436 u32 destval;
437 u32 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800438
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200439 DECODE_PRINTF(",");
440 shiftreg = DECODE_RM_LONG_REGISTER(rh);
441 DECODE_PRINTF(",CL\n");
442 TRACE_AND_STEP();
443 destval = fetch_data_long(destoffset);
444 destval = shld_long(destval,*shiftreg,M.x86.R_CL);
445 store_data_long(destoffset, destval);
446 } else {
447 u16 destval;
448 u16 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800449
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200450 DECODE_PRINTF(",");
451 shiftreg = DECODE_RM_WORD_REGISTER(rh);
452 DECODE_PRINTF(",CL\n");
453 TRACE_AND_STEP();
454 destval = fetch_data_word(destoffset);
455 destval = shld_word(destval,*shiftreg,M.x86.R_CL);
456 store_data_word(destoffset, destval);
457 }
458 } else { /* register to register */
459 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
460 u32 *destreg,*shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800461
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200462 destreg = DECODE_RM_LONG_REGISTER(rl);
463 DECODE_PRINTF(",");
464 shiftreg = DECODE_RM_LONG_REGISTER(rh);
465 DECODE_PRINTF(",CL\n");
466 TRACE_AND_STEP();
467 *destreg = shld_long(*destreg,*shiftreg,M.x86.R_CL);
468 } else {
469 u16 *destreg,*shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800470
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200471 destreg = DECODE_RM_WORD_REGISTER(rl);
472 DECODE_PRINTF(",");
473 shiftreg = DECODE_RM_WORD_REGISTER(rh);
474 DECODE_PRINTF(",CL\n");
475 TRACE_AND_STEP();
476 *destreg = shld_word(*destreg,*shiftreg,M.x86.R_CL);
477 }
Jason Jinece92f82007-07-06 08:34:56 +0800478 }
479 DECODE_CLEAR_SEGOVR();
480 END_OF_INSTR();
481}
482
483/****************************************************************************
484REMARKS:
485Handles opcode 0x0f,0xa8
486****************************************************************************/
487void x86emuOp2_push_GS(u8 X86EMU_UNUSED(op2))
488{
489 START_OF_INSTR();
490 DECODE_PRINTF("PUSH\tGS\n");
491 TRACE_AND_STEP();
492 push_word(M.x86.R_GS);
493 DECODE_CLEAR_SEGOVR();
494 END_OF_INSTR();
495}
496
497/****************************************************************************
498REMARKS:
499Handles opcode 0x0f,0xa9
500****************************************************************************/
501void x86emuOp2_pop_GS(u8 X86EMU_UNUSED(op2))
502{
503 START_OF_INSTR();
504 DECODE_PRINTF("POP\tGS\n");
505 TRACE_AND_STEP();
506 M.x86.R_GS = pop_word();
507 DECODE_CLEAR_SEGOVR();
508 END_OF_INSTR();
509}
510
511/****************************************************************************
512REMARKS:
513Handles opcode 0x0f,0xaa
514****************************************************************************/
515void x86emuOp2_bts_R(u8 X86EMU_UNUSED(op2))
516{
517 int mod, rl, rh;
518 uint srcoffset;
519 int bit,disp;
520
521 START_OF_INSTR();
522 DECODE_PRINTF("BTS\t");
523 FETCH_DECODE_MODRM(mod, rh, rl);
524 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200525 srcoffset = decode_rmXX_address(mod, rl);
526 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
527 u32 srcval,mask;
528 u32 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800529
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200530 DECODE_PRINTF(",");
531 shiftreg = DECODE_RM_LONG_REGISTER(rh);
532 TRACE_AND_STEP();
533 bit = *shiftreg & 0x1F;
534 disp = (s16)*shiftreg >> 5;
535 srcval = fetch_data_long(srcoffset+disp);
536 mask = (0x1 << bit);
537 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
538 store_data_long(srcoffset+disp, srcval | mask);
539 } else {
540 u16 srcval,mask;
541 u16 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800542
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200543 DECODE_PRINTF(",");
544 shiftreg = DECODE_RM_WORD_REGISTER(rh);
545 TRACE_AND_STEP();
546 bit = *shiftreg & 0xF;
547 disp = (s16)*shiftreg >> 4;
548 srcval = fetch_data_word(srcoffset+disp);
549 mask = (u16)(0x1 << bit);
550 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
551 store_data_word(srcoffset+disp, srcval | mask);
552 }
553 } else { /* register to register */
554 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
555 u32 *srcreg,*shiftreg;
556 u32 mask;
Jason Jinece92f82007-07-06 08:34:56 +0800557
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200558 srcreg = DECODE_RM_LONG_REGISTER(rl);
559 DECODE_PRINTF(",");
560 shiftreg = DECODE_RM_LONG_REGISTER(rh);
561 TRACE_AND_STEP();
562 bit = *shiftreg & 0x1F;
563 mask = (0x1 << bit);
564 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
565 *srcreg |= mask;
566 } else {
567 u16 *srcreg,*shiftreg;
568 u16 mask;
Jason Jinece92f82007-07-06 08:34:56 +0800569
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200570 srcreg = DECODE_RM_WORD_REGISTER(rl);
571 DECODE_PRINTF(",");
572 shiftreg = DECODE_RM_WORD_REGISTER(rh);
573 TRACE_AND_STEP();
574 bit = *shiftreg & 0xF;
575 mask = (u16)(0x1 << bit);
576 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
577 *srcreg |= mask;
578 }
Jason Jinece92f82007-07-06 08:34:56 +0800579 }
580 DECODE_CLEAR_SEGOVR();
581 END_OF_INSTR();
582}
583
584/****************************************************************************
585REMARKS:
586Handles opcode 0x0f,0xac
587****************************************************************************/
588void x86emuOp2_shrd_IMM(u8 X86EMU_UNUSED(op2))
589{
590 int mod, rl, rh;
591 uint destoffset;
592 u8 shift;
593
594 START_OF_INSTR();
595 DECODE_PRINTF("SHLD\t");
596 FETCH_DECODE_MODRM(mod, rh, rl);
597 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200598 destoffset = decode_rmXX_address(mod, rl);
599 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
600 u32 destval;
601 u32 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800602
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200603 DECODE_PRINTF(",");
604 shiftreg = DECODE_RM_LONG_REGISTER(rh);
605 DECODE_PRINTF(",");
606 shift = fetch_byte_imm();
607 DECODE_PRINTF2("%d\n", shift);
608 TRACE_AND_STEP();
609 destval = fetch_data_long(destoffset);
610 destval = shrd_long(destval,*shiftreg,shift);
611 store_data_long(destoffset, destval);
612 } else {
613 u16 destval;
614 u16 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800615
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200616 DECODE_PRINTF(",");
617 shiftreg = DECODE_RM_WORD_REGISTER(rh);
618 DECODE_PRINTF(",");
619 shift = fetch_byte_imm();
620 DECODE_PRINTF2("%d\n", shift);
621 TRACE_AND_STEP();
622 destval = fetch_data_word(destoffset);
623 destval = shrd_word(destval,*shiftreg,shift);
624 store_data_word(destoffset, destval);
625 }
626 } else { /* register to register */
627 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
628 u32 *destreg,*shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800629
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200630 destreg = DECODE_RM_LONG_REGISTER(rl);
631 DECODE_PRINTF(",");
632 shiftreg = DECODE_RM_LONG_REGISTER(rh);
633 DECODE_PRINTF(",");
634 shift = fetch_byte_imm();
635 DECODE_PRINTF2("%d\n", shift);
636 TRACE_AND_STEP();
637 *destreg = shrd_long(*destreg,*shiftreg,shift);
638 } else {
639 u16 *destreg,*shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800640
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200641 destreg = DECODE_RM_WORD_REGISTER(rl);
642 DECODE_PRINTF(",");
643 shiftreg = DECODE_RM_WORD_REGISTER(rh);
644 DECODE_PRINTF(",");
645 shift = fetch_byte_imm();
646 DECODE_PRINTF2("%d\n", shift);
647 TRACE_AND_STEP();
648 *destreg = shrd_word(*destreg,*shiftreg,shift);
649 }
Jason Jinece92f82007-07-06 08:34:56 +0800650 }
651 DECODE_CLEAR_SEGOVR();
652 END_OF_INSTR();
653}
654
655/****************************************************************************
656REMARKS:
657Handles opcode 0x0f,0xad
658****************************************************************************/
659void x86emuOp2_shrd_CL(u8 X86EMU_UNUSED(op2))
660{
661 int mod, rl, rh;
662 uint destoffset;
663
664 START_OF_INSTR();
665 DECODE_PRINTF("SHLD\t");
666 FETCH_DECODE_MODRM(mod, rh, rl);
667 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200668 destoffset = decode_rmXX_address(mod, rl);
669 DECODE_PRINTF(",");
670 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
671 u32 destval;
672 u32 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800673
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200674 shiftreg = DECODE_RM_LONG_REGISTER(rh);
675 DECODE_PRINTF(",CL\n");
676 TRACE_AND_STEP();
677 destval = fetch_data_long(destoffset);
678 destval = shrd_long(destval,*shiftreg,M.x86.R_CL);
679 store_data_long(destoffset, destval);
680 } else {
681 u16 destval;
682 u16 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800683
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200684 shiftreg = DECODE_RM_WORD_REGISTER(rh);
685 DECODE_PRINTF(",CL\n");
686 TRACE_AND_STEP();
687 destval = fetch_data_word(destoffset);
688 destval = shrd_word(destval,*shiftreg,M.x86.R_CL);
689 store_data_word(destoffset, destval);
690 }
691 } else { /* register to register */
692 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
693 u32 *destreg,*shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800694
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200695 destreg = DECODE_RM_LONG_REGISTER(rl);
696 DECODE_PRINTF(",");
697 shiftreg = DECODE_RM_LONG_REGISTER(rh);
698 DECODE_PRINTF(",CL\n");
699 TRACE_AND_STEP();
700 *destreg = shrd_long(*destreg,*shiftreg,M.x86.R_CL);
701 } else {
702 u16 *destreg,*shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800703
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200704 destreg = DECODE_RM_WORD_REGISTER(rl);
705 DECODE_PRINTF(",");
706 shiftreg = DECODE_RM_WORD_REGISTER(rh);
707 DECODE_PRINTF(",CL\n");
708 TRACE_AND_STEP();
709 *destreg = shrd_word(*destreg,*shiftreg,M.x86.R_CL);
710 }
Jason Jinece92f82007-07-06 08:34:56 +0800711 }
712 DECODE_CLEAR_SEGOVR();
713 END_OF_INSTR();
714}
715
716/****************************************************************************
717REMARKS:
718Handles opcode 0x0f,0xaf
719****************************************************************************/
720void x86emuOp2_imul_R_RM(u8 X86EMU_UNUSED(op2))
721{
722 int mod, rl, rh;
723 uint srcoffset;
724
725 START_OF_INSTR();
726 DECODE_PRINTF("IMUL\t");
727 FETCH_DECODE_MODRM(mod, rh, rl);
728 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200729 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
730 u32 *destreg;
731 u32 srcval;
732 u32 res_lo,res_hi;
Jason Jinece92f82007-07-06 08:34:56 +0800733
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200734 destreg = DECODE_RM_LONG_REGISTER(rh);
735 DECODE_PRINTF(",");
736 srcoffset = decode_rmXX_address(mod, rl);
737 srcval = fetch_data_long(srcoffset);
738 TRACE_AND_STEP();
739 imul_long_direct(&res_lo,&res_hi,(s32)*destreg,(s32)srcval);
740 if (res_hi != 0) {
741 SET_FLAG(F_CF);
742 SET_FLAG(F_OF);
743 } else {
744 CLEAR_FLAG(F_CF);
745 CLEAR_FLAG(F_OF);
746 }
747 *destreg = (u32)res_lo;
748 } else {
749 u16 *destreg;
750 u16 srcval;
751 u32 res;
Jason Jinece92f82007-07-06 08:34:56 +0800752
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200753 destreg = DECODE_RM_WORD_REGISTER(rh);
754 DECODE_PRINTF(",");
755 srcoffset = decode_rmXX_address(mod, rl);
756 srcval = fetch_data_word(srcoffset);
757 TRACE_AND_STEP();
758 res = (s16)*destreg * (s16)srcval;
759 if (res > 0xFFFF) {
760 SET_FLAG(F_CF);
761 SET_FLAG(F_OF);
762 } else {
763 CLEAR_FLAG(F_CF);
764 CLEAR_FLAG(F_OF);
765 }
766 *destreg = (u16)res;
767 }
768 } else { /* register to register */
769 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
770 u32 *destreg,*srcreg;
771 u32 res_lo,res_hi;
Jason Jinece92f82007-07-06 08:34:56 +0800772
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200773 destreg = DECODE_RM_LONG_REGISTER(rh);
774 DECODE_PRINTF(",");
775 srcreg = DECODE_RM_LONG_REGISTER(rl);
776 TRACE_AND_STEP();
777 imul_long_direct(&res_lo,&res_hi,(s32)*destreg,(s32)*srcreg);
778 if (res_hi != 0) {
779 SET_FLAG(F_CF);
780 SET_FLAG(F_OF);
781 } else {
782 CLEAR_FLAG(F_CF);
783 CLEAR_FLAG(F_OF);
784 }
785 *destreg = (u32)res_lo;
786 } else {
787 u16 *destreg,*srcreg;
788 u32 res;
Jason Jinece92f82007-07-06 08:34:56 +0800789
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200790 destreg = DECODE_RM_WORD_REGISTER(rh);
791 DECODE_PRINTF(",");
792 srcreg = DECODE_RM_WORD_REGISTER(rl);
793 res = (s16)*destreg * (s16)*srcreg;
794 if (res > 0xFFFF) {
795 SET_FLAG(F_CF);
796 SET_FLAG(F_OF);
797 } else {
798 CLEAR_FLAG(F_CF);
799 CLEAR_FLAG(F_OF);
800 }
801 *destreg = (u16)res;
802 }
Jason Jinece92f82007-07-06 08:34:56 +0800803 }
804 DECODE_CLEAR_SEGOVR();
805 END_OF_INSTR();
806}
807
808/****************************************************************************
809REMARKS:
810Handles opcode 0x0f,0xb2
811****************************************************************************/
812void x86emuOp2_lss_R_IMM(u8 X86EMU_UNUSED(op2))
813{
814 int mod, rh, rl;
815 u16 *dstreg;
816 uint srcoffset;
817
818 START_OF_INSTR();
819 DECODE_PRINTF("LSS\t");
820 FETCH_DECODE_MODRM(mod, rh, rl);
821 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200822 dstreg = DECODE_RM_WORD_REGISTER(rh);
823 DECODE_PRINTF(",");
824 srcoffset = decode_rmXX_address(mod, rl);
825 DECODE_PRINTF("\n");
826 TRACE_AND_STEP();
827 *dstreg = fetch_data_word(srcoffset);
828 M.x86.R_SS = fetch_data_word(srcoffset + 2);
829 } else { /* register to register */
830 /* UNDEFINED! */
831 TRACE_AND_STEP();
Jason Jinece92f82007-07-06 08:34:56 +0800832 }
833 DECODE_CLEAR_SEGOVR();
834 END_OF_INSTR();
835}
836
837/****************************************************************************
838REMARKS:
839Handles opcode 0x0f,0xb3
840****************************************************************************/
841void x86emuOp2_btr_R(u8 X86EMU_UNUSED(op2))
842{
843 int mod, rl, rh;
844 uint srcoffset;
845 int bit,disp;
846
847 START_OF_INSTR();
848 DECODE_PRINTF("BTR\t");
849 FETCH_DECODE_MODRM(mod, rh, rl);
850 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200851 srcoffset = decode_rmXX_address(mod, rl);
852 DECODE_PRINTF(",");
853 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
854 u32 srcval,mask;
855 u32 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800856
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200857 shiftreg = DECODE_RM_LONG_REGISTER(rh);
858 TRACE_AND_STEP();
859 bit = *shiftreg & 0x1F;
860 disp = (s16)*shiftreg >> 5;
861 srcval = fetch_data_long(srcoffset+disp);
862 mask = (0x1 << bit);
863 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
864 store_data_long(srcoffset+disp, srcval & ~mask);
865 } else {
866 u16 srcval,mask;
867 u16 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800868
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200869 shiftreg = DECODE_RM_WORD_REGISTER(rh);
870 TRACE_AND_STEP();
871 bit = *shiftreg & 0xF;
872 disp = (s16)*shiftreg >> 4;
873 srcval = fetch_data_word(srcoffset+disp);
874 mask = (u16)(0x1 << bit);
875 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
876 store_data_word(srcoffset+disp, (u16)(srcval & ~mask));
877 }
878 } else { /* register to register */
879 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
880 u32 *srcreg,*shiftreg;
881 u32 mask;
Jason Jinece92f82007-07-06 08:34:56 +0800882
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200883 srcreg = DECODE_RM_LONG_REGISTER(rl);
884 DECODE_PRINTF(",");
885 shiftreg = DECODE_RM_LONG_REGISTER(rh);
886 TRACE_AND_STEP();
887 bit = *shiftreg & 0x1F;
888 mask = (0x1 << bit);
889 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
890 *srcreg &= ~mask;
891 } else {
892 u16 *srcreg,*shiftreg;
893 u16 mask;
Jason Jinece92f82007-07-06 08:34:56 +0800894
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200895 srcreg = DECODE_RM_WORD_REGISTER(rl);
896 DECODE_PRINTF(",");
897 shiftreg = DECODE_RM_WORD_REGISTER(rh);
898 TRACE_AND_STEP();
899 bit = *shiftreg & 0xF;
900 mask = (u16)(0x1 << bit);
901 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
902 *srcreg &= ~mask;
903 }
Jason Jinece92f82007-07-06 08:34:56 +0800904 }
905 DECODE_CLEAR_SEGOVR();
906 END_OF_INSTR();
907}
908
909/****************************************************************************
910REMARKS:
911Handles opcode 0x0f,0xb4
912****************************************************************************/
913void x86emuOp2_lfs_R_IMM(u8 X86EMU_UNUSED(op2))
914{
915 int mod, rh, rl;
916 u16 *dstreg;
917 uint srcoffset;
918
919 START_OF_INSTR();
920 DECODE_PRINTF("LFS\t");
921 FETCH_DECODE_MODRM(mod, rh, rl);
922 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200923 dstreg = DECODE_RM_WORD_REGISTER(rh);
924 DECODE_PRINTF(",");
925 srcoffset = decode_rmXX_address(mod, rl);
926 DECODE_PRINTF("\n");
927 TRACE_AND_STEP();
928 *dstreg = fetch_data_word(srcoffset);
929 M.x86.R_FS = fetch_data_word(srcoffset + 2);
930 } else { /* register to register */
931 /* UNDEFINED! */
932 TRACE_AND_STEP();
Jason Jinece92f82007-07-06 08:34:56 +0800933 }
934 DECODE_CLEAR_SEGOVR();
935 END_OF_INSTR();
936}
937
938/****************************************************************************
939REMARKS:
940Handles opcode 0x0f,0xb5
941****************************************************************************/
942void x86emuOp2_lgs_R_IMM(u8 X86EMU_UNUSED(op2))
943{
944 int mod, rh, rl;
945 u16 *dstreg;
946 uint srcoffset;
947
948 START_OF_INSTR();
949 DECODE_PRINTF("LGS\t");
950 FETCH_DECODE_MODRM(mod, rh, rl);
951 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200952 dstreg = DECODE_RM_WORD_REGISTER(rh);
953 DECODE_PRINTF(",");
954 srcoffset = decode_rmXX_address(mod, rl);
955 DECODE_PRINTF("\n");
956 TRACE_AND_STEP();
957 *dstreg = fetch_data_word(srcoffset);
958 M.x86.R_GS = fetch_data_word(srcoffset + 2);
959 } else { /* register to register */
960 /* UNDEFINED! */
961 TRACE_AND_STEP();
Jason Jinece92f82007-07-06 08:34:56 +0800962 }
963 DECODE_CLEAR_SEGOVR();
964 END_OF_INSTR();
965}
966
967/****************************************************************************
968REMARKS:
969Handles opcode 0x0f,0xb6
970****************************************************************************/
971void x86emuOp2_movzx_byte_R_RM(u8 X86EMU_UNUSED(op2))
972{
973 int mod, rl, rh;
974 uint srcoffset;
975
976 START_OF_INSTR();
977 DECODE_PRINTF("MOVZX\t");
978 FETCH_DECODE_MODRM(mod, rh, rl);
979 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200980 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
981 u32 *destreg;
982 u32 srcval;
Jason Jinece92f82007-07-06 08:34:56 +0800983
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200984 destreg = DECODE_RM_LONG_REGISTER(rh);
985 DECODE_PRINTF(",");
986 srcoffset = decode_rmXX_address(mod, rl);
987 srcval = fetch_data_byte(srcoffset);
988 DECODE_PRINTF("\n");
989 TRACE_AND_STEP();
990 *destreg = srcval;
991 } else {
992 u16 *destreg;
993 u16 srcval;
Jason Jinece92f82007-07-06 08:34:56 +0800994
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200995 destreg = DECODE_RM_WORD_REGISTER(rh);
996 DECODE_PRINTF(",");
997 srcoffset = decode_rmXX_address(mod, rl);
998 srcval = fetch_data_byte(srcoffset);
999 DECODE_PRINTF("\n");
1000 TRACE_AND_STEP();
1001 *destreg = srcval;
1002 }
1003 } else { /* register to register */
1004 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1005 u32 *destreg;
1006 u8 *srcreg;
Jason Jinece92f82007-07-06 08:34:56 +08001007
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001008 destreg = DECODE_RM_LONG_REGISTER(rh);
1009 DECODE_PRINTF(",");
1010 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1011 DECODE_PRINTF("\n");
1012 TRACE_AND_STEP();
1013 *destreg = *srcreg;
1014 } else {
1015 u16 *destreg;
1016 u8 *srcreg;
Jason Jinece92f82007-07-06 08:34:56 +08001017
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001018 destreg = DECODE_RM_WORD_REGISTER(rh);
1019 DECODE_PRINTF(",");
1020 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1021 DECODE_PRINTF("\n");
1022 TRACE_AND_STEP();
1023 *destreg = *srcreg;
1024 }
Jason Jinece92f82007-07-06 08:34:56 +08001025 }
1026 DECODE_CLEAR_SEGOVR();
1027 END_OF_INSTR();
1028}
1029
1030/****************************************************************************
1031REMARKS:
1032Handles opcode 0x0f,0xb7
1033****************************************************************************/
1034void x86emuOp2_movzx_word_R_RM(u8 X86EMU_UNUSED(op2))
1035{
1036 int mod, rl, rh;
1037 uint srcoffset;
1038 u32 *destreg;
1039 u32 srcval;
1040 u16 *srcreg;
1041
1042 START_OF_INSTR();
1043 DECODE_PRINTF("MOVZX\t");
1044 FETCH_DECODE_MODRM(mod, rh, rl);
1045 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001046 destreg = DECODE_RM_LONG_REGISTER(rh);
1047 DECODE_PRINTF(",");
1048 srcoffset = decode_rmXX_address(mod, rl);
1049 srcval = fetch_data_word(srcoffset);
1050 DECODE_PRINTF("\n");
1051 TRACE_AND_STEP();
1052 *destreg = srcval;
1053 } else { /* register to register */
1054 destreg = DECODE_RM_LONG_REGISTER(rh);
1055 DECODE_PRINTF(",");
1056 srcreg = DECODE_RM_WORD_REGISTER(rl);
1057 DECODE_PRINTF("\n");
1058 TRACE_AND_STEP();
1059 *destreg = *srcreg;
Jason Jinece92f82007-07-06 08:34:56 +08001060 }
1061 DECODE_CLEAR_SEGOVR();
1062 END_OF_INSTR();
1063}
1064
1065/****************************************************************************
1066REMARKS:
1067Handles opcode 0x0f,0xba
1068****************************************************************************/
1069void x86emuOp2_btX_I(u8 X86EMU_UNUSED(op2))
1070{
1071 int mod, rl, rh;
1072 uint srcoffset;
1073 u8 shift;
1074 int bit;
1075
1076 START_OF_INSTR();
1077 FETCH_DECODE_MODRM(mod, rh, rl);
1078 switch (rh) {
1079 case 4:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001080 DECODE_PRINTF("BT\t");
1081 break;
Jason Jinece92f82007-07-06 08:34:56 +08001082 case 5:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001083 DECODE_PRINTF("BTS\t");
1084 break;
Jason Jinece92f82007-07-06 08:34:56 +08001085 case 6:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001086 DECODE_PRINTF("BTR\t");
1087 break;
Jason Jinece92f82007-07-06 08:34:56 +08001088 case 7:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001089 DECODE_PRINTF("BTC\t");
1090 break;
Jason Jinece92f82007-07-06 08:34:56 +08001091 default:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001092 DECODE_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n");
1093 TRACE_REGS();
1094 printk("%04x:%04x: %02X%02X ILLEGAL EXTENDED X86 OPCODE EXTENSION!\n",
1095 M.x86.R_CS, M.x86.R_IP-3,op2, (mod<<6)|(rh<<3)|rl);
1096 HALT_SYS();
Jason Jinece92f82007-07-06 08:34:56 +08001097 }
1098 if (mod < 3) {
1099
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001100 srcoffset = decode_rmXX_address(mod, rl);
1101 shift = fetch_byte_imm();
1102 DECODE_PRINTF2(",%d\n", shift);
1103 TRACE_AND_STEP();
Jason Jinece92f82007-07-06 08:34:56 +08001104
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001105 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1106 u32 srcval, mask;
Jason Jinece92f82007-07-06 08:34:56 +08001107
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001108 bit = shift & 0x1F;
1109 srcval = fetch_data_long(srcoffset);
1110 mask = (0x1 << bit);
1111 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1112 switch (rh) {
1113 case 5:
1114 store_data_long(srcoffset, srcval | mask);
1115 break;
1116 case 6:
1117 store_data_long(srcoffset, srcval & ~mask);
1118 break;
1119 case 7:
1120 store_data_long(srcoffset, srcval ^ mask);
1121 break;
1122 default:
1123 break;
1124 }
1125 } else {
1126 u16 srcval, mask;
Jason Jinece92f82007-07-06 08:34:56 +08001127
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001128 bit = shift & 0xF;
1129 srcval = fetch_data_word(srcoffset);
1130 mask = (0x1 << bit);
1131 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1132 switch (rh) {
1133 case 5:
1134 store_data_word(srcoffset, srcval | mask);
1135 break;
1136 case 6:
1137 store_data_word(srcoffset, srcval & ~mask);
1138 break;
1139 case 7:
1140 store_data_word(srcoffset, srcval ^ mask);
1141 break;
1142 default:
1143 break;
1144 }
1145 }
1146 } else { /* register to register */
1147 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1148 u32 *srcreg;
1149 u32 mask;
Jason Jinece92f82007-07-06 08:34:56 +08001150
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001151 srcreg = DECODE_RM_LONG_REGISTER(rl);
1152 shift = fetch_byte_imm();
1153 DECODE_PRINTF2(",%d\n", shift);
1154 TRACE_AND_STEP();
1155 bit = shift & 0x1F;
1156 mask = (0x1 << bit);
1157 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1158 switch (rh) {
1159 case 5:
1160 *srcreg |= mask;
1161 break;
1162 case 6:
1163 *srcreg &= ~mask;
1164 break;
1165 case 7:
1166 *srcreg ^= mask;
1167 break;
1168 default:
1169 break;
1170 }
1171 } else {
1172 u16 *srcreg;
1173 u16 mask;
Jason Jinece92f82007-07-06 08:34:56 +08001174
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001175 srcreg = DECODE_RM_WORD_REGISTER(rl);
1176 shift = fetch_byte_imm();
1177 DECODE_PRINTF2(",%d\n", shift);
1178 TRACE_AND_STEP();
1179 bit = shift & 0xF;
1180 mask = (0x1 << bit);
1181 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1182 switch (rh) {
1183 case 5:
1184 *srcreg |= mask;
1185 break;
1186 case 6:
1187 *srcreg &= ~mask;
1188 break;
1189 case 7:
1190 *srcreg ^= mask;
1191 break;
1192 default:
1193 break;
1194 }
1195 }
Jason Jinece92f82007-07-06 08:34:56 +08001196 }
1197 DECODE_CLEAR_SEGOVR();
1198 END_OF_INSTR();
1199}
1200
1201/****************************************************************************
1202REMARKS:
1203Handles opcode 0x0f,0xbb
1204****************************************************************************/
1205void x86emuOp2_btc_R(u8 X86EMU_UNUSED(op2))
1206{
1207 int mod, rl, rh;
1208 uint srcoffset;
1209 int bit,disp;
1210
1211 START_OF_INSTR();
1212 DECODE_PRINTF("BTC\t");
1213 FETCH_DECODE_MODRM(mod, rh, rl);
1214 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001215 srcoffset = decode_rmXX_address(mod, rl);
1216 DECODE_PRINTF(",");
1217 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1218 u32 srcval,mask;
1219 u32 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +08001220
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001221 shiftreg = DECODE_RM_LONG_REGISTER(rh);
1222 TRACE_AND_STEP();
1223 bit = *shiftreg & 0x1F;
1224 disp = (s16)*shiftreg >> 5;
1225 srcval = fetch_data_long(srcoffset+disp);
1226 mask = (0x1 << bit);
1227 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1228 store_data_long(srcoffset+disp, srcval ^ mask);
1229 } else {
1230 u16 srcval,mask;
1231 u16 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +08001232
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001233 shiftreg = DECODE_RM_WORD_REGISTER(rh);
1234 TRACE_AND_STEP();
1235 bit = *shiftreg & 0xF;
1236 disp = (s16)*shiftreg >> 4;
1237 srcval = fetch_data_word(srcoffset+disp);
1238 mask = (u16)(0x1 << bit);
1239 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1240 store_data_word(srcoffset+disp, (u16)(srcval ^ mask));
1241 }
1242 } else { /* register to register */
1243 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1244 u32 *srcreg,*shiftreg;
1245 u32 mask;
Jason Jinece92f82007-07-06 08:34:56 +08001246
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001247 srcreg = DECODE_RM_LONG_REGISTER(rl);
1248 DECODE_PRINTF(",");
1249 shiftreg = DECODE_RM_LONG_REGISTER(rh);
1250 TRACE_AND_STEP();
1251 bit = *shiftreg & 0x1F;
1252 mask = (0x1 << bit);
1253 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1254 *srcreg ^= mask;
1255 } else {
1256 u16 *srcreg,*shiftreg;
1257 u16 mask;
Jason Jinece92f82007-07-06 08:34:56 +08001258
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001259 srcreg = DECODE_RM_WORD_REGISTER(rl);
1260 DECODE_PRINTF(",");
1261 shiftreg = DECODE_RM_WORD_REGISTER(rh);
1262 TRACE_AND_STEP();
1263 bit = *shiftreg & 0xF;
1264 mask = (u16)(0x1 << bit);
1265 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1266 *srcreg ^= mask;
1267 }
Jason Jinece92f82007-07-06 08:34:56 +08001268 }
1269 DECODE_CLEAR_SEGOVR();
1270 END_OF_INSTR();
1271}
1272
1273/****************************************************************************
1274REMARKS:
1275Handles opcode 0x0f,0xbc
1276****************************************************************************/
1277void x86emuOp2_bsf(u8 X86EMU_UNUSED(op2))
1278{
1279 int mod, rl, rh;
1280 uint srcoffset;
1281
1282 START_OF_INSTR();
1283 DECODE_PRINTF("BSF\n");
1284 FETCH_DECODE_MODRM(mod, rh, rl);
1285 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001286 srcoffset = decode_rmXX_address(mod, rl);
1287 DECODE_PRINTF(",");
1288 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1289 u32 srcval, *dstreg;
Jason Jinece92f82007-07-06 08:34:56 +08001290
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001291 dstreg = DECODE_RM_LONG_REGISTER(rh);
1292 TRACE_AND_STEP();
1293 srcval = fetch_data_long(srcoffset);
1294 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
1295 for(*dstreg = 0; *dstreg < 32; (*dstreg)++)
1296 if ((srcval >> *dstreg) & 1) break;
1297 } else {
1298 u16 srcval, *dstreg;
Jason Jinece92f82007-07-06 08:34:56 +08001299
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001300 dstreg = DECODE_RM_WORD_REGISTER(rh);
1301 TRACE_AND_STEP();
1302 srcval = fetch_data_word(srcoffset);
1303 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
1304 for(*dstreg = 0; *dstreg < 16; (*dstreg)++)
1305 if ((srcval >> *dstreg) & 1) break;
1306 }
1307 } else { /* register to register */
1308 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1309 u32 *srcreg, *dstreg;
Jason Jinece92f82007-07-06 08:34:56 +08001310
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001311 srcreg = DECODE_RM_LONG_REGISTER(rl);
1312 DECODE_PRINTF(",");
1313 dstreg = DECODE_RM_LONG_REGISTER(rh);
1314 TRACE_AND_STEP();
1315 CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF);
1316 for(*dstreg = 0; *dstreg < 32; (*dstreg)++)
1317 if ((*srcreg >> *dstreg) & 1) break;
1318 } else {
1319 u16 *srcreg, *dstreg;
Jason Jinece92f82007-07-06 08:34:56 +08001320
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001321 srcreg = DECODE_RM_WORD_REGISTER(rl);
1322 DECODE_PRINTF(",");
1323 dstreg = DECODE_RM_WORD_REGISTER(rh);
1324 TRACE_AND_STEP();
1325 CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF);
1326 for(*dstreg = 0; *dstreg < 16; (*dstreg)++)
1327 if ((*srcreg >> *dstreg) & 1) break;
1328 }
Jason Jinece92f82007-07-06 08:34:56 +08001329 }
1330 DECODE_CLEAR_SEGOVR();
1331 END_OF_INSTR();
1332}
1333
1334/****************************************************************************
1335REMARKS:
1336Handles opcode 0x0f,0xbd
1337****************************************************************************/
1338void x86emuOp2_bsr(u8 X86EMU_UNUSED(op2))
1339{
1340 int mod, rl, rh;
1341 uint srcoffset;
1342
1343 START_OF_INSTR();
1344 DECODE_PRINTF("BSF\n");
1345 FETCH_DECODE_MODRM(mod, rh, rl);
1346 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001347 srcoffset = decode_rmXX_address(mod, rl);
1348 DECODE_PRINTF(",");
1349 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1350 u32 srcval, *dstreg;
Jason Jinece92f82007-07-06 08:34:56 +08001351
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001352 dstreg = DECODE_RM_LONG_REGISTER(rh);
1353 TRACE_AND_STEP();
1354 srcval = fetch_data_long(srcoffset);
1355 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
1356 for(*dstreg = 31; *dstreg > 0; (*dstreg)--)
1357 if ((srcval >> *dstreg) & 1) break;
1358 } else {
1359 u16 srcval, *dstreg;
Jason Jinece92f82007-07-06 08:34:56 +08001360
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001361 dstreg = DECODE_RM_WORD_REGISTER(rh);
1362 TRACE_AND_STEP();
1363 srcval = fetch_data_word(srcoffset);
1364 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
1365 for(*dstreg = 15; *dstreg > 0; (*dstreg)--)
1366 if ((srcval >> *dstreg) & 1) break;
1367 }
1368 } else { /* register to register */
1369 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1370 u32 *srcreg, *dstreg;
Jason Jinece92f82007-07-06 08:34:56 +08001371
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001372 srcreg = DECODE_RM_LONG_REGISTER(rl);
1373 DECODE_PRINTF(",");
1374 dstreg = DECODE_RM_LONG_REGISTER(rh);
1375 TRACE_AND_STEP();
1376 CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF);
1377 for(*dstreg = 31; *dstreg > 0; (*dstreg)--)
1378 if ((*srcreg >> *dstreg) & 1) break;
1379 } else {
1380 u16 *srcreg, *dstreg;
Jason Jinece92f82007-07-06 08:34:56 +08001381
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001382 srcreg = DECODE_RM_WORD_REGISTER(rl);
1383 DECODE_PRINTF(",");
1384 dstreg = DECODE_RM_WORD_REGISTER(rh);
1385 TRACE_AND_STEP();
1386 CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF);
1387 for(*dstreg = 15; *dstreg > 0; (*dstreg)--)
1388 if ((*srcreg >> *dstreg) & 1) break;
1389 }
Jason Jinece92f82007-07-06 08:34:56 +08001390 }
1391 DECODE_CLEAR_SEGOVR();
1392 END_OF_INSTR();
1393}
1394
1395/****************************************************************************
1396REMARKS:
1397Handles opcode 0x0f,0xbe
1398****************************************************************************/
1399void x86emuOp2_movsx_byte_R_RM(u8 X86EMU_UNUSED(op2))
1400{
1401 int mod, rl, rh;
1402 uint srcoffset;
1403
1404 START_OF_INSTR();
1405 DECODE_PRINTF("MOVSX\t");
1406 FETCH_DECODE_MODRM(mod, rh, rl);
1407 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001408 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1409 u32 *destreg;
1410 u32 srcval;
Jason Jinece92f82007-07-06 08:34:56 +08001411
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001412 destreg = DECODE_RM_LONG_REGISTER(rh);
1413 DECODE_PRINTF(",");
1414 srcoffset = decode_rmXX_address(mod, rl);
1415 srcval = (s32)((s8)fetch_data_byte(srcoffset));
1416 DECODE_PRINTF("\n");
1417 TRACE_AND_STEP();
1418 *destreg = srcval;
1419 } else {
1420 u16 *destreg;
1421 u16 srcval;
Jason Jinece92f82007-07-06 08:34:56 +08001422
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001423 destreg = DECODE_RM_WORD_REGISTER(rh);
1424 DECODE_PRINTF(",");
1425 srcoffset = decode_rmXX_address(mod, rl);
1426 srcval = (s16)((s8)fetch_data_byte(srcoffset));
1427 DECODE_PRINTF("\n");
1428 TRACE_AND_STEP();
1429 *destreg = srcval;
1430 }
1431 } else { /* register to register */
1432 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1433 u32 *destreg;
1434 u8 *srcreg;
Jason Jinece92f82007-07-06 08:34:56 +08001435
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001436 destreg = DECODE_RM_LONG_REGISTER(rh);
1437 DECODE_PRINTF(",");
1438 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1439 DECODE_PRINTF("\n");
1440 TRACE_AND_STEP();
1441 *destreg = (s32)((s8)*srcreg);
1442 } else {
1443 u16 *destreg;
1444 u8 *srcreg;
Jason Jinece92f82007-07-06 08:34:56 +08001445
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001446 destreg = DECODE_RM_WORD_REGISTER(rh);
1447 DECODE_PRINTF(",");
1448 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1449 DECODE_PRINTF("\n");
1450 TRACE_AND_STEP();
1451 *destreg = (s16)((s8)*srcreg);
1452 }
Jason Jinece92f82007-07-06 08:34:56 +08001453 }
1454 DECODE_CLEAR_SEGOVR();
1455 END_OF_INSTR();
1456}
1457
1458/****************************************************************************
1459REMARKS:
1460Handles opcode 0x0f,0xbf
1461****************************************************************************/
1462void x86emuOp2_movsx_word_R_RM(u8 X86EMU_UNUSED(op2))
1463{
1464 int mod, rl, rh;
1465 uint srcoffset;
1466 u32 *destreg;
1467 u32 srcval;
1468 u16 *srcreg;
1469
1470 START_OF_INSTR();
1471 DECODE_PRINTF("MOVSX\t");
1472 FETCH_DECODE_MODRM(mod, rh, rl);
1473 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001474 destreg = DECODE_RM_LONG_REGISTER(rh);
1475 DECODE_PRINTF(",");
1476 srcoffset = decode_rmXX_address(mod, rl);
1477 srcval = (s32)((s16)fetch_data_word(srcoffset));
1478 DECODE_PRINTF("\n");
1479 TRACE_AND_STEP();
1480 *destreg = srcval;
1481 } else { /* register to register */
1482 destreg = DECODE_RM_LONG_REGISTER(rh);
1483 DECODE_PRINTF(",");
1484 srcreg = DECODE_RM_WORD_REGISTER(rl);
1485 DECODE_PRINTF("\n");
1486 TRACE_AND_STEP();
1487 *destreg = (s32)((s16)*srcreg);
Jason Jinece92f82007-07-06 08:34:56 +08001488 }
1489 DECODE_CLEAR_SEGOVR();
1490 END_OF_INSTR();
1491}
1492
1493/***************************************************************************
1494 * Double byte operation code table:
1495 **************************************************************************/
Ed Swarthout285870f2008-10-09 01:27:18 -05001496void (*x86emu_optab2[256])(u8) =
Jason Jinece92f82007-07-06 08:34:56 +08001497{
1498/* 0x00 */ x86emuOp2_illegal_op, /* Group F (ring 0 PM) */
1499/* 0x01 */ x86emuOp2_illegal_op, /* Group G (ring 0 PM) */
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001500/* 0x02 */ x86emuOp2_illegal_op, /* lar (ring 0 PM) */
1501/* 0x03 */ x86emuOp2_illegal_op, /* lsl (ring 0 PM) */
Jason Jinece92f82007-07-06 08:34:56 +08001502/* 0x04 */ x86emuOp2_illegal_op,
1503/* 0x05 */ x86emuOp2_illegal_op, /* loadall (undocumented) */
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001504/* 0x06 */ x86emuOp2_illegal_op, /* clts (ring 0 PM) */
Jason Jinece92f82007-07-06 08:34:56 +08001505/* 0x07 */ x86emuOp2_illegal_op, /* loadall (undocumented) */
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001506/* 0x08 */ x86emuOp2_illegal_op, /* invd (ring 0 PM) */
Jason Jinece92f82007-07-06 08:34:56 +08001507/* 0x09 */ x86emuOp2_illegal_op, /* wbinvd (ring 0 PM) */
1508/* 0x0a */ x86emuOp2_illegal_op,
1509/* 0x0b */ x86emuOp2_illegal_op,
1510/* 0x0c */ x86emuOp2_illegal_op,
1511/* 0x0d */ x86emuOp2_illegal_op,
1512/* 0x0e */ x86emuOp2_illegal_op,
1513/* 0x0f */ x86emuOp2_illegal_op,
1514
1515/* 0x10 */ x86emuOp2_illegal_op,
1516/* 0x11 */ x86emuOp2_illegal_op,
1517/* 0x12 */ x86emuOp2_illegal_op,
1518/* 0x13 */ x86emuOp2_illegal_op,
1519/* 0x14 */ x86emuOp2_illegal_op,
1520/* 0x15 */ x86emuOp2_illegal_op,
1521/* 0x16 */ x86emuOp2_illegal_op,
1522/* 0x17 */ x86emuOp2_illegal_op,
1523/* 0x18 */ x86emuOp2_illegal_op,
1524/* 0x19 */ x86emuOp2_illegal_op,
1525/* 0x1a */ x86emuOp2_illegal_op,
1526/* 0x1b */ x86emuOp2_illegal_op,
1527/* 0x1c */ x86emuOp2_illegal_op,
1528/* 0x1d */ x86emuOp2_illegal_op,
1529/* 0x1e */ x86emuOp2_illegal_op,
1530/* 0x1f */ x86emuOp2_illegal_op,
1531
1532/* 0x20 */ x86emuOp2_illegal_op, /* mov reg32,creg (ring 0 PM) */
1533/* 0x21 */ x86emuOp2_illegal_op, /* mov reg32,dreg (ring 0 PM) */
1534/* 0x22 */ x86emuOp2_illegal_op, /* mov creg,reg32 (ring 0 PM) */
1535/* 0x23 */ x86emuOp2_illegal_op, /* mov dreg,reg32 (ring 0 PM) */
1536/* 0x24 */ x86emuOp2_illegal_op, /* mov reg32,treg (ring 0 PM) */
1537/* 0x25 */ x86emuOp2_illegal_op,
1538/* 0x26 */ x86emuOp2_illegal_op, /* mov treg,reg32 (ring 0 PM) */
1539/* 0x27 */ x86emuOp2_illegal_op,
1540/* 0x28 */ x86emuOp2_illegal_op,
1541/* 0x29 */ x86emuOp2_illegal_op,
1542/* 0x2a */ x86emuOp2_illegal_op,
1543/* 0x2b */ x86emuOp2_illegal_op,
1544/* 0x2c */ x86emuOp2_illegal_op,
1545/* 0x2d */ x86emuOp2_illegal_op,
1546/* 0x2e */ x86emuOp2_illegal_op,
1547/* 0x2f */ x86emuOp2_illegal_op,
1548
1549/* 0x30 */ x86emuOp2_illegal_op,
1550/* 0x31 */ x86emuOp2_illegal_op,
1551/* 0x32 */ x86emuOp2_illegal_op,
1552/* 0x33 */ x86emuOp2_illegal_op,
1553/* 0x34 */ x86emuOp2_illegal_op,
1554/* 0x35 */ x86emuOp2_illegal_op,
1555/* 0x36 */ x86emuOp2_illegal_op,
1556/* 0x37 */ x86emuOp2_illegal_op,
1557/* 0x38 */ x86emuOp2_illegal_op,
1558/* 0x39 */ x86emuOp2_illegal_op,
1559/* 0x3a */ x86emuOp2_illegal_op,
1560/* 0x3b */ x86emuOp2_illegal_op,
1561/* 0x3c */ x86emuOp2_illegal_op,
1562/* 0x3d */ x86emuOp2_illegal_op,
1563/* 0x3e */ x86emuOp2_illegal_op,
1564/* 0x3f */ x86emuOp2_illegal_op,
1565
1566/* 0x40 */ x86emuOp2_illegal_op,
1567/* 0x41 */ x86emuOp2_illegal_op,
1568/* 0x42 */ x86emuOp2_illegal_op,
1569/* 0x43 */ x86emuOp2_illegal_op,
1570/* 0x44 */ x86emuOp2_illegal_op,
1571/* 0x45 */ x86emuOp2_illegal_op,
1572/* 0x46 */ x86emuOp2_illegal_op,
1573/* 0x47 */ x86emuOp2_illegal_op,
1574/* 0x48 */ x86emuOp2_illegal_op,
1575/* 0x49 */ x86emuOp2_illegal_op,
1576/* 0x4a */ x86emuOp2_illegal_op,
1577/* 0x4b */ x86emuOp2_illegal_op,
1578/* 0x4c */ x86emuOp2_illegal_op,
1579/* 0x4d */ x86emuOp2_illegal_op,
1580/* 0x4e */ x86emuOp2_illegal_op,
1581/* 0x4f */ x86emuOp2_illegal_op,
1582
1583/* 0x50 */ x86emuOp2_illegal_op,
1584/* 0x51 */ x86emuOp2_illegal_op,
1585/* 0x52 */ x86emuOp2_illegal_op,
1586/* 0x53 */ x86emuOp2_illegal_op,
1587/* 0x54 */ x86emuOp2_illegal_op,
1588/* 0x55 */ x86emuOp2_illegal_op,
1589/* 0x56 */ x86emuOp2_illegal_op,
1590/* 0x57 */ x86emuOp2_illegal_op,
1591/* 0x58 */ x86emuOp2_illegal_op,
1592/* 0x59 */ x86emuOp2_illegal_op,
1593/* 0x5a */ x86emuOp2_illegal_op,
1594/* 0x5b */ x86emuOp2_illegal_op,
1595/* 0x5c */ x86emuOp2_illegal_op,
1596/* 0x5d */ x86emuOp2_illegal_op,
1597/* 0x5e */ x86emuOp2_illegal_op,
1598/* 0x5f */ x86emuOp2_illegal_op,
1599
1600/* 0x60 */ x86emuOp2_illegal_op,
1601/* 0x61 */ x86emuOp2_illegal_op,
1602/* 0x62 */ x86emuOp2_illegal_op,
1603/* 0x63 */ x86emuOp2_illegal_op,
1604/* 0x64 */ x86emuOp2_illegal_op,
1605/* 0x65 */ x86emuOp2_illegal_op,
1606/* 0x66 */ x86emuOp2_illegal_op,
1607/* 0x67 */ x86emuOp2_illegal_op,
1608/* 0x68 */ x86emuOp2_illegal_op,
1609/* 0x69 */ x86emuOp2_illegal_op,
1610/* 0x6a */ x86emuOp2_illegal_op,
1611/* 0x6b */ x86emuOp2_illegal_op,
1612/* 0x6c */ x86emuOp2_illegal_op,
1613/* 0x6d */ x86emuOp2_illegal_op,
1614/* 0x6e */ x86emuOp2_illegal_op,
1615/* 0x6f */ x86emuOp2_illegal_op,
1616
1617/* 0x70 */ x86emuOp2_illegal_op,
1618/* 0x71 */ x86emuOp2_illegal_op,
1619/* 0x72 */ x86emuOp2_illegal_op,
1620/* 0x73 */ x86emuOp2_illegal_op,
1621/* 0x74 */ x86emuOp2_illegal_op,
1622/* 0x75 */ x86emuOp2_illegal_op,
1623/* 0x76 */ x86emuOp2_illegal_op,
1624/* 0x77 */ x86emuOp2_illegal_op,
1625/* 0x78 */ x86emuOp2_illegal_op,
1626/* 0x79 */ x86emuOp2_illegal_op,
1627/* 0x7a */ x86emuOp2_illegal_op,
1628/* 0x7b */ x86emuOp2_illegal_op,
1629/* 0x7c */ x86emuOp2_illegal_op,
1630/* 0x7d */ x86emuOp2_illegal_op,
1631/* 0x7e */ x86emuOp2_illegal_op,
1632/* 0x7f */ x86emuOp2_illegal_op,
1633
1634/* 0x80 */ x86emuOp2_long_jump,
1635/* 0x81 */ x86emuOp2_long_jump,
1636/* 0x82 */ x86emuOp2_long_jump,
1637/* 0x83 */ x86emuOp2_long_jump,
1638/* 0x84 */ x86emuOp2_long_jump,
1639/* 0x85 */ x86emuOp2_long_jump,
1640/* 0x86 */ x86emuOp2_long_jump,
1641/* 0x87 */ x86emuOp2_long_jump,
1642/* 0x88 */ x86emuOp2_long_jump,
1643/* 0x89 */ x86emuOp2_long_jump,
1644/* 0x8a */ x86emuOp2_long_jump,
1645/* 0x8b */ x86emuOp2_long_jump,
1646/* 0x8c */ x86emuOp2_long_jump,
1647/* 0x8d */ x86emuOp2_long_jump,
1648/* 0x8e */ x86emuOp2_long_jump,
1649/* 0x8f */ x86emuOp2_long_jump,
1650
1651/* 0x90 */ x86emuOp2_set_byte,
1652/* 0x91 */ x86emuOp2_set_byte,
1653/* 0x92 */ x86emuOp2_set_byte,
1654/* 0x93 */ x86emuOp2_set_byte,
1655/* 0x94 */ x86emuOp2_set_byte,
1656/* 0x95 */ x86emuOp2_set_byte,
1657/* 0x96 */ x86emuOp2_set_byte,
1658/* 0x97 */ x86emuOp2_set_byte,
1659/* 0x98 */ x86emuOp2_set_byte,
1660/* 0x99 */ x86emuOp2_set_byte,
1661/* 0x9a */ x86emuOp2_set_byte,
1662/* 0x9b */ x86emuOp2_set_byte,
1663/* 0x9c */ x86emuOp2_set_byte,
1664/* 0x9d */ x86emuOp2_set_byte,
1665/* 0x9e */ x86emuOp2_set_byte,
1666/* 0x9f */ x86emuOp2_set_byte,
1667
1668/* 0xa0 */ x86emuOp2_push_FS,
1669/* 0xa1 */ x86emuOp2_pop_FS,
1670/* 0xa2 */ x86emuOp2_illegal_op,
1671/* 0xa3 */ x86emuOp2_bt_R,
1672/* 0xa4 */ x86emuOp2_shld_IMM,
1673/* 0xa5 */ x86emuOp2_shld_CL,
1674/* 0xa6 */ x86emuOp2_illegal_op,
1675/* 0xa7 */ x86emuOp2_illegal_op,
1676/* 0xa8 */ x86emuOp2_push_GS,
1677/* 0xa9 */ x86emuOp2_pop_GS,
1678/* 0xaa */ x86emuOp2_illegal_op,
1679/* 0xab */ x86emuOp2_bt_R,
1680/* 0xac */ x86emuOp2_shrd_IMM,
1681/* 0xad */ x86emuOp2_shrd_CL,
1682/* 0xae */ x86emuOp2_illegal_op,
1683/* 0xaf */ x86emuOp2_imul_R_RM,
1684
1685/* 0xb0 */ x86emuOp2_illegal_op, /* TODO: cmpxchg */
1686/* 0xb1 */ x86emuOp2_illegal_op, /* TODO: cmpxchg */
1687/* 0xb2 */ x86emuOp2_lss_R_IMM,
1688/* 0xb3 */ x86emuOp2_btr_R,
1689/* 0xb4 */ x86emuOp2_lfs_R_IMM,
1690/* 0xb5 */ x86emuOp2_lgs_R_IMM,
1691/* 0xb6 */ x86emuOp2_movzx_byte_R_RM,
1692/* 0xb7 */ x86emuOp2_movzx_word_R_RM,
1693/* 0xb8 */ x86emuOp2_illegal_op,
1694/* 0xb9 */ x86emuOp2_illegal_op,
1695/* 0xba */ x86emuOp2_btX_I,
1696/* 0xbb */ x86emuOp2_btc_R,
1697/* 0xbc */ x86emuOp2_bsf,
1698/* 0xbd */ x86emuOp2_bsr,
1699/* 0xbe */ x86emuOp2_movsx_byte_R_RM,
1700/* 0xbf */ x86emuOp2_movsx_word_R_RM,
1701
1702/* 0xc0 */ x86emuOp2_illegal_op, /* TODO: xadd */
1703/* 0xc1 */ x86emuOp2_illegal_op, /* TODO: xadd */
1704/* 0xc2 */ x86emuOp2_illegal_op,
1705/* 0xc3 */ x86emuOp2_illegal_op,
1706/* 0xc4 */ x86emuOp2_illegal_op,
1707/* 0xc5 */ x86emuOp2_illegal_op,
1708/* 0xc6 */ x86emuOp2_illegal_op,
1709/* 0xc7 */ x86emuOp2_illegal_op,
1710/* 0xc8 */ x86emuOp2_illegal_op, /* TODO: bswap */
1711/* 0xc9 */ x86emuOp2_illegal_op, /* TODO: bswap */
1712/* 0xca */ x86emuOp2_illegal_op, /* TODO: bswap */
1713/* 0xcb */ x86emuOp2_illegal_op, /* TODO: bswap */
1714/* 0xcc */ x86emuOp2_illegal_op, /* TODO: bswap */
1715/* 0xcd */ x86emuOp2_illegal_op, /* TODO: bswap */
1716/* 0xce */ x86emuOp2_illegal_op, /* TODO: bswap */
1717/* 0xcf */ x86emuOp2_illegal_op, /* TODO: bswap */
1718
1719/* 0xd0 */ x86emuOp2_illegal_op,
1720/* 0xd1 */ x86emuOp2_illegal_op,
1721/* 0xd2 */ x86emuOp2_illegal_op,
1722/* 0xd3 */ x86emuOp2_illegal_op,
1723/* 0xd4 */ x86emuOp2_illegal_op,
1724/* 0xd5 */ x86emuOp2_illegal_op,
1725/* 0xd6 */ x86emuOp2_illegal_op,
1726/* 0xd7 */ x86emuOp2_illegal_op,
1727/* 0xd8 */ x86emuOp2_illegal_op,
1728/* 0xd9 */ x86emuOp2_illegal_op,
1729/* 0xda */ x86emuOp2_illegal_op,
1730/* 0xdb */ x86emuOp2_illegal_op,
1731/* 0xdc */ x86emuOp2_illegal_op,
1732/* 0xdd */ x86emuOp2_illegal_op,
1733/* 0xde */ x86emuOp2_illegal_op,
1734/* 0xdf */ x86emuOp2_illegal_op,
1735
1736/* 0xe0 */ x86emuOp2_illegal_op,
1737/* 0xe1 */ x86emuOp2_illegal_op,
1738/* 0xe2 */ x86emuOp2_illegal_op,
1739/* 0xe3 */ x86emuOp2_illegal_op,
1740/* 0xe4 */ x86emuOp2_illegal_op,
1741/* 0xe5 */ x86emuOp2_illegal_op,
1742/* 0xe6 */ x86emuOp2_illegal_op,
1743/* 0xe7 */ x86emuOp2_illegal_op,
1744/* 0xe8 */ x86emuOp2_illegal_op,
1745/* 0xe9 */ x86emuOp2_illegal_op,
1746/* 0xea */ x86emuOp2_illegal_op,
1747/* 0xeb */ x86emuOp2_illegal_op,
1748/* 0xec */ x86emuOp2_illegal_op,
1749/* 0xed */ x86emuOp2_illegal_op,
1750/* 0xee */ x86emuOp2_illegal_op,
1751/* 0xef */ x86emuOp2_illegal_op,
1752
1753/* 0xf0 */ x86emuOp2_illegal_op,
1754/* 0xf1 */ x86emuOp2_illegal_op,
1755/* 0xf2 */ x86emuOp2_illegal_op,
1756/* 0xf3 */ x86emuOp2_illegal_op,
1757/* 0xf4 */ x86emuOp2_illegal_op,
1758/* 0xf5 */ x86emuOp2_illegal_op,
1759/* 0xf6 */ x86emuOp2_illegal_op,
1760/* 0xf7 */ x86emuOp2_illegal_op,
1761/* 0xf8 */ x86emuOp2_illegal_op,
1762/* 0xf9 */ x86emuOp2_illegal_op,
1763/* 0xfa */ x86emuOp2_illegal_op,
1764/* 0xfb */ x86emuOp2_illegal_op,
1765/* 0xfc */ x86emuOp2_illegal_op,
1766/* 0xfd */ x86emuOp2_illegal_op,
1767/* 0xfe */ x86emuOp2_illegal_op,
1768/* 0xff */ x86emuOp2_illegal_op,
1769};