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 *******************************************************************/
24 // #define WIN32_NO_STATUS
25 // #define _INC_WINDOWS
37 /* PUBLIC VARIABLES ***********************************************************/
39 FAST486_OPCODE_HANDLER_PROC
40 Fast486ExtendedHandlers
[FAST486_NUM_OPCODE_HANDLERS
] =
42 NULL
, // TODO: OPCODE 0x00 NOT IMPLEMENTED
43 NULL
, // TODO: OPCODE 0x01 NOT IMPLEMENTED
44 NULL
, // TODO: OPCODE 0x02 NOT IMPLEMENTED
45 NULL
, // TODO: OPCODE 0x03 NOT IMPLEMENTED
46 NULL
, // TODO: OPCODE 0x04 NOT IMPLEMENTED
47 NULL
, // TODO: OPCODE 0x05 NOT IMPLEMENTED
48 NULL
, // TODO: OPCODE 0x06 NOT IMPLEMENTED
49 NULL
, // TODO: OPCODE 0x07 NOT IMPLEMENTED
50 NULL
, // TODO: OPCODE 0x08 NOT IMPLEMENTED
51 NULL
, // TODO: OPCODE 0x09 NOT IMPLEMENTED
53 NULL
, // Reserved (UD1)
58 NULL
, // TODO: OPCODE 0x10 NOT IMPLEMENTED
59 NULL
, // TODO: OPCODE 0x11 NOT IMPLEMENTED
60 NULL
, // TODO: OPCODE 0x12 NOT IMPLEMENTED
61 NULL
, // TODO: OPCODE 0x13 NOT IMPLEMENTED
74 NULL
, // TODO: OPCODE 0x20 NOT IMPLEMENTED
75 NULL
, // TODO: OPCODE 0x21 NOT IMPLEMENTED
76 NULL
, // TODO: OPCODE 0x22 NOT IMPLEMENTED
77 NULL
, // TODO: OPCODE 0x23 NOT IMPLEMENTED
78 NULL
, // TODO: OPCODE 0x24 NOT IMPLEMENTED
80 NULL
, // TODO: OPCODE 0x26 NOT IMPLEMENTED
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 Fast486ExtOpcodeConditionalJmp
,
185 Fast486ExtOpcodeConditionalJmp
,
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 Fast486ExtOpcodeConditionalSet
,
201 Fast486ExtOpcodeConditionalSet
,
202 Fast486ExtOpcodePushFs
,
203 Fast486ExtOpcodePopFs
,
205 Fast486ExtOpcodeBitTest
,
206 NULL
, // TODO: OPCODE 0xA4 NOT IMPLEMENTED
207 NULL
, // TODO: OPCODE 0xA5 NOT IMPLEMENTED
210 Fast486ExtOpcodePushGs
,
211 Fast486ExtOpcodePopGs
,
212 NULL
, // TODO: OPCODE 0xAA NOT IMPLEMENTED
214 NULL
, // TODO: OPCODE 0xAC NOT IMPLEMENTED
215 NULL
, // TODO: OPCODE 0xAD NOT IMPLEMENTED
216 NULL
, // TODO: OPCODE 0xAE NOT IMPLEMENTED
217 NULL
, // TODO: OPCODE 0xAF NOT IMPLEMENTED
218 Fast486ExtOpcodeCmpXchgByte
,
219 Fast486ExtOpcodeCmpXchg
,
220 NULL
, // TODO: OPCODE 0xB2 NOT IMPLEMENTED
222 NULL
, // TODO: OPCODE 0xB4 NOT IMPLEMENTED
223 NULL
, // TODO: OPCODE 0xB5 NOT IMPLEMENTED
224 NULL
, // TODO: OPCODE 0xB6 NOT IMPLEMENTED
225 NULL
, // TODO: OPCODE 0xB7 NOT IMPLEMENTED
226 NULL
, // TODO: OPCODE 0xB8 NOT IMPLEMENTED
227 Fast486OpcodeGroup0FB9
,
228 Fast486OpcodeGroup0FBA
,
230 NULL
, // TODO: OPCODE 0xBC NOT IMPLEMENTED
231 NULL
, // TODO: OPCODE 0xBD NOT IMPLEMENTED
232 NULL
, // TODO: OPCODE 0xBE NOT IMPLEMENTED
233 NULL
, // TODO: OPCODE 0xBF NOT IMPLEMENTED
234 NULL
, // TODO: OPCODE 0xC0 NOT IMPLEMENTED
235 NULL
, // TODO: OPCODE 0xC1 NOT IMPLEMENTED
242 Fast486ExtOpcodeBswap
,
243 Fast486ExtOpcodeBswap
,
244 Fast486ExtOpcodeBswap
,
245 Fast486ExtOpcodeBswap
,
246 Fast486ExtOpcodeBswap
,
247 Fast486ExtOpcodeBswap
,
248 Fast486ExtOpcodeBswap
,
249 Fast486ExtOpcodeBswap
,
300 /* PUBLIC FUNCTIONS ***********************************************************/
302 FAST486_OPCODE_HANDLER(Fast486ExtOpcodePushFs
)
304 /* Call the internal API */
305 return Fast486StackPush(State
, State
->SegmentRegs
[FAST486_REG_FS
].Selector
);
308 FAST486_OPCODE_HANDLER(Fast486ExtOpcodePopFs
)
312 if (!Fast486StackPop(State
, &NewSelector
))
314 /* Exception occurred */
318 /* Call the internal API */
319 return Fast486LoadSegment(State
, FAST486_REG_FS
, LOWORD(NewSelector
));
322 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBitTest
)
324 BOOLEAN OperandSize
, AddressSize
;
325 FAST486_MOD_REG_RM ModRegRm
;
329 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
330 TOGGLE_OPSIZE(OperandSize
);
331 TOGGLE_ADSIZE(AddressSize
);
333 /* Get the number of bits */
334 if (OperandSize
) DataSize
= 32;
337 /* Get the operands */
338 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
340 /* Exception occurred */
344 /* Get the bit number */
345 BitNumber
= OperandSize
? State
->GeneralRegs
[ModRegRm
.Register
].Long
346 : (ULONG
)State
->GeneralRegs
[ModRegRm
.Register
].LowWord
;
351 * For memory operands, add the bit offset divided by
352 * the data size to the address
354 ModRegRm
.MemoryAddress
+= BitNumber
/ DataSize
;
357 /* Normalize the bit number */
358 BitNumber
&= (1 << DataSize
) - 1;
365 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
367 /* Exception occurred */
371 /* Set CF to the bit value */
372 State
->Flags
.Cf
= (Value
>> BitNumber
) & 1;
379 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
381 /* Exception occurred */
385 /* Set CF to the bit value */
386 State
->Flags
.Cf
= (Value
>> BitNumber
) & 1;
393 FAST486_OPCODE_HANDLER(Fast486ExtOpcodePushGs
)
395 /* Call the internal API */
396 return Fast486StackPush(State
, State
->SegmentRegs
[FAST486_REG_GS
].Selector
);
399 FAST486_OPCODE_HANDLER(Fast486ExtOpcodePopGs
)
403 if (!Fast486StackPop(State
, &NewSelector
))
405 /* Exception occurred */
409 /* Call the internal API */
410 return Fast486LoadSegment(State
, FAST486_REG_GS
, LOWORD(NewSelector
));
413 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBts
)
415 BOOLEAN OperandSize
, AddressSize
;
416 FAST486_MOD_REG_RM ModRegRm
;
420 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
421 TOGGLE_OPSIZE(OperandSize
);
422 TOGGLE_ADSIZE(AddressSize
);
424 /* Get the number of bits */
425 if (OperandSize
) DataSize
= 32;
428 /* Get the operands */
429 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
431 /* Exception occurred */
435 /* Get the bit number */
436 BitNumber
= OperandSize
? State
->GeneralRegs
[ModRegRm
.Register
].Long
437 : (ULONG
)State
->GeneralRegs
[ModRegRm
.Register
].LowWord
;
442 * For memory operands, add the bit offset divided by
443 * the data size to the address
445 ModRegRm
.MemoryAddress
+= BitNumber
/ DataSize
;
448 /* Normalize the bit number */
449 BitNumber
&= (1 << DataSize
) - 1;
456 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
458 /* Exception occurred */
462 /* Set CF to the bit value */
463 State
->Flags
.Cf
= (Value
>> BitNumber
) & 1;
466 Value
|= 1 << BitNumber
;
468 /* Write back the result */
469 if (!Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Value
))
471 /* Exception occurred */
480 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
482 /* Exception occurred */
486 /* Set CF to the bit value */
487 State
->Flags
.Cf
= (Value
>> BitNumber
) & 1;
490 Value
|= 1 << BitNumber
;
492 /* Write back the result */
493 if (!Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Value
))
495 /* Exception occurred */
504 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeCmpXchgByte
)
506 FAST486_MOD_REG_RM ModRegRm
;
507 UCHAR Accumulator
= State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
;
508 UCHAR Source
, Destination
, Result
;
509 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
511 TOGGLE_ADSIZE(AddressSize
);
513 /* Get the operands */
514 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
516 /* Exception occurred */
520 /* Read the operands */
521 if (!Fast486ReadModrmByteOperands(State
, &ModRegRm
, &Source
, &Destination
))
523 /* Exception occurred */
527 /* Compare AL with the destination */
528 Result
= Accumulator
- Destination
;
530 /* Update the flags */
531 State
->Flags
.Cf
= Accumulator
< Destination
;
532 State
->Flags
.Of
= ((Accumulator
& SIGN_FLAG_BYTE
) != (Destination
& SIGN_FLAG_BYTE
))
533 && ((Accumulator
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
534 State
->Flags
.Af
= (Accumulator
& 0x0F) < (Destination
& 0x0F);
535 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
536 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
537 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
541 /* Load the source operand into the destination */
542 return Fast486WriteModrmByteOperands(State
, &ModRegRm
, FALSE
, Source
);
546 /* Load the destination into AL */
547 State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
= Destination
;
554 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeCmpXchg
)
556 FAST486_MOD_REG_RM ModRegRm
;
557 BOOLEAN OperandSize
, AddressSize
;
559 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
561 TOGGLE_OPSIZE(OperandSize
);
562 TOGGLE_ADSIZE(AddressSize
);
564 /* Get the operands */
565 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
567 /* Exception occurred */
573 ULONG Source
, Destination
, Result
;
574 ULONG Accumulator
= State
->GeneralRegs
[FAST486_REG_EAX
].Long
;
576 /* Read the operands */
577 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, &Source
, &Destination
))
579 /* Exception occurred */
583 /* Compare EAX with the destination */
584 Result
= Accumulator
- Destination
;
586 /* Update the flags */
587 State
->Flags
.Cf
= Accumulator
< Destination
;
588 State
->Flags
.Of
= ((Accumulator
& SIGN_FLAG_LONG
) != (Destination
& SIGN_FLAG_LONG
))
589 && ((Accumulator
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
590 State
->Flags
.Af
= (Accumulator
& 0x0F) < (Destination
& 0x0F);
591 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
592 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
593 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
597 /* Load the source operand into the destination */
598 return Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Source
);
602 /* Load the destination into EAX */
603 State
->GeneralRegs
[FAST486_REG_EAX
].Long
= Destination
;
608 USHORT Source
, Destination
, Result
;
609 USHORT Accumulator
= State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
;
611 /* Read the operands */
612 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, &Source
, &Destination
))
614 /* Exception occurred */
618 /* Compare AX with the destination */
619 Result
= Accumulator
- Destination
;
621 /* Update the flags */
622 State
->Flags
.Cf
= Accumulator
< Destination
;
623 State
->Flags
.Of
= ((Accumulator
& SIGN_FLAG_WORD
) != (Destination
& SIGN_FLAG_WORD
))
624 && ((Accumulator
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
625 State
->Flags
.Af
= (Accumulator
& 0x0F) < (Destination
& 0x0F);
626 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
627 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
628 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
632 /* Load the source operand into the destination */
633 return Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Source
);
637 /* Load the destination into AX */
638 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= Destination
;
646 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBtr
)
648 BOOLEAN OperandSize
, AddressSize
;
649 FAST486_MOD_REG_RM ModRegRm
;
653 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
654 TOGGLE_OPSIZE(OperandSize
);
655 TOGGLE_ADSIZE(AddressSize
);
657 /* Get the number of bits */
658 if (OperandSize
) DataSize
= 32;
661 /* Get the operands */
662 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
664 /* Exception occurred */
668 /* Get the bit number */
669 BitNumber
= OperandSize
? State
->GeneralRegs
[ModRegRm
.Register
].Long
670 : (ULONG
)State
->GeneralRegs
[ModRegRm
.Register
].LowWord
;
675 * For memory operands, add the bit offset divided by
676 * the data size to the address
678 ModRegRm
.MemoryAddress
+= BitNumber
/ DataSize
;
681 /* Normalize the bit number */
682 BitNumber
&= (1 << DataSize
) - 1;
689 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
691 /* Exception occurred */
695 /* Set CF to the bit value */
696 State
->Flags
.Cf
= (Value
>> BitNumber
) & 1;
699 Value
&= ~(1 << BitNumber
);
701 /* Write back the result */
702 if (!Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Value
))
704 /* Exception occurred */
713 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
715 /* Exception occurred */
719 /* Set CF to the bit value */
720 State
->Flags
.Cf
= (Value
>> BitNumber
) & 1;
723 Value
&= ~(1 << BitNumber
);
725 /* Write back the result */
726 if (!Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Value
))
728 /* Exception occurred */
737 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBtc
)
739 BOOLEAN OperandSize
, AddressSize
;
740 FAST486_MOD_REG_RM ModRegRm
;
744 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
745 TOGGLE_OPSIZE(OperandSize
);
746 TOGGLE_ADSIZE(AddressSize
);
748 /* Get the number of bits */
749 if (OperandSize
) DataSize
= 32;
752 /* Get the operands */
753 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
755 /* Exception occurred */
759 /* Get the bit number */
760 BitNumber
= OperandSize
? State
->GeneralRegs
[ModRegRm
.Register
].Long
761 : (ULONG
)State
->GeneralRegs
[ModRegRm
.Register
].LowWord
;
766 * For memory operands, add the bit offset divided by
767 * the data size to the address
769 ModRegRm
.MemoryAddress
+= BitNumber
/ DataSize
;
772 /* Normalize the bit number */
773 BitNumber
&= (1 << DataSize
) - 1;
780 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
782 /* Exception occurred */
786 /* Set CF to the bit value */
787 State
->Flags
.Cf
= (Value
>> BitNumber
) & 1;
790 Value
^= 1 << BitNumber
;
792 /* Write back the result */
793 if (!Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Value
))
795 /* Exception occurred */
804 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
806 /* Exception occurred */
810 /* Set CF to the bit value */
811 State
->Flags
.Cf
= (Value
>> BitNumber
) & 1;
814 Value
^= 1 << BitNumber
;
816 /* Write back the result */
817 if (!Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Value
))
819 /* Exception occurred */
828 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeConditionalJmp
)
830 BOOLEAN Jump
= FALSE
;
832 BOOLEAN Size
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
837 /* Make sure this is the right instruction */
838 ASSERT((Opcode
& 0xF0) == 0x80);
840 /* Fetch the offset */
843 if (!Fast486FetchDword(State
, (PULONG
)&Offset
))
845 /* Exception occurred */
853 if (!Fast486FetchWord(State
, (PUSHORT
)&Value
))
855 /* Exception occurred */
860 Offset
= (LONG
)Value
;
863 switch ((Opcode
& 0x0F) >> 1)
868 Jump
= State
->Flags
.Of
;
875 Jump
= State
->Flags
.Cf
;
882 Jump
= State
->Flags
.Zf
;
889 Jump
= State
->Flags
.Cf
|| State
->Flags
.Zf
;
896 Jump
= State
->Flags
.Sf
;
903 Jump
= State
->Flags
.Pf
;
910 Jump
= State
->Flags
.Sf
!= State
->Flags
.Of
;
917 Jump
= (State
->Flags
.Sf
!= State
->Flags
.Of
) || State
->Flags
.Zf
;
924 /* Invert the result */
930 /* Move the instruction pointer */
931 State
->InstPtr
.Long
+= Offset
;
938 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeConditionalSet
)
940 BOOLEAN Value
= FALSE
;
941 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
942 FAST486_MOD_REG_RM ModRegRm
;
944 TOGGLE_ADSIZE(AddressSize
);
946 /* Get the operands */
947 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
949 /* Exception occurred */
953 /* Make sure this is the right instruction */
954 ASSERT((Opcode
& 0xF0) == 0x90);
956 switch ((Opcode
& 0x0F) >> 1)
961 Value
= State
->Flags
.Of
;
968 Value
= State
->Flags
.Cf
;
975 Value
= State
->Flags
.Zf
;
982 Value
= State
->Flags
.Cf
|| State
->Flags
.Zf
;
989 Value
= State
->Flags
.Sf
;
996 Value
= State
->Flags
.Pf
;
1003 Value
= State
->Flags
.Sf
!= State
->Flags
.Of
;
1007 /* SETLE / SETNLE */
1010 Value
= (State
->Flags
.Sf
!= State
->Flags
.Of
) || State
->Flags
.Zf
;
1017 /* Invert the result */
1021 /* Write back the result */
1022 return Fast486WriteModrmByteOperands(State
, &ModRegRm
, FALSE
, Value
);
1025 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBswap
)
1031 /* Get a pointer to the value */
1032 Pointer
= (PUCHAR
)&State
->GeneralRegs
[Opcode
& 0x07].Long
;
1034 /* Swap the byte order */
1035 SWAP(Pointer
[0], Pointer
[3]);
1036 SWAP(Pointer
[1], Pointer
[2]);
1038 /* Return success */
1042 FAST486_OPCODE_HANDLER(Fast486OpcodeExtended
)
1046 /* Fetch the second operation code */
1047 if (!Fast486FetchByte(State
, &SecondOpcode
))
1049 /* Exception occurred */
1053 if (Fast486ExtendedHandlers
[SecondOpcode
] != NULL
)
1055 /* Call the extended opcode handler */
1056 return Fast486ExtendedHandlers
[SecondOpcode
](State
, SecondOpcode
);
1060 /* This is not a valid opcode */
1061 Fast486Exception(State
, FAST486_EXCEPTION_UD
);