ReactOS  0.4.14-dev-358-gbef841c
extraops.c
Go to the documentation of this file.
1 /*
2  * Fast486 386/486 CPU Emulation Library
3  * extraops.c
4  *
5  * Copyright (C) 2015 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  */
21 
22 /* INCLUDES *******************************************************************/
23 
24 #include <windef.h>
25 
26 // #define NDEBUG
27 #include <debug.h>
28 
29 #include <fast486.h>
30 #include "opcodes.h"
31 #include "common.h"
32 #include "opgroups.h"
33 #include "extraops.h"
34 
35 /* PUBLIC VARIABLES ***********************************************************/
36 
39 {
40  Fast486ExtOpcodeGroup0F00, /* 0x00 - 0x01 */
41  Fast486ExtOpcodeGroup0F01,
42  Fast486ExtOpcodeLar, /* 0x02 */
43  Fast486ExtOpcodeLsl, /* 0x03 */
44  Fast486ExtOpcodeInvalid, /* 0x04 - 0x05 */ // Invalid
45  Fast486ExtOpcodeInvalid, // Invalid
46  Fast486ExtOpcodeClts, /* 0x06 */
47  Fast486ExtOpcodeInvalid, /* 0x07 */ // Invalid
48  Fast486ExtOpcodeUnimplemented, // TODO: OPCODE 0x08 NOT IMPLEMENTED
49  Fast486ExtOpcodeUnimplemented, // TODO: OPCODE 0x09 NOT IMPLEMENTED
50  Fast486ExtOpcodeInvalid, /* 0x0A */ // Invalid
51  Fast486ExtOpcode0F0B, /* 0x0B */ // Reserved (UD2)
52  Fast486ExtOpcodeInvalid, /* 0x0C - 0x1F */ // Invalid
53  Fast486ExtOpcodeInvalid, // Invalid
54  Fast486ExtOpcodeInvalid, // Invalid
55  Fast486ExtOpcodeInvalid, // Invalid
56  Fast486ExtOpcodeInvalid, // Invalid
57  Fast486ExtOpcodeInvalid, // Invalid
58  Fast486ExtOpcodeInvalid, // Invalid
59  Fast486ExtOpcodeInvalid, // Invalid
60  Fast486ExtOpcodeInvalid, // Invalid
61  Fast486ExtOpcodeInvalid, // Invalid
62  Fast486ExtOpcodeInvalid, // Invalid
63  Fast486ExtOpcodeInvalid, // Invalid
64  Fast486ExtOpcodeInvalid, // Invalid
65  Fast486ExtOpcodeInvalid, // Invalid
66  Fast486ExtOpcodeInvalid, // Invalid
67  Fast486ExtOpcodeInvalid, // Invalid
68  Fast486ExtOpcodeInvalid, // Invalid
69  Fast486ExtOpcodeInvalid, // Invalid
70  Fast486ExtOpcodeInvalid, // Invalid
71  Fast486ExtOpcodeInvalid, // Invalid
72  Fast486ExtOpcodeStoreControlReg, /* 0x20 */
73  Fast486ExtOpcodeStoreDebugReg, /* 0x21 */
74  Fast486ExtOpcodeLoadControlReg, /* 0x22 */
75  Fast486ExtOpcodeLoadDebugReg, /* 0x23 */
76  Fast486ExtOpcodeUnimplemented, // TODO: OPCODE 0x24 NOT IMPLEMENTED
77  Fast486ExtOpcodeInvalid, /* 0x25 */ // Invalid
78  Fast486ExtOpcodeUnimplemented, // TODO: OPCODE 0x26 NOT IMPLEMENTED
79  Fast486ExtOpcodeInvalid, /* 0x27 - 0x7F */ // Invalid
80  Fast486ExtOpcodeInvalid, // Invalid
81  Fast486ExtOpcodeInvalid, // Invalid
82  Fast486ExtOpcodeInvalid, // Invalid
83  Fast486ExtOpcodeInvalid, // Invalid
84  Fast486ExtOpcodeInvalid, // Invalid
85  Fast486ExtOpcodeInvalid, // Invalid
86  Fast486ExtOpcodeInvalid, // Invalid
87  Fast486ExtOpcodeInvalid, // Invalid
88  Fast486ExtOpcodeInvalid, // Invalid
89  Fast486ExtOpcodeInvalid, // Invalid
90  Fast486ExtOpcodeInvalid, // Invalid
91  Fast486ExtOpcodeInvalid, // Invalid
92  Fast486ExtOpcodeInvalid, // Invalid
93  Fast486ExtOpcodeInvalid, // Invalid
94  Fast486ExtOpcodeInvalid, // Invalid
95  Fast486ExtOpcodeInvalid, // Invalid
96  Fast486ExtOpcodeInvalid, // Invalid
97  Fast486ExtOpcodeInvalid, // Invalid
98  Fast486ExtOpcodeInvalid, // Invalid
99  Fast486ExtOpcodeInvalid, // Invalid
100  Fast486ExtOpcodeInvalid, // Invalid
101  Fast486ExtOpcodeInvalid, // Invalid
102  Fast486ExtOpcodeInvalid, // Invalid
103  Fast486ExtOpcodeInvalid, // Invalid
104  Fast486ExtOpcodeInvalid, // Invalid
105  Fast486ExtOpcodeInvalid, // Invalid
106  Fast486ExtOpcodeInvalid, // Invalid
107  Fast486ExtOpcodeInvalid, // Invalid
108  Fast486ExtOpcodeInvalid, // Invalid
109  Fast486ExtOpcodeInvalid, // Invalid
110  Fast486ExtOpcodeInvalid, // Invalid
111  Fast486ExtOpcodeInvalid, // Invalid
112  Fast486ExtOpcodeInvalid, // Invalid
113  Fast486ExtOpcodeInvalid, // Invalid
114  Fast486ExtOpcodeInvalid, // Invalid
115  Fast486ExtOpcodeInvalid, // Invalid
116  Fast486ExtOpcodeInvalid, // Invalid
117  Fast486ExtOpcodeInvalid, // Invalid
118  Fast486ExtOpcodeInvalid, // Invalid
119  Fast486ExtOpcodeInvalid, // Invalid
120  Fast486ExtOpcodeInvalid, // Invalid
121  Fast486ExtOpcodeInvalid, // Invalid
122  Fast486ExtOpcodeInvalid, // Invalid
123  Fast486ExtOpcodeInvalid, // Invalid
124  Fast486ExtOpcodeInvalid, // Invalid
125  Fast486ExtOpcodeInvalid, // Invalid
126  Fast486ExtOpcodeInvalid, // Invalid
127  Fast486ExtOpcodeInvalid, // Invalid
128  Fast486ExtOpcodeInvalid, // Invalid
129  Fast486ExtOpcodeInvalid, // Invalid
130  Fast486ExtOpcodeInvalid, // Invalid
131  Fast486ExtOpcodeInvalid, // Invalid
132  Fast486ExtOpcodeInvalid, // Invalid
133  Fast486ExtOpcodeInvalid, // Invalid
134  Fast486ExtOpcodeInvalid, // Invalid
135  Fast486ExtOpcodeInvalid, // Invalid
136  Fast486ExtOpcodeInvalid, // Invalid
137  Fast486ExtOpcodeInvalid, // Invalid
138  Fast486ExtOpcodeInvalid, // Invalid
139  Fast486ExtOpcodeInvalid, // Invalid
140  Fast486ExtOpcodeInvalid, // Invalid
141  Fast486ExtOpcodeInvalid, // Invalid
142  Fast486ExtOpcodeInvalid, // Invalid
143  Fast486ExtOpcodeInvalid, // Invalid
144  Fast486ExtOpcodeInvalid, // Invalid
145  Fast486ExtOpcodeInvalid, // Invalid
146  Fast486ExtOpcodeInvalid, // Invalid
147  Fast486ExtOpcodeInvalid, // Invalid
148  Fast486ExtOpcodeInvalid, // Invalid
149  Fast486ExtOpcodeInvalid, // Invalid
150  Fast486ExtOpcodeInvalid, // Invalid
151  Fast486ExtOpcodeInvalid, // Invalid
152  Fast486ExtOpcodeInvalid, // Invalid
153  Fast486ExtOpcodeInvalid, // Invalid
154  Fast486ExtOpcodeInvalid, // Invalid
155  Fast486ExtOpcodeInvalid, // Invalid
156  Fast486ExtOpcodeInvalid, // Invalid
157  Fast486ExtOpcodeInvalid, // Invalid
158  Fast486ExtOpcodeInvalid, // Invalid
159  Fast486ExtOpcodeInvalid, // Invalid
160  Fast486ExtOpcodeInvalid, // Invalid
161  Fast486ExtOpcodeInvalid, // Invalid
162  Fast486ExtOpcodeInvalid, // Invalid
163  Fast486ExtOpcodeInvalid, // Invalid
164  Fast486ExtOpcodeInvalid, // Invalid
165  Fast486ExtOpcodeInvalid, // Invalid
166  Fast486ExtOpcodeInvalid, // Invalid
167  Fast486ExtOpcodeInvalid, // Invalid
168  Fast486ExtOpcodeConditionalJmp, /* 0x80 - 0x8F */
169  Fast486ExtOpcodeConditionalJmp,
170  Fast486ExtOpcodeConditionalJmp,
171  Fast486ExtOpcodeConditionalJmp,
172  Fast486ExtOpcodeConditionalJmp,
173  Fast486ExtOpcodeConditionalJmp,
174  Fast486ExtOpcodeConditionalJmp,
175  Fast486ExtOpcodeConditionalJmp,
176  Fast486ExtOpcodeConditionalJmp,
177  Fast486ExtOpcodeConditionalJmp,
178  Fast486ExtOpcodeConditionalJmp,
179  Fast486ExtOpcodeConditionalJmp,
180  Fast486ExtOpcodeConditionalJmp,
181  Fast486ExtOpcodeConditionalJmp,
182  Fast486ExtOpcodeConditionalJmp,
183  Fast486ExtOpcodeConditionalJmp,
184  Fast486ExtOpcodeConditionalSet, /* 0x90 - 0x9F */
185  Fast486ExtOpcodeConditionalSet,
186  Fast486ExtOpcodeConditionalSet,
187  Fast486ExtOpcodeConditionalSet,
188  Fast486ExtOpcodeConditionalSet,
189  Fast486ExtOpcodeConditionalSet,
190  Fast486ExtOpcodeConditionalSet,
191  Fast486ExtOpcodeConditionalSet,
192  Fast486ExtOpcodeConditionalSet,
193  Fast486ExtOpcodeConditionalSet,
194  Fast486ExtOpcodeConditionalSet,
195  Fast486ExtOpcodeConditionalSet,
196  Fast486ExtOpcodeConditionalSet,
197  Fast486ExtOpcodeConditionalSet,
198  Fast486ExtOpcodeConditionalSet,
199  Fast486ExtOpcodeConditionalSet,
200  Fast486ExtOpcodePushFs, /* 0xA0 */
201  Fast486ExtOpcodePopFs, /* 0xA1 */
202  Fast486ExtOpcodeInvalid, /* 0xA2 */ // Invalid
203  Fast486ExtOpcodeBitTest, /* 0xA3 */
204  Fast486ExtOpcodeShld, /* 0xA4 - 0xA5 */
205  Fast486ExtOpcodeShld,
206  Fast486ExtOpcodeInvalid, /* 0xA6 - 0xA7 */ // Invalid
207  Fast486ExtOpcodeInvalid, // Invalid
208  Fast486ExtOpcodePushGs, /* 0xA8 - 0xA9 */
209  Fast486ExtOpcodePopGs,
210  Fast486ExtOpcodeInvalid, /* 0xAA */ // Invalid
211  Fast486ExtOpcodeBts, /* 0xAB */
212  Fast486ExtOpcodeShrd, /* 0xAC - 0xAD */
213  Fast486ExtOpcodeShrd,
214  Fast486ExtOpcodeInvalid, /* 0xAE */ // Invalid
215  Fast486ExtOpcodeImul, /* 0xAF */
216  Fast486ExtOpcodeCmpXchgByte, /* 0xB0 */
217  Fast486ExtOpcodeCmpXchg, /* 0xB1 */
218  Fast486ExtOpcodeLss, /* 0xB2 */
219  Fast486ExtOpcodeBtr, /* 0xB3 */
220  Fast486ExtOpcodeLfsLgs, /* 0xB4 - 0xB5 */
221  Fast486ExtOpcodeLfsLgs,
222  Fast486ExtOpcodeMovzxByte, /* 0xB6 - 0xB7 */
223  Fast486ExtOpcodeMovzxWord,
224  Fast486ExtOpcodeInvalid, /* 0xB8 */ // Invalid
225  Fast486ExtOpcodeGroup0FB9, /* 0xB9 */
226  Fast486ExtOpcodeGroup0FBA, /* 0xBA */
227  Fast486ExtOpcodeBtc, /* 0xBB */
228  Fast486ExtOpcodeBsf, /* 0xBC */
229  Fast486ExtOpcodeBsr, /* 0xBD */
230  Fast486ExtOpcodeMovsxByte, /* 0xBE - 0xBF */
231  Fast486ExtOpcodeMovsxWord,
232  Fast486ExtOpcodeXaddByte, /* 0xC0 - 0xC1 */
233  Fast486ExtOpcodeXadd,
234  Fast486ExtOpcodeInvalid, /* 0xC2 - 0xC7 */ // Invalid
235  Fast486ExtOpcodeInvalid, // Invalid
236  Fast486ExtOpcodeInvalid, // Invalid
237  Fast486ExtOpcodeInvalid, // Invalid
238  Fast486ExtOpcodeInvalid, // Invalid
239  Fast486ExtOpcodeInvalid, // Invalid
240  Fast486ExtOpcodeBswap, /* 0xC8 - 0xCF */
241  Fast486ExtOpcodeBswap,
242  Fast486ExtOpcodeBswap,
243  Fast486ExtOpcodeBswap,
244  Fast486ExtOpcodeBswap,
245  Fast486ExtOpcodeBswap,
246  Fast486ExtOpcodeBswap,
247  Fast486ExtOpcodeBswap,
248  Fast486ExtOpcodeInvalid, /* 0xD0 - 0xFF */ // Invalid
249  Fast486ExtOpcodeInvalid, // Invalid
250  Fast486ExtOpcodeInvalid, // Invalid
251  Fast486ExtOpcodeInvalid, // Invalid
252  Fast486ExtOpcodeInvalid, // Invalid
253  Fast486ExtOpcodeInvalid, // Invalid
254  Fast486ExtOpcodeInvalid, // Invalid
255  Fast486ExtOpcodeInvalid, // Invalid
256  Fast486ExtOpcodeInvalid, // Invalid
257  Fast486ExtOpcodeInvalid, // Invalid
258  Fast486ExtOpcodeInvalid, // Invalid
259  Fast486ExtOpcodeInvalid, // Invalid
260  Fast486ExtOpcodeInvalid, // Invalid
261  Fast486ExtOpcodeInvalid, // Invalid
262  Fast486ExtOpcodeInvalid, // Invalid
263  Fast486ExtOpcodeInvalid, // Invalid
264  Fast486ExtOpcodeInvalid, // Invalid
265  Fast486ExtOpcodeInvalid, // Invalid
266  Fast486ExtOpcodeInvalid, // Invalid
267  Fast486ExtOpcodeInvalid, // Invalid
268  Fast486ExtOpcodeInvalid, // Invalid
269  Fast486ExtOpcodeInvalid, // Invalid
270  Fast486ExtOpcodeInvalid, // Invalid
271  Fast486ExtOpcodeInvalid, // Invalid
272  Fast486ExtOpcodeInvalid, // Invalid
273  Fast486ExtOpcodeInvalid, // Invalid
274  Fast486ExtOpcodeInvalid, // Invalid
275  Fast486ExtOpcodeInvalid, // Invalid
276  Fast486ExtOpcodeInvalid, // Invalid
277  Fast486ExtOpcodeInvalid, // Invalid
278  Fast486ExtOpcodeInvalid, // Invalid
279  Fast486ExtOpcodeInvalid, // Invalid
280  Fast486ExtOpcodeInvalid, // Invalid
281  Fast486ExtOpcodeInvalid, // Invalid
282  Fast486ExtOpcodeInvalid, // Invalid
283  Fast486ExtOpcodeInvalid, // Invalid
284  Fast486ExtOpcodeInvalid, // Invalid
285  Fast486ExtOpcodeInvalid, // Invalid
286  Fast486ExtOpcodeInvalid, // Invalid
287  Fast486ExtOpcodeInvalid, // Invalid
288  Fast486ExtOpcodeInvalid, // Invalid
289  Fast486ExtOpcodeInvalid, // Invalid
290  Fast486ExtOpcodeInvalid, // Invalid
291  Fast486ExtOpcodeInvalid, // Invalid
292  Fast486ExtOpcodeInvalid, // Invalid
293  Fast486ExtOpcodeInvalid, // Invalid
294  Fast486ExtOpcodeInvalid, // Invalid
295  Fast486ExtOpcodeInvalid, // Invalid
296 };
297 
298 /* PUBLIC FUNCTIONS ***********************************************************/
299 
300 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeInvalid)
301 {
302  DPRINT1("FAST486 -- Extended opcode 0x%02X is INVALID!\n", Opcode);
303  Fast486Exception(State, FAST486_EXCEPTION_UD);
304  return;
305 }
306 
307 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeUnimplemented)
308 {
309  DPRINT1("FAST486 -- Extended opcode 0x%02X is UNIMPLEMENTED\n", Opcode);
310  // Fast486Exception(State, FAST486_EXCEPTION_UD);
311 }
312 
313 FAST486_OPCODE_HANDLER(Fast486ExtOpcode0F0B)
314 {
315  /* Reserved opcode (UD2) */
316  Fast486Exception(State, FAST486_EXCEPTION_UD);
317 }
318 
319 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLar)
320 {
321  BOOLEAN OperandSize, AddressSize;
322  FAST486_MOD_REG_RM ModRegRm;
323  BOOLEAN Valid;
324  USHORT Selector;
325  FAST486_GDT_ENTRY GdtEntry;
326  DWORD AccessRights;
327 
328  OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
329 
330  if (!(State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
331  || State->Flags.Vm)
332  {
333  /* Not recognized */
334  Fast486Exception(State, FAST486_EXCEPTION_UD);
335  return;
336  }
337 
338  NO_LOCK_PREFIX();
339  TOGGLE_OPSIZE(OperandSize);
340  TOGGLE_ADSIZE(AddressSize);
341 
342  /* Get the operands */
343  if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
344  {
345  /* Exception occurred */
346  return;
347  }
348 
349  if (OperandSize)
350  {
351  ULONG Value;
352 
353  /* Read the value */
354  if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
355  {
356  /* Exception occurred */
357  return;
358  }
359 
360  Selector = LOWORD(Value);
361  }
362  else
363  {
364  /* Read the value */
365  if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Selector))
366  {
367  /* Exception occurred */
368  return;
369  }
370  }
371 
372  if (!Fast486ReadDescriptorEntry(State, Selector, &Valid, &GdtEntry))
373  {
374  /* Exception occurred */
375  return;
376  }
377 
378  if (!Valid)
379  {
380  State->Flags.Zf = FALSE;
381  return;
382  }
383 
384  /* Privilege check */
385  if (((GET_SEGMENT_RPL(Selector) > GdtEntry.Dpl))
386  || (Fast486GetCurrentPrivLevel(State) > GdtEntry.Dpl))
387  {
388  State->Flags.Zf = FALSE;
389  return;
390  }
391 
392  /* Set ZF */
393  State->Flags.Zf = TRUE;
394 
395  /* Get the access rights */
396  AccessRights = ((PDWORD)&GdtEntry)[1] & 0x00F0FF00;
397 
398  /* Return the access rights */
399  if (OperandSize) Fast486WriteModrmDwordOperands(State, &ModRegRm, TRUE, AccessRights);
400  else Fast486WriteModrmWordOperands(State, &ModRegRm, TRUE, LOWORD(AccessRights));
401 }
402 
403 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLsl)
404 {
405  BOOLEAN OperandSize, AddressSize;
406  FAST486_MOD_REG_RM ModRegRm;
407  BOOLEAN Valid;
408  USHORT Selector;
409  ULONG Limit;
410  FAST486_GDT_ENTRY GdtEntry;
411 
412  OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
413 
414  if (!(State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
415  || State->Flags.Vm)
416  {
417  /* Not recognized */
418  Fast486Exception(State, FAST486_EXCEPTION_UD);
419  return;
420  }
421 
422  NO_LOCK_PREFIX();
423  TOGGLE_OPSIZE(OperandSize);
424  TOGGLE_ADSIZE(AddressSize);
425 
426  /* Get the operands */
427  if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
428  {
429  /* Exception occurred */
430  return;
431  }
432 
433  if (OperandSize)
434  {
435  ULONG Value;
436 
437  /* Read the value */
438  if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
439  {
440  /* Exception occurred */
441  return;
442  }
443 
444  Selector = LOWORD(Value);
445  }
446  else
447  {
448  /* Read the value */
449  if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Selector))
450  {
451  /* Exception occurred */
452  return;
453  }
454  }
455 
456  if (!Fast486ReadDescriptorEntry(State, Selector, &Valid, &GdtEntry))
457  {
458  /* Exception occurred */
459  return;
460  }
461 
462  if (!Valid)
463  {
464  State->Flags.Zf = FALSE;
465  return;
466  }
467 
468  /* Privilege check */
469  if (((GET_SEGMENT_RPL(Selector) > GdtEntry.Dpl))
470  || (Fast486GetCurrentPrivLevel(State) > GdtEntry.Dpl))
471  {
472  State->Flags.Zf = FALSE;
473  return;
474  }
475 
476  /* Calculate the limit */
477  Limit = GdtEntry.Limit | (GdtEntry.LimitHigh << 16);
478 
479  if (GdtEntry.Granularity)
480  {
481  Limit <<= 12;
482  Limit |= 0x00000FFF;
483  }
484 
485  /* Set ZF */
486  State->Flags.Zf = TRUE;
487 
488  /* Return the limit */
489  if (OperandSize) Fast486WriteModrmDwordOperands(State, &ModRegRm, TRUE, Limit);
490  else Fast486WriteModrmWordOperands(State, &ModRegRm, TRUE, LOWORD(Limit));
491 }
492 
493 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeClts)
494 {
495  NO_LOCK_PREFIX();
496 
497  /* The current privilege level must be zero */
498  if (Fast486GetCurrentPrivLevel(State) != 0)
499  {
500  Fast486Exception(State, FAST486_EXCEPTION_GP);
501  return;
502  }
503 
504  /* Clear the task switch bit */
505  State->ControlRegisters[FAST486_REG_CR0] &= ~FAST486_CR0_TS;
506 }
507 
508 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeStoreControlReg)
509 {
510  BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
511  FAST486_MOD_REG_RM ModRegRm;
512 
513  NO_LOCK_PREFIX();
514  TOGGLE_ADSIZE(AddressSize);
515 
516  /* Get the operands */
517  if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
518  {
519  /* Exception occurred */
520  return;
521  }
522 
523  /* The current privilege level must be zero */
524  if (Fast486GetCurrentPrivLevel(State) != 0)
525  {
526  Fast486Exception(State, FAST486_EXCEPTION_GP);
527  return;
528  }
529 
530  if ((ModRegRm.Register == 1) || (ModRegRm.Register > 3))
531  {
532  /* CR1, CR4, CR5, CR6 and CR7 don't exist */
533  Fast486Exception(State, FAST486_EXCEPTION_UD);
534  return;
535  }
536 
537  if (ModRegRm.Register != 0)
538  {
539  /* CR2 and CR3 and are stored in array indexes 1 and 2 */
540  ModRegRm.Register--;
541  }
542 
543  /* Store the value of the control register */
544  State->GeneralRegs[ModRegRm.SecondRegister].Long = State->ControlRegisters[ModRegRm.Register];
545 }
546 
547 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeStoreDebugReg)
548 {
549  BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
550  FAST486_MOD_REG_RM ModRegRm;
551 
552  NO_LOCK_PREFIX();
553  TOGGLE_ADSIZE(AddressSize);
554 
555  /* Get the operands */
556  if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
557  {
558  /* Exception occurred */
559  return;
560  }
561 
562  /* The current privilege level must be zero */
563  if (Fast486GetCurrentPrivLevel(State) != 0)
564  {
565  Fast486Exception(State, FAST486_EXCEPTION_GP);
566  return;
567  }
568 
569  if ((ModRegRm.Register == 6) || (ModRegRm.Register == 7))
570  {
571  /* DR6 and DR7 are aliases to DR4 and DR5 */
572  ModRegRm.Register -= 2;
573  }
574 
575  if (State->DebugRegisters[FAST486_REG_DR5] & FAST486_DR5_GD)
576  {
577  /* Disallow access to debug registers */
578  Fast486Exception(State, FAST486_EXCEPTION_GP);
579  return;
580  }
581 
582  /* Store the value of the debug register */
583  State->GeneralRegs[ModRegRm.SecondRegister].Long = State->DebugRegisters[ModRegRm.Register];
584 }
585 
586 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLoadControlReg)
587 {
588  ULONG Value;
589  BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
590  FAST486_MOD_REG_RM ModRegRm;
591 
592  NO_LOCK_PREFIX();
593  TOGGLE_ADSIZE(AddressSize);
594 
595  /* Get the operands */
596  if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
597  {
598  /* Exception occurred */
599  return;
600  }
601 
602  /* The current privilege level must be zero */
603  if (Fast486GetCurrentPrivLevel(State) != 0)
604  {
605  Fast486Exception(State, FAST486_EXCEPTION_GP);
606  return;
607  }
608 
609  if ((ModRegRm.Register == 1) || (ModRegRm.Register > 3))
610  {
611  /* CR1, CR4, CR5, CR6 and CR7 don't exist */
612  Fast486Exception(State, FAST486_EXCEPTION_UD);
613  return;
614  }
615 
616  if (ModRegRm.Register != 0)
617  {
618  /* CR2 and CR3 and are stored in array indexes 1 and 2 */
619  ModRegRm.Register--;
620  }
621 
622  /* Get the value */
623  Value = State->GeneralRegs[ModRegRm.SecondRegister].Long;
624 
625  if (ModRegRm.Register == (INT)FAST486_REG_CR0)
626  {
627  /* CR0 checks */
628 
631  {
632  /* Invalid value */
633  Fast486Exception(State, FAST486_EXCEPTION_GP);
634  return;
635  }
636  }
637 
638 #ifndef FAST486_NO_PREFETCH
639  /* Changing CR0 or CR3 can interfere with prefetching (because of paging) */
640  State->PrefetchValid = FALSE;
641 #endif
642 
643  if (ModRegRm.Register == (INT)FAST486_REG_CR3)
644  {
645  /* Flush the TLB */
646  Fast486FlushTlb(State);
647  }
648 
649  /* Load a value to the control register */
650  State->ControlRegisters[ModRegRm.Register] = Value;
651 }
652 
653 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLoadDebugReg)
654 {
655  BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
656  FAST486_MOD_REG_RM ModRegRm;
657 
658  NO_LOCK_PREFIX();
659  TOGGLE_ADSIZE(AddressSize);
660 
661  /* Get the operands */
662  if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
663  {
664  /* Exception occurred */
665  return;
666  }
667 
668  /* The current privilege level must be zero */
669  if (Fast486GetCurrentPrivLevel(State) != 0)
670  {
671  Fast486Exception(State, FAST486_EXCEPTION_GP);
672  return;
673  }
674 
675  if ((ModRegRm.Register == 6) || (ModRegRm.Register == 7))
676  {
677  /* DR6 and DR7 are aliases to DR4 and DR5 */
678  ModRegRm.Register -= 2;
679  }
680 
681  if (State->DebugRegisters[FAST486_REG_DR5] & FAST486_DR5_GD)
682  {
683  /* Disallow access to debug registers */
684  Fast486Exception(State, FAST486_EXCEPTION_GP);
685  return;
686  }
687 
688  /* Load a value to the debug register */
689  State->DebugRegisters[ModRegRm.Register] = State->GeneralRegs[ModRegRm.SecondRegister].Long;
690 
691  if (ModRegRm.Register == (INT)FAST486_REG_DR4)
692  {
693  /* The reserved bits are 1 */
694  State->DebugRegisters[ModRegRm.Register] |= FAST486_DR4_RESERVED;
695  }
696  else if (ModRegRm.Register == (INT)FAST486_REG_DR5)
697  {
698  /* The reserved bits are 0 */
699  State->DebugRegisters[ModRegRm.Register] &= ~FAST486_DR5_RESERVED;
700  }
701 }
702 
703 FAST486_OPCODE_HANDLER(Fast486ExtOpcodePushFs)
704 {
705  /* Call the internal API */
706  Fast486StackPush(State, State->SegmentRegs[FAST486_REG_FS].Selector);
707 }
708 
709 FAST486_OPCODE_HANDLER(Fast486ExtOpcodePopFs)
710 {
711  ULONG NewSelector;
712 
713  if (!Fast486StackPop(State, &NewSelector))
714  {
715  /* Exception occurred */
716  return;
717  }
718 
719  /* Call the internal API */
720  Fast486LoadSegment(State, FAST486_REG_FS, LOWORD(NewSelector));
721 }
722 
723 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBitTest)
724 {
725  BOOLEAN OperandSize, AddressSize;
726  FAST486_MOD_REG_RM ModRegRm;
727  UINT DataSize;
728  ULONG BitNumber;
729 
730  OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
731  TOGGLE_OPSIZE(OperandSize);
732  TOGGLE_ADSIZE(AddressSize);
733 
734  /* Get the number of bits */
735  if (OperandSize) DataSize = 32;
736  else DataSize = 16;
737 
738  /* Get the operands */
739  if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
740  {
741  /* Exception occurred */
742  return;
743  }
744 
745  /* Get the bit number */
746  BitNumber = OperandSize ? State->GeneralRegs[ModRegRm.Register].Long
747  : (ULONG)State->GeneralRegs[ModRegRm.Register].LowWord;
748 
749  if (ModRegRm.Memory)
750  {
751  /*
752  * For memory operands, add the bit offset divided by
753  * the data size to the address
754  */
755  ModRegRm.MemoryAddress += (BitNumber / DataSize) * (DataSize / 8);
756  }
757 
758  /* Normalize the bit number */
759  BitNumber %= DataSize;
760 
761  if (OperandSize)
762  {
763  ULONG Value;
764 
765  /* Read the value */
766  if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
767  {
768  /* Exception occurred */
769  return;
770  }
771 
772  /* Set CF to the bit value */
773  State->Flags.Cf = (Value >> BitNumber) & 1;
774  }
775  else
776  {
777  USHORT Value;
778 
779  /* Read the value */
780  if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value))
781  {
782  /* Exception occurred */
783  return;
784  }
785 
786  /* Set CF to the bit value */
787  State->Flags.Cf = (Value >> BitNumber) & 1;
788  }
789 }
790 
791 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeShld)
792 {
793  BOOLEAN OperandSize, AddressSize;
794  FAST486_MOD_REG_RM ModRegRm;
795  UCHAR Count;
796 
797  OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
798  TOGGLE_OPSIZE(OperandSize);
799  TOGGLE_ADSIZE(AddressSize);
800 
801  /* Make sure this is the right instruction */
802  ASSERT((Opcode & 0xFE) == 0xA4);
803 
804  /* Get the operands */
805  if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
806  {
807  /* Exception occurred */
808  return;
809  }
810 
811  if (Opcode == 0xA4)
812  {
813  /* Fetch the count */
814  if (!Fast486FetchByte(State, &Count))
815  {
816  /* Exception occurred */
817  return;
818  }
819  }
820  else
821  {
822  /* The count is in CL */
823  Count = State->GeneralRegs[FAST486_REG_ECX].LowByte;
824  }
825 
826  /* Normalize the count */
827  Count &= 0x1F;
828 
829  /* Do nothing if the count is zero */
830  if (Count == 0) return;
831 
832  if (OperandSize)
833  {
835 
836  if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, &Source, &Destination))
837  {
838  /* Exception occurred */
839  return;
840  }
841 
842  /* Calculate the result */
843  Result = (Destination << Count) | (Source >> (32 - Count));
844 
845  /* Update flags */
846  State->Flags.Cf = (Destination >> (32 - Count)) & 1;
847  if (Count == 1) State->Flags.Of = (Result & SIGN_FLAG_LONG)
849  State->Flags.Zf = (Result == 0);
850  State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
851  State->Flags.Pf = Fast486CalculateParity(Result);
852 
853  /* Write back the result */
854  Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Result);
855  }
856  else
857  {
859  ULONG DoubleSource;
860 
861  if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Source, &Destination))
862  {
863  /* Exception occurred */
864  return;
865  }
866 
867  DoubleSource = Source | (Source << 16);
868 
869  /* Calculate the result */
870  Result = (Destination << Count) | (DoubleSource >> (32 - Count));
871 
872  /* Update flags */
873  if (Count <= 16) State->Flags.Cf = (Destination >> (16 - Count)) & 1;
874  else State->Flags.Cf = (Source >> (32 - Count)) & 1;
875 
876  if (Count == 1) State->Flags.Of = (Result & SIGN_FLAG_WORD)
878  State->Flags.Zf = (Result == 0);
879  State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
880  State->Flags.Pf = Fast486CalculateParity(Result);
881 
882  /* Write back the result */
883  Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Result);
884  }
885 }
886 
887 FAST486_OPCODE_HANDLER(Fast486ExtOpcodePushGs)
888 {
889  /* Call the internal API */
890  Fast486StackPush(State, State->SegmentRegs[FAST486_REG_GS].Selector);
891 }
892 
893 FAST486_OPCODE_HANDLER(Fast486ExtOpcodePopGs)
894 {
895  ULONG NewSelector;
896 
897  if (!Fast486StackPop(State, &NewSelector))
898  {
899  /* Exception occurred */
900  return;
901  }
902 
903  /* Call the internal API */
904  Fast486LoadSegment(State, FAST486_REG_GS, LOWORD(NewSelector));
905 }
906 
907 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBts)
908 {
909  BOOLEAN OperandSize, AddressSize;
910  FAST486_MOD_REG_RM ModRegRm;
911  UINT DataSize;
912  ULONG BitNumber;
913 
914  OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
915  TOGGLE_OPSIZE(OperandSize);
916  TOGGLE_ADSIZE(AddressSize);
917 
918  /* Get the number of bits */
919  if (OperandSize) DataSize = 32;
920  else DataSize = 16;
921 
922  /* Get the operands */
923  if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
924  {
925  /* Exception occurred */
926  return;
927  }
928 
929  /* Get the bit number */
930  BitNumber = OperandSize ? State->GeneralRegs[ModRegRm.Register].Long
931  : (ULONG)State->GeneralRegs[ModRegRm.Register].LowWord;
932 
933  if (ModRegRm.Memory)
934  {
935  /*
936  * For memory operands, add the bit offset divided by
937  * the data size to the address
938  */
939  ModRegRm.MemoryAddress += (BitNumber / DataSize) * (DataSize / 8);
940  }
941 
942  /* Normalize the bit number */
943  BitNumber %= DataSize;
944 
945  if (OperandSize)
946  {
947  ULONG Value;
948 
949  /* Read the value */
950  if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
951  {
952  /* Exception occurred */
953  return;
954  }
955 
956  /* Set CF to the bit value */
957  State->Flags.Cf = (Value >> BitNumber) & 1;
958 
959  /* Set the bit */
960  Value |= 1 << BitNumber;
961 
962  /* Write back the result */
963  Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value);
964  }
965  else
966  {
967  USHORT Value;
968 
969  /* Read the value */
970  if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value))
971  {
972  /* Exception occurred */
973  return;
974  }
975 
976  /* Set CF to the bit value */
977  State->Flags.Cf = (Value >> BitNumber) & 1;
978 
979  /* Set the bit */
980  Value |= 1 << BitNumber;
981 
982  /* Write back the result */
983  Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value);
984  }
985 }
986 
987 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeShrd)
988 {
989  BOOLEAN OperandSize, AddressSize;
990  FAST486_MOD_REG_RM ModRegRm;
991  UCHAR Count;
992 
993  OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
994  TOGGLE_OPSIZE(OperandSize);
995  TOGGLE_ADSIZE(AddressSize);
996 
997  /* Make sure this is the right instruction */
998  ASSERT((Opcode & 0xFE) == 0xAC);
999 
1000  /* Get the operands */
1001  if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
1002  {
1003  /* Exception occurred */
1004  return;
1005  }
1006 
1007  if (Opcode == 0xAC)
1008  {
1009  /* Fetch the count */
1010  if (!Fast486FetchByte(State, &Count))
1011  {
1012  /* Exception occurred */
1013  return;
1014  }
1015  }
1016  else
1017  {
1018  /* The count is in CL */
1019  Count = State->GeneralRegs[FAST486_REG_ECX].LowByte;
1020  }
1021 
1022  /* Normalize the count */
1023  Count &= 0x1F;
1024 
1025  /* Do nothing if the count is zero */
1026  if (Count == 0) return;
1027 
1028  if (OperandSize)
1029  {
1031 
1032  if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, &Source, &Destination))
1033  {
1034  /* Exception occurred */
1035  return;
1036  }
1037 
1038  /* Calculate the result */
1039  Result = (Destination >> Count) | (Source << (32 - Count));
1040 
1041  /* Update flags */
1042  State->Flags.Cf = (Destination >> (Count - 1)) & 1;
1043  if (Count == 1) State->Flags.Of = (Result & SIGN_FLAG_LONG)
1044  != (Destination & SIGN_FLAG_LONG);
1045  State->Flags.Zf = (Result == 0);
1046  State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
1047  State->Flags.Pf = Fast486CalculateParity(Result);
1048 
1049  /* Write back the result */
1050  Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Result);
1051  }
1052  else
1053  {
1055 
1056  if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Source, &Destination))
1057  {
1058  /* Exception occurred */
1059  return;
1060  }
1061 
1062  /* Calculate the result */
1063  Result = (Destination >> Count) | (Source << (16 - Count));
1064 
1065  if (Count >= 16) Result |= (ULONG)(Source | (Source << 16)) >> (Count - 16);
1066 
1067  /* Update flags */
1068  if (Count <= 16) State->Flags.Cf = (Destination >> (Count - 1)) & 1;
1069  else State->Flags.Cf = (Source >> (Count - 17)) & 1;
1070 
1071  if (Count == 1) State->Flags.Of = (Result & SIGN_FLAG_WORD)
1072  != (Destination & SIGN_FLAG_WORD);
1073  State->Flags.Zf = (Result == 0);
1074  State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
1075  State->Flags.Pf = Fast486CalculateParity(Result);
1076 
1077  /* Write back the result */
1078  Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Result);
1079  }
1080 }
1081 
1082 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeImul)
1083 {
1084  BOOLEAN OperandSize, AddressSize;
1085  FAST486_MOD_REG_RM ModRegRm;
1086 
1087  OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
1088 
1089  TOGGLE_OPSIZE(OperandSize);
1090  TOGGLE_ADSIZE(AddressSize);
1091 
1092  /* Get the operands */
1093  if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
1094  {
1095  /* Exception occurred */
1096  return;
1097  }
1098 
1099  if (OperandSize)
1100  {
1102  LONGLONG Result;
1103 
1104  /* Read the operands */
1105  if (!Fast486ReadModrmDwordOperands(State,
1106  &ModRegRm,
1107  (PULONG)&Destination,
1108  (PULONG)&Source))
1109  {
1110  /* Exception occurred */
1111  return;
1112  }
1113 
1114  /* Calculate the result */
1116 
1117  /* Update the flags */
1118  State->Flags.Cf = State->Flags.Of = ((Result < -2147483648LL) || (Result > 2147483647LL));
1119 
1120  /* Write back the result */
1121  Fast486WriteModrmDwordOperands(State, &ModRegRm, TRUE, (ULONG)((LONG)Result));
1122  }
1123  else
1124  {
1126  LONG Result;
1127 
1128  /* Read the operands */
1129  if (!Fast486ReadModrmWordOperands(State,
1130  &ModRegRm,
1131  (PUSHORT)&Destination,
1132  (PUSHORT)&Source))
1133  {
1134  /* Exception occurred */
1135  return;
1136  }
1137 
1138  /* Calculate the result */
1140 
1141  /* Update the flags */
1142  State->Flags.Cf = State->Flags.Of = ((Result < -32768) || (Result > 32767));
1143 
1144  /* Write back the result */
1145  Fast486WriteModrmWordOperands(State, &ModRegRm, TRUE, (USHORT)((SHORT)Result));
1146  }
1147 }
1148 
1149 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeCmpXchgByte)
1150 {
1151  FAST486_MOD_REG_RM ModRegRm;
1152  UCHAR Accumulator = State->GeneralRegs[FAST486_REG_EAX].LowByte;
1154  BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
1155 
1156  TOGGLE_ADSIZE(AddressSize);
1157 
1158  /* Get the operands */
1159  if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
1160  {
1161  /* Exception occurred */
1162  return;
1163  }
1164 
1165  /* Read the operands */
1166  if (!Fast486ReadModrmByteOperands(State, &ModRegRm, &Source, &Destination))
1167  {
1168  /* Exception occurred */
1169  return;
1170  }
1171 
1172  /* Compare AL with the destination */
1173  Result = Accumulator - Destination;
1174 
1175  /* Update the flags */
1176  State->Flags.Cf = (Accumulator < Destination);
1177  State->Flags.Of = ((Accumulator & SIGN_FLAG_BYTE) != (Destination & SIGN_FLAG_BYTE))
1178  && ((Accumulator & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
1179  State->Flags.Af = (Accumulator & 0x0F) < (Destination & 0x0F);
1180  State->Flags.Zf = (Result == 0);
1181  State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
1182  State->Flags.Pf = Fast486CalculateParity(Result);
1183 
1184  if (State->Flags.Zf)
1185  {
1186  /* Load the source operand into the destination */
1187  Fast486WriteModrmByteOperands(State, &ModRegRm, FALSE, Source);
1188  }
1189  else
1190  {
1191  /* Load the destination into AL */
1192  State->GeneralRegs[FAST486_REG_EAX].LowByte = Destination;
1193  }
1194 }
1195 
1196 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeCmpXchg)
1197 {
1198  FAST486_MOD_REG_RM ModRegRm;
1199  BOOLEAN OperandSize, AddressSize;
1200 
1201  OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
1202 
1203  TOGGLE_OPSIZE(OperandSize);
1204  TOGGLE_ADSIZE(AddressSize);
1205 
1206  /* Get the operands */
1207  if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
1208  {
1209  /* Exception occurred */
1210  return;
1211  }
1212 
1213  if (OperandSize)
1214  {
1216  ULONG Accumulator = State->GeneralRegs[FAST486_REG_EAX].Long;
1217 
1218  /* Read the operands */
1219  if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, &Source, &Destination))
1220  {
1221  /* Exception occurred */
1222  return;
1223  }
1224 
1225  /* Compare EAX with the destination */
1226  Result = Accumulator - Destination;
1227 
1228  /* Update the flags */
1229  State->Flags.Cf = (Accumulator < Destination);
1230  State->Flags.Of = ((Accumulator & SIGN_FLAG_LONG) != (Destination & SIGN_FLAG_LONG))
1231  && ((Accumulator & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
1232  State->Flags.Af = (Accumulator & 0x0F) < (Destination & 0x0F);
1233  State->Flags.Zf = (Result == 0);
1234  State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
1235  State->Flags.Pf = Fast486CalculateParity(Result);
1236 
1237  if (State->Flags.Zf)
1238  {
1239  /* Load the source operand into the destination */
1240  Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Source);
1241  }
1242  else
1243  {
1244  /* Load the destination into EAX */
1245  State->GeneralRegs[FAST486_REG_EAX].Long = Destination;
1246  }
1247  }
1248  else
1249  {
1251  USHORT Accumulator = State->GeneralRegs[FAST486_REG_EAX].LowWord;
1252 
1253  /* Read the operands */
1254  if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Source, &Destination))
1255  {
1256  /* Exception occurred */
1257  return;
1258  }
1259 
1260  /* Compare AX with the destination */
1261  Result = Accumulator - Destination;
1262 
1263  /* Update the flags */
1264  State->Flags.Cf = (Accumulator < Destination);
1265  State->Flags.Of = ((Accumulator & SIGN_FLAG_WORD) != (Destination & SIGN_FLAG_WORD))
1266  && ((Accumulator & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
1267  State->Flags.Af = (Accumulator & 0x0F) < (Destination & 0x0F);
1268  State->Flags.Zf = (Result == 0);
1269  State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
1270  State->Flags.Pf = Fast486CalculateParity(Result);
1271 
1272  if (State->Flags.Zf)
1273  {
1274  /* Load the source operand into the destination */
1275  Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Source);
1276  }
1277  else
1278  {
1279  /* Load the destination into AX */
1280  State->GeneralRegs[FAST486_REG_EAX].LowWord = Destination;
1281  }
1282  }
1283 }
1284 
1285 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLss)
1286 {
1287  UCHAR FarPointer[6];
1288  BOOLEAN OperandSize, AddressSize;
1289  FAST486_MOD_REG_RM ModRegRm;
1290 
1291  /* Make sure this is the right instruction */
1292  ASSERT(Opcode == 0xB2);
1293 
1294  OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
1295 
1296  TOGGLE_OPSIZE(OperandSize);
1297  TOGGLE_ADSIZE(AddressSize);
1298 
1299  /* Get the operands */
1300  if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
1301  {
1302  /* Exception occurred */
1303  return;
1304  }
1305 
1306  if (!ModRegRm.Memory)
1307  {
1308  /* Invalid */
1309  Fast486Exception(State, FAST486_EXCEPTION_UD);
1310  return;
1311  }
1312 
1313  if (!Fast486ReadMemory(State,
1314  (State->PrefixFlags & FAST486_PREFIX_SEG)
1315  ? State->SegmentOverride : FAST486_REG_DS,
1316  ModRegRm.MemoryAddress,
1317  FALSE,
1318  FarPointer,
1319  OperandSize ? 6 : 4))
1320  {
1321  /* Exception occurred */
1322  return;
1323  }
1324 
1325  if (OperandSize)
1326  {
1327  ULONG Offset = *((PULONG)FarPointer);
1328  USHORT Segment = *((PUSHORT)&FarPointer[sizeof(ULONG)]);
1329 
1330  /* Set the register to the offset */
1331  State->GeneralRegs[ModRegRm.Register].Long = Offset;
1332 
1333  /* Load the segment */
1334  Fast486LoadSegment(State, FAST486_REG_SS, Segment);
1335  }
1336  else
1337  {
1338  USHORT Offset = *((PUSHORT)FarPointer);
1339  USHORT Segment = *((PUSHORT)&FarPointer[sizeof(USHORT)]);
1340 
1341  /* Set the register to the offset */
1342  State->GeneralRegs[ModRegRm.Register].LowWord = Offset;
1343 
1344  /* Load the segment */
1345  Fast486LoadSegment(State, FAST486_REG_SS, Segment);
1346  }
1347 }
1348 
1349 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBtr)
1350 {
1351  BOOLEAN OperandSize, AddressSize;
1352  FAST486_MOD_REG_RM ModRegRm;
1353  UINT DataSize;
1354  ULONG BitNumber;
1355 
1356  OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
1357  TOGGLE_OPSIZE(OperandSize);
1358  TOGGLE_ADSIZE(AddressSize);
1359 
1360  /* Get the number of bits */
1361  if (OperandSize) DataSize = 32;
1362  else DataSize = 16;
1363 
1364  /* Get the operands */
1365  if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
1366  {
1367  /* Exception occurred */
1368  return;
1369  }
1370 
1371  /* Get the bit number */
1372  BitNumber = OperandSize ? State->GeneralRegs[ModRegRm.Register].Long
1373  : (ULONG)State->GeneralRegs[ModRegRm.Register].LowWord;
1374 
1375  if (ModRegRm.Memory)
1376  {
1377  /*
1378  * For memory operands, add the bit offset divided by
1379  * the data size to the address
1380  */
1381  ModRegRm.MemoryAddress += (BitNumber / DataSize) * (DataSize / 8);
1382  }
1383 
1384  /* Normalize the bit number */
1385  BitNumber %= DataSize;
1386 
1387  if (OperandSize)
1388  {
1389  ULONG Value;
1390 
1391  /* Read the value */
1392  if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
1393  {
1394  /* Exception occurred */
1395  return;
1396  }
1397 
1398  /* Set CF to the bit value */
1399  State->Flags.Cf = (Value >> BitNumber) & 1;
1400 
1401  /* Clear the bit */
1402  Value &= ~(1 << BitNumber);
1403 
1404  /* Write back the result */
1405  Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value);
1406  }
1407  else
1408  {
1409  USHORT Value;
1410 
1411  /* Read the value */
1412  if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value))
1413  {
1414  /* Exception occurred */
1415  return;
1416  }
1417 
1418  /* Set CF to the bit value */
1419  State->Flags.Cf = (Value >> BitNumber) & 1;
1420 
1421  /* Clear the bit */
1422  Value &= ~(1 << BitNumber);
1423 
1424  /* Write back the result */
1425  Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value);
1426  }
1427 }
1428 
1429 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLfsLgs)
1430 {
1431  UCHAR FarPointer[6];
1432  BOOLEAN OperandSize, AddressSize;
1433  FAST486_MOD_REG_RM ModRegRm;
1434 
1435  /* Make sure this is the right instruction */
1436  ASSERT((Opcode & 0xFE) == 0xB4);
1437 
1438  OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
1439 
1440  TOGGLE_OPSIZE(OperandSize);
1441  TOGGLE_ADSIZE(AddressSize);
1442 
1443  /* Get the operands */
1444  if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
1445  {
1446  /* Exception occurred */
1447  return;
1448  }
1449 
1450  if (!ModRegRm.Memory)
1451  {
1452  /* Invalid */
1453  Fast486Exception(State, FAST486_EXCEPTION_UD);
1454  return;
1455  }
1456 
1457  if (!Fast486ReadMemory(State,
1458  (State->PrefixFlags & FAST486_PREFIX_SEG)
1459  ? State->SegmentOverride : FAST486_REG_DS,
1460  ModRegRm.MemoryAddress,
1461  FALSE,
1462  FarPointer,
1463  OperandSize ? 6 : 4))
1464  {
1465  /* Exception occurred */
1466  return;
1467  }
1468 
1469  if (OperandSize)
1470  {
1471  ULONG Offset = *((PULONG)FarPointer);
1472  USHORT Segment = *((PUSHORT)&FarPointer[sizeof(ULONG)]);
1473 
1474  /* Set the register to the offset */
1475  State->GeneralRegs[ModRegRm.Register].Long = Offset;
1476 
1477  /* Load the segment */
1478  Fast486LoadSegment(State,
1479  (Opcode == 0xB4)
1480  ? FAST486_REG_FS : FAST486_REG_GS,
1481  Segment);
1482  }
1483  else
1484  {
1485  USHORT Offset = *((PUSHORT)FarPointer);
1486  USHORT Segment = *((PUSHORT)&FarPointer[sizeof(USHORT)]);
1487 
1488  /* Set the register to the offset */
1489  State->GeneralRegs[ModRegRm.Register].LowWord = Offset;
1490 
1491  /* Load the segment */
1492  Fast486LoadSegment(State,
1493  (Opcode == 0xB4)
1494  ? FAST486_REG_FS : FAST486_REG_GS,
1495  Segment);
1496  }
1497 }
1498 
1499 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeMovzxByte)
1500 {
1501  UCHAR Value;
1502  BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
1503  FAST486_MOD_REG_RM ModRegRm;
1504 
1505  TOGGLE_ADSIZE(AddressSize);
1506 
1507  /* Make sure this is the right instruction */
1508  ASSERT(Opcode == 0xB6);
1509 
1510  /* Get the operands */
1511  if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
1512  {
1513  /* Exception occurred */
1514  return;
1515  }
1516 
1517  /* Read the operands */
1518  if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, &Value))
1519  {
1520  /* Exception occurred */
1521  return;
1522  }
1523 
1524  /* Write back the zero-extended value */
1525  Fast486WriteModrmDwordOperands(State,
1526  &ModRegRm,
1527  TRUE,
1528  (ULONG)Value);
1529 }
1530 
1531 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeMovzxWord)
1532 {
1533  USHORT Value;
1534  BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
1535  FAST486_MOD_REG_RM ModRegRm;
1536 
1537  TOGGLE_ADSIZE(AddressSize);
1538 
1539  /* Make sure this is the right instruction */
1540  ASSERT(Opcode == 0xB7);
1541 
1542  /* Get the operands */
1543  if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
1544  {
1545  /* Exception occurred */
1546  return;
1547  }
1548 
1549  /* Read the operands */
1550  if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value))
1551  {
1552  /* Exception occurred */
1553  return;
1554  }
1555 
1556  /* Write back the zero-extended value */
1557  Fast486WriteModrmDwordOperands(State,
1558  &ModRegRm,
1559  TRUE,
1560  (ULONG)Value);
1561 }
1562 
1563 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBtc)
1564 {
1565  BOOLEAN OperandSize, AddressSize;
1566  FAST486_MOD_REG_RM ModRegRm;
1567  UINT DataSize;
1568  ULONG BitNumber;
1569 
1570  OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
1571  TOGGLE_OPSIZE(OperandSize);
1572  TOGGLE_ADSIZE(AddressSize);
1573 
1574  /* Get the number of bits */
1575  if (OperandSize) DataSize = 32;
1576  else DataSize = 16;
1577 
1578  /* Get the operands */
1579  if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
1580  {
1581  /* Exception occurred */
1582  return;
1583  }
1584 
1585  /* Get the bit number */
1586  BitNumber = OperandSize ? State->GeneralRegs[ModRegRm.Register].Long
1587  : (ULONG)State->GeneralRegs[ModRegRm.Register].LowWord;
1588 
1589  if (ModRegRm.Memory)
1590  {
1591  /*
1592  * For memory operands, add the bit offset divided by
1593  * the data size to the address
1594  */
1595  ModRegRm.MemoryAddress += (BitNumber / DataSize) * (DataSize / 8);
1596  }
1597 
1598  /* Normalize the bit number */
1599  BitNumber %= DataSize;
1600 
1601  if (OperandSize)
1602  {
1603  ULONG Value;
1604 
1605  /* Read the value */
1606  if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
1607  {
1608  /* Exception occurred */
1609  return;
1610  }
1611 
1612  /* Set CF to the bit value */
1613  State->Flags.Cf = (Value >> BitNumber) & 1;
1614 
1615  /* Toggle the bit */
1616  Value ^= 1 << BitNumber;
1617 
1618  /* Write back the result */
1619  Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value);
1620  }
1621  else
1622  {
1623  USHORT Value;
1624 
1625  /* Read the value */
1626  if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value))
1627  {
1628  /* Exception occurred */
1629  return;
1630  }
1631 
1632  /* Set CF to the bit value */
1633  State->Flags.Cf = (Value >> BitNumber) & 1;
1634 
1635  /* Toggle the bit */
1636  Value ^= 1 << BitNumber;
1637 
1638  /* Write back the result */
1639  Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value);
1640  }
1641 }
1642 
1643 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBsf)
1644 {
1645  UINT i;
1646  ULONG Value = 0;
1647  BOOLEAN OperandSize, AddressSize;
1648  FAST486_MOD_REG_RM ModRegRm;
1649  ULONG BitNumber;
1650  UINT DataSize;
1651 
1652  OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
1653  TOGGLE_OPSIZE(OperandSize);
1654  TOGGLE_ADSIZE(AddressSize);
1655 
1656  /* Make sure this is the right instruction */
1657  ASSERT(Opcode == 0xBC);
1658 
1659  /* Get the number of bits */
1660  if (OperandSize) DataSize = 32;
1661  else DataSize = 16;
1662 
1663  /* Get the operands */
1664  if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
1665  {
1666  /* Exception occurred */
1667  return;
1668  }
1669 
1670  /* Read the value */
1671  if (OperandSize)
1672  {
1673  if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
1674  {
1675  /* Exception occurred */
1676  return;
1677  }
1678  }
1679  else
1680  {
1681  if (!Fast486ReadModrmWordOperands(State,
1682  &ModRegRm,
1683  (PUSHORT)NULL,
1684  (PUSHORT)&Value))
1685  {
1686  /* Exception occurred */
1687  return;
1688  }
1689  }
1690 
1691  /* Set ZF */
1692  State->Flags.Zf = (Value == 0);
1693  if (State->Flags.Zf) return;
1694 
1695  for (i = 0; i < DataSize; i++)
1696  {
1697  if (Value & (1 << i))
1698  {
1699  /* Save the bit number */
1700  BitNumber = i;
1701 
1702  /* Exit the loop */
1703  break;
1704  }
1705  }
1706 
1707  /* Write back the result */
1708  if (OperandSize) Fast486WriteModrmDwordOperands(State, &ModRegRm, TRUE, BitNumber);
1709  else Fast486WriteModrmWordOperands(State, &ModRegRm, TRUE, LOWORD(BitNumber));
1710 }
1711 
1712 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBsr)
1713 {
1714  INT i;
1715  ULONG Value = 0;
1716  BOOLEAN OperandSize, AddressSize;
1717  FAST486_MOD_REG_RM ModRegRm;
1718  ULONG BitNumber;
1719  UINT DataSize;
1720 
1721  OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
1722  TOGGLE_OPSIZE(OperandSize);
1723  TOGGLE_ADSIZE(AddressSize);
1724 
1725  /* Make sure this is the right instruction */
1726  ASSERT(Opcode == 0xBD);
1727 
1728  /* Get the number of bits */
1729  if (OperandSize) DataSize = 32;
1730  else DataSize = 16;
1731 
1732  /* Get the operands */
1733  if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
1734  {
1735  /* Exception occurred */
1736  return;
1737  }
1738 
1739  /* Read the value */
1740  if (OperandSize)
1741  {
1742  if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
1743  {
1744  /* Exception occurred */
1745  return;
1746  }
1747  }
1748  else
1749  {
1750  if (!Fast486ReadModrmWordOperands(State,
1751  &ModRegRm,
1752  (PUSHORT)NULL,
1753  (PUSHORT)&Value))
1754  {
1755  /* Exception occurred */
1756  return;
1757  }
1758  }
1759 
1760  /* Set ZF according to the value */
1761  State->Flags.Zf = (Value == 0);
1762  if (State->Flags.Zf) return;
1763 
1764  for (i = DataSize - 1; i >= 0; i--)
1765  {
1766  if (Value & (1 << i))
1767  {
1768  /* Save the bit number */
1769  BitNumber = i;
1770 
1771  /* Exit the loop */
1772  break;
1773  }
1774  }
1775 
1776  /* Write back the result */
1777  if (OperandSize) Fast486WriteModrmDwordOperands(State, &ModRegRm, TRUE, BitNumber);
1778  else Fast486WriteModrmWordOperands(State, &ModRegRm, TRUE, LOWORD(BitNumber));
1779 }
1780 
1781 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeMovsxByte)
1782 {
1783  CHAR Value;
1784  BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
1785  FAST486_MOD_REG_RM ModRegRm;
1786 
1787  TOGGLE_ADSIZE(AddressSize);
1788 
1789  /* Make sure this is the right instruction */
1790  ASSERT(Opcode == 0xBE);
1791 
1792  /* Get the operands */
1793  if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
1794  {
1795  /* Exception occurred */
1796  return;
1797  }
1798 
1799  /* Read the operands */
1800  if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, (PUCHAR)&Value))
1801  {
1802  /* Exception occurred */
1803  return;
1804  }
1805 
1806  /* Write back the sign-extended value */
1807  Fast486WriteModrmDwordOperands(State,
1808  &ModRegRm,
1809  TRUE,
1810  (ULONG)((LONG)Value));
1811 }
1812 
1813 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeMovsxWord)
1814 {
1815  SHORT Value;
1816  BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
1817  FAST486_MOD_REG_RM ModRegRm;
1818 
1819  TOGGLE_ADSIZE(AddressSize);
1820 
1821  /* Make sure this is the right instruction */
1822  ASSERT(Opcode == 0xBF);
1823 
1824  /* Get the operands */
1825  if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
1826  {
1827  /* Exception occurred */
1828  return;
1829  }
1830 
1831  /* Read the operands */
1832  if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, (PUSHORT)&Value))
1833  {
1834  /* Exception occurred */
1835  return;
1836  }
1837 
1838  /* Write back the sign-extended value */
1839  Fast486WriteModrmDwordOperands(State,
1840  &ModRegRm,
1841  TRUE,
1842  (ULONG)((LONG)Value));
1843 }
1844 
1845 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeConditionalJmp)
1846 {
1847  BOOLEAN Jump = FALSE;
1848  LONG Offset = 0;
1849  BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
1850 
1852  NO_LOCK_PREFIX();
1853 
1854  /* Make sure this is the right instruction */
1855  ASSERT((Opcode & 0xF0) == 0x80);
1856 
1857  /* Fetch the offset */
1858  if (Size)
1859  {
1860  if (!Fast486FetchDword(State, (PULONG)&Offset))
1861  {
1862  /* Exception occurred */
1863  return;
1864  }
1865  }
1866  else
1867  {
1868  SHORT Value;
1869 
1870  if (!Fast486FetchWord(State, (PUSHORT)&Value))
1871  {
1872  /* Exception occurred */
1873  return;
1874  }
1875 
1876  /* Sign-extend */
1877  Offset = (LONG)Value;
1878  }
1879 
1880  switch ((Opcode & 0x0F) >> 1)
1881  {
1882  /* JO / JNO */
1883  case 0:
1884  {
1885  Jump = State->Flags.Of;
1886  break;
1887  }
1888 
1889  /* JC / JNC */
1890  case 1:
1891  {
1892  Jump = State->Flags.Cf;
1893  break;
1894  }
1895 
1896  /* JZ / JNZ */
1897  case 2:
1898  {
1899  Jump = State->Flags.Zf;
1900  break;
1901  }
1902 
1903  /* JBE / JNBE */
1904  case 3:
1905  {
1906  Jump = State->Flags.Cf || State->Flags.Zf;
1907  break;
1908  }
1909 
1910  /* JS / JNS */
1911  case 4:
1912  {
1913  Jump = State->Flags.Sf;
1914  break;
1915  }
1916 
1917  /* JP / JNP */
1918  case 5:
1919  {
1920  Jump = State->Flags.Pf;
1921  break;
1922  }
1923 
1924  /* JL / JNL */
1925  case 6:
1926  {
1927  Jump = State->Flags.Sf != State->Flags.Of;
1928  break;
1929  }
1930 
1931  /* JLE / JNLE */
1932  case 7:
1933  {
1934  Jump = (State->Flags.Sf != State->Flags.Of) || State->Flags.Zf;
1935  break;
1936  }
1937  }
1938 
1939  if (Opcode & 1)
1940  {
1941  /* Invert the result */
1942  Jump = !Jump;
1943  }
1944 
1945  if (Jump)
1946  {
1947  /* Move the instruction pointer */
1948  State->InstPtr.Long += Offset;
1949  }
1950 }
1951 
1952 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeConditionalSet)
1953 {
1954  BOOLEAN Value = FALSE;
1955  BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
1956  FAST486_MOD_REG_RM ModRegRm;
1957 
1958  TOGGLE_ADSIZE(AddressSize);
1959 
1960  /* Get the operands */
1961  if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
1962  {
1963  /* Exception occurred */
1964  return;
1965  }
1966 
1967  /* Make sure this is the right instruction */
1968  ASSERT((Opcode & 0xF0) == 0x90);
1969 
1970  switch ((Opcode & 0x0F) >> 1)
1971  {
1972  /* SETO / SETNO */
1973  case 0:
1974  {
1975  Value = State->Flags.Of;
1976  break;
1977  }
1978 
1979  /* SETC / SETNC */
1980  case 1:
1981  {
1982  Value = State->Flags.Cf;
1983  break;
1984  }
1985 
1986  /* SETZ / SETNZ */
1987  case 2:
1988  {
1989  Value = State->Flags.Zf;
1990  break;
1991  }
1992 
1993  /* SETBE / SETNBE */
1994  case 3:
1995  {
1996  Value = State->Flags.Cf || State->Flags.Zf;
1997  break;
1998  }
1999 
2000  /* SETS / SETNS */
2001  case 4:
2002  {
2003  Value = State->Flags.Sf;
2004  break;
2005  }
2006 
2007  /* SETP / SETNP */
2008  case 5:
2009  {
2010  Value = State->Flags.Pf;
2011  break;
2012  }
2013 
2014  /* SETL / SETNL */
2015  case 6:
2016  {
2017  Value = State->Flags.Sf != State->Flags.Of;
2018  break;
2019  }
2020 
2021  /* SETLE / SETNLE */
2022  case 7:
2023  {
2024  Value = (State->Flags.Sf != State->Flags.Of) || State->Flags.Zf;
2025  break;
2026  }
2027  }
2028 
2029  if (Opcode & 1)
2030  {
2031  /* Invert the result */
2032  Value = !Value;
2033  }
2034 
2035  /* Write back the result */
2036  Fast486WriteModrmByteOperands(State, &ModRegRm, FALSE, Value);
2037 }
2038 
2039 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeXaddByte)
2040 {
2042  FAST486_MOD_REG_RM ModRegRm;
2043  BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
2044 
2045  /* Make sure this is the right instruction */
2046  ASSERT(Opcode == 0xC0);
2047 
2048  TOGGLE_ADSIZE(AddressSize);
2049 
2050  /* Get the operands */
2051  if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
2052  {
2053  /* Exception occurred */
2054  return;
2055  }
2056 
2057  if (!Fast486ReadModrmByteOperands(State,
2058  &ModRegRm,
2059  &Source,
2060  &Destination))
2061  {
2062  /* Exception occurred */
2063  return;
2064  }
2065 
2066  /* Calculate the result */
2068 
2069  /* Update the flags */
2070  State->Flags.Cf = (Result < Source) && (Result < Destination);
2071  State->Flags.Of = ((Source & SIGN_FLAG_BYTE) == (Destination & SIGN_FLAG_BYTE))
2072  && ((Source & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
2073  State->Flags.Af = ((((Source & 0x0F) + (Destination & 0x0F)) & 0x10) != 0);
2074  State->Flags.Zf = (Result == 0);
2075  State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
2076  State->Flags.Pf = Fast486CalculateParity(Result);
2077 
2078  /* Write the sum to the destination */
2079  if (!Fast486WriteModrmByteOperands(State, &ModRegRm, FALSE, Result))
2080  {
2081  /* Exception occurred */
2082  return;
2083  }
2084 
2085  /* Write the old value of the destination to the source */
2086  Fast486WriteModrmByteOperands(State, &ModRegRm, TRUE, Destination);
2087 }
2088 
2089 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeXadd)
2090 {
2091  FAST486_MOD_REG_RM ModRegRm;
2092  BOOLEAN OperandSize, AddressSize;
2093 
2094  /* Make sure this is the right instruction */
2095  ASSERT(Opcode == 0xC1);
2096 
2097  OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
2098 
2099  TOGGLE_ADSIZE(AddressSize);
2100  TOGGLE_OPSIZE(OperandSize);
2101 
2102  /* Get the operands */
2103  if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
2104  {
2105  /* Exception occurred */
2106  return;
2107  }
2108 
2109  /* Check the operand size */
2110  if (OperandSize)
2111  {
2113 
2114  if (!Fast486ReadModrmDwordOperands(State,
2115  &ModRegRm,
2116  &Source,
2117  &Destination))
2118  {
2119  /* Exception occurred */
2120  return;
2121  }
2122 
2123  /* Calculate the result */
2125 
2126  /* Update the flags */
2127  State->Flags.Cf = (Result < Source) && (Result < Destination);
2128  State->Flags.Of = ((Source & SIGN_FLAG_LONG) == (Destination & SIGN_FLAG_LONG))
2129  && ((Source & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
2130  State->Flags.Af = ((((Source & 0x0F) + (Destination & 0x0F)) & 0x10) != 0);
2131  State->Flags.Zf = (Result == 0);
2132  State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
2133  State->Flags.Pf = Fast486CalculateParity(Result);
2134 
2135  /* Write the old value of the destination to the source */
2136  if (!Fast486WriteModrmDwordOperands(State, &ModRegRm, TRUE, Destination))
2137  {
2138  /* Exception occurred */
2139  return;
2140  }
2141 
2142  /* Write the sum to the destination */
2143  Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Result);
2144  }
2145  else
2146  {
2148 
2149  if (!Fast486ReadModrmWordOperands(State,
2150  &ModRegRm,
2151  &Source,
2152  &Destination))
2153  {
2154  /* Exception occurred */
2155  return;
2156  }
2157 
2158  /* Calculate the result */
2160 
2161  /* Update the flags */
2162  State->Flags.Cf = (Result < Source) && (Result < Destination);
2163  State->Flags.Of = ((Source & SIGN_FLAG_WORD) == (Destination & SIGN_FLAG_WORD))
2164  && ((Source & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
2165  State->Flags.Af = ((((Source & 0x0F) + (Destination & 0x0F)) & 0x10) != 0);
2166  State->Flags.Zf = (Result == 0);
2167  State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
2168  State->Flags.Pf = Fast486CalculateParity(Result);
2169 
2170  /* Write the old value of the destination to the source */
2171  if (!Fast486WriteModrmWordOperands(State, &ModRegRm, TRUE, Destination))
2172  {
2173  /* Exception occurred */
2174  return;
2175  }
2176 
2177  /* Write the sum to the destination */
2178  Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Result);
2179  }
2180 }
2181 
2182 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBswap)
2183 {
2184  PUCHAR Pointer;
2185 
2186  NO_LOCK_PREFIX();
2187 
2188  /* Get a pointer to the value */
2189  Pointer = (PUCHAR)&State->GeneralRegs[Opcode & 0x07].Long;
2190 
2191  /* Swap the byte order */
2192  SWAP(Pointer[0], Pointer[3]);
2193  SWAP(Pointer[1], Pointer[2]);
2194 }
2195 
2196 FAST486_OPCODE_HANDLER(Fast486OpcodeExtended)
2197 {
2198  UCHAR SecondOpcode;
2199 
2200  /* Fetch the second operation code */
2201  if (!Fast486FetchByte(State, &SecondOpcode))
2202  {
2203  /* Exception occurred */
2204  return;
2205  }
2206 
2207  /* Call the extended opcode handler */
2208  Fast486ExtendedHandlers[SecondOpcode](State, SecondOpcode);
2209 }
2210 
2211 /* EOF */
_In_opt_ ULONG _Out_ PULONG Value
Definition: rtlfuncs.h:2343
#define FAST486_CR0_PG
Definition: fast486.h:56
#define TRUE
Definition: types.h:120
#define LL
Definition: tui.h:85
_In_ PVOID _In_ ULONG Opcode
Definition: hubbusif.h:330
#define NO_LOCK_PREFIX()
Definition: common.h:43
#define FAST486_CR0_CD
Definition: fast486.h:55
#define FAST486_DR4_RESERVED
Definition: fast486.h:82
#define FAST486_CR0_PE
Definition: fast486.h:46
unsigned char * PUCHAR
Definition: retypes.h:3
char CHAR
Definition: xmlstorage.h:175
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
FAST486_GEN_REGS Register
Definition: common.h:76
int32_t INT
Definition: typedefs.h:56
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
#define SIGN_FLAG_LONG
Definition: common.h:31
long LONG
Definition: pedump.c:60
short SHORT
Definition: pedump.c:59
#define SIGN_FLAG_WORD
Definition: common.h:30
#define SIGN_FLAG_BYTE
Definition: common.h:29
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
FAST486_OPCODE_HANDLER(Fast486ExtOpcodeInvalid)
Definition: extraops.c:300
_Inout_ PVOID Segment
Definition: exfuncs.h:893
int64_t LONGLONG
Definition: typedefs.h:66
#define TOGGLE_ADSIZE(x)
Definition: common.h:53
#define FAST486_NUM_OPCODE_HANDLERS
Definition: opcodes.h:29
if(!(yy_init))
Definition: macro.lex.yy.c:714
FAST486_GEN_REGS SecondRegister
Definition: common.h:80
unsigned long DWORD
Definition: ntddk_ex.h:95
_In_ PUNICODE_STRING _Inout_ PUNICODE_STRING Destination
Definition: rtlfuncs.h:2891
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
unsigned char UCHAR
Definition: xmlstorage.h:181
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
BOOLEAN FASTCALL Fast486ReadMemory(PFAST486_STATE State, FAST486_SEG_REGS SegmentReg, ULONG Offset, BOOLEAN InstFetch, PVOID Buffer, ULONG Size)
Definition: common.c:36
#define SWAP()
Definition: pattern.c:1256
#define FAST486_PREFIX_SEG
Definition: fast486.h:98
VOID(FASTCALL * FAST486_OPCODE_HANDLER_PROC)(PFAST486_STATE, UCHAR)
Definition: opcodes.h:34
enum State_ State
Definition: pofuncs.h:54
#define TOGGLE_OPSIZE(x)
Definition: common.h:50
unsigned short USHORT
Definition: pedump.c:61
#define GET_SEGMENT_RPL(s)
Definition: common.h:38
#define FAST486_CR0_TS
Definition: fast486.h:49
unsigned int * PULONG
Definition: retypes.h:1
#define FAST486_DR5_GD
Definition: fast486.h:76
unsigned int UINT
Definition: ndis.h:50
DWORD * PDWORD
Definition: pedump.c:68
#define DPRINT1
Definition: precomp.h:8
unsigned int ULONG
Definition: retypes.h:1
#define FAST486_CR0_NW
Definition: fast486.h:54
_In_ UINT _In_ UINT _In_ PNDIS_PACKET Source
Definition: ndis.h:3167
ULONG MemoryAddress
Definition: common.h:81
#define FAST486_DR5_RESERVED
Definition: fast486.h:83
FAST486_OPCODE_HANDLER_PROC Fast486ExtendedHandlers[FAST486_NUM_OPCODE_HANDLERS]
Definition: extraops.c:38
#define LOWORD(l)
Definition: pedump.c:82
_In_ LONG _In_ LONG Limit
Definition: kefuncs.h:328
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT _In_opt_ PVOID _In_ ULONG DataSize
Definition: ndis.h:4751
unsigned short * PUSHORT
Definition: retypes.h:2
BOOLEAN Memory
Definition: common.h:77