2 * Fast486 386/486 CPU Emulation Library
5 * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
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.
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.
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.
22 /* INCLUDES *******************************************************************/
35 /* PUBLIC VARIABLES ***********************************************************/
37 FAST486_OPCODE_HANDLER_PROC
38 Fast486ExtendedHandlers
[FAST486_NUM_OPCODE_HANDLERS
] =
40 Fast486OpcodeGroup0F00
,
41 Fast486OpcodeGroup0F01
,
42 NULL
, // TODO: OPCODE 0x02 NOT IMPLEMENTED
43 NULL
, // TODO: OPCODE 0x03 NOT IMPLEMENTED
44 NULL
, // TODO: OPCODE 0x04 NOT IMPLEMENTED
45 NULL
, // TODO: OPCODE 0x05 NOT IMPLEMENTED
47 NULL
, // TODO: OPCODE 0x07 NOT IMPLEMENTED
48 NULL
, // TODO: OPCODE 0x08 NOT IMPLEMENTED
49 NULL
, // TODO: OPCODE 0x09 NOT IMPLEMENTED
51 NULL
, // Reserved (UD1)
72 Fast486ExtOpcodeStoreControlReg
,
73 Fast486ExtOpcodeStoreDebugReg
,
74 Fast486ExtOpcodeLoadControlReg
,
75 Fast486ExtOpcodeLoadDebugReg
,
76 NULL
, // TODO: OPCODE 0x24 NOT IMPLEMENTED
78 NULL
, // TODO: OPCODE 0x26 NOT IMPLEMENTED
168 Fast486ExtOpcodeConditionalJmp
,
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
,
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
,
201 Fast486ExtOpcodePopFs
,
203 Fast486ExtOpcodeBitTest
,
204 Fast486ExtOpcodeShld
,
205 Fast486ExtOpcodeShld
,
208 Fast486ExtOpcodePushGs
,
209 Fast486ExtOpcodePopGs
,
212 Fast486ExtOpcodeShrd
,
213 Fast486ExtOpcodeShrd
,
214 NULL
, // TODO: OPCODE 0xAE NOT IMPLEMENTED
215 Fast486ExtOpcodeImul
,
216 Fast486ExtOpcodeCmpXchgByte
,
217 Fast486ExtOpcodeCmpXchg
,
220 Fast486ExtOpcodeLfsLgs
,
221 Fast486ExtOpcodeLfsLgs
,
222 Fast486ExtOpcodeMovzxByte
,
223 Fast486ExtOpcodeMovzxWord
,
225 Fast486OpcodeGroup0FB9
,
226 Fast486OpcodeGroup0FBA
,
230 Fast486ExtOpcodeMovsxByte
,
231 Fast486ExtOpcodeMovsxWord
,
232 Fast486ExtOpcodeXaddByte
,
233 Fast486ExtOpcodeXadd
,
240 Fast486ExtOpcodeBswap
,
241 Fast486ExtOpcodeBswap
,
242 Fast486ExtOpcodeBswap
,
243 Fast486ExtOpcodeBswap
,
244 Fast486ExtOpcodeBswap
,
245 Fast486ExtOpcodeBswap
,
246 Fast486ExtOpcodeBswap
,
247 Fast486ExtOpcodeBswap
,
298 /* PUBLIC FUNCTIONS ***********************************************************/
300 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeClts
)
304 /* The current privilege level must be zero */
305 if (Fast486GetCurrentPrivLevel(State
) != 0)
307 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
311 /* Clear the task switch bit */
312 State
->ControlRegisters
[FAST486_REG_CR0
] &= ~FAST486_CR0_TS
;
317 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeStoreControlReg
)
319 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
320 FAST486_MOD_REG_RM ModRegRm
;
323 TOGGLE_ADSIZE(AddressSize
);
325 /* Get the operands */
326 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
328 /* Exception occurred */
332 /* The current privilege level must be zero */
333 if (Fast486GetCurrentPrivLevel(State
) != 0)
335 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
339 if ((ModRegRm
.Register
== 1) || (ModRegRm
.Register
> 3))
341 /* CR1, CR4, CR5, CR6 and CR7 don't exist */
342 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
346 if (ModRegRm
.Register
!= 0)
348 /* CR2 and CR3 and are stored in array indexes 1 and 2 */
352 /* Store the value of the control register */
353 State
->GeneralRegs
[ModRegRm
.SecondRegister
].Long
= State
->ControlRegisters
[ModRegRm
.Register
];
359 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeStoreDebugReg
)
361 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
362 FAST486_MOD_REG_RM ModRegRm
;
365 TOGGLE_ADSIZE(AddressSize
);
367 /* Get the operands */
368 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
370 /* Exception occurred */
374 /* The current privilege level must be zero */
375 if (Fast486GetCurrentPrivLevel(State
) != 0)
377 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
381 if ((ModRegRm
.Register
== 6) || (ModRegRm
.Register
== 7))
383 /* DR6 and DR7 are aliases to DR4 and DR5 */
384 ModRegRm
.Register
-= 2;
387 if (State
->DebugRegisters
[FAST486_REG_DR5
] & FAST486_DR5_GD
)
389 /* Disallow access to debug registers */
390 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
394 /* Store the value of the debug register */
395 State
->GeneralRegs
[ModRegRm
.SecondRegister
].Long
= State
->DebugRegisters
[ModRegRm
.Register
];
401 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLoadControlReg
)
404 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
405 FAST486_MOD_REG_RM ModRegRm
;
408 TOGGLE_ADSIZE(AddressSize
);
410 /* Get the operands */
411 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
413 /* Exception occurred */
417 /* The current privilege level must be zero */
418 if (Fast486GetCurrentPrivLevel(State
) != 0)
420 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
424 if ((ModRegRm
.Register
== 1) || (ModRegRm
.Register
> 3))
426 /* CR1, CR4, CR5, CR6 and CR7 don't exist */
427 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
431 if (ModRegRm
.Register
!= 0)
433 /* CR2 and CR3 and are stored in array indexes 1 and 2 */
438 Value
= State
->GeneralRegs
[ModRegRm
.SecondRegister
].Long
;
440 if (ModRegRm
.Register
== (INT
)FAST486_REG_CR0
)
444 if (((Value
& (FAST486_CR0_PG
| FAST486_CR0_PE
)) == FAST486_CR0_PG
)
445 || ((Value
& (FAST486_CR0_CD
| FAST486_CR0_NW
)) == FAST486_CR0_NW
))
448 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
453 /* Load a value to the control register */
454 State
->ControlRegisters
[ModRegRm
.Register
] = Value
;
460 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLoadDebugReg
)
462 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
463 FAST486_MOD_REG_RM ModRegRm
;
466 TOGGLE_ADSIZE(AddressSize
);
468 /* Get the operands */
469 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
471 /* Exception occurred */
475 /* The current privilege level must be zero */
476 if (Fast486GetCurrentPrivLevel(State
) != 0)
478 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
482 if ((ModRegRm
.Register
== 6) || (ModRegRm
.Register
== 7))
484 /* DR6 and DR7 are aliases to DR4 and DR5 */
485 ModRegRm
.Register
-= 2;
488 if (State
->DebugRegisters
[FAST486_REG_DR5
] & FAST486_DR5_GD
)
490 /* Disallow access to debug registers */
491 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
495 /* Load a value to the debug register */
496 State
->DebugRegisters
[ModRegRm
.Register
] = State
->GeneralRegs
[ModRegRm
.SecondRegister
].Long
;
498 if (ModRegRm
.Register
== (INT
)FAST486_REG_DR4
)
500 /* The reserved bits are 1 */
501 State
->DebugRegisters
[ModRegRm
.Register
] |= FAST486_DR4_RESERVED
;
503 else if (ModRegRm
.Register
== (INT
)FAST486_REG_DR5
)
505 /* The reserved bits are 0 */
506 State
->DebugRegisters
[ModRegRm
.Register
] &= ~FAST486_DR5_RESERVED
;
513 FAST486_OPCODE_HANDLER(Fast486ExtOpcodePushFs
)
515 /* Call the internal API */
516 return Fast486StackPush(State
, State
->SegmentRegs
[FAST486_REG_FS
].Selector
);
519 FAST486_OPCODE_HANDLER(Fast486ExtOpcodePopFs
)
523 if (!Fast486StackPop(State
, &NewSelector
))
525 /* Exception occurred */
529 /* Call the internal API */
530 return Fast486LoadSegment(State
, FAST486_REG_FS
, LOWORD(NewSelector
));
533 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBitTest
)
535 BOOLEAN OperandSize
, AddressSize
;
536 FAST486_MOD_REG_RM ModRegRm
;
540 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
541 TOGGLE_OPSIZE(OperandSize
);
542 TOGGLE_ADSIZE(AddressSize
);
544 /* Get the number of bits */
545 if (OperandSize
) DataSize
= 32;
548 /* Get the operands */
549 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
551 /* Exception occurred */
555 /* Get the bit number */
556 BitNumber
= OperandSize
? State
->GeneralRegs
[ModRegRm
.Register
].Long
557 : (ULONG
)State
->GeneralRegs
[ModRegRm
.Register
].LowWord
;
562 * For memory operands, add the bit offset divided by
563 * the data size to the address
565 ModRegRm
.MemoryAddress
+= BitNumber
/ DataSize
;
568 /* Normalize the bit number */
569 BitNumber
%= DataSize
;
576 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, NULL
, &Value
))
578 /* Exception occurred */
582 /* Set CF to the bit value */
583 State
->Flags
.Cf
= (Value
>> BitNumber
) & 1;
590 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, NULL
, &Value
))
592 /* Exception occurred */
596 /* Set CF to the bit value */
597 State
->Flags
.Cf
= (Value
>> BitNumber
) & 1;
604 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeShld
)
606 BOOLEAN OperandSize
, AddressSize
;
607 FAST486_MOD_REG_RM ModRegRm
;
610 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
611 TOGGLE_OPSIZE(OperandSize
);
612 TOGGLE_ADSIZE(AddressSize
);
614 /* Make sure this is the right instruction */
615 ASSERT((Opcode
& 0xFE) == 0xA4);
617 /* Get the operands */
618 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
620 /* Exception occurred */
626 /* Fetch the count */
627 if (!Fast486FetchByte(State
, &Count
))
629 /* Exception occurred */
635 /* The count is in CL */
636 Count
= State
->GeneralRegs
[FAST486_REG_ECX
].LowByte
;
639 /* Normalize the count */
642 /* Do nothing if the count is zero */
643 if (Count
== 0) return TRUE
;
647 ULONG Source
, Destination
, Result
;
649 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, &Source
, &Destination
))
651 /* Exception occurred */
655 /* Calculate the result */
656 Result
= (Destination
<< Count
) | (Source
>> (32 - Count
));
659 State
->Flags
.Cf
= (Destination
>> (32 - Count
)) & 1;
660 if (Count
== 1) State
->Flags
.Of
= (Result
& SIGN_FLAG_LONG
)
661 != (Destination
& SIGN_FLAG_LONG
);
662 State
->Flags
.Zf
= (Result
== 0);
663 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_LONG
) != 0);
664 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
666 /* Write back the result */
667 return Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Result
);
671 USHORT Source
, Destination
, Result
;
674 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, &Source
, &Destination
))
676 /* Exception occurred */
680 DoubleSource
= Source
| (Source
<< 16);
682 /* Calculate the result */
683 Result
= (Destination
<< Count
) | (DoubleSource
>> (32 - Count
));
686 if (Count
<= 16) State
->Flags
.Cf
= (Destination
>> (16 - Count
)) & 1;
687 else State
->Flags
.Cf
= (Source
>> (32 - Count
)) & 1;
689 if (Count
== 1) State
->Flags
.Of
= (Result
& SIGN_FLAG_WORD
)
690 != (Destination
& SIGN_FLAG_WORD
);
691 State
->Flags
.Zf
= (Result
== 0);
692 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_WORD
) != 0);
693 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
695 /* Write back the result */
696 return Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Result
);
700 FAST486_OPCODE_HANDLER(Fast486ExtOpcodePushGs
)
702 /* Call the internal API */
703 return Fast486StackPush(State
, State
->SegmentRegs
[FAST486_REG_GS
].Selector
);
706 FAST486_OPCODE_HANDLER(Fast486ExtOpcodePopGs
)
710 if (!Fast486StackPop(State
, &NewSelector
))
712 /* Exception occurred */
716 /* Call the internal API */
717 return Fast486LoadSegment(State
, FAST486_REG_GS
, LOWORD(NewSelector
));
720 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBts
)
722 BOOLEAN OperandSize
, AddressSize
;
723 FAST486_MOD_REG_RM ModRegRm
;
727 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
728 TOGGLE_OPSIZE(OperandSize
);
729 TOGGLE_ADSIZE(AddressSize
);
731 /* Get the number of bits */
732 if (OperandSize
) DataSize
= 32;
735 /* Get the operands */
736 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
738 /* Exception occurred */
742 /* Get the bit number */
743 BitNumber
= OperandSize
? State
->GeneralRegs
[ModRegRm
.Register
].Long
744 : (ULONG
)State
->GeneralRegs
[ModRegRm
.Register
].LowWord
;
749 * For memory operands, add the bit offset divided by
750 * the data size to the address
752 ModRegRm
.MemoryAddress
+= BitNumber
/ DataSize
;
755 /* Normalize the bit number */
756 BitNumber
%= DataSize
;
763 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, NULL
, &Value
))
765 /* Exception occurred */
769 /* Set CF to the bit value */
770 State
->Flags
.Cf
= (Value
>> BitNumber
) & 1;
773 Value
|= 1 << BitNumber
;
775 /* Write back the result */
776 if (!Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Value
))
778 /* Exception occurred */
787 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, NULL
, &Value
))
789 /* Exception occurred */
793 /* Set CF to the bit value */
794 State
->Flags
.Cf
= (Value
>> BitNumber
) & 1;
797 Value
|= 1 << BitNumber
;
799 /* Write back the result */
800 if (!Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Value
))
802 /* Exception occurred */
811 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeShrd
)
813 BOOLEAN OperandSize
, AddressSize
;
814 FAST486_MOD_REG_RM ModRegRm
;
817 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
818 TOGGLE_OPSIZE(OperandSize
);
819 TOGGLE_ADSIZE(AddressSize
);
821 /* Make sure this is the right instruction */
822 ASSERT((Opcode
& 0xFE) == 0xAC);
824 /* Get the operands */
825 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
827 /* Exception occurred */
833 /* Fetch the count */
834 if (!Fast486FetchByte(State
, &Count
))
836 /* Exception occurred */
842 /* The count is in CL */
843 Count
= State
->GeneralRegs
[FAST486_REG_ECX
].LowByte
;
846 /* Normalize the count */
849 /* Do nothing if the count is zero */
850 if (Count
== 0) return TRUE
;
854 ULONG Source
, Destination
, Result
;
856 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, &Source
, &Destination
))
858 /* Exception occurred */
862 /* Calculate the result */
863 Result
= (Destination
>> Count
) | (Source
<< (32 - Count
));
866 State
->Flags
.Cf
= (Destination
>> (Count
- 1)) & 1;
867 if (Count
== 1) State
->Flags
.Of
= (Result
& SIGN_FLAG_LONG
)
868 != (Destination
& SIGN_FLAG_LONG
);
869 State
->Flags
.Zf
= (Result
== 0);
870 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_LONG
) != 0);
871 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
873 /* Write back the result */
874 return Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Result
);
878 USHORT Source
, Destination
, Result
;
880 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, &Source
, &Destination
))
882 /* Exception occurred */
886 /* Calculate the result */
887 Result
= (Destination
>> Count
) | (Source
<< (16 - Count
));
889 if (Count
>= 16) Result
|= (ULONG
)(Source
| (Source
<< 16)) >> (Count
- 16);
892 if (Count
<= 16) State
->Flags
.Cf
= (Destination
>> (Count
- 1)) & 1;
893 else State
->Flags
.Cf
= (Source
>> (Count
- 17)) & 1;
895 if (Count
== 1) State
->Flags
.Of
= (Result
& SIGN_FLAG_WORD
)
896 != (Destination
& SIGN_FLAG_WORD
);
897 State
->Flags
.Zf
= (Result
== 0);
898 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_WORD
) != 0);
899 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
901 /* Write back the result */
902 return Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Result
);
906 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeImul
)
908 BOOLEAN OperandSize
, AddressSize
;
909 FAST486_MOD_REG_RM ModRegRm
;
911 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
913 TOGGLE_OPSIZE(OperandSize
);
914 TOGGLE_ADSIZE(AddressSize
);
916 /* Get the operands */
917 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
919 /* Exception occurred */
925 LONG Source
, Destination
;
928 /* Read the operands */
929 if (!Fast486ReadModrmDwordOperands(State
,
931 (PULONG
)&Destination
,
934 /* Exception occurred */
938 /* Calculate the result */
939 Result
= (LONGLONG
)Source
* (LONGLONG
)Destination
;
941 /* Update the flags */
942 State
->Flags
.Cf
= State
->Flags
.Of
= ((Result
< -2147483648LL) || (Result
> 2147483647LL));
944 /* Write back the result */
945 return Fast486WriteModrmDwordOperands(State
, &ModRegRm
, TRUE
, (ULONG
)((LONG
)Result
));
949 SHORT Source
, Destination
;
952 /* Read the operands */
953 if (!Fast486ReadModrmWordOperands(State
,
955 (PUSHORT
)&Destination
,
958 /* Exception occurred */
962 /* Calculate the result */
963 Result
= (LONG
)Source
* (LONG
)Destination
;
965 /* Update the flags */
966 State
->Flags
.Cf
= State
->Flags
.Of
= ((Result
< -32768) || (Result
> 32767));
968 /* Write back the result */
969 return Fast486WriteModrmWordOperands(State
, &ModRegRm
, TRUE
, (USHORT
)((SHORT
)Result
));
973 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeCmpXchgByte
)
975 FAST486_MOD_REG_RM ModRegRm
;
976 UCHAR Accumulator
= State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
;
977 UCHAR Source
, Destination
, Result
;
978 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
980 TOGGLE_ADSIZE(AddressSize
);
982 /* Get the operands */
983 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
985 /* Exception occurred */
989 /* Read the operands */
990 if (!Fast486ReadModrmByteOperands(State
, &ModRegRm
, &Source
, &Destination
))
992 /* Exception occurred */
996 /* Compare AL with the destination */
997 Result
= Accumulator
- Destination
;
999 /* Update the flags */
1000 State
->Flags
.Cf
= (Accumulator
< Destination
);
1001 State
->Flags
.Of
= ((Accumulator
& SIGN_FLAG_BYTE
) != (Destination
& SIGN_FLAG_BYTE
))
1002 && ((Accumulator
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
1003 State
->Flags
.Af
= (Accumulator
& 0x0F) < (Destination
& 0x0F);
1004 State
->Flags
.Zf
= (Result
== 0);
1005 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
1006 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1008 if (State
->Flags
.Zf
)
1010 /* Load the source operand into the destination */
1011 return Fast486WriteModrmByteOperands(State
, &ModRegRm
, FALSE
, Source
);
1015 /* Load the destination into AL */
1016 State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
= Destination
;
1019 /* Return success */
1023 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeCmpXchg
)
1025 FAST486_MOD_REG_RM ModRegRm
;
1026 BOOLEAN OperandSize
, AddressSize
;
1028 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1030 TOGGLE_OPSIZE(OperandSize
);
1031 TOGGLE_ADSIZE(AddressSize
);
1033 /* Get the operands */
1034 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1036 /* Exception occurred */
1042 ULONG Source
, Destination
, Result
;
1043 ULONG Accumulator
= State
->GeneralRegs
[FAST486_REG_EAX
].Long
;
1045 /* Read the operands */
1046 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, &Source
, &Destination
))
1048 /* Exception occurred */
1052 /* Compare EAX with the destination */
1053 Result
= Accumulator
- Destination
;
1055 /* Update the flags */
1056 State
->Flags
.Cf
= (Accumulator
< Destination
);
1057 State
->Flags
.Of
= ((Accumulator
& SIGN_FLAG_LONG
) != (Destination
& SIGN_FLAG_LONG
))
1058 && ((Accumulator
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
1059 State
->Flags
.Af
= (Accumulator
& 0x0F) < (Destination
& 0x0F);
1060 State
->Flags
.Zf
= (Result
== 0);
1061 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_LONG
) != 0);
1062 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1064 if (State
->Flags
.Zf
)
1066 /* Load the source operand into the destination */
1067 return Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Source
);
1071 /* Load the destination into EAX */
1072 State
->GeneralRegs
[FAST486_REG_EAX
].Long
= Destination
;
1077 USHORT Source
, Destination
, Result
;
1078 USHORT Accumulator
= State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
;
1080 /* Read the operands */
1081 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, &Source
, &Destination
))
1083 /* Exception occurred */
1087 /* Compare AX with the destination */
1088 Result
= Accumulator
- Destination
;
1090 /* Update the flags */
1091 State
->Flags
.Cf
= (Accumulator
< Destination
);
1092 State
->Flags
.Of
= ((Accumulator
& SIGN_FLAG_WORD
) != (Destination
& SIGN_FLAG_WORD
))
1093 && ((Accumulator
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
1094 State
->Flags
.Af
= (Accumulator
& 0x0F) < (Destination
& 0x0F);
1095 State
->Flags
.Zf
= (Result
== 0);
1096 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_WORD
) != 0);
1097 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1099 if (State
->Flags
.Zf
)
1101 /* Load the source operand into the destination */
1102 return Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Source
);
1106 /* Load the destination into AX */
1107 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= Destination
;
1111 /* Return success */
1115 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLss
)
1117 UCHAR FarPointer
[6];
1118 BOOLEAN OperandSize
, AddressSize
;
1119 FAST486_MOD_REG_RM ModRegRm
;
1121 /* Make sure this is the right instruction */
1122 ASSERT(Opcode
== 0xB2);
1124 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1126 TOGGLE_OPSIZE(OperandSize
);
1127 TOGGLE_ADSIZE(AddressSize
);
1129 /* Get the operands */
1130 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1132 /* Exception occurred */
1136 if (!ModRegRm
.Memory
)
1139 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
1143 if (!Fast486ReadMemory(State
,
1144 (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
1145 ? State
->SegmentOverride
: FAST486_REG_DS
,
1146 ModRegRm
.MemoryAddress
,
1149 OperandSize
? 6 : 4))
1151 /* Exception occurred */
1157 ULONG Offset
= *((PULONG
)FarPointer
);
1158 USHORT Segment
= *((PUSHORT
)&FarPointer
[sizeof(ULONG
)]);
1160 /* Set the register to the offset */
1161 State
->GeneralRegs
[ModRegRm
.Register
].Long
= Offset
;
1163 /* Load the segment */
1164 return Fast486LoadSegment(State
,
1170 USHORT Offset
= *((PUSHORT
)FarPointer
);
1171 USHORT Segment
= *((PUSHORT
)&FarPointer
[sizeof(USHORT
)]);
1173 /* Set the register to the offset */
1174 State
->GeneralRegs
[ModRegRm
.Register
].LowWord
= Offset
;
1176 /* Load the segment */
1177 return Fast486LoadSegment(State
,
1183 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBtr
)
1185 BOOLEAN OperandSize
, AddressSize
;
1186 FAST486_MOD_REG_RM ModRegRm
;
1190 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1191 TOGGLE_OPSIZE(OperandSize
);
1192 TOGGLE_ADSIZE(AddressSize
);
1194 /* Get the number of bits */
1195 if (OperandSize
) DataSize
= 32;
1198 /* Get the operands */
1199 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1201 /* Exception occurred */
1205 /* Get the bit number */
1206 BitNumber
= OperandSize
? State
->GeneralRegs
[ModRegRm
.Register
].Long
1207 : (ULONG
)State
->GeneralRegs
[ModRegRm
.Register
].LowWord
;
1209 if (ModRegRm
.Memory
)
1212 * For memory operands, add the bit offset divided by
1213 * the data size to the address
1215 ModRegRm
.MemoryAddress
+= BitNumber
/ DataSize
;
1218 /* Normalize the bit number */
1219 BitNumber
%= DataSize
;
1225 /* Read the value */
1226 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, NULL
, &Value
))
1228 /* Exception occurred */
1232 /* Set CF to the bit value */
1233 State
->Flags
.Cf
= (Value
>> BitNumber
) & 1;
1236 Value
&= ~(1 << BitNumber
);
1238 /* Write back the result */
1239 if (!Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Value
))
1241 /* Exception occurred */
1249 /* Read the value */
1250 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, NULL
, &Value
))
1252 /* Exception occurred */
1256 /* Set CF to the bit value */
1257 State
->Flags
.Cf
= (Value
>> BitNumber
) & 1;
1260 Value
&= ~(1 << BitNumber
);
1262 /* Write back the result */
1263 if (!Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Value
))
1265 /* Exception occurred */
1270 /* Return success */
1274 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLfsLgs
)
1276 UCHAR FarPointer
[6];
1277 BOOLEAN OperandSize
, AddressSize
;
1278 FAST486_MOD_REG_RM ModRegRm
;
1280 /* Make sure this is the right instruction */
1281 ASSERT((Opcode
& 0xFE) == 0xB4);
1283 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1285 TOGGLE_OPSIZE(OperandSize
);
1286 TOGGLE_ADSIZE(AddressSize
);
1288 /* Get the operands */
1289 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1291 /* Exception occurred */
1295 if (!ModRegRm
.Memory
)
1298 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
1302 if (!Fast486ReadMemory(State
,
1303 (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
1304 ? State
->SegmentOverride
: FAST486_REG_DS
,
1305 ModRegRm
.MemoryAddress
,
1308 OperandSize
? 6 : 4))
1310 /* Exception occurred */
1316 ULONG Offset
= *((PULONG
)FarPointer
);
1317 USHORT Segment
= *((PUSHORT
)&FarPointer
[sizeof(ULONG
)]);
1319 /* Set the register to the offset */
1320 State
->GeneralRegs
[ModRegRm
.Register
].Long
= Offset
;
1322 /* Load the segment */
1323 return Fast486LoadSegment(State
,
1325 ? FAST486_REG_FS
: FAST486_REG_GS
,
1330 USHORT Offset
= *((PUSHORT
)FarPointer
);
1331 USHORT Segment
= *((PUSHORT
)&FarPointer
[sizeof(USHORT
)]);
1333 /* Set the register to the offset */
1334 State
->GeneralRegs
[ModRegRm
.Register
].LowWord
= Offset
;
1336 /* Load the segment */
1337 return Fast486LoadSegment(State
,
1339 ? FAST486_REG_FS
: FAST486_REG_GS
,
1344 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeMovzxByte
)
1347 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1348 FAST486_MOD_REG_RM ModRegRm
;
1350 TOGGLE_ADSIZE(AddressSize
);
1352 /* Make sure this is the right instruction */
1353 ASSERT(Opcode
== 0xB6);
1355 /* Get the operands */
1356 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1358 /* Exception occurred */
1362 /* Read the operands */
1363 if (!Fast486ReadModrmByteOperands(State
, &ModRegRm
, NULL
, &Value
))
1365 /* Exception occurred */
1369 /* Write back the zero-extended value */
1370 return Fast486WriteModrmDwordOperands(State
,
1376 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeMovzxWord
)
1379 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1380 FAST486_MOD_REG_RM ModRegRm
;
1382 TOGGLE_ADSIZE(AddressSize
);
1384 /* Make sure this is the right instruction */
1385 ASSERT(Opcode
== 0xB7);
1387 /* Get the operands */
1388 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1390 /* Exception occurred */
1394 /* Read the operands */
1395 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, NULL
, &Value
))
1397 /* Exception occurred */
1401 /* Write back the zero-extended value */
1402 return Fast486WriteModrmDwordOperands(State
,
1408 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBtc
)
1410 BOOLEAN OperandSize
, AddressSize
;
1411 FAST486_MOD_REG_RM ModRegRm
;
1415 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1416 TOGGLE_OPSIZE(OperandSize
);
1417 TOGGLE_ADSIZE(AddressSize
);
1419 /* Get the number of bits */
1420 if (OperandSize
) DataSize
= 32;
1423 /* Get the operands */
1424 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1426 /* Exception occurred */
1430 /* Get the bit number */
1431 BitNumber
= OperandSize
? State
->GeneralRegs
[ModRegRm
.Register
].Long
1432 : (ULONG
)State
->GeneralRegs
[ModRegRm
.Register
].LowWord
;
1434 if (ModRegRm
.Memory
)
1437 * For memory operands, add the bit offset divided by
1438 * the data size to the address
1440 ModRegRm
.MemoryAddress
+= BitNumber
/ DataSize
;
1443 /* Normalize the bit number */
1444 BitNumber
%= DataSize
;
1450 /* Read the value */
1451 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, NULL
, &Value
))
1453 /* Exception occurred */
1457 /* Set CF to the bit value */
1458 State
->Flags
.Cf
= (Value
>> BitNumber
) & 1;
1460 /* Toggle the bit */
1461 Value
^= 1 << BitNumber
;
1463 /* Write back the result */
1464 if (!Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Value
))
1466 /* Exception occurred */
1474 /* Read the value */
1475 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, NULL
, &Value
))
1477 /* Exception occurred */
1481 /* Set CF to the bit value */
1482 State
->Flags
.Cf
= (Value
>> BitNumber
) & 1;
1484 /* Toggle the bit */
1485 Value
^= 1 << BitNumber
;
1487 /* Write back the result */
1488 if (!Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Value
))
1490 /* Exception occurred */
1495 /* Return success */
1499 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBsf
)
1503 BOOLEAN OperandSize
, AddressSize
;
1504 FAST486_MOD_REG_RM ModRegRm
;
1508 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1509 TOGGLE_OPSIZE(OperandSize
);
1510 TOGGLE_ADSIZE(AddressSize
);
1512 /* Make sure this is the right instruction */
1513 ASSERT(Opcode
== 0xBC);
1515 /* Get the number of bits */
1516 if (OperandSize
) DataSize
= 32;
1519 /* Get the operands */
1520 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1522 /* Exception occurred */
1526 /* Read the value */
1529 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, NULL
, &Value
))
1531 /* Exception occurred */
1537 if (!Fast486ReadModrmWordOperands(State
,
1542 /* Exception occurred */
1548 State
->Flags
.Zf
= (Value
== 0);
1549 if (State
->Flags
.Zf
) return TRUE
;
1551 for (i
= 0; i
< DataSize
; i
++)
1553 if(Value
& (1 << i
))
1555 /* Save the bit number */
1563 /* Write back the result */
1566 if (!Fast486WriteModrmDwordOperands(State
, &ModRegRm
, TRUE
, BitNumber
))
1568 /* Exception occurred */
1574 if (!Fast486WriteModrmWordOperands(State
, &ModRegRm
, TRUE
, LOWORD(BitNumber
)))
1576 /* Exception occurred */
1584 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBsr
)
1588 BOOLEAN OperandSize
, AddressSize
;
1589 FAST486_MOD_REG_RM ModRegRm
;
1593 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1594 TOGGLE_OPSIZE(OperandSize
);
1595 TOGGLE_ADSIZE(AddressSize
);
1597 /* Make sure this is the right instruction */
1598 ASSERT(Opcode
== 0xBD);
1600 /* Get the number of bits */
1601 if (OperandSize
) DataSize
= 32;
1604 /* Get the operands */
1605 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1607 /* Exception occurred */
1611 /* Read the value */
1614 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, NULL
, &Value
))
1616 /* Exception occurred */
1622 if (!Fast486ReadModrmWordOperands(State
,
1627 /* Exception occurred */
1632 /* Set ZF according to the value */
1633 State
->Flags
.Zf
= (Value
== 0);
1634 if (State
->Flags
.Zf
) return TRUE
;
1636 for (i
= DataSize
- 1; i
>= 0; i
--)
1638 if(Value
& (1 << i
))
1640 /* Save the bit number */
1648 /* Write back the result */
1651 if (!Fast486WriteModrmDwordOperands(State
, &ModRegRm
, TRUE
, BitNumber
))
1653 /* Exception occurred */
1659 if (!Fast486WriteModrmWordOperands(State
, &ModRegRm
, TRUE
, LOWORD(BitNumber
)))
1661 /* Exception occurred */
1669 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeMovsxByte
)
1672 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1673 FAST486_MOD_REG_RM ModRegRm
;
1675 TOGGLE_ADSIZE(AddressSize
);
1677 /* Make sure this is the right instruction */
1678 ASSERT(Opcode
== 0xBE);
1680 /* Get the operands */
1681 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1683 /* Exception occurred */
1687 /* Read the operands */
1688 if (!Fast486ReadModrmByteOperands(State
, &ModRegRm
, NULL
, (PUCHAR
)&Value
))
1690 /* Exception occurred */
1694 /* Write back the sign-extended value */
1695 return Fast486WriteModrmDwordOperands(State
,
1698 (ULONG
)((LONG
)Value
));
1701 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeMovsxWord
)
1704 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1705 FAST486_MOD_REG_RM ModRegRm
;
1707 TOGGLE_ADSIZE(AddressSize
);
1709 /* Make sure this is the right instruction */
1710 ASSERT(Opcode
== 0xBF);
1712 /* Get the operands */
1713 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1715 /* Exception occurred */
1719 /* Read the operands */
1720 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, NULL
, (PUSHORT
)&Value
))
1722 /* Exception occurred */
1726 /* Write back the sign-extended value */
1727 return Fast486WriteModrmDwordOperands(State
,
1730 (ULONG
)((LONG
)Value
));
1733 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeConditionalJmp
)
1735 BOOLEAN Jump
= FALSE
;
1737 BOOLEAN Size
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1739 TOGGLE_OPSIZE(Size
);
1742 /* Make sure this is the right instruction */
1743 ASSERT((Opcode
& 0xF0) == 0x80);
1745 /* Fetch the offset */
1748 if (!Fast486FetchDword(State
, (PULONG
)&Offset
))
1750 /* Exception occurred */
1758 if (!Fast486FetchWord(State
, (PUSHORT
)&Value
))
1760 /* Exception occurred */
1765 Offset
= (LONG
)Value
;
1768 switch ((Opcode
& 0x0F) >> 1)
1773 Jump
= State
->Flags
.Of
;
1780 Jump
= State
->Flags
.Cf
;
1787 Jump
= State
->Flags
.Zf
;
1794 Jump
= State
->Flags
.Cf
|| State
->Flags
.Zf
;
1801 Jump
= State
->Flags
.Sf
;
1808 Jump
= State
->Flags
.Pf
;
1815 Jump
= State
->Flags
.Sf
!= State
->Flags
.Of
;
1822 Jump
= (State
->Flags
.Sf
!= State
->Flags
.Of
) || State
->Flags
.Zf
;
1829 /* Invert the result */
1835 /* Move the instruction pointer */
1836 State
->InstPtr
.Long
+= Offset
;
1839 /* Return success */
1843 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeConditionalSet
)
1845 BOOLEAN Value
= FALSE
;
1846 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1847 FAST486_MOD_REG_RM ModRegRm
;
1849 TOGGLE_ADSIZE(AddressSize
);
1851 /* Get the operands */
1852 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1854 /* Exception occurred */
1858 /* Make sure this is the right instruction */
1859 ASSERT((Opcode
& 0xF0) == 0x90);
1861 switch ((Opcode
& 0x0F) >> 1)
1866 Value
= State
->Flags
.Of
;
1873 Value
= State
->Flags
.Cf
;
1880 Value
= State
->Flags
.Zf
;
1884 /* SETBE / SETNBE */
1887 Value
= State
->Flags
.Cf
|| State
->Flags
.Zf
;
1894 Value
= State
->Flags
.Sf
;
1901 Value
= State
->Flags
.Pf
;
1908 Value
= State
->Flags
.Sf
!= State
->Flags
.Of
;
1912 /* SETLE / SETNLE */
1915 Value
= (State
->Flags
.Sf
!= State
->Flags
.Of
) || State
->Flags
.Zf
;
1922 /* Invert the result */
1926 /* Write back the result */
1927 return Fast486WriteModrmByteOperands(State
, &ModRegRm
, FALSE
, Value
);
1930 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeXaddByte
)
1932 UCHAR Source
, Destination
, Result
;
1933 FAST486_MOD_REG_RM ModRegRm
;
1934 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1936 /* Make sure this is the right instruction */
1937 ASSERT(Opcode
== 0xC0);
1939 TOGGLE_ADSIZE(AddressSize
);
1941 /* Get the operands */
1942 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1944 /* Exception occurred */
1948 if (!Fast486ReadModrmByteOperands(State
,
1953 /* Exception occurred */
1957 /* Calculate the result */
1958 Result
= Source
+ Destination
;
1960 /* Update the flags */
1961 State
->Flags
.Cf
= (Result
< Source
) && (Result
< Destination
);
1962 State
->Flags
.Of
= ((Source
& SIGN_FLAG_BYTE
) == (Destination
& SIGN_FLAG_BYTE
))
1963 && ((Source
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
1964 State
->Flags
.Af
= ((((Source
& 0x0F) + (Destination
& 0x0F)) & 0x10) != 0);
1965 State
->Flags
.Zf
= (Result
== 0);
1966 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
1967 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1969 /* Write the sum to the destination */
1970 if (!Fast486WriteModrmByteOperands(State
, &ModRegRm
, FALSE
, Result
))
1972 /* Exception occurred */
1976 /* Write the old value of the destination to the source */
1977 if (!Fast486WriteModrmByteOperands(State
, &ModRegRm
, TRUE
, Destination
))
1979 /* Exception occurred */
1986 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeXadd
)
1988 FAST486_MOD_REG_RM ModRegRm
;
1989 BOOLEAN OperandSize
, AddressSize
;
1991 /* Make sure this is the right instruction */
1992 ASSERT(Opcode
== 0xC1);
1994 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1996 TOGGLE_ADSIZE(AddressSize
);
1997 TOGGLE_OPSIZE(OperandSize
);
1999 /* Get the operands */
2000 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2002 /* Exception occurred */
2006 /* Check the operand size */
2009 ULONG Source
, Destination
, Result
;
2011 if (!Fast486ReadModrmDwordOperands(State
,
2016 /* Exception occurred */
2020 /* Calculate the result */
2021 Result
= Source
+ Destination
;
2023 /* Update the flags */
2024 State
->Flags
.Cf
= (Result
< Source
) && (Result
< Destination
);
2025 State
->Flags
.Of
= ((Source
& SIGN_FLAG_LONG
) == (Destination
& SIGN_FLAG_LONG
))
2026 && ((Source
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
2027 State
->Flags
.Af
= ((((Source
& 0x0F) + (Destination
& 0x0F)) & 0x10) != 0);
2028 State
->Flags
.Zf
= (Result
== 0);
2029 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_LONG
) != 0);
2030 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2032 /* Write the old value of the destination to the source */
2033 if (!Fast486WriteModrmDwordOperands(State
, &ModRegRm
, TRUE
, Destination
))
2035 /* Exception occurred */
2039 /* Write the sum to the destination */
2040 if (!Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Result
))
2042 /* Exception occurred */
2048 USHORT Source
, Destination
, Result
;
2050 if (!Fast486ReadModrmWordOperands(State
,
2055 /* Exception occurred */
2059 /* Calculate the result */
2060 Result
= Source
+ Destination
;
2062 /* Update the flags */
2063 State
->Flags
.Cf
= (Result
< Source
) && (Result
< Destination
);
2064 State
->Flags
.Of
= ((Source
& SIGN_FLAG_WORD
) == (Destination
& SIGN_FLAG_WORD
))
2065 && ((Source
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
2066 State
->Flags
.Af
= ((((Source
& 0x0F) + (Destination
& 0x0F)) & 0x10) != 0);
2067 State
->Flags
.Zf
= (Result
== 0);
2068 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_WORD
) != 0);
2069 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2071 /* Write the old value of the destination to the source */
2072 if (!Fast486WriteModrmWordOperands(State
, &ModRegRm
, TRUE
, Destination
))
2074 /* Exception occurred */
2078 /* Write the sum to the destination */
2079 if (!Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Result
))
2081 /* Exception occurred */
2089 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBswap
)
2095 /* Get a pointer to the value */
2096 Pointer
= (PUCHAR
)&State
->GeneralRegs
[Opcode
& 0x07].Long
;
2098 /* Swap the byte order */
2099 SWAP(Pointer
[0], Pointer
[3]);
2100 SWAP(Pointer
[1], Pointer
[2]);
2102 /* Return success */
2106 FAST486_OPCODE_HANDLER(Fast486OpcodeExtended
)
2110 /* Fetch the second operation code */
2111 if (!Fast486FetchByte(State
, &SecondOpcode
))
2113 /* Exception occurred */
2117 if (Fast486ExtendedHandlers
[SecondOpcode
] != NULL
)
2119 /* Call the extended opcode handler */
2120 return Fast486ExtendedHandlers
[SecondOpcode
](State
, SecondOpcode
);
2124 /* This is not a valid opcode */
2125 Fast486Exception(State
, FAST486_EXCEPTION_UD
);