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;
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 return FALSE
; // TODO: NOT IMPLEMENTED
995 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupF7
)
998 return FALSE
; // TODO: NOT IMPLEMENTED
1001 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupFE
)
1004 SOFT386_MOD_REG_RM ModRegRm
;
1005 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1007 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
1009 /* The ADSIZE prefix toggles the size */
1010 AddressSize
= !AddressSize
;
1013 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1015 /* Exception occurred */
1019 if (ModRegRm
.Register
> 1)
1022 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1026 /* Read the operands */
1027 if (!Soft386ReadModrmByteOperands(State
, &ModRegRm
, &Dummy
, &Value
))
1029 /* Exception occurred */
1033 if (ModRegRm
.Register
== 0)
1035 /* Increment and update OF */
1037 State
->Flags
.Of
= (Value
== SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
1041 /* Decrement and update OF */
1042 State
->Flags
.Of
= (Value
== SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
1047 State
->Flags
.Sf
= (Value
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
1048 State
->Flags
.Zf
= (Value
== 0) ? TRUE
: FALSE
;
1049 State
->Flags
.Af
= ((Value
& 0x0F) == 0) ? TRUE
: FALSE
;
1050 State
->Flags
.Pf
= Soft386CalculateParity(Value
);
1052 /* Write back the result */
1053 return Soft386WriteModrmByteOperands(State
,
1059 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupFF
)
1061 SOFT386_MOD_REG_RM ModRegRm
;
1062 BOOLEAN OperandSize
, AddressSize
;
1064 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1066 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
1068 /* The OPSIZE prefix toggles the size */
1069 OperandSize
= !OperandSize
;
1072 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
1074 /* The ADSIZE prefix toggles the size */
1075 AddressSize
= !AddressSize
;
1078 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1080 /* Exception occurred */
1084 if (ModRegRm
.Register
== 7)
1087 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1091 /* Read the operands */
1096 if (!Soft386ReadModrmDwordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
1098 /* Exception occurred */
1102 if (ModRegRm
.Register
== 0)
1104 /* Increment and update OF */
1106 State
->Flags
.Of
= (Value
== SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1108 else if (ModRegRm
.Register
== 1)
1110 /* Decrement and update OF */
1111 State
->Flags
.Of
= (Value
== SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1115 if (ModRegRm
.Register
<= 1)
1118 State
->Flags
.Sf
= (Value
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1119 State
->Flags
.Zf
= (Value
== 0) ? TRUE
: FALSE
;
1120 State
->Flags
.Af
= ((Value
& 0x0F) == 0) ? TRUE
: FALSE
;
1121 State
->Flags
.Pf
= Soft386CalculateParity(Value
);
1123 /* Write back the result */
1124 return Soft386WriteModrmDwordOperands(State
,
1132 USHORT Dummy
, Value
;
1134 if (!Soft386ReadModrmWordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
1136 /* Exception occurred */
1140 if (ModRegRm
.Register
== 0)
1142 /* Increment and update OF */
1144 State
->Flags
.Of
= (Value
== SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
1146 else if (ModRegRm
.Register
== 1)
1148 /* Decrement and update OF */
1149 State
->Flags
.Of
= (Value
== SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
1153 if (ModRegRm
.Register
<= 1)
1156 State
->Flags
.Sf
= (Value
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
1157 State
->Flags
.Zf
= (Value
== 0) ? TRUE
: FALSE
;
1158 State
->Flags
.Af
= ((Value
& 0x0F) == 0) ? TRUE
: FALSE
;
1159 State
->Flags
.Pf
= Soft386CalculateParity(Value
);
1161 /* Write back the result */
1162 return Soft386WriteModrmWordOperands(State
,
1169 if (ModRegRm
.Register
> 1)
1172 return FALSE
; // NOT IMPLEMENTED