]> git.ipfire.org Git - people/ms/u-boot.git/blame - board/MAI/bios_emulator/scitech/src/x86emu/ops2.c
* Code cleanup:
[people/ms/u-boot.git] / board / MAI / bios_emulator / scitech / src / x86emu / ops2.c
CommitLineData
c7de829c
WD
1/****************************************************************************
2*
3* Realmode X86 Emulator Library
4*
5* Copyright (C) 1996-1999 SciTech Software, Inc.
6* Copyright (C) David Mosberger-Tang
7* Copyright (C) 1999 Egbert Eich
8*
9* ========================================================================
10*
11* Permission to use, copy, modify, distribute, and sell this software and
12* its documentation for any purpose is hereby granted without fee,
13* provided that the above copyright notice appear in all copies and that
14* both that copyright notice and this permission notice appear in
15* supporting documentation, and that the name of the authors not be used
16* in advertising or publicity pertaining to distribution of the software
17* without specific, written prior permission. The authors makes no
18* representations about the suitability of this software for any purpose.
19* It is provided "as is" without express or implied warranty.
20*
21* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
22* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
23* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
24* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
25* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
26* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
27* PERFORMANCE OF THIS SOFTWARE.
28*
29* ========================================================================
30*
31* Language: ANSI C
32* Environment: Any
33* Developer: Kendall Bennett
34*
35* Description: This file includes subroutines to implement the decoding
36* and emulation of all the x86 extended two-byte processor
37* instructions.
38*
39****************************************************************************/
40
41#include "x86emu/x86emui.h"
42
43/*----------------------------- Implementation ----------------------------*/
44
45/****************************************************************************
46PARAMETERS:
47op1 - Instruction op code
48
49REMARKS:
50Handles illegal opcodes.
51****************************************************************************/
52void x86emuOp2_illegal_op(
53 u8 op2)
54{
55 START_OF_INSTR();
56 DECODE_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n");
57 TRACE_REGS();
58 printk("%04x:%04x: %02X ILLEGAL EXTENDED X86 OPCODE!\n",
59 M.x86.R_CS, M.x86.R_IP-2,op2);
60 HALT_SYS();
61 END_OF_INSTR();
62}
63
64#define xorl(a,b) ((a) && !(b)) || (!(a) && (b))
65
66/****************************************************************************
67REMARKS:
68Handles opcode 0x0f,0x80-0x8F
69****************************************************************************/
70void x86emuOp2_long_jump(u8 op2)
71{
72 s32 target;
73 char *name = 0;
74 int cond = 0;
75
76 /* conditional jump to word offset. */
77 START_OF_INSTR();
78 switch (op2) {
79 case 0x80:
8bde7f77
WD
80 name = "JO\t";
81 cond = ACCESS_FLAG(F_OF);
82 break;
c7de829c 83 case 0x81:
8bde7f77
WD
84 name = "JNO\t";
85 cond = !ACCESS_FLAG(F_OF);
86 break;
c7de829c 87 case 0x82:
8bde7f77
WD
88 name = "JB\t";
89 cond = ACCESS_FLAG(F_CF);
90 break;
c7de829c 91 case 0x83:
8bde7f77
WD
92 name = "JNB\t";
93 cond = !ACCESS_FLAG(F_CF);
94 break;
c7de829c 95 case 0x84:
8bde7f77
WD
96 name = "JZ\t";
97 cond = ACCESS_FLAG(F_ZF);
98 break;
c7de829c 99 case 0x85:
8bde7f77
WD
100 name = "JNZ\t";
101 cond = !ACCESS_FLAG(F_ZF);
102 break;
c7de829c 103 case 0x86:
8bde7f77
WD
104 name = "JBE\t";
105 cond = ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF);
106 break;
c7de829c 107 case 0x87:
8bde7f77
WD
108 name = "JNBE\t";
109 cond = !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
110 break;
c7de829c 111 case 0x88:
8bde7f77
WD
112 name = "JS\t";
113 cond = ACCESS_FLAG(F_SF);
114 break;
c7de829c 115 case 0x89:
8bde7f77
WD
116 name = "JNS\t";
117 cond = !ACCESS_FLAG(F_SF);
118 break;
c7de829c 119 case 0x8a:
8bde7f77
WD
120 name = "JP\t";
121 cond = ACCESS_FLAG(F_PF);
122 break;
c7de829c 123 case 0x8b:
8bde7f77
WD
124 name = "JNP\t";
125 cond = !ACCESS_FLAG(F_PF);
126 break;
c7de829c 127 case 0x8c:
8bde7f77
WD
128 name = "JL\t";
129 cond = xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
130 break;
c7de829c 131 case 0x8d:
8bde7f77
WD
132 name = "JNL\t";
133 cond = xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
134 break;
c7de829c 135 case 0x8e:
8bde7f77
WD
136 name = "JLE\t";
137 cond = (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
138 ACCESS_FLAG(F_ZF));
139 break;
c7de829c 140 case 0x8f:
8bde7f77
WD
141 name = "JNLE\t";
142 cond = !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
143 ACCESS_FLAG(F_ZF));
144 break;
c7de829c
WD
145 }
146 DECODE_PRINTF(name);
147 target = (s16) fetch_word_imm();
148 target += (s16) M.x86.R_IP;
149 DECODE_PRINTF2("%04x\n", target);
150 TRACE_AND_STEP();
151 if (cond)
8bde7f77 152 M.x86.R_IP = (u16)target;
c7de829c
WD
153 DECODE_CLEAR_SEGOVR();
154 END_OF_INSTR();
155}
156
157/****************************************************************************
158REMARKS:
159Handles opcode 0x0f,0x90-0x9F
160****************************************************************************/
161void x86emuOp2_set_byte(u8 op2)
162{
163 int mod, rl, rh;
164 uint destoffset;
165 u8 *destreg;
166 char *name = 0;
167 int cond = 0;
168
169 START_OF_INSTR();
170 switch (op2) {
171 case 0x90:
8bde7f77
WD
172 name = "SETO\t";
173 cond = ACCESS_FLAG(F_OF);
174 break;
c7de829c 175 case 0x91:
8bde7f77
WD
176 name = "SETNO\t";
177 cond = !ACCESS_FLAG(F_OF);
178 break;
c7de829c 179 case 0x92:
8bde7f77
WD
180 name = "SETB\t";
181 cond = ACCESS_FLAG(F_CF);
182 break;
c7de829c 183 case 0x93:
8bde7f77
WD
184 name = "SETNB\t";
185 cond = !ACCESS_FLAG(F_CF);
186 break;
c7de829c 187 case 0x94:
8bde7f77
WD
188 name = "SETZ\t";
189 cond = ACCESS_FLAG(F_ZF);
190 break;
c7de829c 191 case 0x95:
8bde7f77
WD
192 name = "SETNZ\t";
193 cond = !ACCESS_FLAG(F_ZF);
194 break;
c7de829c 195 case 0x96:
8bde7f77
WD
196 name = "SETBE\t";
197 cond = ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF);
198 break;
c7de829c 199 case 0x97:
8bde7f77
WD
200 name = "SETNBE\t";
201 cond = !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
202 break;
c7de829c 203 case 0x98:
8bde7f77
WD
204 name = "SETS\t";
205 cond = ACCESS_FLAG(F_SF);
206 break;
c7de829c 207 case 0x99:
8bde7f77
WD
208 name = "SETNS\t";
209 cond = !ACCESS_FLAG(F_SF);
210 break;
c7de829c 211 case 0x9a:
8bde7f77
WD
212 name = "SETP\t";
213 cond = ACCESS_FLAG(F_PF);
214 break;
c7de829c 215 case 0x9b:
8bde7f77
WD
216 name = "SETNP\t";
217 cond = !ACCESS_FLAG(F_PF);
218 break;
c7de829c 219 case 0x9c:
8bde7f77
WD
220 name = "SETL\t";
221 cond = xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
222 break;
c7de829c 223 case 0x9d:
8bde7f77
WD
224 name = "SETNL\t";
225 cond = xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
226 break;
c7de829c 227 case 0x9e:
8bde7f77
WD
228 name = "SETLE\t";
229 cond = (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
230 ACCESS_FLAG(F_ZF));
231 break;
c7de829c 232 case 0x9f:
8bde7f77
WD
233 name = "SETNLE\t";
234 cond = !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
235 ACCESS_FLAG(F_ZF));
236 break;
c7de829c
WD
237 }
238 DECODE_PRINTF(name);
239 FETCH_DECODE_MODRM(mod, rh, rl);
240 switch (mod) {
241 case 0:
8bde7f77
WD
242 destoffset = decode_rm00_address(rl);
243 TRACE_AND_STEP();
244 store_data_byte(destoffset, cond ? 0x01 : 0x00);
245 break;
c7de829c 246 case 1:
8bde7f77
WD
247 destoffset = decode_rm01_address(rl);
248 TRACE_AND_STEP();
249 store_data_byte(destoffset, cond ? 0x01 : 0x00);
250 break;
c7de829c 251 case 2:
8bde7f77
WD
252 destoffset = decode_rm10_address(rl);
253 TRACE_AND_STEP();
254 store_data_byte(destoffset, cond ? 0x01 : 0x00);
255 break;
c7de829c 256 case 3: /* register to register */
8bde7f77
WD
257 destreg = DECODE_RM_BYTE_REGISTER(rl);
258 TRACE_AND_STEP();
259 *destreg = cond ? 0x01 : 0x00;
260 break;
c7de829c
WD
261 }
262 DECODE_CLEAR_SEGOVR();
263 END_OF_INSTR();
264}
265
266/****************************************************************************
267REMARKS:
268Handles opcode 0x0f,0xa0
269****************************************************************************/
270void x86emuOp2_push_FS(u8 X86EMU_UNUSED(op2))
271{
272 START_OF_INSTR();
273 DECODE_PRINTF("PUSH\tFS\n");
274 TRACE_AND_STEP();
275 push_word(M.x86.R_FS);
276 DECODE_CLEAR_SEGOVR();
277 END_OF_INSTR();
278}
279
280/****************************************************************************
281REMARKS:
282Handles opcode 0x0f,0xa1
283****************************************************************************/
284void x86emuOp2_pop_FS(u8 X86EMU_UNUSED(op2))
285{
286 START_OF_INSTR();
287 DECODE_PRINTF("POP\tFS\n");
288 TRACE_AND_STEP();
289 M.x86.R_FS = pop_word();
290 DECODE_CLEAR_SEGOVR();
291 END_OF_INSTR();
292}
293
294/****************************************************************************
295REMARKS:
296Handles opcode 0x0f,0xa3
297****************************************************************************/
298void x86emuOp2_bt_R(u8 X86EMU_UNUSED(op2))
299{
300 int mod, rl, rh;
301 uint srcoffset;
302 int bit,disp;
303
304 START_OF_INSTR();
305 DECODE_PRINTF("BT\t");
306 FETCH_DECODE_MODRM(mod, rh, rl);
307 switch (mod) {
308 case 0:
8bde7f77
WD
309 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
310 u32 srcval;
311 u32 *shiftreg;
312
313 srcoffset = decode_rm00_address(rl);
314 DECODE_PRINTF(",");
315 shiftreg = DECODE_RM_LONG_REGISTER(rh);
316 TRACE_AND_STEP();
317 bit = *shiftreg & 0x1F;
318 disp = (s16)*shiftreg >> 5;
319 srcval = fetch_data_long(srcoffset+disp);
320 CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF);
321 } else {
322 u16 srcval;
323 u16 *shiftreg;
324
325 srcoffset = decode_rm00_address(rl);
326 DECODE_PRINTF(",");
327 shiftreg = DECODE_RM_WORD_REGISTER(rh);
328 TRACE_AND_STEP();
329 bit = *shiftreg & 0xF;
330 disp = (s16)*shiftreg >> 4;
331 srcval = fetch_data_word(srcoffset+disp);
332 CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF);
333 }
334 break;
c7de829c 335 case 1:
8bde7f77
WD
336 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
337 u32 srcval;
338 u32 *shiftreg;
339
340 srcoffset = decode_rm01_address(rl);
341 DECODE_PRINTF(",");
342 shiftreg = DECODE_RM_LONG_REGISTER(rh);
343 TRACE_AND_STEP();
344 bit = *shiftreg & 0x1F;
345 disp = (s16)*shiftreg >> 5;
346 srcval = fetch_data_long(srcoffset+disp);
347 CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF);
348 } else {
349 u16 srcval;
350 u16 *shiftreg;
351
352 srcoffset = decode_rm01_address(rl);
353 DECODE_PRINTF(",");
354 shiftreg = DECODE_RM_WORD_REGISTER(rh);
355 TRACE_AND_STEP();
356 bit = *shiftreg & 0xF;
357 disp = (s16)*shiftreg >> 4;
358 srcval = fetch_data_word(srcoffset+disp);
359 CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF);
360 }
361 break;
c7de829c 362 case 2:
8bde7f77
WD
363 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
364 u32 srcval;
365 u32 *shiftreg;
366
367 srcoffset = decode_rm10_address(rl);
368 DECODE_PRINTF(",");
369 shiftreg = DECODE_RM_LONG_REGISTER(rh);
370 TRACE_AND_STEP();
371 bit = *shiftreg & 0x1F;
372 disp = (s16)*shiftreg >> 5;
373 srcval = fetch_data_long(srcoffset+disp);
374 CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF);
375 } else {
376 u16 srcval;
377 u16 *shiftreg;
378
379 srcoffset = decode_rm10_address(rl);
380 DECODE_PRINTF(",");
381 shiftreg = DECODE_RM_WORD_REGISTER(rh);
382 TRACE_AND_STEP();
383 bit = *shiftreg & 0xF;
384 disp = (s16)*shiftreg >> 4;
385 srcval = fetch_data_word(srcoffset+disp);
386 CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF);
387 }
388 break;
c7de829c 389 case 3: /* register to register */
8bde7f77
WD
390 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
391 u32 *srcreg,*shiftreg;
392
393 srcreg = DECODE_RM_LONG_REGISTER(rl);
394 DECODE_PRINTF(",");
395 shiftreg = DECODE_RM_LONG_REGISTER(rh);
396 TRACE_AND_STEP();
397 bit = *shiftreg & 0x1F;
398 CONDITIONAL_SET_FLAG(*srcreg & (0x1 << bit),F_CF);
399 } else {
400 u16 *srcreg,*shiftreg;
401
402 srcreg = DECODE_RM_WORD_REGISTER(rl);
403 DECODE_PRINTF(",");
404 shiftreg = DECODE_RM_WORD_REGISTER(rh);
405 TRACE_AND_STEP();
406 bit = *shiftreg & 0xF;
407 CONDITIONAL_SET_FLAG(*srcreg & (0x1 << bit),F_CF);
408 }
409 break;
c7de829c
WD
410 }
411 DECODE_CLEAR_SEGOVR();
412 END_OF_INSTR();
413}
414
415/****************************************************************************
416REMARKS:
417Handles opcode 0x0f,0xa4
418****************************************************************************/
419void x86emuOp2_shld_IMM(u8 X86EMU_UNUSED(op2))
420{
421 int mod, rl, rh;
422 uint destoffset;
423 u8 shift;
424
425 START_OF_INSTR();
426 DECODE_PRINTF("SHLD\t");
427 FETCH_DECODE_MODRM(mod, rh, rl);
428 switch (mod) {
429 case 0:
8bde7f77
WD
430 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
431 u32 destval;
432 u32 *shiftreg;
433
434 destoffset = decode_rm00_address(rl);
435 DECODE_PRINTF(",");
436 shiftreg = DECODE_RM_LONG_REGISTER(rh);
437 DECODE_PRINTF(",");
438 shift = fetch_byte_imm();
439 DECODE_PRINTF2("%d\n", shift);
440 TRACE_AND_STEP();
441 destval = fetch_data_long(destoffset);
442 destval = shld_long(destval,*shiftreg,shift);
443 store_data_long(destoffset, destval);
444 } else {
445 u16 destval;
446 u16 *shiftreg;
447
448 destoffset = decode_rm00_address(rl);
449 DECODE_PRINTF(",");
450 shiftreg = DECODE_RM_WORD_REGISTER(rh);
451 DECODE_PRINTF(",");
452 shift = fetch_byte_imm();
453 DECODE_PRINTF2("%d\n", shift);
454 TRACE_AND_STEP();
455 destval = fetch_data_word(destoffset);
456 destval = shld_word(destval,*shiftreg,shift);
457 store_data_word(destoffset, destval);
458 }
459 break;
c7de829c 460 case 1:
8bde7f77
WD
461 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
462 u32 destval;
463 u32 *shiftreg;
464
465 destoffset = decode_rm01_address(rl);
466 DECODE_PRINTF(",");
467 shiftreg = DECODE_RM_LONG_REGISTER(rh);
468 DECODE_PRINTF(",");
469 shift = fetch_byte_imm();
470 DECODE_PRINTF2("%d\n", shift);
471 TRACE_AND_STEP();
472 destval = fetch_data_long(destoffset);
473 destval = shld_long(destval,*shiftreg,shift);
474 store_data_long(destoffset, destval);
475 } else {
476 u16 destval;
477 u16 *shiftreg;
478
479 destoffset = decode_rm01_address(rl);
480 DECODE_PRINTF(",");
481 shiftreg = DECODE_RM_WORD_REGISTER(rh);
482 DECODE_PRINTF(",");
483 shift = fetch_byte_imm();
484 DECODE_PRINTF2("%d\n", shift);
485 TRACE_AND_STEP();
486 destval = fetch_data_word(destoffset);
487 destval = shld_word(destval,*shiftreg,shift);
488 store_data_word(destoffset, destval);
489 }
490 break;
c7de829c 491 case 2:
8bde7f77
WD
492 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
493 u32 destval;
494 u32 *shiftreg;
495
496 destoffset = decode_rm10_address(rl);
497 DECODE_PRINTF(",");
498 shiftreg = DECODE_RM_LONG_REGISTER(rh);
499 DECODE_PRINTF(",");
500 shift = fetch_byte_imm();
501 DECODE_PRINTF2("%d\n", shift);
502 TRACE_AND_STEP();
503 destval = fetch_data_long(destoffset);
504 destval = shld_long(destval,*shiftreg,shift);
505 store_data_long(destoffset, destval);
506 } else {
507 u16 destval;
508 u16 *shiftreg;
509
510 destoffset = decode_rm10_address(rl);
511 DECODE_PRINTF(",");
512 shiftreg = DECODE_RM_WORD_REGISTER(rh);
513 DECODE_PRINTF(",");
514 shift = fetch_byte_imm();
515 DECODE_PRINTF2("%d\n", shift);
516 TRACE_AND_STEP();
517 destval = fetch_data_word(destoffset);
518 destval = shld_word(destval,*shiftreg,shift);
519 store_data_word(destoffset, destval);
520 }
521 break;
c7de829c 522 case 3: /* register to register */
8bde7f77
WD
523 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
524 u32 *destreg,*shiftreg;
525
526 destreg = DECODE_RM_LONG_REGISTER(rl);
527 DECODE_PRINTF(",");
528 shiftreg = DECODE_RM_LONG_REGISTER(rh);
529 DECODE_PRINTF(",");
530 shift = fetch_byte_imm();
531 DECODE_PRINTF2("%d\n", shift);
532 TRACE_AND_STEP();
533 *destreg = shld_long(*destreg,*shiftreg,shift);
534 } else {
535 u16 *destreg,*shiftreg;
536
537 destreg = DECODE_RM_WORD_REGISTER(rl);
538 DECODE_PRINTF(",");
539 shiftreg = DECODE_RM_WORD_REGISTER(rh);
540 DECODE_PRINTF(",");
541 shift = fetch_byte_imm();
542 DECODE_PRINTF2("%d\n", shift);
543 TRACE_AND_STEP();
544 *destreg = shld_word(*destreg,*shiftreg,shift);
545 }
546 break;
c7de829c
WD
547 }
548 DECODE_CLEAR_SEGOVR();
549 END_OF_INSTR();
550}
551
552/****************************************************************************
553REMARKS:
554Handles opcode 0x0f,0xa5
555****************************************************************************/
556void x86emuOp2_shld_CL(u8 X86EMU_UNUSED(op2))
557{
558 int mod, rl, rh;
559 uint destoffset;
560
561 START_OF_INSTR();
562 DECODE_PRINTF("SHLD\t");
563 FETCH_DECODE_MODRM(mod, rh, rl);
564 switch (mod) {
565 case 0:
8bde7f77
WD
566 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
567 u32 destval;
568 u32 *shiftreg;
569
570 destoffset = decode_rm00_address(rl);
571 DECODE_PRINTF(",");
572 shiftreg = DECODE_RM_LONG_REGISTER(rh);
573 DECODE_PRINTF(",CL\n");
574 TRACE_AND_STEP();
575 destval = fetch_data_long(destoffset);
576 destval = shld_long(destval,*shiftreg,M.x86.R_CL);
577 store_data_long(destoffset, destval);
578 } else {
579 u16 destval;
580 u16 *shiftreg;
581
582 destoffset = decode_rm00_address(rl);
583 DECODE_PRINTF(",");
584 shiftreg = DECODE_RM_WORD_REGISTER(rh);
585 DECODE_PRINTF(",CL\n");
586 TRACE_AND_STEP();
587 destval = fetch_data_word(destoffset);
588 destval = shld_word(destval,*shiftreg,M.x86.R_CL);
589 store_data_word(destoffset, destval);
590 }
591 break;
c7de829c 592 case 1:
8bde7f77
WD
593 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
594 u32 destval;
595 u32 *shiftreg;
596
597 destoffset = decode_rm01_address(rl);
598 DECODE_PRINTF(",");
599 shiftreg = DECODE_RM_LONG_REGISTER(rh);
600 DECODE_PRINTF(",CL\n");
601 TRACE_AND_STEP();
602 destval = fetch_data_long(destoffset);
603 destval = shld_long(destval,*shiftreg,M.x86.R_CL);
604 store_data_long(destoffset, destval);
605 } else {
606 u16 destval;
607 u16 *shiftreg;
608
609 destoffset = decode_rm01_address(rl);
610 DECODE_PRINTF(",");
611 shiftreg = DECODE_RM_WORD_REGISTER(rh);
612 DECODE_PRINTF(",CL\n");
613 TRACE_AND_STEP();
614 destval = fetch_data_word(destoffset);
615 destval = shld_word(destval,*shiftreg,M.x86.R_CL);
616 store_data_word(destoffset, destval);
617 }
618 break;
c7de829c 619 case 2:
8bde7f77
WD
620 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
621 u32 destval;
622 u32 *shiftreg;
623
624 destoffset = decode_rm10_address(rl);
625 DECODE_PRINTF(",");
626 shiftreg = DECODE_RM_LONG_REGISTER(rh);
627 DECODE_PRINTF(",CL\n");
628 TRACE_AND_STEP();
629 destval = fetch_data_long(destoffset);
630 destval = shld_long(destval,*shiftreg,M.x86.R_CL);
631 store_data_long(destoffset, destval);
632 } else {
633 u16 destval;
634 u16 *shiftreg;
635
636 destoffset = decode_rm10_address(rl);
637 DECODE_PRINTF(",");
638 shiftreg = DECODE_RM_WORD_REGISTER(rh);
639 DECODE_PRINTF(",CL\n");
640 TRACE_AND_STEP();
641 destval = fetch_data_word(destoffset);
642 destval = shld_word(destval,*shiftreg,M.x86.R_CL);
643 store_data_word(destoffset, destval);
644 }
645 break;
c7de829c 646 case 3: /* register to register */
8bde7f77
WD
647 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
648 u32 *destreg,*shiftreg;
649
650 destreg = DECODE_RM_LONG_REGISTER(rl);
651 DECODE_PRINTF(",");
652 shiftreg = DECODE_RM_LONG_REGISTER(rh);
653 DECODE_PRINTF(",CL\n");
654 TRACE_AND_STEP();
655 *destreg = shld_long(*destreg,*shiftreg,M.x86.R_CL);
656 } else {
657 u16 *destreg,*shiftreg;
658
659 destreg = DECODE_RM_WORD_REGISTER(rl);
660 DECODE_PRINTF(",");
661 shiftreg = DECODE_RM_WORD_REGISTER(rh);
662 DECODE_PRINTF(",CL\n");
663 TRACE_AND_STEP();
664 *destreg = shld_word(*destreg,*shiftreg,M.x86.R_CL);
665 }
666 break;
c7de829c
WD
667 }
668 DECODE_CLEAR_SEGOVR();
669 END_OF_INSTR();
670}
671
672/****************************************************************************
673REMARKS:
674Handles opcode 0x0f,0xa8
675****************************************************************************/
676void x86emuOp2_push_GS(u8 X86EMU_UNUSED(op2))
677{
678 START_OF_INSTR();
679 DECODE_PRINTF("PUSH\tGS\n");
680 TRACE_AND_STEP();
681 push_word(M.x86.R_GS);
682 DECODE_CLEAR_SEGOVR();
683 END_OF_INSTR();
684}
685
686/****************************************************************************
687REMARKS:
688Handles opcode 0x0f,0xa9
689****************************************************************************/
690void x86emuOp2_pop_GS(u8 X86EMU_UNUSED(op2))
691{
692 START_OF_INSTR();
693 DECODE_PRINTF("POP\tGS\n");
694 TRACE_AND_STEP();
695 M.x86.R_GS = pop_word();
696 DECODE_CLEAR_SEGOVR();
697 END_OF_INSTR();
698}
699
700/****************************************************************************
701REMARKS:
702Handles opcode 0x0f,0xaa
703****************************************************************************/
704void x86emuOp2_bts_R(u8 X86EMU_UNUSED(op2))
705{
706 int mod, rl, rh;
707 uint srcoffset;
708 int bit,disp;
709
710 START_OF_INSTR();
711 DECODE_PRINTF("BTS\t");
712 FETCH_DECODE_MODRM(mod, rh, rl);
713 switch (mod) {
714 case 0:
8bde7f77
WD
715 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
716 u32 srcval,mask;
717 u32 *shiftreg;
718
719 srcoffset = decode_rm00_address(rl);
720 DECODE_PRINTF(",");
721 shiftreg = DECODE_RM_LONG_REGISTER(rh);
722 TRACE_AND_STEP();
723 bit = *shiftreg & 0x1F;
724 disp = (s16)*shiftreg >> 5;
725 srcval = fetch_data_long(srcoffset+disp);
726 mask = (0x1 << bit);
727 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
728 store_data_long(srcoffset+disp, srcval | mask);
729 } else {
730 u16 srcval,mask;
731 u16 *shiftreg;
732
733 srcoffset = decode_rm00_address(rl);
734 DECODE_PRINTF(",");
735 shiftreg = DECODE_RM_WORD_REGISTER(rh);
736 TRACE_AND_STEP();
737 bit = *shiftreg & 0xF;
738 disp = (s16)*shiftreg >> 4;
739 srcval = fetch_data_word(srcoffset+disp);
c7de829c 740 mask = (u16)(0x1 << bit);
8bde7f77
WD
741 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
742 store_data_word(srcoffset+disp, srcval | mask);
743 }
744 break;
c7de829c 745 case 1:
8bde7f77
WD
746 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
747 u32 srcval,mask;
748 u32 *shiftreg;
749
750 srcoffset = decode_rm01_address(rl);
751 DECODE_PRINTF(",");
752 shiftreg = DECODE_RM_LONG_REGISTER(rh);
753 TRACE_AND_STEP();
754 bit = *shiftreg & 0x1F;
755 disp = (s16)*shiftreg >> 5;
756 srcval = fetch_data_long(srcoffset+disp);
757 mask = (0x1 << bit);
758 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
759 store_data_long(srcoffset+disp, srcval | mask);
760 } else {
761 u16 srcval,mask;
762 u16 *shiftreg;
763
764 srcoffset = decode_rm01_address(rl);
765 DECODE_PRINTF(",");
766 shiftreg = DECODE_RM_WORD_REGISTER(rh);
767 TRACE_AND_STEP();
768 bit = *shiftreg & 0xF;
769 disp = (s16)*shiftreg >> 4;
770 srcval = fetch_data_word(srcoffset+disp);
c7de829c 771 mask = (u16)(0x1 << bit);
8bde7f77
WD
772 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
773 store_data_word(srcoffset+disp, srcval | mask);
774 }
775 break;
c7de829c 776 case 2:
8bde7f77
WD
777 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
778 u32 srcval,mask;
779 u32 *shiftreg;
780
781 srcoffset = decode_rm10_address(rl);
782 DECODE_PRINTF(",");
783 shiftreg = DECODE_RM_LONG_REGISTER(rh);
784 TRACE_AND_STEP();
785 bit = *shiftreg & 0x1F;
786 disp = (s16)*shiftreg >> 5;
787 srcval = fetch_data_long(srcoffset+disp);
788 mask = (0x1 << bit);
789 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
790 store_data_long(srcoffset+disp, srcval | mask);
791 } else {
792 u16 srcval,mask;
793 u16 *shiftreg;
c7de829c
WD
794
795 srcoffset = decode_rm10_address(rl);
796 DECODE_PRINTF(",");
797 shiftreg = DECODE_RM_WORD_REGISTER(rh);
798 TRACE_AND_STEP();
799 bit = *shiftreg & 0xF;
800 disp = (s16)*shiftreg >> 4;
801 srcval = fetch_data_word(srcoffset+disp);
802 mask = (u16)(0x1 << bit);
803 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
804 store_data_word(srcoffset+disp, srcval | mask);
805 }
806 break;
807 case 3: /* register to register */
808 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
809 u32 *srcreg,*shiftreg;
810 u32 mask;
811
812 srcreg = DECODE_RM_LONG_REGISTER(rl);
813 DECODE_PRINTF(",");
814 shiftreg = DECODE_RM_LONG_REGISTER(rh);
815 TRACE_AND_STEP();
816 bit = *shiftreg & 0x1F;
817 mask = (0x1 << bit);
818 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
819 *srcreg |= mask;
820 } else {
821 u16 *srcreg,*shiftreg;
822 u16 mask;
823
824 srcreg = DECODE_RM_WORD_REGISTER(rl);
825 DECODE_PRINTF(",");
826 shiftreg = DECODE_RM_WORD_REGISTER(rh);
827 TRACE_AND_STEP();
828 bit = *shiftreg & 0xF;
829 mask = (u16)(0x1 << bit);
8bde7f77
WD
830 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
831 *srcreg |= mask;
832 }
833 break;
c7de829c
WD
834 }
835 DECODE_CLEAR_SEGOVR();
836 END_OF_INSTR();
837}
838
839/****************************************************************************
840REMARKS:
841Handles opcode 0x0f,0xac
842****************************************************************************/
843void x86emuOp2_shrd_IMM(u8 X86EMU_UNUSED(op2))
844{
845 int mod, rl, rh;
846 uint destoffset;
847 u8 shift;
848
849 START_OF_INSTR();
850 DECODE_PRINTF("SHLD\t");
851 FETCH_DECODE_MODRM(mod, rh, rl);
852 switch (mod) {
853 case 0:
8bde7f77
WD
854 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
855 u32 destval;
856 u32 *shiftreg;
857
858 destoffset = decode_rm00_address(rl);
859 DECODE_PRINTF(",");
860 shiftreg = DECODE_RM_LONG_REGISTER(rh);
861 DECODE_PRINTF(",");
862 shift = fetch_byte_imm();
863 DECODE_PRINTF2("%d\n", shift);
864 TRACE_AND_STEP();
865 destval = fetch_data_long(destoffset);
866 destval = shrd_long(destval,*shiftreg,shift);
867 store_data_long(destoffset, destval);
868 } else {
869 u16 destval;
870 u16 *shiftreg;
871
872 destoffset = decode_rm00_address(rl);
873 DECODE_PRINTF(",");
874 shiftreg = DECODE_RM_WORD_REGISTER(rh);
875 DECODE_PRINTF(",");
876 shift = fetch_byte_imm();
877 DECODE_PRINTF2("%d\n", shift);
878 TRACE_AND_STEP();
879 destval = fetch_data_word(destoffset);
880 destval = shrd_word(destval,*shiftreg,shift);
881 store_data_word(destoffset, destval);
882 }
883 break;
c7de829c 884 case 1:
8bde7f77
WD
885 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
886 u32 destval;
887 u32 *shiftreg;
888
889 destoffset = decode_rm01_address(rl);
890 DECODE_PRINTF(",");
891 shiftreg = DECODE_RM_LONG_REGISTER(rh);
892 DECODE_PRINTF(",");
893 shift = fetch_byte_imm();
894 DECODE_PRINTF2("%d\n", shift);
895 TRACE_AND_STEP();
896 destval = fetch_data_long(destoffset);
897 destval = shrd_long(destval,*shiftreg,shift);
898 store_data_long(destoffset, destval);
899 } else {
900 u16 destval;
901 u16 *shiftreg;
902
903 destoffset = decode_rm01_address(rl);
904 DECODE_PRINTF(",");
905 shiftreg = DECODE_RM_WORD_REGISTER(rh);
906 DECODE_PRINTF(",");
907 shift = fetch_byte_imm();
908 DECODE_PRINTF2("%d\n", shift);
909 TRACE_AND_STEP();
910 destval = fetch_data_word(destoffset);
911 destval = shrd_word(destval,*shiftreg,shift);
912 store_data_word(destoffset, destval);
913 }
914 break;
c7de829c 915 case 2:
8bde7f77
WD
916 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
917 u32 destval;
918 u32 *shiftreg;
919
920 destoffset = decode_rm10_address(rl);
921 DECODE_PRINTF(",");
922 shiftreg = DECODE_RM_LONG_REGISTER(rh);
923 DECODE_PRINTF(",");
924 shift = fetch_byte_imm();
925 DECODE_PRINTF2("%d\n", shift);
926 TRACE_AND_STEP();
927 destval = fetch_data_long(destoffset);
928 destval = shrd_long(destval,*shiftreg,shift);
929 store_data_long(destoffset, destval);
930 } else {
931 u16 destval;
932 u16 *shiftreg;
933
934 destoffset = decode_rm10_address(rl);
935 DECODE_PRINTF(",");
936 shiftreg = DECODE_RM_WORD_REGISTER(rh);
937 DECODE_PRINTF(",");
938 shift = fetch_byte_imm();
939 DECODE_PRINTF2("%d\n", shift);
940 TRACE_AND_STEP();
941 destval = fetch_data_word(destoffset);
942 destval = shrd_word(destval,*shiftreg,shift);
943 store_data_word(destoffset, destval);
944 }
945 break;
c7de829c 946 case 3: /* register to register */
8bde7f77
WD
947 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
948 u32 *destreg,*shiftreg;
949
950 destreg = DECODE_RM_LONG_REGISTER(rl);
951 DECODE_PRINTF(",");
952 shiftreg = DECODE_RM_LONG_REGISTER(rh);
953 DECODE_PRINTF(",");
954 shift = fetch_byte_imm();
955 DECODE_PRINTF2("%d\n", shift);
956 TRACE_AND_STEP();
957 *destreg = shrd_long(*destreg,*shiftreg,shift);
958 } else {
959 u16 *destreg,*shiftreg;
960
961 destreg = DECODE_RM_WORD_REGISTER(rl);
962 DECODE_PRINTF(",");
963 shiftreg = DECODE_RM_WORD_REGISTER(rh);
964 DECODE_PRINTF(",");
965 shift = fetch_byte_imm();
966 DECODE_PRINTF2("%d\n", shift);
967 TRACE_AND_STEP();
968 *destreg = shrd_word(*destreg,*shiftreg,shift);
969 }
970 break;
c7de829c
WD
971 }
972 DECODE_CLEAR_SEGOVR();
973 END_OF_INSTR();
974}
975
976/****************************************************************************
977REMARKS:
978Handles opcode 0x0f,0xad
979****************************************************************************/
980void x86emuOp2_shrd_CL(u8 X86EMU_UNUSED(op2))
981{
982 int mod, rl, rh;
983 uint destoffset;
984
985 START_OF_INSTR();
986 DECODE_PRINTF("SHLD\t");
987 FETCH_DECODE_MODRM(mod, rh, rl);
988 switch (mod) {
989 case 0:
8bde7f77
WD
990 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
991 u32 destval;
992 u32 *shiftreg;
993
994 destoffset = decode_rm00_address(rl);
995 DECODE_PRINTF(",");
996 shiftreg = DECODE_RM_LONG_REGISTER(rh);
997 DECODE_PRINTF(",CL\n");
998 TRACE_AND_STEP();
999 destval = fetch_data_long(destoffset);
1000 destval = shrd_long(destval,*shiftreg,M.x86.R_CL);
1001 store_data_long(destoffset, destval);
1002 } else {
1003 u16 destval;
1004 u16 *shiftreg;
1005
1006 destoffset = decode_rm00_address(rl);
1007 DECODE_PRINTF(",");
1008 shiftreg = DECODE_RM_WORD_REGISTER(rh);
1009 DECODE_PRINTF(",CL\n");
1010 TRACE_AND_STEP();
1011 destval = fetch_data_word(destoffset);
1012 destval = shrd_word(destval,*shiftreg,M.x86.R_CL);
1013 store_data_word(destoffset, destval);
1014 }
1015 break;
c7de829c 1016 case 1:
8bde7f77
WD
1017 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1018 u32 destval;
1019 u32 *shiftreg;
1020
1021 destoffset = decode_rm01_address(rl);
1022 DECODE_PRINTF(",");
1023 shiftreg = DECODE_RM_LONG_REGISTER(rh);
1024 DECODE_PRINTF(",CL\n");
1025 TRACE_AND_STEP();
1026 destval = fetch_data_long(destoffset);
1027 destval = shrd_long(destval,*shiftreg,M.x86.R_CL);
1028 store_data_long(destoffset, destval);
1029 } else {
1030 u16 destval;
1031 u16 *shiftreg;
1032
1033 destoffset = decode_rm01_address(rl);
1034 DECODE_PRINTF(",");
1035 shiftreg = DECODE_RM_WORD_REGISTER(rh);
1036 DECODE_PRINTF(",CL\n");
1037 TRACE_AND_STEP();
1038 destval = fetch_data_word(destoffset);
1039 destval = shrd_word(destval,*shiftreg,M.x86.R_CL);
1040 store_data_word(destoffset, destval);
1041 }
1042 break;
c7de829c 1043 case 2:
8bde7f77
WD
1044 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1045 u32 destval;
1046 u32 *shiftreg;
1047
1048 destoffset = decode_rm10_address(rl);
1049 DECODE_PRINTF(",");
1050 shiftreg = DECODE_RM_LONG_REGISTER(rh);
1051 DECODE_PRINTF(",CL\n");
1052 TRACE_AND_STEP();
1053 destval = fetch_data_long(destoffset);
1054 destval = shrd_long(destval,*shiftreg,M.x86.R_CL);
1055 store_data_long(destoffset, destval);
1056 } else {
1057 u16 destval;
1058 u16 *shiftreg;
1059
1060 destoffset = decode_rm10_address(rl);
1061 DECODE_PRINTF(",");
1062 shiftreg = DECODE_RM_WORD_REGISTER(rh);
1063 DECODE_PRINTF(",CL\n");
1064 TRACE_AND_STEP();
1065 destval = fetch_data_word(destoffset);
1066 destval = shrd_word(destval,*shiftreg,M.x86.R_CL);
1067 store_data_word(destoffset, destval);
1068 }
1069 break;
c7de829c 1070 case 3: /* register to register */
8bde7f77
WD
1071 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1072 u32 *destreg,*shiftreg;
1073
1074 destreg = DECODE_RM_LONG_REGISTER(rl);
1075 DECODE_PRINTF(",");
1076 shiftreg = DECODE_RM_LONG_REGISTER(rh);
1077 DECODE_PRINTF(",CL\n");
1078 TRACE_AND_STEP();
1079 *destreg = shrd_long(*destreg,*shiftreg,M.x86.R_CL);
1080 } else {
1081 u16 *destreg,*shiftreg;
1082
1083 destreg = DECODE_RM_WORD_REGISTER(rl);
1084 DECODE_PRINTF(",");
1085 shiftreg = DECODE_RM_WORD_REGISTER(rh);
1086 DECODE_PRINTF(",CL\n");
1087 TRACE_AND_STEP();
1088 *destreg = shrd_word(*destreg,*shiftreg,M.x86.R_CL);
1089 }
1090 break;
c7de829c
WD
1091 }
1092 DECODE_CLEAR_SEGOVR();
1093 END_OF_INSTR();
1094}
1095
1096/****************************************************************************
1097REMARKS:
1098Handles opcode 0x0f,0xaf
1099****************************************************************************/
1100void x86emuOp2_imul_R_RM(u8 X86EMU_UNUSED(op2))
1101{
1102 int mod, rl, rh;
1103 uint srcoffset;
1104
1105 START_OF_INSTR();
1106 DECODE_PRINTF("IMUL\t");
1107 FETCH_DECODE_MODRM(mod, rh, rl);
1108 switch (mod) {
1109 case 0:
8bde7f77
WD
1110 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1111 u32 *destreg;
1112 u32 srcval;
1113 u32 res_lo,res_hi;
1114
1115 destreg = DECODE_RM_LONG_REGISTER(rh);
1116 DECODE_PRINTF(",");
1117 srcoffset = decode_rm00_address(rl);
1118 srcval = fetch_data_long(srcoffset);
1119 TRACE_AND_STEP();
1120 imul_long_direct(&res_lo,&res_hi,(s32)*destreg,(s32)srcval);
1121 if (res_hi != 0) {
1122 SET_FLAG(F_CF);
1123 SET_FLAG(F_OF);
1124 } else {
1125 CLEAR_FLAG(F_CF);
1126 CLEAR_FLAG(F_OF);
1127 }
1128 *destreg = (u32)res_lo;
1129 } else {
1130 u16 *destreg;
1131 u16 srcval;
1132 u32 res;
1133
1134 destreg = DECODE_RM_WORD_REGISTER(rh);
1135 DECODE_PRINTF(",");
1136 srcoffset = decode_rm00_address(rl);
1137 srcval = fetch_data_word(srcoffset);
1138 TRACE_AND_STEP();
1139 res = (s16)*destreg * (s16)srcval;
1140 if (res > 0xFFFF) {
1141 SET_FLAG(F_CF);
1142 SET_FLAG(F_OF);
1143 } else {
1144 CLEAR_FLAG(F_CF);
1145 CLEAR_FLAG(F_OF);
1146 }
1147 *destreg = (u16)res;
1148 }
1149 break;
c7de829c 1150 case 1:
8bde7f77
WD
1151 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1152 u32 *destreg;
1153 u32 srcval;
1154 u32 res_lo,res_hi;
1155
1156 destreg = DECODE_RM_LONG_REGISTER(rh);
1157 DECODE_PRINTF(",");
1158 srcoffset = decode_rm01_address(rl);
1159 srcval = fetch_data_long(srcoffset);
1160 TRACE_AND_STEP();
1161 imul_long_direct(&res_lo,&res_hi,(s32)*destreg,(s32)srcval);
1162 if (res_hi != 0) {
1163 SET_FLAG(F_CF);
1164 SET_FLAG(F_OF);
1165 } else {
1166 CLEAR_FLAG(F_CF);
1167 CLEAR_FLAG(F_OF);
1168 }
1169 *destreg = (u32)res_lo;
1170 } else {
1171 u16 *destreg;
1172 u16 srcval;
1173 u32 res;
1174
1175 destreg = DECODE_RM_WORD_REGISTER(rh);
1176 DECODE_PRINTF(",");
1177 srcoffset = decode_rm01_address(rl);
1178 srcval = fetch_data_word(srcoffset);
1179 TRACE_AND_STEP();
1180 res = (s16)*destreg * (s16)srcval;
1181 if (res > 0xFFFF) {
1182 SET_FLAG(F_CF);
1183 SET_FLAG(F_OF);
1184 } else {
1185 CLEAR_FLAG(F_CF);
1186 CLEAR_FLAG(F_OF);
1187 }
1188 *destreg = (u16)res;
1189 }
1190 break;
c7de829c 1191 case 2:
8bde7f77
WD
1192 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1193 u32 *destreg;
1194 u32 srcval;
1195 u32 res_lo,res_hi;
1196
1197 destreg = DECODE_RM_LONG_REGISTER(rh);
1198 DECODE_PRINTF(",");
1199 srcoffset = decode_rm10_address(rl);
1200 srcval = fetch_data_long(srcoffset);
1201 TRACE_AND_STEP();
1202 imul_long_direct(&res_lo,&res_hi,(s32)*destreg,(s32)srcval);
1203 if (res_hi != 0) {
1204 SET_FLAG(F_CF);
1205 SET_FLAG(F_OF);
1206 } else {
1207 CLEAR_FLAG(F_CF);
1208 CLEAR_FLAG(F_OF);
1209 }
1210 *destreg = (u32)res_lo;
1211 } else {
1212 u16 *destreg;
1213 u16 srcval;
1214 u32 res;
1215
1216 destreg = DECODE_RM_WORD_REGISTER(rh);
1217 DECODE_PRINTF(",");
1218 srcoffset = decode_rm10_address(rl);
1219 srcval = fetch_data_word(srcoffset);
1220 TRACE_AND_STEP();
1221 res = (s16)*destreg * (s16)srcval;
1222 if (res > 0xFFFF) {
1223 SET_FLAG(F_CF);
1224 SET_FLAG(F_OF);
1225 } else {
1226 CLEAR_FLAG(F_CF);
1227 CLEAR_FLAG(F_OF);
1228 }
1229 *destreg = (u16)res;
1230 }
1231 break;
c7de829c 1232 case 3: /* register to register */
8bde7f77
WD
1233 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1234 u32 *destreg,*srcreg;
1235 u32 res_lo,res_hi;
1236
1237 destreg = DECODE_RM_LONG_REGISTER(rh);
1238 DECODE_PRINTF(",");
1239 srcreg = DECODE_RM_LONG_REGISTER(rl);
1240 TRACE_AND_STEP();
1241 imul_long_direct(&res_lo,&res_hi,(s32)*destreg,(s32)*srcreg);
1242 if (res_hi != 0) {
1243 SET_FLAG(F_CF);
1244 SET_FLAG(F_OF);
1245 } else {
1246 CLEAR_FLAG(F_CF);
1247 CLEAR_FLAG(F_OF);
1248 }
1249 *destreg = (u32)res_lo;
1250 } else {
1251 u16 *destreg,*srcreg;
1252 u32 res;
1253
1254 destreg = DECODE_RM_WORD_REGISTER(rh);
1255 DECODE_PRINTF(",");
1256 srcreg = DECODE_RM_WORD_REGISTER(rl);
1257 res = (s16)*destreg * (s16)*srcreg;
1258 if (res > 0xFFFF) {
1259 SET_FLAG(F_CF);
1260 SET_FLAG(F_OF);
1261 } else {
1262 CLEAR_FLAG(F_CF);
1263 CLEAR_FLAG(F_OF);
1264 }
1265 *destreg = (u16)res;
1266 }
1267 break;
c7de829c
WD
1268 }
1269 DECODE_CLEAR_SEGOVR();
1270 END_OF_INSTR();
1271}
1272
1273/****************************************************************************
1274REMARKS:
1275Handles opcode 0x0f,0xb2
1276****************************************************************************/
1277void x86emuOp2_lss_R_IMM(u8 X86EMU_UNUSED(op2))
1278{
1279 int mod, rh, rl;
1280 u16 *dstreg;
1281 uint srcoffset;
1282
1283 START_OF_INSTR();
1284 DECODE_PRINTF("LSS\t");
1285 FETCH_DECODE_MODRM(mod, rh, rl);
1286 switch (mod) {
1287 case 0:
8bde7f77
WD
1288 dstreg = DECODE_RM_WORD_REGISTER(rh);
1289 DECODE_PRINTF(",");
1290 srcoffset = decode_rm00_address(rl);
1291 DECODE_PRINTF("\n");
1292 TRACE_AND_STEP();
1293 *dstreg = fetch_data_word(srcoffset);
1294 M.x86.R_SS = fetch_data_word(srcoffset + 2);
1295 break;
c7de829c 1296 case 1:
8bde7f77
WD
1297 dstreg = DECODE_RM_WORD_REGISTER(rh);
1298 DECODE_PRINTF(",");
1299 srcoffset = decode_rm01_address(rl);
1300 DECODE_PRINTF("\n");
1301 TRACE_AND_STEP();
1302 *dstreg = fetch_data_word(srcoffset);
1303 M.x86.R_SS = fetch_data_word(srcoffset + 2);
1304 break;
c7de829c 1305 case 2:
8bde7f77
WD
1306 dstreg = DECODE_RM_WORD_REGISTER(rh);
1307 DECODE_PRINTF(",");
1308 srcoffset = decode_rm10_address(rl);
1309 DECODE_PRINTF("\n");
1310 TRACE_AND_STEP();
1311 *dstreg = fetch_data_word(srcoffset);
1312 M.x86.R_SS = fetch_data_word(srcoffset + 2);
1313 break;
c7de829c 1314 case 3: /* register to register */
8bde7f77
WD
1315 /* UNDEFINED! */
1316 TRACE_AND_STEP();
c7de829c
WD
1317 }
1318 DECODE_CLEAR_SEGOVR();
1319 END_OF_INSTR();
1320}
1321
1322/****************************************************************************
1323REMARKS:
1324Handles opcode 0x0f,0xb3
1325****************************************************************************/
1326void x86emuOp2_btr_R(u8 X86EMU_UNUSED(op2))
1327{
1328 int mod, rl, rh;
1329 uint srcoffset;
1330 int bit,disp;
1331
1332 START_OF_INSTR();
1333 DECODE_PRINTF("BTR\t");
1334 FETCH_DECODE_MODRM(mod, rh, rl);
1335 switch (mod) {
1336 case 0:
1337 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1338 u32 srcval,mask;
1339 u32 *shiftreg;
1340
1341 srcoffset = decode_rm00_address(rl);
1342 DECODE_PRINTF(",");
1343 shiftreg = DECODE_RM_LONG_REGISTER(rh);
1344 TRACE_AND_STEP();
1345 bit = *shiftreg & 0x1F;
1346 disp = (s16)*shiftreg >> 5;
1347 srcval = fetch_data_long(srcoffset+disp);
1348 mask = (0x1 << bit);
1349 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1350 store_data_long(srcoffset+disp, srcval & ~mask);
1351 } else {
1352 u16 srcval,mask;
1353 u16 *shiftreg;
1354
1355 srcoffset = decode_rm00_address(rl);
1356 DECODE_PRINTF(",");
1357 shiftreg = DECODE_RM_WORD_REGISTER(rh);
1358 TRACE_AND_STEP();
1359 bit = *shiftreg & 0xF;
1360 disp = (s16)*shiftreg >> 4;
1361 srcval = fetch_data_word(srcoffset+disp);
1362 mask = (u16)(0x1 << bit);
1363 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1364 store_data_word(srcoffset+disp, (u16)(srcval & ~mask));
1365 }
1366 break;
1367 case 1:
1368 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1369 u32 srcval,mask;
1370 u32 *shiftreg;
1371
1372 srcoffset = decode_rm01_address(rl);
1373 DECODE_PRINTF(",");
1374 shiftreg = DECODE_RM_LONG_REGISTER(rh);
1375 TRACE_AND_STEP();
1376 bit = *shiftreg & 0x1F;
1377 disp = (s16)*shiftreg >> 5;
1378 srcval = fetch_data_long(srcoffset+disp);
1379 mask = (0x1 << bit);
1380 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1381 store_data_long(srcoffset+disp, srcval & ~mask);
1382 } else {
1383 u16 srcval,mask;
1384 u16 *shiftreg;
1385
1386 srcoffset = decode_rm01_address(rl);
1387 DECODE_PRINTF(",");
1388 shiftreg = DECODE_RM_WORD_REGISTER(rh);
1389 TRACE_AND_STEP();
1390 bit = *shiftreg & 0xF;
1391 disp = (s16)*shiftreg >> 4;
1392 srcval = fetch_data_word(srcoffset+disp);
1393 mask = (u16)(0x1 << bit);
1394 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1395 store_data_word(srcoffset+disp, (u16)(srcval & ~mask));
1396 }
1397 break;
1398 case 2:
1399 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1400 u32 srcval,mask;
1401 u32 *shiftreg;
1402
1403 srcoffset = decode_rm10_address(rl);
1404 DECODE_PRINTF(",");
1405 shiftreg = DECODE_RM_LONG_REGISTER(rh);
1406 TRACE_AND_STEP();
1407 bit = *shiftreg & 0x1F;
1408 disp = (s16)*shiftreg >> 5;
1409 srcval = fetch_data_long(srcoffset+disp);
1410 mask = (0x1 << bit);
1411 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1412 store_data_long(srcoffset+disp, srcval & ~mask);
1413 } else {
1414 u16 srcval,mask;
1415 u16 *shiftreg;
1416
1417 srcoffset = decode_rm10_address(rl);
1418 DECODE_PRINTF(",");
1419 shiftreg = DECODE_RM_WORD_REGISTER(rh);
1420 TRACE_AND_STEP();
1421 bit = *shiftreg & 0xF;
1422 disp = (s16)*shiftreg >> 4;
1423 srcval = fetch_data_word(srcoffset+disp);
1424 mask = (u16)(0x1 << bit);
1425 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1426 store_data_word(srcoffset+disp, (u16)(srcval & ~mask));
1427 }
1428 break;
1429 case 3: /* register to register */
1430 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1431 u32 *srcreg,*shiftreg;
1432 u32 mask;
1433
1434 srcreg = DECODE_RM_LONG_REGISTER(rl);
1435 DECODE_PRINTF(",");
1436 shiftreg = DECODE_RM_LONG_REGISTER(rh);
1437 TRACE_AND_STEP();
1438 bit = *shiftreg & 0x1F;
1439 mask = (0x1 << bit);
1440 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1441 *srcreg &= ~mask;
1442 } else {
1443 u16 *srcreg,*shiftreg;
1444 u16 mask;
1445
1446 srcreg = DECODE_RM_WORD_REGISTER(rl);
1447 DECODE_PRINTF(",");
1448 shiftreg = DECODE_RM_WORD_REGISTER(rh);
1449 TRACE_AND_STEP();
1450 bit = *shiftreg & 0xF;
1451 mask = (u16)(0x1 << bit);
1452 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1453 *srcreg &= ~mask;
1454 }
1455 break;
1456 }
1457 DECODE_CLEAR_SEGOVR();
1458 END_OF_INSTR();
1459}
1460
1461/****************************************************************************
1462REMARKS:
1463Handles opcode 0x0f,0xb4
1464****************************************************************************/
1465void x86emuOp2_lfs_R_IMM(u8 X86EMU_UNUSED(op2))
1466{
1467 int mod, rh, rl;
1468 u16 *dstreg;
1469 uint srcoffset;
1470
1471 START_OF_INSTR();
1472 DECODE_PRINTF("LFS\t");
1473 FETCH_DECODE_MODRM(mod, rh, rl);
1474 switch (mod) {
1475 case 0:
8bde7f77
WD
1476 dstreg = DECODE_RM_WORD_REGISTER(rh);
1477 DECODE_PRINTF(",");
1478 srcoffset = decode_rm00_address(rl);
1479 DECODE_PRINTF("\n");
1480 TRACE_AND_STEP();
1481 *dstreg = fetch_data_word(srcoffset);
1482 M.x86.R_FS = fetch_data_word(srcoffset + 2);
1483 break;
c7de829c 1484 case 1:
8bde7f77
WD
1485 dstreg = DECODE_RM_WORD_REGISTER(rh);
1486 DECODE_PRINTF(",");
1487 srcoffset = decode_rm01_address(rl);
1488 DECODE_PRINTF("\n");
1489 TRACE_AND_STEP();
1490 *dstreg = fetch_data_word(srcoffset);
1491 M.x86.R_FS = fetch_data_word(srcoffset + 2);
1492 break;
c7de829c 1493 case 2:
8bde7f77
WD
1494 dstreg = DECODE_RM_WORD_REGISTER(rh);
1495 DECODE_PRINTF(",");
1496 srcoffset = decode_rm10_address(rl);
1497 DECODE_PRINTF("\n");
1498 TRACE_AND_STEP();
1499 *dstreg = fetch_data_word(srcoffset);
1500 M.x86.R_FS = fetch_data_word(srcoffset + 2);
1501 break;
c7de829c 1502 case 3: /* register to register */
8bde7f77
WD
1503 /* UNDEFINED! */
1504 TRACE_AND_STEP();
c7de829c
WD
1505 }
1506 DECODE_CLEAR_SEGOVR();
1507 END_OF_INSTR();
1508}
1509
1510/****************************************************************************
1511REMARKS:
1512Handles opcode 0x0f,0xb5
1513****************************************************************************/
1514void x86emuOp2_lgs_R_IMM(u8 X86EMU_UNUSED(op2))
1515{
1516 int mod, rh, rl;
1517 u16 *dstreg;
1518 uint srcoffset;
1519
1520 START_OF_INSTR();
1521 DECODE_PRINTF("LGS\t");
1522 FETCH_DECODE_MODRM(mod, rh, rl);
1523 switch (mod) {
1524 case 0:
8bde7f77
WD
1525 dstreg = DECODE_RM_WORD_REGISTER(rh);
1526 DECODE_PRINTF(",");
1527 srcoffset = decode_rm00_address(rl);
1528 DECODE_PRINTF("\n");
1529 TRACE_AND_STEP();
1530 *dstreg = fetch_data_word(srcoffset);
1531 M.x86.R_GS = fetch_data_word(srcoffset + 2);
1532 break;
c7de829c 1533 case 1:
8bde7f77
WD
1534 dstreg = DECODE_RM_WORD_REGISTER(rh);
1535 DECODE_PRINTF(",");
1536 srcoffset = decode_rm01_address(rl);
1537 DECODE_PRINTF("\n");
1538 TRACE_AND_STEP();
1539 *dstreg = fetch_data_word(srcoffset);
1540 M.x86.R_GS = fetch_data_word(srcoffset + 2);
1541 break;
c7de829c 1542 case 2:
8bde7f77
WD
1543 dstreg = DECODE_RM_WORD_REGISTER(rh);
1544 DECODE_PRINTF(",");
1545 srcoffset = decode_rm10_address(rl);
1546 DECODE_PRINTF("\n");
1547 TRACE_AND_STEP();
1548 *dstreg = fetch_data_word(srcoffset);
1549 M.x86.R_GS = fetch_data_word(srcoffset + 2);
1550 break;
c7de829c 1551 case 3: /* register to register */
8bde7f77
WD
1552 /* UNDEFINED! */
1553 TRACE_AND_STEP();
c7de829c
WD
1554 }
1555 DECODE_CLEAR_SEGOVR();
1556 END_OF_INSTR();
1557}
1558
1559/****************************************************************************
1560REMARKS:
1561Handles opcode 0x0f,0xb6
1562****************************************************************************/
1563void x86emuOp2_movzx_byte_R_RM(u8 X86EMU_UNUSED(op2))
1564{
1565 int mod, rl, rh;
1566 uint srcoffset;
1567
1568 START_OF_INSTR();
1569 DECODE_PRINTF("MOVZX\t");
1570 FETCH_DECODE_MODRM(mod, rh, rl);
1571 switch (mod) {
1572 case 0:
8bde7f77
WD
1573 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1574 u32 *destreg;
1575 u32 srcval;
1576
1577 destreg = DECODE_RM_LONG_REGISTER(rh);
1578 DECODE_PRINTF(",");
1579 srcoffset = decode_rm00_address(rl);
1580 srcval = fetch_data_byte(srcoffset);
1581 DECODE_PRINTF("\n");
1582 TRACE_AND_STEP();
1583 *destreg = srcval;
1584 } else {
1585 u16 *destreg;
1586 u16 srcval;
1587
1588 destreg = DECODE_RM_WORD_REGISTER(rh);
1589 DECODE_PRINTF(",");
1590 srcoffset = decode_rm00_address(rl);
1591 srcval = fetch_data_byte(srcoffset);
1592 DECODE_PRINTF("\n");
1593 TRACE_AND_STEP();
1594 *destreg = srcval;
1595 }
1596 break;
c7de829c 1597 case 1:
8bde7f77
WD
1598 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1599 u32 *destreg;
1600 u32 srcval;
1601
1602 destreg = DECODE_RM_LONG_REGISTER(rh);
1603 DECODE_PRINTF(",");
1604 srcoffset = decode_rm01_address(rl);
1605 srcval = fetch_data_byte(srcoffset);
1606 DECODE_PRINTF("\n");
1607 TRACE_AND_STEP();
1608 *destreg = srcval;
1609 } else {
1610 u16 *destreg;
1611 u16 srcval;
1612
1613 destreg = DECODE_RM_WORD_REGISTER(rh);
1614 DECODE_PRINTF(",");
1615 srcoffset = decode_rm01_address(rl);
1616 srcval = fetch_data_byte(srcoffset);
1617 DECODE_PRINTF("\n");
1618 TRACE_AND_STEP();
1619 *destreg = srcval;
1620 }
1621 break;
c7de829c 1622 case 2:
8bde7f77
WD
1623 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1624 u32 *destreg;
1625 u32 srcval;
1626
1627 destreg = DECODE_RM_LONG_REGISTER(rh);
1628 DECODE_PRINTF(",");
1629 srcoffset = decode_rm10_address(rl);
1630 srcval = fetch_data_byte(srcoffset);
1631 DECODE_PRINTF("\n");
1632 TRACE_AND_STEP();
1633 *destreg = srcval;
1634 } else {
1635 u16 *destreg;
1636 u16 srcval;
1637
1638 destreg = DECODE_RM_WORD_REGISTER(rh);
1639 DECODE_PRINTF(",");
1640 srcoffset = decode_rm10_address(rl);
1641 srcval = fetch_data_byte(srcoffset);
1642 DECODE_PRINTF("\n");
1643 TRACE_AND_STEP();
1644 *destreg = srcval;
1645 }
1646 break;
c7de829c 1647 case 3: /* register to register */
8bde7f77
WD
1648 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1649 u32 *destreg;
1650 u8 *srcreg;
1651
1652 destreg = DECODE_RM_LONG_REGISTER(rh);
1653 DECODE_PRINTF(",");
1654 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1655 DECODE_PRINTF("\n");
1656 TRACE_AND_STEP();
1657 *destreg = *srcreg;
1658 } else {
1659 u16 *destreg;
1660 u8 *srcreg;
1661
1662 destreg = DECODE_RM_WORD_REGISTER(rh);
1663 DECODE_PRINTF(",");
1664 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1665 DECODE_PRINTF("\n");
1666 TRACE_AND_STEP();
1667 *destreg = *srcreg;
1668 }
1669 break;
c7de829c
WD
1670 }
1671 DECODE_CLEAR_SEGOVR();
1672 END_OF_INSTR();
1673}
1674
1675/****************************************************************************
1676REMARKS:
1677Handles opcode 0x0f,0xb7
1678****************************************************************************/
1679void x86emuOp2_movzx_word_R_RM(u8 X86EMU_UNUSED(op2))
1680{
1681 int mod, rl, rh;
1682 uint srcoffset;
1683 u32 *destreg;
1684 u32 srcval;
1685 u16 *srcreg;
1686
1687 START_OF_INSTR();
1688 DECODE_PRINTF("MOVZX\t");
1689 FETCH_DECODE_MODRM(mod, rh, rl);
1690 switch (mod) {
1691 case 0:
8bde7f77
WD
1692 destreg = DECODE_RM_LONG_REGISTER(rh);
1693 DECODE_PRINTF(",");
1694 srcoffset = decode_rm00_address(rl);
1695 srcval = fetch_data_word(srcoffset);
1696 DECODE_PRINTF("\n");
1697 TRACE_AND_STEP();
1698 *destreg = srcval;
1699 break;
c7de829c 1700 case 1:
8bde7f77
WD
1701 destreg = DECODE_RM_LONG_REGISTER(rh);
1702 DECODE_PRINTF(",");
1703 srcoffset = decode_rm01_address(rl);
1704 srcval = fetch_data_word(srcoffset);
1705 DECODE_PRINTF("\n");
1706 TRACE_AND_STEP();
1707 *destreg = srcval;
1708 break;
c7de829c 1709 case 2:
8bde7f77
WD
1710 destreg = DECODE_RM_LONG_REGISTER(rh);
1711 DECODE_PRINTF(",");
1712 srcoffset = decode_rm10_address(rl);
1713 srcval = fetch_data_word(srcoffset);
1714 DECODE_PRINTF("\n");
1715 TRACE_AND_STEP();
1716 *destreg = srcval;
1717 break;
c7de829c 1718 case 3: /* register to register */
8bde7f77
WD
1719 destreg = DECODE_RM_LONG_REGISTER(rh);
1720 DECODE_PRINTF(",");
1721 srcreg = DECODE_RM_WORD_REGISTER(rl);
1722 DECODE_PRINTF("\n");
1723 TRACE_AND_STEP();
1724 *destreg = *srcreg;
1725 break;
c7de829c
WD
1726 }
1727 DECODE_CLEAR_SEGOVR();
1728 END_OF_INSTR();
1729}
1730
1731/****************************************************************************
1732REMARKS:
1733Handles opcode 0x0f,0xba
1734****************************************************************************/
1735void x86emuOp2_btX_I(u8 X86EMU_UNUSED(op2))
1736{
1737 int mod, rl, rh;
1738 uint srcoffset;
1739 int bit;
1740
1741 START_OF_INSTR();
1742 FETCH_DECODE_MODRM(mod, rh, rl);
1743 switch (rh) {
1744 case 3:
8bde7f77
WD
1745 DECODE_PRINTF("BT\t");
1746 break;
c7de829c 1747 case 4:
8bde7f77
WD
1748 DECODE_PRINTF("BTS\t");
1749 break;
c7de829c 1750 case 5:
8bde7f77
WD
1751 DECODE_PRINTF("BTR\t");
1752 break;
c7de829c 1753 case 6:
8bde7f77
WD
1754 DECODE_PRINTF("BTC\t");
1755 break;
c7de829c 1756 default:
8bde7f77
WD
1757 DECODE_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n");
1758 TRACE_REGS();
1759 printk("%04x:%04x: %02X%02X ILLEGAL EXTENDED X86 OPCODE EXTENSION!\n",
1760 M.x86.R_CS, M.x86.R_IP-3,op2, (mod<<6)|(rh<<3)|rl);
1761 HALT_SYS();
c7de829c
WD
1762 }
1763 switch (mod) {
1764 case 0:
8bde7f77
WD
1765 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1766 u32 srcval, mask;
1767 u8 shift;
1768
1769 srcoffset = decode_rm00_address(rl);
1770 DECODE_PRINTF(",");
1771 shift = fetch_byte_imm();
1772 TRACE_AND_STEP();
1773 bit = shift & 0x1F;
1774 srcval = fetch_data_long(srcoffset);
1775 mask = (0x1 << bit);
1776 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1777 switch (rh) {
1778 case 4:
1779 store_data_long(srcoffset, srcval | mask);
1780 break;
1781 case 5:
1782 store_data_long(srcoffset, srcval & ~mask);
1783 break;
1784 case 6:
1785 store_data_long(srcoffset, srcval ^ mask);
1786 break;
1787 default:
1788 break;
1789 }
1790 } else {
1791 u16 srcval, mask;
1792 u8 shift;
1793
1794 srcoffset = decode_rm00_address(rl);
1795 DECODE_PRINTF(",");
1796 shift = fetch_byte_imm();
1797 TRACE_AND_STEP();
1798 bit = shift & 0xF;
1799 srcval = fetch_data_word(srcoffset);
1800 mask = (0x1 << bit);
1801 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1802 switch (rh) {
1803 case 4:
1804 store_data_word(srcoffset, srcval | mask);
1805 break;
1806 case 5:
1807 store_data_word(srcoffset, srcval & ~mask);
1808 break;
1809 case 6:
1810 store_data_word(srcoffset, srcval ^ mask);
1811 break;
1812 default:
1813 break;
1814 }
1815 }
1816 break;
c7de829c 1817 case 1:
8bde7f77
WD
1818 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1819 u32 srcval, mask;
1820 u8 shift;
1821
1822 srcoffset = decode_rm01_address(rl);
1823 DECODE_PRINTF(",");
1824 shift = fetch_byte_imm();
1825 TRACE_AND_STEP();
1826 bit = shift & 0x1F;
1827 srcval = fetch_data_long(srcoffset);
1828 mask = (0x1 << bit);
1829 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1830 switch (rh) {
1831 case 4:
1832 store_data_long(srcoffset, srcval | mask);
1833 break;
1834 case 5:
1835 store_data_long(srcoffset, srcval & ~mask);
1836 break;
1837 case 6:
1838 store_data_long(srcoffset, srcval ^ mask);
1839 break;
1840 default:
1841 break;
1842 }
1843 } else {
1844 u16 srcval, mask;
1845 u8 shift;
1846
1847 srcoffset = decode_rm01_address(rl);
1848 DECODE_PRINTF(",");
1849 shift = fetch_byte_imm();
1850 TRACE_AND_STEP();
1851 bit = shift & 0xF;
1852 srcval = fetch_data_word(srcoffset);
1853 mask = (0x1 << bit);
1854 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1855 switch (rh) {
1856 case 4:
1857 store_data_word(srcoffset, srcval | mask);
1858 break;
1859 case 5:
1860 store_data_word(srcoffset, srcval & ~mask);
1861 break;
1862 case 6:
1863 store_data_word(srcoffset, srcval ^ mask);
1864 break;
1865 default:
1866 break;
1867 }
1868 }
1869 break;
c7de829c 1870 case 2:
8bde7f77
WD
1871 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1872 u32 srcval, mask;
1873 u8 shift;
1874
1875 srcoffset = decode_rm10_address(rl);
1876 DECODE_PRINTF(",");
1877 shift = fetch_byte_imm();
1878 TRACE_AND_STEP();
1879 bit = shift & 0x1F;
1880 srcval = fetch_data_long(srcoffset);
1881 mask = (0x1 << bit);
1882 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1883 switch (rh) {
1884 case 4:
1885 store_data_long(srcoffset, srcval | mask);
1886 break;
1887 case 5:
1888 store_data_long(srcoffset, srcval & ~mask);
1889 break;
1890 case 6:
1891 store_data_long(srcoffset, srcval ^ mask);
1892 break;
1893 default:
1894 break;
1895 }
1896 } else {
1897 u16 srcval, mask;
1898 u8 shift;
1899
1900 srcoffset = decode_rm10_address(rl);
1901 DECODE_PRINTF(",");
1902 shift = fetch_byte_imm();
1903 TRACE_AND_STEP();
1904 bit = shift & 0xF;
1905 srcval = fetch_data_word(srcoffset);
1906 mask = (0x1 << bit);
1907 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
1908 switch (rh) {
1909 case 4:
1910 store_data_word(srcoffset, srcval | mask);
1911 break;
1912 case 5:
1913 store_data_word(srcoffset, srcval & ~mask);
1914 break;
1915 case 6:
1916 store_data_word(srcoffset, srcval ^ mask);
1917 break;
1918 default:
1919 break;
1920 }
1921 }
1922 break;
c7de829c 1923 case 3: /* register to register */
8bde7f77
WD
1924 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1925 u32 *srcreg;
1926 u32 mask;
1927 u8 shift;
1928
1929 srcreg = DECODE_RM_LONG_REGISTER(rl);
1930 DECODE_PRINTF(",");
1931 shift = fetch_byte_imm();
1932 TRACE_AND_STEP();
1933 bit = shift & 0x1F;
1934 mask = (0x1 << bit);
1935 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1936 switch (rh) {
1937 case 4:
1938 *srcreg |= mask;
1939 break;
1940 case 5:
1941 *srcreg &= ~mask;
1942 break;
1943 case 6:
1944 *srcreg ^= mask;
1945 break;
1946 default:
1947 break;
1948 }
1949 } else {
1950 u16 *srcreg;
1951 u16 mask;
1952 u8 shift;
1953
1954 srcreg = DECODE_RM_WORD_REGISTER(rl);
1955 DECODE_PRINTF(",");
1956 shift = fetch_byte_imm();
1957 TRACE_AND_STEP();
1958 bit = shift & 0xF;
1959 mask = (0x1 << bit);
1960 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
1961 switch (rh) {
1962 case 4:
1963 *srcreg |= mask;
1964 break;
1965 case 5:
1966 *srcreg &= ~mask;
1967 break;
1968 case 6:
1969 *srcreg ^= mask;
1970 break;
1971 default:
1972 break;
1973 }
1974 }
1975 break;
c7de829c
WD
1976 }
1977 DECODE_CLEAR_SEGOVR();
1978 END_OF_INSTR();
1979}
1980
1981/****************************************************************************
1982REMARKS:
1983Handles opcode 0x0f,0xbb
1984****************************************************************************/
1985void x86emuOp2_btc_R(u8 X86EMU_UNUSED(op2))
1986{
1987 int mod, rl, rh;
1988 uint srcoffset;
1989 int bit,disp;
1990
1991 START_OF_INSTR();
1992 DECODE_PRINTF("BTC\t");
1993 FETCH_DECODE_MODRM(mod, rh, rl);
1994 switch (mod) {
1995 case 0:
8bde7f77
WD
1996 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1997 u32 srcval,mask;
1998 u32 *shiftreg;
1999
2000 srcoffset = decode_rm00_address(rl);
2001 DECODE_PRINTF(",");
2002 shiftreg = DECODE_RM_LONG_REGISTER(rh);
2003 TRACE_AND_STEP();
2004 bit = *shiftreg & 0x1F;
2005 disp = (s16)*shiftreg >> 5;
2006 srcval = fetch_data_long(srcoffset+disp);
2007 mask = (0x1 << bit);
2008 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
2009 store_data_long(srcoffset+disp, srcval ^ mask);
2010 } else {
2011 u16 srcval,mask;
2012 u16 *shiftreg;
2013
2014 srcoffset = decode_rm00_address(rl);
2015 DECODE_PRINTF(",");
2016 shiftreg = DECODE_RM_WORD_REGISTER(rh);
2017 TRACE_AND_STEP();
2018 bit = *shiftreg & 0xF;
2019 disp = (s16)*shiftreg >> 4;
2020 srcval = fetch_data_word(srcoffset+disp);
c7de829c 2021 mask = (u16)(0x1 << bit);
8bde7f77 2022 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
c7de829c 2023 store_data_word(srcoffset+disp, (u16)(srcval ^ mask));
8bde7f77
WD
2024 }
2025 break;
c7de829c 2026 case 1:
8bde7f77
WD
2027 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2028 u32 srcval,mask;
2029 u32 *shiftreg;
2030
2031 srcoffset = decode_rm01_address(rl);
2032 DECODE_PRINTF(",");
2033 shiftreg = DECODE_RM_LONG_REGISTER(rh);
2034 TRACE_AND_STEP();
2035 bit = *shiftreg & 0x1F;
2036 disp = (s16)*shiftreg >> 5;
2037 srcval = fetch_data_long(srcoffset+disp);
2038 mask = (0x1 << bit);
2039 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
2040 store_data_long(srcoffset+disp, srcval ^ mask);
2041 } else {
2042 u16 srcval,mask;
2043 u16 *shiftreg;
2044
2045 srcoffset = decode_rm01_address(rl);
2046 DECODE_PRINTF(",");
2047 shiftreg = DECODE_RM_WORD_REGISTER(rh);
2048 TRACE_AND_STEP();
2049 bit = *shiftreg & 0xF;
2050 disp = (s16)*shiftreg >> 4;
2051 srcval = fetch_data_word(srcoffset+disp);
c7de829c
WD
2052 mask = (u16)(0x1 << bit);
2053 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
2054 store_data_word(srcoffset+disp, (u16)(srcval ^ mask));
8bde7f77
WD
2055 }
2056 break;
c7de829c 2057 case 2:
8bde7f77
WD
2058 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2059 u32 srcval,mask;
2060 u32 *shiftreg;
2061
2062 srcoffset = decode_rm10_address(rl);
2063 DECODE_PRINTF(",");
2064 shiftreg = DECODE_RM_LONG_REGISTER(rh);
2065 TRACE_AND_STEP();
2066 bit = *shiftreg & 0x1F;
2067 disp = (s16)*shiftreg >> 5;
2068 srcval = fetch_data_long(srcoffset+disp);
2069 mask = (0x1 << bit);
2070 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
2071 store_data_long(srcoffset+disp, srcval ^ mask);
2072 } else {
2073 u16 srcval,mask;
2074 u16 *shiftreg;
2075
2076 srcoffset = decode_rm10_address(rl);
2077 DECODE_PRINTF(",");
2078 shiftreg = DECODE_RM_WORD_REGISTER(rh);
2079 TRACE_AND_STEP();
2080 bit = *shiftreg & 0xF;
2081 disp = (s16)*shiftreg >> 4;
2082 srcval = fetch_data_word(srcoffset+disp);
c7de829c
WD
2083 mask = (u16)(0x1 << bit);
2084 CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
2085 store_data_word(srcoffset+disp, (u16)(srcval ^ mask));
8bde7f77
WD
2086 }
2087 break;
c7de829c 2088 case 3: /* register to register */
8bde7f77 2089 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
c7de829c 2090 u32 *srcreg,*shiftreg;
8bde7f77
WD
2091 u32 mask;
2092
2093 srcreg = DECODE_RM_LONG_REGISTER(rl);
2094 DECODE_PRINTF(",");
2095 shiftreg = DECODE_RM_LONG_REGISTER(rh);
2096 TRACE_AND_STEP();
2097 bit = *shiftreg & 0x1F;
2098 mask = (0x1 << bit);
c7de829c
WD
2099 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
2100 *srcreg ^= mask;
2101 } else {
2102 u16 *srcreg,*shiftreg;
2103 u16 mask;
2104
2105 srcreg = DECODE_RM_WORD_REGISTER(rl);
2106 DECODE_PRINTF(",");
2107 shiftreg = DECODE_RM_WORD_REGISTER(rh);
2108 TRACE_AND_STEP();
2109 bit = *shiftreg & 0xF;
2110 mask = (u16)(0x1 << bit);
8bde7f77
WD
2111 CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
2112 *srcreg ^= mask;
2113 }
2114 break;
c7de829c
WD
2115 }
2116 DECODE_CLEAR_SEGOVR();
2117 END_OF_INSTR();
2118}
2119
2120/****************************************************************************
2121REMARKS:
2122Handles opcode 0x0f,0xbc
2123****************************************************************************/
2124void x86emuOp2_bsf(u8 X86EMU_UNUSED(op2))
2125{
2126 int mod, rl, rh;
2127 uint srcoffset;
2128
2129 START_OF_INSTR();
2130 DECODE_PRINTF("BSF\n");
2131 FETCH_DECODE_MODRM(mod, rh, rl);
2132 switch(mod) {
2133 case 0:
2134 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2135 u32 srcval, *dstreg;
2136
2137 srcoffset = decode_rm00_address(rl);
2138 DECODE_PRINTF(",");
2139 dstreg = DECODE_RM_LONG_REGISTER(rh);
2140 TRACE_AND_STEP();
2141 srcval = fetch_data_long(srcoffset);
2142 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
2143 for(*dstreg = 0; *dstreg < 32; (*dstreg)++)
2144 if ((srcval >> *dstreg) & 1) break;
2145 } else {
2146 u16 srcval, *dstreg;
2147
2148 srcoffset = decode_rm00_address(rl);
2149 DECODE_PRINTF(",");
2150 dstreg = DECODE_RM_WORD_REGISTER(rh);
2151 TRACE_AND_STEP();
2152 srcval = fetch_data_word(srcoffset);
2153 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
2154 for(*dstreg = 0; *dstreg < 16; (*dstreg)++)
2155 if ((srcval >> *dstreg) & 1) break;
2156 }
2157 break;
2158 case 1:
2159 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2160 u32 srcval, *dstreg;
2161
2162 srcoffset = decode_rm01_address(rl);
2163 DECODE_PRINTF(",");
2164 dstreg = DECODE_RM_LONG_REGISTER(rh);
2165 TRACE_AND_STEP();
2166 srcval = fetch_data_long(srcoffset);
2167 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
2168 for(*dstreg = 0; *dstreg < 32; (*dstreg)++)
2169 if ((srcval >> *dstreg) & 1) break;
2170 } else {
2171 u16 srcval, *dstreg;
2172
2173 srcoffset = decode_rm01_address(rl);
2174 DECODE_PRINTF(",");
2175 dstreg = DECODE_RM_WORD_REGISTER(rh);
2176 TRACE_AND_STEP();
2177 srcval = fetch_data_word(srcoffset);
2178 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
2179 for(*dstreg = 0; *dstreg < 16; (*dstreg)++)
2180 if ((srcval >> *dstreg) & 1) break;
2181 }
2182 break;
2183 case 2:
2184 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2185 u32 srcval, *dstreg;
2186
2187 srcoffset = decode_rm10_address(rl);
2188 DECODE_PRINTF(",");
2189 dstreg = DECODE_RM_LONG_REGISTER(rh);
2190 TRACE_AND_STEP();
2191 srcval = fetch_data_long(srcoffset);
2192 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
2193 for(*dstreg = 0; *dstreg < 32; (*dstreg)++)
2194 if ((srcval >> *dstreg) & 1) break;
2195 } else {
2196 u16 srcval, *dstreg;
2197
2198 srcoffset = decode_rm10_address(rl);
2199 DECODE_PRINTF(",");
2200 dstreg = DECODE_RM_WORD_REGISTER(rh);
2201 TRACE_AND_STEP();
2202 srcval = fetch_data_word(srcoffset);
2203 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
2204 for(*dstreg = 0; *dstreg < 16; (*dstreg)++)
2205 if ((srcval >> *dstreg) & 1) break;
2206 }
2207 break;
2208 case 3: /* register to register */
2209 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2210 u32 *srcreg, *dstreg;
2211
2212 srcreg = DECODE_RM_LONG_REGISTER(rl);
2213 DECODE_PRINTF(",");
2214 dstreg = DECODE_RM_LONG_REGISTER(rh);
2215 TRACE_AND_STEP();
2216 CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF);
2217 for(*dstreg = 0; *dstreg < 32; (*dstreg)++)
2218 if ((*srcreg >> *dstreg) & 1) break;
2219 } else {
2220 u16 *srcreg, *dstreg;
2221
2222 srcreg = DECODE_RM_WORD_REGISTER(rl);
2223 DECODE_PRINTF(",");
2224 dstreg = DECODE_RM_WORD_REGISTER(rh);
2225 TRACE_AND_STEP();
2226 CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF);
2227 for(*dstreg = 0; *dstreg < 16; (*dstreg)++)
2228 if ((*srcreg >> *dstreg) & 1) break;
2229 }
2230 break;
2231 }
2232 DECODE_CLEAR_SEGOVR();
2233 END_OF_INSTR();
2234}
2235
2236/****************************************************************************
2237REMARKS:
2238Handles opcode 0x0f,0xbd
2239****************************************************************************/
2240void x86emuOp2_bsr(u8 X86EMU_UNUSED(op2))
2241{
2242 int mod, rl, rh;
2243 uint srcoffset;
2244
2245 START_OF_INSTR();
2246 DECODE_PRINTF("BSF\n");
2247 FETCH_DECODE_MODRM(mod, rh, rl);
2248 switch(mod) {
2249 case 0:
2250 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2251 u32 srcval, *dstreg;
2252
2253 srcoffset = decode_rm00_address(rl);
2254 DECODE_PRINTF(",");
2255 dstreg = DECODE_RM_LONG_REGISTER(rh);
2256 TRACE_AND_STEP();
2257 srcval = fetch_data_long(srcoffset);
2258 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
2259 for(*dstreg = 31; *dstreg > 0; (*dstreg)--)
2260 if ((srcval >> *dstreg) & 1) break;
2261 } else {
2262 u16 srcval, *dstreg;
2263
2264 srcoffset = decode_rm00_address(rl);
2265 DECODE_PRINTF(",");
2266 dstreg = DECODE_RM_WORD_REGISTER(rh);
2267 TRACE_AND_STEP();
2268 srcval = fetch_data_word(srcoffset);
2269 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
2270 for(*dstreg = 15; *dstreg > 0; (*dstreg)--)
2271 if ((srcval >> *dstreg) & 1) break;
2272 }
2273 break;
2274 case 1:
2275 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2276 u32 srcval, *dstreg;
2277
2278 srcoffset = decode_rm01_address(rl);
2279 DECODE_PRINTF(",");
2280 dstreg = DECODE_RM_LONG_REGISTER(rh);
2281 TRACE_AND_STEP();
2282 srcval = fetch_data_long(srcoffset);
2283 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
2284 for(*dstreg = 31; *dstreg > 0; (*dstreg)--)
2285 if ((srcval >> *dstreg) & 1) break;
2286 } else {
2287 u16 srcval, *dstreg;
2288
2289 srcoffset = decode_rm01_address(rl);
2290 DECODE_PRINTF(",");
2291 dstreg = DECODE_RM_WORD_REGISTER(rh);
2292 TRACE_AND_STEP();
2293 srcval = fetch_data_word(srcoffset);
2294 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
2295 for(*dstreg = 15; *dstreg > 0; (*dstreg)--)
2296 if ((srcval >> *dstreg) & 1) break;
2297 }
2298 break;
2299 case 2:
2300 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2301 u32 srcval, *dstreg;
2302
2303 srcoffset = decode_rm10_address(rl);
2304 DECODE_PRINTF(",");
2305 dstreg = DECODE_RM_LONG_REGISTER(rh);
2306 TRACE_AND_STEP();
2307 srcval = fetch_data_long(srcoffset);
2308 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
2309 for(*dstreg = 31; *dstreg > 0; (*dstreg)--)
2310 if ((srcval >> *dstreg) & 1) break;
2311 } else {
2312 u16 srcval, *dstreg;
2313
2314 srcoffset = decode_rm10_address(rl);
2315 DECODE_PRINTF(",");
2316 dstreg = DECODE_RM_WORD_REGISTER(rh);
2317 TRACE_AND_STEP();
2318 srcval = fetch_data_word(srcoffset);
2319 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
2320 for(*dstreg = 15; *dstreg > 0; (*dstreg)--)
2321 if ((srcval >> *dstreg) & 1) break;
2322 }
2323 break;
2324 case 3: /* register to register */
2325 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2326 u32 *srcreg, *dstreg;
2327
2328 srcreg = DECODE_RM_LONG_REGISTER(rl);
2329 DECODE_PRINTF(",");
2330 dstreg = DECODE_RM_LONG_REGISTER(rh);
2331 TRACE_AND_STEP();
2332 CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF);
2333 for(*dstreg = 31; *dstreg > 0; (*dstreg)--)
2334 if ((*srcreg >> *dstreg) & 1) break;
2335 } else {
2336 u16 *srcreg, *dstreg;
2337
2338 srcreg = DECODE_RM_WORD_REGISTER(rl);
2339 DECODE_PRINTF(",");
2340 dstreg = DECODE_RM_WORD_REGISTER(rh);
2341 TRACE_AND_STEP();
2342 CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF);
2343 for(*dstreg = 15; *dstreg > 0; (*dstreg)--)
2344 if ((*srcreg >> *dstreg) & 1) break;
2345 }
2346 break;
2347 }
2348 DECODE_CLEAR_SEGOVR();
2349 END_OF_INSTR();
2350}
2351
2352/****************************************************************************
2353REMARKS:
2354Handles opcode 0x0f,0xbe
2355****************************************************************************/
2356void x86emuOp2_movsx_byte_R_RM(u8 X86EMU_UNUSED(op2))
2357{
2358 int mod, rl, rh;
2359 uint srcoffset;
2360
2361 START_OF_INSTR();
2362 DECODE_PRINTF("MOVSX\t");
2363 FETCH_DECODE_MODRM(mod, rh, rl);
2364 switch (mod) {
2365 case 0:
8bde7f77
WD
2366 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2367 u32 *destreg;
2368 u32 srcval;
2369
2370 destreg = DECODE_RM_LONG_REGISTER(rh);
2371 DECODE_PRINTF(",");
2372 srcoffset = decode_rm00_address(rl);
2373 srcval = (s32)((s8)fetch_data_byte(srcoffset));
2374 DECODE_PRINTF("\n");
2375 TRACE_AND_STEP();
2376 *destreg = srcval;
2377 } else {
2378 u16 *destreg;
2379 u16 srcval;
2380
2381 destreg = DECODE_RM_WORD_REGISTER(rh);
2382 DECODE_PRINTF(",");
2383 srcoffset = decode_rm00_address(rl);
2384 srcval = (s16)((s8)fetch_data_byte(srcoffset));
2385 DECODE_PRINTF("\n");
2386 TRACE_AND_STEP();
2387 *destreg = srcval;
2388 }
2389 break;
c7de829c 2390 case 1:
8bde7f77
WD
2391 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2392 u32 *destreg;
2393 u32 srcval;
2394
2395 destreg = DECODE_RM_LONG_REGISTER(rh);
2396 DECODE_PRINTF(",");
2397 srcoffset = decode_rm01_address(rl);
2398 srcval = (s32)((s8)fetch_data_byte(srcoffset));
2399 DECODE_PRINTF("\n");
2400 TRACE_AND_STEP();
2401 *destreg = srcval;
2402 } else {
2403 u16 *destreg;
2404 u16 srcval;
2405
2406 destreg = DECODE_RM_WORD_REGISTER(rh);
2407 DECODE_PRINTF(",");
2408 srcoffset = decode_rm01_address(rl);
2409 srcval = (s16)((s8)fetch_data_byte(srcoffset));
2410 DECODE_PRINTF("\n");
2411 TRACE_AND_STEP();
2412 *destreg = srcval;
2413 }
2414 break;
c7de829c 2415 case 2:
8bde7f77
WD
2416 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2417 u32 *destreg;
2418 u32 srcval;
2419
2420 destreg = DECODE_RM_LONG_REGISTER(rh);
2421 DECODE_PRINTF(",");
2422 srcoffset = decode_rm10_address(rl);
2423 srcval = (s32)((s8)fetch_data_byte(srcoffset));
2424 DECODE_PRINTF("\n");
2425 TRACE_AND_STEP();
2426 *destreg = srcval;
2427 } else {
2428 u16 *destreg;
2429 u16 srcval;
2430
2431 destreg = DECODE_RM_WORD_REGISTER(rh);
2432 DECODE_PRINTF(",");
2433 srcoffset = decode_rm10_address(rl);
2434 srcval = (s16)((s8)fetch_data_byte(srcoffset));
2435 DECODE_PRINTF("\n");
2436 TRACE_AND_STEP();
2437 *destreg = srcval;
2438 }
2439 break;
c7de829c 2440 case 3: /* register to register */
8bde7f77
WD
2441 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2442 u32 *destreg;
2443 u8 *srcreg;
2444
2445 destreg = DECODE_RM_LONG_REGISTER(rh);
2446 DECODE_PRINTF(",");
2447 srcreg = DECODE_RM_BYTE_REGISTER(rl);
2448 DECODE_PRINTF("\n");
2449 TRACE_AND_STEP();
2450 *destreg = (s32)((s8)*srcreg);
2451 } else {
2452 u16 *destreg;
2453 u8 *srcreg;
2454
2455 destreg = DECODE_RM_WORD_REGISTER(rh);
2456 DECODE_PRINTF(",");
2457 srcreg = DECODE_RM_BYTE_REGISTER(rl);
2458 DECODE_PRINTF("\n");
2459 TRACE_AND_STEP();
2460 *destreg = (s16)((s8)*srcreg);
2461 }
2462 break;
c7de829c
WD
2463 }
2464 DECODE_CLEAR_SEGOVR();
2465 END_OF_INSTR();
2466}
2467
2468/****************************************************************************
2469REMARKS:
2470Handles opcode 0x0f,0xbf
2471****************************************************************************/
2472void x86emuOp2_movsx_word_R_RM(u8 X86EMU_UNUSED(op2))
2473{
2474 int mod, rl, rh;
2475 uint srcoffset;
2476 u32 *destreg;
2477 u32 srcval;
2478 u16 *srcreg;
2479
2480 START_OF_INSTR();
2481 DECODE_PRINTF("MOVSX\t");
2482 FETCH_DECODE_MODRM(mod, rh, rl);
2483 switch (mod) {
2484 case 0:
8bde7f77
WD
2485 destreg = DECODE_RM_LONG_REGISTER(rh);
2486 DECODE_PRINTF(",");
2487 srcoffset = decode_rm00_address(rl);
2488 srcval = (s32)((s16)fetch_data_word(srcoffset));
2489 DECODE_PRINTF("\n");
2490 TRACE_AND_STEP();
2491 *destreg = srcval;
2492 break;
c7de829c 2493 case 1:
8bde7f77
WD
2494 destreg = DECODE_RM_LONG_REGISTER(rh);
2495 DECODE_PRINTF(",");
2496 srcoffset = decode_rm01_address(rl);
2497 srcval = (s32)((s16)fetch_data_word(srcoffset));
2498 DECODE_PRINTF("\n");
2499 TRACE_AND_STEP();
2500 *destreg = srcval;
2501 break;
c7de829c 2502 case 2:
8bde7f77
WD
2503 destreg = DECODE_RM_LONG_REGISTER(rh);
2504 DECODE_PRINTF(",");
2505 srcoffset = decode_rm10_address(rl);
2506 srcval = (s32)((s16)fetch_data_word(srcoffset));
2507 DECODE_PRINTF("\n");
2508 TRACE_AND_STEP();
2509 *destreg = srcval;
2510 break;
c7de829c 2511 case 3: /* register to register */
8bde7f77
WD
2512 destreg = DECODE_RM_LONG_REGISTER(rh);
2513 DECODE_PRINTF(",");
2514 srcreg = DECODE_RM_WORD_REGISTER(rl);
2515 DECODE_PRINTF("\n");
2516 TRACE_AND_STEP();
2517 *destreg = (s32)((s16)*srcreg);
2518 break;
c7de829c
WD
2519 }
2520 DECODE_CLEAR_SEGOVR();
2521 END_OF_INSTR();
2522}
2523
2524/***************************************************************************
2525 * Double byte operation code table:
2526 **************************************************************************/
2527void (*x86emu_optab2[256])(u8) =
2528{
2529/* 0x00 */ x86emuOp2_illegal_op, /* Group F (ring 0 PM) */
2530/* 0x01 */ x86emuOp2_illegal_op, /* Group G (ring 0 PM) */
2531/* 0x02 */ x86emuOp2_illegal_op, /* lar (ring 0 PM) */
2532/* 0x03 */ x86emuOp2_illegal_op, /* lsl (ring 0 PM) */
2533/* 0x04 */ x86emuOp2_illegal_op,
2534/* 0x05 */ x86emuOp2_illegal_op, /* loadall (undocumented) */
2535/* 0x06 */ x86emuOp2_illegal_op, /* clts (ring 0 PM) */
2536/* 0x07 */ x86emuOp2_illegal_op, /* loadall (undocumented) */
2537/* 0x08 */ x86emuOp2_illegal_op, /* invd (ring 0 PM) */
2538/* 0x09 */ x86emuOp2_illegal_op, /* wbinvd (ring 0 PM) */
2539/* 0x0a */ x86emuOp2_illegal_op,
2540/* 0x0b */ x86emuOp2_illegal_op,
2541/* 0x0c */ x86emuOp2_illegal_op,
2542/* 0x0d */ x86emuOp2_illegal_op,
2543/* 0x0e */ x86emuOp2_illegal_op,
2544/* 0x0f */ x86emuOp2_illegal_op,
2545
2546/* 0x10 */ x86emuOp2_illegal_op,
2547/* 0x11 */ x86emuOp2_illegal_op,
2548/* 0x12 */ x86emuOp2_illegal_op,
2549/* 0x13 */ x86emuOp2_illegal_op,
2550/* 0x14 */ x86emuOp2_illegal_op,
2551/* 0x15 */ x86emuOp2_illegal_op,
2552/* 0x16 */ x86emuOp2_illegal_op,
2553/* 0x17 */ x86emuOp2_illegal_op,
2554/* 0x18 */ x86emuOp2_illegal_op,
2555/* 0x19 */ x86emuOp2_illegal_op,
2556/* 0x1a */ x86emuOp2_illegal_op,
2557/* 0x1b */ x86emuOp2_illegal_op,
2558/* 0x1c */ x86emuOp2_illegal_op,
2559/* 0x1d */ x86emuOp2_illegal_op,
2560/* 0x1e */ x86emuOp2_illegal_op,
2561/* 0x1f */ x86emuOp2_illegal_op,
2562
2563/* 0x20 */ x86emuOp2_illegal_op, /* mov reg32,creg (ring 0 PM) */
2564/* 0x21 */ x86emuOp2_illegal_op, /* mov reg32,dreg (ring 0 PM) */
2565/* 0x22 */ x86emuOp2_illegal_op, /* mov creg,reg32 (ring 0 PM) */
2566/* 0x23 */ x86emuOp2_illegal_op, /* mov dreg,reg32 (ring 0 PM) */
2567/* 0x24 */ x86emuOp2_illegal_op, /* mov reg32,treg (ring 0 PM) */
2568/* 0x25 */ x86emuOp2_illegal_op,
2569/* 0x26 */ x86emuOp2_illegal_op, /* mov treg,reg32 (ring 0 PM) */
2570/* 0x27 */ x86emuOp2_illegal_op,
2571/* 0x28 */ x86emuOp2_illegal_op,
2572/* 0x29 */ x86emuOp2_illegal_op,
2573/* 0x2a */ x86emuOp2_illegal_op,
2574/* 0x2b */ x86emuOp2_illegal_op,
2575/* 0x2c */ x86emuOp2_illegal_op,
2576/* 0x2d */ x86emuOp2_illegal_op,
2577/* 0x2e */ x86emuOp2_illegal_op,
2578/* 0x2f */ x86emuOp2_illegal_op,
2579
2580/* 0x30 */ x86emuOp2_illegal_op,
2581/* 0x31 */ x86emuOp2_illegal_op,
2582/* 0x32 */ x86emuOp2_illegal_op,
2583/* 0x33 */ x86emuOp2_illegal_op,
2584/* 0x34 */ x86emuOp2_illegal_op,
2585/* 0x35 */ x86emuOp2_illegal_op,
2586/* 0x36 */ x86emuOp2_illegal_op,
2587/* 0x37 */ x86emuOp2_illegal_op,
2588/* 0x38 */ x86emuOp2_illegal_op,
2589/* 0x39 */ x86emuOp2_illegal_op,
2590/* 0x3a */ x86emuOp2_illegal_op,
2591/* 0x3b */ x86emuOp2_illegal_op,
2592/* 0x3c */ x86emuOp2_illegal_op,
2593/* 0x3d */ x86emuOp2_illegal_op,
2594/* 0x3e */ x86emuOp2_illegal_op,
2595/* 0x3f */ x86emuOp2_illegal_op,
2596
2597/* 0x40 */ x86emuOp2_illegal_op,
2598/* 0x41 */ x86emuOp2_illegal_op,
2599/* 0x42 */ x86emuOp2_illegal_op,
2600/* 0x43 */ x86emuOp2_illegal_op,
2601/* 0x44 */ x86emuOp2_illegal_op,
2602/* 0x45 */ x86emuOp2_illegal_op,
2603/* 0x46 */ x86emuOp2_illegal_op,
2604/* 0x47 */ x86emuOp2_illegal_op,
2605/* 0x48 */ x86emuOp2_illegal_op,
2606/* 0x49 */ x86emuOp2_illegal_op,
2607/* 0x4a */ x86emuOp2_illegal_op,
2608/* 0x4b */ x86emuOp2_illegal_op,
2609/* 0x4c */ x86emuOp2_illegal_op,
2610/* 0x4d */ x86emuOp2_illegal_op,
2611/* 0x4e */ x86emuOp2_illegal_op,
2612/* 0x4f */ x86emuOp2_illegal_op,
2613
2614/* 0x50 */ x86emuOp2_illegal_op,
2615/* 0x51 */ x86emuOp2_illegal_op,
2616/* 0x52 */ x86emuOp2_illegal_op,
2617/* 0x53 */ x86emuOp2_illegal_op,
2618/* 0x54 */ x86emuOp2_illegal_op,
2619/* 0x55 */ x86emuOp2_illegal_op,
2620/* 0x56 */ x86emuOp2_illegal_op,
2621/* 0x57 */ x86emuOp2_illegal_op,
2622/* 0x58 */ x86emuOp2_illegal_op,
2623/* 0x59 */ x86emuOp2_illegal_op,
2624/* 0x5a */ x86emuOp2_illegal_op,
2625/* 0x5b */ x86emuOp2_illegal_op,
2626/* 0x5c */ x86emuOp2_illegal_op,
2627/* 0x5d */ x86emuOp2_illegal_op,
2628/* 0x5e */ x86emuOp2_illegal_op,
2629/* 0x5f */ x86emuOp2_illegal_op,
2630
2631/* 0x60 */ x86emuOp2_illegal_op,
2632/* 0x61 */ x86emuOp2_illegal_op,
2633/* 0x62 */ x86emuOp2_illegal_op,
2634/* 0x63 */ x86emuOp2_illegal_op,
2635/* 0x64 */ x86emuOp2_illegal_op,
2636/* 0x65 */ x86emuOp2_illegal_op,
2637/* 0x66 */ x86emuOp2_illegal_op,
2638/* 0x67 */ x86emuOp2_illegal_op,
2639/* 0x68 */ x86emuOp2_illegal_op,
2640/* 0x69 */ x86emuOp2_illegal_op,
2641/* 0x6a */ x86emuOp2_illegal_op,
2642/* 0x6b */ x86emuOp2_illegal_op,
2643/* 0x6c */ x86emuOp2_illegal_op,
2644/* 0x6d */ x86emuOp2_illegal_op,
2645/* 0x6e */ x86emuOp2_illegal_op,
2646/* 0x6f */ x86emuOp2_illegal_op,
2647
2648/* 0x70 */ x86emuOp2_illegal_op,
2649/* 0x71 */ x86emuOp2_illegal_op,
2650/* 0x72 */ x86emuOp2_illegal_op,
2651/* 0x73 */ x86emuOp2_illegal_op,
2652/* 0x74 */ x86emuOp2_illegal_op,
2653/* 0x75 */ x86emuOp2_illegal_op,
2654/* 0x76 */ x86emuOp2_illegal_op,
2655/* 0x77 */ x86emuOp2_illegal_op,
2656/* 0x78 */ x86emuOp2_illegal_op,
2657/* 0x79 */ x86emuOp2_illegal_op,
2658/* 0x7a */ x86emuOp2_illegal_op,
2659/* 0x7b */ x86emuOp2_illegal_op,
2660/* 0x7c */ x86emuOp2_illegal_op,
2661/* 0x7d */ x86emuOp2_illegal_op,
2662/* 0x7e */ x86emuOp2_illegal_op,
2663/* 0x7f */ x86emuOp2_illegal_op,
2664
2665/* 0x80 */ x86emuOp2_long_jump,
2666/* 0x81 */ x86emuOp2_long_jump,
2667/* 0x82 */ x86emuOp2_long_jump,
2668/* 0x83 */ x86emuOp2_long_jump,
2669/* 0x84 */ x86emuOp2_long_jump,
2670/* 0x85 */ x86emuOp2_long_jump,
2671/* 0x86 */ x86emuOp2_long_jump,
2672/* 0x87 */ x86emuOp2_long_jump,
2673/* 0x88 */ x86emuOp2_long_jump,
2674/* 0x89 */ x86emuOp2_long_jump,
2675/* 0x8a */ x86emuOp2_long_jump,
2676/* 0x8b */ x86emuOp2_long_jump,
2677/* 0x8c */ x86emuOp2_long_jump,
2678/* 0x8d */ x86emuOp2_long_jump,
2679/* 0x8e */ x86emuOp2_long_jump,
2680/* 0x8f */ x86emuOp2_long_jump,
2681
2682/* 0x90 */ x86emuOp2_set_byte,
2683/* 0x91 */ x86emuOp2_set_byte,
2684/* 0x92 */ x86emuOp2_set_byte,
2685/* 0x93 */ x86emuOp2_set_byte,
2686/* 0x94 */ x86emuOp2_set_byte,
2687/* 0x95 */ x86emuOp2_set_byte,
2688/* 0x96 */ x86emuOp2_set_byte,
2689/* 0x97 */ x86emuOp2_set_byte,
2690/* 0x98 */ x86emuOp2_set_byte,
2691/* 0x99 */ x86emuOp2_set_byte,
2692/* 0x9a */ x86emuOp2_set_byte,
2693/* 0x9b */ x86emuOp2_set_byte,
2694/* 0x9c */ x86emuOp2_set_byte,
2695/* 0x9d */ x86emuOp2_set_byte,
2696/* 0x9e */ x86emuOp2_set_byte,
2697/* 0x9f */ x86emuOp2_set_byte,
2698
2699/* 0xa0 */ x86emuOp2_push_FS,
2700/* 0xa1 */ x86emuOp2_pop_FS,
2701/* 0xa2 */ x86emuOp2_illegal_op,
2702/* 0xa3 */ x86emuOp2_bt_R,
2703/* 0xa4 */ x86emuOp2_shld_IMM,
2704/* 0xa5 */ x86emuOp2_shld_CL,
2705/* 0xa6 */ x86emuOp2_illegal_op,
2706/* 0xa7 */ x86emuOp2_illegal_op,
2707/* 0xa8 */ x86emuOp2_push_GS,
2708/* 0xa9 */ x86emuOp2_pop_GS,
2709/* 0xaa */ x86emuOp2_illegal_op,
2710/* 0xab */ x86emuOp2_bt_R,
2711/* 0xac */ x86emuOp2_shrd_IMM,
2712/* 0xad */ x86emuOp2_shrd_CL,
2713/* 0xae */ x86emuOp2_illegal_op,
2714/* 0xaf */ x86emuOp2_imul_R_RM,
2715
2716/* 0xb0 */ x86emuOp2_illegal_op, /* TODO: cmpxchg */
2717/* 0xb1 */ x86emuOp2_illegal_op, /* TODO: cmpxchg */
2718/* 0xb2 */ x86emuOp2_lss_R_IMM,
2719/* 0xb3 */ x86emuOp2_btr_R,
2720/* 0xb4 */ x86emuOp2_lfs_R_IMM,
2721/* 0xb5 */ x86emuOp2_lgs_R_IMM,
2722/* 0xb6 */ x86emuOp2_movzx_byte_R_RM,
2723/* 0xb7 */ x86emuOp2_movzx_word_R_RM,
2724/* 0xb8 */ x86emuOp2_illegal_op,
2725/* 0xb9 */ x86emuOp2_illegal_op,
2726/* 0xba */ x86emuOp2_btX_I,
2727/* 0xbb */ x86emuOp2_btc_R,
2728/* 0xbc */ x86emuOp2_bsf,
2729/* 0xbd */ x86emuOp2_bsr,
2730/* 0xbe */ x86emuOp2_movsx_byte_R_RM,
2731/* 0xbf */ x86emuOp2_movsx_word_R_RM,
2732
2733/* 0xc0 */ x86emuOp2_illegal_op, /* TODO: xadd */
2734/* 0xc1 */ x86emuOp2_illegal_op, /* TODO: xadd */
2735/* 0xc2 */ x86emuOp2_illegal_op,
2736/* 0xc3 */ x86emuOp2_illegal_op,
2737/* 0xc4 */ x86emuOp2_illegal_op,
2738/* 0xc5 */ x86emuOp2_illegal_op,
2739/* 0xc6 */ x86emuOp2_illegal_op,
2740/* 0xc7 */ x86emuOp2_illegal_op,
2741/* 0xc8 */ x86emuOp2_illegal_op, /* TODO: bswap */
2742/* 0xc9 */ x86emuOp2_illegal_op, /* TODO: bswap */
2743/* 0xca */ x86emuOp2_illegal_op, /* TODO: bswap */
2744/* 0xcb */ x86emuOp2_illegal_op, /* TODO: bswap */
2745/* 0xcc */ x86emuOp2_illegal_op, /* TODO: bswap */
2746/* 0xcd */ x86emuOp2_illegal_op, /* TODO: bswap */
2747/* 0xce */ x86emuOp2_illegal_op, /* TODO: bswap */
2748/* 0xcf */ x86emuOp2_illegal_op, /* TODO: bswap */
2749
2750/* 0xd0 */ x86emuOp2_illegal_op,
2751/* 0xd1 */ x86emuOp2_illegal_op,
2752/* 0xd2 */ x86emuOp2_illegal_op,
2753/* 0xd3 */ x86emuOp2_illegal_op,
2754/* 0xd4 */ x86emuOp2_illegal_op,
2755/* 0xd5 */ x86emuOp2_illegal_op,
2756/* 0xd6 */ x86emuOp2_illegal_op,
2757/* 0xd7 */ x86emuOp2_illegal_op,
2758/* 0xd8 */ x86emuOp2_illegal_op,
2759/* 0xd9 */ x86emuOp2_illegal_op,
2760/* 0xda */ x86emuOp2_illegal_op,
2761/* 0xdb */ x86emuOp2_illegal_op,
2762/* 0xdc */ x86emuOp2_illegal_op,
2763/* 0xdd */ x86emuOp2_illegal_op,
2764/* 0xde */ x86emuOp2_illegal_op,
2765/* 0xdf */ x86emuOp2_illegal_op,
2766
2767/* 0xe0 */ x86emuOp2_illegal_op,
2768/* 0xe1 */ x86emuOp2_illegal_op,
2769/* 0xe2 */ x86emuOp2_illegal_op,
2770/* 0xe3 */ x86emuOp2_illegal_op,
2771/* 0xe4 */ x86emuOp2_illegal_op,
2772/* 0xe5 */ x86emuOp2_illegal_op,
2773/* 0xe6 */ x86emuOp2_illegal_op,
2774/* 0xe7 */ x86emuOp2_illegal_op,
2775/* 0xe8 */ x86emuOp2_illegal_op,
2776/* 0xe9 */ x86emuOp2_illegal_op,
2777/* 0xea */ x86emuOp2_illegal_op,
2778/* 0xeb */ x86emuOp2_illegal_op,
2779/* 0xec */ x86emuOp2_illegal_op,
2780/* 0xed */ x86emuOp2_illegal_op,
2781/* 0xee */ x86emuOp2_illegal_op,
2782/* 0xef */ x86emuOp2_illegal_op,
2783
2784/* 0xf0 */ x86emuOp2_illegal_op,
2785/* 0xf1 */ x86emuOp2_illegal_op,
2786/* 0xf2 */ x86emuOp2_illegal_op,
2787/* 0xf3 */ x86emuOp2_illegal_op,
2788/* 0xf4 */ x86emuOp2_illegal_op,
2789/* 0xf5 */ x86emuOp2_illegal_op,
2790/* 0xf6 */ x86emuOp2_illegal_op,
2791/* 0xf7 */ x86emuOp2_illegal_op,
2792/* 0xf8 */ x86emuOp2_illegal_op,
2793/* 0xf9 */ x86emuOp2_illegal_op,
2794/* 0xfa */ x86emuOp2_illegal_op,
2795/* 0xfb */ x86emuOp2_illegal_op,
2796/* 0xfc */ x86emuOp2_illegal_op,
2797/* 0xfd */ x86emuOp2_illegal_op,
2798/* 0xfe */ x86emuOp2_illegal_op,
2799/* 0xff */ x86emuOp2_illegal_op,
2800};