2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: 386/486 CPU Emulation Library
5 * PURPOSE: Opcode group handlers.
6 * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
9 /* INCLUDES *******************************************************************/
11 // #define WIN32_NO_STATUS
12 // #define _INC_WINDOWS
22 /* PRIVATE FUNCTIONS **********************************************************/
27 Soft386RotateOperation(PSOFT386_STATE State
,
33 ULONG HighestBit
= 1 << (Bits
- 1);
36 if ((Operation
!= 2) && (Operation
!= 3))
43 /* For RCL and RCR, the CF is included in the value */
47 /* Check which operation is this */
53 Result
= (Value
<< Count
) | (Value
>> (Bits
- Count
));
55 /* Update CF and OF */
56 State
->Flags
.Cf
= Result
& 1;
57 if (Count
== 1) State
->Flags
.Of
= ((Result
& HighestBit
) ? TRUE
: FALSE
)
66 Result
= (Value
>> Count
) | (Value
<< (Bits
- Count
));
68 /* Update CF and OF */
69 State
->Flags
.Cf
= (Result
& HighestBit
) ? TRUE
: FALSE
;
70 if (Count
== 1) State
->Flags
.Of
= State
->Flags
.Cf
71 ^ ((Result
& (HighestBit
>> 1))
80 Result
= (Value
<< Count
)
81 | (State
->Flags
.Cf
<< (Count
- 1))
82 | (Value
>> (Bits
- Count
+ 1));
84 /* Update CF and OF */
85 State
->Flags
.Cf
= (Value
& (1 << (Bits
- Count
))) ? TRUE
: FALSE
;
86 if (Count
== 1) State
->Flags
.Of
= ((Result
& HighestBit
) ? TRUE
: FALSE
)
95 Result
= (Value
>> Count
)
96 | (State
->Flags
.Cf
<< (Bits
- Count
))
97 | (Value
<< (Bits
- Count
+ 1));
99 /* Update CF and OF */
100 State
->Flags
.Cf
= (Value
& (1 << (Bits
- Count
))) ? TRUE
: FALSE
;
101 if (Count
== 1) State
->Flags
.Of
= State
->Flags
.Cf
102 ^ ((Result
& (HighestBit
>> 1))
112 Result
= Value
<< Count
;
114 /* Update CF and OF */
115 State
->Flags
.Cf
= (Value
& (1 << (Bits
- Count
))) ? TRUE
: FALSE
;
116 if (Count
== 1) State
->Flags
.Of
= ((Result
& HighestBit
) ? TRUE
: FALSE
)
117 ^ (State
->Flags
.Cf
? TRUE
: FALSE
);
125 Result
= Value
>> Count
;
127 /* Update CF and OF */
128 State
->Flags
.Cf
= (Value
& (1 << (Count
- 1))) ? TRUE
: FALSE
;
129 if (Count
== 1) State
->Flags
.Of
= (Value
& HighestBit
) ? TRUE
: FALSE
;
137 Result
= Value
>> Count
;
139 /* Fill the top Count bits with the sign bit */
140 if (Value
& HighestBit
) Result
|= ((1 << Count
) - 1) << (Bits
- Count
);
142 /* Update CF and OF */
143 State
->Flags
.Cf
= Value
& 1;
144 if (Count
== 1) State
->Flags
.Of
= FALSE
;
150 /* Update ZF, SF and PF */
151 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
152 State
->Flags
.Sf
= (Result
& HighestBit
) ? TRUE
: FALSE
;
153 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
155 /* Return the result */
159 /* PUBLIC FUNCTIONS ***********************************************************/
161 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroup8082
)
163 UCHAR Immediate
, Result
, Dummy
, Value
;
164 SOFT386_MOD_REG_RM ModRegRm
;
165 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
167 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
169 /* The ADSIZE prefix toggles the size */
170 AddressSize
= !AddressSize
;
173 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
175 /* Exception occurred */
179 /* Fetch the immediate operand */
180 if (!Soft386FetchByte(State
, &Immediate
))
182 /* Exception occurred */
186 /* Read the operands */
187 if (!Soft386ReadModrmByteOperands(State
, &ModRegRm
, &Dummy
, &Value
))
189 /* Exception occurred */
193 /* Check which operation is this */
194 switch (ModRegRm
.Register
)
199 Result
= Value
+ Immediate
;
201 /* Update CF, OF and AF */
202 State
->Flags
.Cf
= (Result
< Value
) && (Result
< Immediate
);
203 State
->Flags
.Of
= ((Value
& SIGN_FLAG_BYTE
) == (Immediate
& SIGN_FLAG_BYTE
))
204 && ((Value
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
205 State
->Flags
.Af
= (((Value
& 0x0F) + (Immediate
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
213 Result
= Value
| Immediate
;
220 INT Carry
= State
->Flags
.Cf
? 1 : 0;
222 Result
= Value
+ Immediate
+ Carry
;
224 /* Update CF, OF and AF */
225 State
->Flags
.Cf
= ((Immediate
== 0xFF) && (Carry
== 1))
226 || ((Result
< Value
) && (Result
< (Immediate
+ Carry
)));
227 State
->Flags
.Of
= ((Value
& SIGN_FLAG_BYTE
) == (Immediate
& SIGN_FLAG_BYTE
))
228 && ((Value
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
229 State
->Flags
.Af
= (((Value
& 0x0F) + ((Immediate
+ Carry
) & 0x0F)) & 0x10)
238 INT Carry
= State
->Flags
.Cf
? 1 : 0;
240 Result
= Value
- Immediate
- Carry
;
242 /* Update CF, OF and AF */
243 State
->Flags
.Cf
= Value
< (Immediate
+ Carry
);
244 State
->Flags
.Of
= ((Value
& SIGN_FLAG_BYTE
) != (Immediate
& SIGN_FLAG_BYTE
))
245 && ((Value
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
246 State
->Flags
.Af
= (Value
& 0x0F) < ((Immediate
+ Carry
) & 0x0F);
254 Result
= Value
& Immediate
;
262 Result
= Value
- Immediate
;
264 /* Update CF, OF and AF */
265 State
->Flags
.Cf
= Value
< Immediate
;
266 State
->Flags
.Of
= ((Value
& SIGN_FLAG_BYTE
) != (Immediate
& SIGN_FLAG_BYTE
))
267 && ((Value
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
268 State
->Flags
.Af
= (Value
& 0x0F) < (Immediate
& 0x0F);
282 /* Shouldn't happen */
287 /* Update ZF, SF and PF */
288 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
289 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
290 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
292 /* Unless this is CMP, write back the result */
293 if (ModRegRm
.Register
!= 7)
295 return Soft386WriteModrmByteOperands(State
, &ModRegRm
, FALSE
, Result
);
301 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroup81
)
304 return FALSE
; // TODO: NOT IMPLEMENTED
307 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroup83
)
310 return FALSE
; // TODO: NOT IMPLEMENTED
313 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroup8F
)
316 SOFT386_MOD_REG_RM ModRegRm
;
317 BOOLEAN OperandSize
, AddressSize
;
319 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
321 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
323 /* The OPSIZE prefix toggles the size */
324 OperandSize
= !OperandSize
;
327 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
329 /* The ADSIZE prefix toggles the size */
330 AddressSize
= !AddressSize
;
333 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
335 /* Exception occurred */
339 if (ModRegRm
.Register
!= 0)
342 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
346 /* Pop a value from the stack */
347 if (!Soft386StackPop(State
, &Value
))
349 /* Exception occurred */
355 return Soft386WriteModrmDwordOperands(State
,
362 return Soft386WriteModrmWordOperands(State
,
369 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupC0
)
371 UCHAR Dummy
, Value
, Count
;
372 SOFT386_MOD_REG_RM ModRegRm
;
373 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
375 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
377 /* The ADSIZE prefix toggles the size */
378 AddressSize
= !AddressSize
;
381 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
383 /* Exception occurred */
387 /* Fetch the count */
388 if (!Soft386FetchByte(State
, &Count
))
390 /* Exception occurred */
394 /* Read the operands */
395 if (!Soft386ReadModrmByteOperands(State
, &ModRegRm
, &Dummy
, &Value
))
397 /* Exception occurred */
401 /* Calculate the result */
402 Value
= LOBYTE(Soft386RotateOperation(State
,
408 /* Write back the result */
409 return Soft386WriteModrmByteOperands(State
,
415 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupC1
)
418 SOFT386_MOD_REG_RM ModRegRm
;
419 BOOLEAN OperandSize
, AddressSize
;
421 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
423 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
425 /* The OPSIZE prefix toggles the size */
426 OperandSize
= !OperandSize
;
429 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
431 /* The ADSIZE prefix toggles the size */
432 AddressSize
= !AddressSize
;
435 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
437 /* Exception occurred */
441 /* Fetch the count */
442 if (!Soft386FetchByte(State
, &Count
))
444 /* Exception occurred */
452 /* Read the operands */
453 if (!Soft386ReadModrmDwordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
455 /* Exception occurred */
459 /* Calculate the result */
460 Value
= Soft386RotateOperation(State
,
466 /* Write back the result */
467 return Soft386WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Value
);
473 /* Read the operands */
474 if (!Soft386ReadModrmWordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
476 /* Exception occurred */
480 /* Calculate the result */
481 Value
= LOWORD(Soft386RotateOperation(State
,
487 /* Write back the result */
488 return Soft386WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Value
);
492 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupC6
)
495 SOFT386_MOD_REG_RM ModRegRm
;
496 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
498 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
500 /* The ADSIZE prefix toggles the size */
501 AddressSize
= !AddressSize
;
504 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
506 /* Exception occurred */
510 if (ModRegRm
.Register
!= 0)
513 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
517 /* Get the immediate operand */
518 if (!Soft386FetchByte(State
, &Immediate
))
520 /* Exception occurred */
524 return Soft386WriteModrmByteOperands(State
,
530 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupC7
)
532 SOFT386_MOD_REG_RM ModRegRm
;
533 BOOLEAN OperandSize
, AddressSize
;
535 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
537 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
539 /* The OPSIZE prefix toggles the size */
540 OperandSize
= !OperandSize
;
543 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
545 /* The ADSIZE prefix toggles the size */
546 AddressSize
= !AddressSize
;
549 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
551 /* Exception occurred */
555 if (ModRegRm
.Register
!= 0)
558 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
566 /* Get the immediate operand */
567 if (!Soft386FetchDword(State
, &Immediate
))
569 /* Exception occurred */
573 return Soft386WriteModrmDwordOperands(State
,
582 /* Get the immediate operand */
583 if (!Soft386FetchWord(State
, &Immediate
))
585 /* Exception occurred */
589 return Soft386WriteModrmWordOperands(State
,
596 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupD0
)
599 SOFT386_MOD_REG_RM ModRegRm
;
600 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
602 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
604 /* The ADSIZE prefix toggles the size */
605 AddressSize
= !AddressSize
;
608 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
610 /* Exception occurred */
614 /* Read the operands */
615 if (!Soft386ReadModrmByteOperands(State
, &ModRegRm
, &Dummy
, &Value
))
617 /* Exception occurred */
621 /* Calculate the result */
622 Value
= LOBYTE(Soft386RotateOperation(State
, ModRegRm
.Register
, Value
, 8, 1));
624 /* Write back the result */
625 return Soft386WriteModrmByteOperands(State
,
632 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupD1
)
634 SOFT386_MOD_REG_RM ModRegRm
;
635 BOOLEAN OperandSize
, AddressSize
;
637 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
639 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
641 /* The OPSIZE prefix toggles the size */
642 OperandSize
= !OperandSize
;
646 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
648 /* The ADSIZE prefix toggles the size */
649 AddressSize
= !AddressSize
;
652 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
654 /* Exception occurred */
662 /* Read the operands */
663 if (!Soft386ReadModrmDwordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
665 /* Exception occurred */
669 /* Calculate the result */
670 Value
= Soft386RotateOperation(State
, ModRegRm
.Register
, Value
, 32, 1);
672 /* Write back the result */
673 return Soft386WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Value
);
679 /* Read the operands */
680 if (!Soft386ReadModrmWordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
682 /* Exception occurred */
686 /* Calculate the result */
687 Value
= LOWORD(Soft386RotateOperation(State
, ModRegRm
.Register
, Value
, 16, 1));
689 /* Write back the result */
690 return Soft386WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Value
);
694 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupD2
)
697 SOFT386_MOD_REG_RM ModRegRm
;
698 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
700 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
702 /* The ADSIZE prefix toggles the size */
703 AddressSize
= !AddressSize
;
706 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
708 /* Exception occurred */
712 /* Read the operands */
713 if (!Soft386ReadModrmByteOperands(State
, &ModRegRm
, &Dummy
, &Value
))
715 /* Exception occurred */
719 /* Calculate the result */
720 Value
= LOBYTE(Soft386RotateOperation(State
,
724 State
->GeneralRegs
[SOFT386_REG_ECX
].LowByte
));
726 /* Write back the result */
727 return Soft386WriteModrmByteOperands(State
,
733 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupD3
)
735 SOFT386_MOD_REG_RM ModRegRm
;
736 BOOLEAN OperandSize
, AddressSize
;
738 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
740 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
742 /* The OPSIZE prefix toggles the size */
743 OperandSize
= !OperandSize
;
746 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
748 /* The ADSIZE prefix toggles the size */
749 AddressSize
= !AddressSize
;
752 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
754 /* Exception occurred */
762 /* Read the operands */
763 if (!Soft386ReadModrmDwordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
765 /* Exception occurred */
769 /* Calculate the result */
770 Value
= Soft386RotateOperation(State
,
774 State
->GeneralRegs
[SOFT386_REG_ECX
].LowByte
);
776 /* Write back the result */
777 return Soft386WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Value
);
783 /* Read the operands */
784 if (!Soft386ReadModrmWordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
786 /* Exception occurred */
790 /* Calculate the result */
791 Value
= LOWORD(Soft386RotateOperation(State
,
795 State
->GeneralRegs
[SOFT386_REG_ECX
].LowByte
));
797 /* Write back the result */
798 return Soft386WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Value
);
802 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupF6
)
805 return FALSE
; // TODO: NOT IMPLEMENTED
808 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupF7
)
811 return FALSE
; // TODO: NOT IMPLEMENTED
814 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupFE
)
817 SOFT386_MOD_REG_RM ModRegRm
;
818 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
820 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
822 /* The ADSIZE prefix toggles the size */
823 AddressSize
= !AddressSize
;
826 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
828 /* Exception occurred */
832 if (ModRegRm
.Register
> 1)
835 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
839 /* Read the operands */
840 if (!Soft386ReadModrmByteOperands(State
, &ModRegRm
, &Dummy
, &Value
))
842 /* Exception occurred */
846 if (ModRegRm
.Register
== 0)
848 /* Increment and update OF */
850 State
->Flags
.Of
= (Value
== SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
854 /* Decrement and update OF */
855 State
->Flags
.Of
= (Value
== SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
860 State
->Flags
.Sf
= (Value
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
861 State
->Flags
.Zf
= (Value
== 0) ? TRUE
: FALSE
;
862 State
->Flags
.Af
= ((Value
& 0x0F) == 0) ? TRUE
: FALSE
;
863 State
->Flags
.Pf
= Soft386CalculateParity(Value
);
865 /* Write back the result */
866 return Soft386WriteModrmByteOperands(State
,
872 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupFF
)
875 return FALSE
; // TODO: NOT IMPLEMENTED