blob: d90d36629fce7c93a31a7645e429676cccaa12af [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*
5* Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
6* 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*
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +020042* Jason port this file to u-boot. Put the function pointer into
43* got2 sector.
Jason Jinece92f82007-07-06 08:34:56 +080044*
45****************************************************************************/
46
Michal Simek78cff502007-08-16 10:46:28 +020047#include <common.h>
48
Jason Jince981dc2007-08-08 08:33:11 +080049#if defined(CONFIG_BIOSEMU)
50
Michal Simek5b4de932007-08-15 21:15:05 +020051#include "x86emu/x86emui.h"
52
Jason Jinece92f82007-07-06 08:34:56 +080053/*----------------------------- Implementation ----------------------------*/
54
55/****************************************************************************
56PARAMETERS:
57op1 - Instruction op code
58
59REMARKS:
60Handles illegal opcodes.
61****************************************************************************/
62void x86emuOp2_illegal_op(
63 u8 op2)
64{
65 START_OF_INSTR();
66 DECODE_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n");
67 TRACE_REGS();
68 printk("%04x:%04x: %02X ILLEGAL EXTENDED X86 OPCODE!\n",
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +020069 M.x86.R_CS, M.x86.R_IP-2,op2);
Jason Jinece92f82007-07-06 08:34:56 +080070 HALT_SYS();
71 END_OF_INSTR();
72}
73
74#define xorl(a,b) ((a) && !(b)) || (!(a) && (b))
75
76/****************************************************************************
77REMARKS:
78Handles opcode 0x0f,0x80-0x8F
79****************************************************************************/
80int x86emu_check_jump_condition(u8 op)
81{
82 switch (op) {
83 case 0x0:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +020084 DECODE_PRINTF("JO\t");
85 return ACCESS_FLAG(F_OF);
Jason Jinece92f82007-07-06 08:34:56 +080086 case 0x1:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +020087 DECODE_PRINTF("JNO\t");
88 return !ACCESS_FLAG(F_OF);
89 break;
Jason Jinece92f82007-07-06 08:34:56 +080090 case 0x2:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +020091 DECODE_PRINTF("JB\t");
92 return ACCESS_FLAG(F_CF);
93 break;
Jason Jinece92f82007-07-06 08:34:56 +080094 case 0x3:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +020095 DECODE_PRINTF("JNB\t");
96 return !ACCESS_FLAG(F_CF);
97 break;
Jason Jinece92f82007-07-06 08:34:56 +080098 case 0x4:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +020099 DECODE_PRINTF("JZ\t");
100 return ACCESS_FLAG(F_ZF);
101 break;
Jason Jinece92f82007-07-06 08:34:56 +0800102 case 0x5:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200103 DECODE_PRINTF("JNZ\t");
104 return !ACCESS_FLAG(F_ZF);
105 break;
Jason Jinece92f82007-07-06 08:34:56 +0800106 case 0x6:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200107 DECODE_PRINTF("JBE\t");
108 return ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF);
109 break;
Jason Jinece92f82007-07-06 08:34:56 +0800110 case 0x7:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200111 DECODE_PRINTF("JNBE\t");
112 return !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
113 break;
Jason Jinece92f82007-07-06 08:34:56 +0800114 case 0x8:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200115 DECODE_PRINTF("JS\t");
116 return ACCESS_FLAG(F_SF);
117 break;
Jason Jinece92f82007-07-06 08:34:56 +0800118 case 0x9:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200119 DECODE_PRINTF("JNS\t");
120 return !ACCESS_FLAG(F_SF);
121 break;
Jason Jinece92f82007-07-06 08:34:56 +0800122 case 0xa:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200123 DECODE_PRINTF("JP\t");
124 return ACCESS_FLAG(F_PF);
125 break;
Jason Jinece92f82007-07-06 08:34:56 +0800126 case 0xb:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200127 DECODE_PRINTF("JNP\t");
128 return !ACCESS_FLAG(F_PF);
129 break;
Jason Jinece92f82007-07-06 08:34:56 +0800130 case 0xc:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200131 DECODE_PRINTF("JL\t");
132 return xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
133 break;
Jason Jinece92f82007-07-06 08:34:56 +0800134 case 0xd:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200135 DECODE_PRINTF("JNL\t");
136 return !xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
137 break;
Jason Jinece92f82007-07-06 08:34:56 +0800138 case 0xe:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200139 DECODE_PRINTF("JLE\t");
140 return (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
141 ACCESS_FLAG(F_ZF));
142 break;
Jason Jinece92f82007-07-06 08:34:56 +0800143 default:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200144 DECODE_PRINTF("JNLE\t");
145 return !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
146 ACCESS_FLAG(F_ZF));
Jason Jinece92f82007-07-06 08:34:56 +0800147 }
148}
149
150void x86emuOp2_long_jump(u8 op2)
151{
152 s32 target;
153 int cond;
154
155 /* conditional jump to word offset. */
156 START_OF_INSTR();
157 cond = x86emu_check_jump_condition(op2 & 0xF);
158 target = (s16) fetch_word_imm();
159 target += (s16) M.x86.R_IP;
160 DECODE_PRINTF2("%04x\n", target);
161 TRACE_AND_STEP();
162 if (cond)
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200163 M.x86.R_IP = (u16)target;
Jason Jinece92f82007-07-06 08:34:56 +0800164 DECODE_CLEAR_SEGOVR();
165 END_OF_INSTR();
166}
167
168/****************************************************************************
169REMARKS:
170Handles opcode 0x0f,0x90-0x9F
171****************************************************************************/
172void x86emuOp2_set_byte(u8 op2)
173{
174 int mod, rl, rh;
175 uint destoffset;
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200176 u8 *destreg;
Jason Jinece92f82007-07-06 08:34:56 +0800177 char *name = 0;
178 int cond = 0;
179
180 START_OF_INSTR();
181 switch (op2) {
182 case 0x90:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200183 name = "SETO\t";
184 cond = ACCESS_FLAG(F_OF);
185 break;
Jason Jinece92f82007-07-06 08:34:56 +0800186 case 0x91:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200187 name = "SETNO\t";
188 cond = !ACCESS_FLAG(F_OF);
189 break;
Jason Jinece92f82007-07-06 08:34:56 +0800190 case 0x92:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200191 name = "SETB\t";
192 cond = ACCESS_FLAG(F_CF);
193 break;
Jason Jinece92f82007-07-06 08:34:56 +0800194 case 0x93:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200195 name = "SETNB\t";
196 cond = !ACCESS_FLAG(F_CF);
197 break;
Jason Jinece92f82007-07-06 08:34:56 +0800198 case 0x94:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200199 name = "SETZ\t";
200 cond = ACCESS_FLAG(F_ZF);
201 break;
Jason Jinece92f82007-07-06 08:34:56 +0800202 case 0x95:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200203 name = "SETNZ\t";
204 cond = !ACCESS_FLAG(F_ZF);
205 break;
Jason Jinece92f82007-07-06 08:34:56 +0800206 case 0x96:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200207 name = "SETBE\t";
208 cond = ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF);
209 break;
Jason Jinece92f82007-07-06 08:34:56 +0800210 case 0x97:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200211 name = "SETNBE\t";
212 cond = !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
213 break;
Jason Jinece92f82007-07-06 08:34:56 +0800214 case 0x98:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200215 name = "SETS\t";
216 cond = ACCESS_FLAG(F_SF);
217 break;
Jason Jinece92f82007-07-06 08:34:56 +0800218 case 0x99:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200219 name = "SETNS\t";
220 cond = !ACCESS_FLAG(F_SF);
221 break;
Jason Jinece92f82007-07-06 08:34:56 +0800222 case 0x9a:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200223 name = "SETP\t";
224 cond = ACCESS_FLAG(F_PF);
225 break;
Jason Jinece92f82007-07-06 08:34:56 +0800226 case 0x9b:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200227 name = "SETNP\t";
228 cond = !ACCESS_FLAG(F_PF);
229 break;
Jason Jinece92f82007-07-06 08:34:56 +0800230 case 0x9c:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200231 name = "SETL\t";
232 cond = xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
233 break;
Jason Jinece92f82007-07-06 08:34:56 +0800234 case 0x9d:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200235 name = "SETNL\t";
236 cond = !xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
237 break;
Jason Jinece92f82007-07-06 08:34:56 +0800238 case 0x9e:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200239 name = "SETLE\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 case 0x9f:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200244 name = "SETNLE\t";
245 cond = !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
246 ACCESS_FLAG(F_ZF));
247 break;
Jason Jinece92f82007-07-06 08:34:56 +0800248 }
249 DECODE_PRINTF(name);
250 FETCH_DECODE_MODRM(mod, rh, rl);
251 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200252 destoffset = decode_rmXX_address(mod, rl);
253 TRACE_AND_STEP();
254 store_data_byte(destoffset, cond ? 0x01 : 0x00);
255 } else { /* register to register */
256 destreg = DECODE_RM_BYTE_REGISTER(rl);
257 TRACE_AND_STEP();
258 *destreg = cond ? 0x01 : 0x00;
Jason Jinece92f82007-07-06 08:34:56 +0800259 }
260 DECODE_CLEAR_SEGOVR();
261 END_OF_INSTR();
262}
263
264/****************************************************************************
265REMARKS:
266Handles opcode 0x0f,0xa0
267****************************************************************************/
268void x86emuOp2_push_FS(u8 X86EMU_UNUSED(op2))
269{
270 START_OF_INSTR();
271 DECODE_PRINTF("PUSH\tFS\n");
272 TRACE_AND_STEP();
273 push_word(M.x86.R_FS);
274 DECODE_CLEAR_SEGOVR();
275 END_OF_INSTR();
276}
277
278/****************************************************************************
279REMARKS:
280Handles opcode 0x0f,0xa1
281****************************************************************************/
282void x86emuOp2_pop_FS(u8 X86EMU_UNUSED(op2))
283{
284 START_OF_INSTR();
285 DECODE_PRINTF("POP\tFS\n");
286 TRACE_AND_STEP();
287 M.x86.R_FS = pop_word();
288 DECODE_CLEAR_SEGOVR();
289 END_OF_INSTR();
290}
291
292/****************************************************************************
293REMARKS:
294Handles opcode 0x0f,0xa3
295****************************************************************************/
296void x86emuOp2_bt_R(u8 X86EMU_UNUSED(op2))
297{
298 int mod, rl, rh;
299 uint srcoffset;
300 int bit,disp;
301
302 START_OF_INSTR();
303 DECODE_PRINTF("BT\t");
304 FETCH_DECODE_MODRM(mod, rh, rl);
305 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200306 srcoffset = decode_rmXX_address(mod, rl);
307 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
308 u32 srcval;
309 u32 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800310
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200311 DECODE_PRINTF(",");
312 shiftreg = DECODE_RM_LONG_REGISTER(rh);
313 TRACE_AND_STEP();
314 bit = *shiftreg & 0x1F;
315 disp = (s16)*shiftreg >> 5;
316 srcval = fetch_data_long(srcoffset+disp);
317 CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF);
318 } else {
319 u16 srcval;
320 u16 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800321
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200322 DECODE_PRINTF(",");
323 shiftreg = DECODE_RM_WORD_REGISTER(rh);
324 TRACE_AND_STEP();
325 bit = *shiftreg & 0xF;
326 disp = (s16)*shiftreg >> 4;
327 srcval = fetch_data_word(srcoffset+disp);
328 CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF);
329 }
330 } else { /* register to register */
331 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
332 u32 *srcreg,*shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800333
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200334 srcreg = DECODE_RM_LONG_REGISTER(rl);
335 DECODE_PRINTF(",");
336 shiftreg = DECODE_RM_LONG_REGISTER(rh);
337 TRACE_AND_STEP();
338 bit = *shiftreg & 0x1F;
339 CONDITIONAL_SET_FLAG(*srcreg & (0x1 << bit),F_CF);
340 } else {
341 u16 *srcreg,*shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800342
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200343 srcreg = DECODE_RM_WORD_REGISTER(rl);
344 DECODE_PRINTF(",");
345 shiftreg = DECODE_RM_WORD_REGISTER(rh);
346 TRACE_AND_STEP();
347 bit = *shiftreg & 0xF;
348 CONDITIONAL_SET_FLAG(*srcreg & (0x1 << bit),F_CF);
349 }
Jason Jinece92f82007-07-06 08:34:56 +0800350 }
351 DECODE_CLEAR_SEGOVR();
352 END_OF_INSTR();
353}
354
355/****************************************************************************
356REMARKS:
357Handles opcode 0x0f,0xa4
358****************************************************************************/
359void x86emuOp2_shld_IMM(u8 X86EMU_UNUSED(op2))
360{
361 int mod, rl, rh;
362 uint destoffset;
363 u8 shift;
364
365 START_OF_INSTR();
366 DECODE_PRINTF("SHLD\t");
367 FETCH_DECODE_MODRM(mod, rh, rl);
368 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200369 destoffset = decode_rmXX_address(mod, rl);
370 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
371 u32 destval;
372 u32 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800373
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200374 DECODE_PRINTF(",");
375 shiftreg = DECODE_RM_LONG_REGISTER(rh);
376 DECODE_PRINTF(",");
377 shift = fetch_byte_imm();
378 DECODE_PRINTF2("%d\n", shift);
379 TRACE_AND_STEP();
380 destval = fetch_data_long(destoffset);
381 destval = shld_long(destval,*shiftreg,shift);
382 store_data_long(destoffset, destval);
383 } else {
384 u16 destval;
385 u16 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800386
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200387 DECODE_PRINTF(",");
388 shiftreg = DECODE_RM_WORD_REGISTER(rh);
389 DECODE_PRINTF(",");
390 shift = fetch_byte_imm();
391 DECODE_PRINTF2("%d\n", shift);
392 TRACE_AND_STEP();
393 destval = fetch_data_word(destoffset);
394 destval = shld_word(destval,*shiftreg,shift);
395 store_data_word(destoffset, destval);
396 }
397 } else { /* register to register */
398 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
399 u32 *destreg,*shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800400
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200401 destreg = DECODE_RM_LONG_REGISTER(rl);
402 DECODE_PRINTF(",");
403 shiftreg = DECODE_RM_LONG_REGISTER(rh);
404 DECODE_PRINTF(",");
405 shift = fetch_byte_imm();
406 DECODE_PRINTF2("%d\n", shift);
407 TRACE_AND_STEP();
408 *destreg = shld_long(*destreg,*shiftreg,shift);
409 } else {
410 u16 *destreg,*shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800411
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200412 destreg = DECODE_RM_WORD_REGISTER(rl);
413 DECODE_PRINTF(",");
414 shiftreg = DECODE_RM_WORD_REGISTER(rh);
415 DECODE_PRINTF(",");
416 shift = fetch_byte_imm();
417 DECODE_PRINTF2("%d\n", shift);
418 TRACE_AND_STEP();
419 *destreg = shld_word(*destreg,*shiftreg,shift);
420 }
Jason Jinece92f82007-07-06 08:34:56 +0800421 }
422 DECODE_CLEAR_SEGOVR();
423 END_OF_INSTR();
424}
425
426/****************************************************************************
427REMARKS:
428Handles opcode 0x0f,0xa5
429****************************************************************************/
430void x86emuOp2_shld_CL(u8 X86EMU_UNUSED(op2))
431{
432 int mod, rl, rh;
433 uint destoffset;
434
435 START_OF_INSTR();
436 DECODE_PRINTF("SHLD\t");
437 FETCH_DECODE_MODRM(mod, rh, rl);
438 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200439 destoffset = decode_rmXX_address(mod, rl);
440 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
441 u32 destval;
442 u32 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800443
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200444 DECODE_PRINTF(",");
445 shiftreg = DECODE_RM_LONG_REGISTER(rh);
446 DECODE_PRINTF(",CL\n");
447 TRACE_AND_STEP();
448 destval = fetch_data_long(destoffset);
449 destval = shld_long(destval,*shiftreg,M.x86.R_CL);
450 store_data_long(destoffset, destval);
451 } else {
452 u16 destval;
453 u16 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800454
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200455 DECODE_PRINTF(",");
456 shiftreg = DECODE_RM_WORD_REGISTER(rh);
457 DECODE_PRINTF(",CL\n");
458 TRACE_AND_STEP();
459 destval = fetch_data_word(destoffset);
460 destval = shld_word(destval,*shiftreg,M.x86.R_CL);
461 store_data_word(destoffset, destval);
462 }
463 } else { /* register to register */
464 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
465 u32 *destreg,*shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800466
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200467 destreg = DECODE_RM_LONG_REGISTER(rl);
468 DECODE_PRINTF(",");
469 shiftreg = DECODE_RM_LONG_REGISTER(rh);
470 DECODE_PRINTF(",CL\n");
471 TRACE_AND_STEP();
472 *destreg = shld_long(*destreg,*shiftreg,M.x86.R_CL);
473 } else {
474 u16 *destreg,*shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800475
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200476 destreg = DECODE_RM_WORD_REGISTER(rl);
477 DECODE_PRINTF(",");
478 shiftreg = DECODE_RM_WORD_REGISTER(rh);
479 DECODE_PRINTF(",CL\n");
480 TRACE_AND_STEP();
481 *destreg = shld_word(*destreg,*shiftreg,M.x86.R_CL);
482 }
Jason Jinece92f82007-07-06 08:34:56 +0800483 }
484 DECODE_CLEAR_SEGOVR();
485 END_OF_INSTR();
486}
487
488/****************************************************************************
489REMARKS:
490Handles opcode 0x0f,0xa8
491****************************************************************************/
492void x86emuOp2_push_GS(u8 X86EMU_UNUSED(op2))
493{
494 START_OF_INSTR();
495 DECODE_PRINTF("PUSH\tGS\n");
496 TRACE_AND_STEP();
497 push_word(M.x86.R_GS);
498 DECODE_CLEAR_SEGOVR();
499 END_OF_INSTR();
500}
501
502/****************************************************************************
503REMARKS:
504Handles opcode 0x0f,0xa9
505****************************************************************************/
506void x86emuOp2_pop_GS(u8 X86EMU_UNUSED(op2))
507{
508 START_OF_INSTR();
509 DECODE_PRINTF("POP\tGS\n");
510 TRACE_AND_STEP();
511 M.x86.R_GS = pop_word();
512 DECODE_CLEAR_SEGOVR();
513 END_OF_INSTR();
514}
515
516/****************************************************************************
517REMARKS:
518Handles opcode 0x0f,0xaa
519****************************************************************************/
520void x86emuOp2_bts_R(u8 X86EMU_UNUSED(op2))
521{
522 int mod, rl, rh;
523 uint srcoffset;
524 int bit,disp;
525
526 START_OF_INSTR();
527 DECODE_PRINTF("BTS\t");
528 FETCH_DECODE_MODRM(mod, rh, rl);
529 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200530 srcoffset = decode_rmXX_address(mod, rl);
531 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
532 u32 srcval,mask;
533 u32 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800534
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200535 DECODE_PRINTF(",");
536 shiftreg = DECODE_RM_LONG_REGISTER(rh);
537 TRACE_AND_STEP();
538 bit = *shiftreg & 0x1F;
539 disp = (s16)*shiftreg >> 5;
540 srcval = fetch_data_long(srcoffset+disp);
541 mask = (0x1 << bit);
542 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
543 store_data_long(srcoffset+disp, srcval | mask);
544 } else {
545 u16 srcval,mask;
546 u16 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800547
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200548 DECODE_PRINTF(",");
549 shiftreg = DECODE_RM_WORD_REGISTER(rh);
550 TRACE_AND_STEP();
551 bit = *shiftreg & 0xF;
552 disp = (s16)*shiftreg >> 4;
553 srcval = fetch_data_word(srcoffset+disp);
554 mask = (u16)(0x1 << bit);
555 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
556 store_data_word(srcoffset+disp, srcval | mask);
557 }
558 } else { /* register to register */
559 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
560 u32 *srcreg,*shiftreg;
561 u32 mask;
Jason Jinece92f82007-07-06 08:34:56 +0800562
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200563 srcreg = DECODE_RM_LONG_REGISTER(rl);
564 DECODE_PRINTF(",");
565 shiftreg = DECODE_RM_LONG_REGISTER(rh);
566 TRACE_AND_STEP();
567 bit = *shiftreg & 0x1F;
568 mask = (0x1 << bit);
569 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
570 *srcreg |= mask;
571 } else {
572 u16 *srcreg,*shiftreg;
573 u16 mask;
Jason Jinece92f82007-07-06 08:34:56 +0800574
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200575 srcreg = DECODE_RM_WORD_REGISTER(rl);
576 DECODE_PRINTF(",");
577 shiftreg = DECODE_RM_WORD_REGISTER(rh);
578 TRACE_AND_STEP();
579 bit = *shiftreg & 0xF;
580 mask = (u16)(0x1 << bit);
581 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
582 *srcreg |= mask;
583 }
Jason Jinece92f82007-07-06 08:34:56 +0800584 }
585 DECODE_CLEAR_SEGOVR();
586 END_OF_INSTR();
587}
588
589/****************************************************************************
590REMARKS:
591Handles opcode 0x0f,0xac
592****************************************************************************/
593void x86emuOp2_shrd_IMM(u8 X86EMU_UNUSED(op2))
594{
595 int mod, rl, rh;
596 uint destoffset;
597 u8 shift;
598
599 START_OF_INSTR();
600 DECODE_PRINTF("SHLD\t");
601 FETCH_DECODE_MODRM(mod, rh, rl);
602 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200603 destoffset = decode_rmXX_address(mod, rl);
604 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
605 u32 destval;
606 u32 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800607
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200608 DECODE_PRINTF(",");
609 shiftreg = DECODE_RM_LONG_REGISTER(rh);
610 DECODE_PRINTF(",");
611 shift = fetch_byte_imm();
612 DECODE_PRINTF2("%d\n", shift);
613 TRACE_AND_STEP();
614 destval = fetch_data_long(destoffset);
615 destval = shrd_long(destval,*shiftreg,shift);
616 store_data_long(destoffset, destval);
617 } else {
618 u16 destval;
619 u16 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800620
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200621 DECODE_PRINTF(",");
622 shiftreg = DECODE_RM_WORD_REGISTER(rh);
623 DECODE_PRINTF(",");
624 shift = fetch_byte_imm();
625 DECODE_PRINTF2("%d\n", shift);
626 TRACE_AND_STEP();
627 destval = fetch_data_word(destoffset);
628 destval = shrd_word(destval,*shiftreg,shift);
629 store_data_word(destoffset, destval);
630 }
631 } else { /* register to register */
632 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
633 u32 *destreg,*shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800634
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200635 destreg = DECODE_RM_LONG_REGISTER(rl);
636 DECODE_PRINTF(",");
637 shiftreg = DECODE_RM_LONG_REGISTER(rh);
638 DECODE_PRINTF(",");
639 shift = fetch_byte_imm();
640 DECODE_PRINTF2("%d\n", shift);
641 TRACE_AND_STEP();
642 *destreg = shrd_long(*destreg,*shiftreg,shift);
643 } else {
644 u16 *destreg,*shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800645
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200646 destreg = DECODE_RM_WORD_REGISTER(rl);
647 DECODE_PRINTF(",");
648 shiftreg = DECODE_RM_WORD_REGISTER(rh);
649 DECODE_PRINTF(",");
650 shift = fetch_byte_imm();
651 DECODE_PRINTF2("%d\n", shift);
652 TRACE_AND_STEP();
653 *destreg = shrd_word(*destreg,*shiftreg,shift);
654 }
Jason Jinece92f82007-07-06 08:34:56 +0800655 }
656 DECODE_CLEAR_SEGOVR();
657 END_OF_INSTR();
658}
659
660/****************************************************************************
661REMARKS:
662Handles opcode 0x0f,0xad
663****************************************************************************/
664void x86emuOp2_shrd_CL(u8 X86EMU_UNUSED(op2))
665{
666 int mod, rl, rh;
667 uint destoffset;
668
669 START_OF_INSTR();
670 DECODE_PRINTF("SHLD\t");
671 FETCH_DECODE_MODRM(mod, rh, rl);
672 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200673 destoffset = decode_rmXX_address(mod, rl);
674 DECODE_PRINTF(",");
675 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
676 u32 destval;
677 u32 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800678
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200679 shiftreg = DECODE_RM_LONG_REGISTER(rh);
680 DECODE_PRINTF(",CL\n");
681 TRACE_AND_STEP();
682 destval = fetch_data_long(destoffset);
683 destval = shrd_long(destval,*shiftreg,M.x86.R_CL);
684 store_data_long(destoffset, destval);
685 } else {
686 u16 destval;
687 u16 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800688
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200689 shiftreg = DECODE_RM_WORD_REGISTER(rh);
690 DECODE_PRINTF(",CL\n");
691 TRACE_AND_STEP();
692 destval = fetch_data_word(destoffset);
693 destval = shrd_word(destval,*shiftreg,M.x86.R_CL);
694 store_data_word(destoffset, destval);
695 }
696 } else { /* register to register */
697 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
698 u32 *destreg,*shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800699
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200700 destreg = DECODE_RM_LONG_REGISTER(rl);
701 DECODE_PRINTF(",");
702 shiftreg = DECODE_RM_LONG_REGISTER(rh);
703 DECODE_PRINTF(",CL\n");
704 TRACE_AND_STEP();
705 *destreg = shrd_long(*destreg,*shiftreg,M.x86.R_CL);
706 } else {
707 u16 *destreg,*shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800708
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200709 destreg = DECODE_RM_WORD_REGISTER(rl);
710 DECODE_PRINTF(",");
711 shiftreg = DECODE_RM_WORD_REGISTER(rh);
712 DECODE_PRINTF(",CL\n");
713 TRACE_AND_STEP();
714 *destreg = shrd_word(*destreg,*shiftreg,M.x86.R_CL);
715 }
Jason Jinece92f82007-07-06 08:34:56 +0800716 }
717 DECODE_CLEAR_SEGOVR();
718 END_OF_INSTR();
719}
720
721/****************************************************************************
722REMARKS:
723Handles opcode 0x0f,0xaf
724****************************************************************************/
725void x86emuOp2_imul_R_RM(u8 X86EMU_UNUSED(op2))
726{
727 int mod, rl, rh;
728 uint srcoffset;
729
730 START_OF_INSTR();
731 DECODE_PRINTF("IMUL\t");
732 FETCH_DECODE_MODRM(mod, rh, rl);
733 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200734 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
735 u32 *destreg;
736 u32 srcval;
737 u32 res_lo,res_hi;
Jason Jinece92f82007-07-06 08:34:56 +0800738
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200739 destreg = DECODE_RM_LONG_REGISTER(rh);
740 DECODE_PRINTF(",");
741 srcoffset = decode_rmXX_address(mod, rl);
742 srcval = fetch_data_long(srcoffset);
743 TRACE_AND_STEP();
744 imul_long_direct(&res_lo,&res_hi,(s32)*destreg,(s32)srcval);
745 if (res_hi != 0) {
746 SET_FLAG(F_CF);
747 SET_FLAG(F_OF);
748 } else {
749 CLEAR_FLAG(F_CF);
750 CLEAR_FLAG(F_OF);
751 }
752 *destreg = (u32)res_lo;
753 } else {
754 u16 *destreg;
755 u16 srcval;
756 u32 res;
Jason Jinece92f82007-07-06 08:34:56 +0800757
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200758 destreg = DECODE_RM_WORD_REGISTER(rh);
759 DECODE_PRINTF(",");
760 srcoffset = decode_rmXX_address(mod, rl);
761 srcval = fetch_data_word(srcoffset);
762 TRACE_AND_STEP();
763 res = (s16)*destreg * (s16)srcval;
764 if (res > 0xFFFF) {
765 SET_FLAG(F_CF);
766 SET_FLAG(F_OF);
767 } else {
768 CLEAR_FLAG(F_CF);
769 CLEAR_FLAG(F_OF);
770 }
771 *destreg = (u16)res;
772 }
773 } else { /* register to register */
774 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
775 u32 *destreg,*srcreg;
776 u32 res_lo,res_hi;
Jason Jinece92f82007-07-06 08:34:56 +0800777
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200778 destreg = DECODE_RM_LONG_REGISTER(rh);
779 DECODE_PRINTF(",");
780 srcreg = DECODE_RM_LONG_REGISTER(rl);
781 TRACE_AND_STEP();
782 imul_long_direct(&res_lo,&res_hi,(s32)*destreg,(s32)*srcreg);
783 if (res_hi != 0) {
784 SET_FLAG(F_CF);
785 SET_FLAG(F_OF);
786 } else {
787 CLEAR_FLAG(F_CF);
788 CLEAR_FLAG(F_OF);
789 }
790 *destreg = (u32)res_lo;
791 } else {
792 u16 *destreg,*srcreg;
793 u32 res;
Jason Jinece92f82007-07-06 08:34:56 +0800794
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200795 destreg = DECODE_RM_WORD_REGISTER(rh);
796 DECODE_PRINTF(",");
797 srcreg = DECODE_RM_WORD_REGISTER(rl);
798 res = (s16)*destreg * (s16)*srcreg;
799 if (res > 0xFFFF) {
800 SET_FLAG(F_CF);
801 SET_FLAG(F_OF);
802 } else {
803 CLEAR_FLAG(F_CF);
804 CLEAR_FLAG(F_OF);
805 }
806 *destreg = (u16)res;
807 }
Jason Jinece92f82007-07-06 08:34:56 +0800808 }
809 DECODE_CLEAR_SEGOVR();
810 END_OF_INSTR();
811}
812
813/****************************************************************************
814REMARKS:
815Handles opcode 0x0f,0xb2
816****************************************************************************/
817void x86emuOp2_lss_R_IMM(u8 X86EMU_UNUSED(op2))
818{
819 int mod, rh, rl;
820 u16 *dstreg;
821 uint srcoffset;
822
823 START_OF_INSTR();
824 DECODE_PRINTF("LSS\t");
825 FETCH_DECODE_MODRM(mod, rh, rl);
826 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200827 dstreg = DECODE_RM_WORD_REGISTER(rh);
828 DECODE_PRINTF(",");
829 srcoffset = decode_rmXX_address(mod, rl);
830 DECODE_PRINTF("\n");
831 TRACE_AND_STEP();
832 *dstreg = fetch_data_word(srcoffset);
833 M.x86.R_SS = fetch_data_word(srcoffset + 2);
834 } else { /* register to register */
835 /* UNDEFINED! */
836 TRACE_AND_STEP();
Jason Jinece92f82007-07-06 08:34:56 +0800837 }
838 DECODE_CLEAR_SEGOVR();
839 END_OF_INSTR();
840}
841
842/****************************************************************************
843REMARKS:
844Handles opcode 0x0f,0xb3
845****************************************************************************/
846void x86emuOp2_btr_R(u8 X86EMU_UNUSED(op2))
847{
848 int mod, rl, rh;
849 uint srcoffset;
850 int bit,disp;
851
852 START_OF_INSTR();
853 DECODE_PRINTF("BTR\t");
854 FETCH_DECODE_MODRM(mod, rh, rl);
855 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200856 srcoffset = decode_rmXX_address(mod, rl);
857 DECODE_PRINTF(",");
858 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
859 u32 srcval,mask;
860 u32 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800861
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200862 shiftreg = DECODE_RM_LONG_REGISTER(rh);
863 TRACE_AND_STEP();
864 bit = *shiftreg & 0x1F;
865 disp = (s16)*shiftreg >> 5;
866 srcval = fetch_data_long(srcoffset+disp);
867 mask = (0x1 << bit);
868 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
869 store_data_long(srcoffset+disp, srcval & ~mask);
870 } else {
871 u16 srcval,mask;
872 u16 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800873
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200874 shiftreg = DECODE_RM_WORD_REGISTER(rh);
875 TRACE_AND_STEP();
876 bit = *shiftreg & 0xF;
877 disp = (s16)*shiftreg >> 4;
878 srcval = fetch_data_word(srcoffset+disp);
879 mask = (u16)(0x1 << bit);
880 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
881 store_data_word(srcoffset+disp, (u16)(srcval & ~mask));
882 }
883 } else { /* register to register */
884 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
885 u32 *srcreg,*shiftreg;
886 u32 mask;
Jason Jinece92f82007-07-06 08:34:56 +0800887
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200888 srcreg = DECODE_RM_LONG_REGISTER(rl);
889 DECODE_PRINTF(",");
890 shiftreg = DECODE_RM_LONG_REGISTER(rh);
891 TRACE_AND_STEP();
892 bit = *shiftreg & 0x1F;
893 mask = (0x1 << bit);
894 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
895 *srcreg &= ~mask;
896 } else {
897 u16 *srcreg,*shiftreg;
898 u16 mask;
Jason Jinece92f82007-07-06 08:34:56 +0800899
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200900 srcreg = DECODE_RM_WORD_REGISTER(rl);
901 DECODE_PRINTF(",");
902 shiftreg = DECODE_RM_WORD_REGISTER(rh);
903 TRACE_AND_STEP();
904 bit = *shiftreg & 0xF;
905 mask = (u16)(0x1 << bit);
906 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
907 *srcreg &= ~mask;
908 }
Jason Jinece92f82007-07-06 08:34:56 +0800909 }
910 DECODE_CLEAR_SEGOVR();
911 END_OF_INSTR();
912}
913
914/****************************************************************************
915REMARKS:
916Handles opcode 0x0f,0xb4
917****************************************************************************/
918void x86emuOp2_lfs_R_IMM(u8 X86EMU_UNUSED(op2))
919{
920 int mod, rh, rl;
921 u16 *dstreg;
922 uint srcoffset;
923
924 START_OF_INSTR();
925 DECODE_PRINTF("LFS\t");
926 FETCH_DECODE_MODRM(mod, rh, rl);
927 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200928 dstreg = DECODE_RM_WORD_REGISTER(rh);
929 DECODE_PRINTF(",");
930 srcoffset = decode_rmXX_address(mod, rl);
931 DECODE_PRINTF("\n");
932 TRACE_AND_STEP();
933 *dstreg = fetch_data_word(srcoffset);
934 M.x86.R_FS = fetch_data_word(srcoffset + 2);
935 } else { /* register to register */
936 /* UNDEFINED! */
937 TRACE_AND_STEP();
Jason Jinece92f82007-07-06 08:34:56 +0800938 }
939 DECODE_CLEAR_SEGOVR();
940 END_OF_INSTR();
941}
942
943/****************************************************************************
944REMARKS:
945Handles opcode 0x0f,0xb5
946****************************************************************************/
947void x86emuOp2_lgs_R_IMM(u8 X86EMU_UNUSED(op2))
948{
949 int mod, rh, rl;
950 u16 *dstreg;
951 uint srcoffset;
952
953 START_OF_INSTR();
954 DECODE_PRINTF("LGS\t");
955 FETCH_DECODE_MODRM(mod, rh, rl);
956 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200957 dstreg = DECODE_RM_WORD_REGISTER(rh);
958 DECODE_PRINTF(",");
959 srcoffset = decode_rmXX_address(mod, rl);
960 DECODE_PRINTF("\n");
961 TRACE_AND_STEP();
962 *dstreg = fetch_data_word(srcoffset);
963 M.x86.R_GS = fetch_data_word(srcoffset + 2);
964 } else { /* register to register */
965 /* UNDEFINED! */
966 TRACE_AND_STEP();
Jason Jinece92f82007-07-06 08:34:56 +0800967 }
968 DECODE_CLEAR_SEGOVR();
969 END_OF_INSTR();
970}
971
972/****************************************************************************
973REMARKS:
974Handles opcode 0x0f,0xb6
975****************************************************************************/
976void x86emuOp2_movzx_byte_R_RM(u8 X86EMU_UNUSED(op2))
977{
978 int mod, rl, rh;
979 uint srcoffset;
980
981 START_OF_INSTR();
982 DECODE_PRINTF("MOVZX\t");
983 FETCH_DECODE_MODRM(mod, rh, rl);
984 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200985 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
986 u32 *destreg;
987 u32 srcval;
Jason Jinece92f82007-07-06 08:34:56 +0800988
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200989 destreg = DECODE_RM_LONG_REGISTER(rh);
990 DECODE_PRINTF(",");
991 srcoffset = decode_rmXX_address(mod, rl);
992 srcval = fetch_data_byte(srcoffset);
993 DECODE_PRINTF("\n");
994 TRACE_AND_STEP();
995 *destreg = srcval;
996 } else {
997 u16 *destreg;
998 u16 srcval;
Jason Jinece92f82007-07-06 08:34:56 +0800999
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001000 destreg = DECODE_RM_WORD_REGISTER(rh);
1001 DECODE_PRINTF(",");
1002 srcoffset = decode_rmXX_address(mod, rl);
1003 srcval = fetch_data_byte(srcoffset);
1004 DECODE_PRINTF("\n");
1005 TRACE_AND_STEP();
1006 *destreg = srcval;
1007 }
1008 } else { /* register to register */
1009 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1010 u32 *destreg;
1011 u8 *srcreg;
Jason Jinece92f82007-07-06 08:34:56 +08001012
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001013 destreg = DECODE_RM_LONG_REGISTER(rh);
1014 DECODE_PRINTF(",");
1015 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1016 DECODE_PRINTF("\n");
1017 TRACE_AND_STEP();
1018 *destreg = *srcreg;
1019 } else {
1020 u16 *destreg;
1021 u8 *srcreg;
Jason Jinece92f82007-07-06 08:34:56 +08001022
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001023 destreg = DECODE_RM_WORD_REGISTER(rh);
1024 DECODE_PRINTF(",");
1025 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1026 DECODE_PRINTF("\n");
1027 TRACE_AND_STEP();
1028 *destreg = *srcreg;
1029 }
Jason Jinece92f82007-07-06 08:34:56 +08001030 }
1031 DECODE_CLEAR_SEGOVR();
1032 END_OF_INSTR();
1033}
1034
1035/****************************************************************************
1036REMARKS:
1037Handles opcode 0x0f,0xb7
1038****************************************************************************/
1039void x86emuOp2_movzx_word_R_RM(u8 X86EMU_UNUSED(op2))
1040{
1041 int mod, rl, rh;
1042 uint srcoffset;
1043 u32 *destreg;
1044 u32 srcval;
1045 u16 *srcreg;
1046
1047 START_OF_INSTR();
1048 DECODE_PRINTF("MOVZX\t");
1049 FETCH_DECODE_MODRM(mod, rh, rl);
1050 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001051 destreg = DECODE_RM_LONG_REGISTER(rh);
1052 DECODE_PRINTF(",");
1053 srcoffset = decode_rmXX_address(mod, rl);
1054 srcval = fetch_data_word(srcoffset);
1055 DECODE_PRINTF("\n");
1056 TRACE_AND_STEP();
1057 *destreg = srcval;
1058 } else { /* register to register */
1059 destreg = DECODE_RM_LONG_REGISTER(rh);
1060 DECODE_PRINTF(",");
1061 srcreg = DECODE_RM_WORD_REGISTER(rl);
1062 DECODE_PRINTF("\n");
1063 TRACE_AND_STEP();
1064 *destreg = *srcreg;
Jason Jinece92f82007-07-06 08:34:56 +08001065 }
1066 DECODE_CLEAR_SEGOVR();
1067 END_OF_INSTR();
1068}
1069
1070/****************************************************************************
1071REMARKS:
1072Handles opcode 0x0f,0xba
1073****************************************************************************/
1074void x86emuOp2_btX_I(u8 X86EMU_UNUSED(op2))
1075{
1076 int mod, rl, rh;
1077 uint srcoffset;
1078 u8 shift;
1079 int bit;
1080
1081 START_OF_INSTR();
1082 FETCH_DECODE_MODRM(mod, rh, rl);
1083 switch (rh) {
1084 case 4:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001085 DECODE_PRINTF("BT\t");
1086 break;
Jason Jinece92f82007-07-06 08:34:56 +08001087 case 5:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001088 DECODE_PRINTF("BTS\t");
1089 break;
Jason Jinece92f82007-07-06 08:34:56 +08001090 case 6:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001091 DECODE_PRINTF("BTR\t");
1092 break;
Jason Jinece92f82007-07-06 08:34:56 +08001093 case 7:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001094 DECODE_PRINTF("BTC\t");
1095 break;
Jason Jinece92f82007-07-06 08:34:56 +08001096 default:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001097 DECODE_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n");
1098 TRACE_REGS();
1099 printk("%04x:%04x: %02X%02X ILLEGAL EXTENDED X86 OPCODE EXTENSION!\n",
1100 M.x86.R_CS, M.x86.R_IP-3,op2, (mod<<6)|(rh<<3)|rl);
1101 HALT_SYS();
Jason Jinece92f82007-07-06 08:34:56 +08001102 }
1103 if (mod < 3) {
1104
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001105 srcoffset = decode_rmXX_address(mod, rl);
1106 shift = fetch_byte_imm();
1107 DECODE_PRINTF2(",%d\n", shift);
1108 TRACE_AND_STEP();
Jason Jinece92f82007-07-06 08:34:56 +08001109
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001110 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1111 u32 srcval, mask;
Jason Jinece92f82007-07-06 08:34:56 +08001112
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001113 bit = shift & 0x1F;
1114 srcval = fetch_data_long(srcoffset);
1115 mask = (0x1 << bit);
1116 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1117 switch (rh) {
1118 case 5:
1119 store_data_long(srcoffset, srcval | mask);
1120 break;
1121 case 6:
1122 store_data_long(srcoffset, srcval & ~mask);
1123 break;
1124 case 7:
1125 store_data_long(srcoffset, srcval ^ mask);
1126 break;
1127 default:
1128 break;
1129 }
1130 } else {
1131 u16 srcval, mask;
Jason Jinece92f82007-07-06 08:34:56 +08001132
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001133 bit = shift & 0xF;
1134 srcval = fetch_data_word(srcoffset);
1135 mask = (0x1 << bit);
1136 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1137 switch (rh) {
1138 case 5:
1139 store_data_word(srcoffset, srcval | mask);
1140 break;
1141 case 6:
1142 store_data_word(srcoffset, srcval & ~mask);
1143 break;
1144 case 7:
1145 store_data_word(srcoffset, srcval ^ mask);
1146 break;
1147 default:
1148 break;
1149 }
1150 }
1151 } else { /* register to register */
1152 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1153 u32 *srcreg;
1154 u32 mask;
Jason Jinece92f82007-07-06 08:34:56 +08001155
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001156 srcreg = DECODE_RM_LONG_REGISTER(rl);
1157 shift = fetch_byte_imm();
1158 DECODE_PRINTF2(",%d\n", shift);
1159 TRACE_AND_STEP();
1160 bit = shift & 0x1F;
1161 mask = (0x1 << bit);
1162 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1163 switch (rh) {
1164 case 5:
1165 *srcreg |= mask;
1166 break;
1167 case 6:
1168 *srcreg &= ~mask;
1169 break;
1170 case 7:
1171 *srcreg ^= mask;
1172 break;
1173 default:
1174 break;
1175 }
1176 } else {
1177 u16 *srcreg;
1178 u16 mask;
Jason Jinece92f82007-07-06 08:34:56 +08001179
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001180 srcreg = DECODE_RM_WORD_REGISTER(rl);
1181 shift = fetch_byte_imm();
1182 DECODE_PRINTF2(",%d\n", shift);
1183 TRACE_AND_STEP();
1184 bit = shift & 0xF;
1185 mask = (0x1 << bit);
1186 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1187 switch (rh) {
1188 case 5:
1189 *srcreg |= mask;
1190 break;
1191 case 6:
1192 *srcreg &= ~mask;
1193 break;
1194 case 7:
1195 *srcreg ^= mask;
1196 break;
1197 default:
1198 break;
1199 }
1200 }
Jason Jinece92f82007-07-06 08:34:56 +08001201 }
1202 DECODE_CLEAR_SEGOVR();
1203 END_OF_INSTR();
1204}
1205
1206/****************************************************************************
1207REMARKS:
1208Handles opcode 0x0f,0xbb
1209****************************************************************************/
1210void x86emuOp2_btc_R(u8 X86EMU_UNUSED(op2))
1211{
1212 int mod, rl, rh;
1213 uint srcoffset;
1214 int bit,disp;
1215
1216 START_OF_INSTR();
1217 DECODE_PRINTF("BTC\t");
1218 FETCH_DECODE_MODRM(mod, rh, rl);
1219 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001220 srcoffset = decode_rmXX_address(mod, rl);
1221 DECODE_PRINTF(",");
1222 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1223 u32 srcval,mask;
1224 u32 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +08001225
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001226 shiftreg = DECODE_RM_LONG_REGISTER(rh);
1227 TRACE_AND_STEP();
1228 bit = *shiftreg & 0x1F;
1229 disp = (s16)*shiftreg >> 5;
1230 srcval = fetch_data_long(srcoffset+disp);
1231 mask = (0x1 << bit);
1232 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1233 store_data_long(srcoffset+disp, srcval ^ mask);
1234 } else {
1235 u16 srcval,mask;
1236 u16 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +08001237
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001238 shiftreg = DECODE_RM_WORD_REGISTER(rh);
1239 TRACE_AND_STEP();
1240 bit = *shiftreg & 0xF;
1241 disp = (s16)*shiftreg >> 4;
1242 srcval = fetch_data_word(srcoffset+disp);
1243 mask = (u16)(0x1 << bit);
1244 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1245 store_data_word(srcoffset+disp, (u16)(srcval ^ mask));
1246 }
1247 } else { /* register to register */
1248 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1249 u32 *srcreg,*shiftreg;
1250 u32 mask;
Jason Jinece92f82007-07-06 08:34:56 +08001251
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001252 srcreg = DECODE_RM_LONG_REGISTER(rl);
1253 DECODE_PRINTF(",");
1254 shiftreg = DECODE_RM_LONG_REGISTER(rh);
1255 TRACE_AND_STEP();
1256 bit = *shiftreg & 0x1F;
1257 mask = (0x1 << bit);
1258 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1259 *srcreg ^= mask;
1260 } else {
1261 u16 *srcreg,*shiftreg;
1262 u16 mask;
Jason Jinece92f82007-07-06 08:34:56 +08001263
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001264 srcreg = DECODE_RM_WORD_REGISTER(rl);
1265 DECODE_PRINTF(",");
1266 shiftreg = DECODE_RM_WORD_REGISTER(rh);
1267 TRACE_AND_STEP();
1268 bit = *shiftreg & 0xF;
1269 mask = (u16)(0x1 << bit);
1270 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1271 *srcreg ^= mask;
1272 }
Jason Jinece92f82007-07-06 08:34:56 +08001273 }
1274 DECODE_CLEAR_SEGOVR();
1275 END_OF_INSTR();
1276}
1277
1278/****************************************************************************
1279REMARKS:
1280Handles opcode 0x0f,0xbc
1281****************************************************************************/
1282void x86emuOp2_bsf(u8 X86EMU_UNUSED(op2))
1283{
1284 int mod, rl, rh;
1285 uint srcoffset;
1286
1287 START_OF_INSTR();
1288 DECODE_PRINTF("BSF\n");
1289 FETCH_DECODE_MODRM(mod, rh, rl);
1290 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001291 srcoffset = decode_rmXX_address(mod, rl);
1292 DECODE_PRINTF(",");
1293 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1294 u32 srcval, *dstreg;
Jason Jinece92f82007-07-06 08:34:56 +08001295
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001296 dstreg = DECODE_RM_LONG_REGISTER(rh);
1297 TRACE_AND_STEP();
1298 srcval = fetch_data_long(srcoffset);
1299 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
1300 for(*dstreg = 0; *dstreg < 32; (*dstreg)++)
1301 if ((srcval >> *dstreg) & 1) break;
1302 } else {
1303 u16 srcval, *dstreg;
Jason Jinece92f82007-07-06 08:34:56 +08001304
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001305 dstreg = DECODE_RM_WORD_REGISTER(rh);
1306 TRACE_AND_STEP();
1307 srcval = fetch_data_word(srcoffset);
1308 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
1309 for(*dstreg = 0; *dstreg < 16; (*dstreg)++)
1310 if ((srcval >> *dstreg) & 1) break;
1311 }
1312 } else { /* register to register */
1313 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1314 u32 *srcreg, *dstreg;
Jason Jinece92f82007-07-06 08:34:56 +08001315
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001316 srcreg = DECODE_RM_LONG_REGISTER(rl);
1317 DECODE_PRINTF(",");
1318 dstreg = DECODE_RM_LONG_REGISTER(rh);
1319 TRACE_AND_STEP();
1320 CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF);
1321 for(*dstreg = 0; *dstreg < 32; (*dstreg)++)
1322 if ((*srcreg >> *dstreg) & 1) break;
1323 } else {
1324 u16 *srcreg, *dstreg;
Jason Jinece92f82007-07-06 08:34:56 +08001325
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001326 srcreg = DECODE_RM_WORD_REGISTER(rl);
1327 DECODE_PRINTF(",");
1328 dstreg = DECODE_RM_WORD_REGISTER(rh);
1329 TRACE_AND_STEP();
1330 CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF);
1331 for(*dstreg = 0; *dstreg < 16; (*dstreg)++)
1332 if ((*srcreg >> *dstreg) & 1) break;
1333 }
Jason Jinece92f82007-07-06 08:34:56 +08001334 }
1335 DECODE_CLEAR_SEGOVR();
1336 END_OF_INSTR();
1337}
1338
1339/****************************************************************************
1340REMARKS:
1341Handles opcode 0x0f,0xbd
1342****************************************************************************/
1343void x86emuOp2_bsr(u8 X86EMU_UNUSED(op2))
1344{
1345 int mod, rl, rh;
1346 uint srcoffset;
1347
1348 START_OF_INSTR();
1349 DECODE_PRINTF("BSF\n");
1350 FETCH_DECODE_MODRM(mod, rh, rl);
1351 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001352 srcoffset = decode_rmXX_address(mod, rl);
1353 DECODE_PRINTF(",");
1354 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1355 u32 srcval, *dstreg;
Jason Jinece92f82007-07-06 08:34:56 +08001356
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001357 dstreg = DECODE_RM_LONG_REGISTER(rh);
1358 TRACE_AND_STEP();
1359 srcval = fetch_data_long(srcoffset);
1360 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
1361 for(*dstreg = 31; *dstreg > 0; (*dstreg)--)
1362 if ((srcval >> *dstreg) & 1) break;
1363 } else {
1364 u16 srcval, *dstreg;
Jason Jinece92f82007-07-06 08:34:56 +08001365
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001366 dstreg = DECODE_RM_WORD_REGISTER(rh);
1367 TRACE_AND_STEP();
1368 srcval = fetch_data_word(srcoffset);
1369 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
1370 for(*dstreg = 15; *dstreg > 0; (*dstreg)--)
1371 if ((srcval >> *dstreg) & 1) break;
1372 }
1373 } else { /* register to register */
1374 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1375 u32 *srcreg, *dstreg;
Jason Jinece92f82007-07-06 08:34:56 +08001376
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001377 srcreg = DECODE_RM_LONG_REGISTER(rl);
1378 DECODE_PRINTF(",");
1379 dstreg = DECODE_RM_LONG_REGISTER(rh);
1380 TRACE_AND_STEP();
1381 CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF);
1382 for(*dstreg = 31; *dstreg > 0; (*dstreg)--)
1383 if ((*srcreg >> *dstreg) & 1) break;
1384 } else {
1385 u16 *srcreg, *dstreg;
Jason Jinece92f82007-07-06 08:34:56 +08001386
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001387 srcreg = DECODE_RM_WORD_REGISTER(rl);
1388 DECODE_PRINTF(",");
1389 dstreg = DECODE_RM_WORD_REGISTER(rh);
1390 TRACE_AND_STEP();
1391 CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF);
1392 for(*dstreg = 15; *dstreg > 0; (*dstreg)--)
1393 if ((*srcreg >> *dstreg) & 1) break;
1394 }
Jason Jinece92f82007-07-06 08:34:56 +08001395 }
1396 DECODE_CLEAR_SEGOVR();
1397 END_OF_INSTR();
1398}
1399
1400/****************************************************************************
1401REMARKS:
1402Handles opcode 0x0f,0xbe
1403****************************************************************************/
1404void x86emuOp2_movsx_byte_R_RM(u8 X86EMU_UNUSED(op2))
1405{
1406 int mod, rl, rh;
1407 uint srcoffset;
1408
1409 START_OF_INSTR();
1410 DECODE_PRINTF("MOVSX\t");
1411 FETCH_DECODE_MODRM(mod, rh, rl);
1412 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001413 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1414 u32 *destreg;
1415 u32 srcval;
Jason Jinece92f82007-07-06 08:34:56 +08001416
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001417 destreg = DECODE_RM_LONG_REGISTER(rh);
1418 DECODE_PRINTF(",");
1419 srcoffset = decode_rmXX_address(mod, rl);
1420 srcval = (s32)((s8)fetch_data_byte(srcoffset));
1421 DECODE_PRINTF("\n");
1422 TRACE_AND_STEP();
1423 *destreg = srcval;
1424 } else {
1425 u16 *destreg;
1426 u16 srcval;
Jason Jinece92f82007-07-06 08:34:56 +08001427
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001428 destreg = DECODE_RM_WORD_REGISTER(rh);
1429 DECODE_PRINTF(",");
1430 srcoffset = decode_rmXX_address(mod, rl);
1431 srcval = (s16)((s8)fetch_data_byte(srcoffset));
1432 DECODE_PRINTF("\n");
1433 TRACE_AND_STEP();
1434 *destreg = srcval;
1435 }
1436 } else { /* register to register */
1437 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1438 u32 *destreg;
1439 u8 *srcreg;
Jason Jinece92f82007-07-06 08:34:56 +08001440
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001441 destreg = DECODE_RM_LONG_REGISTER(rh);
1442 DECODE_PRINTF(",");
1443 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1444 DECODE_PRINTF("\n");
1445 TRACE_AND_STEP();
1446 *destreg = (s32)((s8)*srcreg);
1447 } else {
1448 u16 *destreg;
1449 u8 *srcreg;
Jason Jinece92f82007-07-06 08:34:56 +08001450
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001451 destreg = DECODE_RM_WORD_REGISTER(rh);
1452 DECODE_PRINTF(",");
1453 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1454 DECODE_PRINTF("\n");
1455 TRACE_AND_STEP();
1456 *destreg = (s16)((s8)*srcreg);
1457 }
Jason Jinece92f82007-07-06 08:34:56 +08001458 }
1459 DECODE_CLEAR_SEGOVR();
1460 END_OF_INSTR();
1461}
1462
1463/****************************************************************************
1464REMARKS:
1465Handles opcode 0x0f,0xbf
1466****************************************************************************/
1467void x86emuOp2_movsx_word_R_RM(u8 X86EMU_UNUSED(op2))
1468{
1469 int mod, rl, rh;
1470 uint srcoffset;
1471 u32 *destreg;
1472 u32 srcval;
1473 u16 *srcreg;
1474
1475 START_OF_INSTR();
1476 DECODE_PRINTF("MOVSX\t");
1477 FETCH_DECODE_MODRM(mod, rh, rl);
1478 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001479 destreg = DECODE_RM_LONG_REGISTER(rh);
1480 DECODE_PRINTF(",");
1481 srcoffset = decode_rmXX_address(mod, rl);
1482 srcval = (s32)((s16)fetch_data_word(srcoffset));
1483 DECODE_PRINTF("\n");
1484 TRACE_AND_STEP();
1485 *destreg = srcval;
1486 } else { /* register to register */
1487 destreg = DECODE_RM_LONG_REGISTER(rh);
1488 DECODE_PRINTF(",");
1489 srcreg = DECODE_RM_WORD_REGISTER(rl);
1490 DECODE_PRINTF("\n");
1491 TRACE_AND_STEP();
1492 *destreg = (s32)((s16)*srcreg);
Jason Jinece92f82007-07-06 08:34:56 +08001493 }
1494 DECODE_CLEAR_SEGOVR();
1495 END_OF_INSTR();
1496}
1497
1498/***************************************************************************
1499 * Double byte operation code table:
1500 **************************************************************************/
Anatolij Gustschin30c6a242008-02-15 20:09:01 +01001501void (*x86emu_optab2[256])(u8) __attribute__((section(GOT2_TYPE))) =
Jason Jinece92f82007-07-06 08:34:56 +08001502{
1503/* 0x00 */ x86emuOp2_illegal_op, /* Group F (ring 0 PM) */
1504/* 0x01 */ x86emuOp2_illegal_op, /* Group G (ring 0 PM) */
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001505/* 0x02 */ x86emuOp2_illegal_op, /* lar (ring 0 PM) */
1506/* 0x03 */ x86emuOp2_illegal_op, /* lsl (ring 0 PM) */
Jason Jinece92f82007-07-06 08:34:56 +08001507/* 0x04 */ x86emuOp2_illegal_op,
1508/* 0x05 */ x86emuOp2_illegal_op, /* loadall (undocumented) */
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001509/* 0x06 */ x86emuOp2_illegal_op, /* clts (ring 0 PM) */
Jason Jinece92f82007-07-06 08:34:56 +08001510/* 0x07 */ x86emuOp2_illegal_op, /* loadall (undocumented) */
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001511/* 0x08 */ x86emuOp2_illegal_op, /* invd (ring 0 PM) */
Jason Jinece92f82007-07-06 08:34:56 +08001512/* 0x09 */ x86emuOp2_illegal_op, /* wbinvd (ring 0 PM) */
1513/* 0x0a */ x86emuOp2_illegal_op,
1514/* 0x0b */ x86emuOp2_illegal_op,
1515/* 0x0c */ x86emuOp2_illegal_op,
1516/* 0x0d */ x86emuOp2_illegal_op,
1517/* 0x0e */ x86emuOp2_illegal_op,
1518/* 0x0f */ x86emuOp2_illegal_op,
1519
1520/* 0x10 */ x86emuOp2_illegal_op,
1521/* 0x11 */ x86emuOp2_illegal_op,
1522/* 0x12 */ x86emuOp2_illegal_op,
1523/* 0x13 */ x86emuOp2_illegal_op,
1524/* 0x14 */ x86emuOp2_illegal_op,
1525/* 0x15 */ x86emuOp2_illegal_op,
1526/* 0x16 */ x86emuOp2_illegal_op,
1527/* 0x17 */ x86emuOp2_illegal_op,
1528/* 0x18 */ x86emuOp2_illegal_op,
1529/* 0x19 */ x86emuOp2_illegal_op,
1530/* 0x1a */ x86emuOp2_illegal_op,
1531/* 0x1b */ x86emuOp2_illegal_op,
1532/* 0x1c */ x86emuOp2_illegal_op,
1533/* 0x1d */ x86emuOp2_illegal_op,
1534/* 0x1e */ x86emuOp2_illegal_op,
1535/* 0x1f */ x86emuOp2_illegal_op,
1536
1537/* 0x20 */ x86emuOp2_illegal_op, /* mov reg32,creg (ring 0 PM) */
1538/* 0x21 */ x86emuOp2_illegal_op, /* mov reg32,dreg (ring 0 PM) */
1539/* 0x22 */ x86emuOp2_illegal_op, /* mov creg,reg32 (ring 0 PM) */
1540/* 0x23 */ x86emuOp2_illegal_op, /* mov dreg,reg32 (ring 0 PM) */
1541/* 0x24 */ x86emuOp2_illegal_op, /* mov reg32,treg (ring 0 PM) */
1542/* 0x25 */ x86emuOp2_illegal_op,
1543/* 0x26 */ x86emuOp2_illegal_op, /* mov treg,reg32 (ring 0 PM) */
1544/* 0x27 */ x86emuOp2_illegal_op,
1545/* 0x28 */ x86emuOp2_illegal_op,
1546/* 0x29 */ x86emuOp2_illegal_op,
1547/* 0x2a */ x86emuOp2_illegal_op,
1548/* 0x2b */ x86emuOp2_illegal_op,
1549/* 0x2c */ x86emuOp2_illegal_op,
1550/* 0x2d */ x86emuOp2_illegal_op,
1551/* 0x2e */ x86emuOp2_illegal_op,
1552/* 0x2f */ x86emuOp2_illegal_op,
1553
1554/* 0x30 */ x86emuOp2_illegal_op,
1555/* 0x31 */ x86emuOp2_illegal_op,
1556/* 0x32 */ x86emuOp2_illegal_op,
1557/* 0x33 */ x86emuOp2_illegal_op,
1558/* 0x34 */ x86emuOp2_illegal_op,
1559/* 0x35 */ x86emuOp2_illegal_op,
1560/* 0x36 */ x86emuOp2_illegal_op,
1561/* 0x37 */ x86emuOp2_illegal_op,
1562/* 0x38 */ x86emuOp2_illegal_op,
1563/* 0x39 */ x86emuOp2_illegal_op,
1564/* 0x3a */ x86emuOp2_illegal_op,
1565/* 0x3b */ x86emuOp2_illegal_op,
1566/* 0x3c */ x86emuOp2_illegal_op,
1567/* 0x3d */ x86emuOp2_illegal_op,
1568/* 0x3e */ x86emuOp2_illegal_op,
1569/* 0x3f */ x86emuOp2_illegal_op,
1570
1571/* 0x40 */ x86emuOp2_illegal_op,
1572/* 0x41 */ x86emuOp2_illegal_op,
1573/* 0x42 */ x86emuOp2_illegal_op,
1574/* 0x43 */ x86emuOp2_illegal_op,
1575/* 0x44 */ x86emuOp2_illegal_op,
1576/* 0x45 */ x86emuOp2_illegal_op,
1577/* 0x46 */ x86emuOp2_illegal_op,
1578/* 0x47 */ x86emuOp2_illegal_op,
1579/* 0x48 */ x86emuOp2_illegal_op,
1580/* 0x49 */ x86emuOp2_illegal_op,
1581/* 0x4a */ x86emuOp2_illegal_op,
1582/* 0x4b */ x86emuOp2_illegal_op,
1583/* 0x4c */ x86emuOp2_illegal_op,
1584/* 0x4d */ x86emuOp2_illegal_op,
1585/* 0x4e */ x86emuOp2_illegal_op,
1586/* 0x4f */ x86emuOp2_illegal_op,
1587
1588/* 0x50 */ x86emuOp2_illegal_op,
1589/* 0x51 */ x86emuOp2_illegal_op,
1590/* 0x52 */ x86emuOp2_illegal_op,
1591/* 0x53 */ x86emuOp2_illegal_op,
1592/* 0x54 */ x86emuOp2_illegal_op,
1593/* 0x55 */ x86emuOp2_illegal_op,
1594/* 0x56 */ x86emuOp2_illegal_op,
1595/* 0x57 */ x86emuOp2_illegal_op,
1596/* 0x58 */ x86emuOp2_illegal_op,
1597/* 0x59 */ x86emuOp2_illegal_op,
1598/* 0x5a */ x86emuOp2_illegal_op,
1599/* 0x5b */ x86emuOp2_illegal_op,
1600/* 0x5c */ x86emuOp2_illegal_op,
1601/* 0x5d */ x86emuOp2_illegal_op,
1602/* 0x5e */ x86emuOp2_illegal_op,
1603/* 0x5f */ x86emuOp2_illegal_op,
1604
1605/* 0x60 */ x86emuOp2_illegal_op,
1606/* 0x61 */ x86emuOp2_illegal_op,
1607/* 0x62 */ x86emuOp2_illegal_op,
1608/* 0x63 */ x86emuOp2_illegal_op,
1609/* 0x64 */ x86emuOp2_illegal_op,
1610/* 0x65 */ x86emuOp2_illegal_op,
1611/* 0x66 */ x86emuOp2_illegal_op,
1612/* 0x67 */ x86emuOp2_illegal_op,
1613/* 0x68 */ x86emuOp2_illegal_op,
1614/* 0x69 */ x86emuOp2_illegal_op,
1615/* 0x6a */ x86emuOp2_illegal_op,
1616/* 0x6b */ x86emuOp2_illegal_op,
1617/* 0x6c */ x86emuOp2_illegal_op,
1618/* 0x6d */ x86emuOp2_illegal_op,
1619/* 0x6e */ x86emuOp2_illegal_op,
1620/* 0x6f */ x86emuOp2_illegal_op,
1621
1622/* 0x70 */ x86emuOp2_illegal_op,
1623/* 0x71 */ x86emuOp2_illegal_op,
1624/* 0x72 */ x86emuOp2_illegal_op,
1625/* 0x73 */ x86emuOp2_illegal_op,
1626/* 0x74 */ x86emuOp2_illegal_op,
1627/* 0x75 */ x86emuOp2_illegal_op,
1628/* 0x76 */ x86emuOp2_illegal_op,
1629/* 0x77 */ x86emuOp2_illegal_op,
1630/* 0x78 */ x86emuOp2_illegal_op,
1631/* 0x79 */ x86emuOp2_illegal_op,
1632/* 0x7a */ x86emuOp2_illegal_op,
1633/* 0x7b */ x86emuOp2_illegal_op,
1634/* 0x7c */ x86emuOp2_illegal_op,
1635/* 0x7d */ x86emuOp2_illegal_op,
1636/* 0x7e */ x86emuOp2_illegal_op,
1637/* 0x7f */ x86emuOp2_illegal_op,
1638
1639/* 0x80 */ x86emuOp2_long_jump,
1640/* 0x81 */ x86emuOp2_long_jump,
1641/* 0x82 */ x86emuOp2_long_jump,
1642/* 0x83 */ x86emuOp2_long_jump,
1643/* 0x84 */ x86emuOp2_long_jump,
1644/* 0x85 */ x86emuOp2_long_jump,
1645/* 0x86 */ x86emuOp2_long_jump,
1646/* 0x87 */ x86emuOp2_long_jump,
1647/* 0x88 */ x86emuOp2_long_jump,
1648/* 0x89 */ x86emuOp2_long_jump,
1649/* 0x8a */ x86emuOp2_long_jump,
1650/* 0x8b */ x86emuOp2_long_jump,
1651/* 0x8c */ x86emuOp2_long_jump,
1652/* 0x8d */ x86emuOp2_long_jump,
1653/* 0x8e */ x86emuOp2_long_jump,
1654/* 0x8f */ x86emuOp2_long_jump,
1655
1656/* 0x90 */ x86emuOp2_set_byte,
1657/* 0x91 */ x86emuOp2_set_byte,
1658/* 0x92 */ x86emuOp2_set_byte,
1659/* 0x93 */ x86emuOp2_set_byte,
1660/* 0x94 */ x86emuOp2_set_byte,
1661/* 0x95 */ x86emuOp2_set_byte,
1662/* 0x96 */ x86emuOp2_set_byte,
1663/* 0x97 */ x86emuOp2_set_byte,
1664/* 0x98 */ x86emuOp2_set_byte,
1665/* 0x99 */ x86emuOp2_set_byte,
1666/* 0x9a */ x86emuOp2_set_byte,
1667/* 0x9b */ x86emuOp2_set_byte,
1668/* 0x9c */ x86emuOp2_set_byte,
1669/* 0x9d */ x86emuOp2_set_byte,
1670/* 0x9e */ x86emuOp2_set_byte,
1671/* 0x9f */ x86emuOp2_set_byte,
1672
1673/* 0xa0 */ x86emuOp2_push_FS,
1674/* 0xa1 */ x86emuOp2_pop_FS,
1675/* 0xa2 */ x86emuOp2_illegal_op,
1676/* 0xa3 */ x86emuOp2_bt_R,
1677/* 0xa4 */ x86emuOp2_shld_IMM,
1678/* 0xa5 */ x86emuOp2_shld_CL,
1679/* 0xa6 */ x86emuOp2_illegal_op,
1680/* 0xa7 */ x86emuOp2_illegal_op,
1681/* 0xa8 */ x86emuOp2_push_GS,
1682/* 0xa9 */ x86emuOp2_pop_GS,
1683/* 0xaa */ x86emuOp2_illegal_op,
1684/* 0xab */ x86emuOp2_bt_R,
1685/* 0xac */ x86emuOp2_shrd_IMM,
1686/* 0xad */ x86emuOp2_shrd_CL,
1687/* 0xae */ x86emuOp2_illegal_op,
1688/* 0xaf */ x86emuOp2_imul_R_RM,
1689
1690/* 0xb0 */ x86emuOp2_illegal_op, /* TODO: cmpxchg */
1691/* 0xb1 */ x86emuOp2_illegal_op, /* TODO: cmpxchg */
1692/* 0xb2 */ x86emuOp2_lss_R_IMM,
1693/* 0xb3 */ x86emuOp2_btr_R,
1694/* 0xb4 */ x86emuOp2_lfs_R_IMM,
1695/* 0xb5 */ x86emuOp2_lgs_R_IMM,
1696/* 0xb6 */ x86emuOp2_movzx_byte_R_RM,
1697/* 0xb7 */ x86emuOp2_movzx_word_R_RM,
1698/* 0xb8 */ x86emuOp2_illegal_op,
1699/* 0xb9 */ x86emuOp2_illegal_op,
1700/* 0xba */ x86emuOp2_btX_I,
1701/* 0xbb */ x86emuOp2_btc_R,
1702/* 0xbc */ x86emuOp2_bsf,
1703/* 0xbd */ x86emuOp2_bsr,
1704/* 0xbe */ x86emuOp2_movsx_byte_R_RM,
1705/* 0xbf */ x86emuOp2_movsx_word_R_RM,
1706
1707/* 0xc0 */ x86emuOp2_illegal_op, /* TODO: xadd */
1708/* 0xc1 */ x86emuOp2_illegal_op, /* TODO: xadd */
1709/* 0xc2 */ x86emuOp2_illegal_op,
1710/* 0xc3 */ x86emuOp2_illegal_op,
1711/* 0xc4 */ x86emuOp2_illegal_op,
1712/* 0xc5 */ x86emuOp2_illegal_op,
1713/* 0xc6 */ x86emuOp2_illegal_op,
1714/* 0xc7 */ x86emuOp2_illegal_op,
1715/* 0xc8 */ x86emuOp2_illegal_op, /* TODO: bswap */
1716/* 0xc9 */ x86emuOp2_illegal_op, /* TODO: bswap */
1717/* 0xca */ x86emuOp2_illegal_op, /* TODO: bswap */
1718/* 0xcb */ x86emuOp2_illegal_op, /* TODO: bswap */
1719/* 0xcc */ x86emuOp2_illegal_op, /* TODO: bswap */
1720/* 0xcd */ x86emuOp2_illegal_op, /* TODO: bswap */
1721/* 0xce */ x86emuOp2_illegal_op, /* TODO: bswap */
1722/* 0xcf */ x86emuOp2_illegal_op, /* TODO: bswap */
1723
1724/* 0xd0 */ x86emuOp2_illegal_op,
1725/* 0xd1 */ x86emuOp2_illegal_op,
1726/* 0xd2 */ x86emuOp2_illegal_op,
1727/* 0xd3 */ x86emuOp2_illegal_op,
1728/* 0xd4 */ x86emuOp2_illegal_op,
1729/* 0xd5 */ x86emuOp2_illegal_op,
1730/* 0xd6 */ x86emuOp2_illegal_op,
1731/* 0xd7 */ x86emuOp2_illegal_op,
1732/* 0xd8 */ x86emuOp2_illegal_op,
1733/* 0xd9 */ x86emuOp2_illegal_op,
1734/* 0xda */ x86emuOp2_illegal_op,
1735/* 0xdb */ x86emuOp2_illegal_op,
1736/* 0xdc */ x86emuOp2_illegal_op,
1737/* 0xdd */ x86emuOp2_illegal_op,
1738/* 0xde */ x86emuOp2_illegal_op,
1739/* 0xdf */ x86emuOp2_illegal_op,
1740
1741/* 0xe0 */ x86emuOp2_illegal_op,
1742/* 0xe1 */ x86emuOp2_illegal_op,
1743/* 0xe2 */ x86emuOp2_illegal_op,
1744/* 0xe3 */ x86emuOp2_illegal_op,
1745/* 0xe4 */ x86emuOp2_illegal_op,
1746/* 0xe5 */ x86emuOp2_illegal_op,
1747/* 0xe6 */ x86emuOp2_illegal_op,
1748/* 0xe7 */ x86emuOp2_illegal_op,
1749/* 0xe8 */ x86emuOp2_illegal_op,
1750/* 0xe9 */ x86emuOp2_illegal_op,
1751/* 0xea */ x86emuOp2_illegal_op,
1752/* 0xeb */ x86emuOp2_illegal_op,
1753/* 0xec */ x86emuOp2_illegal_op,
1754/* 0xed */ x86emuOp2_illegal_op,
1755/* 0xee */ x86emuOp2_illegal_op,
1756/* 0xef */ x86emuOp2_illegal_op,
1757
1758/* 0xf0 */ x86emuOp2_illegal_op,
1759/* 0xf1 */ x86emuOp2_illegal_op,
1760/* 0xf2 */ x86emuOp2_illegal_op,
1761/* 0xf3 */ x86emuOp2_illegal_op,
1762/* 0xf4 */ x86emuOp2_illegal_op,
1763/* 0xf5 */ x86emuOp2_illegal_op,
1764/* 0xf6 */ x86emuOp2_illegal_op,
1765/* 0xf7 */ x86emuOp2_illegal_op,
1766/* 0xf8 */ x86emuOp2_illegal_op,
1767/* 0xf9 */ x86emuOp2_illegal_op,
1768/* 0xfa */ x86emuOp2_illegal_op,
1769/* 0xfb */ x86emuOp2_illegal_op,
1770/* 0xfc */ x86emuOp2_illegal_op,
1771/* 0xfd */ x86emuOp2_illegal_op,
1772/* 0xfe */ x86emuOp2_illegal_op,
1773/* 0xff */ x86emuOp2_illegal_op,
1774};
Jason Jince981dc2007-08-08 08:33:11 +08001775
1776#endif