blob: c8b8517192897e835f0dc96e050fc226e6d57401 [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
Jason Jince981dc2007-08-08 08:33:11 +080047#if defined(CONFIG_BIOSEMU)
48
Michal Simek5b4de932007-08-15 21:15:05 +020049#include "x86emu/x86emui.h"
50
Jason Jinece92f82007-07-06 08:34:56 +080051/*----------------------------- Implementation ----------------------------*/
52
53/****************************************************************************
54PARAMETERS:
55op1 - Instruction op code
56
57REMARKS:
58Handles illegal opcodes.
59****************************************************************************/
60void x86emuOp2_illegal_op(
61 u8 op2)
62{
63 START_OF_INSTR();
64 DECODE_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n");
65 TRACE_REGS();
66 printk("%04x:%04x: %02X ILLEGAL EXTENDED X86 OPCODE!\n",
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +020067 M.x86.R_CS, M.x86.R_IP-2,op2);
Jason Jinece92f82007-07-06 08:34:56 +080068 HALT_SYS();
69 END_OF_INSTR();
70}
71
72#define xorl(a,b) ((a) && !(b)) || (!(a) && (b))
73
74/****************************************************************************
75REMARKS:
76Handles opcode 0x0f,0x80-0x8F
77****************************************************************************/
78int x86emu_check_jump_condition(u8 op)
79{
80 switch (op) {
81 case 0x0:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +020082 DECODE_PRINTF("JO\t");
83 return ACCESS_FLAG(F_OF);
Jason Jinece92f82007-07-06 08:34:56 +080084 case 0x1:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +020085 DECODE_PRINTF("JNO\t");
86 return !ACCESS_FLAG(F_OF);
87 break;
Jason Jinece92f82007-07-06 08:34:56 +080088 case 0x2:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +020089 DECODE_PRINTF("JB\t");
90 return ACCESS_FLAG(F_CF);
91 break;
Jason Jinece92f82007-07-06 08:34:56 +080092 case 0x3:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +020093 DECODE_PRINTF("JNB\t");
94 return !ACCESS_FLAG(F_CF);
95 break;
Jason Jinece92f82007-07-06 08:34:56 +080096 case 0x4:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +020097 DECODE_PRINTF("JZ\t");
98 return ACCESS_FLAG(F_ZF);
99 break;
Jason Jinece92f82007-07-06 08:34:56 +0800100 case 0x5:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200101 DECODE_PRINTF("JNZ\t");
102 return !ACCESS_FLAG(F_ZF);
103 break;
Jason Jinece92f82007-07-06 08:34:56 +0800104 case 0x6:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200105 DECODE_PRINTF("JBE\t");
106 return ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF);
107 break;
Jason Jinece92f82007-07-06 08:34:56 +0800108 case 0x7:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200109 DECODE_PRINTF("JNBE\t");
110 return !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
111 break;
Jason Jinece92f82007-07-06 08:34:56 +0800112 case 0x8:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200113 DECODE_PRINTF("JS\t");
114 return ACCESS_FLAG(F_SF);
115 break;
Jason Jinece92f82007-07-06 08:34:56 +0800116 case 0x9:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200117 DECODE_PRINTF("JNS\t");
118 return !ACCESS_FLAG(F_SF);
119 break;
Jason Jinece92f82007-07-06 08:34:56 +0800120 case 0xa:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200121 DECODE_PRINTF("JP\t");
122 return ACCESS_FLAG(F_PF);
123 break;
Jason Jinece92f82007-07-06 08:34:56 +0800124 case 0xb:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200125 DECODE_PRINTF("JNP\t");
126 return !ACCESS_FLAG(F_PF);
127 break;
Jason Jinece92f82007-07-06 08:34:56 +0800128 case 0xc:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200129 DECODE_PRINTF("JL\t");
130 return xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
131 break;
Jason Jinece92f82007-07-06 08:34:56 +0800132 case 0xd:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200133 DECODE_PRINTF("JNL\t");
134 return !xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
135 break;
Jason Jinece92f82007-07-06 08:34:56 +0800136 case 0xe:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200137 DECODE_PRINTF("JLE\t");
138 return (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
139 ACCESS_FLAG(F_ZF));
140 break;
Jason Jinece92f82007-07-06 08:34:56 +0800141 default:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200142 DECODE_PRINTF("JNLE\t");
143 return !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
144 ACCESS_FLAG(F_ZF));
Jason Jinece92f82007-07-06 08:34:56 +0800145 }
146}
147
148void x86emuOp2_long_jump(u8 op2)
149{
150 s32 target;
151 int cond;
152
153 /* conditional jump to word offset. */
154 START_OF_INSTR();
155 cond = x86emu_check_jump_condition(op2 & 0xF);
156 target = (s16) fetch_word_imm();
157 target += (s16) M.x86.R_IP;
158 DECODE_PRINTF2("%04x\n", target);
159 TRACE_AND_STEP();
160 if (cond)
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200161 M.x86.R_IP = (u16)target;
Jason Jinece92f82007-07-06 08:34:56 +0800162 DECODE_CLEAR_SEGOVR();
163 END_OF_INSTR();
164}
165
166/****************************************************************************
167REMARKS:
168Handles opcode 0x0f,0x90-0x9F
169****************************************************************************/
170void x86emuOp2_set_byte(u8 op2)
171{
172 int mod, rl, rh;
173 uint destoffset;
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200174 u8 *destreg;
Jason Jinece92f82007-07-06 08:34:56 +0800175 char *name = 0;
176 int cond = 0;
177
178 START_OF_INSTR();
179 switch (op2) {
180 case 0x90:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200181 name = "SETO\t";
182 cond = ACCESS_FLAG(F_OF);
183 break;
Jason Jinece92f82007-07-06 08:34:56 +0800184 case 0x91:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200185 name = "SETNO\t";
186 cond = !ACCESS_FLAG(F_OF);
187 break;
Jason Jinece92f82007-07-06 08:34:56 +0800188 case 0x92:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200189 name = "SETB\t";
190 cond = ACCESS_FLAG(F_CF);
191 break;
Jason Jinece92f82007-07-06 08:34:56 +0800192 case 0x93:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200193 name = "SETNB\t";
194 cond = !ACCESS_FLAG(F_CF);
195 break;
Jason Jinece92f82007-07-06 08:34:56 +0800196 case 0x94:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200197 name = "SETZ\t";
198 cond = ACCESS_FLAG(F_ZF);
199 break;
Jason Jinece92f82007-07-06 08:34:56 +0800200 case 0x95:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200201 name = "SETNZ\t";
202 cond = !ACCESS_FLAG(F_ZF);
203 break;
Jason Jinece92f82007-07-06 08:34:56 +0800204 case 0x96:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200205 name = "SETBE\t";
206 cond = ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF);
207 break;
Jason Jinece92f82007-07-06 08:34:56 +0800208 case 0x97:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200209 name = "SETNBE\t";
210 cond = !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
211 break;
Jason Jinece92f82007-07-06 08:34:56 +0800212 case 0x98:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200213 name = "SETS\t";
214 cond = ACCESS_FLAG(F_SF);
215 break;
Jason Jinece92f82007-07-06 08:34:56 +0800216 case 0x99:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200217 name = "SETNS\t";
218 cond = !ACCESS_FLAG(F_SF);
219 break;
Jason Jinece92f82007-07-06 08:34:56 +0800220 case 0x9a:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200221 name = "SETP\t";
222 cond = ACCESS_FLAG(F_PF);
223 break;
Jason Jinece92f82007-07-06 08:34:56 +0800224 case 0x9b:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200225 name = "SETNP\t";
226 cond = !ACCESS_FLAG(F_PF);
227 break;
Jason Jinece92f82007-07-06 08:34:56 +0800228 case 0x9c:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200229 name = "SETL\t";
230 cond = xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
231 break;
Jason Jinece92f82007-07-06 08:34:56 +0800232 case 0x9d:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200233 name = "SETNL\t";
234 cond = !xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
235 break;
Jason Jinece92f82007-07-06 08:34:56 +0800236 case 0x9e:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200237 name = "SETLE\t";
238 cond = (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
239 ACCESS_FLAG(F_ZF));
240 break;
Jason Jinece92f82007-07-06 08:34:56 +0800241 case 0x9f:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200242 name = "SETNLE\t";
243 cond = !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
244 ACCESS_FLAG(F_ZF));
245 break;
Jason Jinece92f82007-07-06 08:34:56 +0800246 }
247 DECODE_PRINTF(name);
248 FETCH_DECODE_MODRM(mod, rh, rl);
249 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200250 destoffset = decode_rmXX_address(mod, rl);
251 TRACE_AND_STEP();
252 store_data_byte(destoffset, cond ? 0x01 : 0x00);
253 } else { /* register to register */
254 destreg = DECODE_RM_BYTE_REGISTER(rl);
255 TRACE_AND_STEP();
256 *destreg = cond ? 0x01 : 0x00;
Jason Jinece92f82007-07-06 08:34:56 +0800257 }
258 DECODE_CLEAR_SEGOVR();
259 END_OF_INSTR();
260}
261
262/****************************************************************************
263REMARKS:
264Handles opcode 0x0f,0xa0
265****************************************************************************/
266void x86emuOp2_push_FS(u8 X86EMU_UNUSED(op2))
267{
268 START_OF_INSTR();
269 DECODE_PRINTF("PUSH\tFS\n");
270 TRACE_AND_STEP();
271 push_word(M.x86.R_FS);
272 DECODE_CLEAR_SEGOVR();
273 END_OF_INSTR();
274}
275
276/****************************************************************************
277REMARKS:
278Handles opcode 0x0f,0xa1
279****************************************************************************/
280void x86emuOp2_pop_FS(u8 X86EMU_UNUSED(op2))
281{
282 START_OF_INSTR();
283 DECODE_PRINTF("POP\tFS\n");
284 TRACE_AND_STEP();
285 M.x86.R_FS = pop_word();
286 DECODE_CLEAR_SEGOVR();
287 END_OF_INSTR();
288}
289
290/****************************************************************************
291REMARKS:
292Handles opcode 0x0f,0xa3
293****************************************************************************/
294void x86emuOp2_bt_R(u8 X86EMU_UNUSED(op2))
295{
296 int mod, rl, rh;
297 uint srcoffset;
298 int bit,disp;
299
300 START_OF_INSTR();
301 DECODE_PRINTF("BT\t");
302 FETCH_DECODE_MODRM(mod, rh, rl);
303 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200304 srcoffset = decode_rmXX_address(mod, rl);
305 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
306 u32 srcval;
307 u32 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800308
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200309 DECODE_PRINTF(",");
310 shiftreg = DECODE_RM_LONG_REGISTER(rh);
311 TRACE_AND_STEP();
312 bit = *shiftreg & 0x1F;
313 disp = (s16)*shiftreg >> 5;
314 srcval = fetch_data_long(srcoffset+disp);
315 CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF);
316 } else {
317 u16 srcval;
318 u16 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800319
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200320 DECODE_PRINTF(",");
321 shiftreg = DECODE_RM_WORD_REGISTER(rh);
322 TRACE_AND_STEP();
323 bit = *shiftreg & 0xF;
324 disp = (s16)*shiftreg >> 4;
325 srcval = fetch_data_word(srcoffset+disp);
326 CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF);
327 }
328 } else { /* register to register */
329 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
330 u32 *srcreg,*shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800331
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200332 srcreg = DECODE_RM_LONG_REGISTER(rl);
333 DECODE_PRINTF(",");
334 shiftreg = DECODE_RM_LONG_REGISTER(rh);
335 TRACE_AND_STEP();
336 bit = *shiftreg & 0x1F;
337 CONDITIONAL_SET_FLAG(*srcreg & (0x1 << bit),F_CF);
338 } else {
339 u16 *srcreg,*shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800340
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200341 srcreg = DECODE_RM_WORD_REGISTER(rl);
342 DECODE_PRINTF(",");
343 shiftreg = DECODE_RM_WORD_REGISTER(rh);
344 TRACE_AND_STEP();
345 bit = *shiftreg & 0xF;
346 CONDITIONAL_SET_FLAG(*srcreg & (0x1 << bit),F_CF);
347 }
Jason Jinece92f82007-07-06 08:34:56 +0800348 }
349 DECODE_CLEAR_SEGOVR();
350 END_OF_INSTR();
351}
352
353/****************************************************************************
354REMARKS:
355Handles opcode 0x0f,0xa4
356****************************************************************************/
357void x86emuOp2_shld_IMM(u8 X86EMU_UNUSED(op2))
358{
359 int mod, rl, rh;
360 uint destoffset;
361 u8 shift;
362
363 START_OF_INSTR();
364 DECODE_PRINTF("SHLD\t");
365 FETCH_DECODE_MODRM(mod, rh, rl);
366 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200367 destoffset = decode_rmXX_address(mod, rl);
368 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
369 u32 destval;
370 u32 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800371
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200372 DECODE_PRINTF(",");
373 shiftreg = DECODE_RM_LONG_REGISTER(rh);
374 DECODE_PRINTF(",");
375 shift = fetch_byte_imm();
376 DECODE_PRINTF2("%d\n", shift);
377 TRACE_AND_STEP();
378 destval = fetch_data_long(destoffset);
379 destval = shld_long(destval,*shiftreg,shift);
380 store_data_long(destoffset, destval);
381 } else {
382 u16 destval;
383 u16 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800384
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200385 DECODE_PRINTF(",");
386 shiftreg = DECODE_RM_WORD_REGISTER(rh);
387 DECODE_PRINTF(",");
388 shift = fetch_byte_imm();
389 DECODE_PRINTF2("%d\n", shift);
390 TRACE_AND_STEP();
391 destval = fetch_data_word(destoffset);
392 destval = shld_word(destval,*shiftreg,shift);
393 store_data_word(destoffset, destval);
394 }
395 } else { /* register to register */
396 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
397 u32 *destreg,*shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800398
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200399 destreg = DECODE_RM_LONG_REGISTER(rl);
400 DECODE_PRINTF(",");
401 shiftreg = DECODE_RM_LONG_REGISTER(rh);
402 DECODE_PRINTF(",");
403 shift = fetch_byte_imm();
404 DECODE_PRINTF2("%d\n", shift);
405 TRACE_AND_STEP();
406 *destreg = shld_long(*destreg,*shiftreg,shift);
407 } else {
408 u16 *destreg,*shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800409
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200410 destreg = DECODE_RM_WORD_REGISTER(rl);
411 DECODE_PRINTF(",");
412 shiftreg = DECODE_RM_WORD_REGISTER(rh);
413 DECODE_PRINTF(",");
414 shift = fetch_byte_imm();
415 DECODE_PRINTF2("%d\n", shift);
416 TRACE_AND_STEP();
417 *destreg = shld_word(*destreg,*shiftreg,shift);
418 }
Jason Jinece92f82007-07-06 08:34:56 +0800419 }
420 DECODE_CLEAR_SEGOVR();
421 END_OF_INSTR();
422}
423
424/****************************************************************************
425REMARKS:
426Handles opcode 0x0f,0xa5
427****************************************************************************/
428void x86emuOp2_shld_CL(u8 X86EMU_UNUSED(op2))
429{
430 int mod, rl, rh;
431 uint destoffset;
432
433 START_OF_INSTR();
434 DECODE_PRINTF("SHLD\t");
435 FETCH_DECODE_MODRM(mod, rh, rl);
436 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200437 destoffset = decode_rmXX_address(mod, rl);
438 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
439 u32 destval;
440 u32 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800441
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200442 DECODE_PRINTF(",");
443 shiftreg = DECODE_RM_LONG_REGISTER(rh);
444 DECODE_PRINTF(",CL\n");
445 TRACE_AND_STEP();
446 destval = fetch_data_long(destoffset);
447 destval = shld_long(destval,*shiftreg,M.x86.R_CL);
448 store_data_long(destoffset, destval);
449 } else {
450 u16 destval;
451 u16 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800452
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200453 DECODE_PRINTF(",");
454 shiftreg = DECODE_RM_WORD_REGISTER(rh);
455 DECODE_PRINTF(",CL\n");
456 TRACE_AND_STEP();
457 destval = fetch_data_word(destoffset);
458 destval = shld_word(destval,*shiftreg,M.x86.R_CL);
459 store_data_word(destoffset, destval);
460 }
461 } else { /* register to register */
462 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
463 u32 *destreg,*shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800464
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200465 destreg = DECODE_RM_LONG_REGISTER(rl);
466 DECODE_PRINTF(",");
467 shiftreg = DECODE_RM_LONG_REGISTER(rh);
468 DECODE_PRINTF(",CL\n");
469 TRACE_AND_STEP();
470 *destreg = shld_long(*destreg,*shiftreg,M.x86.R_CL);
471 } else {
472 u16 *destreg,*shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800473
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200474 destreg = DECODE_RM_WORD_REGISTER(rl);
475 DECODE_PRINTF(",");
476 shiftreg = DECODE_RM_WORD_REGISTER(rh);
477 DECODE_PRINTF(",CL\n");
478 TRACE_AND_STEP();
479 *destreg = shld_word(*destreg,*shiftreg,M.x86.R_CL);
480 }
Jason Jinece92f82007-07-06 08:34:56 +0800481 }
482 DECODE_CLEAR_SEGOVR();
483 END_OF_INSTR();
484}
485
486/****************************************************************************
487REMARKS:
488Handles opcode 0x0f,0xa8
489****************************************************************************/
490void x86emuOp2_push_GS(u8 X86EMU_UNUSED(op2))
491{
492 START_OF_INSTR();
493 DECODE_PRINTF("PUSH\tGS\n");
494 TRACE_AND_STEP();
495 push_word(M.x86.R_GS);
496 DECODE_CLEAR_SEGOVR();
497 END_OF_INSTR();
498}
499
500/****************************************************************************
501REMARKS:
502Handles opcode 0x0f,0xa9
503****************************************************************************/
504void x86emuOp2_pop_GS(u8 X86EMU_UNUSED(op2))
505{
506 START_OF_INSTR();
507 DECODE_PRINTF("POP\tGS\n");
508 TRACE_AND_STEP();
509 M.x86.R_GS = pop_word();
510 DECODE_CLEAR_SEGOVR();
511 END_OF_INSTR();
512}
513
514/****************************************************************************
515REMARKS:
516Handles opcode 0x0f,0xaa
517****************************************************************************/
518void x86emuOp2_bts_R(u8 X86EMU_UNUSED(op2))
519{
520 int mod, rl, rh;
521 uint srcoffset;
522 int bit,disp;
523
524 START_OF_INSTR();
525 DECODE_PRINTF("BTS\t");
526 FETCH_DECODE_MODRM(mod, rh, rl);
527 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200528 srcoffset = decode_rmXX_address(mod, rl);
529 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
530 u32 srcval,mask;
531 u32 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800532
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200533 DECODE_PRINTF(",");
534 shiftreg = DECODE_RM_LONG_REGISTER(rh);
535 TRACE_AND_STEP();
536 bit = *shiftreg & 0x1F;
537 disp = (s16)*shiftreg >> 5;
538 srcval = fetch_data_long(srcoffset+disp);
539 mask = (0x1 << bit);
540 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
541 store_data_long(srcoffset+disp, srcval | mask);
542 } else {
543 u16 srcval,mask;
544 u16 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800545
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200546 DECODE_PRINTF(",");
547 shiftreg = DECODE_RM_WORD_REGISTER(rh);
548 TRACE_AND_STEP();
549 bit = *shiftreg & 0xF;
550 disp = (s16)*shiftreg >> 4;
551 srcval = fetch_data_word(srcoffset+disp);
552 mask = (u16)(0x1 << bit);
553 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
554 store_data_word(srcoffset+disp, srcval | mask);
555 }
556 } else { /* register to register */
557 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
558 u32 *srcreg,*shiftreg;
559 u32 mask;
Jason Jinece92f82007-07-06 08:34:56 +0800560
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200561 srcreg = DECODE_RM_LONG_REGISTER(rl);
562 DECODE_PRINTF(",");
563 shiftreg = DECODE_RM_LONG_REGISTER(rh);
564 TRACE_AND_STEP();
565 bit = *shiftreg & 0x1F;
566 mask = (0x1 << bit);
567 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
568 *srcreg |= mask;
569 } else {
570 u16 *srcreg,*shiftreg;
571 u16 mask;
Jason Jinece92f82007-07-06 08:34:56 +0800572
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200573 srcreg = DECODE_RM_WORD_REGISTER(rl);
574 DECODE_PRINTF(",");
575 shiftreg = DECODE_RM_WORD_REGISTER(rh);
576 TRACE_AND_STEP();
577 bit = *shiftreg & 0xF;
578 mask = (u16)(0x1 << bit);
579 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
580 *srcreg |= mask;
581 }
Jason Jinece92f82007-07-06 08:34:56 +0800582 }
583 DECODE_CLEAR_SEGOVR();
584 END_OF_INSTR();
585}
586
587/****************************************************************************
588REMARKS:
589Handles opcode 0x0f,0xac
590****************************************************************************/
591void x86emuOp2_shrd_IMM(u8 X86EMU_UNUSED(op2))
592{
593 int mod, rl, rh;
594 uint destoffset;
595 u8 shift;
596
597 START_OF_INSTR();
598 DECODE_PRINTF("SHLD\t");
599 FETCH_DECODE_MODRM(mod, rh, rl);
600 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200601 destoffset = decode_rmXX_address(mod, rl);
602 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
603 u32 destval;
604 u32 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800605
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200606 DECODE_PRINTF(",");
607 shiftreg = DECODE_RM_LONG_REGISTER(rh);
608 DECODE_PRINTF(",");
609 shift = fetch_byte_imm();
610 DECODE_PRINTF2("%d\n", shift);
611 TRACE_AND_STEP();
612 destval = fetch_data_long(destoffset);
613 destval = shrd_long(destval,*shiftreg,shift);
614 store_data_long(destoffset, destval);
615 } else {
616 u16 destval;
617 u16 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800618
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200619 DECODE_PRINTF(",");
620 shiftreg = DECODE_RM_WORD_REGISTER(rh);
621 DECODE_PRINTF(",");
622 shift = fetch_byte_imm();
623 DECODE_PRINTF2("%d\n", shift);
624 TRACE_AND_STEP();
625 destval = fetch_data_word(destoffset);
626 destval = shrd_word(destval,*shiftreg,shift);
627 store_data_word(destoffset, destval);
628 }
629 } else { /* register to register */
630 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
631 u32 *destreg,*shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800632
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200633 destreg = DECODE_RM_LONG_REGISTER(rl);
634 DECODE_PRINTF(",");
635 shiftreg = DECODE_RM_LONG_REGISTER(rh);
636 DECODE_PRINTF(",");
637 shift = fetch_byte_imm();
638 DECODE_PRINTF2("%d\n", shift);
639 TRACE_AND_STEP();
640 *destreg = shrd_long(*destreg,*shiftreg,shift);
641 } else {
642 u16 *destreg,*shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800643
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200644 destreg = DECODE_RM_WORD_REGISTER(rl);
645 DECODE_PRINTF(",");
646 shiftreg = DECODE_RM_WORD_REGISTER(rh);
647 DECODE_PRINTF(",");
648 shift = fetch_byte_imm();
649 DECODE_PRINTF2("%d\n", shift);
650 TRACE_AND_STEP();
651 *destreg = shrd_word(*destreg,*shiftreg,shift);
652 }
Jason Jinece92f82007-07-06 08:34:56 +0800653 }
654 DECODE_CLEAR_SEGOVR();
655 END_OF_INSTR();
656}
657
658/****************************************************************************
659REMARKS:
660Handles opcode 0x0f,0xad
661****************************************************************************/
662void x86emuOp2_shrd_CL(u8 X86EMU_UNUSED(op2))
663{
664 int mod, rl, rh;
665 uint destoffset;
666
667 START_OF_INSTR();
668 DECODE_PRINTF("SHLD\t");
669 FETCH_DECODE_MODRM(mod, rh, rl);
670 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200671 destoffset = decode_rmXX_address(mod, rl);
672 DECODE_PRINTF(",");
673 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
674 u32 destval;
675 u32 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800676
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200677 shiftreg = DECODE_RM_LONG_REGISTER(rh);
678 DECODE_PRINTF(",CL\n");
679 TRACE_AND_STEP();
680 destval = fetch_data_long(destoffset);
681 destval = shrd_long(destval,*shiftreg,M.x86.R_CL);
682 store_data_long(destoffset, destval);
683 } else {
684 u16 destval;
685 u16 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800686
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200687 shiftreg = DECODE_RM_WORD_REGISTER(rh);
688 DECODE_PRINTF(",CL\n");
689 TRACE_AND_STEP();
690 destval = fetch_data_word(destoffset);
691 destval = shrd_word(destval,*shiftreg,M.x86.R_CL);
692 store_data_word(destoffset, destval);
693 }
694 } else { /* register to register */
695 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
696 u32 *destreg,*shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800697
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200698 destreg = DECODE_RM_LONG_REGISTER(rl);
699 DECODE_PRINTF(",");
700 shiftreg = DECODE_RM_LONG_REGISTER(rh);
701 DECODE_PRINTF(",CL\n");
702 TRACE_AND_STEP();
703 *destreg = shrd_long(*destreg,*shiftreg,M.x86.R_CL);
704 } else {
705 u16 *destreg,*shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800706
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200707 destreg = DECODE_RM_WORD_REGISTER(rl);
708 DECODE_PRINTF(",");
709 shiftreg = DECODE_RM_WORD_REGISTER(rh);
710 DECODE_PRINTF(",CL\n");
711 TRACE_AND_STEP();
712 *destreg = shrd_word(*destreg,*shiftreg,M.x86.R_CL);
713 }
Jason Jinece92f82007-07-06 08:34:56 +0800714 }
715 DECODE_CLEAR_SEGOVR();
716 END_OF_INSTR();
717}
718
719/****************************************************************************
720REMARKS:
721Handles opcode 0x0f,0xaf
722****************************************************************************/
723void x86emuOp2_imul_R_RM(u8 X86EMU_UNUSED(op2))
724{
725 int mod, rl, rh;
726 uint srcoffset;
727
728 START_OF_INSTR();
729 DECODE_PRINTF("IMUL\t");
730 FETCH_DECODE_MODRM(mod, rh, rl);
731 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200732 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
733 u32 *destreg;
734 u32 srcval;
735 u32 res_lo,res_hi;
Jason Jinece92f82007-07-06 08:34:56 +0800736
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200737 destreg = DECODE_RM_LONG_REGISTER(rh);
738 DECODE_PRINTF(",");
739 srcoffset = decode_rmXX_address(mod, rl);
740 srcval = fetch_data_long(srcoffset);
741 TRACE_AND_STEP();
742 imul_long_direct(&res_lo,&res_hi,(s32)*destreg,(s32)srcval);
743 if (res_hi != 0) {
744 SET_FLAG(F_CF);
745 SET_FLAG(F_OF);
746 } else {
747 CLEAR_FLAG(F_CF);
748 CLEAR_FLAG(F_OF);
749 }
750 *destreg = (u32)res_lo;
751 } else {
752 u16 *destreg;
753 u16 srcval;
754 u32 res;
Jason Jinece92f82007-07-06 08:34:56 +0800755
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200756 destreg = DECODE_RM_WORD_REGISTER(rh);
757 DECODE_PRINTF(",");
758 srcoffset = decode_rmXX_address(mod, rl);
759 srcval = fetch_data_word(srcoffset);
760 TRACE_AND_STEP();
761 res = (s16)*destreg * (s16)srcval;
762 if (res > 0xFFFF) {
763 SET_FLAG(F_CF);
764 SET_FLAG(F_OF);
765 } else {
766 CLEAR_FLAG(F_CF);
767 CLEAR_FLAG(F_OF);
768 }
769 *destreg = (u16)res;
770 }
771 } else { /* register to register */
772 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
773 u32 *destreg,*srcreg;
774 u32 res_lo,res_hi;
Jason Jinece92f82007-07-06 08:34:56 +0800775
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200776 destreg = DECODE_RM_LONG_REGISTER(rh);
777 DECODE_PRINTF(",");
778 srcreg = DECODE_RM_LONG_REGISTER(rl);
779 TRACE_AND_STEP();
780 imul_long_direct(&res_lo,&res_hi,(s32)*destreg,(s32)*srcreg);
781 if (res_hi != 0) {
782 SET_FLAG(F_CF);
783 SET_FLAG(F_OF);
784 } else {
785 CLEAR_FLAG(F_CF);
786 CLEAR_FLAG(F_OF);
787 }
788 *destreg = (u32)res_lo;
789 } else {
790 u16 *destreg,*srcreg;
791 u32 res;
Jason Jinece92f82007-07-06 08:34:56 +0800792
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200793 destreg = DECODE_RM_WORD_REGISTER(rh);
794 DECODE_PRINTF(",");
795 srcreg = DECODE_RM_WORD_REGISTER(rl);
796 res = (s16)*destreg * (s16)*srcreg;
797 if (res > 0xFFFF) {
798 SET_FLAG(F_CF);
799 SET_FLAG(F_OF);
800 } else {
801 CLEAR_FLAG(F_CF);
802 CLEAR_FLAG(F_OF);
803 }
804 *destreg = (u16)res;
805 }
Jason Jinece92f82007-07-06 08:34:56 +0800806 }
807 DECODE_CLEAR_SEGOVR();
808 END_OF_INSTR();
809}
810
811/****************************************************************************
812REMARKS:
813Handles opcode 0x0f,0xb2
814****************************************************************************/
815void x86emuOp2_lss_R_IMM(u8 X86EMU_UNUSED(op2))
816{
817 int mod, rh, rl;
818 u16 *dstreg;
819 uint srcoffset;
820
821 START_OF_INSTR();
822 DECODE_PRINTF("LSS\t");
823 FETCH_DECODE_MODRM(mod, rh, rl);
824 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200825 dstreg = DECODE_RM_WORD_REGISTER(rh);
826 DECODE_PRINTF(",");
827 srcoffset = decode_rmXX_address(mod, rl);
828 DECODE_PRINTF("\n");
829 TRACE_AND_STEP();
830 *dstreg = fetch_data_word(srcoffset);
831 M.x86.R_SS = fetch_data_word(srcoffset + 2);
832 } else { /* register to register */
833 /* UNDEFINED! */
834 TRACE_AND_STEP();
Jason Jinece92f82007-07-06 08:34:56 +0800835 }
836 DECODE_CLEAR_SEGOVR();
837 END_OF_INSTR();
838}
839
840/****************************************************************************
841REMARKS:
842Handles opcode 0x0f,0xb3
843****************************************************************************/
844void x86emuOp2_btr_R(u8 X86EMU_UNUSED(op2))
845{
846 int mod, rl, rh;
847 uint srcoffset;
848 int bit,disp;
849
850 START_OF_INSTR();
851 DECODE_PRINTF("BTR\t");
852 FETCH_DECODE_MODRM(mod, rh, rl);
853 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200854 srcoffset = decode_rmXX_address(mod, rl);
855 DECODE_PRINTF(",");
856 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
857 u32 srcval,mask;
858 u32 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800859
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200860 shiftreg = DECODE_RM_LONG_REGISTER(rh);
861 TRACE_AND_STEP();
862 bit = *shiftreg & 0x1F;
863 disp = (s16)*shiftreg >> 5;
864 srcval = fetch_data_long(srcoffset+disp);
865 mask = (0x1 << bit);
866 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
867 store_data_long(srcoffset+disp, srcval & ~mask);
868 } else {
869 u16 srcval,mask;
870 u16 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +0800871
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200872 shiftreg = DECODE_RM_WORD_REGISTER(rh);
873 TRACE_AND_STEP();
874 bit = *shiftreg & 0xF;
875 disp = (s16)*shiftreg >> 4;
876 srcval = fetch_data_word(srcoffset+disp);
877 mask = (u16)(0x1 << bit);
878 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
879 store_data_word(srcoffset+disp, (u16)(srcval & ~mask));
880 }
881 } else { /* register to register */
882 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
883 u32 *srcreg,*shiftreg;
884 u32 mask;
Jason Jinece92f82007-07-06 08:34:56 +0800885
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200886 srcreg = DECODE_RM_LONG_REGISTER(rl);
887 DECODE_PRINTF(",");
888 shiftreg = DECODE_RM_LONG_REGISTER(rh);
889 TRACE_AND_STEP();
890 bit = *shiftreg & 0x1F;
891 mask = (0x1 << bit);
892 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
893 *srcreg &= ~mask;
894 } else {
895 u16 *srcreg,*shiftreg;
896 u16 mask;
Jason Jinece92f82007-07-06 08:34:56 +0800897
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200898 srcreg = DECODE_RM_WORD_REGISTER(rl);
899 DECODE_PRINTF(",");
900 shiftreg = DECODE_RM_WORD_REGISTER(rh);
901 TRACE_AND_STEP();
902 bit = *shiftreg & 0xF;
903 mask = (u16)(0x1 << bit);
904 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
905 *srcreg &= ~mask;
906 }
Jason Jinece92f82007-07-06 08:34:56 +0800907 }
908 DECODE_CLEAR_SEGOVR();
909 END_OF_INSTR();
910}
911
912/****************************************************************************
913REMARKS:
914Handles opcode 0x0f,0xb4
915****************************************************************************/
916void x86emuOp2_lfs_R_IMM(u8 X86EMU_UNUSED(op2))
917{
918 int mod, rh, rl;
919 u16 *dstreg;
920 uint srcoffset;
921
922 START_OF_INSTR();
923 DECODE_PRINTF("LFS\t");
924 FETCH_DECODE_MODRM(mod, rh, rl);
925 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200926 dstreg = DECODE_RM_WORD_REGISTER(rh);
927 DECODE_PRINTF(",");
928 srcoffset = decode_rmXX_address(mod, rl);
929 DECODE_PRINTF("\n");
930 TRACE_AND_STEP();
931 *dstreg = fetch_data_word(srcoffset);
932 M.x86.R_FS = fetch_data_word(srcoffset + 2);
933 } else { /* register to register */
934 /* UNDEFINED! */
935 TRACE_AND_STEP();
Jason Jinece92f82007-07-06 08:34:56 +0800936 }
937 DECODE_CLEAR_SEGOVR();
938 END_OF_INSTR();
939}
940
941/****************************************************************************
942REMARKS:
943Handles opcode 0x0f,0xb5
944****************************************************************************/
945void x86emuOp2_lgs_R_IMM(u8 X86EMU_UNUSED(op2))
946{
947 int mod, rh, rl;
948 u16 *dstreg;
949 uint srcoffset;
950
951 START_OF_INSTR();
952 DECODE_PRINTF("LGS\t");
953 FETCH_DECODE_MODRM(mod, rh, rl);
954 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200955 dstreg = DECODE_RM_WORD_REGISTER(rh);
956 DECODE_PRINTF(",");
957 srcoffset = decode_rmXX_address(mod, rl);
958 DECODE_PRINTF("\n");
959 TRACE_AND_STEP();
960 *dstreg = fetch_data_word(srcoffset);
961 M.x86.R_GS = fetch_data_word(srcoffset + 2);
962 } else { /* register to register */
963 /* UNDEFINED! */
964 TRACE_AND_STEP();
Jason Jinece92f82007-07-06 08:34:56 +0800965 }
966 DECODE_CLEAR_SEGOVR();
967 END_OF_INSTR();
968}
969
970/****************************************************************************
971REMARKS:
972Handles opcode 0x0f,0xb6
973****************************************************************************/
974void x86emuOp2_movzx_byte_R_RM(u8 X86EMU_UNUSED(op2))
975{
976 int mod, rl, rh;
977 uint srcoffset;
978
979 START_OF_INSTR();
980 DECODE_PRINTF("MOVZX\t");
981 FETCH_DECODE_MODRM(mod, rh, rl);
982 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200983 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
984 u32 *destreg;
985 u32 srcval;
Jason Jinece92f82007-07-06 08:34:56 +0800986
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200987 destreg = DECODE_RM_LONG_REGISTER(rh);
988 DECODE_PRINTF(",");
989 srcoffset = decode_rmXX_address(mod, rl);
990 srcval = fetch_data_byte(srcoffset);
991 DECODE_PRINTF("\n");
992 TRACE_AND_STEP();
993 *destreg = srcval;
994 } else {
995 u16 *destreg;
996 u16 srcval;
Jason Jinece92f82007-07-06 08:34:56 +0800997
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200998 destreg = DECODE_RM_WORD_REGISTER(rh);
999 DECODE_PRINTF(",");
1000 srcoffset = decode_rmXX_address(mod, rl);
1001 srcval = fetch_data_byte(srcoffset);
1002 DECODE_PRINTF("\n");
1003 TRACE_AND_STEP();
1004 *destreg = srcval;
1005 }
1006 } else { /* register to register */
1007 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1008 u32 *destreg;
1009 u8 *srcreg;
Jason Jinece92f82007-07-06 08:34:56 +08001010
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001011 destreg = DECODE_RM_LONG_REGISTER(rh);
1012 DECODE_PRINTF(",");
1013 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1014 DECODE_PRINTF("\n");
1015 TRACE_AND_STEP();
1016 *destreg = *srcreg;
1017 } else {
1018 u16 *destreg;
1019 u8 *srcreg;
Jason Jinece92f82007-07-06 08:34:56 +08001020
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001021 destreg = DECODE_RM_WORD_REGISTER(rh);
1022 DECODE_PRINTF(",");
1023 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1024 DECODE_PRINTF("\n");
1025 TRACE_AND_STEP();
1026 *destreg = *srcreg;
1027 }
Jason Jinece92f82007-07-06 08:34:56 +08001028 }
1029 DECODE_CLEAR_SEGOVR();
1030 END_OF_INSTR();
1031}
1032
1033/****************************************************************************
1034REMARKS:
1035Handles opcode 0x0f,0xb7
1036****************************************************************************/
1037void x86emuOp2_movzx_word_R_RM(u8 X86EMU_UNUSED(op2))
1038{
1039 int mod, rl, rh;
1040 uint srcoffset;
1041 u32 *destreg;
1042 u32 srcval;
1043 u16 *srcreg;
1044
1045 START_OF_INSTR();
1046 DECODE_PRINTF("MOVZX\t");
1047 FETCH_DECODE_MODRM(mod, rh, rl);
1048 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001049 destreg = DECODE_RM_LONG_REGISTER(rh);
1050 DECODE_PRINTF(",");
1051 srcoffset = decode_rmXX_address(mod, rl);
1052 srcval = fetch_data_word(srcoffset);
1053 DECODE_PRINTF("\n");
1054 TRACE_AND_STEP();
1055 *destreg = srcval;
1056 } else { /* register to register */
1057 destreg = DECODE_RM_LONG_REGISTER(rh);
1058 DECODE_PRINTF(",");
1059 srcreg = DECODE_RM_WORD_REGISTER(rl);
1060 DECODE_PRINTF("\n");
1061 TRACE_AND_STEP();
1062 *destreg = *srcreg;
Jason Jinece92f82007-07-06 08:34:56 +08001063 }
1064 DECODE_CLEAR_SEGOVR();
1065 END_OF_INSTR();
1066}
1067
1068/****************************************************************************
1069REMARKS:
1070Handles opcode 0x0f,0xba
1071****************************************************************************/
1072void x86emuOp2_btX_I(u8 X86EMU_UNUSED(op2))
1073{
1074 int mod, rl, rh;
1075 uint srcoffset;
1076 u8 shift;
1077 int bit;
1078
1079 START_OF_INSTR();
1080 FETCH_DECODE_MODRM(mod, rh, rl);
1081 switch (rh) {
1082 case 4:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001083 DECODE_PRINTF("BT\t");
1084 break;
Jason Jinece92f82007-07-06 08:34:56 +08001085 case 5:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001086 DECODE_PRINTF("BTS\t");
1087 break;
Jason Jinece92f82007-07-06 08:34:56 +08001088 case 6:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001089 DECODE_PRINTF("BTR\t");
1090 break;
Jason Jinece92f82007-07-06 08:34:56 +08001091 case 7:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001092 DECODE_PRINTF("BTC\t");
1093 break;
Jason Jinece92f82007-07-06 08:34:56 +08001094 default:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001095 DECODE_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n");
1096 TRACE_REGS();
1097 printk("%04x:%04x: %02X%02X ILLEGAL EXTENDED X86 OPCODE EXTENSION!\n",
1098 M.x86.R_CS, M.x86.R_IP-3,op2, (mod<<6)|(rh<<3)|rl);
1099 HALT_SYS();
Jason Jinece92f82007-07-06 08:34:56 +08001100 }
1101 if (mod < 3) {
1102
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001103 srcoffset = decode_rmXX_address(mod, rl);
1104 shift = fetch_byte_imm();
1105 DECODE_PRINTF2(",%d\n", shift);
1106 TRACE_AND_STEP();
Jason Jinece92f82007-07-06 08:34:56 +08001107
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001108 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1109 u32 srcval, mask;
Jason Jinece92f82007-07-06 08:34:56 +08001110
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001111 bit = shift & 0x1F;
1112 srcval = fetch_data_long(srcoffset);
1113 mask = (0x1 << bit);
1114 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1115 switch (rh) {
1116 case 5:
1117 store_data_long(srcoffset, srcval | mask);
1118 break;
1119 case 6:
1120 store_data_long(srcoffset, srcval & ~mask);
1121 break;
1122 case 7:
1123 store_data_long(srcoffset, srcval ^ mask);
1124 break;
1125 default:
1126 break;
1127 }
1128 } else {
1129 u16 srcval, mask;
Jason Jinece92f82007-07-06 08:34:56 +08001130
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001131 bit = shift & 0xF;
1132 srcval = fetch_data_word(srcoffset);
1133 mask = (0x1 << bit);
1134 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1135 switch (rh) {
1136 case 5:
1137 store_data_word(srcoffset, srcval | mask);
1138 break;
1139 case 6:
1140 store_data_word(srcoffset, srcval & ~mask);
1141 break;
1142 case 7:
1143 store_data_word(srcoffset, srcval ^ mask);
1144 break;
1145 default:
1146 break;
1147 }
1148 }
1149 } else { /* register to register */
1150 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1151 u32 *srcreg;
1152 u32 mask;
Jason Jinece92f82007-07-06 08:34:56 +08001153
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001154 srcreg = DECODE_RM_LONG_REGISTER(rl);
1155 shift = fetch_byte_imm();
1156 DECODE_PRINTF2(",%d\n", shift);
1157 TRACE_AND_STEP();
1158 bit = shift & 0x1F;
1159 mask = (0x1 << bit);
1160 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1161 switch (rh) {
1162 case 5:
1163 *srcreg |= mask;
1164 break;
1165 case 6:
1166 *srcreg &= ~mask;
1167 break;
1168 case 7:
1169 *srcreg ^= mask;
1170 break;
1171 default:
1172 break;
1173 }
1174 } else {
1175 u16 *srcreg;
1176 u16 mask;
Jason Jinece92f82007-07-06 08:34:56 +08001177
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001178 srcreg = DECODE_RM_WORD_REGISTER(rl);
1179 shift = fetch_byte_imm();
1180 DECODE_PRINTF2(",%d\n", shift);
1181 TRACE_AND_STEP();
1182 bit = shift & 0xF;
1183 mask = (0x1 << bit);
1184 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1185 switch (rh) {
1186 case 5:
1187 *srcreg |= mask;
1188 break;
1189 case 6:
1190 *srcreg &= ~mask;
1191 break;
1192 case 7:
1193 *srcreg ^= mask;
1194 break;
1195 default:
1196 break;
1197 }
1198 }
Jason Jinece92f82007-07-06 08:34:56 +08001199 }
1200 DECODE_CLEAR_SEGOVR();
1201 END_OF_INSTR();
1202}
1203
1204/****************************************************************************
1205REMARKS:
1206Handles opcode 0x0f,0xbb
1207****************************************************************************/
1208void x86emuOp2_btc_R(u8 X86EMU_UNUSED(op2))
1209{
1210 int mod, rl, rh;
1211 uint srcoffset;
1212 int bit,disp;
1213
1214 START_OF_INSTR();
1215 DECODE_PRINTF("BTC\t");
1216 FETCH_DECODE_MODRM(mod, rh, rl);
1217 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001218 srcoffset = decode_rmXX_address(mod, rl);
1219 DECODE_PRINTF(",");
1220 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1221 u32 srcval,mask;
1222 u32 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +08001223
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001224 shiftreg = DECODE_RM_LONG_REGISTER(rh);
1225 TRACE_AND_STEP();
1226 bit = *shiftreg & 0x1F;
1227 disp = (s16)*shiftreg >> 5;
1228 srcval = fetch_data_long(srcoffset+disp);
1229 mask = (0x1 << bit);
1230 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1231 store_data_long(srcoffset+disp, srcval ^ mask);
1232 } else {
1233 u16 srcval,mask;
1234 u16 *shiftreg;
Jason Jinece92f82007-07-06 08:34:56 +08001235
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001236 shiftreg = DECODE_RM_WORD_REGISTER(rh);
1237 TRACE_AND_STEP();
1238 bit = *shiftreg & 0xF;
1239 disp = (s16)*shiftreg >> 4;
1240 srcval = fetch_data_word(srcoffset+disp);
1241 mask = (u16)(0x1 << bit);
1242 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1243 store_data_word(srcoffset+disp, (u16)(srcval ^ mask));
1244 }
1245 } else { /* register to register */
1246 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1247 u32 *srcreg,*shiftreg;
1248 u32 mask;
Jason Jinece92f82007-07-06 08:34:56 +08001249
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001250 srcreg = DECODE_RM_LONG_REGISTER(rl);
1251 DECODE_PRINTF(",");
1252 shiftreg = DECODE_RM_LONG_REGISTER(rh);
1253 TRACE_AND_STEP();
1254 bit = *shiftreg & 0x1F;
1255 mask = (0x1 << bit);
1256 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1257 *srcreg ^= mask;
1258 } else {
1259 u16 *srcreg,*shiftreg;
1260 u16 mask;
Jason Jinece92f82007-07-06 08:34:56 +08001261
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001262 srcreg = DECODE_RM_WORD_REGISTER(rl);
1263 DECODE_PRINTF(",");
1264 shiftreg = DECODE_RM_WORD_REGISTER(rh);
1265 TRACE_AND_STEP();
1266 bit = *shiftreg & 0xF;
1267 mask = (u16)(0x1 << bit);
1268 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1269 *srcreg ^= mask;
1270 }
Jason Jinece92f82007-07-06 08:34:56 +08001271 }
1272 DECODE_CLEAR_SEGOVR();
1273 END_OF_INSTR();
1274}
1275
1276/****************************************************************************
1277REMARKS:
1278Handles opcode 0x0f,0xbc
1279****************************************************************************/
1280void x86emuOp2_bsf(u8 X86EMU_UNUSED(op2))
1281{
1282 int mod, rl, rh;
1283 uint srcoffset;
1284
1285 START_OF_INSTR();
1286 DECODE_PRINTF("BSF\n");
1287 FETCH_DECODE_MODRM(mod, rh, rl);
1288 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001289 srcoffset = decode_rmXX_address(mod, rl);
1290 DECODE_PRINTF(",");
1291 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1292 u32 srcval, *dstreg;
Jason Jinece92f82007-07-06 08:34:56 +08001293
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001294 dstreg = DECODE_RM_LONG_REGISTER(rh);
1295 TRACE_AND_STEP();
1296 srcval = fetch_data_long(srcoffset);
1297 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
1298 for(*dstreg = 0; *dstreg < 32; (*dstreg)++)
1299 if ((srcval >> *dstreg) & 1) break;
1300 } else {
1301 u16 srcval, *dstreg;
Jason Jinece92f82007-07-06 08:34:56 +08001302
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001303 dstreg = DECODE_RM_WORD_REGISTER(rh);
1304 TRACE_AND_STEP();
1305 srcval = fetch_data_word(srcoffset);
1306 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
1307 for(*dstreg = 0; *dstreg < 16; (*dstreg)++)
1308 if ((srcval >> *dstreg) & 1) break;
1309 }
1310 } else { /* register to register */
1311 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1312 u32 *srcreg, *dstreg;
Jason Jinece92f82007-07-06 08:34:56 +08001313
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001314 srcreg = DECODE_RM_LONG_REGISTER(rl);
1315 DECODE_PRINTF(",");
1316 dstreg = DECODE_RM_LONG_REGISTER(rh);
1317 TRACE_AND_STEP();
1318 CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF);
1319 for(*dstreg = 0; *dstreg < 32; (*dstreg)++)
1320 if ((*srcreg >> *dstreg) & 1) break;
1321 } else {
1322 u16 *srcreg, *dstreg;
Jason Jinece92f82007-07-06 08:34:56 +08001323
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001324 srcreg = DECODE_RM_WORD_REGISTER(rl);
1325 DECODE_PRINTF(",");
1326 dstreg = DECODE_RM_WORD_REGISTER(rh);
1327 TRACE_AND_STEP();
1328 CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF);
1329 for(*dstreg = 0; *dstreg < 16; (*dstreg)++)
1330 if ((*srcreg >> *dstreg) & 1) break;
1331 }
Jason Jinece92f82007-07-06 08:34:56 +08001332 }
1333 DECODE_CLEAR_SEGOVR();
1334 END_OF_INSTR();
1335}
1336
1337/****************************************************************************
1338REMARKS:
1339Handles opcode 0x0f,0xbd
1340****************************************************************************/
1341void x86emuOp2_bsr(u8 X86EMU_UNUSED(op2))
1342{
1343 int mod, rl, rh;
1344 uint srcoffset;
1345
1346 START_OF_INSTR();
1347 DECODE_PRINTF("BSF\n");
1348 FETCH_DECODE_MODRM(mod, rh, rl);
1349 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001350 srcoffset = decode_rmXX_address(mod, rl);
1351 DECODE_PRINTF(",");
1352 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1353 u32 srcval, *dstreg;
Jason Jinece92f82007-07-06 08:34:56 +08001354
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001355 dstreg = DECODE_RM_LONG_REGISTER(rh);
1356 TRACE_AND_STEP();
1357 srcval = fetch_data_long(srcoffset);
1358 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
1359 for(*dstreg = 31; *dstreg > 0; (*dstreg)--)
1360 if ((srcval >> *dstreg) & 1) break;
1361 } else {
1362 u16 srcval, *dstreg;
Jason Jinece92f82007-07-06 08:34:56 +08001363
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001364 dstreg = DECODE_RM_WORD_REGISTER(rh);
1365 TRACE_AND_STEP();
1366 srcval = fetch_data_word(srcoffset);
1367 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
1368 for(*dstreg = 15; *dstreg > 0; (*dstreg)--)
1369 if ((srcval >> *dstreg) & 1) break;
1370 }
1371 } else { /* register to register */
1372 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1373 u32 *srcreg, *dstreg;
Jason Jinece92f82007-07-06 08:34:56 +08001374
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001375 srcreg = DECODE_RM_LONG_REGISTER(rl);
1376 DECODE_PRINTF(",");
1377 dstreg = DECODE_RM_LONG_REGISTER(rh);
1378 TRACE_AND_STEP();
1379 CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF);
1380 for(*dstreg = 31; *dstreg > 0; (*dstreg)--)
1381 if ((*srcreg >> *dstreg) & 1) break;
1382 } else {
1383 u16 *srcreg, *dstreg;
Jason Jinece92f82007-07-06 08:34:56 +08001384
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001385 srcreg = DECODE_RM_WORD_REGISTER(rl);
1386 DECODE_PRINTF(",");
1387 dstreg = DECODE_RM_WORD_REGISTER(rh);
1388 TRACE_AND_STEP();
1389 CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF);
1390 for(*dstreg = 15; *dstreg > 0; (*dstreg)--)
1391 if ((*srcreg >> *dstreg) & 1) break;
1392 }
Jason Jinece92f82007-07-06 08:34:56 +08001393 }
1394 DECODE_CLEAR_SEGOVR();
1395 END_OF_INSTR();
1396}
1397
1398/****************************************************************************
1399REMARKS:
1400Handles opcode 0x0f,0xbe
1401****************************************************************************/
1402void x86emuOp2_movsx_byte_R_RM(u8 X86EMU_UNUSED(op2))
1403{
1404 int mod, rl, rh;
1405 uint srcoffset;
1406
1407 START_OF_INSTR();
1408 DECODE_PRINTF("MOVSX\t");
1409 FETCH_DECODE_MODRM(mod, rh, rl);
1410 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001411 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1412 u32 *destreg;
1413 u32 srcval;
Jason Jinece92f82007-07-06 08:34:56 +08001414
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001415 destreg = DECODE_RM_LONG_REGISTER(rh);
1416 DECODE_PRINTF(",");
1417 srcoffset = decode_rmXX_address(mod, rl);
1418 srcval = (s32)((s8)fetch_data_byte(srcoffset));
1419 DECODE_PRINTF("\n");
1420 TRACE_AND_STEP();
1421 *destreg = srcval;
1422 } else {
1423 u16 *destreg;
1424 u16 srcval;
Jason Jinece92f82007-07-06 08:34:56 +08001425
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001426 destreg = DECODE_RM_WORD_REGISTER(rh);
1427 DECODE_PRINTF(",");
1428 srcoffset = decode_rmXX_address(mod, rl);
1429 srcval = (s16)((s8)fetch_data_byte(srcoffset));
1430 DECODE_PRINTF("\n");
1431 TRACE_AND_STEP();
1432 *destreg = srcval;
1433 }
1434 } else { /* register to register */
1435 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1436 u32 *destreg;
1437 u8 *srcreg;
Jason Jinece92f82007-07-06 08:34:56 +08001438
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001439 destreg = DECODE_RM_LONG_REGISTER(rh);
1440 DECODE_PRINTF(",");
1441 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1442 DECODE_PRINTF("\n");
1443 TRACE_AND_STEP();
1444 *destreg = (s32)((s8)*srcreg);
1445 } else {
1446 u16 *destreg;
1447 u8 *srcreg;
Jason Jinece92f82007-07-06 08:34:56 +08001448
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001449 destreg = DECODE_RM_WORD_REGISTER(rh);
1450 DECODE_PRINTF(",");
1451 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1452 DECODE_PRINTF("\n");
1453 TRACE_AND_STEP();
1454 *destreg = (s16)((s8)*srcreg);
1455 }
Jason Jinece92f82007-07-06 08:34:56 +08001456 }
1457 DECODE_CLEAR_SEGOVR();
1458 END_OF_INSTR();
1459}
1460
1461/****************************************************************************
1462REMARKS:
1463Handles opcode 0x0f,0xbf
1464****************************************************************************/
1465void x86emuOp2_movsx_word_R_RM(u8 X86EMU_UNUSED(op2))
1466{
1467 int mod, rl, rh;
1468 uint srcoffset;
1469 u32 *destreg;
1470 u32 srcval;
1471 u16 *srcreg;
1472
1473 START_OF_INSTR();
1474 DECODE_PRINTF("MOVSX\t");
1475 FETCH_DECODE_MODRM(mod, rh, rl);
1476 if (mod < 3) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001477 destreg = DECODE_RM_LONG_REGISTER(rh);
1478 DECODE_PRINTF(",");
1479 srcoffset = decode_rmXX_address(mod, rl);
1480 srcval = (s32)((s16)fetch_data_word(srcoffset));
1481 DECODE_PRINTF("\n");
1482 TRACE_AND_STEP();
1483 *destreg = srcval;
1484 } else { /* register to register */
1485 destreg = DECODE_RM_LONG_REGISTER(rh);
1486 DECODE_PRINTF(",");
1487 srcreg = DECODE_RM_WORD_REGISTER(rl);
1488 DECODE_PRINTF("\n");
1489 TRACE_AND_STEP();
1490 *destreg = (s32)((s16)*srcreg);
Jason Jinece92f82007-07-06 08:34:56 +08001491 }
1492 DECODE_CLEAR_SEGOVR();
1493 END_OF_INSTR();
1494}
1495
1496/***************************************************************************
1497 * Double byte operation code table:
1498 **************************************************************************/
1499void (*x86emu_optab2[256])(u8) __attribute__((section(".got2"))) =
1500{
1501/* 0x00 */ x86emuOp2_illegal_op, /* Group F (ring 0 PM) */
1502/* 0x01 */ x86emuOp2_illegal_op, /* Group G (ring 0 PM) */
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001503/* 0x02 */ x86emuOp2_illegal_op, /* lar (ring 0 PM) */
1504/* 0x03 */ x86emuOp2_illegal_op, /* lsl (ring 0 PM) */
Jason Jinece92f82007-07-06 08:34:56 +08001505/* 0x04 */ x86emuOp2_illegal_op,
1506/* 0x05 */ x86emuOp2_illegal_op, /* loadall (undocumented) */
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001507/* 0x06 */ x86emuOp2_illegal_op, /* clts (ring 0 PM) */
Jason Jinece92f82007-07-06 08:34:56 +08001508/* 0x07 */ x86emuOp2_illegal_op, /* loadall (undocumented) */
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001509/* 0x08 */ x86emuOp2_illegal_op, /* invd (ring 0 PM) */
Jason Jinece92f82007-07-06 08:34:56 +08001510/* 0x09 */ x86emuOp2_illegal_op, /* wbinvd (ring 0 PM) */
1511/* 0x0a */ x86emuOp2_illegal_op,
1512/* 0x0b */ x86emuOp2_illegal_op,
1513/* 0x0c */ x86emuOp2_illegal_op,
1514/* 0x0d */ x86emuOp2_illegal_op,
1515/* 0x0e */ x86emuOp2_illegal_op,
1516/* 0x0f */ x86emuOp2_illegal_op,
1517
1518/* 0x10 */ x86emuOp2_illegal_op,
1519/* 0x11 */ x86emuOp2_illegal_op,
1520/* 0x12 */ x86emuOp2_illegal_op,
1521/* 0x13 */ x86emuOp2_illegal_op,
1522/* 0x14 */ x86emuOp2_illegal_op,
1523/* 0x15 */ x86emuOp2_illegal_op,
1524/* 0x16 */ x86emuOp2_illegal_op,
1525/* 0x17 */ x86emuOp2_illegal_op,
1526/* 0x18 */ x86emuOp2_illegal_op,
1527/* 0x19 */ x86emuOp2_illegal_op,
1528/* 0x1a */ x86emuOp2_illegal_op,
1529/* 0x1b */ x86emuOp2_illegal_op,
1530/* 0x1c */ x86emuOp2_illegal_op,
1531/* 0x1d */ x86emuOp2_illegal_op,
1532/* 0x1e */ x86emuOp2_illegal_op,
1533/* 0x1f */ x86emuOp2_illegal_op,
1534
1535/* 0x20 */ x86emuOp2_illegal_op, /* mov reg32,creg (ring 0 PM) */
1536/* 0x21 */ x86emuOp2_illegal_op, /* mov reg32,dreg (ring 0 PM) */
1537/* 0x22 */ x86emuOp2_illegal_op, /* mov creg,reg32 (ring 0 PM) */
1538/* 0x23 */ x86emuOp2_illegal_op, /* mov dreg,reg32 (ring 0 PM) */
1539/* 0x24 */ x86emuOp2_illegal_op, /* mov reg32,treg (ring 0 PM) */
1540/* 0x25 */ x86emuOp2_illegal_op,
1541/* 0x26 */ x86emuOp2_illegal_op, /* mov treg,reg32 (ring 0 PM) */
1542/* 0x27 */ x86emuOp2_illegal_op,
1543/* 0x28 */ x86emuOp2_illegal_op,
1544/* 0x29 */ x86emuOp2_illegal_op,
1545/* 0x2a */ x86emuOp2_illegal_op,
1546/* 0x2b */ x86emuOp2_illegal_op,
1547/* 0x2c */ x86emuOp2_illegal_op,
1548/* 0x2d */ x86emuOp2_illegal_op,
1549/* 0x2e */ x86emuOp2_illegal_op,
1550/* 0x2f */ x86emuOp2_illegal_op,
1551
1552/* 0x30 */ x86emuOp2_illegal_op,
1553/* 0x31 */ x86emuOp2_illegal_op,
1554/* 0x32 */ x86emuOp2_illegal_op,
1555/* 0x33 */ x86emuOp2_illegal_op,
1556/* 0x34 */ x86emuOp2_illegal_op,
1557/* 0x35 */ x86emuOp2_illegal_op,
1558/* 0x36 */ x86emuOp2_illegal_op,
1559/* 0x37 */ x86emuOp2_illegal_op,
1560/* 0x38 */ x86emuOp2_illegal_op,
1561/* 0x39 */ x86emuOp2_illegal_op,
1562/* 0x3a */ x86emuOp2_illegal_op,
1563/* 0x3b */ x86emuOp2_illegal_op,
1564/* 0x3c */ x86emuOp2_illegal_op,
1565/* 0x3d */ x86emuOp2_illegal_op,
1566/* 0x3e */ x86emuOp2_illegal_op,
1567/* 0x3f */ x86emuOp2_illegal_op,
1568
1569/* 0x40 */ x86emuOp2_illegal_op,
1570/* 0x41 */ x86emuOp2_illegal_op,
1571/* 0x42 */ x86emuOp2_illegal_op,
1572/* 0x43 */ x86emuOp2_illegal_op,
1573/* 0x44 */ x86emuOp2_illegal_op,
1574/* 0x45 */ x86emuOp2_illegal_op,
1575/* 0x46 */ x86emuOp2_illegal_op,
1576/* 0x47 */ x86emuOp2_illegal_op,
1577/* 0x48 */ x86emuOp2_illegal_op,
1578/* 0x49 */ x86emuOp2_illegal_op,
1579/* 0x4a */ x86emuOp2_illegal_op,
1580/* 0x4b */ x86emuOp2_illegal_op,
1581/* 0x4c */ x86emuOp2_illegal_op,
1582/* 0x4d */ x86emuOp2_illegal_op,
1583/* 0x4e */ x86emuOp2_illegal_op,
1584/* 0x4f */ x86emuOp2_illegal_op,
1585
1586/* 0x50 */ x86emuOp2_illegal_op,
1587/* 0x51 */ x86emuOp2_illegal_op,
1588/* 0x52 */ x86emuOp2_illegal_op,
1589/* 0x53 */ x86emuOp2_illegal_op,
1590/* 0x54 */ x86emuOp2_illegal_op,
1591/* 0x55 */ x86emuOp2_illegal_op,
1592/* 0x56 */ x86emuOp2_illegal_op,
1593/* 0x57 */ x86emuOp2_illegal_op,
1594/* 0x58 */ x86emuOp2_illegal_op,
1595/* 0x59 */ x86emuOp2_illegal_op,
1596/* 0x5a */ x86emuOp2_illegal_op,
1597/* 0x5b */ x86emuOp2_illegal_op,
1598/* 0x5c */ x86emuOp2_illegal_op,
1599/* 0x5d */ x86emuOp2_illegal_op,
1600/* 0x5e */ x86emuOp2_illegal_op,
1601/* 0x5f */ x86emuOp2_illegal_op,
1602
1603/* 0x60 */ x86emuOp2_illegal_op,
1604/* 0x61 */ x86emuOp2_illegal_op,
1605/* 0x62 */ x86emuOp2_illegal_op,
1606/* 0x63 */ x86emuOp2_illegal_op,
1607/* 0x64 */ x86emuOp2_illegal_op,
1608/* 0x65 */ x86emuOp2_illegal_op,
1609/* 0x66 */ x86emuOp2_illegal_op,
1610/* 0x67 */ x86emuOp2_illegal_op,
1611/* 0x68 */ x86emuOp2_illegal_op,
1612/* 0x69 */ x86emuOp2_illegal_op,
1613/* 0x6a */ x86emuOp2_illegal_op,
1614/* 0x6b */ x86emuOp2_illegal_op,
1615/* 0x6c */ x86emuOp2_illegal_op,
1616/* 0x6d */ x86emuOp2_illegal_op,
1617/* 0x6e */ x86emuOp2_illegal_op,
1618/* 0x6f */ x86emuOp2_illegal_op,
1619
1620/* 0x70 */ x86emuOp2_illegal_op,
1621/* 0x71 */ x86emuOp2_illegal_op,
1622/* 0x72 */ x86emuOp2_illegal_op,
1623/* 0x73 */ x86emuOp2_illegal_op,
1624/* 0x74 */ x86emuOp2_illegal_op,
1625/* 0x75 */ x86emuOp2_illegal_op,
1626/* 0x76 */ x86emuOp2_illegal_op,
1627/* 0x77 */ x86emuOp2_illegal_op,
1628/* 0x78 */ x86emuOp2_illegal_op,
1629/* 0x79 */ x86emuOp2_illegal_op,
1630/* 0x7a */ x86emuOp2_illegal_op,
1631/* 0x7b */ x86emuOp2_illegal_op,
1632/* 0x7c */ x86emuOp2_illegal_op,
1633/* 0x7d */ x86emuOp2_illegal_op,
1634/* 0x7e */ x86emuOp2_illegal_op,
1635/* 0x7f */ x86emuOp2_illegal_op,
1636
1637/* 0x80 */ x86emuOp2_long_jump,
1638/* 0x81 */ x86emuOp2_long_jump,
1639/* 0x82 */ x86emuOp2_long_jump,
1640/* 0x83 */ x86emuOp2_long_jump,
1641/* 0x84 */ x86emuOp2_long_jump,
1642/* 0x85 */ x86emuOp2_long_jump,
1643/* 0x86 */ x86emuOp2_long_jump,
1644/* 0x87 */ x86emuOp2_long_jump,
1645/* 0x88 */ x86emuOp2_long_jump,
1646/* 0x89 */ x86emuOp2_long_jump,
1647/* 0x8a */ x86emuOp2_long_jump,
1648/* 0x8b */ x86emuOp2_long_jump,
1649/* 0x8c */ x86emuOp2_long_jump,
1650/* 0x8d */ x86emuOp2_long_jump,
1651/* 0x8e */ x86emuOp2_long_jump,
1652/* 0x8f */ x86emuOp2_long_jump,
1653
1654/* 0x90 */ x86emuOp2_set_byte,
1655/* 0x91 */ x86emuOp2_set_byte,
1656/* 0x92 */ x86emuOp2_set_byte,
1657/* 0x93 */ x86emuOp2_set_byte,
1658/* 0x94 */ x86emuOp2_set_byte,
1659/* 0x95 */ x86emuOp2_set_byte,
1660/* 0x96 */ x86emuOp2_set_byte,
1661/* 0x97 */ x86emuOp2_set_byte,
1662/* 0x98 */ x86emuOp2_set_byte,
1663/* 0x99 */ x86emuOp2_set_byte,
1664/* 0x9a */ x86emuOp2_set_byte,
1665/* 0x9b */ x86emuOp2_set_byte,
1666/* 0x9c */ x86emuOp2_set_byte,
1667/* 0x9d */ x86emuOp2_set_byte,
1668/* 0x9e */ x86emuOp2_set_byte,
1669/* 0x9f */ x86emuOp2_set_byte,
1670
1671/* 0xa0 */ x86emuOp2_push_FS,
1672/* 0xa1 */ x86emuOp2_pop_FS,
1673/* 0xa2 */ x86emuOp2_illegal_op,
1674/* 0xa3 */ x86emuOp2_bt_R,
1675/* 0xa4 */ x86emuOp2_shld_IMM,
1676/* 0xa5 */ x86emuOp2_shld_CL,
1677/* 0xa6 */ x86emuOp2_illegal_op,
1678/* 0xa7 */ x86emuOp2_illegal_op,
1679/* 0xa8 */ x86emuOp2_push_GS,
1680/* 0xa9 */ x86emuOp2_pop_GS,
1681/* 0xaa */ x86emuOp2_illegal_op,
1682/* 0xab */ x86emuOp2_bt_R,
1683/* 0xac */ x86emuOp2_shrd_IMM,
1684/* 0xad */ x86emuOp2_shrd_CL,
1685/* 0xae */ x86emuOp2_illegal_op,
1686/* 0xaf */ x86emuOp2_imul_R_RM,
1687
1688/* 0xb0 */ x86emuOp2_illegal_op, /* TODO: cmpxchg */
1689/* 0xb1 */ x86emuOp2_illegal_op, /* TODO: cmpxchg */
1690/* 0xb2 */ x86emuOp2_lss_R_IMM,
1691/* 0xb3 */ x86emuOp2_btr_R,
1692/* 0xb4 */ x86emuOp2_lfs_R_IMM,
1693/* 0xb5 */ x86emuOp2_lgs_R_IMM,
1694/* 0xb6 */ x86emuOp2_movzx_byte_R_RM,
1695/* 0xb7 */ x86emuOp2_movzx_word_R_RM,
1696/* 0xb8 */ x86emuOp2_illegal_op,
1697/* 0xb9 */ x86emuOp2_illegal_op,
1698/* 0xba */ x86emuOp2_btX_I,
1699/* 0xbb */ x86emuOp2_btc_R,
1700/* 0xbc */ x86emuOp2_bsf,
1701/* 0xbd */ x86emuOp2_bsr,
1702/* 0xbe */ x86emuOp2_movsx_byte_R_RM,
1703/* 0xbf */ x86emuOp2_movsx_word_R_RM,
1704
1705/* 0xc0 */ x86emuOp2_illegal_op, /* TODO: xadd */
1706/* 0xc1 */ x86emuOp2_illegal_op, /* TODO: xadd */
1707/* 0xc2 */ x86emuOp2_illegal_op,
1708/* 0xc3 */ x86emuOp2_illegal_op,
1709/* 0xc4 */ x86emuOp2_illegal_op,
1710/* 0xc5 */ x86emuOp2_illegal_op,
1711/* 0xc6 */ x86emuOp2_illegal_op,
1712/* 0xc7 */ x86emuOp2_illegal_op,
1713/* 0xc8 */ x86emuOp2_illegal_op, /* TODO: bswap */
1714/* 0xc9 */ x86emuOp2_illegal_op, /* TODO: bswap */
1715/* 0xca */ x86emuOp2_illegal_op, /* TODO: bswap */
1716/* 0xcb */ x86emuOp2_illegal_op, /* TODO: bswap */
1717/* 0xcc */ x86emuOp2_illegal_op, /* TODO: bswap */
1718/* 0xcd */ x86emuOp2_illegal_op, /* TODO: bswap */
1719/* 0xce */ x86emuOp2_illegal_op, /* TODO: bswap */
1720/* 0xcf */ x86emuOp2_illegal_op, /* TODO: bswap */
1721
1722/* 0xd0 */ x86emuOp2_illegal_op,
1723/* 0xd1 */ x86emuOp2_illegal_op,
1724/* 0xd2 */ x86emuOp2_illegal_op,
1725/* 0xd3 */ x86emuOp2_illegal_op,
1726/* 0xd4 */ x86emuOp2_illegal_op,
1727/* 0xd5 */ x86emuOp2_illegal_op,
1728/* 0xd6 */ x86emuOp2_illegal_op,
1729/* 0xd7 */ x86emuOp2_illegal_op,
1730/* 0xd8 */ x86emuOp2_illegal_op,
1731/* 0xd9 */ x86emuOp2_illegal_op,
1732/* 0xda */ x86emuOp2_illegal_op,
1733/* 0xdb */ x86emuOp2_illegal_op,
1734/* 0xdc */ x86emuOp2_illegal_op,
1735/* 0xdd */ x86emuOp2_illegal_op,
1736/* 0xde */ x86emuOp2_illegal_op,
1737/* 0xdf */ x86emuOp2_illegal_op,
1738
1739/* 0xe0 */ x86emuOp2_illegal_op,
1740/* 0xe1 */ x86emuOp2_illegal_op,
1741/* 0xe2 */ x86emuOp2_illegal_op,
1742/* 0xe3 */ x86emuOp2_illegal_op,
1743/* 0xe4 */ x86emuOp2_illegal_op,
1744/* 0xe5 */ x86emuOp2_illegal_op,
1745/* 0xe6 */ x86emuOp2_illegal_op,
1746/* 0xe7 */ x86emuOp2_illegal_op,
1747/* 0xe8 */ x86emuOp2_illegal_op,
1748/* 0xe9 */ x86emuOp2_illegal_op,
1749/* 0xea */ x86emuOp2_illegal_op,
1750/* 0xeb */ x86emuOp2_illegal_op,
1751/* 0xec */ x86emuOp2_illegal_op,
1752/* 0xed */ x86emuOp2_illegal_op,
1753/* 0xee */ x86emuOp2_illegal_op,
1754/* 0xef */ x86emuOp2_illegal_op,
1755
1756/* 0xf0 */ x86emuOp2_illegal_op,
1757/* 0xf1 */ x86emuOp2_illegal_op,
1758/* 0xf2 */ x86emuOp2_illegal_op,
1759/* 0xf3 */ x86emuOp2_illegal_op,
1760/* 0xf4 */ x86emuOp2_illegal_op,
1761/* 0xf5 */ x86emuOp2_illegal_op,
1762/* 0xf6 */ x86emuOp2_illegal_op,
1763/* 0xf7 */ x86emuOp2_illegal_op,
1764/* 0xf8 */ x86emuOp2_illegal_op,
1765/* 0xf9 */ x86emuOp2_illegal_op,
1766/* 0xfa */ x86emuOp2_illegal_op,
1767/* 0xfb */ x86emuOp2_illegal_op,
1768/* 0xfc */ x86emuOp2_illegal_op,
1769/* 0xfd */ x86emuOp2_illegal_op,
1770/* 0xfe */ x86emuOp2_illegal_op,
1771/* 0xff */ x86emuOp2_illegal_op,
1772};
Jason Jince981dc2007-08-08 08:33:11 +08001773
1774#endif