blob: 1ff27b2af9511d7ffe948fd2cd011e2a26e8a254 [file] [log] [blame]
Jason Jina63ce952007-07-06 08:34:56 +08001/****************************************************************************
2*
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003* Realmode X86 Emulator Library
Jason Jina63ce952007-07-06 08:34:56 +08004*
Kumar Gala6a6d9482009-07-28 21:49:52 -05005* Copyright (C) 2007 Freescale Semiconductor, Inc.
Jason Jina63ce952007-07-06 08:34:56 +08006* Jason Jin <Jason.jin@freescale.com>
7*
Wolfgang Denk96bb2e02007-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 Jina63ce952007-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 Denk96bb2e02007-08-06 02:17:36 +020020* without specific, written prior permission. The authors makes no
Jason Jina63ce952007-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 Denk96bb2e02007-08-06 02:17:36 +020034* Language: ANSI C
35* Environment: Any
36* Developer: Kendall Bennett
Jason Jina63ce952007-07-06 08:34:56 +080037*
Wolfgang Denk96bb2e02007-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 Jina63ce952007-07-06 08:34:56 +080041*
Jason Jina63ce952007-07-06 08:34:56 +080042****************************************************************************/
43
Kumar Gala812a1742011-11-23 06:31:04 +000044#include <linux/compiler.h>
Simon Glassbdd5f812023-09-14 18:21:46 -060045#include <linux/printk.h>
Michal Simek952d8612007-08-15 21:15:05 +020046#include "x86emu/x86emui.h"
47
Jason Jina63ce952007-07-06 08:34:56 +080048/*----------------------------- Implementation ----------------------------*/
49
50/****************************************************************************
51PARAMETERS:
52op1 - Instruction op code
53
54REMARKS:
55Handles illegal opcodes.
56****************************************************************************/
57void x86emuOp2_illegal_op(
58 u8 op2)
59{
60 START_OF_INSTR();
Simon Glassb91ea302014-11-14 20:56:43 -070061 ERR_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n");
Jason Jina63ce952007-07-06 08:34:56 +080062 TRACE_REGS();
63 printk("%04x:%04x: %02X ILLEGAL EXTENDED X86 OPCODE!\n",
Wolfgang Denk96bb2e02007-08-06 02:17:36 +020064 M.x86.R_CS, M.x86.R_IP-2,op2);
Jason Jina63ce952007-07-06 08:34:56 +080065 HALT_SYS();
66 END_OF_INSTR();
67}
68
69#define xorl(a,b) ((a) && !(b)) || (!(a) && (b))
70
71/****************************************************************************
72REMARKS:
73Handles opcode 0x0f,0x80-0x8F
74****************************************************************************/
75int x86emu_check_jump_condition(u8 op)
76{
77 switch (op) {
78 case 0x0:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +020079 DECODE_PRINTF("JO\t");
80 return ACCESS_FLAG(F_OF);
Jason Jina63ce952007-07-06 08:34:56 +080081 case 0x1:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +020082 DECODE_PRINTF("JNO\t");
83 return !ACCESS_FLAG(F_OF);
84 break;
Jason Jina63ce952007-07-06 08:34:56 +080085 case 0x2:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +020086 DECODE_PRINTF("JB\t");
87 return ACCESS_FLAG(F_CF);
88 break;
Jason Jina63ce952007-07-06 08:34:56 +080089 case 0x3:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +020090 DECODE_PRINTF("JNB\t");
91 return !ACCESS_FLAG(F_CF);
92 break;
Jason Jina63ce952007-07-06 08:34:56 +080093 case 0x4:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +020094 DECODE_PRINTF("JZ\t");
95 return ACCESS_FLAG(F_ZF);
96 break;
Jason Jina63ce952007-07-06 08:34:56 +080097 case 0x5:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +020098 DECODE_PRINTF("JNZ\t");
99 return !ACCESS_FLAG(F_ZF);
100 break;
Jason Jina63ce952007-07-06 08:34:56 +0800101 case 0x6:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200102 DECODE_PRINTF("JBE\t");
103 return ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF);
104 break;
Jason Jina63ce952007-07-06 08:34:56 +0800105 case 0x7:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200106 DECODE_PRINTF("JNBE\t");
107 return !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
108 break;
Jason Jina63ce952007-07-06 08:34:56 +0800109 case 0x8:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200110 DECODE_PRINTF("JS\t");
111 return ACCESS_FLAG(F_SF);
112 break;
Jason Jina63ce952007-07-06 08:34:56 +0800113 case 0x9:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200114 DECODE_PRINTF("JNS\t");
115 return !ACCESS_FLAG(F_SF);
116 break;
Jason Jina63ce952007-07-06 08:34:56 +0800117 case 0xa:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200118 DECODE_PRINTF("JP\t");
119 return ACCESS_FLAG(F_PF);
120 break;
Jason Jina63ce952007-07-06 08:34:56 +0800121 case 0xb:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200122 DECODE_PRINTF("JNP\t");
123 return !ACCESS_FLAG(F_PF);
124 break;
Jason Jina63ce952007-07-06 08:34:56 +0800125 case 0xc:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200126 DECODE_PRINTF("JL\t");
127 return xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
128 break;
Jason Jina63ce952007-07-06 08:34:56 +0800129 case 0xd:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200130 DECODE_PRINTF("JNL\t");
131 return !xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
132 break;
Jason Jina63ce952007-07-06 08:34:56 +0800133 case 0xe:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200134 DECODE_PRINTF("JLE\t");
135 return (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
136 ACCESS_FLAG(F_ZF));
137 break;
Jason Jina63ce952007-07-06 08:34:56 +0800138 default:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200139 DECODE_PRINTF("JNLE\t");
140 return !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
141 ACCESS_FLAG(F_ZF));
Jason Jina63ce952007-07-06 08:34:56 +0800142 }
143}
144
145void x86emuOp2_long_jump(u8 op2)
146{
147 s32 target;
148 int cond;
149
150 /* conditional jump to word offset. */
151 START_OF_INSTR();
152 cond = x86emu_check_jump_condition(op2 & 0xF);
153 target = (s16) fetch_word_imm();
154 target += (s16) M.x86.R_IP;
155 DECODE_PRINTF2("%04x\n", target);
156 TRACE_AND_STEP();
157 if (cond)
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200158 M.x86.R_IP = (u16)target;
Jason Jina63ce952007-07-06 08:34:56 +0800159 DECODE_CLEAR_SEGOVR();
160 END_OF_INSTR();
161}
162
163/****************************************************************************
164REMARKS:
165Handles opcode 0x0f,0x90-0x9F
166****************************************************************************/
167void x86emuOp2_set_byte(u8 op2)
168{
169 int mod, rl, rh;
170 uint destoffset;
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200171 u8 *destreg;
Kumar Gala812a1742011-11-23 06:31:04 +0000172 __maybe_unused char *name = 0;
Jason Jina63ce952007-07-06 08:34:56 +0800173 int cond = 0;
174
175 START_OF_INSTR();
176 switch (op2) {
177 case 0x90:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200178 name = "SETO\t";
179 cond = ACCESS_FLAG(F_OF);
180 break;
Jason Jina63ce952007-07-06 08:34:56 +0800181 case 0x91:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200182 name = "SETNO\t";
183 cond = !ACCESS_FLAG(F_OF);
184 break;
Jason Jina63ce952007-07-06 08:34:56 +0800185 case 0x92:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200186 name = "SETB\t";
187 cond = ACCESS_FLAG(F_CF);
188 break;
Jason Jina63ce952007-07-06 08:34:56 +0800189 case 0x93:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200190 name = "SETNB\t";
191 cond = !ACCESS_FLAG(F_CF);
192 break;
Jason Jina63ce952007-07-06 08:34:56 +0800193 case 0x94:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200194 name = "SETZ\t";
195 cond = ACCESS_FLAG(F_ZF);
196 break;
Jason Jina63ce952007-07-06 08:34:56 +0800197 case 0x95:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200198 name = "SETNZ\t";
199 cond = !ACCESS_FLAG(F_ZF);
200 break;
Jason Jina63ce952007-07-06 08:34:56 +0800201 case 0x96:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200202 name = "SETBE\t";
203 cond = ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF);
204 break;
Jason Jina63ce952007-07-06 08:34:56 +0800205 case 0x97:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200206 name = "SETNBE\t";
207 cond = !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
208 break;
Jason Jina63ce952007-07-06 08:34:56 +0800209 case 0x98:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200210 name = "SETS\t";
211 cond = ACCESS_FLAG(F_SF);
212 break;
Jason Jina63ce952007-07-06 08:34:56 +0800213 case 0x99:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200214 name = "SETNS\t";
215 cond = !ACCESS_FLAG(F_SF);
216 break;
Jason Jina63ce952007-07-06 08:34:56 +0800217 case 0x9a:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200218 name = "SETP\t";
219 cond = ACCESS_FLAG(F_PF);
220 break;
Jason Jina63ce952007-07-06 08:34:56 +0800221 case 0x9b:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200222 name = "SETNP\t";
223 cond = !ACCESS_FLAG(F_PF);
224 break;
Jason Jina63ce952007-07-06 08:34:56 +0800225 case 0x9c:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200226 name = "SETL\t";
227 cond = xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
228 break;
Jason Jina63ce952007-07-06 08:34:56 +0800229 case 0x9d:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200230 name = "SETNL\t";
231 cond = !xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
232 break;
Jason Jina63ce952007-07-06 08:34:56 +0800233 case 0x9e:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200234 name = "SETLE\t";
235 cond = (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
236 ACCESS_FLAG(F_ZF));
237 break;
Jason Jina63ce952007-07-06 08:34:56 +0800238 case 0x9f:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200239 name = "SETNLE\t";
240 cond = !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
241 ACCESS_FLAG(F_ZF));
242 break;
Jason Jina63ce952007-07-06 08:34:56 +0800243 }
244 DECODE_PRINTF(name);
245 FETCH_DECODE_MODRM(mod, rh, rl);
246 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200247 destoffset = decode_rmXX_address(mod, rl);
Yuri Zaporozhets1edd1012024-11-27 00:29:53 +0100248 DECODE_PRINTF("\n");
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200249 TRACE_AND_STEP();
250 store_data_byte(destoffset, cond ? 0x01 : 0x00);
251 } else { /* register to register */
252 destreg = DECODE_RM_BYTE_REGISTER(rl);
Yuri Zaporozhets1edd1012024-11-27 00:29:53 +0100253 DECODE_PRINTF("\n");
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200254 TRACE_AND_STEP();
255 *destreg = cond ? 0x01 : 0x00;
Jason Jina63ce952007-07-06 08:34:56 +0800256 }
257 DECODE_CLEAR_SEGOVR();
258 END_OF_INSTR();
259}
260
261/****************************************************************************
262REMARKS:
263Handles opcode 0x0f,0xa0
264****************************************************************************/
265void x86emuOp2_push_FS(u8 X86EMU_UNUSED(op2))
266{
267 START_OF_INSTR();
268 DECODE_PRINTF("PUSH\tFS\n");
269 TRACE_AND_STEP();
270 push_word(M.x86.R_FS);
271 DECODE_CLEAR_SEGOVR();
272 END_OF_INSTR();
273}
274
275/****************************************************************************
276REMARKS:
277Handles opcode 0x0f,0xa1
278****************************************************************************/
279void x86emuOp2_pop_FS(u8 X86EMU_UNUSED(op2))
280{
281 START_OF_INSTR();
282 DECODE_PRINTF("POP\tFS\n");
283 TRACE_AND_STEP();
284 M.x86.R_FS = pop_word();
285 DECODE_CLEAR_SEGOVR();
286 END_OF_INSTR();
287}
288
289/****************************************************************************
290REMARKS:
291Handles opcode 0x0f,0xa3
292****************************************************************************/
293void x86emuOp2_bt_R(u8 X86EMU_UNUSED(op2))
294{
295 int mod, rl, rh;
296 uint srcoffset;
297 int bit,disp;
298
299 START_OF_INSTR();
300 DECODE_PRINTF("BT\t");
301 FETCH_DECODE_MODRM(mod, rh, rl);
302 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200303 srcoffset = decode_rmXX_address(mod, rl);
304 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
305 u32 srcval;
306 u32 *shiftreg;
Jason Jina63ce952007-07-06 08:34:56 +0800307
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200308 DECODE_PRINTF(",");
309 shiftreg = DECODE_RM_LONG_REGISTER(rh);
310 TRACE_AND_STEP();
311 bit = *shiftreg & 0x1F;
312 disp = (s16)*shiftreg >> 5;
313 srcval = fetch_data_long(srcoffset+disp);
314 CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF);
315 } else {
316 u16 srcval;
317 u16 *shiftreg;
Jason Jina63ce952007-07-06 08:34:56 +0800318
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200319 DECODE_PRINTF(",");
320 shiftreg = DECODE_RM_WORD_REGISTER(rh);
321 TRACE_AND_STEP();
322 bit = *shiftreg & 0xF;
323 disp = (s16)*shiftreg >> 4;
324 srcval = fetch_data_word(srcoffset+disp);
325 CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF);
326 }
327 } else { /* register to register */
328 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
329 u32 *srcreg,*shiftreg;
Jason Jina63ce952007-07-06 08:34:56 +0800330
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200331 srcreg = DECODE_RM_LONG_REGISTER(rl);
332 DECODE_PRINTF(",");
333 shiftreg = DECODE_RM_LONG_REGISTER(rh);
334 TRACE_AND_STEP();
335 bit = *shiftreg & 0x1F;
336 CONDITIONAL_SET_FLAG(*srcreg & (0x1 << bit),F_CF);
337 } else {
338 u16 *srcreg,*shiftreg;
Jason Jina63ce952007-07-06 08:34:56 +0800339
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200340 srcreg = DECODE_RM_WORD_REGISTER(rl);
341 DECODE_PRINTF(",");
342 shiftreg = DECODE_RM_WORD_REGISTER(rh);
343 TRACE_AND_STEP();
344 bit = *shiftreg & 0xF;
345 CONDITIONAL_SET_FLAG(*srcreg & (0x1 << bit),F_CF);
346 }
Jason Jina63ce952007-07-06 08:34:56 +0800347 }
348 DECODE_CLEAR_SEGOVR();
349 END_OF_INSTR();
350}
351
352/****************************************************************************
353REMARKS:
354Handles opcode 0x0f,0xa4
355****************************************************************************/
356void x86emuOp2_shld_IMM(u8 X86EMU_UNUSED(op2))
357{
358 int mod, rl, rh;
359 uint destoffset;
360 u8 shift;
361
362 START_OF_INSTR();
363 DECODE_PRINTF("SHLD\t");
364 FETCH_DECODE_MODRM(mod, rh, rl);
365 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200366 destoffset = decode_rmXX_address(mod, rl);
367 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
368 u32 destval;
369 u32 *shiftreg;
Jason Jina63ce952007-07-06 08:34:56 +0800370
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200371 DECODE_PRINTF(",");
372 shiftreg = DECODE_RM_LONG_REGISTER(rh);
373 DECODE_PRINTF(",");
374 shift = fetch_byte_imm();
375 DECODE_PRINTF2("%d\n", shift);
376 TRACE_AND_STEP();
377 destval = fetch_data_long(destoffset);
378 destval = shld_long(destval,*shiftreg,shift);
379 store_data_long(destoffset, destval);
380 } else {
381 u16 destval;
382 u16 *shiftreg;
Jason Jina63ce952007-07-06 08:34:56 +0800383
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200384 DECODE_PRINTF(",");
385 shiftreg = DECODE_RM_WORD_REGISTER(rh);
386 DECODE_PRINTF(",");
387 shift = fetch_byte_imm();
388 DECODE_PRINTF2("%d\n", shift);
389 TRACE_AND_STEP();
390 destval = fetch_data_word(destoffset);
391 destval = shld_word(destval,*shiftreg,shift);
392 store_data_word(destoffset, destval);
393 }
394 } else { /* register to register */
395 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
396 u32 *destreg,*shiftreg;
Jason Jina63ce952007-07-06 08:34:56 +0800397
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200398 destreg = DECODE_RM_LONG_REGISTER(rl);
399 DECODE_PRINTF(",");
400 shiftreg = DECODE_RM_LONG_REGISTER(rh);
401 DECODE_PRINTF(",");
402 shift = fetch_byte_imm();
403 DECODE_PRINTF2("%d\n", shift);
404 TRACE_AND_STEP();
405 *destreg = shld_long(*destreg,*shiftreg,shift);
406 } else {
407 u16 *destreg,*shiftreg;
Jason Jina63ce952007-07-06 08:34:56 +0800408
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200409 destreg = DECODE_RM_WORD_REGISTER(rl);
410 DECODE_PRINTF(",");
411 shiftreg = DECODE_RM_WORD_REGISTER(rh);
412 DECODE_PRINTF(",");
413 shift = fetch_byte_imm();
414 DECODE_PRINTF2("%d\n", shift);
415 TRACE_AND_STEP();
416 *destreg = shld_word(*destreg,*shiftreg,shift);
417 }
Jason Jina63ce952007-07-06 08:34:56 +0800418 }
419 DECODE_CLEAR_SEGOVR();
420 END_OF_INSTR();
421}
422
423/****************************************************************************
424REMARKS:
425Handles opcode 0x0f,0xa5
426****************************************************************************/
427void x86emuOp2_shld_CL(u8 X86EMU_UNUSED(op2))
428{
429 int mod, rl, rh;
430 uint destoffset;
431
432 START_OF_INSTR();
433 DECODE_PRINTF("SHLD\t");
434 FETCH_DECODE_MODRM(mod, rh, rl);
435 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200436 destoffset = decode_rmXX_address(mod, rl);
437 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
438 u32 destval;
439 u32 *shiftreg;
Jason Jina63ce952007-07-06 08:34:56 +0800440
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200441 DECODE_PRINTF(",");
442 shiftreg = DECODE_RM_LONG_REGISTER(rh);
443 DECODE_PRINTF(",CL\n");
444 TRACE_AND_STEP();
445 destval = fetch_data_long(destoffset);
446 destval = shld_long(destval,*shiftreg,M.x86.R_CL);
447 store_data_long(destoffset, destval);
448 } else {
449 u16 destval;
450 u16 *shiftreg;
Jason Jina63ce952007-07-06 08:34:56 +0800451
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200452 DECODE_PRINTF(",");
453 shiftreg = DECODE_RM_WORD_REGISTER(rh);
454 DECODE_PRINTF(",CL\n");
455 TRACE_AND_STEP();
456 destval = fetch_data_word(destoffset);
457 destval = shld_word(destval,*shiftreg,M.x86.R_CL);
458 store_data_word(destoffset, destval);
459 }
460 } else { /* register to register */
461 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
462 u32 *destreg,*shiftreg;
Jason Jina63ce952007-07-06 08:34:56 +0800463
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200464 destreg = DECODE_RM_LONG_REGISTER(rl);
465 DECODE_PRINTF(",");
466 shiftreg = DECODE_RM_LONG_REGISTER(rh);
467 DECODE_PRINTF(",CL\n");
468 TRACE_AND_STEP();
469 *destreg = shld_long(*destreg,*shiftreg,M.x86.R_CL);
470 } else {
471 u16 *destreg,*shiftreg;
Jason Jina63ce952007-07-06 08:34:56 +0800472
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200473 destreg = DECODE_RM_WORD_REGISTER(rl);
474 DECODE_PRINTF(",");
475 shiftreg = DECODE_RM_WORD_REGISTER(rh);
476 DECODE_PRINTF(",CL\n");
477 TRACE_AND_STEP();
478 *destreg = shld_word(*destreg,*shiftreg,M.x86.R_CL);
479 }
Jason Jina63ce952007-07-06 08:34:56 +0800480 }
481 DECODE_CLEAR_SEGOVR();
482 END_OF_INSTR();
483}
484
485/****************************************************************************
486REMARKS:
487Handles opcode 0x0f,0xa8
488****************************************************************************/
489void x86emuOp2_push_GS(u8 X86EMU_UNUSED(op2))
490{
491 START_OF_INSTR();
492 DECODE_PRINTF("PUSH\tGS\n");
493 TRACE_AND_STEP();
494 push_word(M.x86.R_GS);
495 DECODE_CLEAR_SEGOVR();
496 END_OF_INSTR();
497}
498
499/****************************************************************************
500REMARKS:
501Handles opcode 0x0f,0xa9
502****************************************************************************/
503void x86emuOp2_pop_GS(u8 X86EMU_UNUSED(op2))
504{
505 START_OF_INSTR();
506 DECODE_PRINTF("POP\tGS\n");
507 TRACE_AND_STEP();
508 M.x86.R_GS = pop_word();
509 DECODE_CLEAR_SEGOVR();
510 END_OF_INSTR();
511}
512
513/****************************************************************************
514REMARKS:
515Handles opcode 0x0f,0xaa
516****************************************************************************/
517void x86emuOp2_bts_R(u8 X86EMU_UNUSED(op2))
518{
519 int mod, rl, rh;
520 uint srcoffset;
521 int bit,disp;
522
523 START_OF_INSTR();
524 DECODE_PRINTF("BTS\t");
525 FETCH_DECODE_MODRM(mod, rh, rl);
526 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200527 srcoffset = decode_rmXX_address(mod, rl);
528 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
529 u32 srcval,mask;
530 u32 *shiftreg;
Jason Jina63ce952007-07-06 08:34:56 +0800531
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200532 DECODE_PRINTF(",");
533 shiftreg = DECODE_RM_LONG_REGISTER(rh);
534 TRACE_AND_STEP();
535 bit = *shiftreg & 0x1F;
536 disp = (s16)*shiftreg >> 5;
537 srcval = fetch_data_long(srcoffset+disp);
538 mask = (0x1 << bit);
539 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
540 store_data_long(srcoffset+disp, srcval | mask);
541 } else {
542 u16 srcval,mask;
543 u16 *shiftreg;
Jason Jina63ce952007-07-06 08:34:56 +0800544
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200545 DECODE_PRINTF(",");
546 shiftreg = DECODE_RM_WORD_REGISTER(rh);
547 TRACE_AND_STEP();
548 bit = *shiftreg & 0xF;
549 disp = (s16)*shiftreg >> 4;
550 srcval = fetch_data_word(srcoffset+disp);
551 mask = (u16)(0x1 << bit);
552 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
553 store_data_word(srcoffset+disp, srcval | mask);
554 }
555 } else { /* register to register */
556 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
557 u32 *srcreg,*shiftreg;
558 u32 mask;
Jason Jina63ce952007-07-06 08:34:56 +0800559
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200560 srcreg = DECODE_RM_LONG_REGISTER(rl);
561 DECODE_PRINTF(",");
562 shiftreg = DECODE_RM_LONG_REGISTER(rh);
563 TRACE_AND_STEP();
564 bit = *shiftreg & 0x1F;
565 mask = (0x1 << bit);
566 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
567 *srcreg |= mask;
568 } else {
569 u16 *srcreg,*shiftreg;
570 u16 mask;
Jason Jina63ce952007-07-06 08:34:56 +0800571
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200572 srcreg = DECODE_RM_WORD_REGISTER(rl);
573 DECODE_PRINTF(",");
574 shiftreg = DECODE_RM_WORD_REGISTER(rh);
575 TRACE_AND_STEP();
576 bit = *shiftreg & 0xF;
577 mask = (u16)(0x1 << bit);
578 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
579 *srcreg |= mask;
580 }
Jason Jina63ce952007-07-06 08:34:56 +0800581 }
582 DECODE_CLEAR_SEGOVR();
583 END_OF_INSTR();
584}
585
586/****************************************************************************
587REMARKS:
588Handles opcode 0x0f,0xac
589****************************************************************************/
590void x86emuOp2_shrd_IMM(u8 X86EMU_UNUSED(op2))
591{
592 int mod, rl, rh;
593 uint destoffset;
594 u8 shift;
595
596 START_OF_INSTR();
597 DECODE_PRINTF("SHLD\t");
598 FETCH_DECODE_MODRM(mod, rh, rl);
599 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200600 destoffset = decode_rmXX_address(mod, rl);
601 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
602 u32 destval;
603 u32 *shiftreg;
Jason Jina63ce952007-07-06 08:34:56 +0800604
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200605 DECODE_PRINTF(",");
606 shiftreg = DECODE_RM_LONG_REGISTER(rh);
607 DECODE_PRINTF(",");
608 shift = fetch_byte_imm();
609 DECODE_PRINTF2("%d\n", shift);
610 TRACE_AND_STEP();
611 destval = fetch_data_long(destoffset);
612 destval = shrd_long(destval,*shiftreg,shift);
613 store_data_long(destoffset, destval);
614 } else {
615 u16 destval;
616 u16 *shiftreg;
Jason Jina63ce952007-07-06 08:34:56 +0800617
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200618 DECODE_PRINTF(",");
619 shiftreg = DECODE_RM_WORD_REGISTER(rh);
620 DECODE_PRINTF(",");
621 shift = fetch_byte_imm();
622 DECODE_PRINTF2("%d\n", shift);
623 TRACE_AND_STEP();
624 destval = fetch_data_word(destoffset);
625 destval = shrd_word(destval,*shiftreg,shift);
626 store_data_word(destoffset, destval);
627 }
628 } else { /* register to register */
629 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
630 u32 *destreg,*shiftreg;
Jason Jina63ce952007-07-06 08:34:56 +0800631
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200632 destreg = DECODE_RM_LONG_REGISTER(rl);
633 DECODE_PRINTF(",");
634 shiftreg = DECODE_RM_LONG_REGISTER(rh);
635 DECODE_PRINTF(",");
636 shift = fetch_byte_imm();
637 DECODE_PRINTF2("%d\n", shift);
638 TRACE_AND_STEP();
639 *destreg = shrd_long(*destreg,*shiftreg,shift);
640 } else {
641 u16 *destreg,*shiftreg;
Jason Jina63ce952007-07-06 08:34:56 +0800642
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200643 destreg = DECODE_RM_WORD_REGISTER(rl);
644 DECODE_PRINTF(",");
645 shiftreg = DECODE_RM_WORD_REGISTER(rh);
646 DECODE_PRINTF(",");
647 shift = fetch_byte_imm();
648 DECODE_PRINTF2("%d\n", shift);
649 TRACE_AND_STEP();
650 *destreg = shrd_word(*destreg,*shiftreg,shift);
651 }
Jason Jina63ce952007-07-06 08:34:56 +0800652 }
653 DECODE_CLEAR_SEGOVR();
654 END_OF_INSTR();
655}
656
657/****************************************************************************
658REMARKS:
659Handles opcode 0x0f,0xad
660****************************************************************************/
661void x86emuOp2_shrd_CL(u8 X86EMU_UNUSED(op2))
662{
663 int mod, rl, rh;
664 uint destoffset;
665
666 START_OF_INSTR();
667 DECODE_PRINTF("SHLD\t");
668 FETCH_DECODE_MODRM(mod, rh, rl);
669 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200670 destoffset = decode_rmXX_address(mod, rl);
671 DECODE_PRINTF(",");
672 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
673 u32 destval;
674 u32 *shiftreg;
Jason Jina63ce952007-07-06 08:34:56 +0800675
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200676 shiftreg = DECODE_RM_LONG_REGISTER(rh);
677 DECODE_PRINTF(",CL\n");
678 TRACE_AND_STEP();
679 destval = fetch_data_long(destoffset);
680 destval = shrd_long(destval,*shiftreg,M.x86.R_CL);
681 store_data_long(destoffset, destval);
682 } else {
683 u16 destval;
684 u16 *shiftreg;
Jason Jina63ce952007-07-06 08:34:56 +0800685
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200686 shiftreg = DECODE_RM_WORD_REGISTER(rh);
687 DECODE_PRINTF(",CL\n");
688 TRACE_AND_STEP();
689 destval = fetch_data_word(destoffset);
690 destval = shrd_word(destval,*shiftreg,M.x86.R_CL);
691 store_data_word(destoffset, destval);
692 }
693 } else { /* register to register */
694 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
695 u32 *destreg,*shiftreg;
Jason Jina63ce952007-07-06 08:34:56 +0800696
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200697 destreg = DECODE_RM_LONG_REGISTER(rl);
698 DECODE_PRINTF(",");
699 shiftreg = DECODE_RM_LONG_REGISTER(rh);
700 DECODE_PRINTF(",CL\n");
701 TRACE_AND_STEP();
702 *destreg = shrd_long(*destreg,*shiftreg,M.x86.R_CL);
703 } else {
704 u16 *destreg,*shiftreg;
Jason Jina63ce952007-07-06 08:34:56 +0800705
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200706 destreg = DECODE_RM_WORD_REGISTER(rl);
707 DECODE_PRINTF(",");
708 shiftreg = DECODE_RM_WORD_REGISTER(rh);
709 DECODE_PRINTF(",CL\n");
710 TRACE_AND_STEP();
711 *destreg = shrd_word(*destreg,*shiftreg,M.x86.R_CL);
712 }
Jason Jina63ce952007-07-06 08:34:56 +0800713 }
714 DECODE_CLEAR_SEGOVR();
715 END_OF_INSTR();
716}
717
718/****************************************************************************
719REMARKS:
720Handles opcode 0x0f,0xaf
721****************************************************************************/
722void x86emuOp2_imul_R_RM(u8 X86EMU_UNUSED(op2))
723{
724 int mod, rl, rh;
725 uint srcoffset;
726
727 START_OF_INSTR();
728 DECODE_PRINTF("IMUL\t");
729 FETCH_DECODE_MODRM(mod, rh, rl);
730 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200731 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
732 u32 *destreg;
733 u32 srcval;
734 u32 res_lo,res_hi;
Jason Jina63ce952007-07-06 08:34:56 +0800735
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200736 destreg = DECODE_RM_LONG_REGISTER(rh);
737 DECODE_PRINTF(",");
738 srcoffset = decode_rmXX_address(mod, rl);
739 srcval = fetch_data_long(srcoffset);
740 TRACE_AND_STEP();
741 imul_long_direct(&res_lo,&res_hi,(s32)*destreg,(s32)srcval);
742 if (res_hi != 0) {
743 SET_FLAG(F_CF);
744 SET_FLAG(F_OF);
745 } else {
746 CLEAR_FLAG(F_CF);
747 CLEAR_FLAG(F_OF);
748 }
749 *destreg = (u32)res_lo;
750 } else {
751 u16 *destreg;
752 u16 srcval;
753 u32 res;
Jason Jina63ce952007-07-06 08:34:56 +0800754
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200755 destreg = DECODE_RM_WORD_REGISTER(rh);
756 DECODE_PRINTF(",");
757 srcoffset = decode_rmXX_address(mod, rl);
758 srcval = fetch_data_word(srcoffset);
759 TRACE_AND_STEP();
760 res = (s16)*destreg * (s16)srcval;
761 if (res > 0xFFFF) {
762 SET_FLAG(F_CF);
763 SET_FLAG(F_OF);
764 } else {
765 CLEAR_FLAG(F_CF);
766 CLEAR_FLAG(F_OF);
767 }
768 *destreg = (u16)res;
769 }
770 } else { /* register to register */
771 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
772 u32 *destreg,*srcreg;
773 u32 res_lo,res_hi;
Jason Jina63ce952007-07-06 08:34:56 +0800774
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200775 destreg = DECODE_RM_LONG_REGISTER(rh);
776 DECODE_PRINTF(",");
777 srcreg = DECODE_RM_LONG_REGISTER(rl);
778 TRACE_AND_STEP();
779 imul_long_direct(&res_lo,&res_hi,(s32)*destreg,(s32)*srcreg);
780 if (res_hi != 0) {
781 SET_FLAG(F_CF);
782 SET_FLAG(F_OF);
783 } else {
784 CLEAR_FLAG(F_CF);
785 CLEAR_FLAG(F_OF);
786 }
787 *destreg = (u32)res_lo;
788 } else {
789 u16 *destreg,*srcreg;
790 u32 res;
Jason Jina63ce952007-07-06 08:34:56 +0800791
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200792 destreg = DECODE_RM_WORD_REGISTER(rh);
793 DECODE_PRINTF(",");
794 srcreg = DECODE_RM_WORD_REGISTER(rl);
795 res = (s16)*destreg * (s16)*srcreg;
796 if (res > 0xFFFF) {
797 SET_FLAG(F_CF);
798 SET_FLAG(F_OF);
799 } else {
800 CLEAR_FLAG(F_CF);
801 CLEAR_FLAG(F_OF);
802 }
803 *destreg = (u16)res;
804 }
Jason Jina63ce952007-07-06 08:34:56 +0800805 }
806 DECODE_CLEAR_SEGOVR();
807 END_OF_INSTR();
808}
809
810/****************************************************************************
811REMARKS:
812Handles opcode 0x0f,0xb2
813****************************************************************************/
814void x86emuOp2_lss_R_IMM(u8 X86EMU_UNUSED(op2))
815{
816 int mod, rh, rl;
817 u16 *dstreg;
818 uint srcoffset;
819
820 START_OF_INSTR();
821 DECODE_PRINTF("LSS\t");
822 FETCH_DECODE_MODRM(mod, rh, rl);
823 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200824 dstreg = DECODE_RM_WORD_REGISTER(rh);
825 DECODE_PRINTF(",");
826 srcoffset = decode_rmXX_address(mod, rl);
827 DECODE_PRINTF("\n");
828 TRACE_AND_STEP();
829 *dstreg = fetch_data_word(srcoffset);
830 M.x86.R_SS = fetch_data_word(srcoffset + 2);
831 } else { /* register to register */
832 /* UNDEFINED! */
833 TRACE_AND_STEP();
Jason Jina63ce952007-07-06 08:34:56 +0800834 }
835 DECODE_CLEAR_SEGOVR();
836 END_OF_INSTR();
837}
838
839/****************************************************************************
840REMARKS:
841Handles opcode 0x0f,0xb3
842****************************************************************************/
843void x86emuOp2_btr_R(u8 X86EMU_UNUSED(op2))
844{
845 int mod, rl, rh;
846 uint srcoffset;
847 int bit,disp;
848
849 START_OF_INSTR();
850 DECODE_PRINTF("BTR\t");
851 FETCH_DECODE_MODRM(mod, rh, rl);
852 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200853 srcoffset = decode_rmXX_address(mod, rl);
854 DECODE_PRINTF(",");
855 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
856 u32 srcval,mask;
857 u32 *shiftreg;
Jason Jina63ce952007-07-06 08:34:56 +0800858
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200859 shiftreg = DECODE_RM_LONG_REGISTER(rh);
860 TRACE_AND_STEP();
861 bit = *shiftreg & 0x1F;
862 disp = (s16)*shiftreg >> 5;
863 srcval = fetch_data_long(srcoffset+disp);
864 mask = (0x1 << bit);
865 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
866 store_data_long(srcoffset+disp, srcval & ~mask);
867 } else {
868 u16 srcval,mask;
869 u16 *shiftreg;
Jason Jina63ce952007-07-06 08:34:56 +0800870
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200871 shiftreg = DECODE_RM_WORD_REGISTER(rh);
872 TRACE_AND_STEP();
873 bit = *shiftreg & 0xF;
874 disp = (s16)*shiftreg >> 4;
875 srcval = fetch_data_word(srcoffset+disp);
876 mask = (u16)(0x1 << bit);
877 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
878 store_data_word(srcoffset+disp, (u16)(srcval & ~mask));
879 }
880 } else { /* register to register */
881 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
882 u32 *srcreg,*shiftreg;
883 u32 mask;
Jason Jina63ce952007-07-06 08:34:56 +0800884
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200885 srcreg = DECODE_RM_LONG_REGISTER(rl);
886 DECODE_PRINTF(",");
887 shiftreg = DECODE_RM_LONG_REGISTER(rh);
888 TRACE_AND_STEP();
889 bit = *shiftreg & 0x1F;
890 mask = (0x1 << bit);
891 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
892 *srcreg &= ~mask;
893 } else {
894 u16 *srcreg,*shiftreg;
895 u16 mask;
Jason Jina63ce952007-07-06 08:34:56 +0800896
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200897 srcreg = DECODE_RM_WORD_REGISTER(rl);
898 DECODE_PRINTF(",");
899 shiftreg = DECODE_RM_WORD_REGISTER(rh);
900 TRACE_AND_STEP();
901 bit = *shiftreg & 0xF;
902 mask = (u16)(0x1 << bit);
903 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
904 *srcreg &= ~mask;
905 }
Jason Jina63ce952007-07-06 08:34:56 +0800906 }
907 DECODE_CLEAR_SEGOVR();
908 END_OF_INSTR();
909}
910
911/****************************************************************************
912REMARKS:
913Handles opcode 0x0f,0xb4
914****************************************************************************/
915void x86emuOp2_lfs_R_IMM(u8 X86EMU_UNUSED(op2))
916{
917 int mod, rh, rl;
918 u16 *dstreg;
919 uint srcoffset;
920
921 START_OF_INSTR();
922 DECODE_PRINTF("LFS\t");
923 FETCH_DECODE_MODRM(mod, rh, rl);
924 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200925 dstreg = DECODE_RM_WORD_REGISTER(rh);
926 DECODE_PRINTF(",");
927 srcoffset = decode_rmXX_address(mod, rl);
928 DECODE_PRINTF("\n");
929 TRACE_AND_STEP();
930 *dstreg = fetch_data_word(srcoffset);
931 M.x86.R_FS = fetch_data_word(srcoffset + 2);
932 } else { /* register to register */
933 /* UNDEFINED! */
934 TRACE_AND_STEP();
Jason Jina63ce952007-07-06 08:34:56 +0800935 }
936 DECODE_CLEAR_SEGOVR();
937 END_OF_INSTR();
938}
939
940/****************************************************************************
941REMARKS:
942Handles opcode 0x0f,0xb5
943****************************************************************************/
944void x86emuOp2_lgs_R_IMM(u8 X86EMU_UNUSED(op2))
945{
946 int mod, rh, rl;
947 u16 *dstreg;
948 uint srcoffset;
949
950 START_OF_INSTR();
951 DECODE_PRINTF("LGS\t");
952 FETCH_DECODE_MODRM(mod, rh, rl);
953 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200954 dstreg = DECODE_RM_WORD_REGISTER(rh);
955 DECODE_PRINTF(",");
956 srcoffset = decode_rmXX_address(mod, rl);
957 DECODE_PRINTF("\n");
958 TRACE_AND_STEP();
959 *dstreg = fetch_data_word(srcoffset);
960 M.x86.R_GS = fetch_data_word(srcoffset + 2);
961 } else { /* register to register */
962 /* UNDEFINED! */
963 TRACE_AND_STEP();
Jason Jina63ce952007-07-06 08:34:56 +0800964 }
965 DECODE_CLEAR_SEGOVR();
966 END_OF_INSTR();
967}
968
969/****************************************************************************
970REMARKS:
971Handles opcode 0x0f,0xb6
972****************************************************************************/
973void x86emuOp2_movzx_byte_R_RM(u8 X86EMU_UNUSED(op2))
974{
975 int mod, rl, rh;
976 uint srcoffset;
977
978 START_OF_INSTR();
979 DECODE_PRINTF("MOVZX\t");
980 FETCH_DECODE_MODRM(mod, rh, rl);
981 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200982 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
983 u32 *destreg;
984 u32 srcval;
Jason Jina63ce952007-07-06 08:34:56 +0800985
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200986 destreg = DECODE_RM_LONG_REGISTER(rh);
987 DECODE_PRINTF(",");
988 srcoffset = decode_rmXX_address(mod, rl);
989 srcval = fetch_data_byte(srcoffset);
990 DECODE_PRINTF("\n");
991 TRACE_AND_STEP();
992 *destreg = srcval;
993 } else {
994 u16 *destreg;
995 u16 srcval;
Jason Jina63ce952007-07-06 08:34:56 +0800996
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200997 destreg = DECODE_RM_WORD_REGISTER(rh);
998 DECODE_PRINTF(",");
999 srcoffset = decode_rmXX_address(mod, rl);
1000 srcval = fetch_data_byte(srcoffset);
1001 DECODE_PRINTF("\n");
1002 TRACE_AND_STEP();
1003 *destreg = srcval;
1004 }
1005 } else { /* register to register */
1006 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1007 u32 *destreg;
1008 u8 *srcreg;
Jason Jina63ce952007-07-06 08:34:56 +08001009
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001010 destreg = DECODE_RM_LONG_REGISTER(rh);
1011 DECODE_PRINTF(",");
1012 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1013 DECODE_PRINTF("\n");
1014 TRACE_AND_STEP();
1015 *destreg = *srcreg;
1016 } else {
1017 u16 *destreg;
1018 u8 *srcreg;
Jason Jina63ce952007-07-06 08:34:56 +08001019
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001020 destreg = DECODE_RM_WORD_REGISTER(rh);
1021 DECODE_PRINTF(",");
1022 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1023 DECODE_PRINTF("\n");
1024 TRACE_AND_STEP();
1025 *destreg = *srcreg;
1026 }
Jason Jina63ce952007-07-06 08:34:56 +08001027 }
1028 DECODE_CLEAR_SEGOVR();
1029 END_OF_INSTR();
1030}
1031
1032/****************************************************************************
1033REMARKS:
1034Handles opcode 0x0f,0xb7
1035****************************************************************************/
1036void x86emuOp2_movzx_word_R_RM(u8 X86EMU_UNUSED(op2))
1037{
1038 int mod, rl, rh;
1039 uint srcoffset;
1040 u32 *destreg;
1041 u32 srcval;
1042 u16 *srcreg;
1043
1044 START_OF_INSTR();
1045 DECODE_PRINTF("MOVZX\t");
1046 FETCH_DECODE_MODRM(mod, rh, rl);
1047 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001048 destreg = DECODE_RM_LONG_REGISTER(rh);
1049 DECODE_PRINTF(",");
1050 srcoffset = decode_rmXX_address(mod, rl);
1051 srcval = fetch_data_word(srcoffset);
1052 DECODE_PRINTF("\n");
1053 TRACE_AND_STEP();
1054 *destreg = srcval;
1055 } else { /* register to register */
1056 destreg = DECODE_RM_LONG_REGISTER(rh);
1057 DECODE_PRINTF(",");
1058 srcreg = DECODE_RM_WORD_REGISTER(rl);
1059 DECODE_PRINTF("\n");
1060 TRACE_AND_STEP();
1061 *destreg = *srcreg;
Jason Jina63ce952007-07-06 08:34:56 +08001062 }
1063 DECODE_CLEAR_SEGOVR();
1064 END_OF_INSTR();
1065}
1066
1067/****************************************************************************
1068REMARKS:
1069Handles opcode 0x0f,0xba
1070****************************************************************************/
1071void x86emuOp2_btX_I(u8 X86EMU_UNUSED(op2))
1072{
1073 int mod, rl, rh;
1074 uint srcoffset;
1075 u8 shift;
1076 int bit;
1077
1078 START_OF_INSTR();
1079 FETCH_DECODE_MODRM(mod, rh, rl);
1080 switch (rh) {
1081 case 4:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001082 DECODE_PRINTF("BT\t");
1083 break;
Jason Jina63ce952007-07-06 08:34:56 +08001084 case 5:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001085 DECODE_PRINTF("BTS\t");
1086 break;
Jason Jina63ce952007-07-06 08:34:56 +08001087 case 6:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001088 DECODE_PRINTF("BTR\t");
1089 break;
Jason Jina63ce952007-07-06 08:34:56 +08001090 case 7:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001091 DECODE_PRINTF("BTC\t");
1092 break;
Jason Jina63ce952007-07-06 08:34:56 +08001093 default:
Simon Glassb91ea302014-11-14 20:56:43 -07001094 ERR_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n");
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001095 TRACE_REGS();
1096 printk("%04x:%04x: %02X%02X ILLEGAL EXTENDED X86 OPCODE EXTENSION!\n",
1097 M.x86.R_CS, M.x86.R_IP-3,op2, (mod<<6)|(rh<<3)|rl);
1098 HALT_SYS();
Jason Jina63ce952007-07-06 08:34:56 +08001099 }
1100 if (mod < 3) {
1101
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001102 srcoffset = decode_rmXX_address(mod, rl);
1103 shift = fetch_byte_imm();
1104 DECODE_PRINTF2(",%d\n", shift);
1105 TRACE_AND_STEP();
Jason Jina63ce952007-07-06 08:34:56 +08001106
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001107 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1108 u32 srcval, mask;
Jason Jina63ce952007-07-06 08:34:56 +08001109
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001110 bit = shift & 0x1F;
1111 srcval = fetch_data_long(srcoffset);
1112 mask = (0x1 << bit);
1113 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1114 switch (rh) {
1115 case 5:
1116 store_data_long(srcoffset, srcval | mask);
1117 break;
1118 case 6:
1119 store_data_long(srcoffset, srcval & ~mask);
1120 break;
1121 case 7:
1122 store_data_long(srcoffset, srcval ^ mask);
1123 break;
1124 default:
1125 break;
1126 }
1127 } else {
1128 u16 srcval, mask;
Jason Jina63ce952007-07-06 08:34:56 +08001129
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001130 bit = shift & 0xF;
1131 srcval = fetch_data_word(srcoffset);
1132 mask = (0x1 << bit);
1133 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1134 switch (rh) {
1135 case 5:
1136 store_data_word(srcoffset, srcval | mask);
1137 break;
1138 case 6:
1139 store_data_word(srcoffset, srcval & ~mask);
1140 break;
1141 case 7:
1142 store_data_word(srcoffset, srcval ^ mask);
1143 break;
1144 default:
1145 break;
1146 }
1147 }
1148 } else { /* register to register */
1149 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1150 u32 *srcreg;
1151 u32 mask;
Jason Jina63ce952007-07-06 08:34:56 +08001152
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001153 srcreg = DECODE_RM_LONG_REGISTER(rl);
1154 shift = fetch_byte_imm();
1155 DECODE_PRINTF2(",%d\n", shift);
1156 TRACE_AND_STEP();
1157 bit = shift & 0x1F;
1158 mask = (0x1 << bit);
1159 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1160 switch (rh) {
1161 case 5:
1162 *srcreg |= mask;
1163 break;
1164 case 6:
1165 *srcreg &= ~mask;
1166 break;
1167 case 7:
1168 *srcreg ^= mask;
1169 break;
1170 default:
1171 break;
1172 }
1173 } else {
1174 u16 *srcreg;
1175 u16 mask;
Jason Jina63ce952007-07-06 08:34:56 +08001176
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001177 srcreg = DECODE_RM_WORD_REGISTER(rl);
1178 shift = fetch_byte_imm();
1179 DECODE_PRINTF2(",%d\n", shift);
1180 TRACE_AND_STEP();
1181 bit = shift & 0xF;
1182 mask = (0x1 << bit);
1183 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1184 switch (rh) {
1185 case 5:
1186 *srcreg |= mask;
1187 break;
1188 case 6:
1189 *srcreg &= ~mask;
1190 break;
1191 case 7:
1192 *srcreg ^= mask;
1193 break;
1194 default:
1195 break;
1196 }
1197 }
Jason Jina63ce952007-07-06 08:34:56 +08001198 }
1199 DECODE_CLEAR_SEGOVR();
1200 END_OF_INSTR();
1201}
1202
1203/****************************************************************************
1204REMARKS:
1205Handles opcode 0x0f,0xbb
1206****************************************************************************/
1207void x86emuOp2_btc_R(u8 X86EMU_UNUSED(op2))
1208{
1209 int mod, rl, rh;
1210 uint srcoffset;
1211 int bit,disp;
1212
1213 START_OF_INSTR();
1214 DECODE_PRINTF("BTC\t");
1215 FETCH_DECODE_MODRM(mod, rh, rl);
1216 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001217 srcoffset = decode_rmXX_address(mod, rl);
1218 DECODE_PRINTF(",");
1219 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1220 u32 srcval,mask;
1221 u32 *shiftreg;
Jason Jina63ce952007-07-06 08:34:56 +08001222
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001223 shiftreg = DECODE_RM_LONG_REGISTER(rh);
1224 TRACE_AND_STEP();
1225 bit = *shiftreg & 0x1F;
1226 disp = (s16)*shiftreg >> 5;
1227 srcval = fetch_data_long(srcoffset+disp);
1228 mask = (0x1 << bit);
1229 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1230 store_data_long(srcoffset+disp, srcval ^ mask);
1231 } else {
1232 u16 srcval,mask;
1233 u16 *shiftreg;
Jason Jina63ce952007-07-06 08:34:56 +08001234
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001235 shiftreg = DECODE_RM_WORD_REGISTER(rh);
1236 TRACE_AND_STEP();
1237 bit = *shiftreg & 0xF;
1238 disp = (s16)*shiftreg >> 4;
1239 srcval = fetch_data_word(srcoffset+disp);
1240 mask = (u16)(0x1 << bit);
1241 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1242 store_data_word(srcoffset+disp, (u16)(srcval ^ mask));
1243 }
1244 } else { /* register to register */
1245 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1246 u32 *srcreg,*shiftreg;
1247 u32 mask;
Jason Jina63ce952007-07-06 08:34:56 +08001248
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001249 srcreg = DECODE_RM_LONG_REGISTER(rl);
1250 DECODE_PRINTF(",");
1251 shiftreg = DECODE_RM_LONG_REGISTER(rh);
1252 TRACE_AND_STEP();
1253 bit = *shiftreg & 0x1F;
1254 mask = (0x1 << bit);
1255 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1256 *srcreg ^= mask;
1257 } else {
1258 u16 *srcreg,*shiftreg;
1259 u16 mask;
Jason Jina63ce952007-07-06 08:34:56 +08001260
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001261 srcreg = DECODE_RM_WORD_REGISTER(rl);
1262 DECODE_PRINTF(",");
1263 shiftreg = DECODE_RM_WORD_REGISTER(rh);
1264 TRACE_AND_STEP();
1265 bit = *shiftreg & 0xF;
1266 mask = (u16)(0x1 << bit);
1267 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1268 *srcreg ^= mask;
1269 }
Jason Jina63ce952007-07-06 08:34:56 +08001270 }
1271 DECODE_CLEAR_SEGOVR();
1272 END_OF_INSTR();
1273}
1274
1275/****************************************************************************
1276REMARKS:
1277Handles opcode 0x0f,0xbc
1278****************************************************************************/
1279void x86emuOp2_bsf(u8 X86EMU_UNUSED(op2))
1280{
1281 int mod, rl, rh;
1282 uint srcoffset;
1283
1284 START_OF_INSTR();
Yuri Zaporozhetsefeaa582024-11-26 22:59:37 +01001285 DECODE_PRINTF("BSF\t");
Jason Jina63ce952007-07-06 08:34:56 +08001286 FETCH_DECODE_MODRM(mod, rh, rl);
1287 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001288 srcoffset = decode_rmXX_address(mod, rl);
1289 DECODE_PRINTF(",");
1290 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1291 u32 srcval, *dstreg;
Jason Jina63ce952007-07-06 08:34:56 +08001292
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001293 dstreg = DECODE_RM_LONG_REGISTER(rh);
1294 TRACE_AND_STEP();
1295 srcval = fetch_data_long(srcoffset);
1296 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
1297 for(*dstreg = 0; *dstreg < 32; (*dstreg)++)
1298 if ((srcval >> *dstreg) & 1) break;
1299 } else {
1300 u16 srcval, *dstreg;
Jason Jina63ce952007-07-06 08:34:56 +08001301
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001302 dstreg = DECODE_RM_WORD_REGISTER(rh);
1303 TRACE_AND_STEP();
1304 srcval = fetch_data_word(srcoffset);
1305 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
1306 for(*dstreg = 0; *dstreg < 16; (*dstreg)++)
1307 if ((srcval >> *dstreg) & 1) break;
1308 }
1309 } else { /* register to register */
1310 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1311 u32 *srcreg, *dstreg;
Jason Jina63ce952007-07-06 08:34:56 +08001312
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001313 srcreg = DECODE_RM_LONG_REGISTER(rl);
1314 DECODE_PRINTF(",");
1315 dstreg = DECODE_RM_LONG_REGISTER(rh);
1316 TRACE_AND_STEP();
1317 CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF);
1318 for(*dstreg = 0; *dstreg < 32; (*dstreg)++)
1319 if ((*srcreg >> *dstreg) & 1) break;
1320 } else {
1321 u16 *srcreg, *dstreg;
Jason Jina63ce952007-07-06 08:34:56 +08001322
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001323 srcreg = DECODE_RM_WORD_REGISTER(rl);
1324 DECODE_PRINTF(",");
1325 dstreg = DECODE_RM_WORD_REGISTER(rh);
1326 TRACE_AND_STEP();
1327 CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF);
1328 for(*dstreg = 0; *dstreg < 16; (*dstreg)++)
1329 if ((*srcreg >> *dstreg) & 1) break;
1330 }
Jason Jina63ce952007-07-06 08:34:56 +08001331 }
1332 DECODE_CLEAR_SEGOVR();
1333 END_OF_INSTR();
1334}
1335
1336/****************************************************************************
1337REMARKS:
1338Handles opcode 0x0f,0xbd
1339****************************************************************************/
1340void x86emuOp2_bsr(u8 X86EMU_UNUSED(op2))
1341{
1342 int mod, rl, rh;
1343 uint srcoffset;
1344
1345 START_OF_INSTR();
Yuri Zaporozhetsefeaa582024-11-26 22:59:37 +01001346 DECODE_PRINTF("BSF\t");
Jason Jina63ce952007-07-06 08:34:56 +08001347 FETCH_DECODE_MODRM(mod, rh, rl);
1348 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001349 srcoffset = decode_rmXX_address(mod, rl);
1350 DECODE_PRINTF(",");
1351 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1352 u32 srcval, *dstreg;
Jason Jina63ce952007-07-06 08:34:56 +08001353
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001354 dstreg = DECODE_RM_LONG_REGISTER(rh);
1355 TRACE_AND_STEP();
1356 srcval = fetch_data_long(srcoffset);
1357 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
1358 for(*dstreg = 31; *dstreg > 0; (*dstreg)--)
1359 if ((srcval >> *dstreg) & 1) break;
1360 } else {
1361 u16 srcval, *dstreg;
Jason Jina63ce952007-07-06 08:34:56 +08001362
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001363 dstreg = DECODE_RM_WORD_REGISTER(rh);
1364 TRACE_AND_STEP();
1365 srcval = fetch_data_word(srcoffset);
1366 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
1367 for(*dstreg = 15; *dstreg > 0; (*dstreg)--)
1368 if ((srcval >> *dstreg) & 1) break;
1369 }
1370 } else { /* register to register */
1371 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1372 u32 *srcreg, *dstreg;
Jason Jina63ce952007-07-06 08:34:56 +08001373
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001374 srcreg = DECODE_RM_LONG_REGISTER(rl);
1375 DECODE_PRINTF(",");
1376 dstreg = DECODE_RM_LONG_REGISTER(rh);
1377 TRACE_AND_STEP();
1378 CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF);
1379 for(*dstreg = 31; *dstreg > 0; (*dstreg)--)
1380 if ((*srcreg >> *dstreg) & 1) break;
1381 } else {
1382 u16 *srcreg, *dstreg;
Jason Jina63ce952007-07-06 08:34:56 +08001383
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001384 srcreg = DECODE_RM_WORD_REGISTER(rl);
1385 DECODE_PRINTF(",");
1386 dstreg = DECODE_RM_WORD_REGISTER(rh);
1387 TRACE_AND_STEP();
1388 CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF);
1389 for(*dstreg = 15; *dstreg > 0; (*dstreg)--)
1390 if ((*srcreg >> *dstreg) & 1) break;
1391 }
Jason Jina63ce952007-07-06 08:34:56 +08001392 }
1393 DECODE_CLEAR_SEGOVR();
1394 END_OF_INSTR();
1395}
1396
1397/****************************************************************************
1398REMARKS:
1399Handles opcode 0x0f,0xbe
1400****************************************************************************/
1401void x86emuOp2_movsx_byte_R_RM(u8 X86EMU_UNUSED(op2))
1402{
1403 int mod, rl, rh;
1404 uint srcoffset;
1405
1406 START_OF_INSTR();
1407 DECODE_PRINTF("MOVSX\t");
1408 FETCH_DECODE_MODRM(mod, rh, rl);
1409 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001410 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1411 u32 *destreg;
1412 u32 srcval;
Jason Jina63ce952007-07-06 08:34:56 +08001413
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001414 destreg = DECODE_RM_LONG_REGISTER(rh);
1415 DECODE_PRINTF(",");
1416 srcoffset = decode_rmXX_address(mod, rl);
1417 srcval = (s32)((s8)fetch_data_byte(srcoffset));
1418 DECODE_PRINTF("\n");
1419 TRACE_AND_STEP();
1420 *destreg = srcval;
1421 } else {
1422 u16 *destreg;
1423 u16 srcval;
Jason Jina63ce952007-07-06 08:34:56 +08001424
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001425 destreg = DECODE_RM_WORD_REGISTER(rh);
1426 DECODE_PRINTF(",");
1427 srcoffset = decode_rmXX_address(mod, rl);
1428 srcval = (s16)((s8)fetch_data_byte(srcoffset));
1429 DECODE_PRINTF("\n");
1430 TRACE_AND_STEP();
1431 *destreg = srcval;
1432 }
1433 } else { /* register to register */
1434 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1435 u32 *destreg;
1436 u8 *srcreg;
Jason Jina63ce952007-07-06 08:34:56 +08001437
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001438 destreg = DECODE_RM_LONG_REGISTER(rh);
1439 DECODE_PRINTF(",");
1440 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1441 DECODE_PRINTF("\n");
1442 TRACE_AND_STEP();
1443 *destreg = (s32)((s8)*srcreg);
1444 } else {
1445 u16 *destreg;
1446 u8 *srcreg;
Jason Jina63ce952007-07-06 08:34:56 +08001447
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001448 destreg = DECODE_RM_WORD_REGISTER(rh);
1449 DECODE_PRINTF(",");
1450 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1451 DECODE_PRINTF("\n");
1452 TRACE_AND_STEP();
1453 *destreg = (s16)((s8)*srcreg);
1454 }
Jason Jina63ce952007-07-06 08:34:56 +08001455 }
1456 DECODE_CLEAR_SEGOVR();
1457 END_OF_INSTR();
1458}
1459
1460/****************************************************************************
1461REMARKS:
1462Handles opcode 0x0f,0xbf
1463****************************************************************************/
1464void x86emuOp2_movsx_word_R_RM(u8 X86EMU_UNUSED(op2))
1465{
1466 int mod, rl, rh;
1467 uint srcoffset;
1468 u32 *destreg;
1469 u32 srcval;
1470 u16 *srcreg;
1471
1472 START_OF_INSTR();
1473 DECODE_PRINTF("MOVSX\t");
1474 FETCH_DECODE_MODRM(mod, rh, rl);
1475 if (mod < 3) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001476 destreg = DECODE_RM_LONG_REGISTER(rh);
1477 DECODE_PRINTF(",");
1478 srcoffset = decode_rmXX_address(mod, rl);
1479 srcval = (s32)((s16)fetch_data_word(srcoffset));
1480 DECODE_PRINTF("\n");
1481 TRACE_AND_STEP();
1482 *destreg = srcval;
1483 } else { /* register to register */
1484 destreg = DECODE_RM_LONG_REGISTER(rh);
1485 DECODE_PRINTF(",");
1486 srcreg = DECODE_RM_WORD_REGISTER(rl);
1487 DECODE_PRINTF("\n");
1488 TRACE_AND_STEP();
1489 *destreg = (s32)((s16)*srcreg);
Jason Jina63ce952007-07-06 08:34:56 +08001490 }
1491 DECODE_CLEAR_SEGOVR();
1492 END_OF_INSTR();
1493}
1494
1495/***************************************************************************
1496 * Double byte operation code table:
1497 **************************************************************************/
Ed Swarthout1cffcde2008-10-09 01:27:18 -05001498void (*x86emu_optab2[256])(u8) =
Jason Jina63ce952007-07-06 08:34:56 +08001499{
1500/* 0x00 */ x86emuOp2_illegal_op, /* Group F (ring 0 PM) */
1501/* 0x01 */ x86emuOp2_illegal_op, /* Group G (ring 0 PM) */
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001502/* 0x02 */ x86emuOp2_illegal_op, /* lar (ring 0 PM) */
1503/* 0x03 */ x86emuOp2_illegal_op, /* lsl (ring 0 PM) */
Jason Jina63ce952007-07-06 08:34:56 +08001504/* 0x04 */ x86emuOp2_illegal_op,
1505/* 0x05 */ x86emuOp2_illegal_op, /* loadall (undocumented) */
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001506/* 0x06 */ x86emuOp2_illegal_op, /* clts (ring 0 PM) */
Jason Jina63ce952007-07-06 08:34:56 +08001507/* 0x07 */ x86emuOp2_illegal_op, /* loadall (undocumented) */
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001508/* 0x08 */ x86emuOp2_illegal_op, /* invd (ring 0 PM) */
Jason Jina63ce952007-07-06 08:34:56 +08001509/* 0x09 */ x86emuOp2_illegal_op, /* wbinvd (ring 0 PM) */
1510/* 0x0a */ x86emuOp2_illegal_op,
1511/* 0x0b */ x86emuOp2_illegal_op,
1512/* 0x0c */ x86emuOp2_illegal_op,
1513/* 0x0d */ x86emuOp2_illegal_op,
1514/* 0x0e */ x86emuOp2_illegal_op,
1515/* 0x0f */ x86emuOp2_illegal_op,
1516
1517/* 0x10 */ x86emuOp2_illegal_op,
1518/* 0x11 */ x86emuOp2_illegal_op,
1519/* 0x12 */ x86emuOp2_illegal_op,
1520/* 0x13 */ x86emuOp2_illegal_op,
1521/* 0x14 */ x86emuOp2_illegal_op,
1522/* 0x15 */ x86emuOp2_illegal_op,
1523/* 0x16 */ x86emuOp2_illegal_op,
1524/* 0x17 */ x86emuOp2_illegal_op,
1525/* 0x18 */ x86emuOp2_illegal_op,
1526/* 0x19 */ x86emuOp2_illegal_op,
1527/* 0x1a */ x86emuOp2_illegal_op,
1528/* 0x1b */ x86emuOp2_illegal_op,
1529/* 0x1c */ x86emuOp2_illegal_op,
1530/* 0x1d */ x86emuOp2_illegal_op,
1531/* 0x1e */ x86emuOp2_illegal_op,
1532/* 0x1f */ x86emuOp2_illegal_op,
1533
1534/* 0x20 */ x86emuOp2_illegal_op, /* mov reg32,creg (ring 0 PM) */
1535/* 0x21 */ x86emuOp2_illegal_op, /* mov reg32,dreg (ring 0 PM) */
1536/* 0x22 */ x86emuOp2_illegal_op, /* mov creg,reg32 (ring 0 PM) */
1537/* 0x23 */ x86emuOp2_illegal_op, /* mov dreg,reg32 (ring 0 PM) */
1538/* 0x24 */ x86emuOp2_illegal_op, /* mov reg32,treg (ring 0 PM) */
1539/* 0x25 */ x86emuOp2_illegal_op,
1540/* 0x26 */ x86emuOp2_illegal_op, /* mov treg,reg32 (ring 0 PM) */
1541/* 0x27 */ x86emuOp2_illegal_op,
1542/* 0x28 */ x86emuOp2_illegal_op,
1543/* 0x29 */ x86emuOp2_illegal_op,
1544/* 0x2a */ x86emuOp2_illegal_op,
1545/* 0x2b */ x86emuOp2_illegal_op,
1546/* 0x2c */ x86emuOp2_illegal_op,
1547/* 0x2d */ x86emuOp2_illegal_op,
1548/* 0x2e */ x86emuOp2_illegal_op,
1549/* 0x2f */ x86emuOp2_illegal_op,
1550
1551/* 0x30 */ x86emuOp2_illegal_op,
1552/* 0x31 */ x86emuOp2_illegal_op,
1553/* 0x32 */ x86emuOp2_illegal_op,
1554/* 0x33 */ x86emuOp2_illegal_op,
1555/* 0x34 */ x86emuOp2_illegal_op,
1556/* 0x35 */ x86emuOp2_illegal_op,
1557/* 0x36 */ x86emuOp2_illegal_op,
1558/* 0x37 */ x86emuOp2_illegal_op,
1559/* 0x38 */ x86emuOp2_illegal_op,
1560/* 0x39 */ x86emuOp2_illegal_op,
1561/* 0x3a */ x86emuOp2_illegal_op,
1562/* 0x3b */ x86emuOp2_illegal_op,
1563/* 0x3c */ x86emuOp2_illegal_op,
1564/* 0x3d */ x86emuOp2_illegal_op,
1565/* 0x3e */ x86emuOp2_illegal_op,
1566/* 0x3f */ x86emuOp2_illegal_op,
1567
1568/* 0x40 */ x86emuOp2_illegal_op,
1569/* 0x41 */ x86emuOp2_illegal_op,
1570/* 0x42 */ x86emuOp2_illegal_op,
1571/* 0x43 */ x86emuOp2_illegal_op,
1572/* 0x44 */ x86emuOp2_illegal_op,
1573/* 0x45 */ x86emuOp2_illegal_op,
1574/* 0x46 */ x86emuOp2_illegal_op,
1575/* 0x47 */ x86emuOp2_illegal_op,
1576/* 0x48 */ x86emuOp2_illegal_op,
1577/* 0x49 */ x86emuOp2_illegal_op,
1578/* 0x4a */ x86emuOp2_illegal_op,
1579/* 0x4b */ x86emuOp2_illegal_op,
1580/* 0x4c */ x86emuOp2_illegal_op,
1581/* 0x4d */ x86emuOp2_illegal_op,
1582/* 0x4e */ x86emuOp2_illegal_op,
1583/* 0x4f */ x86emuOp2_illegal_op,
1584
1585/* 0x50 */ x86emuOp2_illegal_op,
1586/* 0x51 */ x86emuOp2_illegal_op,
1587/* 0x52 */ x86emuOp2_illegal_op,
1588/* 0x53 */ x86emuOp2_illegal_op,
1589/* 0x54 */ x86emuOp2_illegal_op,
1590/* 0x55 */ x86emuOp2_illegal_op,
1591/* 0x56 */ x86emuOp2_illegal_op,
1592/* 0x57 */ x86emuOp2_illegal_op,
1593/* 0x58 */ x86emuOp2_illegal_op,
1594/* 0x59 */ x86emuOp2_illegal_op,
1595/* 0x5a */ x86emuOp2_illegal_op,
1596/* 0x5b */ x86emuOp2_illegal_op,
1597/* 0x5c */ x86emuOp2_illegal_op,
1598/* 0x5d */ x86emuOp2_illegal_op,
1599/* 0x5e */ x86emuOp2_illegal_op,
1600/* 0x5f */ x86emuOp2_illegal_op,
1601
1602/* 0x60 */ x86emuOp2_illegal_op,
1603/* 0x61 */ x86emuOp2_illegal_op,
1604/* 0x62 */ x86emuOp2_illegal_op,
1605/* 0x63 */ x86emuOp2_illegal_op,
1606/* 0x64 */ x86emuOp2_illegal_op,
1607/* 0x65 */ x86emuOp2_illegal_op,
1608/* 0x66 */ x86emuOp2_illegal_op,
1609/* 0x67 */ x86emuOp2_illegal_op,
1610/* 0x68 */ x86emuOp2_illegal_op,
1611/* 0x69 */ x86emuOp2_illegal_op,
1612/* 0x6a */ x86emuOp2_illegal_op,
1613/* 0x6b */ x86emuOp2_illegal_op,
1614/* 0x6c */ x86emuOp2_illegal_op,
1615/* 0x6d */ x86emuOp2_illegal_op,
1616/* 0x6e */ x86emuOp2_illegal_op,
1617/* 0x6f */ x86emuOp2_illegal_op,
1618
1619/* 0x70 */ x86emuOp2_illegal_op,
1620/* 0x71 */ x86emuOp2_illegal_op,
1621/* 0x72 */ x86emuOp2_illegal_op,
1622/* 0x73 */ x86emuOp2_illegal_op,
1623/* 0x74 */ x86emuOp2_illegal_op,
1624/* 0x75 */ x86emuOp2_illegal_op,
1625/* 0x76 */ x86emuOp2_illegal_op,
1626/* 0x77 */ x86emuOp2_illegal_op,
1627/* 0x78 */ x86emuOp2_illegal_op,
1628/* 0x79 */ x86emuOp2_illegal_op,
1629/* 0x7a */ x86emuOp2_illegal_op,
1630/* 0x7b */ x86emuOp2_illegal_op,
1631/* 0x7c */ x86emuOp2_illegal_op,
1632/* 0x7d */ x86emuOp2_illegal_op,
1633/* 0x7e */ x86emuOp2_illegal_op,
1634/* 0x7f */ x86emuOp2_illegal_op,
1635
1636/* 0x80 */ x86emuOp2_long_jump,
1637/* 0x81 */ x86emuOp2_long_jump,
1638/* 0x82 */ x86emuOp2_long_jump,
1639/* 0x83 */ x86emuOp2_long_jump,
1640/* 0x84 */ x86emuOp2_long_jump,
1641/* 0x85 */ x86emuOp2_long_jump,
1642/* 0x86 */ x86emuOp2_long_jump,
1643/* 0x87 */ x86emuOp2_long_jump,
1644/* 0x88 */ x86emuOp2_long_jump,
1645/* 0x89 */ x86emuOp2_long_jump,
1646/* 0x8a */ x86emuOp2_long_jump,
1647/* 0x8b */ x86emuOp2_long_jump,
1648/* 0x8c */ x86emuOp2_long_jump,
1649/* 0x8d */ x86emuOp2_long_jump,
1650/* 0x8e */ x86emuOp2_long_jump,
1651/* 0x8f */ x86emuOp2_long_jump,
1652
1653/* 0x90 */ x86emuOp2_set_byte,
1654/* 0x91 */ x86emuOp2_set_byte,
1655/* 0x92 */ x86emuOp2_set_byte,
1656/* 0x93 */ x86emuOp2_set_byte,
1657/* 0x94 */ x86emuOp2_set_byte,
1658/* 0x95 */ x86emuOp2_set_byte,
1659/* 0x96 */ x86emuOp2_set_byte,
1660/* 0x97 */ x86emuOp2_set_byte,
1661/* 0x98 */ x86emuOp2_set_byte,
1662/* 0x99 */ x86emuOp2_set_byte,
1663/* 0x9a */ x86emuOp2_set_byte,
1664/* 0x9b */ x86emuOp2_set_byte,
1665/* 0x9c */ x86emuOp2_set_byte,
1666/* 0x9d */ x86emuOp2_set_byte,
1667/* 0x9e */ x86emuOp2_set_byte,
1668/* 0x9f */ x86emuOp2_set_byte,
1669
1670/* 0xa0 */ x86emuOp2_push_FS,
1671/* 0xa1 */ x86emuOp2_pop_FS,
1672/* 0xa2 */ x86emuOp2_illegal_op,
1673/* 0xa3 */ x86emuOp2_bt_R,
1674/* 0xa4 */ x86emuOp2_shld_IMM,
1675/* 0xa5 */ x86emuOp2_shld_CL,
1676/* 0xa6 */ x86emuOp2_illegal_op,
1677/* 0xa7 */ x86emuOp2_illegal_op,
1678/* 0xa8 */ x86emuOp2_push_GS,
1679/* 0xa9 */ x86emuOp2_pop_GS,
1680/* 0xaa */ x86emuOp2_illegal_op,
1681/* 0xab */ x86emuOp2_bt_R,
1682/* 0xac */ x86emuOp2_shrd_IMM,
1683/* 0xad */ x86emuOp2_shrd_CL,
1684/* 0xae */ x86emuOp2_illegal_op,
1685/* 0xaf */ x86emuOp2_imul_R_RM,
1686
1687/* 0xb0 */ x86emuOp2_illegal_op, /* TODO: cmpxchg */
1688/* 0xb1 */ x86emuOp2_illegal_op, /* TODO: cmpxchg */
1689/* 0xb2 */ x86emuOp2_lss_R_IMM,
1690/* 0xb3 */ x86emuOp2_btr_R,
1691/* 0xb4 */ x86emuOp2_lfs_R_IMM,
1692/* 0xb5 */ x86emuOp2_lgs_R_IMM,
1693/* 0xb6 */ x86emuOp2_movzx_byte_R_RM,
1694/* 0xb7 */ x86emuOp2_movzx_word_R_RM,
1695/* 0xb8 */ x86emuOp2_illegal_op,
1696/* 0xb9 */ x86emuOp2_illegal_op,
1697/* 0xba */ x86emuOp2_btX_I,
1698/* 0xbb */ x86emuOp2_btc_R,
1699/* 0xbc */ x86emuOp2_bsf,
1700/* 0xbd */ x86emuOp2_bsr,
1701/* 0xbe */ x86emuOp2_movsx_byte_R_RM,
1702/* 0xbf */ x86emuOp2_movsx_word_R_RM,
1703
1704/* 0xc0 */ x86emuOp2_illegal_op, /* TODO: xadd */
1705/* 0xc1 */ x86emuOp2_illegal_op, /* TODO: xadd */
1706/* 0xc2 */ x86emuOp2_illegal_op,
1707/* 0xc3 */ x86emuOp2_illegal_op,
1708/* 0xc4 */ x86emuOp2_illegal_op,
1709/* 0xc5 */ x86emuOp2_illegal_op,
1710/* 0xc6 */ x86emuOp2_illegal_op,
1711/* 0xc7 */ x86emuOp2_illegal_op,
1712/* 0xc8 */ x86emuOp2_illegal_op, /* TODO: bswap */
1713/* 0xc9 */ x86emuOp2_illegal_op, /* TODO: bswap */
1714/* 0xca */ x86emuOp2_illegal_op, /* TODO: bswap */
1715/* 0xcb */ x86emuOp2_illegal_op, /* TODO: bswap */
1716/* 0xcc */ x86emuOp2_illegal_op, /* TODO: bswap */
1717/* 0xcd */ x86emuOp2_illegal_op, /* TODO: bswap */
1718/* 0xce */ x86emuOp2_illegal_op, /* TODO: bswap */
1719/* 0xcf */ x86emuOp2_illegal_op, /* TODO: bswap */
1720
1721/* 0xd0 */ x86emuOp2_illegal_op,
1722/* 0xd1 */ x86emuOp2_illegal_op,
1723/* 0xd2 */ x86emuOp2_illegal_op,
1724/* 0xd3 */ x86emuOp2_illegal_op,
1725/* 0xd4 */ x86emuOp2_illegal_op,
1726/* 0xd5 */ x86emuOp2_illegal_op,
1727/* 0xd6 */ x86emuOp2_illegal_op,
1728/* 0xd7 */ x86emuOp2_illegal_op,
1729/* 0xd8 */ x86emuOp2_illegal_op,
1730/* 0xd9 */ x86emuOp2_illegal_op,
1731/* 0xda */ x86emuOp2_illegal_op,
1732/* 0xdb */ x86emuOp2_illegal_op,
1733/* 0xdc */ x86emuOp2_illegal_op,
1734/* 0xdd */ x86emuOp2_illegal_op,
1735/* 0xde */ x86emuOp2_illegal_op,
1736/* 0xdf */ x86emuOp2_illegal_op,
1737
1738/* 0xe0 */ x86emuOp2_illegal_op,
1739/* 0xe1 */ x86emuOp2_illegal_op,
1740/* 0xe2 */ x86emuOp2_illegal_op,
1741/* 0xe3 */ x86emuOp2_illegal_op,
1742/* 0xe4 */ x86emuOp2_illegal_op,
1743/* 0xe5 */ x86emuOp2_illegal_op,
1744/* 0xe6 */ x86emuOp2_illegal_op,
1745/* 0xe7 */ x86emuOp2_illegal_op,
1746/* 0xe8 */ x86emuOp2_illegal_op,
1747/* 0xe9 */ x86emuOp2_illegal_op,
1748/* 0xea */ x86emuOp2_illegal_op,
1749/* 0xeb */ x86emuOp2_illegal_op,
1750/* 0xec */ x86emuOp2_illegal_op,
1751/* 0xed */ x86emuOp2_illegal_op,
1752/* 0xee */ x86emuOp2_illegal_op,
1753/* 0xef */ x86emuOp2_illegal_op,
1754
1755/* 0xf0 */ x86emuOp2_illegal_op,
1756/* 0xf1 */ x86emuOp2_illegal_op,
1757/* 0xf2 */ x86emuOp2_illegal_op,
1758/* 0xf3 */ x86emuOp2_illegal_op,
1759/* 0xf4 */ x86emuOp2_illegal_op,
1760/* 0xf5 */ x86emuOp2_illegal_op,
1761/* 0xf6 */ x86emuOp2_illegal_op,
1762/* 0xf7 */ x86emuOp2_illegal_op,
1763/* 0xf8 */ x86emuOp2_illegal_op,
1764/* 0xf9 */ x86emuOp2_illegal_op,
1765/* 0xfa */ x86emuOp2_illegal_op,
1766/* 0xfb */ x86emuOp2_illegal_op,
1767/* 0xfc */ x86emuOp2_illegal_op,
1768/* 0xfd */ x86emuOp2_illegal_op,
1769/* 0xfe */ x86emuOp2_illegal_op,
1770/* 0xff */ x86emuOp2_illegal_op,
1771};