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
36 /* PUBLIC VARIABLES ***********************************************************/
38 FAST486_OPCODE_HANDLER_PROC
39 Fast486ExtendedHandlers
[FAST486_NUM_OPCODE_HANDLERS
] =
41 NULL
, // TODO: OPCODE 0x00 NOT IMPLEMENTED
42 NULL
, // TODO: OPCODE 0x01 NOT IMPLEMENTED
43 NULL
, // TODO: OPCODE 0x02 NOT IMPLEMENTED
44 NULL
, // TODO: OPCODE 0x03 NOT IMPLEMENTED
45 NULL
, // TODO: OPCODE 0x04 NOT IMPLEMENTED
46 NULL
, // TODO: OPCODE 0x05 NOT IMPLEMENTED
47 NULL
, // TODO: OPCODE 0x06 NOT IMPLEMENTED
48 NULL
, // TODO: OPCODE 0x07 NOT IMPLEMENTED
49 NULL
, // TODO: OPCODE 0x08 NOT IMPLEMENTED
50 NULL
, // TODO: OPCODE 0x09 NOT IMPLEMENTED
52 NULL
, // Reserved (UD1)
57 NULL
, // TODO: OPCODE 0x10 NOT IMPLEMENTED
58 NULL
, // TODO: OPCODE 0x11 NOT IMPLEMENTED
59 NULL
, // TODO: OPCODE 0x12 NOT IMPLEMENTED
60 NULL
, // TODO: OPCODE 0x13 NOT IMPLEMENTED
73 NULL
, // TODO: OPCODE 0x20 NOT IMPLEMENTED
74 NULL
, // TODO: OPCODE 0x21 NOT IMPLEMENTED
75 NULL
, // TODO: OPCODE 0x22 NOT IMPLEMENTED
76 NULL
, // TODO: OPCODE 0x23 NOT IMPLEMENTED
77 NULL
, // TODO: OPCODE 0x24 NOT IMPLEMENTED
79 NULL
, // TODO: OPCODE 0x26 NOT IMPLEMENTED
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 Fast486ExtOpcodeConditionalJmp
,
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 Fast486ExtOpcodeConditionalSet
,
201 Fast486ExtOpcodePushFs
,
202 Fast486ExtOpcodePopFs
,
204 NULL
, // TODO: OPCODE 0xA3 NOT IMPLEMENTED
205 NULL
, // TODO: OPCODE 0xA4 NOT IMPLEMENTED
206 NULL
, // TODO: OPCODE 0xA5 NOT IMPLEMENTED
209 Fast486ExtOpcodePushGs
,
210 Fast486ExtOpcodePopGs
,
211 NULL
, // TODO: OPCODE 0xAA NOT IMPLEMENTED
212 NULL
, // TODO: OPCODE 0xAB NOT IMPLEMENTED
213 NULL
, // TODO: OPCODE 0xAC NOT IMPLEMENTED
214 NULL
, // TODO: OPCODE 0xAD NOT IMPLEMENTED
215 NULL
, // TODO: OPCODE 0xAE NOT IMPLEMENTED
216 NULL
, // TODO: OPCODE 0xAF NOT IMPLEMENTED
217 NULL
, // TODO: OPCODE 0xB0 NOT IMPLEMENTED
218 NULL
, // TODO: OPCODE 0xB1 NOT IMPLEMENTED
219 NULL
, // TODO: OPCODE 0xB2 NOT IMPLEMENTED
220 NULL
, // TODO: OPCODE 0xB3 NOT IMPLEMENTED
221 NULL
, // TODO: OPCODE 0xB4 NOT IMPLEMENTED
222 NULL
, // TODO: OPCODE 0xB5 NOT IMPLEMENTED
223 NULL
, // TODO: OPCODE 0xB6 NOT IMPLEMENTED
224 NULL
, // TODO: OPCODE 0xB7 NOT IMPLEMENTED
225 NULL
, // TODO: OPCODE 0xB8 NOT IMPLEMENTED
226 NULL
, // TODO: OPCODE 0xB9 NOT IMPLEMENTED
227 NULL
, // TODO: OPCODE 0xBA NOT IMPLEMENTED
228 NULL
, // TODO: OPCODE 0xBB NOT IMPLEMENTED
229 NULL
, // TODO: OPCODE 0xBC NOT IMPLEMENTED
230 NULL
, // TODO: OPCODE 0xBD NOT IMPLEMENTED
231 NULL
, // TODO: OPCODE 0xBE NOT IMPLEMENTED
232 NULL
, // TODO: OPCODE 0xBF NOT IMPLEMENTED
233 NULL
, // TODO: OPCODE 0xC0 NOT IMPLEMENTED
234 NULL
, // TODO: OPCODE 0xC1 NOT IMPLEMENTED
241 NULL
, // TODO: OPCODE 0xC8 NOT IMPLEMENTED
242 NULL
, // TODO: OPCODE 0xC9 NOT IMPLEMENTED
243 NULL
, // TODO: OPCODE 0xCA NOT IMPLEMENTED
244 NULL
, // TODO: OPCODE 0xCB NOT IMPLEMENTED
245 NULL
, // TODO: OPCODE 0xCC NOT IMPLEMENTED
246 NULL
, // TODO: OPCODE 0xCD NOT IMPLEMENTED
247 NULL
, // TODO: OPCODE 0xCE NOT IMPLEMENTED
248 NULL
, // TODO: OPCODE 0xCF NOT IMPLEMENTED
299 /* PUBLIC FUNCTIONS ***********************************************************/
301 FAST486_OPCODE_HANDLER(Fast486ExtOpcodePushFs
)
303 /* Call the internal API */
304 return Fast486StackPush(State
, State
->SegmentRegs
[FAST486_REG_FS
].Selector
);
307 FAST486_OPCODE_HANDLER(Fast486ExtOpcodePopFs
)
311 if (!Fast486StackPop(State
, &NewSelector
))
313 /* Exception occurred */
317 /* Call the internal API */
318 return Fast486LoadSegment(State
, FAST486_REG_FS
, LOWORD(NewSelector
));
321 FAST486_OPCODE_HANDLER(Fast486ExtOpcodePushGs
)
323 /* Call the internal API */
324 return Fast486StackPush(State
, State
->SegmentRegs
[FAST486_REG_GS
].Selector
);
327 FAST486_OPCODE_HANDLER(Fast486ExtOpcodePopGs
)
331 if (!Fast486StackPop(State
, &NewSelector
))
333 /* Exception occurred */
337 /* Call the internal API */
338 return Fast486LoadSegment(State
, FAST486_REG_GS
, LOWORD(NewSelector
));
341 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeConditionalJmp
)
343 BOOLEAN Jump
= FALSE
;
345 BOOLEAN Size
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
347 if (State
->PrefixFlags
& FAST486_PREFIX_OPSIZE
)
349 /* The OPSIZE prefix toggles the size */
353 if (State
->PrefixFlags
& FAST486_PREFIX_LOCK
)
356 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
360 /* Make sure this is the right instruction */
361 ASSERT((Opcode
& 0xF0) == 0x80);
363 /* Fetch the offset */
366 if (!Fast486FetchDword(State
, (PULONG
)&Offset
))
368 /* Exception occurred */
376 if (!Fast486FetchWord(State
, (PUSHORT
)&Value
))
378 /* Exception occurred */
383 Offset
= (LONG
)Value
;
386 switch ((Opcode
& 0x0F) >> 1)
391 Jump
= State
->Flags
.Of
;
398 Jump
= State
->Flags
.Cf
;
405 Jump
= State
->Flags
.Zf
;
412 Jump
= State
->Flags
.Cf
|| State
->Flags
.Zf
;
419 Jump
= State
->Flags
.Sf
;
426 Jump
= State
->Flags
.Pf
;
433 Jump
= State
->Flags
.Sf
!= State
->Flags
.Of
;
440 Jump
= (State
->Flags
.Sf
!= State
->Flags
.Of
) || State
->Flags
.Zf
;
447 /* Invert the result */
453 /* Move the instruction pointer */
454 State
->InstPtr
.Long
+= Offset
;
461 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeConditionalSet
)
463 BOOLEAN Value
= FALSE
;
464 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
465 FAST486_MOD_REG_RM ModRegRm
;
467 if (State
->PrefixFlags
& FAST486_PREFIX_ADSIZE
)
469 /* The OPSIZE prefix toggles the size */
470 AddressSize
= !AddressSize
;
473 /* Get the operands */
474 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
476 /* Exception occurred */
480 /* Make sure this is the right instruction */
481 ASSERT((Opcode
& 0xF0) == 0x90);
483 switch ((Opcode
& 0x0F) >> 1)
488 Value
= State
->Flags
.Of
;
495 Value
= State
->Flags
.Cf
;
502 Value
= State
->Flags
.Zf
;
509 Value
= State
->Flags
.Cf
|| State
->Flags
.Zf
;
516 Value
= State
->Flags
.Sf
;
523 Value
= State
->Flags
.Pf
;
530 Value
= State
->Flags
.Sf
!= State
->Flags
.Of
;
537 Value
= (State
->Flags
.Sf
!= State
->Flags
.Of
) || State
->Flags
.Zf
;
544 /* Invert the result */
548 /* Write back the result */
549 return Fast486WriteModrmByteOperands(State
, &ModRegRm
, FALSE
, Value
);
552 FAST486_OPCODE_HANDLER(Fast486OpcodeExtended
)
556 /* Fetch the second operation code */
557 if (!Fast486FetchByte(State
, &SecondOpcode
))
559 /* Exception occurred */
563 if (Fast486ExtendedHandlers
[SecondOpcode
] != NULL
)
565 /* Call the extended opcode handler */
566 return Fast486ExtendedHandlers
[SecondOpcode
](State
, SecondOpcode
);
570 /* This is not a valid opcode */
571 Fast486Exception(State
, FAST486_EXCEPTION_UD
);