2 * Soft386 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 *******************************************************************/
24 // #define WIN32_NO_STATUS
25 // #define _INC_WINDOWS
35 /* PRIVATE FUNCTIONS **********************************************************/
40 Soft386ArithmeticOperation(PSOFT386_STATE State
,
47 ULONG SignFlag
= 1 << (Bits
- 1);
48 ULONG MaxValue
= (1 << Bits
) - 1;
50 /* Make sure the values don't exceed the maximum for their size */
51 FirstValue
&= MaxValue
;
52 SecondValue
&= MaxValue
;
54 /* Check which operation is this */
60 Result
= (FirstValue
+ SecondValue
) & MaxValue
;
62 /* Update CF, OF and AF */
63 State
->Flags
.Cf
= (Result
< FirstValue
) && (Result
< SecondValue
);
64 State
->Flags
.Of
= ((FirstValue
& SignFlag
) == (SecondValue
& SignFlag
))
65 && ((FirstValue
& SignFlag
) != (Result
& SignFlag
));
66 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
74 Result
= FirstValue
| SecondValue
;
81 INT Carry
= State
->Flags
.Cf
? 1 : 0;
83 Result
= (FirstValue
+ SecondValue
+ Carry
) & MaxValue
;
85 /* Update CF, OF and AF */
86 State
->Flags
.Cf
= ((SecondValue
== MaxValue
) && (Carry
== 1))
87 || ((Result
< FirstValue
) && (Result
< (SecondValue
+ Carry
)));
88 State
->Flags
.Of
= ((FirstValue
& SignFlag
) == (SecondValue
& SignFlag
))
89 && ((FirstValue
& SignFlag
) != (Result
& SignFlag
));
90 State
->Flags
.Af
= (((FirstValue
& 0x0F) + ((SecondValue
+ Carry
) & 0x0F)) & 0x10)
99 INT Carry
= State
->Flags
.Cf
? 1 : 0;
101 Result
= (FirstValue
- SecondValue
- Carry
) & MaxValue
;
103 /* Update CF, OF and AF */
104 State
->Flags
.Cf
= FirstValue
< (SecondValue
+ Carry
);
105 State
->Flags
.Of
= ((FirstValue
& SignFlag
) != (SecondValue
& SignFlag
))
106 && ((FirstValue
& SignFlag
) != (Result
& SignFlag
));
107 State
->Flags
.Af
= (FirstValue
& 0x0F) < ((SecondValue
+ Carry
) & 0x0F);
115 Result
= FirstValue
& SecondValue
;
123 Result
= (FirstValue
- SecondValue
) & MaxValue
;
125 /* Update CF, OF and AF */
126 State
->Flags
.Cf
= FirstValue
< SecondValue
;
127 State
->Flags
.Of
= ((FirstValue
& SignFlag
) != (SecondValue
& SignFlag
))
128 && ((FirstValue
& SignFlag
) != (Result
& SignFlag
));
129 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
137 Result
= FirstValue
^ SecondValue
;
143 /* Shouldn't happen */
148 /* Update ZF, SF and PF */
149 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
150 State
->Flags
.Sf
= (Result
& SignFlag
) ? TRUE
: FALSE
;
151 State
->Flags
.Pf
= Soft386CalculateParity(LOBYTE(Result
));
153 /* Return the result */
160 Soft386RotateOperation(PSOFT386_STATE State
,
166 ULONG HighestBit
= 1 << (Bits
- 1);
169 if ((Operation
!= 2) && (Operation
!= 3))
176 /* For RCL and RCR, the CF is included in the value */
180 /* Check which operation is this */
186 Result
= (Value
<< Count
) | (Value
>> (Bits
- Count
));
188 /* Update CF and OF */
189 State
->Flags
.Cf
= Result
& 1;
190 if (Count
== 1) State
->Flags
.Of
= ((Result
& HighestBit
) ? TRUE
: FALSE
)
199 Result
= (Value
>> Count
) | (Value
<< (Bits
- Count
));
201 /* Update CF and OF */
202 State
->Flags
.Cf
= (Result
& HighestBit
) ? TRUE
: FALSE
;
203 if (Count
== 1) State
->Flags
.Of
= State
->Flags
.Cf
204 ^ ((Result
& (HighestBit
>> 1))
213 Result
= (Value
<< Count
)
214 | (State
->Flags
.Cf
<< (Count
- 1))
215 | (Value
>> (Bits
- Count
+ 1));
217 /* Update CF and OF */
218 State
->Flags
.Cf
= (Value
& (1 << (Bits
- Count
))) ? TRUE
: FALSE
;
219 if (Count
== 1) State
->Flags
.Of
= ((Result
& HighestBit
) ? TRUE
: FALSE
)
228 Result
= (Value
>> Count
)
229 | (State
->Flags
.Cf
<< (Bits
- Count
))
230 | (Value
<< (Bits
- Count
+ 1));
232 /* Update CF and OF */
233 State
->Flags
.Cf
= (Value
& (1 << (Bits
- Count
))) ? TRUE
: FALSE
;
234 if (Count
== 1) State
->Flags
.Of
= State
->Flags
.Cf
235 ^ ((Result
& (HighestBit
>> 1))
245 Result
= Value
<< Count
;
247 /* Update CF and OF */
248 State
->Flags
.Cf
= (Value
& (1 << (Bits
- Count
))) ? TRUE
: FALSE
;
249 if (Count
== 1) State
->Flags
.Of
= ((Result
& HighestBit
) ? TRUE
: FALSE
)
250 ^ (State
->Flags
.Cf
? TRUE
: FALSE
);
258 Result
= Value
>> Count
;
260 /* Update CF and OF */
261 State
->Flags
.Cf
= (Value
& (1 << (Count
- 1))) ? TRUE
: FALSE
;
262 if (Count
== 1) State
->Flags
.Of
= (Value
& HighestBit
) ? TRUE
: FALSE
;
270 Result
= Value
>> Count
;
272 /* Fill the top Count bits with the sign bit */
273 if (Value
& HighestBit
) Result
|= ((1 << Count
) - 1) << (Bits
- Count
);
275 /* Update CF and OF */
276 State
->Flags
.Cf
= (Value
& (1 << (Count
- 1))) ? TRUE
: FALSE
;
277 if (Count
== 1) State
->Flags
.Of
= FALSE
;
283 /* Update ZF, SF and PF */
284 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
285 State
->Flags
.Sf
= (Result
& HighestBit
) ? TRUE
: FALSE
;
286 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
288 /* Return the result */
292 /* PUBLIC FUNCTIONS ***********************************************************/
294 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroup8082
)
296 UCHAR Immediate
, Dummy
, Value
;
297 SOFT386_MOD_REG_RM ModRegRm
;
298 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
300 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
302 /* The ADSIZE prefix toggles the size */
303 AddressSize
= !AddressSize
;
306 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
308 /* Exception occurred */
312 /* Fetch the immediate operand */
313 if (!Soft386FetchByte(State
, &Immediate
))
315 /* Exception occurred */
319 /* Read the operands */
320 if (!Soft386ReadModrmByteOperands(State
, &ModRegRm
, &Dummy
, &Value
))
322 /* Exception occurred */
326 /* Calculate the result */
327 Value
= Soft386ArithmeticOperation(State
, ModRegRm
.Register
, Value
, Immediate
, 8);
329 /* Unless this is CMP, write back the result */
330 if (ModRegRm
.Register
!= 7)
332 return Soft386WriteModrmByteOperands(State
, &ModRegRm
, FALSE
, Value
);
338 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroup81
)
340 SOFT386_MOD_REG_RM ModRegRm
;
341 BOOLEAN OperandSize
, AddressSize
;
343 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
345 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
347 /* The OPSIZE prefix toggles the size */
348 OperandSize
= !OperandSize
;
351 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
353 /* The ADSIZE prefix toggles the size */
354 AddressSize
= !AddressSize
;
357 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
359 /* Exception occurred */
365 ULONG Immediate
, Value
, Dummy
;
367 /* Fetch the immediate operand */
368 if (!Soft386FetchDword(State
, &Immediate
))
370 /* Exception occurred */
374 /* Read the operands */
375 if (!Soft386ReadModrmDwordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
377 /* Exception occurred */
381 /* Calculate the result */
382 Value
= Soft386ArithmeticOperation(State
, ModRegRm
.Register
, Value
, Immediate
, 32);
384 /* Unless this is CMP, write back the result */
385 if (ModRegRm
.Register
!= 7)
387 return Soft386WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Value
);
392 USHORT Immediate
, Value
, Dummy
;
394 /* Fetch the immediate operand */
395 if (!Soft386FetchWord(State
, &Immediate
))
397 /* Exception occurred */
401 /* Read the operands */
402 if (!Soft386ReadModrmWordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
404 /* Exception occurred */
408 /* Calculate the result */
409 Value
= Soft386ArithmeticOperation(State
, ModRegRm
.Register
, Value
, Immediate
, 16);
411 /* Unless this is CMP, write back the result */
412 if (ModRegRm
.Register
!= 7)
414 return Soft386WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Value
);
421 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroup83
)
424 SOFT386_MOD_REG_RM ModRegRm
;
425 BOOLEAN OperandSize
, AddressSize
;
427 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
429 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
431 /* The OPSIZE prefix toggles the size */
432 OperandSize
= !OperandSize
;
435 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
437 /* The ADSIZE prefix toggles the size */
438 AddressSize
= !AddressSize
;
441 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
443 /* Exception occurred */
447 /* Fetch the immediate operand */
448 if (!Soft386FetchByte(State
, (PUCHAR
)&ImmByte
))
450 /* Exception occurred */
456 ULONG Immediate
= (ULONG
)((LONG
)ImmByte
); // Sign extend
459 /* Read the operands */
460 if (!Soft386ReadModrmDwordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
462 /* Exception occurred */
466 /* Calculate the result */
467 Value
= Soft386ArithmeticOperation(State
, ModRegRm
.Register
, Value
, Immediate
, 32);
469 /* Unless this is CMP, write back the result */
470 if (ModRegRm
.Register
!= 7)
472 return Soft386WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Value
);
477 USHORT Immediate
= (USHORT
)((SHORT
)ImmByte
); // Sign extend
480 /* Read the operands */
481 if (!Soft386ReadModrmWordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
483 /* Exception occurred */
487 /* Calculate the result */
488 Value
= Soft386ArithmeticOperation(State
, ModRegRm
.Register
, Value
, Immediate
, 16);
490 /* Unless this is CMP, write back the result */
491 if (ModRegRm
.Register
!= 7)
493 return Soft386WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Value
);
500 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroup8F
)
503 SOFT386_MOD_REG_RM ModRegRm
;
504 BOOLEAN OperandSize
, AddressSize
;
506 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
508 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
510 /* The OPSIZE prefix toggles the size */
511 OperandSize
= !OperandSize
;
514 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
516 /* The ADSIZE prefix toggles the size */
517 AddressSize
= !AddressSize
;
520 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
522 /* Exception occurred */
526 if (ModRegRm
.Register
!= 0)
529 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
533 /* Pop a value from the stack */
534 if (!Soft386StackPop(State
, &Value
))
536 /* Exception occurred */
542 return Soft386WriteModrmDwordOperands(State
,
549 return Soft386WriteModrmWordOperands(State
,
556 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupC0
)
558 UCHAR Dummy
, Value
, Count
;
559 SOFT386_MOD_REG_RM ModRegRm
;
560 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
562 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
564 /* The ADSIZE prefix toggles the size */
565 AddressSize
= !AddressSize
;
568 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
570 /* Exception occurred */
574 /* Fetch the count */
575 if (!Soft386FetchByte(State
, &Count
))
577 /* Exception occurred */
581 /* Read the operands */
582 if (!Soft386ReadModrmByteOperands(State
, &ModRegRm
, &Dummy
, &Value
))
584 /* Exception occurred */
588 /* Calculate the result */
589 Value
= LOBYTE(Soft386RotateOperation(State
,
595 /* Write back the result */
596 return Soft386WriteModrmByteOperands(State
,
602 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupC1
)
605 SOFT386_MOD_REG_RM ModRegRm
;
606 BOOLEAN OperandSize
, AddressSize
;
608 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
610 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
612 /* The OPSIZE prefix toggles the size */
613 OperandSize
= !OperandSize
;
616 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
618 /* The ADSIZE prefix toggles the size */
619 AddressSize
= !AddressSize
;
622 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
624 /* Exception occurred */
628 /* Fetch the count */
629 if (!Soft386FetchByte(State
, &Count
))
631 /* Exception occurred */
639 /* Read the operands */
640 if (!Soft386ReadModrmDwordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
642 /* Exception occurred */
646 /* Calculate the result */
647 Value
= Soft386RotateOperation(State
,
653 /* Write back the result */
654 return Soft386WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Value
);
660 /* Read the operands */
661 if (!Soft386ReadModrmWordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
663 /* Exception occurred */
667 /* Calculate the result */
668 Value
= LOWORD(Soft386RotateOperation(State
,
674 /* Write back the result */
675 return Soft386WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Value
);
679 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupC6
)
682 SOFT386_MOD_REG_RM ModRegRm
;
683 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
685 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
687 /* The ADSIZE prefix toggles the size */
688 AddressSize
= !AddressSize
;
691 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
693 /* Exception occurred */
697 if (ModRegRm
.Register
!= 0)
700 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
704 /* Get the immediate operand */
705 if (!Soft386FetchByte(State
, &Immediate
))
707 /* Exception occurred */
711 return Soft386WriteModrmByteOperands(State
,
717 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupC7
)
719 SOFT386_MOD_REG_RM ModRegRm
;
720 BOOLEAN OperandSize
, AddressSize
;
722 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
724 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
726 /* The OPSIZE prefix toggles the size */
727 OperandSize
= !OperandSize
;
730 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
732 /* The ADSIZE prefix toggles the size */
733 AddressSize
= !AddressSize
;
736 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
738 /* Exception occurred */
742 if (ModRegRm
.Register
!= 0)
745 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
753 /* Get the immediate operand */
754 if (!Soft386FetchDword(State
, &Immediate
))
756 /* Exception occurred */
760 return Soft386WriteModrmDwordOperands(State
,
769 /* Get the immediate operand */
770 if (!Soft386FetchWord(State
, &Immediate
))
772 /* Exception occurred */
776 return Soft386WriteModrmWordOperands(State
,
783 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupD0
)
786 SOFT386_MOD_REG_RM ModRegRm
;
787 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
789 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
791 /* The ADSIZE prefix toggles the size */
792 AddressSize
= !AddressSize
;
795 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
797 /* Exception occurred */
801 /* Read the operands */
802 if (!Soft386ReadModrmByteOperands(State
, &ModRegRm
, &Dummy
, &Value
))
804 /* Exception occurred */
808 /* Calculate the result */
809 Value
= LOBYTE(Soft386RotateOperation(State
, ModRegRm
.Register
, Value
, 8, 1));
811 /* Write back the result */
812 return Soft386WriteModrmByteOperands(State
,
819 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupD1
)
821 SOFT386_MOD_REG_RM ModRegRm
;
822 BOOLEAN OperandSize
, AddressSize
;
824 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
826 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
828 /* The OPSIZE prefix toggles the size */
829 OperandSize
= !OperandSize
;
833 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
835 /* The ADSIZE prefix toggles the size */
836 AddressSize
= !AddressSize
;
839 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
841 /* Exception occurred */
849 /* Read the operands */
850 if (!Soft386ReadModrmDwordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
852 /* Exception occurred */
856 /* Calculate the result */
857 Value
= Soft386RotateOperation(State
, ModRegRm
.Register
, Value
, 32, 1);
859 /* Write back the result */
860 return Soft386WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Value
);
866 /* Read the operands */
867 if (!Soft386ReadModrmWordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
869 /* Exception occurred */
873 /* Calculate the result */
874 Value
= LOWORD(Soft386RotateOperation(State
, ModRegRm
.Register
, Value
, 16, 1));
876 /* Write back the result */
877 return Soft386WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Value
);
881 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupD2
)
884 SOFT386_MOD_REG_RM ModRegRm
;
885 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
887 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
889 /* The ADSIZE prefix toggles the size */
890 AddressSize
= !AddressSize
;
893 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
895 /* Exception occurred */
899 /* Read the operands */
900 if (!Soft386ReadModrmByteOperands(State
, &ModRegRm
, &Dummy
, &Value
))
902 /* Exception occurred */
906 /* Calculate the result */
907 Value
= LOBYTE(Soft386RotateOperation(State
,
911 State
->GeneralRegs
[SOFT386_REG_ECX
].LowByte
));
913 /* Write back the result */
914 return Soft386WriteModrmByteOperands(State
,
920 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupD3
)
922 SOFT386_MOD_REG_RM ModRegRm
;
923 BOOLEAN OperandSize
, AddressSize
;
925 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
927 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
929 /* The OPSIZE prefix toggles the size */
930 OperandSize
= !OperandSize
;
933 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
935 /* The ADSIZE prefix toggles the size */
936 AddressSize
= !AddressSize
;
939 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
941 /* Exception occurred */
949 /* Read the operands */
950 if (!Soft386ReadModrmDwordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
952 /* Exception occurred */
956 /* Calculate the result */
957 Value
= Soft386RotateOperation(State
,
961 State
->GeneralRegs
[SOFT386_REG_ECX
].LowByte
);
963 /* Write back the result */
964 return Soft386WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Value
);
970 /* Read the operands */
971 if (!Soft386ReadModrmWordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
973 /* Exception occurred */
977 /* Calculate the result */
978 Value
= LOWORD(Soft386RotateOperation(State
,
982 State
->GeneralRegs
[SOFT386_REG_ECX
].LowByte
));
984 /* Write back the result */
985 return Soft386WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Value
);
989 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupF6
)
992 SOFT386_MOD_REG_RM ModRegRm
;
993 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
995 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
997 /* The ADSIZE prefix toggles the size */
998 AddressSize
= !AddressSize
;
1001 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1003 /* Exception occurred */
1007 /* Read the operands */
1008 if (!Soft386ReadModrmByteOperands(State
, &ModRegRm
, &Dummy
, &Value
))
1010 /* Exception occurred */
1014 switch (ModRegRm
.Register
)
1020 UCHAR Immediate
, Result
;
1022 /* Fetch the immediate byte */
1023 if (!Soft386FetchByte(State
, &Immediate
))
1025 /* Exception occurred */
1029 /* Calculate the result */
1030 Result
= Value
& Immediate
;
1032 /* Update the flags */
1033 State
->Flags
.Cf
= FALSE
;
1034 State
->Flags
.Of
= FALSE
;
1035 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1036 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
1037 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1045 /* Write back the result */
1046 return Soft386WriteModrmByteOperands(State
, &ModRegRm
, FALSE
, ~Value
);
1052 /* Calculate the result */
1053 UCHAR Result
= -Value
;
1055 /* Update the flags */
1056 State
->Flags
.Cf
= (Value
!= 0) ? TRUE
: FALSE
;
1057 State
->Flags
.Of
= (Value
& SIGN_FLAG_BYTE
) && (Result
& SIGN_FLAG_BYTE
);
1058 State
->Flags
.Af
= ((Value
& 0x0F) != 0) ? TRUE
: FALSE
;
1059 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1060 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
1061 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1063 /* Write back the result */
1064 return Soft386WriteModrmByteOperands(State
, &ModRegRm
, FALSE
, Result
);
1070 USHORT Result
= (USHORT
)Value
* (USHORT
)State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
1072 /* Update the flags */
1073 State
->Flags
.Cf
= State
->Flags
.Of
= HIBYTE(Result
) ? TRUE
: FALSE
;
1075 /* Write back the result */
1076 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= Result
;
1084 SHORT Result
= (SHORT
)Value
* (SHORT
)State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
1086 /* Update the flags */
1087 State
->Flags
.Cf
= State
->Flags
.Of
=
1088 ((Result
< -128) || (Result
> 127)) ? TRUE
: FALSE
;
1090 /* Write back the result */
1091 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= (USHORT
)Result
;
1099 UCHAR Quotient
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
/ Value
;
1100 UCHAR Remainder
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
% Value
;
1102 /* Write back the results */
1103 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Quotient
;
1104 State
->GeneralRegs
[SOFT386_REG_EAX
].HighByte
= Remainder
;
1112 CHAR Quotient
= (SHORT
)State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
/ (CHAR
)Value
;
1113 CHAR Remainder
= (SHORT
)State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
% (CHAR
)Value
;
1115 /* Write back the results */
1116 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= (UCHAR
)Quotient
;
1117 State
->GeneralRegs
[SOFT386_REG_EAX
].HighByte
= (UCHAR
)Remainder
;
1126 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupF7
)
1128 ULONG Dummy
, Value
, SignFlag
;
1129 SOFT386_MOD_REG_RM ModRegRm
;
1130 BOOLEAN OperandSize
, AddressSize
;
1132 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1134 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
1136 /* The OPSIZE prefix toggles the size */
1137 OperandSize
= !OperandSize
;
1140 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
1142 /* The ADSIZE prefix toggles the size */
1143 AddressSize
= !AddressSize
;
1146 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1148 /* Exception occurred */
1152 /* Set the sign flag */
1153 if (OperandSize
) SignFlag
= SIGN_FLAG_LONG
;
1154 else SignFlag
= SIGN_FLAG_WORD
;
1156 /* Read the operand */
1160 if (!Soft386ReadModrmDwordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
1162 /* Exception occurred */
1169 if (!Soft386ReadModrmWordOperands(State
, &ModRegRm
, (PUSHORT
)&Dummy
, (PUSHORT
)&Value
))
1171 /* Exception occurred */
1176 switch (ModRegRm
.Register
)
1182 ULONG Immediate
= 0, Result
= 0;
1186 /* Fetch the immediate dword */
1187 if (!Soft386FetchDword(State
, &Immediate
))
1189 /* Exception occurred */
1195 /* Fetch the immediate word */
1196 if (!Soft386FetchWord(State
, (PUSHORT
)&Immediate
))
1198 /* Exception occurred */
1203 /* Calculate the result */
1204 Result
= Value
& Immediate
;
1206 /* Update the flags */
1207 State
->Flags
.Cf
= FALSE
;
1208 State
->Flags
.Of
= FALSE
;
1209 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1210 State
->Flags
.Sf
= (Result
& SignFlag
) ? TRUE
: FALSE
;
1211 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1219 /* Write back the result */
1223 return Soft386WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, ~Value
);
1228 return Soft386WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, LOWORD(~Value
));
1235 /* Calculate the result */
1236 ULONG Result
= -Value
;
1237 if (!OperandSize
) Result
&= 0xFFFF;
1239 /* Update the flags */
1240 State
->Flags
.Cf
= (Value
!= 0) ? TRUE
: FALSE
;
1241 State
->Flags
.Of
= (Value
& SignFlag
) && (Result
& SignFlag
);
1242 State
->Flags
.Af
= ((Value
& 0x0F) != 0) ? TRUE
: FALSE
;
1243 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1244 State
->Flags
.Sf
= (Result
& SignFlag
) ? TRUE
: FALSE
;
1245 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1247 /* Write back the result */
1251 return Soft386WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Result
);
1256 return Soft386WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, LOWORD(Result
));
1265 ULONGLONG Result
= (ULONGLONG
)Value
* (ULONGLONG
)State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
1267 /* Update the flags */
1268 State
->Flags
.Cf
= State
->Flags
.Of
=
1269 (Result
& 0xFFFFFFFF00000000ULL
) ? TRUE
: FALSE
;
1271 /* Write back the result */
1272 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Result
& 0xFFFFFFFFULL
;
1273 State
->GeneralRegs
[SOFT386_REG_EDX
].Long
= Result
>> 32;
1277 ULONG Result
= (ULONG
)Value
* (ULONG
)State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
1279 /* Update the flags */
1280 State
->Flags
.Cf
= State
->Flags
.Of
= HIWORD(Result
) ? TRUE
: FALSE
;
1282 /* Write back the result */
1283 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= LOWORD(Result
);
1284 State
->GeneralRegs
[SOFT386_REG_EDX
].LowWord
= HIWORD(Result
);
1295 LONGLONG Result
= (LONGLONG
)Value
* (LONGLONG
)State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
1297 /* Update the flags */
1298 State
->Flags
.Cf
= State
->Flags
.Of
=
1299 ((Result
< -2147483648LL) || (Result
> 2147483647LL)) ? TRUE
: FALSE
;
1301 /* Write back the result */
1302 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Result
& 0xFFFFFFFFULL
;
1303 State
->GeneralRegs
[SOFT386_REG_EDX
].Long
= Result
>> 32;
1307 LONG Result
= (LONG
)Value
* (LONG
)State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
1309 /* Update the flags */
1310 State
->Flags
.Cf
= State
->Flags
.Of
=
1311 ((Result
< -32768) || (Result
> 32767)) ? TRUE
: FALSE
;
1313 /* Write back the result */
1314 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= LOWORD(Result
);
1315 State
->GeneralRegs
[SOFT386_REG_EDX
].LowWord
= HIWORD(Result
);
1326 ULONGLONG Dividend
= (ULONGLONG
)State
->GeneralRegs
[SOFT386_REG_EAX
].Long
1327 | ((ULONGLONG
)State
->GeneralRegs
[SOFT386_REG_EDX
].Long
<< 32);
1328 ULONG Quotient
= Dividend
/ Value
;
1329 ULONG Remainder
= Dividend
% Value
;
1331 /* Write back the results */
1332 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Quotient
;
1333 State
->GeneralRegs
[SOFT386_REG_EDX
].Long
= Remainder
;
1337 ULONG Dividend
= (ULONG
)State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
1338 | ((ULONG
)State
->GeneralRegs
[SOFT386_REG_EDX
].LowWord
<< 16);
1339 USHORT Quotient
= Dividend
/ Value
;
1340 USHORT Remainder
= Dividend
% Value
;
1342 /* Write back the results */
1343 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= Quotient
;
1344 State
->GeneralRegs
[SOFT386_REG_EDX
].LowWord
= Remainder
;
1355 LONGLONG Dividend
= (LONGLONG
)State
->GeneralRegs
[SOFT386_REG_EAX
].Long
1356 | ((LONGLONG
)State
->GeneralRegs
[SOFT386_REG_EDX
].Long
<< 32);
1357 LONG Quotient
= Dividend
/ (LONG
)Value
;
1358 LONG Remainder
= Dividend
% (LONG
)Value
;
1360 /* Write back the results */
1361 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= (ULONG
)Quotient
;
1362 State
->GeneralRegs
[SOFT386_REG_EDX
].Long
= (ULONG
)Remainder
;
1366 LONG Dividend
= (LONG
)State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
1367 | ((LONG
)State
->GeneralRegs
[SOFT386_REG_EDX
].LowWord
<< 16);
1368 SHORT Quotient
= Dividend
/ (SHORT
)Value
;
1369 SHORT Remainder
= Dividend
% (SHORT
)Value
;
1371 /* Write back the results */
1372 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= (USHORT
)Quotient
;
1373 State
->GeneralRegs
[SOFT386_REG_EDX
].LowWord
= (USHORT
)Remainder
;
1383 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupFE
)
1386 SOFT386_MOD_REG_RM ModRegRm
;
1387 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1389 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
1391 /* The ADSIZE prefix toggles the size */
1392 AddressSize
= !AddressSize
;
1395 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1397 /* Exception occurred */
1401 if (ModRegRm
.Register
> 1)
1404 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1408 /* Read the operands */
1409 if (!Soft386ReadModrmByteOperands(State
, &ModRegRm
, &Dummy
, &Value
))
1411 /* Exception occurred */
1415 if (ModRegRm
.Register
== 0)
1417 /* Increment and update OF and AF */
1419 State
->Flags
.Of
= (Value
== SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
1420 State
->Flags
.Af
= ((Value
& 0x0F) == 0);
1424 /* Decrement and update OF and AF */
1425 State
->Flags
.Of
= (Value
== SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
1427 State
->Flags
.Af
= ((Value
& 0x0F) == 0x0F);
1431 State
->Flags
.Sf
= (Value
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
1432 State
->Flags
.Zf
= (Value
== 0) ? TRUE
: FALSE
;
1433 State
->Flags
.Pf
= Soft386CalculateParity(Value
);
1435 /* Write back the result */
1436 return Soft386WriteModrmByteOperands(State
,
1442 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupFF
)
1444 SOFT386_MOD_REG_RM ModRegRm
;
1445 BOOLEAN OperandSize
, AddressSize
;
1447 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1449 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
1451 /* The OPSIZE prefix toggles the size */
1452 OperandSize
= !OperandSize
;
1455 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
1457 /* The ADSIZE prefix toggles the size */
1458 AddressSize
= !AddressSize
;
1461 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1463 /* Exception occurred */
1467 if (ModRegRm
.Register
== 7)
1470 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1474 /* Read the operands */
1479 if (!Soft386ReadModrmDwordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
1481 /* Exception occurred */
1485 if (ModRegRm
.Register
== 0)
1487 /* Increment and update OF and AF */
1489 State
->Flags
.Of
= (Value
== SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1490 State
->Flags
.Af
= ((Value
& 0x0F) == 0);
1492 else if (ModRegRm
.Register
== 1)
1494 /* Decrement and update OF and AF */
1495 State
->Flags
.Of
= (Value
== SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1497 State
->Flags
.Af
= ((Value
& 0x0F) == 0x0F);
1500 if (ModRegRm
.Register
<= 1)
1503 State
->Flags
.Sf
= (Value
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1504 State
->Flags
.Zf
= (Value
== 0) ? TRUE
: FALSE
;
1505 State
->Flags
.Pf
= Soft386CalculateParity(Value
);
1507 /* Write back the result */
1508 return Soft386WriteModrmDwordOperands(State
,
1516 USHORT Dummy
, Value
;
1518 if (!Soft386ReadModrmWordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
1520 /* Exception occurred */
1524 if (ModRegRm
.Register
== 0)
1526 /* Increment and update OF */
1528 State
->Flags
.Of
= (Value
== SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
1529 State
->Flags
.Af
= ((Value
& 0x0F) == 0);
1531 else if (ModRegRm
.Register
== 1)
1533 /* Decrement and update OF */
1534 State
->Flags
.Of
= (Value
== SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
1536 State
->Flags
.Af
= ((Value
& 0x0F) == 0x0F);
1539 if (ModRegRm
.Register
<= 1)
1542 State
->Flags
.Sf
= (Value
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
1543 State
->Flags
.Zf
= (Value
== 0) ? TRUE
: FALSE
;
1544 State
->Flags
.Pf
= Soft386CalculateParity(Value
);
1546 /* Write back the result */
1547 return Soft386WriteModrmWordOperands(State
,
1554 if (ModRegRm
.Register
> 1)
1557 return FALSE
; // NOT IMPLEMENTED