ReactOS 0.4.15-dev-7834-g00c4b3d
opcodes.c File Reference
#include <windef.h>
#include <debug.h>
#include <fast486.h>
#include "opcodes.h"
#include "opgroups.h"
#include "extraops.h"
#include "common.h"
#include "fpu.h"
Include dependency graph for opcodes.c:

Go to the source code of this file.

Functions

 FAST486_OPCODE_HANDLER (Fast486OpcodeInvalid)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodePrefix)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeIncrement)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeDecrement)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodePushReg)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodePopReg)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeNop)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeExchangeEax)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeShortConditionalJmp)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeClearCarry)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeSetCarry)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeComplCarry)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeClearInt)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeSetInt)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeClearDir)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeSetDir)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeHalt)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeInByte)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeIn)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeOutByte)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeOut)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeShortJump)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeMovRegImm)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeMovByteRegImm)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeAddByteModrm)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeAddModrm)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeAddAl)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeAddEax)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeOrByteModrm)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeOrModrm)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeOrAl)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeOrEax)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeAndByteModrm)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeAndModrm)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeAndAl)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeAndEax)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeXorByteModrm)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeXorModrm)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeXorAl)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeXorEax)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeTestByteModrm)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeTestModrm)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeTestAl)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeTestEax)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeXchgByteModrm)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeXchgModrm)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodePushEs)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodePopEs)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodePushCs)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeAdcByteModrm)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeAdcModrm)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeAdcAl)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeAdcEax)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodePushSs)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodePopSs)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeSbbByteModrm)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeSbbModrm)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeSbbAl)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeSbbEax)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodePushDs)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodePopDs)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeDaa)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeCmpSubByteModrm)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeCmpSubModrm)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeCmpSubAl)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeCmpSubEax)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeDas)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeAaa)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeAas)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodePushAll)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodePopAll)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeBound)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeArpl)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodePushImm)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeImulModrmImm)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodePushByteImm)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeMovByteModrm)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeMovModrm)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeMovStoreSeg)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeLea)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeMovLoadSeg)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeCwde)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeCdq)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeCallAbs)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeWait)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodePushFlags)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodePopFlags)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeSahf)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeLahf)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeRet)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeLdsLes)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeEnter)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeLeave)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeRetFar)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeInt)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeIret)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeAam)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeAad)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeXlat)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeLoop)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeJecxz)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeCall)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeJmp)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeJmpAbs)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeMovAlOffset)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeMovEaxOffset)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeMovOffsetAl)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeMovOffsetEax)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeSalc)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeMovs)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeCmps)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeStos)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeLods)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeScas)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeIns)
 
 FAST486_OPCODE_HANDLER (Fast486OpcodeOuts)
 

Variables

FAST486_OPCODE_HANDLER_PROC Fast486OpcodeHandlers [FAST486_NUM_OPCODE_HANDLERS]
 

Function Documentation

◆ FAST486_OPCODE_HANDLER() [1/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeAaa  )

Definition at line 3150 of file opcodes.c.

3151{
3152 UCHAR Value = State->GeneralRegs[FAST486_REG_EAX].LowByte;
3153
3154 /*
3155 * Check if the value in AL is not a valid BCD digit,
3156 * or there was a carry from the lowest 4 bits of AL
3157 */
3158 if (((Value & 0x0F) > 9) || State->Flags.Af)
3159 {
3160 /* Correct it */
3161 State->GeneralRegs[FAST486_REG_EAX].LowWord += 0x06;
3162 State->GeneralRegs[FAST486_REG_EAX].HighByte++;
3163
3164 /* Set CF and AF */
3165 State->Flags.Cf = State->Flags.Af = TRUE;
3166 }
3167 else
3168 {
3169 /* Clear CF and AF */
3170 State->Flags.Cf = State->Flags.Af = FALSE;
3171 }
3172
3173 /* Keep only the lowest 4 bits of AL */
3174 State->GeneralRegs[FAST486_REG_EAX].LowByte &= 0x0F;
3175}
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
unsigned char UCHAR
Definition: xmlstorage.h:181

◆ FAST486_OPCODE_HANDLER() [2/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeAad  )

Definition at line 4734 of file opcodes.c.

4735{
4736 UCHAR Base;
4737 UCHAR Value = State->GeneralRegs[FAST486_REG_EAX].LowByte;
4738
4740
4741 /* Fetch the base */
4742 if (!Fast486FetchByte(State, &Base))
4743 {
4744 /* Exception occurred */
4745 return;
4746 }
4747
4748 /* Adjust */
4749 Value += State->GeneralRegs[FAST486_REG_EAX].HighByte * Base;
4750 State->GeneralRegs[FAST486_REG_EAX].LowWord = Value;
4751
4752 /* Update flags */
4753 State->Flags.Af = FALSE;
4754 State->Flags.Zf = (Value == 0);
4755 State->Flags.Sf = ((Value & SIGN_FLAG_BYTE) != 0);
4756 State->Flags.Pf = Fast486CalculateParity(Value);
4757}
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2439
#define SIGN_FLAG_BYTE
Definition: common.h:29
#define NO_LOCK_PREFIX()
Definition: common.h:43

◆ FAST486_OPCODE_HANDLER() [3/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeAam  )

Definition at line 4701 of file opcodes.c.

4702{
4703 UCHAR Base;
4704 UCHAR Value = State->GeneralRegs[FAST486_REG_EAX].LowByte;
4705
4707
4708 /* Fetch the base */
4709 if (!Fast486FetchByte(State, &Base))
4710 {
4711 /* Exception occurred */
4712 return;
4713 }
4714
4715 /* Check if the base is zero */
4716 if (Base == 0)
4717 {
4718 /* Divide error */
4719 Fast486Exception(State, FAST486_EXCEPTION_DE);
4720 return;
4721 }
4722
4723 /* Adjust */
4724 State->GeneralRegs[FAST486_REG_EAX].HighByte = Value / Base;
4725 State->GeneralRegs[FAST486_REG_EAX].LowByte = Value %= Base;
4726
4727 /* Update flags */
4728 State->Flags.Af = FALSE;
4729 State->Flags.Zf = (Value == 0);
4730 State->Flags.Sf = ((Value & SIGN_FLAG_BYTE) != 0);
4731 State->Flags.Pf = Fast486CalculateParity(Value);
4732}

◆ FAST486_OPCODE_HANDLER() [4/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeAas  )

Definition at line 3177 of file opcodes.c.

3178{
3179 UCHAR Value = State->GeneralRegs[FAST486_REG_EAX].LowByte;
3180
3181 /*
3182 * Check if the value in AL is not a valid BCD digit,
3183 * or there was a borrow from the lowest 4 bits of AL
3184 */
3185 if (((Value & 0x0F) > 9) || State->Flags.Af)
3186 {
3187 /* Correct it */
3188 State->GeneralRegs[FAST486_REG_EAX].LowWord -= 0x06;
3189 State->GeneralRegs[FAST486_REG_EAX].HighByte--;
3190
3191 /* Set CF and AF */
3192 State->Flags.Cf = State->Flags.Af = TRUE;
3193 }
3194 else
3195 {
3196 /* Clear CF and AF */
3197 State->Flags.Cf = State->Flags.Af = FALSE;
3198 }
3199
3200 /* Keep only the lowest 4 bits of AL */
3201 State->GeneralRegs[FAST486_REG_EAX].LowByte &= 0x0F;
3202}

◆ FAST486_OPCODE_HANDLER() [5/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeAdcAl  )

Definition at line 2392 of file opcodes.c.

2393{
2394 UCHAR FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowByte;
2395 UCHAR SecondValue, Result;
2396
2397 /* Make sure this is the right instruction */
2398 ASSERT(Opcode == 0x14);
2399
2401
2402 if (!Fast486FetchByte(State, &SecondValue))
2403 {
2404 /* Exception occurred */
2405 return;
2406 }
2407
2408 /* Calculate the result */
2409 Result = FirstValue + SecondValue + State->Flags.Cf;
2410
2411 /* Special exception for CF */
2412 State->Flags.Cf = State->Flags.Cf &&
2413 ((FirstValue == 0xFF) || (SecondValue == 0xFF));
2414
2415 /* Update the flags */
2416 State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue));
2417 State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) == (SecondValue & SIGN_FLAG_BYTE))
2418 && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
2419 State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
2420 State->Flags.Zf = (Result == 0);
2421 State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
2422 State->Flags.Pf = Fast486CalculateParity(Result);
2423
2424 /* Write back the result */
2425 State->GeneralRegs[FAST486_REG_EAX].LowByte = Result;
2426}
_In_ PVOID _In_ ULONG Opcode
Definition: hubbusif.h:331
#define ASSERT(a)
Definition: mode.c:44
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409

◆ FAST486_OPCODE_HANDLER() [6/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeAdcByteModrm  )

Definition at line 2248 of file opcodes.c.

2249{
2250 UCHAR FirstValue, SecondValue, Result;
2251 FAST486_MOD_REG_RM ModRegRm;
2252 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
2253
2254 /* Make sure this is the right instruction */
2255 ASSERT((Opcode & 0xFD) == 0x10);
2256
2257 TOGGLE_ADSIZE(AddressSize);
2258
2259 /* Get the operands */
2260 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
2261 {
2262 /* Exception occurred */
2263 return;
2264 }
2265
2266 if (!Fast486ReadModrmByteOperands(State,
2267 &ModRegRm,
2268 &FirstValue,
2269 &SecondValue))
2270 {
2271 /* Exception occurred */
2272 return;
2273 }
2274
2275 /* Calculate the result */
2276 Result = FirstValue + SecondValue + State->Flags.Cf;
2277
2278 /* Special exception for CF */
2279 State->Flags.Cf = State->Flags.Cf
2280 && ((FirstValue == 0xFF) || (SecondValue == 0xFF));
2281
2282 /* Update the flags */
2283 State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue));
2284 State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) == (SecondValue & SIGN_FLAG_BYTE))
2285 && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
2286 State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
2287 State->Flags.Zf = (Result == 0);
2288 State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
2289 State->Flags.Pf = Fast486CalculateParity(Result);
2290
2291 /* Write back the result */
2292 Fast486WriteModrmByteOperands(State,
2293 &ModRegRm,
2295 Result);
2296}
unsigned char BOOLEAN
#define FAST486_OPCODE_WRITE_REG
Definition: opcodes.h:30
#define TOGGLE_ADSIZE(x)
Definition: common.h:53

◆ FAST486_OPCODE_HANDLER() [7/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeAdcEax  )

Definition at line 2428 of file opcodes.c.

2429{
2430 BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
2431
2432 /* Make sure this is the right instruction */
2433 ASSERT(Opcode == 0x15);
2434
2437
2438 if (Size)
2439 {
2440 ULONG FirstValue = State->GeneralRegs[FAST486_REG_EAX].Long;
2441 ULONG SecondValue, Result;
2442
2443 if (!Fast486FetchDword(State, &SecondValue))
2444 {
2445 /* Exception occurred */
2446 return;
2447 }
2448
2449 /* Calculate the result */
2450 Result = FirstValue + SecondValue + State->Flags.Cf;
2451
2452 /* Special exception for CF */
2453 State->Flags.Cf = State->Flags.Cf &&
2454 ((FirstValue == 0xFFFFFFFF) || (SecondValue == 0xFFFFFFFF));
2455
2456 /* Update the flags */
2457 State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue));
2458 State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) == (SecondValue & SIGN_FLAG_LONG))
2459 && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
2460 State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
2461 State->Flags.Zf = (Result == 0);
2462 State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
2463 State->Flags.Pf = Fast486CalculateParity(Result);
2464
2465 /* Write back the result */
2466 State->GeneralRegs[FAST486_REG_EAX].Long = Result;
2467 }
2468 else
2469 {
2470 USHORT FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowWord;
2471 USHORT SecondValue, Result;
2472
2473 if (!Fast486FetchWord(State, &SecondValue))
2474 {
2475 /* Exception occurred */
2476 return;
2477 }
2478
2479 /* Calculate the result */
2480 Result = FirstValue + SecondValue + State->Flags.Cf;
2481
2482 /* Special exception for CF */
2483 State->Flags.Cf = State->Flags.Cf &&
2484 ((FirstValue == 0xFFFF) || (SecondValue == 0xFFFF));
2485
2486 /* Update the flags */
2487 State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue));
2488 State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) == (SecondValue & SIGN_FLAG_WORD))
2489 && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
2490 State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
2491 State->Flags.Zf = (Result == 0);
2492 State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
2493 State->Flags.Pf = Fast486CalculateParity(Result);
2494
2495 /* Write back the result */
2496 State->GeneralRegs[FAST486_REG_EAX].LowWord = Result;
2497 }
2498}
unsigned short USHORT
Definition: pedump.c:61
#define SIGN_FLAG_WORD
Definition: common.h:30
#define SIGN_FLAG_LONG
Definition: common.h:31
#define TOGGLE_OPSIZE(x)
Definition: common.h:50
uint32_t ULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533

◆ FAST486_OPCODE_HANDLER() [8/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeAdcModrm  )

Definition at line 2298 of file opcodes.c.

2299{
2300 FAST486_MOD_REG_RM ModRegRm;
2301 BOOLEAN OperandSize, AddressSize;
2302
2303 /* Make sure this is the right instruction */
2304 ASSERT((Opcode & 0xFD) == 0x11);
2305
2306 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
2307
2308 TOGGLE_ADSIZE(AddressSize);
2309 TOGGLE_OPSIZE(OperandSize);
2310
2311 /* Get the operands */
2312 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
2313 {
2314 /* Exception occurred */
2315 return;
2316 }
2317
2318 /* Check the operand size */
2319 if (OperandSize)
2320 {
2321 ULONG FirstValue, SecondValue, Result;
2322
2323 if (!Fast486ReadModrmDwordOperands(State,
2324 &ModRegRm,
2325 &FirstValue,
2326 &SecondValue))
2327 {
2328 /* Exception occurred */
2329 return;
2330 }
2331
2332 /* Calculate the result */
2333 Result = FirstValue + SecondValue + State->Flags.Cf;
2334
2335 /* Special exception for CF */
2336 State->Flags.Cf = State->Flags.Cf
2337 && ((FirstValue == 0xFFFFFFFF) || (SecondValue == 0xFFFFFFFF));
2338
2339 /* Update the flags */
2340 State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue));
2341 State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) == (SecondValue & SIGN_FLAG_LONG))
2342 && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
2343 State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
2344 State->Flags.Zf = (Result == 0);
2345 State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
2346 State->Flags.Pf = Fast486CalculateParity(Result);
2347
2348 /* Write back the result */
2349 Fast486WriteModrmDwordOperands(State,
2350 &ModRegRm,
2352 Result);
2353 }
2354 else
2355 {
2356 USHORT FirstValue, SecondValue, Result;
2357
2358 if (!Fast486ReadModrmWordOperands(State,
2359 &ModRegRm,
2360 &FirstValue,
2361 &SecondValue))
2362 {
2363 /* Exception occurred */
2364 return;
2365 }
2366
2367 /* Calculate the result */
2368 Result = FirstValue + SecondValue + State->Flags.Cf;
2369
2370 /* Special exception for CF */
2371 State->Flags.Cf = State->Flags.Cf
2372 && ((FirstValue == 0xFFFF) || (SecondValue == 0xFFFF));
2373
2374 /* Update the flags */
2375 State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue));
2376 State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) == (SecondValue & SIGN_FLAG_WORD))
2377 && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
2378 State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
2379 State->Flags.Zf = (Result == 0);
2380 State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
2381 State->Flags.Pf = Fast486CalculateParity(Result);
2382
2383 /* Write back the result */
2384 Fast486WriteModrmWordOperands(State,
2385 &ModRegRm,
2387 Result);
2388 }
2389
2390}

◆ FAST486_OPCODE_HANDLER() [9/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeAddAl  )

Definition at line 1169 of file opcodes.c.

1170{
1171 UCHAR FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowByte;
1172 UCHAR SecondValue, Result;
1173
1174 /* Make sure this is the right instruction */
1175 ASSERT(Opcode == 0x04);
1176
1178
1179 if (!Fast486FetchByte(State, &SecondValue))
1180 {
1181 /* Exception occurred */
1182 return;
1183 }
1184
1185 /* Calculate the result */
1186 Result = FirstValue + SecondValue;
1187
1188 /* Update the flags */
1189 State->Flags.Cf = (Result < FirstValue) && (Result < SecondValue);
1190 State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) == (SecondValue & SIGN_FLAG_BYTE))
1191 && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
1192 State->Flags.Af = ((((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) != 0);
1193 State->Flags.Zf = (Result == 0);
1194 State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
1195 State->Flags.Pf = Fast486CalculateParity(Result);
1196
1197 /* Write back the result */
1198 State->GeneralRegs[FAST486_REG_EAX].LowByte = Result;
1199}

◆ FAST486_OPCODE_HANDLER() [10/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeAddByteModrm  )

Definition at line 1038 of file opcodes.c.

1039{
1040 UCHAR FirstValue, SecondValue, Result;
1041 FAST486_MOD_REG_RM ModRegRm;
1042 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
1043
1044 /* Make sure this is the right instruction */
1045 ASSERT((Opcode & 0xFD) == 0x00);
1046
1047 TOGGLE_ADSIZE(AddressSize);
1048
1049 /* Get the operands */
1050 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
1051 {
1052 /* Exception occurred */
1053 return;
1054 }
1055
1056 if (!Fast486ReadModrmByteOperands(State,
1057 &ModRegRm,
1058 &FirstValue,
1059 &SecondValue))
1060 {
1061 /* Exception occurred */
1062 return;
1063 }
1064
1065 /* Calculate the result */
1066 Result = FirstValue + SecondValue;
1067
1068 /* Update the flags */
1069 State->Flags.Cf = (Result < FirstValue) && (Result < SecondValue);
1070 State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) == (SecondValue & SIGN_FLAG_BYTE))
1071 && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
1072 State->Flags.Af = ((((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) != 0);
1073 State->Flags.Zf = (Result == 0);
1074 State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
1075 State->Flags.Pf = Fast486CalculateParity(Result);
1076
1077 /* Write back the result */
1078 Fast486WriteModrmByteOperands(State,
1079 &ModRegRm,
1081 Result);
1082}

◆ FAST486_OPCODE_HANDLER() [11/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeAddEax  )

Definition at line 1201 of file opcodes.c.

1202{
1203 BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
1204
1205 /* Make sure this is the right instruction */
1206 ASSERT(Opcode == 0x05);
1207
1210
1211 if (Size)
1212 {
1213 ULONG FirstValue = State->GeneralRegs[FAST486_REG_EAX].Long;
1214 ULONG SecondValue, Result;
1215
1216 if (!Fast486FetchDword(State, &SecondValue))
1217 {
1218 /* Exception occurred */
1219 return;
1220 }
1221
1222 /* Calculate the result */
1223 Result = FirstValue + SecondValue;
1224
1225 /* Update the flags */
1226 State->Flags.Cf = (Result < FirstValue) && (Result < SecondValue);
1227 State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) == (SecondValue & SIGN_FLAG_LONG))
1228 && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
1229 State->Flags.Af = ((((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) != 0);
1230 State->Flags.Zf = (Result == 0);
1231 State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
1232 State->Flags.Pf = Fast486CalculateParity(Result);
1233
1234 /* Write back the result */
1235 State->GeneralRegs[FAST486_REG_EAX].Long = Result;
1236 }
1237 else
1238 {
1239 USHORT FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowWord;
1240 USHORT SecondValue, Result;
1241
1242 if (!Fast486FetchWord(State, &SecondValue))
1243 {
1244 /* Exception occurred */
1245 return;
1246 }
1247
1248 /* Calculate the result */
1249 Result = FirstValue + SecondValue;
1250
1251 /* Update the flags */
1252 State->Flags.Cf = (Result < FirstValue) && (Result < SecondValue);
1253 State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) == (SecondValue & SIGN_FLAG_WORD))
1254 && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
1255 State->Flags.Af = ((((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) != 0);
1256 State->Flags.Zf = (Result == 0);
1257 State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
1258 State->Flags.Pf = Fast486CalculateParity(Result);
1259
1260 /* Write back the result */
1261 State->GeneralRegs[FAST486_REG_EAX].LowWord = Result;
1262 }
1263}

◆ FAST486_OPCODE_HANDLER() [12/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeAddModrm  )

Definition at line 1084 of file opcodes.c.

1085{
1086 FAST486_MOD_REG_RM ModRegRm;
1087 BOOLEAN OperandSize, AddressSize;
1088
1089 /* Make sure this is the right instruction */
1090 ASSERT((Opcode & 0xFD) == 0x01);
1091
1092 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
1093
1094 TOGGLE_ADSIZE(AddressSize);
1095 TOGGLE_OPSIZE(OperandSize);
1096
1097 /* Get the operands */
1098 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
1099 {
1100 /* Exception occurred */
1101 return;
1102 }
1103
1104 /* Check the operand size */
1105 if (OperandSize)
1106 {
1107 ULONG FirstValue, SecondValue, Result;
1108
1109 if (!Fast486ReadModrmDwordOperands(State,
1110 &ModRegRm,
1111 &FirstValue,
1112 &SecondValue))
1113 {
1114 /* Exception occurred */
1115 return;
1116 }
1117
1118 /* Calculate the result */
1119 Result = FirstValue + SecondValue;
1120
1121 /* Update the flags */
1122 State->Flags.Cf = (Result < FirstValue) && (Result < SecondValue);
1123 State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) == (SecondValue & SIGN_FLAG_LONG))
1124 && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
1125 State->Flags.Af = ((((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) != 0);
1126 State->Flags.Zf = (Result == 0);
1127 State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
1128 State->Flags.Pf = Fast486CalculateParity(Result);
1129
1130 /* Write back the result */
1131 Fast486WriteModrmDwordOperands(State,
1132 &ModRegRm,
1134 Result);
1135 }
1136 else
1137 {
1138 USHORT FirstValue, SecondValue, Result;
1139
1140 if (!Fast486ReadModrmWordOperands(State,
1141 &ModRegRm,
1142 &FirstValue,
1143 &SecondValue))
1144 {
1145 /* Exception occurred */
1146 return;
1147 }
1148
1149 /* Calculate the result */
1150 Result = FirstValue + SecondValue;
1151
1152 /* Update the flags */
1153 State->Flags.Cf = (Result < FirstValue) && (Result < SecondValue);
1154 State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) == (SecondValue & SIGN_FLAG_WORD))
1155 && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
1156 State->Flags.Af = ((((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) != 0);
1157 State->Flags.Zf = (Result == 0);
1158 State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
1159 State->Flags.Pf = Fast486CalculateParity(Result);
1160
1161 /* Write back the result */
1162 Fast486WriteModrmWordOperands(State,
1163 &ModRegRm,
1165 Result);
1166 }
1167}

◆ FAST486_OPCODE_HANDLER() [13/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeAndAl  )

Definition at line 1605 of file opcodes.c.

1606{
1607 UCHAR FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowByte;
1608 UCHAR SecondValue, Result;
1609
1610 /* Make sure this is the right instruction */
1611 ASSERT(Opcode == 0x24);
1612
1614
1615 if (!Fast486FetchByte(State, &SecondValue))
1616 {
1617 /* Exception occurred */
1618 return;
1619 }
1620
1621 /* Calculate the result */
1622 Result = FirstValue & SecondValue;
1623
1624 /* Update the flags */
1625 State->Flags.Cf = FALSE;
1626 State->Flags.Of = FALSE;
1627 State->Flags.Zf = (Result == 0);
1628 State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
1629 State->Flags.Pf = Fast486CalculateParity(Result);
1630
1631 /* Write back the result */
1632 State->GeneralRegs[FAST486_REG_EAX].LowByte = Result;
1633}

◆ FAST486_OPCODE_HANDLER() [14/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeAndByteModrm  )

Definition at line 1480 of file opcodes.c.

1481{
1482 UCHAR FirstValue, SecondValue, Result;
1483 FAST486_MOD_REG_RM ModRegRm;
1484 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
1485
1486 /* Make sure this is the right instruction */
1487 ASSERT((Opcode & 0xFD) == 0x20);
1488
1489 TOGGLE_ADSIZE(AddressSize);
1490
1491 /* Get the operands */
1492 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
1493 {
1494 /* Exception occurred */
1495 return;
1496 }
1497
1498 if (!Fast486ReadModrmByteOperands(State,
1499 &ModRegRm,
1500 &FirstValue,
1501 &SecondValue))
1502 {
1503 /* Exception occurred */
1504 return;
1505 }
1506
1507 /* Calculate the result */
1508 Result = FirstValue & SecondValue;
1509
1510 /* Update the flags */
1511 State->Flags.Cf = FALSE;
1512 State->Flags.Of = FALSE;
1513 State->Flags.Zf = (Result == 0);
1514 State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
1515 State->Flags.Pf = Fast486CalculateParity(Result);
1516
1517 /* Write back the result */
1518 Fast486WriteModrmByteOperands(State,
1519 &ModRegRm,
1521 Result);
1522}

◆ FAST486_OPCODE_HANDLER() [15/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeAndEax  )

Definition at line 1635 of file opcodes.c.

1636{
1637 BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
1638
1639 /* Make sure this is the right instruction */
1640 ASSERT(Opcode == 0x25);
1641
1644
1645 if (Size)
1646 {
1647 ULONG FirstValue = State->GeneralRegs[FAST486_REG_EAX].Long;
1648 ULONG SecondValue, Result;
1649
1650 if (!Fast486FetchDword(State, &SecondValue))
1651 {
1652 /* Exception occurred */
1653 return;
1654 }
1655
1656 /* Calculate the result */
1657 Result = FirstValue & SecondValue;
1658
1659 /* Update the flags */
1660 State->Flags.Cf = FALSE;
1661 State->Flags.Of = FALSE;
1662 State->Flags.Zf = (Result == 0);
1663 State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
1664 State->Flags.Pf = Fast486CalculateParity(Result);
1665
1666 /* Write back the result */
1667 State->GeneralRegs[FAST486_REG_EAX].Long = Result;
1668 }
1669 else
1670 {
1671 USHORT FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowWord;
1672 USHORT SecondValue, Result;
1673
1674 if (!Fast486FetchWord(State, &SecondValue))
1675 {
1676 /* Exception occurred */
1677 return;
1678 }
1679
1680 /* Calculate the result */
1681 Result = FirstValue & SecondValue;
1682
1683 /* Update the flags */
1684 State->Flags.Cf = FALSE;
1685 State->Flags.Of = FALSE;
1686 State->Flags.Zf = (Result == 0);
1687 State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
1688 State->Flags.Pf = Fast486CalculateParity(Result);
1689
1690 /* Write back the result */
1691 State->GeneralRegs[FAST486_REG_EAX].LowWord = Result;
1692 }
1693}

◆ FAST486_OPCODE_HANDLER() [16/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeAndModrm  )

Definition at line 1524 of file opcodes.c.

1525{
1526 FAST486_MOD_REG_RM ModRegRm;
1527 BOOLEAN OperandSize, AddressSize;
1528
1529 /* Make sure this is the right instruction */
1530 ASSERT((Opcode & 0xFD) == 0x21);
1531
1532 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
1533
1534 TOGGLE_ADSIZE(AddressSize);
1535 TOGGLE_OPSIZE(OperandSize);
1536
1537 /* Get the operands */
1538 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
1539 {
1540 /* Exception occurred */
1541 return;
1542 }
1543
1544 /* Check the operand size */
1545 if (OperandSize)
1546 {
1547 ULONG FirstValue, SecondValue, Result;
1548
1549 if (!Fast486ReadModrmDwordOperands(State,
1550 &ModRegRm,
1551 &FirstValue,
1552 &SecondValue))
1553 {
1554 /* Exception occurred */
1555 return;
1556 }
1557
1558 /* Calculate the result */
1559 Result = FirstValue & SecondValue;
1560
1561 /* Update the flags */
1562 State->Flags.Cf = FALSE;
1563 State->Flags.Of = FALSE;
1564 State->Flags.Zf = (Result == 0);
1565 State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
1566 State->Flags.Pf = Fast486CalculateParity(Result);
1567
1568 /* Write back the result */
1569 Fast486WriteModrmDwordOperands(State,
1570 &ModRegRm,
1572 Result);
1573 }
1574 else
1575 {
1576 USHORT FirstValue, SecondValue, Result;
1577
1578 if (!Fast486ReadModrmWordOperands(State,
1579 &ModRegRm,
1580 &FirstValue,
1581 &SecondValue))
1582 {
1583 /* Exception occurred */
1584 return;
1585 }
1586
1587 /* Calculate the result */
1588 Result = FirstValue & SecondValue;
1589
1590 /* Update the flags */
1591 State->Flags.Cf = FALSE;
1592 State->Flags.Of = FALSE;
1593 State->Flags.Zf = (Result == 0);
1594 State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
1595 State->Flags.Pf = Fast486CalculateParity(Result);
1596
1597 /* Write back the result */
1598 Fast486WriteModrmWordOperands(State,
1599 &ModRegRm,
1601 Result);
1602 }
1603}

◆ FAST486_OPCODE_HANDLER() [17/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeArpl  )

Definition at line 3368 of file opcodes.c.

3369{
3370 USHORT FirstValue, SecondValue;
3371 FAST486_MOD_REG_RM ModRegRm;
3372 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
3373
3374 if (!(State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
3375 || State->Flags.Vm
3376 || (State->PrefixFlags & FAST486_PREFIX_LOCK))
3377 {
3378 /* Cannot be used in real mode or with a LOCK prefix */
3379 Fast486Exception(State, FAST486_EXCEPTION_UD);
3380 return;
3381 }
3382
3383 TOGGLE_ADSIZE(AddressSize);
3384
3385 /* Get the operands */
3386 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
3387 {
3388 /* Exception occurred */
3389 return;
3390 }
3391
3392 /* Read the operands */
3393 if (!Fast486ReadModrmWordOperands(State,
3394 &ModRegRm,
3395 &FirstValue,
3396 &SecondValue))
3397 {
3398 /* Exception occurred */
3399 return;
3400 }
3401
3402 /* Check if the RPL needs adjusting */
3403 if ((SecondValue & 3) < (FirstValue & 3))
3404 {
3405 /* Adjust the RPL */
3406 SecondValue &= ~3;
3407 SecondValue |= FirstValue & 3;
3408
3409 /* Set ZF */
3410 State->Flags.Zf = TRUE;
3411
3412 /* Write back the result */
3413 Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, SecondValue);
3414 }
3415 else
3416 {
3417 /* Clear ZF */
3418 State->Flags.Zf = FALSE;
3419 }
3420}
#define FAST486_CR0_PE
Definition: fast486.h:46
#define FAST486_PREFIX_LOCK
Definition: fast486.h:101

◆ FAST486_OPCODE_HANDLER() [18/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeBound  )

Definition at line 3272 of file opcodes.c.

3273{
3274 BOOLEAN OperandSize, AddressSize;
3275 FAST486_MOD_REG_RM ModRegRm;
3276 FAST486_SEG_REGS Segment = FAST486_REG_DS;
3277
3278 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
3279
3281 TOGGLE_OPSIZE(OperandSize);
3282 TOGGLE_ADSIZE(AddressSize);
3283
3284 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
3285 {
3286 /* Exception occurred */
3287 return;
3288 }
3289
3290 if (!ModRegRm.Memory)
3291 {
3292 /* Invalid */
3293 Fast486Exception(State, FAST486_EXCEPTION_UD);
3294 return;
3295 }
3296
3297 /* Check for the segment override */
3298 if (State->PrefixFlags & FAST486_PREFIX_SEG)
3299 {
3300 /* Use the override segment instead */
3301 Segment = State->SegmentOverride;
3302 }
3303
3304 if (OperandSize)
3305 {
3306 LONG Index, LowerBound, UpperBound;
3307
3308 /* Read the operands */
3309 if (!Fast486ReadModrmDwordOperands(State,
3310 &ModRegRm,
3311 (PULONG)&Index,
3312 (PULONG)&LowerBound))
3313 {
3314 /* Exception occurred */
3315 return;
3316 }
3317
3319 Segment,
3320 ModRegRm.MemoryAddress + sizeof(ULONG),
3321 FALSE,
3322 &UpperBound,
3323 sizeof(ULONG)))
3324 {
3325 /* Exception occurred */
3326 return;
3327 }
3328
3329 if ((Index < LowerBound) || (Index > UpperBound))
3330 {
3331 /* Out of bounds */
3332 Fast486Exception(State, FAST486_EXCEPTION_BR);
3333 }
3334 }
3335 else
3336 {
3337 SHORT Index, LowerBound, UpperBound;
3338
3339 /* Read the operands */
3340 if (!Fast486ReadModrmWordOperands(State,
3341 &ModRegRm,
3342 (PUSHORT)&Index,
3343 (PUSHORT)&LowerBound))
3344 {
3345 /* Exception occurred */
3346 return;
3347 }
3348
3350 Segment,
3351 ModRegRm.MemoryAddress + sizeof(USHORT),
3352 FALSE,
3353 &UpperBound,
3354 sizeof(USHORT)))
3355 {
3356 /* Exception occurred */
3357 return;
3358 }
3359
3360 if ((Index < LowerBound) || (Index > UpperBound))
3361 {
3362 /* Out of bounds */
3363 Fast486Exception(State, FAST486_EXCEPTION_BR);
3364 }
3365 }
3366}
#define FAST486_PREFIX_SEG
Definition: fast486.h:98
short SHORT
Definition: pedump.c:59
long LONG
Definition: pedump.c:60
BOOLEAN FASTCALL Fast486ReadMemory(PFAST486_STATE State, FAST486_SEG_REGS SegmentReg, ULONG Offset, BOOLEAN InstFetch, PVOID Buffer, ULONG Size)
Definition: common.c:36
ULONG MemoryAddress
Definition: common.h:81
BOOLEAN Memory
Definition: common.h:77
uint32_t * PULONG
Definition: typedefs.h:59
uint16_t * PUSHORT
Definition: typedefs.h:56
_In_ WDFCOLLECTION _In_ ULONG Index
_Inout_ PVOID Segment
Definition: exfuncs.h:1101

◆ FAST486_OPCODE_HANDLER() [19/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeCall  )

Definition at line 4856 of file opcodes.c.

4857{
4858 BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
4859
4860 /* Make sure this is the right instruction */
4861 ASSERT(Opcode == 0xE8);
4862
4865
4866 if (Size)
4867 {
4868 LONG Offset = 0;
4869
4870 /* Fetch the offset */
4871 if (!Fast486FetchDword(State, (PULONG)&Offset))
4872 {
4873 /* An exception occurred */
4874 return;
4875 }
4876
4877 /* Push the current value of the instruction pointer */
4878 if (!Fast486StackPush(State, State->InstPtr.Long))
4879 {
4880 /* Exception occurred */
4881 return;
4882 }
4883
4884 /* Move the instruction pointer */
4885 State->InstPtr.Long += Offset;
4886 }
4887 else
4888 {
4889 SHORT Offset = 0;
4890
4891 /* Fetch the offset */
4892 if (!Fast486FetchWord(State, (PUSHORT)&Offset))
4893 {
4894 /* An exception occurred */
4895 return;
4896 }
4897
4898 /* Push the current value of the instruction pointer */
4899 if (!Fast486StackPush(State, State->InstPtr.Long))
4900 {
4901 /* Exception occurred */
4902 return;
4903 }
4904
4905 /* Move the instruction pointer */
4906 State->InstPtr.LowWord += Offset;
4907 }
4908}
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101

◆ FAST486_OPCODE_HANDLER() [20/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeCallAbs  )

Definition at line 3910 of file opcodes.c.

3911{
3912 USHORT Segment = 0;
3913 ULONG Offset = 0;
3914 BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
3915
3916 /* Make sure this is the right instruction */
3917 ASSERT(Opcode == 0x9A);
3918
3921
3922 /* Fetch the offset */
3923 if (Size)
3924 {
3925 if (!Fast486FetchDword(State, &Offset))
3926 {
3927 /* Exception occurred */
3928 return;
3929 }
3930 }
3931 else
3932 {
3933 if (!Fast486FetchWord(State, (PUSHORT)&Offset))
3934 {
3935 /* Exception occurred */
3936 return;
3937 }
3938 }
3939
3940 /* Fetch the segment */
3941 if (!Fast486FetchWord(State, &Segment))
3942 {
3943 /* Exception occurred */
3944 return;
3945 }
3946
3947 if ((State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) && !State->Flags.Vm)
3948 {
3949 if (!Fast486ProcessGate(State, Segment, Offset, TRUE))
3950 {
3951 /* Gate processed or exception occurred */
3952 return;
3953 }
3954 }
3955
3956 /* Push the current code segment selector */
3957 if (!Fast486StackPush(State, State->SegmentRegs[FAST486_REG_CS].Selector))
3958 {
3959 /* Exception occurred */
3960 return;
3961 }
3962
3963 /* Push the current value of the instruction pointer */
3964 if (!Fast486StackPush(State, State->InstPtr.Long))
3965 {
3966 /* Exception occurred */
3967 return;
3968 }
3969
3970 /* Load the new CS */
3971 if (!Fast486LoadSegment(State, FAST486_REG_CS, Segment))
3972 {
3973 /* Exception occurred */
3974 return;
3975 }
3976
3977 /* Load new (E)IP */
3978 if (Size) State->InstPtr.Long = Offset;
3979 else State->InstPtr.LowWord = LOWORD(Offset);
3980}
#define LOWORD(l)
Definition: pedump.c:82

◆ FAST486_OPCODE_HANDLER() [21/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeCdq  )

Definition at line 3884 of file opcodes.c.

3885{
3886 BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
3887
3888 /* Make sure this is the right instruction */
3889 ASSERT(Opcode == 0x99);
3890
3893
3894 if (Size)
3895 {
3896 /* Sign extend EAX to EDX:EAX */
3897 State->GeneralRegs[FAST486_REG_EDX].Long =
3898 (State->GeneralRegs[FAST486_REG_EAX].Long & SIGN_FLAG_LONG)
3899 ? 0xFFFFFFFF : 0x00000000;
3900 }
3901 else
3902 {
3903 /* Sign extend AX to DX:AX */
3904 State->GeneralRegs[FAST486_REG_EDX].LowWord =
3905 (State->GeneralRegs[FAST486_REG_EAX].LowWord & SIGN_FLAG_WORD)
3906 ? 0xFFFF : 0x0000;
3907 }
3908}

◆ FAST486_OPCODE_HANDLER() [22/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeClearCarry  )

Definition at line 633 of file opcodes.c.

634{
635 /* Make sure this is the right instruction */
636 ASSERT(Opcode == 0xF8);
637
639
640 /* Clear CF and return success */
641 State->Flags.Cf = FALSE;
642}

◆ FAST486_OPCODE_HANDLER() [23/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeClearDir  )

Definition at line 727 of file opcodes.c.

728{
729 /* Make sure this is the right instruction */
730 ASSERT(Opcode == 0xFC);
731
733
734 /* Clear DF */
735 State->Flags.Df = FALSE;
736}

◆ FAST486_OPCODE_HANDLER() [24/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeClearInt  )

Definition at line 667 of file opcodes.c.

668{
669 /* Make sure this is the right instruction */
670 ASSERT(Opcode == 0xFA);
671
673
674 /* Check for protected mode */
675 if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
676 {
677 /* Check IOPL */
678 if (State->Flags.Iopl >= Fast486GetCurrentPrivLevel(State))
679 {
680 /* Clear the interrupt flag */
681 State->Flags.If = FALSE;
682 }
683 else
684 {
685 /* General Protection Fault */
686 Fast486Exception(State, FAST486_EXCEPTION_GP);
687 return;
688 }
689 }
690 else
691 {
692 /* Just clear the interrupt flag */
693 State->Flags.If = FALSE;
694 }
695}

◆ FAST486_OPCODE_HANDLER() [25/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeCmps  )

Definition at line 5368 of file opcodes.c.

5369{
5370 ULONG FirstValue = 0, SecondValue = 0, Result;
5371 ULONG DataSize, DataMask, SignFlag;
5372 BOOLEAN OperandSize, AddressSize;
5373 FAST486_SEG_REGS Segment = FAST486_REG_DS;
5374
5375 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
5376
5377 /* Make sure this is the right instruction */
5378 ASSERT((Opcode & 0xFE) == 0xA6);
5379
5380 TOGGLE_OPSIZE(OperandSize);
5381 TOGGLE_ADSIZE(AddressSize);
5382
5383 if (State->PrefixFlags & FAST486_PREFIX_SEG)
5384 {
5385 /* Use the override segment instead of DS */
5386 Segment = State->SegmentOverride;
5387 }
5388
5389 if ((State->PrefixFlags & FAST486_PREFIX_REP)
5390 || (State->PrefixFlags & FAST486_PREFIX_REPNZ))
5391 {
5392 if ((AddressSize && (State->GeneralRegs[FAST486_REG_ECX].Long == 0))
5393 || (!AddressSize && (State->GeneralRegs[FAST486_REG_ECX].LowWord == 0)))
5394 {
5395 /* Do nothing */
5396 return;
5397 }
5398 }
5399
5400 /* Calculate the size */
5401 if (Opcode == 0xA6) DataSize = sizeof(UCHAR);
5402 else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);
5403
5404 /* Calculate the mask and sign flag */
5405 SignFlag = 1 << ((DataSize * 8) - 1);
5406 DataMask = SignFlag | (SignFlag - 1);
5407
5408 /* Read from the first source operand */
5410 Segment,
5411 AddressSize ? State->GeneralRegs[FAST486_REG_ESI].Long
5412 : State->GeneralRegs[FAST486_REG_ESI].LowWord,
5413 FALSE,
5414 &FirstValue,
5415 DataSize))
5416 {
5417 /* Exception occurred */
5418 return;
5419 }
5420
5421 /* Read from the second source operand */
5423 FAST486_REG_ES,
5424 AddressSize ? State->GeneralRegs[FAST486_REG_EDI].Long
5425 : State->GeneralRegs[FAST486_REG_EDI].LowWord,
5426 FALSE,
5427 &SecondValue,
5428 DataSize))
5429 {
5430 /* Exception occurred */
5431 return;
5432 }
5433
5434 /* Calculate the result */
5435 FirstValue &= DataMask;
5436 SecondValue &= DataMask;
5437 Result = (FirstValue - SecondValue) & DataMask;
5438
5439 /* Update the flags */
5440 State->Flags.Cf = (FirstValue < SecondValue);
5441 State->Flags.Of = ((FirstValue & SignFlag) != (SecondValue & SignFlag))
5442 && ((FirstValue & SignFlag) != (Result & SignFlag));
5443 State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F);
5444 State->Flags.Zf = (Result == 0);
5445 State->Flags.Sf = ((Result & SignFlag) != 0);
5446 State->Flags.Pf = Fast486CalculateParity(Result);
5447
5448 /* Increment/decrement ESI and EDI */
5449 if (AddressSize)
5450 {
5451 if (!State->Flags.Df)
5452 {
5453 State->GeneralRegs[FAST486_REG_ESI].Long += DataSize;
5454 State->GeneralRegs[FAST486_REG_EDI].Long += DataSize;
5455 }
5456 else
5457 {
5458 State->GeneralRegs[FAST486_REG_ESI].Long -= DataSize;
5459 State->GeneralRegs[FAST486_REG_EDI].Long -= DataSize;
5460 }
5461 }
5462 else
5463 {
5464 if (!State->Flags.Df)
5465 {
5466 State->GeneralRegs[FAST486_REG_ESI].LowWord += DataSize;
5467 State->GeneralRegs[FAST486_REG_EDI].LowWord += DataSize;
5468 }
5469 else
5470 {
5471 State->GeneralRegs[FAST486_REG_ESI].LowWord -= DataSize;
5472 State->GeneralRegs[FAST486_REG_EDI].LowWord -= DataSize;
5473 }
5474 }
5475
5476 // FIXME: This method is slow!
5477 if ((State->PrefixFlags & FAST486_PREFIX_REP)
5478 || (State->PrefixFlags & FAST486_PREFIX_REPNZ))
5479 {
5481
5482 if (AddressSize)
5483 {
5484 if ((--State->GeneralRegs[FAST486_REG_ECX].Long) == 0)
5485 {
5486 /* ECX is 0 */
5487 Repeat = FALSE;
5488 }
5489 }
5490 else
5491 {
5492 if ((--State->GeneralRegs[FAST486_REG_ECX].LowWord) == 0)
5493 {
5494 /* CX is 0 */
5495 Repeat = FALSE;
5496 }
5497 }
5498
5499 if (((State->PrefixFlags & FAST486_PREFIX_REP) && !State->Flags.Zf)
5500 || ((State->PrefixFlags & FAST486_PREFIX_REPNZ) && State->Flags.Zf))
5501 {
5502 /* REPZ with ZF = 0 or REPNZ with ZF = 1 */
5503 Repeat = FALSE;
5504 }
5505
5506 if (Repeat)
5507 {
5508 /* Repeat the instruction */
5509 State->InstPtr = State->SavedInstPtr;
5510 }
5511 }
5512}
static BOOLEAN Repeat
Definition: dem.c:247
#define FAST486_PREFIX_REPNZ
Definition: fast486.h:102
#define FAST486_PREFIX_REP
Definition: fast486.h:103
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT _In_opt_ PVOID _In_ ULONG DataSize
Definition: ndis.h:4755

◆ FAST486_OPCODE_HANDLER() [26/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeCmpSubAl  )

Definition at line 3001 of file opcodes.c.

3002{
3003 UCHAR FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowByte;
3004 UCHAR SecondValue, Result;
3005
3006 /* Make sure this is the right instruction */
3007 ASSERT((Opcode & 0xEF) == 0x2C);
3008
3010
3011 if (!Fast486FetchByte(State, &SecondValue))
3012 {
3013 /* Exception occurred */
3014 return;
3015 }
3016
3017 /* Calculate the result */
3018 Result = FirstValue - SecondValue;
3019
3020 /* Update the flags */
3021 State->Flags.Cf = (FirstValue < SecondValue);
3022 State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) != (SecondValue & SIGN_FLAG_BYTE))
3023 && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
3024 State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F);
3025 State->Flags.Zf = (Result == 0);
3026 State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
3027 State->Flags.Pf = Fast486CalculateParity(Result);
3028
3029 /* Check if this is not a CMP */
3030 if (!(Opcode & 0x10))
3031 {
3032 /* Write back the result */
3033 State->GeneralRegs[FAST486_REG_EAX].LowByte = Result;
3034 }
3035}

◆ FAST486_OPCODE_HANDLER() [27/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeCmpSubByteModrm  )

Definition at line 2837 of file opcodes.c.

2838{
2839 UCHAR FirstValue, SecondValue, Result;
2840 FAST486_MOD_REG_RM ModRegRm;
2841 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
2842
2843 /* Make sure this is the right instruction */
2844 ASSERT((Opcode & 0xED) == 0x28);
2845
2846 TOGGLE_ADSIZE(AddressSize);
2847
2848 /* Get the operands */
2849 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
2850 {
2851 /* Exception occurred */
2852 return;
2853 }
2854
2855 if (!Fast486ReadModrmByteOperands(State,
2856 &ModRegRm,
2857 &FirstValue,
2858 &SecondValue))
2859 {
2860 /* Exception occurred */
2861 return;
2862 }
2863
2864 /* Check if this is the instruction that writes to R/M */
2866 {
2867 /* Swap the order */
2868 SWAP(FirstValue, SecondValue);
2869 }
2870
2871 /* Calculate the result */
2872 Result = FirstValue - SecondValue;
2873
2874 /* Update the flags */
2875 State->Flags.Cf = (FirstValue < SecondValue);
2876 State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) != (SecondValue & SIGN_FLAG_BYTE))
2877 && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
2878 State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F);
2879 State->Flags.Zf = (Result == 0);
2880 State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
2881 State->Flags.Pf = Fast486CalculateParity(Result);
2882
2883 /* Check if this is not a CMP */
2884 if (!(Opcode & 0x10))
2885 {
2886 /* Write back the result */
2887 Fast486WriteModrmByteOperands(State,
2888 &ModRegRm,
2890 Result);
2891 }
2892}
#define SWAP()
Definition: pattern.c:1185

◆ FAST486_OPCODE_HANDLER() [28/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeCmpSubEax  )

Definition at line 3037 of file opcodes.c.

3038{
3039 BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
3040
3041 /* Make sure this is the right instruction */
3042 ASSERT((Opcode & 0xEF) == 0x2D);
3043
3046
3047 if (Size)
3048 {
3049 ULONG FirstValue = State->GeneralRegs[FAST486_REG_EAX].Long;
3050 ULONG SecondValue, Result;
3051
3052 if (!Fast486FetchDword(State, &SecondValue))
3053 {
3054 /* Exception occurred */
3055 return;
3056 }
3057
3058 /* Calculate the result */
3059 Result = FirstValue - SecondValue;
3060
3061 /* Update the flags */
3062 State->Flags.Cf = (FirstValue < SecondValue);
3063 State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) != (SecondValue & SIGN_FLAG_LONG))
3064 && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
3065 State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F);
3066 State->Flags.Zf = (Result == 0);
3067 State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
3068 State->Flags.Pf = Fast486CalculateParity(Result);
3069
3070 /* Check if this is not a CMP */
3071 if (!(Opcode & 0x10))
3072 {
3073 /* Write back the result */
3074 State->GeneralRegs[FAST486_REG_EAX].Long = Result;
3075 }
3076 }
3077 else
3078 {
3079 USHORT FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowWord;
3080 USHORT SecondValue, Result;
3081
3082 if (!Fast486FetchWord(State, &SecondValue))
3083 {
3084 /* Exception occurred */
3085 return;
3086 }
3087
3088 /* Calculate the result */
3089 Result = FirstValue - SecondValue;
3090
3091 /* Update the flags */
3092 State->Flags.Cf = (FirstValue < SecondValue);
3093 State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) != (SecondValue & SIGN_FLAG_WORD))
3094 && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
3095 State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F);
3096 State->Flags.Zf = (Result == 0);
3097 State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
3098 State->Flags.Pf = Fast486CalculateParity(Result);
3099
3100 /* Check if this is not a CMP */
3101 if (!(Opcode & 0x10))
3102 {
3103 /* Write back the result */
3104 State->GeneralRegs[FAST486_REG_EAX].LowWord = Result;
3105 }
3106 }
3107}

◆ FAST486_OPCODE_HANDLER() [29/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeCmpSubModrm  )

Definition at line 2894 of file opcodes.c.

2895{
2896 FAST486_MOD_REG_RM ModRegRm;
2897 BOOLEAN OperandSize, AddressSize;
2898
2899 /* Make sure this is the right instruction */
2900 ASSERT((Opcode & 0xED) == 0x29);
2901
2902 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
2903
2904 TOGGLE_ADSIZE(AddressSize);
2905 TOGGLE_OPSIZE(OperandSize);
2906
2907 /* Get the operands */
2908 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
2909 {
2910 /* Exception occurred */
2911 return;
2912 }
2913
2914 /* Check the operand size */
2915 if (OperandSize)
2916 {
2917 ULONG FirstValue, SecondValue, Result;
2918
2919 if (!Fast486ReadModrmDwordOperands(State,
2920 &ModRegRm,
2921 &FirstValue,
2922 &SecondValue))
2923 {
2924 /* Exception occurred */
2925 return;
2926 }
2927
2928 /* Check if this is the instruction that writes to R/M */
2930 {
2931 /* Swap the order */
2932 SWAP(FirstValue, SecondValue);
2933 }
2934
2935 /* Calculate the result */
2936 Result = FirstValue - SecondValue;
2937
2938 /* Update the flags */
2939 State->Flags.Cf = (FirstValue < SecondValue);
2940 State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) != (SecondValue & SIGN_FLAG_LONG))
2941 && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
2942 State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F);
2943 State->Flags.Zf = (Result == 0);
2944 State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
2945 State->Flags.Pf = Fast486CalculateParity(Result);
2946
2947 /* Check if this is not a CMP */
2948 if (!(Opcode & 0x10))
2949 {
2950 /* Write back the result */
2951 Fast486WriteModrmDwordOperands(State,
2952 &ModRegRm,
2954 Result);
2955 }
2956 }
2957 else
2958 {
2959 USHORT FirstValue, SecondValue, Result;
2960
2961 if (!Fast486ReadModrmWordOperands(State,
2962 &ModRegRm,
2963 &FirstValue,
2964 &SecondValue))
2965 {
2966 /* Exception occurred */
2967 return;
2968 }
2969
2970 /* Check if this is the instruction that writes to R/M */
2972 {
2973 /* Swap the order */
2974 SWAP(FirstValue, SecondValue);
2975 }
2976
2977 /* Calculate the result */
2978 Result = FirstValue - SecondValue;
2979
2980 /* Update the flags */
2981 State->Flags.Cf = (FirstValue < SecondValue);
2982 State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) != (SecondValue & SIGN_FLAG_WORD))
2983 && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
2984 State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F);
2985 State->Flags.Zf = (Result == 0);
2986 State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
2987 State->Flags.Pf = Fast486CalculateParity(Result);
2988
2989 /* Check if this is not a CMP */
2990 if (!(Opcode & 0x10))
2991 {
2992 /* Write back the result */
2993 Fast486WriteModrmWordOperands(State,
2994 &ModRegRm,
2996 Result);
2997 }
2998 }
2999}

◆ FAST486_OPCODE_HANDLER() [30/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeComplCarry  )

Definition at line 655 of file opcodes.c.

656{
657 /* Make sure this is the right instruction */
658 ASSERT(Opcode == 0xF5);
659
661
662 /* Toggle CF and return success */
663 State->Flags.Cf = !State->Flags.Cf;
664 return;
665}

◆ FAST486_OPCODE_HANDLER() [31/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeCwde  )

Definition at line 3855 of file opcodes.c.

3856{
3857 BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
3858
3859 /* Make sure this is the right instruction */
3860 ASSERT(Opcode == 0x98);
3861
3864
3865 if (Size)
3866 {
3867 /* Sign extend AX to EAX */
3868 State->GeneralRegs[FAST486_REG_EAX].Long = MAKELONG
3869 (
3870 State->GeneralRegs[FAST486_REG_EAX].LowWord,
3871 (State->GeneralRegs[FAST486_REG_EAX].LowWord & SIGN_FLAG_WORD)
3872 ? 0xFFFF : 0x0000
3873 );
3874 }
3875 else
3876 {
3877 /* Sign extend AL to AX */
3878 State->GeneralRegs[FAST486_REG_EAX].HighByte =
3879 (State->GeneralRegs[FAST486_REG_EAX].LowByte & SIGN_FLAG_BYTE)
3880 ? 0xFF : 0x00;
3881 }
3882}
#define MAKELONG(a, b)
Definition: typedefs.h:249

◆ FAST486_OPCODE_HANDLER() [32/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeDaa  )

Definition at line 2796 of file opcodes.c.

2797{
2798 UCHAR Value = State->GeneralRegs[FAST486_REG_EAX].LowByte;
2799 BOOLEAN Carry = State->Flags.Cf;
2800
2801 /* Clear the carry flag */
2802 State->Flags.Cf = FALSE;
2803
2804 /* Check if the first BCD digit is invalid or there was a carry from it */
2805 if (((Value & 0x0F) > 9) || State->Flags.Af)
2806 {
2807 /* Correct it */
2808 State->GeneralRegs[FAST486_REG_EAX].LowByte += 0x06;
2809 if (State->GeneralRegs[FAST486_REG_EAX].LowByte < 0x06)
2810 {
2811 /* A carry occurred */
2812 State->Flags.Cf = TRUE;
2813 }
2814
2815 /* Set the adjust flag */
2816 State->Flags.Af = TRUE;
2817 }
2818
2819 /* Check if the second BCD digit is invalid or there was a carry from it */
2820 if ((Value > 0x99) || Carry)
2821 {
2822 /* Correct it */
2823 State->GeneralRegs[FAST486_REG_EAX].LowByte += 0x60;
2824
2825 /* There was a carry */
2826 State->Flags.Cf = TRUE;
2827 }
2828
2829 Value = State->GeneralRegs[FAST486_REG_EAX].LowByte;
2830
2831 /* Update the flags */
2832 State->Flags.Sf = (Value & SIGN_FLAG_BYTE) != 0;
2833 State->Flags.Zf = (Value == 0);
2834 State->Flags.Pf = Fast486CalculateParity(Value);
2835}

◆ FAST486_OPCODE_HANDLER() [33/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeDas  )

Definition at line 3109 of file opcodes.c.

3110{
3111 UCHAR Value = State->GeneralRegs[FAST486_REG_EAX].LowByte;
3112 BOOLEAN Carry = State->Flags.Cf;
3113
3114 /* Clear the carry flag */
3115 State->Flags.Cf = FALSE;
3116
3117 /* Check if the first BCD digit is invalid or there was a borrow */
3118 if (((Value & 0x0F) > 9) || State->Flags.Af)
3119 {
3120 /* Correct it */
3121 State->GeneralRegs[FAST486_REG_EAX].LowByte -= 0x06;
3122 if (State->GeneralRegs[FAST486_REG_EAX].LowByte > 0xFB)
3123 {
3124 /* A borrow occurred */
3125 State->Flags.Cf = TRUE;
3126 }
3127
3128 /* Set the adjust flag */
3129 State->Flags.Af = TRUE;
3130 }
3131
3132 /* Check if the second BCD digit is invalid or there was a borrow */
3133 if ((Value > 0x99) || Carry)
3134 {
3135 /* Correct it */
3136 State->GeneralRegs[FAST486_REG_EAX].LowByte -= 0x60;
3137
3138 /* There was a borrow */
3139 State->Flags.Cf = TRUE;
3140 }
3141
3142 Value = State->GeneralRegs[FAST486_REG_EAX].LowByte;
3143
3144 /* Update the flags */
3145 State->Flags.Sf = (Value & SIGN_FLAG_BYTE) != 0;
3146 State->Flags.Zf = (Value == 0);
3147 State->Flags.Pf = Fast486CalculateParity(Value);
3148}

◆ FAST486_OPCODE_HANDLER() [34/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeDecrement  )

Definition at line 442 of file opcodes.c.

443{
444 ULONG Value;
445 BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
446
449
450 /* Make sure this is the right instruction */
451 ASSERT((Opcode & 0xF8) == 0x48);
452
453 if (Size)
454 {
455 Value = --State->GeneralRegs[Opcode & 0x07].Long;
456
457 State->Flags.Of = (Value == (SIGN_FLAG_LONG - 1));
458 State->Flags.Sf = ((Value & SIGN_FLAG_LONG) != 0);
459 }
460 else
461 {
462 Value = --State->GeneralRegs[Opcode & 0x07].LowWord;
463
464 State->Flags.Of = (Value == (SIGN_FLAG_WORD - 1));
465 State->Flags.Sf = ((Value & SIGN_FLAG_WORD) != 0);
466 }
467
468 State->Flags.Zf = (Value == 0);
469 State->Flags.Af = ((Value & 0x0F) == 0x0F);
470 State->Flags.Pf = Fast486CalculateParity(LOBYTE(Value));
471}
#define LOBYTE(W)
Definition: jmemdos.c:487

◆ FAST486_OPCODE_HANDLER() [35/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeEnter  )

Definition at line 4209 of file opcodes.c.

4210{
4211 INT i;
4212 BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
4213 USHORT FrameSize;
4214 UCHAR NestingLevel;
4215 FAST486_REG FramePointer;
4216
4217 /* Make sure this is the right instruction */
4218 ASSERT(Opcode == 0xC8);
4219
4222
4223 if (!Fast486FetchWord(State, &FrameSize))
4224 {
4225 /* Exception occurred */
4226 return;
4227 }
4228
4229 if (!Fast486FetchByte(State, &NestingLevel))
4230 {
4231 /* Exception occurred */
4232 return;
4233 }
4234
4235 /* Push EBP */
4236 if (!Fast486StackPush(State, State->GeneralRegs[FAST486_REG_EBP].Long))
4237 {
4238 /* Exception occurred */
4239 return;
4240 }
4241
4242 /* Save ESP */
4243 FramePointer = State->GeneralRegs[FAST486_REG_ESP];
4244
4245 /* Set up the nested procedure stacks */
4246 for (i = 1; i < NestingLevel; i++)
4247 {
4248 if (Size)
4249 {
4250 State->GeneralRegs[FAST486_REG_EBP].Long -= 4;
4251 Fast486StackPush(State, State->GeneralRegs[FAST486_REG_EBP].Long);
4252 }
4253 else
4254 {
4255 State->GeneralRegs[FAST486_REG_EBP].LowWord -= 2;
4256 Fast486StackPush(State, State->GeneralRegs[FAST486_REG_EBP].LowWord);
4257 }
4258 }
4259
4260 if (NestingLevel > 0) Fast486StackPush(State, FramePointer.Long);
4261
4262 /* Set EBP to the frame pointer */
4263 if (Size) State->GeneralRegs[FAST486_REG_EBP].Long = FramePointer.Long;
4264 else State->GeneralRegs[FAST486_REG_EBP].LowWord = FramePointer.LowWord;
4265
4266 /* Reserve space for the frame */
4267 if (State->SegmentRegs[FAST486_REG_SS].Size)
4268 {
4269 State->GeneralRegs[FAST486_REG_ESP].Long -= (ULONG)FrameSize;
4270 }
4271 else
4272 {
4273 State->GeneralRegs[FAST486_REG_ESP].LowWord -= FrameSize;
4274 }
4275}
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
int32_t INT
Definition: typedefs.h:58

◆ FAST486_OPCODE_HANDLER() [36/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeExchangeEax  )

Definition at line 507 of file opcodes.c.

508{
509 INT Reg = Opcode & 0x07;
510 BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
511
514
515 /* Make sure this is the right instruction */
516 ASSERT((Opcode & 0xF8) == 0x90);
517
518 /* Exchange the values */
519 if (Size)
520 {
521 ULONG Value;
522
523 Value = State->GeneralRegs[Reg].Long;
524 State->GeneralRegs[Reg].Long = State->GeneralRegs[FAST486_REG_EAX].Long;
525 State->GeneralRegs[FAST486_REG_EAX].Long = Value;
526 }
527 else
528 {
530
531 Value = State->GeneralRegs[Reg].LowWord;
532 State->GeneralRegs[Reg].LowWord = State->GeneralRegs[FAST486_REG_EAX].LowWord;
533 State->GeneralRegs[FAST486_REG_EAX].LowWord = Value;
534 }
535}

◆ FAST486_OPCODE_HANDLER() [37/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeHalt  )

Definition at line 749 of file opcodes.c.

750{
751 /* Make sure this is the right instruction */
752 ASSERT(Opcode == 0xF4);
753
755
756 /* Privileged instructions can only be executed under CPL = 0 */
757 if (Fast486GetCurrentPrivLevel(State) != 0)
758 {
759 Fast486Exception(State, FAST486_EXCEPTION_GP);
760 return;
761 }
762
763 /* Halt */
764 State->Halted = TRUE;
765}

◆ FAST486_OPCODE_HANDLER() [38/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeImulModrmImm  )

Definition at line 3460 of file opcodes.c.

3461{
3462 BOOLEAN OperandSize, AddressSize;
3463 FAST486_MOD_REG_RM ModRegRm;
3464 LONG Multiplier;
3465
3466 /* Make sure this is the right instruction */
3467 ASSERT((Opcode & 0xFD) == 0x69);
3468
3469 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
3470
3471 TOGGLE_ADSIZE(AddressSize);
3472 TOGGLE_OPSIZE(OperandSize);
3473
3474 /* Fetch the parameters */
3475 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
3476 {
3477 /* Exception occurred */
3478 return;
3479 }
3480
3481 if (Opcode == 0x6B)
3482 {
3483 CHAR Byte;
3484
3485 /* Fetch the immediate operand */
3486 if (!Fast486FetchByte(State, (PUCHAR)&Byte))
3487 {
3488 /* Exception occurred */
3489 return;
3490 }
3491
3492 Multiplier = (LONG)Byte;
3493 }
3494 else
3495 {
3496 if (OperandSize)
3497 {
3498 LONG Dword;
3499
3500 /* Fetch the immediate operand */
3501 if (!Fast486FetchDword(State, (PULONG)&Dword))
3502 {
3503 /* Exception occurred */
3504 return;
3505 }
3506
3507 Multiplier = Dword;
3508 }
3509 else
3510 {
3511 SHORT Word;
3512
3513 /* Fetch the immediate operand */
3514 if (!Fast486FetchWord(State, (PUSHORT)&Word))
3515 {
3516 /* Exception occurred */
3517 return;
3518 }
3519
3520 Multiplier = (LONG)Word;
3521 }
3522 }
3523
3524 if (OperandSize)
3525 {
3526 LONG RegValue, Multiplicand;
3527 LONGLONG Product;
3528
3529 /* Read the operands */
3530 if (!Fast486ReadModrmDwordOperands(State,
3531 &ModRegRm,
3532 (PULONG)&RegValue,
3533 (PULONG)&Multiplicand))
3534 {
3535 /* Exception occurred */
3536 return;
3537 }
3538
3539 /* Multiply */
3540 Product = (LONGLONG)Multiplicand * (LONGLONG)Multiplier;
3541
3542 /* Check for carry/overflow */
3543 State->Flags.Cf = State->Flags.Of = ((Product < FAST486_LONG_MIN)
3544 || (Product > FAST486_LONG_MAX));
3545
3546 /* Write-back the result */
3547 Fast486WriteModrmDwordOperands(State,
3548 &ModRegRm,
3549 TRUE,
3550 (ULONG)((LONG)Product));
3551 }
3552 else
3553 {
3554 SHORT RegValue, Multiplicand;
3555 LONG Product;
3556
3557 /* Read the operands */
3558 if (!Fast486ReadModrmWordOperands(State,
3559 &ModRegRm,
3560 (PUSHORT)&RegValue,
3561 (PUSHORT)&Multiplicand))
3562 {
3563 /* Exception occurred */
3564 return;
3565 }
3566
3567 /* Multiply */
3568 Product = (LONG)Multiplicand * (LONG)Multiplier;
3569
3570 /* Check for carry/overflow */
3571 State->Flags.Cf = State->Flags.Of = ((Product < FAST486_SHORT_MIN)
3572 || (Product > FAST486_SHORT_MAX));
3573
3574 /* Write-back the result */
3575 Fast486WriteModrmWordOperands(State,
3576 &ModRegRm,
3577 TRUE,
3578 (USHORT)((SHORT)Product));
3579 }
3580}
unsigned char Byte
Definition: zlib.h:37
#define FAST486_SHORT_MAX
Definition: fast486.h:36
#define FAST486_LONG_MIN
Definition: fast486.h:37
#define FAST486_SHORT_MIN
Definition: fast486.h:35
#define FAST486_LONG_MAX
Definition: fast486.h:38
int64_t LONGLONG
Definition: typedefs.h:68
unsigned char * PUCHAR
Definition: typedefs.h:53
char CHAR
Definition: xmlstorage.h:175

◆ FAST486_OPCODE_HANDLER() [39/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeIn  )

Definition at line 802 of file opcodes.c.

803{
804 ULONG Port;
805 BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
806
807 /* Make sure this is the right instruction */
808 ASSERT((Opcode & 0xF7) == 0xE5);
809
812
813 if (Opcode == 0xE5)
814 {
815 UCHAR Data;
816
817 /* Fetch the parameter */
818 if (!Fast486FetchByte(State, &Data))
819 {
820 /* Exception occurred */
821 return;
822 }
823
824 /* Set the port number to the parameter */
825 Port = Data;
826 }
827 else
828 {
829 /* The port number is in DX */
830 Port = State->GeneralRegs[FAST486_REG_EDX].LowWord;
831 }
832
833 if (!Fast486IoPrivilegeCheck(State, Port)) return;
834
835 if (Size)
836 {
837 ULONG Data;
838
839 /* Read a dword from the I/O port */
840 State->IoReadCallback(State, Port, &Data, 1, sizeof(ULONG));
841
842 /* Store the value in EAX */
843 State->GeneralRegs[FAST486_REG_EAX].Long = Data;
844 }
845 else
846 {
847 USHORT Data;
848
849 /* Read a word from the I/O port */
850 State->IoReadCallback(State, Port, &Data, 1, sizeof(USHORT));
851
852 /* Store the value in AX */
853 State->GeneralRegs[FAST486_REG_EAX].LowWord = Data;
854 }
855}
CPPORT Port[4]
Definition: headless.c:35

◆ FAST486_OPCODE_HANDLER() [40/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeInByte  )

Definition at line 767 of file opcodes.c.

768{
769 UCHAR Data;
770 ULONG Port;
771
772 /* Make sure this is the right instruction */
773 ASSERT((Opcode & 0xF7) == 0xE4);
774
775 if (Opcode == 0xE4)
776 {
777 /* Fetch the parameter */
778 if (!Fast486FetchByte(State, &Data))
779 {
780 /* Exception occurred */
781 return;
782 }
783
784 /* Set the port number to the parameter */
785 Port = Data;
786 }
787 else
788 {
789 /* The port number is in DX */
790 Port = State->GeneralRegs[FAST486_REG_EDX].LowWord;
791 }
792
793 if (!Fast486IoPrivilegeCheck(State, Port)) return;
794
795 /* Read a byte from the I/O port */
796 State->IoReadCallback(State, Port, &Data, 1, sizeof(UCHAR));
797
798 /* Store the result in AL */
799 State->GeneralRegs[FAST486_REG_EAX].LowByte = Data;
800}

◆ FAST486_OPCODE_HANDLER() [41/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeIncrement  )

Definition at line 411 of file opcodes.c.

412{
413 ULONG Value;
414 BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
415
418
419 /* Make sure this is the right instruction */
420 ASSERT((Opcode & 0xF8) == 0x40);
421
422 if (Size)
423 {
424 Value = ++State->GeneralRegs[Opcode & 0x07].Long;
425
426 State->Flags.Of = (Value == SIGN_FLAG_LONG);
427 State->Flags.Sf = ((Value & SIGN_FLAG_LONG) != 0);
428 }
429 else
430 {
431 Value = ++State->GeneralRegs[Opcode & 0x07].LowWord;
432
433 State->Flags.Of = (Value == SIGN_FLAG_WORD);
434 State->Flags.Sf = ((Value & SIGN_FLAG_WORD) != 0);
435 }
436
437 State->Flags.Zf = (Value == 0);
438 State->Flags.Af = ((Value & 0x0F) == 0);
439 State->Flags.Pf = Fast486CalculateParity(LOBYTE(Value));
440}

◆ FAST486_OPCODE_HANDLER() [42/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeIns  )

Definition at line 5834 of file opcodes.c.

5835{
5837 BOOLEAN OperandSize, AddressSize;
5838
5839 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
5840
5841 /* Make sure this is the right instruction */
5842 ASSERT((Opcode & 0xFE) == 0x6C);
5843
5844 TOGGLE_OPSIZE(OperandSize);
5845 TOGGLE_ADSIZE(AddressSize);
5846
5847 if (!Fast486IoPrivilegeCheck(State, State->GeneralRegs[FAST486_REG_EDX].LowWord)) return;
5848
5849 /* Calculate the size */
5850 if (Opcode == 0x6C) DataSize = sizeof(UCHAR);
5851 else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);
5852
5853 if (State->PrefixFlags & (FAST486_PREFIX_REP | FAST486_PREFIX_REPNZ))
5854 {
5855 UCHAR Block[STRING_BLOCK_SIZE];
5856 ULONG Count = AddressSize ? State->GeneralRegs[FAST486_REG_ECX].Long
5857 : State->GeneralRegs[FAST486_REG_ECX].LowWord;
5858
5859 /* Clear the memory block */
5860 RtlZeroMemory(Block, sizeof(Block));
5861
5862 /* Transfer until finished */
5863 while (Count)
5864 {
5865 ULONG Processed = min(Count, STRING_BLOCK_SIZE / DataSize);
5866
5867 /* Simulate the 16-bit wrap-around of DI in 16-bit address mode */
5868 if (!AddressSize)
5869 {
5870 ULONG MaxBytes = State->Flags.Df
5871 ? (ULONG)State->GeneralRegs[FAST486_REG_EDI].LowWord
5872 : (0x10000 - (ULONG)State->GeneralRegs[FAST486_REG_EDI].LowWord);
5873
5874 Processed = min(Processed, MaxBytes / DataSize);
5875 if (Processed == 0) Processed = 1;
5876 }
5877
5878 /* Read from the I/O port */
5879 State->IoReadCallback(State,
5880 State->GeneralRegs[FAST486_REG_EDX].LowWord,
5881 Block,
5882 Processed,
5883 DataSize);
5884
5885 if (State->Flags.Df)
5886 {
5887 ULONG i, j;
5888
5889 /* Reduce EDI by the number of bytes to transfer */
5890 if (AddressSize) State->GeneralRegs[FAST486_REG_EDI].Long -= Processed * DataSize;
5891 else State->GeneralRegs[FAST486_REG_EDI].LowWord -= Processed * DataSize;
5892
5893 /* Reverse the block data */
5894 for (i = 0; i < Processed / 2; i++)
5895 {
5896 /* Swap the values */
5897 for (j = 0; j < DataSize; j++)
5898 {
5899 UCHAR Temp = Block[i * DataSize + j];
5900 Block[i * DataSize + j] = Block[(Processed - i - 1) * DataSize + j];
5901 Block[(Processed - i - 1) * DataSize + j] = Temp;
5902 }
5903 }
5904 }
5905
5906 /* Write to memory */
5908 FAST486_REG_ES,
5909 AddressSize ? State->GeneralRegs[FAST486_REG_EDI].Long
5910 : State->GeneralRegs[FAST486_REG_EDI].LowWord,
5911 Block,
5912 Processed * DataSize))
5913 {
5914 /* Set ECX */
5915 if (AddressSize) State->GeneralRegs[FAST486_REG_ECX].Long = Count;
5916 else State->GeneralRegs[FAST486_REG_ECX].LowWord = LOWORD(Count);
5917
5918 /* Exception occurred */
5919 return;
5920 }
5921
5922 if (!State->Flags.Df)
5923 {
5924 /* Increase EDI by the number of bytes transfered */
5925 if (AddressSize) State->GeneralRegs[FAST486_REG_EDI].Long += Processed * DataSize;
5926 else State->GeneralRegs[FAST486_REG_EDI].LowWord += Processed * DataSize;
5927 }
5928
5929 /* Reduce the total count by the number processed in this run */
5930 Count -= Processed;
5931 }
5932
5933 /* Clear ECX */
5934 if (AddressSize) State->GeneralRegs[FAST486_REG_ECX].Long = 0;
5935 else State->GeneralRegs[FAST486_REG_ECX].LowWord = 0;
5936 }
5937 else
5938 {
5939 ULONG Data = 0;
5940
5941 /* Read from the I/O port */
5942 State->IoReadCallback(State,
5943 State->GeneralRegs[FAST486_REG_EDX].LowWord,
5944 &Data,
5945 1,
5946 DataSize);
5947
5948 /* Write to the destination operand */
5950 FAST486_REG_ES,
5951 AddressSize ? State->GeneralRegs[FAST486_REG_EDI].Long
5952 : State->GeneralRegs[FAST486_REG_EDI].LowWord,
5953 &Data,
5954 DataSize))
5955 {
5956 /* Exception occurred */
5957 return;
5958 }
5959
5960 /* Increment/decrement EDI */
5961 if (AddressSize)
5962 {
5963 if (!State->Flags.Df) State->GeneralRegs[FAST486_REG_EDI].Long += DataSize;
5964 else State->GeneralRegs[FAST486_REG_EDI].Long -= DataSize;
5965 }
5966 else
5967 {
5968 if (!State->Flags.Df) State->GeneralRegs[FAST486_REG_EDI].LowWord += DataSize;
5969 else State->GeneralRegs[FAST486_REG_EDI].LowWord -= DataSize;
5970 }
5971 }
5972}
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define min(a, b)
Definition: monoChain.cc:55
int Count
Definition: noreturn.cpp:7
BOOLEAN FASTCALL Fast486WriteMemory(PFAST486_STATE State, FAST486_SEG_REGS SegmentReg, ULONG Offset, PVOID Buffer, ULONG Size)
Definition: common.c:163
#define STRING_BLOCK_SIZE
Definition: common.h:36
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262

◆ FAST486_OPCODE_HANDLER() [43/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeInt  )

Definition at line 4422 of file opcodes.c.

4423{
4424 UCHAR IntNum;
4425
4426 /* Check for V86 mode */
4427 if (State->Flags.Vm && (State->Flags.Iopl != 3))
4428 {
4429 /* Call the V86 monitor */
4430 Fast486Exception(State, FAST486_EXCEPTION_GP);
4431 return;
4432 }
4433
4434 switch (Opcode)
4435 {
4436 case 0xCC: // INT 3
4437 {
4438 /* This is the INT3 instruction */
4439 IntNum = 3;
4440 break;
4441 }
4442
4443 case 0xCD: // INT xx
4444 {
4445 /* Fetch the interrupt number */
4446 if (!Fast486FetchByte(State, &IntNum))
4447 {
4448 /* Exception occurred */
4449 return;
4450 }
4451
4452 break;
4453 }
4454
4455 case 0xCE: // INTO
4456 {
4457 /* Don't do anything if OF is cleared */
4458 if (!State->Flags.Of) return;
4459
4460 /* Exception #OF */
4461 IntNum = FAST486_EXCEPTION_OF;
4462
4463 break;
4464 }
4465
4466 default:
4467 {
4468 /* Should not happen */
4469 ASSERT(FALSE);
4470 }
4471 }
4472
4473 /* Perform the interrupt */
4475}
BOOLEAN FASTCALL Fast486PerformInterrupt(PFAST486_STATE State, UCHAR Number)
Definition: common.c:533

◆ FAST486_OPCODE_HANDLER() [44/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeInvalid  )

Definition at line 301 of file opcodes.c.

302{
303 /*
304 * This is not a valid opcode.
305 * Well, not totally: see http://www.rcollins.org/secrets/opcodes/ICEBP.html
306 * for more details.
307 */
308 DPRINT1("FAST486 -- Calling ICEBP opcode\n");
309 Fast486Exception(State, FAST486_EXCEPTION_UD);
310}
#define DPRINT1
Definition: precomp.h:8

◆ FAST486_OPCODE_HANDLER() [45/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeIret  )

Definition at line 4477 of file opcodes.c.

4478{
4479 FAST486_SEG_REGS i;
4480 ULONG InstPtr, CodeSel, StackPtr, StackSel;
4481 FAST486_FLAGS_REG NewFlags;
4482 BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
4483
4484 /* Make sure this is the right instruction */
4485 ASSERT(Opcode == 0xCF);
4486
4489
4490 /* Check if this is a nested task return */
4491 if (State->Flags.Nt && (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE))
4492 {
4493 /* Clear the NT flag of the current task */
4494 State->Flags.Nt = FALSE;
4495
4496 /* Switch to the old task */
4498 return;
4499 }
4500
4501 /* Pop EIP */
4502 if (!Fast486StackPop(State, &InstPtr))
4503 {
4504 /* Exception occurred */
4505 return;
4506 }
4507
4508 /* Pop CS */
4509 if (!Fast486StackPop(State, &CodeSel))
4510 {
4511 /* Exception occurred */
4512 return;
4513 }
4514
4515 /* Pop EFLAGS */
4516 if (!Fast486StackPop(State, &NewFlags.Long))
4517 {
4518 /* Exception occurred */
4519 return;
4520 }
4521
4522 /* Check for protected mode */
4523 if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
4524 {
4525 UINT OldCpl = Fast486GetCurrentPrivLevel(State);
4526
4527 if (State->Flags.Vm)
4528 {
4529 /* Return from VM86 mode */
4530
4531 /* Check the IOPL */
4532 if (State->Flags.Iopl == 3)
4533 {
4534 /* Set new EIP */
4535 State->InstPtr.Long = LOWORD(InstPtr);
4536
4537 /* Load new CS */
4538 if (!Fast486LoadSegment(State, FAST486_REG_CS, CodeSel))
4539 {
4540 /* Exception occurred */
4541 return;
4542 }
4543
4544 /* Set the new flags */
4545 if (Size) State->Flags.Long = NewFlags.Long & REAL_MODE_FLAGS_MASK;
4546 else State->Flags.LowWord = NewFlags.LowWord & REAL_MODE_FLAGS_MASK;
4547 State->Flags.AlwaysSet = State->Flags.Vm = TRUE;
4548 State->Flags.Iopl = 3;
4549 }
4550 else
4551 {
4552 /* Call the VM86 monitor */
4553 Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, 0);
4554 return;
4555 }
4556
4557 return;
4558 }
4559
4560 if (NewFlags.Vm)
4561 {
4562 /* Return to VM86 mode */
4563 ULONG Es, Ds, Fs, Gs;
4564
4565 /* Pop ESP, SS, ES, DS, FS, GS */
4566 if (!Fast486StackPop(State, &StackPtr)) return;
4567 if (!Fast486StackPop(State, &StackSel)) return;
4568 if (!Fast486StackPop(State, &Es)) return;
4569 if (!Fast486StackPop(State, &Ds)) return;
4570 if (!Fast486StackPop(State, &Fs)) return;
4571 if (!Fast486StackPop(State, &Gs)) return;
4572
4573 /* Set the new IP */
4574 State->InstPtr.Long = LOWORD(InstPtr);
4575
4576 /* Set the new SP */
4577 State->GeneralRegs[FAST486_REG_ESP].Long = StackPtr;
4578
4579 /* Set the new flags */
4580 if (Size) State->Flags.Long = NewFlags.Long & REAL_MODE_FLAGS_MASK;
4581 else State->Flags.LowWord = NewFlags.LowWord & REAL_MODE_FLAGS_MASK;
4582 State->Flags.AlwaysSet = State->Flags.Vm = TRUE;
4583
4584 /* Switch to CPL 3 */
4585 State->Cpl = 3;
4586
4587 /* Load the new segments */
4588 if (!Fast486LoadSegment(State, FAST486_REG_CS, CodeSel)) return;
4589 if (!Fast486LoadSegment(State, FAST486_REG_SS, StackSel)) return;
4590 if (!Fast486LoadSegment(State, FAST486_REG_ES, Es)) return;
4591 if (!Fast486LoadSegment(State, FAST486_REG_DS, Ds)) return;
4592 if (!Fast486LoadSegment(State, FAST486_REG_FS, Fs)) return;
4593 if (!Fast486LoadSegment(State, FAST486_REG_GS, Gs)) return;
4594
4595 return;
4596 }
4597
4598 if (GET_SEGMENT_RPL(CodeSel) > OldCpl)
4599 {
4600 /* Pop ESP */
4601 if (!Fast486StackPop(State, &StackPtr))
4602 {
4603 /* Exception */
4604 return;
4605 }
4606
4607 /* Pop SS */
4608 if (!Fast486StackPop(State, &StackSel))
4609 {
4610 /* Exception */
4611 return;
4612 }
4613 }
4614
4615 /* Load the new CS */
4616 if (!Fast486LoadSegment(State, FAST486_REG_CS, CodeSel))
4617 {
4618 /* Exception occurred */
4619 return;
4620 }
4621
4622 /* Set EIP */
4623 if (Size) State->InstPtr.Long = InstPtr;
4624 else State->InstPtr.LowWord = LOWORD(InstPtr);
4625
4626 /* Update the CPL */
4627 State->Cpl = GET_SEGMENT_RPL(CodeSel);
4628
4629 /* Set the new flags */
4630 if (Size)
4631 {
4632 State->Flags.Long = (State->Flags.Long & ~PROT_MODE_FLAGS_MASK)
4633 | (NewFlags.Long & PROT_MODE_FLAGS_MASK);
4634 }
4635 else
4636 {
4637 State->Flags.LowWord = (State->Flags.LowWord & ~PROT_MODE_FLAGS_MASK)
4638 | (NewFlags.LowWord & PROT_MODE_FLAGS_MASK);
4639 }
4640 State->Flags.AlwaysSet = TRUE;
4641
4642 /* Set additional flags */
4643 if (OldCpl <= State->Flags.Iopl) State->Flags.If = NewFlags.If;
4644 if (OldCpl == 0) State->Flags.Iopl = NewFlags.Iopl;
4645
4646 if (State->Cpl > OldCpl)
4647 {
4648 /* Load new SS */
4649 if (!Fast486LoadSegment(State, FAST486_REG_SS, StackSel))
4650 {
4651 /* Exception */
4652 return;
4653 }
4654
4655 /* Set ESP */
4656 if (Size) State->GeneralRegs[FAST486_REG_ESP].Long = StackPtr;
4657 else State->GeneralRegs[FAST486_REG_ESP].LowWord = LOWORD(StackPtr);
4658
4659 /* Check segment security */
4660 for (i = 0; i < FAST486_NUM_SEG_REGS; i++)
4661 {
4662 /* Don't check CS or SS */
4663 if ((i == FAST486_REG_CS) || (i == FAST486_REG_SS)) continue;
4664
4665 if ((State->Cpl > State->SegmentRegs[i].Dpl)
4666 && (!State->SegmentRegs[i].Executable
4667 || !State->SegmentRegs[i].DirConf))
4668 {
4669 /* Load the NULL descriptor in the segment */
4670 if (!Fast486LoadSegment(State, i, 0)) return;
4671 }
4672 }
4673 }
4674 }
4675 else
4676 {
4677 if (Size && (InstPtr & 0xFFFF0000))
4678 {
4679 /* Invalid */
4680 Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, 0);
4681 return;
4682 }
4683
4684 /* Set new EIP */
4685 State->InstPtr.Long = InstPtr;
4686
4687 /* Load new CS */
4688 if (!Fast486LoadSegment(State, FAST486_REG_CS, CodeSel))
4689 {
4690 /* Exception occurred */
4691 return;
4692 }
4693
4694 /* Set the new flags */
4695 if (Size) State->Flags.Long = NewFlags.Long & REAL_MODE_FLAGS_MASK;
4696 else State->Flags.LowWord = NewFlags.LowWord & REAL_MODE_FLAGS_MASK;
4697 State->Flags.AlwaysSet = TRUE;
4698 }
4699}
#define FAST486_NUM_SEG_REGS
Definition: fast486.h:41
unsigned int UINT
Definition: ndis.h:50
VOID FASTCALL Fast486ExceptionWithErrorCode(PFAST486_STATE State, FAST486_EXCEPTIONS ExceptionCode, ULONG ErrorCode)
Definition: common.c:557
BOOLEAN FASTCALL Fast486TaskSwitch(PFAST486_STATE State, FAST486_TASK_SWITCH_TYPE Type, USHORT Selector)
Definition: common.c:624
#define GET_SEGMENT_RPL(s)
Definition: common.h:38
#define PROT_MODE_FLAGS_MASK
Definition: common.h:33
@ FAST486_TASK_RETURN
Definition: common.h:89
#define REAL_MODE_FLAGS_MASK
Definition: common.h:32
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170

◆ FAST486_OPCODE_HANDLER() [46/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeJecxz  )

Definition at line 4826 of file opcodes.c.

4827{
4829 BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
4830 CHAR Offset = 0;
4831
4832 /* Make sure this is the right instruction */
4833 ASSERT(Opcode == 0xE3);
4834
4837
4838 if (Size) Condition = (State->GeneralRegs[FAST486_REG_ECX].Long == 0);
4839 else Condition = (State->GeneralRegs[FAST486_REG_ECX].LowWord == 0);
4840
4841 /* Fetch the offset */
4842 if (!Fast486FetchByte(State, (PUCHAR)&Offset))
4843 {
4844 /* An exception occurred */
4845 return;
4846 }
4847
4848 if (Condition)
4849 {
4850 /* Move the instruction pointer */
4851 if (Size) State->InstPtr.Long += Offset;
4852 else State->InstPtr.LowWord += Offset;
4853 }
4854}
IN ULONG IN UCHAR Condition

◆ FAST486_OPCODE_HANDLER() [47/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeJmp  )

Definition at line 4910 of file opcodes.c.

4911{
4912 BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
4913
4914 /* Make sure this is the right instruction */
4915 ASSERT(Opcode == 0xE9);
4916
4919
4920 if (Size)
4921 {
4922 LONG Offset = 0;
4923
4924 /* Fetch the offset */
4925 if (!Fast486FetchDword(State, (PULONG)&Offset))
4926 {
4927 /* An exception occurred */
4928 return;
4929 }
4930
4931 /* Move the instruction pointer */
4932 State->InstPtr.Long += Offset;
4933 }
4934 else
4935 {
4936 SHORT Offset = 0;
4937
4938 /* Fetch the offset */
4939 if (!Fast486FetchWord(State, (PUSHORT)&Offset))
4940 {
4941 /* An exception occurred */
4942 return;
4943 }
4944
4945 /* Move the instruction pointer */
4946 State->InstPtr.Long += Offset;
4947
4948 /* Clear the top half of EIP */
4949 State->InstPtr.Long &= 0xFFFF;
4950 }
4951}

◆ FAST486_OPCODE_HANDLER() [48/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeJmpAbs  )

Definition at line 4953 of file opcodes.c.

4954{
4955 USHORT Segment = 0;
4956 ULONG Offset = 0;
4957 BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
4958
4959 /* Make sure this is the right instruction */
4960 ASSERT(Opcode == 0xEA);
4961
4964
4965 /* Fetch the offset */
4966 if (Size)
4967 {
4968 if (!Fast486FetchDword(State, &Offset))
4969 {
4970 /* Exception occurred */
4971 return;
4972 }
4973 }
4974 else
4975 {
4976 if (!Fast486FetchWord(State, (PUSHORT)&Offset))
4977 {
4978 /* Exception occurred */
4979 return;
4980 }
4981 }
4982
4983 /* Fetch the segment */
4984 if (!Fast486FetchWord(State, &Segment))
4985 {
4986 /* Exception occurred */
4987 return;
4988 }
4989
4990 if ((State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) && !State->Flags.Vm)
4991 {
4992 if (!Fast486ProcessGate(State, Segment, Offset, FALSE))
4993 {
4994 /* Gate processed or exception occurred */
4995 return;
4996 }
4997 }
4998
4999 /* Load the new CS */
5000 if (!Fast486LoadSegment(State, FAST486_REG_CS, Segment))
5001 {
5002 /* Exception occurred */
5003 return;
5004 }
5005
5006 /* Load new EIP */
5007 State->InstPtr.Long = Offset;
5008}

◆ FAST486_OPCODE_HANDLER() [49/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeLahf  )

Definition at line 4062 of file opcodes.c.

4063{
4064 /* Make sure this is the right instruction */
4065 ASSERT(Opcode == 0x9F);
4066
4067 /* Set AH to the low-order byte of FLAGS */
4068 State->GeneralRegs[FAST486_REG_EAX].HighByte = LOBYTE(State->Flags.Long);
4069}

◆ FAST486_OPCODE_HANDLER() [50/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeLdsLes  )

Definition at line 4105 of file opcodes.c.

4106{
4107 UCHAR FarPointer[6];
4108 BOOLEAN OperandSize, AddressSize;
4109 FAST486_MOD_REG_RM ModRegRm;
4110
4111 /* Make sure this is the right instruction */
4112 ASSERT((Opcode & 0xFE) == 0xC4);
4113
4114 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
4115
4116 TOGGLE_OPSIZE(OperandSize);
4117 TOGGLE_ADSIZE(AddressSize);
4118
4119 /* Get the operands */
4120 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
4121 {
4122 /* Exception occurred */
4123 return;
4124 }
4125
4126 if (!ModRegRm.Memory)
4127 {
4128 /* Check if this is a BOP and the host supports BOPs */
4129 if ((Opcode == 0xC4)
4130 && (ModRegRm.Register == FAST486_REG_EAX)
4131 && (ModRegRm.SecondRegister == FAST486_REG_ESP)
4132 && (State->BopCallback != NULL))
4133 {
4134 UCHAR BopCode;
4135
4136 /* Fetch the BOP code */
4137 if (!Fast486FetchByte(State, &BopCode))
4138 {
4139 /* Exception occurred */
4140 return;
4141 }
4142
4143#ifndef FAST486_NO_PREFETCH
4144 /* Invalidate the prefetch since BOP handlers can alter the memory */
4145 State->PrefetchValid = FALSE;
4146#endif
4147
4148 /* Call the BOP handler */
4149 State->BopCallback(State, BopCode);
4150
4151 /*
4152 * If an interrupt should occur at this time, delay it.
4153 * We must do this because if an interrupt begins and the BOP callback
4154 * changes the CS:IP, the interrupt handler won't execute and the
4155 * stack pointer will never be restored.
4156 */
4157 State->DoNotInterrupt = TRUE;
4158
4159 return;
4160 }
4161
4162 /* Invalid */
4163 Fast486Exception(State, FAST486_EXCEPTION_UD);
4164 return;
4165 }
4166
4168 (State->PrefixFlags & FAST486_PREFIX_SEG)
4169 ? State->SegmentOverride : FAST486_REG_DS,
4170 ModRegRm.MemoryAddress,
4171 FALSE,
4172 FarPointer,
4173 OperandSize ? 6 : 4))
4174 {
4175 /* Exception occurred */
4176 return;
4177 }
4178
4179 if (OperandSize)
4180 {
4181 ULONG Offset = *((PULONG)FarPointer);
4182 USHORT Segment = *((PUSHORT)&FarPointer[sizeof(ULONG)]);
4183
4184 /* Set the register to the offset */
4185 State->GeneralRegs[ModRegRm.Register].Long = Offset;
4186
4187 /* Load the segment */
4188 Fast486LoadSegment(State,
4189 (Opcode == 0xC4)
4190 ? FAST486_REG_ES : FAST486_REG_DS,
4191 Segment);
4192 }
4193 else
4194 {
4195 USHORT Offset = *((PUSHORT)FarPointer);
4196 USHORT Segment = *((PUSHORT)&FarPointer[sizeof(USHORT)]);
4197
4198 /* Set the register to the offset */
4199 State->GeneralRegs[ModRegRm.Register].LowWord = Offset;
4200
4201 /* Load the segment */
4202 Fast486LoadSegment(State,
4203 (Opcode == 0xC4)
4204 ? FAST486_REG_ES : FAST486_REG_DS,
4205 Segment);
4206 }
4207}
#define NULL
Definition: types.h:112
FAST486_GEN_REGS SecondRegister
Definition: common.h:80
FAST486_GEN_REGS Register
Definition: common.h:76

◆ FAST486_OPCODE_HANDLER() [51/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeLea  )

Definition at line 3764 of file opcodes.c.

3765{
3766 FAST486_MOD_REG_RM ModRegRm;
3767 BOOLEAN OperandSize, AddressSize;
3768
3769 /* Make sure this is the right instruction */
3770 ASSERT(Opcode == 0x8D);
3771
3772 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
3773
3774 TOGGLE_ADSIZE(AddressSize);
3775 TOGGLE_OPSIZE(OperandSize);
3776
3777 /* Get the operands */
3778 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
3779 {
3780 /* Exception occurred */
3781 return;
3782 }
3783
3784 /* The second operand must be memory */
3785 if (!ModRegRm.Memory)
3786 {
3787 /* Invalid */
3788 Fast486Exception(State, FAST486_EXCEPTION_UD);
3789 return;
3790 }
3791
3792 /* Write the address to the register */
3793 if (OperandSize)
3794 {
3795 Fast486WriteModrmDwordOperands(State,
3796 &ModRegRm,
3797 TRUE,
3798 ModRegRm.MemoryAddress);
3799 }
3800 else
3801 {
3802 Fast486WriteModrmWordOperands(State,
3803 &ModRegRm,
3804 TRUE,
3805 ModRegRm.MemoryAddress);
3806
3807 }
3808}

◆ FAST486_OPCODE_HANDLER() [52/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeLeave  )

Definition at line 4277 of file opcodes.c.

4278{
4279 BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
4280 ULONG Value;
4281
4282 /* Make sure this is the right instruction */
4283 ASSERT(Opcode == 0xC9);
4284
4287
4288 if (State->SegmentRegs[FAST486_REG_SS].Size)
4289 {
4290 /* Set the stack pointer (ESP) to the base pointer (EBP) */
4291 State->GeneralRegs[FAST486_REG_ESP].Long = State->GeneralRegs[FAST486_REG_EBP].Long;
4292 }
4293 else
4294 {
4295 /* Set the stack pointer (SP) to the base pointer (BP) */
4296 State->GeneralRegs[FAST486_REG_ESP].LowWord = State->GeneralRegs[FAST486_REG_EBP].LowWord;
4297 }
4298
4299 /* Pop the saved base pointer from the stack */
4300 if (Fast486StackPop(State, &Value))
4301 {
4302 if (Size) State->GeneralRegs[FAST486_REG_EBP].Long = Value;
4303 else State->GeneralRegs[FAST486_REG_EBP].LowWord = LOWORD(Value);
4304 }
4305}

◆ FAST486_OPCODE_HANDLER() [53/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeLods  )

Definition at line 5647 of file opcodes.c.

5648{
5650 BOOLEAN OperandSize, AddressSize;
5651 FAST486_SEG_REGS Segment = FAST486_REG_DS;
5652
5653 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
5654
5655 /* Make sure this is the right instruction */
5656 ASSERT((Opcode & 0xFE) == 0xAC);
5657
5658 TOGGLE_OPSIZE(OperandSize);
5659 TOGGLE_ADSIZE(AddressSize);
5660
5661 if (State->PrefixFlags & FAST486_PREFIX_SEG)
5662 {
5663 /* Use the override segment instead of DS */
5664 Segment = State->SegmentOverride;
5665 }
5666
5667 /* Calculate the size */
5668 if (Opcode == 0xAC) DataSize = sizeof(UCHAR);
5669 else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);
5670
5671 if (State->PrefixFlags & (FAST486_PREFIX_REP | FAST486_PREFIX_REPNZ))
5672 {
5673 ULONG Count = AddressSize ? State->GeneralRegs[FAST486_REG_ECX].Long
5674 : State->GeneralRegs[FAST486_REG_ECX].LowWord;
5675
5676 /* If the count is 0, do nothing */
5677 if (Count == 0) return;
5678
5679 /* Only the last entry will be loaded */
5680 if (!State->Flags.Df)
5681 {
5682 if (AddressSize) State->GeneralRegs[FAST486_REG_ESI].Long += (Count - 1) * DataSize;
5683 else State->GeneralRegs[FAST486_REG_ESI].LowWord += (Count - 1) * DataSize;
5684 }
5685 else
5686 {
5687 if (AddressSize) State->GeneralRegs[FAST486_REG_ESI].Long -= (Count - 1) * DataSize;
5688 else State->GeneralRegs[FAST486_REG_ESI].LowWord -= (Count - 1) * DataSize;
5689 }
5690
5691 /* Clear ECX */
5692 if (AddressSize) State->GeneralRegs[FAST486_REG_ECX].Long = 0;
5693 else State->GeneralRegs[FAST486_REG_ECX].LowWord = 0;
5694 }
5695
5696 /* Read from the source operand */
5698 Segment,
5699 AddressSize ? State->GeneralRegs[FAST486_REG_ESI].Long
5700 : State->GeneralRegs[FAST486_REG_ESI].LowWord,
5701 FALSE,
5702 &State->GeneralRegs[FAST486_REG_EAX].Long,
5703 DataSize))
5704 {
5705 /* Exception occurred */
5706 return;
5707 }
5708
5709 /* Increment/decrement ESI */
5710 if (AddressSize)
5711 {
5712 if (!State->Flags.Df) State->GeneralRegs[FAST486_REG_ESI].Long += DataSize;
5713 else State->GeneralRegs[FAST486_REG_ESI].Long -= DataSize;
5714 }
5715 else
5716 {
5717 if (!State->Flags.Df) State->GeneralRegs[FAST486_REG_ESI].LowWord += DataSize;
5718 else State->GeneralRegs[FAST486_REG_ESI].LowWord -= DataSize;
5719 }
5720}

◆ FAST486_OPCODE_HANDLER() [54/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeLoop  )

Definition at line 4785 of file opcodes.c.

4786{
4788 BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
4789 CHAR Offset = 0;
4790
4791 /* Make sure this is the right instruction */
4792 ASSERT((Opcode >= 0xE0) && (Opcode <= 0xE2));
4793
4796
4797 if (Size) Condition = ((--State->GeneralRegs[FAST486_REG_ECX].Long) != 0);
4798 else Condition = ((--State->GeneralRegs[FAST486_REG_ECX].LowWord) != 0);
4799
4800 if (Opcode == 0xE0)
4801 {
4802 /* Additional rule for LOOPNZ */
4803 if (State->Flags.Zf) Condition = FALSE;
4804 }
4805 else if (Opcode == 0xE1)
4806 {
4807 /* Additional rule for LOOPZ */
4808 if (!State->Flags.Zf) Condition = FALSE;
4809 }
4810
4811 /* Fetch the offset */
4812 if (!Fast486FetchByte(State, (PUCHAR)&Offset))
4813 {
4814 /* An exception occurred */
4815 return;
4816 }
4817
4818 if (Condition)
4819 {
4820 /* Move the instruction pointer */
4821 if (Size) State->InstPtr.Long += Offset;
4822 else State->InstPtr.LowWord += Offset;
4823 }
4824}

◆ FAST486_OPCODE_HANDLER() [55/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeMovAlOffset  )

Definition at line 5010 of file opcodes.c.

5011{
5012 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
5013 ULONG Offset;
5014
5015 /* Make sure this is the right instruction */
5016 ASSERT(Opcode == 0xA0);
5017
5018 TOGGLE_ADSIZE(AddressSize);
5019
5020 if (AddressSize)
5021 {
5022 if (!Fast486FetchDword(State, &Offset))
5023 {
5024 /* Exception occurred */
5025 return;
5026 }
5027 }
5028 else
5029 {
5030 USHORT WordOffset;
5031
5032 if (!Fast486FetchWord(State, &WordOffset))
5033 {
5034 /* Exception occurred */
5035 return;
5036 }
5037
5038 Offset = (ULONG)WordOffset;
5039 }
5040
5041 /* Read from memory */
5043 (State->PrefixFlags & FAST486_PREFIX_SEG) ?
5044 State->SegmentOverride : FAST486_REG_DS,
5045 Offset,
5046 FALSE,
5047 &State->GeneralRegs[FAST486_REG_EAX].LowByte,
5048 sizeof(UCHAR));
5049}

◆ FAST486_OPCODE_HANDLER() [56/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeMovByteModrm  )

Definition at line 3599 of file opcodes.c.

3600{
3601 UCHAR Result;
3602 FAST486_MOD_REG_RM ModRegRm;
3603 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
3604
3605 /* Make sure this is the right instruction */
3606 ASSERT((Opcode & 0xFD) == 0x88);
3607
3608 TOGGLE_ADSIZE(AddressSize);
3609
3610 /* Get the operands */
3611 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
3612 {
3613 /* Exception occurred */
3614 return;
3615 }
3616
3618 {
3619 if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, &Result))
3620 {
3621 /* Exception occurred */
3622 return;
3623 }
3624 }
3625 else
3626 {
3627 if (!Fast486ReadModrmByteOperands(State, &ModRegRm, &Result, NULL))
3628 {
3629 /* Exception occurred */
3630 return;
3631 }
3632 }
3633
3634 /* Write back the result */
3635 Fast486WriteModrmByteOperands(State,
3636 &ModRegRm,
3638 Result);
3639}

◆ FAST486_OPCODE_HANDLER() [57/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeMovByteRegImm  )

Definition at line 1010 of file opcodes.c.

1011{
1012 UCHAR Value;
1013
1014 /* Make sure this is the right instruction */
1015 ASSERT((Opcode & 0xF8) == 0xB0);
1016
1018
1019 /* Fetch the byte */
1020 if (!Fast486FetchByte(State, &Value))
1021 {
1022 /* Exception occurred */
1023 return;
1024 }
1025
1026 if (Opcode & 0x04)
1027 {
1028 /* AH, CH, DH or BH */
1029 State->GeneralRegs[Opcode & 0x03].HighByte = Value;
1030 }
1031 else
1032 {
1033 /* AL, CL, DL or BL */
1034 State->GeneralRegs[Opcode & 0x03].LowByte = Value;
1035 }
1036}

◆ FAST486_OPCODE_HANDLER() [58/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeMovEaxOffset  )

Definition at line 5051 of file opcodes.c.

5052{
5053 BOOLEAN OperandSize, AddressSize;
5054
5055 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
5056
5057 /* Make sure this is the right instruction */
5058 ASSERT(Opcode == 0xA1);
5059
5060 TOGGLE_OPSIZE(OperandSize);
5061 TOGGLE_ADSIZE(AddressSize);
5062
5063 if (AddressSize)
5064 {
5065 ULONG Offset;
5066
5067 if (!Fast486FetchDword(State, &Offset))
5068 {
5069 /* Exception occurred */
5070 return;
5071 }
5072
5073 /* Read from memory */
5074 if (OperandSize)
5075 {
5077 (State->PrefixFlags & FAST486_PREFIX_SEG) ?
5078 State->SegmentOverride : FAST486_REG_DS,
5079 Offset,
5080 FALSE,
5081 &State->GeneralRegs[FAST486_REG_EAX].Long,
5082 sizeof(ULONG));
5083 }
5084 else
5085 {
5087 (State->PrefixFlags & FAST486_PREFIX_SEG) ?
5088 State->SegmentOverride : FAST486_REG_DS,
5089 Offset,
5090 FALSE,
5091 &State->GeneralRegs[FAST486_REG_EAX].LowWord,
5092 sizeof(USHORT));
5093 }
5094 }
5095 else
5096 {
5097 USHORT Offset;
5098
5099 if (!Fast486FetchWord(State, &Offset))
5100 {
5101 /* Exception occurred */
5102 return;
5103 }
5104
5105 /* Read from memory */
5106 if (OperandSize)
5107 {
5109 (State->PrefixFlags & FAST486_PREFIX_SEG) ?
5110 State->SegmentOverride : FAST486_REG_DS,
5111 Offset,
5112 FALSE,
5113 &State->GeneralRegs[FAST486_REG_EAX].Long,
5114 sizeof(ULONG));
5115 }
5116 else
5117 {
5119 (State->PrefixFlags & FAST486_PREFIX_SEG) ?
5120 State->SegmentOverride : FAST486_REG_DS,
5121 Offset,
5122 FALSE,
5123 &State->GeneralRegs[FAST486_REG_EAX].LowWord,
5124 sizeof(USHORT));
5125 }
5126 }
5127}

◆ FAST486_OPCODE_HANDLER() [59/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeMovLoadSeg  )

Definition at line 3810 of file opcodes.c.

3811{
3812 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
3813 FAST486_MOD_REG_RM ModRegRm;
3814 USHORT Selector;
3815
3816 /* Make sure this is the right instruction */
3817 ASSERT(Opcode == 0x8E);
3818
3819 TOGGLE_ADSIZE(AddressSize);
3820
3821 /* Get the operands */
3822 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
3823 {
3824 /* Exception occurred */
3825 return;
3826 }
3827
3828 if ((ModRegRm.Register >= FAST486_NUM_SEG_REGS)
3829 || ((FAST486_SEG_REGS)ModRegRm.Register == FAST486_REG_CS))
3830 {
3831 /* Invalid */
3832 Fast486Exception(State, FAST486_EXCEPTION_UD);
3833 return;
3834 }
3835
3836 if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Selector))
3837 {
3838 /* Exception occurred */
3839 return;
3840 }
3841
3842 if (!Fast486LoadSegment(State, ModRegRm.Register, Selector))
3843 {
3844 /* Exception occurred */
3845 return;
3846 }
3847
3848 if ((INT)ModRegRm.Register == FAST486_REG_SS)
3849 {
3850 /* Inhibit all interrupts until the next instruction */
3851 State->DoNotInterrupt = TRUE;
3852 }
3853}

◆ FAST486_OPCODE_HANDLER() [60/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeMovModrm  )

Definition at line 3641 of file opcodes.c.

3642{
3643 FAST486_MOD_REG_RM ModRegRm;
3644 BOOLEAN OperandSize, AddressSize;
3645
3646 /* Make sure this is the right instruction */
3647 ASSERT((Opcode & 0xFD) == 0x89);
3648
3649 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
3650
3651 TOGGLE_ADSIZE(AddressSize);
3652 TOGGLE_OPSIZE(OperandSize);
3653
3654 /* Get the operands */
3655 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
3656 {
3657 /* Exception occurred */
3658 return;
3659 }
3660
3661 /* Check the operand size */
3662 if (OperandSize)
3663 {
3664 ULONG Result;
3665
3666
3667
3669 {
3670 if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Result))
3671 {
3672 /* Exception occurred */
3673 return;
3674 }
3675 }
3676 else
3677 {
3678 if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, &Result, NULL))
3679 {
3680 /* Exception occurred */
3681 return;
3682 }
3683 }
3684
3685 /* Write back the result */
3686 Fast486WriteModrmDwordOperands(State,
3687 &ModRegRm,
3689 Result);
3690 }
3691 else
3692 {
3693 USHORT Result;
3694
3696 {
3697 if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Result))
3698 {
3699 /* Exception occurred */
3700 return;
3701 }
3702 }
3703 else
3704 {
3705 if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Result, NULL))
3706 {
3707 /* Exception occurred */
3708 return;
3709 }
3710 }
3711
3712 /* Write back the result */
3713 Fast486WriteModrmWordOperands(State,
3714 &ModRegRm,
3716 Result);
3717 }
3718}

◆ FAST486_OPCODE_HANDLER() [61/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeMovOffsetAl  )

Definition at line 5129 of file opcodes.c.

5130{
5131 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
5132 ULONG Offset;
5133
5134 /* Make sure this is the right instruction */
5135 ASSERT(Opcode == 0xA2);
5136
5137 TOGGLE_ADSIZE(AddressSize);
5138
5139 if (AddressSize)
5140 {
5141 if (!Fast486FetchDword(State, &Offset))
5142 {
5143 /* Exception occurred */
5144 return;
5145 }
5146 }
5147 else
5148 {
5149 USHORT WordOffset;
5150
5151 if (!Fast486FetchWord(State, &WordOffset))
5152 {
5153 /* Exception occurred */
5154 return;
5155 }
5156
5157 Offset = (ULONG)WordOffset;
5158 }
5159
5160 /* Write to memory */
5162 (State->PrefixFlags & FAST486_PREFIX_SEG) ?
5163 State->SegmentOverride : FAST486_REG_DS,
5164 Offset,
5165 &State->GeneralRegs[FAST486_REG_EAX].LowByte,
5166 sizeof(UCHAR));
5167}

◆ FAST486_OPCODE_HANDLER() [62/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeMovOffsetEax  )

Definition at line 5169 of file opcodes.c.

5170{
5171 BOOLEAN OperandSize, AddressSize;
5172
5173 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
5174
5175 /* Make sure this is the right instruction */
5176 ASSERT(Opcode == 0xA3);
5177
5178 TOGGLE_OPSIZE(OperandSize);
5179 TOGGLE_ADSIZE(AddressSize);
5180
5181 if (AddressSize)
5182 {
5183 ULONG Offset;
5184
5185 if (!Fast486FetchDword(State, &Offset))
5186 {
5187 /* Exception occurred */
5188 return;
5189 }
5190
5191 /* Write to memory */
5192 if (OperandSize)
5193 {
5195 (State->PrefixFlags & FAST486_PREFIX_SEG) ?
5196 State->SegmentOverride : FAST486_REG_DS,
5197 Offset,
5198 &State->GeneralRegs[FAST486_REG_EAX].Long,
5199 sizeof(ULONG));
5200 }
5201 else
5202 {
5204 (State->PrefixFlags & FAST486_PREFIX_SEG) ?
5205 State->SegmentOverride : FAST486_REG_DS,
5206 Offset,
5207 &State->GeneralRegs[FAST486_REG_EAX].LowWord,
5208 sizeof(USHORT));
5209 }
5210 }
5211 else
5212 {
5213 USHORT Offset;
5214
5215 if (!Fast486FetchWord(State, &Offset))
5216 {
5217 /* Exception occurred */
5218 return;
5219 }
5220
5221 /* Write to memory */
5222 if (OperandSize)
5223 {
5225 (State->PrefixFlags & FAST486_PREFIX_SEG) ?
5226 State->SegmentOverride : FAST486_REG_DS,
5227 Offset,
5228 &State->GeneralRegs[FAST486_REG_EAX].Long,
5229 sizeof(ULONG));
5230 }
5231 else
5232 {
5234 (State->PrefixFlags & FAST486_PREFIX_SEG) ?
5235 State->SegmentOverride : FAST486_REG_DS,
5236 Offset,
5237 &State->GeneralRegs[FAST486_REG_EAX].LowWord,
5238 sizeof(USHORT));
5239 }
5240 }
5241}

◆ FAST486_OPCODE_HANDLER() [63/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeMovRegImm  )

Definition at line 970 of file opcodes.c.

971{
972 BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
973
974 /* Make sure this is the right instruction */
975 ASSERT((Opcode & 0xF8) == 0xB8);
976
979
980 if (Size)
981 {
982 ULONG Value;
983
984 /* Fetch the dword */
985 if (!Fast486FetchDword(State, &Value))
986 {
987 /* Exception occurred */
988 return;
989 }
990
991 /* Store the value in the register */
992 State->GeneralRegs[Opcode & 0x07].Long = Value;
993 }
994 else
995 {
997
998 /* Fetch the word */
999 if (!Fast486FetchWord(State, &Value))
1000 {
1001 /* Exception occurred */
1002 return;
1003 }
1004
1005 /* Store the value in the register */
1006 State->GeneralRegs[Opcode & 0x07].LowWord = Value;
1007 }
1008}

◆ FAST486_OPCODE_HANDLER() [64/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeMovs  )

Definition at line 5259 of file opcodes.c.

5260{
5262 BOOLEAN OperandSize, AddressSize;
5263 FAST486_SEG_REGS Segment = FAST486_REG_DS;
5264
5265 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
5266
5267 /* Make sure this is the right instruction */
5268 ASSERT((Opcode & 0xFE) == 0xA4);
5269
5270 TOGGLE_OPSIZE(OperandSize);
5271 TOGGLE_ADSIZE(AddressSize);
5272
5273 if (State->PrefixFlags & FAST486_PREFIX_SEG)
5274 {
5275 /* Use the override segment instead of DS */
5276 Segment = State->SegmentOverride;
5277 }
5278
5279 if (State->PrefixFlags & (FAST486_PREFIX_REP | FAST486_PREFIX_REPNZ))
5280 {
5281 if ((AddressSize && (State->GeneralRegs[FAST486_REG_ECX].Long == 0))
5282 || (!AddressSize && (State->GeneralRegs[FAST486_REG_ECX].LowWord == 0)))
5283 {
5284 /* Do nothing */
5285 return;
5286 }
5287 }
5288
5289 /* Calculate the size */
5290 if (Opcode == 0xA4) DataSize = sizeof(UCHAR);
5291 else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);
5292
5293 /* Read from the source operand */
5295 Segment,
5296 AddressSize ? State->GeneralRegs[FAST486_REG_ESI].Long
5297 : State->GeneralRegs[FAST486_REG_ESI].LowWord,
5298 FALSE,
5299 &Data,
5300 DataSize))
5301 {
5302 /* Exception occurred */
5303 return;
5304 }
5305
5306 /* Write to the destination operand */
5308 FAST486_REG_ES,
5309 AddressSize ? State->GeneralRegs[FAST486_REG_EDI].Long
5310 : State->GeneralRegs[FAST486_REG_EDI].LowWord,
5311 &Data,
5312 DataSize))
5313 {
5314 /* Exception occurred */
5315 return;
5316 }
5317
5318 /* Increment/decrement ESI and EDI */
5319 if (AddressSize)
5320 {
5321 if (!State->Flags.Df)
5322 {
5323 State->GeneralRegs[FAST486_REG_ESI].Long += DataSize;
5324 State->GeneralRegs[FAST486_REG_EDI].Long += DataSize;
5325 }
5326 else
5327 {
5328 State->GeneralRegs[FAST486_REG_ESI].Long -= DataSize;
5329 State->GeneralRegs[FAST486_REG_EDI].Long -= DataSize;
5330 }
5331 }
5332 else
5333 {
5334 if (!State->Flags.Df)
5335 {
5336 State->GeneralRegs[FAST486_REG_ESI].LowWord += DataSize;
5337 State->GeneralRegs[FAST486_REG_EDI].LowWord += DataSize;
5338 }
5339 else
5340 {
5341 State->GeneralRegs[FAST486_REG_ESI].LowWord -= DataSize;
5342 State->GeneralRegs[FAST486_REG_EDI].LowWord -= DataSize;
5343 }
5344 }
5345
5346 // FIXME: This method is slow!
5347 if (State->PrefixFlags & (FAST486_PREFIX_REP | FAST486_PREFIX_REPNZ))
5348 {
5349 if (AddressSize)
5350 {
5351 if (--State->GeneralRegs[FAST486_REG_ECX].Long)
5352 {
5353 /* Repeat the instruction */
5354 State->InstPtr = State->SavedInstPtr;
5355 }
5356 }
5357 else
5358 {
5359 if (--State->GeneralRegs[FAST486_REG_ECX].LowWord)
5360 {
5361 /* Repeat the instruction */
5362 State->InstPtr = State->SavedInstPtr;
5363 }
5364 }
5365 }
5366}

◆ FAST486_OPCODE_HANDLER() [65/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeMovStoreSeg  )

Definition at line 3720 of file opcodes.c.

3721{
3722 BOOLEAN OperandSize, AddressSize;
3723 FAST486_MOD_REG_RM ModRegRm;
3724
3725 /* Make sure this is the right instruction */
3726 ASSERT(Opcode == 0x8C);
3727
3728 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
3729
3730 TOGGLE_ADSIZE(AddressSize);
3731 TOGGLE_OPSIZE(OperandSize);
3732
3733 /* Get the operands */
3734 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
3735 {
3736 /* Exception occurred */
3737 return;
3738 }
3739
3740 if (ModRegRm.Register >= FAST486_NUM_SEG_REGS)
3741 {
3742 /* Invalid */
3743 Fast486Exception(State, FAST486_EXCEPTION_UD);
3744 return;
3745 }
3746
3747 /* When the other operand is a memory location, always use 16-bit */
3748 if (OperandSize && !ModRegRm.Memory)
3749 {
3750 Fast486WriteModrmDwordOperands(State,
3751 &ModRegRm,
3752 FALSE,
3753 State->SegmentRegs[ModRegRm.Register].Selector);
3754 }
3755 else
3756 {
3757 Fast486WriteModrmWordOperands(State,
3758 &ModRegRm,
3759 FALSE,
3760 State->SegmentRegs[ModRegRm.Register].Selector);
3761 }
3762}

◆ FAST486_OPCODE_HANDLER() [66/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeNop  )

Definition at line 503 of file opcodes.c.

504{
505}

◆ FAST486_OPCODE_HANDLER() [67/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeOrAl  )

Definition at line 1390 of file opcodes.c.

1391{
1392 UCHAR FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowByte;
1393 UCHAR SecondValue, Result;
1394
1395 /* Make sure this is the right instruction */
1396 ASSERT(Opcode == 0x0C);
1397
1399
1400 if (!Fast486FetchByte(State, &SecondValue))
1401 {
1402 /* Exception occurred */
1403 return;
1404 }
1405
1406 /* Calculate the result */
1407 Result = FirstValue | SecondValue;
1408
1409 /* Update the flags */
1410 State->Flags.Cf = FALSE;
1411 State->Flags.Of = FALSE;
1412 State->Flags.Zf = (Result == 0);
1413 State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
1414 State->Flags.Pf = Fast486CalculateParity(Result);
1415
1416 /* Write back the result */
1417 State->GeneralRegs[FAST486_REG_EAX].LowByte = Result;
1418}

◆ FAST486_OPCODE_HANDLER() [68/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeOrByteModrm  )

Definition at line 1265 of file opcodes.c.

1266{
1267 UCHAR FirstValue, SecondValue, Result;
1268 FAST486_MOD_REG_RM ModRegRm;
1269 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
1270
1271 /* Make sure this is the right instruction */
1272 ASSERT((Opcode & 0xFD) == 0x08);
1273
1274 TOGGLE_ADSIZE(AddressSize);
1275
1276 /* Get the operands */
1277 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
1278 {
1279 /* Exception occurred */
1280 return;
1281 }
1282
1283 if (!Fast486ReadModrmByteOperands(State,
1284 &ModRegRm,
1285 &FirstValue,
1286 &SecondValue))
1287 {
1288 /* Exception occurred */
1289 return;
1290 }
1291
1292 /* Calculate the result */
1293 Result = FirstValue | SecondValue;
1294
1295 /* Update the flags */
1296 State->Flags.Cf = FALSE;
1297 State->Flags.Of = FALSE;
1298 State->Flags.Zf = (Result == 0);
1299 State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
1300 State->Flags.Pf = Fast486CalculateParity(Result);
1301
1302 /* Write back the result */
1303 Fast486WriteModrmByteOperands(State,
1304 &ModRegRm,
1306 Result);
1307}

◆ FAST486_OPCODE_HANDLER() [69/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeOrEax  )

Definition at line 1420 of file opcodes.c.

1421{
1422 BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
1423
1424 /* Make sure this is the right instruction */
1425 ASSERT(Opcode == 0x0D);
1426
1429
1430 if (Size)
1431 {
1432 ULONG FirstValue = State->GeneralRegs[FAST486_REG_EAX].Long;
1433 ULONG SecondValue, Result;
1434
1435 if (!Fast486FetchDword(State, &SecondValue))
1436 {
1437 /* Exception occurred */
1438 return;
1439 }
1440
1441 /* Calculate the result */
1442 Result = FirstValue | SecondValue;
1443
1444 /* Update the flags */
1445 State->Flags.Cf = FALSE;
1446 State->Flags.Of = FALSE;
1447 State->Flags.Zf = (Result == 0);
1448 State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
1449 State->Flags.Pf = Fast486CalculateParity(Result);
1450
1451 /* Write back the result */
1452 State->GeneralRegs[FAST486_REG_EAX].Long = Result;
1453 }
1454 else
1455 {
1456 USHORT FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowWord;
1457 USHORT SecondValue, Result;
1458
1459 if (!Fast486FetchWord(State, &SecondValue))
1460 {
1461 /* Exception occurred */
1462 return;
1463 }
1464
1465 /* Calculate the result */
1466 Result = FirstValue | SecondValue;
1467
1468 /* Update the flags */
1469 State->Flags.Cf = FALSE;
1470 State->Flags.Of = FALSE;
1471 State->Flags.Zf = (Result == 0);
1472 State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
1473 State->Flags.Pf = Fast486CalculateParity(Result);
1474
1475 /* Write back the result */
1476 State->GeneralRegs[FAST486_REG_EAX].LowWord = Result;
1477 }
1478}

◆ FAST486_OPCODE_HANDLER() [70/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeOrModrm  )

Definition at line 1309 of file opcodes.c.

1310{
1311 FAST486_MOD_REG_RM ModRegRm;
1312 BOOLEAN OperandSize, AddressSize;
1313
1314 /* Make sure this is the right instruction */
1315 ASSERT((Opcode & 0xFD) == 0x09);
1316
1317 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
1318
1319 TOGGLE_ADSIZE(AddressSize);
1320 TOGGLE_OPSIZE(OperandSize);
1321
1322 /* Get the operands */
1323 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
1324 {
1325 /* Exception occurred */
1326 return;
1327 }
1328
1329 /* Check the operand size */
1330 if (OperandSize)
1331 {
1332 ULONG FirstValue, SecondValue, Result;
1333
1334 if (!Fast486ReadModrmDwordOperands(State,
1335 &ModRegRm,
1336 &FirstValue,
1337 &SecondValue))
1338 {
1339 /* Exception occurred */
1340 return;
1341 }
1342
1343 /* Calculate the result */
1344 Result = FirstValue | SecondValue;
1345
1346 /* Update the flags */
1347 State->Flags.Cf = FALSE;
1348 State->Flags.Of = FALSE;
1349 State->Flags.Zf = (Result == 0);
1350 State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
1351 State->Flags.Pf = Fast486CalculateParity(Result);
1352
1353 /* Write back the result */
1354 Fast486WriteModrmDwordOperands(State,
1355 &ModRegRm,
1357 Result);
1358 }
1359 else
1360 {
1361 USHORT FirstValue, SecondValue, Result;
1362
1363 if (!Fast486ReadModrmWordOperands(State,
1364 &ModRegRm,
1365 &FirstValue,
1366 &SecondValue))
1367 {
1368 /* Exception occurred */
1369 return;
1370 }
1371
1372 /* Calculate the result */
1373 Result = FirstValue | SecondValue;
1374
1375 /* Update the flags */
1376 State->Flags.Cf = FALSE;
1377 State->Flags.Of = FALSE;
1378 State->Flags.Zf = (Result == 0);
1379 State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
1380 State->Flags.Pf = Fast486CalculateParity(Result);
1381
1382 /* Write back the result */
1383 Fast486WriteModrmWordOperands(State,
1384 &ModRegRm,
1386 Result);
1387 }
1388}

◆ FAST486_OPCODE_HANDLER() [71/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeOut  )

Definition at line 892 of file opcodes.c.

893{
894 ULONG Port;
895 BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
896
897 /* Make sure this is the right instruction */
898 ASSERT((Opcode & 0xF7) == 0xE7);
899
902
903 if (Opcode == 0xE7)
904 {
905 UCHAR Data;
906
907 /* Fetch the parameter */
908 if (!Fast486FetchByte(State, &Data))
909 {
910 /* Exception occurred */
911 return;
912 }
913
914 /* Set the port number to the parameter */
915 Port = Data;
916 }
917 else
918 {
919 /* The port number is in DX */
920 Port = State->GeneralRegs[FAST486_REG_EDX].LowWord;
921 }
922
923 if (!Fast486IoPrivilegeCheck(State, Port)) return;
924
925 if (Size)
926 {
927 /* Get the value from EAX */
928 ULONG Data = State->GeneralRegs[FAST486_REG_EAX].Long;
929
930 /* Write a dword to the I/O port */
931 State->IoWriteCallback(State, Port, &Data, 1, sizeof(ULONG));
932 }
933 else
934 {
935 /* Get the value from AX */
936 USHORT Data = State->GeneralRegs[FAST486_REG_EAX].LowWord;
937
938 /* Write a word to the I/O port */
939 State->IoWriteCallback(State, Port, &Data, 1, sizeof(USHORT));
940 }
941}

◆ FAST486_OPCODE_HANDLER() [72/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeOutByte  )

Definition at line 857 of file opcodes.c.

858{
859 UCHAR Data;
860 ULONG Port;
861
862 /* Make sure this is the right instruction */
863 ASSERT((Opcode & 0xF7) == 0xE6);
864
865 if (Opcode == 0xE6)
866 {
867 /* Fetch the parameter */
868 if (!Fast486FetchByte(State, &Data))
869 {
870 /* Exception occurred */
871 return;
872 }
873
874 /* Set the port number to the parameter */
875 Port = Data;
876 }
877 else
878 {
879 /* The port number is in DX */
880 Port = State->GeneralRegs[FAST486_REG_EDX].LowWord;
881 }
882
883 if (!Fast486IoPrivilegeCheck(State, Port)) return;
884
885 /* Read the value from AL */
886 Data = State->GeneralRegs[FAST486_REG_EAX].LowByte;
887
888 /* Write the byte to the I/O port */
889 State->IoWriteCallback(State, Port, &Data, 1, sizeof(UCHAR));
890}

◆ FAST486_OPCODE_HANDLER() [73/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeOuts  )

Definition at line 5974 of file opcodes.c.

5975{
5977 BOOLEAN OperandSize, AddressSize;
5978
5979 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
5980
5981 /* Make sure this is the right instruction */
5982 ASSERT((Opcode & 0xFE) == 0x6E);
5983
5984 TOGGLE_OPSIZE(OperandSize);
5985 TOGGLE_ADSIZE(AddressSize);
5986
5987 if (!Fast486IoPrivilegeCheck(State, State->GeneralRegs[FAST486_REG_EDX].LowWord)) return;
5988
5989 /* Calculate the size */
5990 if (Opcode == 0x6E) DataSize = sizeof(UCHAR);
5991 else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);
5992
5993 if (State->PrefixFlags & (FAST486_PREFIX_REP | FAST486_PREFIX_REPNZ))
5994 {
5995 UCHAR Block[STRING_BLOCK_SIZE];
5996 ULONG Count = AddressSize ? State->GeneralRegs[FAST486_REG_ECX].Long
5997 : State->GeneralRegs[FAST486_REG_ECX].LowWord;
5998
5999 /* Clear the memory block */
6000 RtlZeroMemory(Block, sizeof(Block));
6001
6002 /* Transfer until finished */
6003 while (Count)
6004 {
6005 ULONG Processed = min(Count, STRING_BLOCK_SIZE / DataSize);
6006
6007 /* Simulate the 16-bit wrap-around of DI in 16-bit address mode */
6008 if (!AddressSize)
6009 {
6010 ULONG MaxBytes = State->Flags.Df
6011 ? (ULONG)State->GeneralRegs[FAST486_REG_ESI].LowWord
6012 : (0x10000 - (ULONG)State->GeneralRegs[FAST486_REG_ESI].LowWord);
6013
6014 Processed = min(Processed, MaxBytes / DataSize);
6015 if (Processed == 0) Processed = 1;
6016 }
6017
6018 /* Read from memory */
6020 (State->PrefixFlags & FAST486_PREFIX_SEG)
6021 ? State->SegmentOverride : FAST486_REG_DS,
6022 AddressSize ? State->GeneralRegs[FAST486_REG_ESI].Long
6023 : State->GeneralRegs[FAST486_REG_ESI].LowWord,
6024 FALSE,
6025 Block,
6026 Processed * DataSize))
6027 {
6028 /* Set ECX */
6029 if (AddressSize) State->GeneralRegs[FAST486_REG_ECX].Long = Count;
6030 else State->GeneralRegs[FAST486_REG_ECX].LowWord = LOWORD(Count);
6031
6032 /* Exception occurred */
6033 return;
6034 }
6035
6036 if (State->Flags.Df)
6037 {
6038 ULONG i, j;
6039
6040 /* Reduce ESI by the number of bytes to transfer */
6041 if (AddressSize) State->GeneralRegs[FAST486_REG_ESI].Long -= Processed * DataSize;
6042 else State->GeneralRegs[FAST486_REG_ESI].LowWord -= Processed * DataSize;
6043
6044 /* Reverse the block data */
6045 for (i = 0; i < Processed / 2; i++)
6046 {
6047 /* Swap the values */
6048 for (j = 0; j < DataSize; j++)
6049 {
6050 UCHAR Temp = Block[i * DataSize + j];
6051 Block[i * DataSize + j] = Block[(Processed - i - 1) * DataSize + j];
6052 Block[(Processed - i - 1) * DataSize + j] = Temp;
6053 }
6054 }
6055 }
6056
6057 /* Write to the I/O port */
6058 State->IoWriteCallback(State,
6059 State->GeneralRegs[FAST486_REG_EDX].LowWord,
6060 Block,
6061 Processed,
6062 DataSize);
6063
6064 if (!State->Flags.Df)
6065 {
6066 /* Increase ESI by the number of bytes transfered */
6067 if (AddressSize) State->GeneralRegs[FAST486_REG_ESI].Long += Processed * DataSize;
6068 else State->GeneralRegs[FAST486_REG_ESI].LowWord += Processed * DataSize;
6069 }
6070
6071 /* Reduce the total count by the number processed in this run */
6072 Count -= Processed;
6073 }
6074
6075 /* Clear ECX */
6076 if (AddressSize) State->GeneralRegs[FAST486_REG_ECX].Long = 0;
6077 else State->GeneralRegs[FAST486_REG_ECX].LowWord = 0;
6078 }
6079 else
6080 {
6081 ULONG Data = 0;
6082
6083 /* Read from the source operand */
6085 (State->PrefixFlags & FAST486_PREFIX_SEG)
6086 ? State->SegmentOverride : FAST486_REG_DS,
6087 AddressSize ? State->GeneralRegs[FAST486_REG_ESI].Long
6088 : State->GeneralRegs[FAST486_REG_ESI].LowWord,
6089 FALSE,
6090 &Data,
6091 DataSize))
6092 {
6093 /* Exception occurred */
6094 return;
6095 }
6096
6097 /* Write to the I/O port */
6098 State->IoWriteCallback(State,
6099 State->GeneralRegs[FAST486_REG_EDX].LowWord,
6100 &Data,
6101 1,
6102 DataSize);
6103
6104 /* Increment/decrement ESI */
6105 if (AddressSize)
6106 {
6107 if (!State->Flags.Df) State->GeneralRegs[FAST486_REG_ESI].Long += DataSize;
6108 else State->GeneralRegs[FAST486_REG_ESI].Long -= DataSize;
6109 }
6110 else
6111 {
6112 if (!State->Flags.Df) State->GeneralRegs[FAST486_REG_ESI].LowWord += DataSize;
6113 else State->GeneralRegs[FAST486_REG_ESI].LowWord -= DataSize;
6114 }
6115 }
6116}

◆ FAST486_OPCODE_HANDLER() [74/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodePopAll  )

Definition at line 3241 of file opcodes.c.

3242{
3243 INT i;
3244 BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
3245 ULONG Value;
3246
3247 /* Make sure this is the right instruction */
3248 ASSERT(Opcode == 0x61);
3249
3252
3253 /* Pop all the registers in reverse order */
3254 for (i = FAST486_NUM_GEN_REGS - 1; i >= 0; i--)
3255 {
3256 /* Pop the value */
3257 if (!Fast486StackPop(State, &Value))
3258 {
3259 /* Exception occurred */
3260 return;
3261 }
3262
3263 /* Don't modify ESP */
3264 if (i != FAST486_REG_ESP)
3265 {
3266 if (Size) State->GeneralRegs[i].Long = Value;
3267 else State->GeneralRegs[i].LowWord = LOWORD(Value);
3268 }
3269 }
3270}
#define FAST486_NUM_GEN_REGS
Definition: fast486.h:40

◆ FAST486_OPCODE_HANDLER() [75/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodePopDs  )

Definition at line 2782 of file opcodes.c.

2783{
2784 ULONG NewSelector;
2785
2786 if (!Fast486StackPop(State, &NewSelector))
2787 {
2788 /* Exception occurred */
2789 return;
2790 }
2791
2792 /* Call the internal API */
2793 Fast486LoadSegment(State, FAST486_REG_DS, LOWORD(NewSelector));
2794}

◆ FAST486_OPCODE_HANDLER() [76/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodePopEs  )

Definition at line 2228 of file opcodes.c.

2229{
2230 ULONG NewSelector;
2231
2232 if (!Fast486StackPop(State, &NewSelector))
2233 {
2234 /* Exception occurred */
2235 return;
2236 }
2237
2238 /* Call the internal API */
2239 Fast486LoadSegment(State, FAST486_REG_ES, LOWORD(NewSelector));
2240}

◆ FAST486_OPCODE_HANDLER() [77/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodePopFlags  )

Definition at line 4009 of file opcodes.c.

4010{
4011 BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
4012 UINT Cpl = Fast486GetCurrentPrivLevel(State);
4013 FAST486_FLAGS_REG NewFlags;
4014
4017
4018 /* Pop the new flags */
4019 if (!Fast486StackPop(State, &NewFlags.Long))
4020 {
4021 /* Exception occurred */
4022 return;
4023 }
4024
4025 /* Check for VM86 mode when IOPL is not 3 */
4026 if (State->Flags.Vm && (State->Flags.Iopl != 3))
4027 {
4028 /* Call the VM86 monitor */
4029 Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, 0);
4030 return;
4031 }
4032
4033 State->Flags.Cf = NewFlags.Cf;
4034 State->Flags.Pf = NewFlags.Pf;
4035 State->Flags.Af = NewFlags.Af;
4036 State->Flags.Zf = NewFlags.Zf;
4037 State->Flags.Sf = NewFlags.Sf;
4038 State->Flags.Tf = NewFlags.Tf;
4039 State->Flags.Df = NewFlags.Df;
4040 State->Flags.Of = NewFlags.Of;
4041 State->Flags.Nt = NewFlags.Nt;
4042 State->Flags.Ac = NewFlags.Ac;
4043
4044 if (Cpl == 0) State->Flags.Iopl = NewFlags.Iopl;
4045 if (Cpl <= State->Flags.Iopl) State->Flags.If = NewFlags.If;
4046}

◆ FAST486_OPCODE_HANDLER() [78/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodePopReg  )

Definition at line 484 of file opcodes.c.

485{
486 ULONG Value;
487 BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
488
491
492 /* Make sure this is the right instruction */
493 ASSERT((Opcode & 0xF8) == 0x58);
494
495 /* Call the internal function */
496 if (!Fast486StackPop(State, &Value)) return;
497
498 /* Store the value */
499 if (Size) State->GeneralRegs[Opcode & 0x07].Long = Value;
500 else State->GeneralRegs[Opcode & 0x07].LowWord = Value;
501}

◆ FAST486_OPCODE_HANDLER() [79/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodePopSs  )

Definition at line 2506 of file opcodes.c.

2507{
2508 ULONG NewSelector;
2509
2510 if (!Fast486StackPop(State, &NewSelector))
2511 {
2512 /* Exception occurred */
2513 return;
2514 }
2515
2516 /* Call the internal API */
2517 if (Fast486LoadSegment(State, FAST486_REG_SS, LOWORD(NewSelector)))
2518 {
2519 /* Inhibit all interrupts until the next instruction */
2520 State->DoNotInterrupt = TRUE;
2521 }
2522}

◆ FAST486_OPCODE_HANDLER() [80/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodePrefix  )

Definition at line 312 of file opcodes.c.

313{
314 switch (Opcode)
315 {
316 /* ES: */
317 case 0x26:
318 {
319 State->PrefixFlags |= FAST486_PREFIX_SEG;
320 State->SegmentOverride = FAST486_REG_ES;
321 break;
322 }
323
324 /* CS: */
325 case 0x2E:
326 {
327 State->PrefixFlags |= FAST486_PREFIX_SEG;
328 State->SegmentOverride = FAST486_REG_CS;
329 break;
330 }
331
332 /* SS: */
333 case 0x36:
334 {
335 State->PrefixFlags |= FAST486_PREFIX_SEG;
336 State->SegmentOverride = FAST486_REG_SS;
337 break;
338 }
339
340 /* DS: */
341 case 0x3E:
342 {
343 State->PrefixFlags |= FAST486_PREFIX_SEG;
344 State->SegmentOverride = FAST486_REG_DS;
345 break;
346 }
347
348 /* FS: */
349 case 0x64:
350 {
351 State->PrefixFlags |= FAST486_PREFIX_SEG;
352 State->SegmentOverride = FAST486_REG_FS;
353 break;
354 }
355
356 /* GS: */
357 case 0x65:
358 {
359 State->PrefixFlags |= FAST486_PREFIX_SEG;
360 State->SegmentOverride = FAST486_REG_GS;
361 break;
362 }
363
364 /* OPSIZE */
365 case 0x66:
366 {
367 State->PrefixFlags |= FAST486_PREFIX_OPSIZE;
368 break;
369 }
370
371 /* ADSIZE */
372 case 0x67:
373 {
374 State->PrefixFlags |= FAST486_PREFIX_ADSIZE;
375 break;
376 }
377
378 /* LOCK */
379 case 0xF0:
380 {
381 State->PrefixFlags |= FAST486_PREFIX_LOCK;
382 break;
383 }
384
385 /* REPNZ */
386 case 0xF2:
387 {
388 /* Mutually exclusive with REP */
389 State->PrefixFlags |= FAST486_PREFIX_REPNZ;
390 State->PrefixFlags &= ~FAST486_PREFIX_REP;
391 break;
392 }
393
394 /* REP / REPZ */
395 case 0xF3:
396 {
397 /* Mutually exclusive with REPNZ */
398 State->PrefixFlags |= FAST486_PREFIX_REP;
399 State->PrefixFlags &= ~FAST486_PREFIX_REPNZ;
400 break;
401 }
402
403 default:
404 {
405 /* Shouldn't happen */
406 ASSERT(FALSE);
407 }
408 }
409}
#define FAST486_PREFIX_OPSIZE
Definition: fast486.h:99
#define FAST486_PREFIX_ADSIZE
Definition: fast486.h:100

◆ FAST486_OPCODE_HANDLER() [81/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodePushAll  )

Definition at line 3204 of file opcodes.c.

3205{
3206 INT i;
3207 BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
3208 FAST486_REG SavedEsp = State->GeneralRegs[FAST486_REG_ESP];
3209
3210 /* Make sure this is the right instruction */
3211 ASSERT(Opcode == 0x60);
3212
3215
3216 /* Push all the registers in order */
3217 for (i = 0; i < FAST486_NUM_GEN_REGS; i++)
3218 {
3219 if (i == FAST486_REG_ESP)
3220 {
3221 /* Use the saved ESP instead */
3222 if (!Fast486StackPush(State, Size ? SavedEsp.Long : SavedEsp.LowWord))
3223 {
3224 /* Exception occurred */
3225 return;
3226 }
3227 }
3228 else
3229 {
3230 /* Push the register */
3231 if (!Fast486StackPush(State, Size ? State->GeneralRegs[i].Long
3232 : State->GeneralRegs[i].LowWord))
3233 {
3234 /* Exception occurred */
3235 return;
3236 }
3237 }
3238 }
3239}

◆ FAST486_OPCODE_HANDLER() [82/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodePushByteImm  )

Definition at line 3582 of file opcodes.c.

3583{
3584 CHAR Data;
3585
3586 /* Make sure this is the right instruction */
3587 ASSERT(Opcode == 0x6A);
3588
3589 if (!Fast486FetchByte(State, (PUCHAR)&Data))
3590 {
3591 /* Exception occurred */
3592 return;
3593 }
3594
3595 /* Call the internal API */
3596 Fast486StackPush(State, Data);
3597}

◆ FAST486_OPCODE_HANDLER() [83/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodePushCs  )

Definition at line 2242 of file opcodes.c.

2243{
2244 /* Call the internal API */
2245 Fast486StackPush(State, State->SegmentRegs[FAST486_REG_CS].Selector);
2246}

◆ FAST486_OPCODE_HANDLER() [84/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodePushDs  )

Definition at line 2776 of file opcodes.c.

2777{
2778 /* Call the internal API */
2779 Fast486StackPush(State, State->SegmentRegs[FAST486_REG_DS].Selector);
2780}

◆ FAST486_OPCODE_HANDLER() [85/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodePushEs  )

Definition at line 2222 of file opcodes.c.

2223{
2224 /* Call the internal API */
2225 Fast486StackPush(State, State->SegmentRegs[FAST486_REG_ES].Selector);
2226}

◆ FAST486_OPCODE_HANDLER() [86/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodePushFlags  )

Definition at line 3989 of file opcodes.c.

3990{
3991 BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
3992
3995
3996 /* Check for VM86 mode when IOPL is not 3 */
3997 if (State->Flags.Vm && (State->Flags.Iopl != 3))
3998 {
3999 /* Call the VM86 monitor */
4000 Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, 0);
4001 return;
4002 }
4003
4004 /* Push the flags */
4005 if (Size) Fast486StackPush(State, State->Flags.Long);
4006 else Fast486StackPush(State, LOWORD(State->Flags.Long));
4007}

◆ FAST486_OPCODE_HANDLER() [87/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodePushImm  )

Definition at line 3422 of file opcodes.c.

3423{
3424 BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
3425
3426 /* Make sure this is the right instruction */
3427 ASSERT(Opcode == 0x68);
3428
3431
3432 if (Size)
3433 {
3434 ULONG Data;
3435
3436 if (!Fast486FetchDword(State, &Data))
3437 {
3438 /* Exception occurred */
3439 return;
3440 }
3441
3442 /* Call the internal API */
3443 Fast486StackPush(State, Data);
3444 }
3445 else
3446 {
3447 SHORT Data;
3448
3449 if (!Fast486FetchWord(State, (PUSHORT)&Data))
3450 {
3451 /* Exception occurred */
3452 return;
3453 }
3454
3455 /* Call the internal API */
3456 Fast486StackPush(State, Data);
3457 }
3458}

◆ FAST486_OPCODE_HANDLER() [88/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodePushReg  )

Definition at line 473 of file opcodes.c.

474{
476
477 /* Make sure this is the right instruction */
478 ASSERT((Opcode & 0xF8) == 0x50);
479
480 /* Call the internal function */
481 Fast486StackPush(State, State->GeneralRegs[Opcode & 0x07].Long);
482}

◆ FAST486_OPCODE_HANDLER() [89/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodePushSs  )

Definition at line 2500 of file opcodes.c.

2501{
2502 /* Call the internal API */
2503 Fast486StackPush(State, State->SegmentRegs[FAST486_REG_SS].Selector);
2504}

◆ FAST486_OPCODE_HANDLER() [90/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeRet  )

Definition at line 4071 of file opcodes.c.

4072{
4073 ULONG ReturnAddress;
4074 USHORT BytesToPop = 0;
4075 BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
4076
4077 /* Make sure this is the right instruction */
4078 ASSERT((Opcode & 0xFE) == 0xC2);
4079
4082
4083 if (Opcode == 0xC2)
4084 {
4085 /* Fetch the number of bytes to pop after the return */
4086 if (!Fast486FetchWord(State, &BytesToPop)) return;
4087 }
4088
4089 /* Pop the return address */
4090 if (!Fast486StackPop(State, &ReturnAddress)) return;
4091
4092 /* Return to the calling procedure, and if necessary, pop the parameters */
4093 if (Size)
4094 {
4095 State->InstPtr.Long = ReturnAddress;
4096 State->GeneralRegs[FAST486_REG_ESP].Long += BytesToPop;
4097 }
4098 else
4099 {
4100 State->InstPtr.LowWord = LOWORD(ReturnAddress);
4101 State->GeneralRegs[FAST486_REG_ESP].LowWord += BytesToPop;
4102 }
4103}

◆ FAST486_OPCODE_HANDLER() [91/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeRetFar  )

Definition at line 4307 of file opcodes.c.

4308{
4309 ULONG Segment = 0;
4310 ULONG Offset = 0;
4311 USHORT BytesToPop = 0;
4312 BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
4313 ULONG StackPtr;
4314 ULONG StackSel;
4315 UCHAR OldCpl = Fast486GetCurrentPrivLevel(State);
4316
4317 /* Make sure this is the right instruction */
4318 ASSERT((Opcode & 0xFE) == 0xCA);
4319
4322
4323 if (Opcode == 0xCA)
4324 {
4325 /* Fetch the number of bytes to pop after the return */
4326 if (!Fast486FetchWord(State, &BytesToPop)) return;
4327 }
4328
4329 /* Pop the offset */
4330 if (!Fast486StackPop(State, &Offset))
4331 {
4332 /* Exception occurred */
4333 return;
4334 }
4335
4336 /* Pop the segment */
4337 if (!Fast486StackPop(State, &Segment))
4338 {
4339 /* Exception occurred */
4340 return;
4341 }
4342
4343 /* Pop the parameters */
4344 if (State->SegmentRegs[FAST486_REG_SS].Size)
4345 {
4346 State->GeneralRegs[FAST486_REG_ESP].Long += BytesToPop;
4347 }
4348 else
4349 {
4350 State->GeneralRegs[FAST486_REG_ESP].LowWord += BytesToPop;
4351 }
4352
4353 if ((State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) && !State->Flags.Vm)
4354 {
4355 if (GET_SEGMENT_RPL(Segment) > OldCpl)
4356 {
4357 /* Pop ESP */
4358 if (!Fast486StackPop(State, &StackPtr))
4359 {
4360 /* Exception */
4361 return;
4362 }
4363
4364 /* Pop SS */
4365 if (!Fast486StackPop(State, &StackSel))
4366 {
4367 /* Exception */
4368 return;
4369 }
4370 }
4371 }
4372
4373 /* Load the new CS */
4374 if (!Fast486LoadSegment(State, FAST486_REG_CS, Segment))
4375 {
4376 /* Exception occurred */
4377 return;
4378 }
4379
4380 /* Load new (E)IP */
4381 if (Size) State->InstPtr.Long = Offset;
4382 else State->InstPtr.LowWord = LOWORD(Offset);
4383
4384 if ((State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) && !State->Flags.Vm)
4385 {
4386 UINT i;
4387
4388 /* Update the CPL */
4390
4391 if (State->Cpl > OldCpl)
4392 {
4393 /* Load new SS */
4394 if (!Fast486LoadSegment(State, FAST486_REG_SS, StackSel))
4395 {
4396 /* Exception */
4397 return;
4398 }
4399
4400 /* Set ESP */
4401 if (Size) State->GeneralRegs[FAST486_REG_ESP].Long = StackPtr;
4402 else State->GeneralRegs[FAST486_REG_ESP].LowWord = LOWORD(StackPtr);
4403
4404 /* Check segment security */
4405 for (i = 0; i < FAST486_NUM_SEG_REGS; i++)
4406 {
4407 /* Don't check CS or SS */
4408 if ((i == FAST486_REG_CS) || (i == FAST486_REG_SS)) continue;
4409
4410 if ((State->Cpl > State->SegmentRegs[i].Dpl)
4411 && (!State->SegmentRegs[i].Executable
4412 || !State->SegmentRegs[i].DirConf))
4413 {
4414 /* Load the NULL descriptor in the segment */
4415 if (!Fast486LoadSegment(State, i, 0)) return;
4416 }
4417 }
4418 }
4419 }
4420}

◆ FAST486_OPCODE_HANDLER() [92/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeSahf  )

Definition at line 4048 of file opcodes.c.

4049{
4050 /* Make sure this is the right instruction */
4051 ASSERT(Opcode == 0x9E);
4052
4053 /* Set the low-order byte of FLAGS to AH */
4054 State->Flags.Long &= 0xFFFFFF00;
4055 State->Flags.Long |= State->GeneralRegs[FAST486_REG_EAX].HighByte;
4056
4057 /* Restore the reserved bits of FLAGS */
4058 State->Flags.AlwaysSet = TRUE;
4059 State->Flags.Reserved0 = State->Flags.Reserved1 = FALSE;
4060}

◆ FAST486_OPCODE_HANDLER() [93/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeSalc  )

Definition at line 5243 of file opcodes.c.

5244{
5245 /*
5246 * See: http://www.rcollins.org/secrets/opcodes/SALC.html
5247 * for more information.
5248 */
5249
5250 /* Make sure this is the right instruction */
5251 ASSERT(Opcode == 0xD6);
5252
5254
5255 /* Set all the bits of AL to CF */
5256 State->GeneralRegs[FAST486_REG_EAX].LowByte = State->Flags.Cf ? 0xFF : 0x00;
5257}

◆ FAST486_OPCODE_HANDLER() [94/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeSbbAl  )

Definition at line 2678 of file opcodes.c.

2679{
2680 UCHAR FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowByte;
2681 UCHAR SecondValue, Result;
2682 INT Carry = State->Flags.Cf ? 1 : 0;
2683
2684 /* Make sure this is the right instruction */
2685 ASSERT(Opcode == 0x1C);
2686
2688
2689 if (!Fast486FetchByte(State, &SecondValue))
2690 {
2691 /* Exception occurred */
2692 return;
2693 }
2694
2695 /* Calculate the result */
2696 Result = FirstValue - SecondValue - Carry;
2697
2698 /* Update the flags */
2699 State->Flags.Cf = Carry ? (FirstValue <= SecondValue) : (FirstValue < SecondValue);
2700 State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) != (SecondValue & SIGN_FLAG_BYTE))
2701 && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
2702 State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
2703 State->Flags.Zf = (Result == 0);
2704 State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
2705 State->Flags.Pf = Fast486CalculateParity(Result);
2706
2707 /* Write back the result */
2708 State->GeneralRegs[FAST486_REG_EAX].LowByte = Result;
2709}

◆ FAST486_OPCODE_HANDLER() [95/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeSbbByteModrm  )

Definition at line 2524 of file opcodes.c.

2525{
2526 UCHAR FirstValue, SecondValue, Result;
2527 FAST486_MOD_REG_RM ModRegRm;
2528 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
2529 INT Carry = State->Flags.Cf ? 1 : 0;
2530
2531 /* Make sure this is the right instruction */
2532 ASSERT((Opcode & 0xFD) == 0x18);
2533
2534 TOGGLE_ADSIZE(AddressSize);
2535
2536 /* Get the operands */
2537 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
2538 {
2539 /* Exception occurred */
2540 return;
2541 }
2542
2543 if (!Fast486ReadModrmByteOperands(State,
2544 &ModRegRm,
2545 &FirstValue,
2546 &SecondValue))
2547 {
2548 /* Exception occurred */
2549 return;
2550 }
2551
2552 /* Check if this is the instruction that writes to R/M */
2554 {
2555 /* Swap the order */
2556 SWAP(FirstValue, SecondValue);
2557 }
2558
2559 /* Calculate the result */
2560 Result = FirstValue - SecondValue - Carry;
2561
2562 /* Update the flags */
2563 State->Flags.Cf = Carry ? (FirstValue <= SecondValue) : (FirstValue < SecondValue);
2564 State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) != (SecondValue & SIGN_FLAG_BYTE))
2565 && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
2566 State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
2567 State->Flags.Zf = (Result == 0);
2568 State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
2569 State->Flags.Pf = Fast486CalculateParity(Result);
2570
2571 /* Write back the result */
2572 Fast486WriteModrmByteOperands(State,
2573 &ModRegRm,
2575 Result);
2576}

◆ FAST486_OPCODE_HANDLER() [96/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeSbbEax  )

Definition at line 2711 of file opcodes.c.

2712{
2713 BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
2714 INT Carry = State->Flags.Cf ? 1 : 0;
2715
2716 /* Make sure this is the right instruction */
2717 ASSERT(Opcode == 0x1D);
2718
2721
2722 if (Size)
2723 {
2724 ULONG FirstValue = State->GeneralRegs[FAST486_REG_EAX].Long;
2725 ULONG SecondValue, Result;
2726
2727 if (!Fast486FetchDword(State, &SecondValue))
2728 {
2729 /* Exception occurred */
2730 return;
2731 }
2732
2733 /* Calculate the result */
2734 Result = FirstValue - SecondValue - Carry;
2735
2736 /* Update the flags */
2737 State->Flags.Cf = Carry ? (FirstValue <= SecondValue) : (FirstValue < SecondValue);
2738 State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) != (SecondValue & SIGN_FLAG_LONG))
2739 && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
2740 State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
2741 State->Flags.Zf = (Result == 0);
2742 State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
2743 State->Flags.Pf = Fast486CalculateParity(Result);
2744
2745 /* Write back the result */
2746 State->GeneralRegs[FAST486_REG_EAX].Long = Result;
2747 }
2748 else
2749 {
2750 USHORT FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowWord;
2751 USHORT SecondValue, Result;
2752
2753 if (!Fast486FetchWord(State, &SecondValue))
2754 {
2755 /* Exception occurred */
2756 return;
2757 }
2758
2759 /* Calculate the result */
2760 Result = FirstValue - SecondValue - Carry;
2761
2762 /* Update the flags */
2763 State->Flags.Cf = Carry ? (FirstValue <= SecondValue) : (FirstValue < SecondValue);
2764 State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) != (SecondValue & SIGN_FLAG_WORD))
2765 && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
2766 State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
2767 State->Flags.Zf = (Result == 0);
2768 State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
2769 State->Flags.Pf = Fast486CalculateParity(Result);
2770
2771 /* Write back the result */
2772 State->GeneralRegs[FAST486_REG_EAX].LowWord = Result;
2773 }
2774}

◆ FAST486_OPCODE_HANDLER() [97/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeSbbModrm  )

Definition at line 2578 of file opcodes.c.

2579{
2580 FAST486_MOD_REG_RM ModRegRm;
2581 BOOLEAN OperandSize, AddressSize;
2582 INT Carry = State->Flags.Cf ? 1 : 0;
2583
2584 /* Make sure this is the right instruction */
2585 ASSERT((Opcode & 0xFD) == 0x19);
2586
2587 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
2588
2589 TOGGLE_ADSIZE(AddressSize);
2590 TOGGLE_OPSIZE(OperandSize);
2591
2592 /* Get the operands */
2593 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
2594 {
2595 /* Exception occurred */
2596 return;
2597 }
2598
2599 /* Check the operand size */
2600 if (OperandSize)
2601 {
2602 ULONG FirstValue, SecondValue, Result;
2603
2604 if (!Fast486ReadModrmDwordOperands(State,
2605 &ModRegRm,
2606 &FirstValue,
2607 &SecondValue))
2608 {
2609 /* Exception occurred */
2610 return;
2611 }
2612
2613 /* Check if this is the instruction that writes to R/M */
2615 {
2616 /* Swap the order */
2617 SWAP(FirstValue, SecondValue);
2618 }
2619
2620 /* Calculate the result */
2621 Result = FirstValue - SecondValue - Carry;
2622
2623 /* Update the flags */
2624 State->Flags.Cf = Carry ? (FirstValue <= SecondValue) : (FirstValue < SecondValue);
2625 State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) != (SecondValue & SIGN_FLAG_LONG))
2626 && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
2627 State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
2628 State->Flags.Zf = (Result == 0);
2629 State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
2630 State->Flags.Pf = Fast486CalculateParity(Result);
2631
2632 /* Write back the result */
2633 Fast486WriteModrmDwordOperands(State,
2634 &ModRegRm,
2636 Result);
2637 }
2638 else
2639 {
2640 USHORT FirstValue, SecondValue, Result;
2641
2642 if (!Fast486ReadModrmWordOperands(State,
2643 &ModRegRm,
2644 &FirstValue,
2645 &SecondValue))
2646 {
2647 /* Exception occurred */
2648 return;
2649 }
2650
2651 /* Check if this is the instruction that writes to R/M */
2653 {
2654 /* Swap the order */
2655 SWAP(FirstValue, SecondValue);
2656 }
2657
2658 /* Calculate the result */
2659 Result = FirstValue - SecondValue - Carry;
2660
2661 /* Update the flags */
2662 State->Flags.Cf = Carry ? (FirstValue <= SecondValue) : (FirstValue < SecondValue);
2663 State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) != (SecondValue & SIGN_FLAG_WORD))
2664 && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
2665 State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
2666 State->Flags.Zf = (Result == 0);
2667 State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
2668 State->Flags.Pf = Fast486CalculateParity(Result);
2669
2670 /* Write back the result */
2671 Fast486WriteModrmWordOperands(State,
2672 &ModRegRm,
2674 Result);
2675 }
2676}

◆ FAST486_OPCODE_HANDLER() [98/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeScas  )

Definition at line 5722 of file opcodes.c.

5723{
5724 ULONG FirstValue = State->GeneralRegs[FAST486_REG_EAX].Long;
5725 ULONG SecondValue = 0;
5726 ULONG Result;
5727 ULONG DataSize, DataMask, SignFlag;
5728 BOOLEAN OperandSize, AddressSize;
5729
5730 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
5731
5732 /* Make sure this is the right instruction */
5733 ASSERT((Opcode & 0xFE) == 0xAE);
5734
5735 TOGGLE_OPSIZE(OperandSize);
5736 TOGGLE_ADSIZE(AddressSize);
5737
5738 if ((State->PrefixFlags & FAST486_PREFIX_REP)
5739 || (State->PrefixFlags & FAST486_PREFIX_REPNZ))
5740 {
5741 if ((AddressSize && (State->GeneralRegs[FAST486_REG_ECX].Long == 0))
5742 || (!AddressSize && (State->GeneralRegs[FAST486_REG_ECX].LowWord == 0)))
5743 {
5744 /* Do nothing */
5745 return;
5746 }
5747 }
5748
5749 /* Calculate the size */
5750 if (Opcode == 0xAE) DataSize = sizeof(UCHAR);
5751 else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);
5752
5753 /* Calculate the mask and sign flag */
5754 SignFlag = 1 << ((DataSize * 8) - 1);
5755 DataMask = SignFlag | (SignFlag - 1);
5756
5757 /* Read from the source operand */
5759 FAST486_REG_ES,
5760 AddressSize ? State->GeneralRegs[FAST486_REG_EDI].Long
5761 : State->GeneralRegs[FAST486_REG_EDI].LowWord,
5762 FALSE,
5763 &SecondValue,
5764 DataSize))
5765 {
5766 /* Exception occurred */
5767 return;
5768 }
5769
5770 /* Calculate the result */
5771 FirstValue &= DataMask;
5772 SecondValue &= DataMask;
5773 Result = (FirstValue - SecondValue) & DataMask;
5774
5775 /* Update the flags */
5776 State->Flags.Cf = (FirstValue < SecondValue);
5777 State->Flags.Of = ((FirstValue & SignFlag) != (SecondValue & SignFlag))
5778 && ((FirstValue & SignFlag) != (Result & SignFlag));
5779 State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F);
5780 State->Flags.Zf = (Result == 0);
5781 State->Flags.Sf = ((Result & SignFlag) != 0);
5782 State->Flags.Pf = Fast486CalculateParity(Result);
5783
5784 /* Increment/decrement EDI */
5785 if (AddressSize)
5786 {
5787 if (!State->Flags.Df) State->GeneralRegs[FAST486_REG_EDI].Long += DataSize;
5788 else State->GeneralRegs[FAST486_REG_EDI].Long -= DataSize;
5789 }
5790 else
5791 {
5792 if (!State->Flags.Df) State->GeneralRegs[FAST486_REG_EDI].LowWord += DataSize;
5793 else State->GeneralRegs[FAST486_REG_EDI].LowWord -= DataSize;
5794 }
5795
5796 // FIXME: This method is slow!
5797 if ((State->PrefixFlags & FAST486_PREFIX_REP)
5798 || (State->PrefixFlags & FAST486_PREFIX_REPNZ))
5799 {
5801
5802 if (AddressSize)
5803 {
5804 if ((--State->GeneralRegs[FAST486_REG_ECX].Long) == 0)
5805 {
5806 /* ECX is 0 */
5807 Repeat = FALSE;
5808 }
5809 }
5810 else
5811 {
5812 if ((--State->GeneralRegs[FAST486_REG_ECX].LowWord) == 0)
5813 {
5814 /* CX is 0 */
5815 Repeat = FALSE;
5816 }
5817 }
5818
5819 if (((State->PrefixFlags & FAST486_PREFIX_REP) && !State->Flags.Zf)
5820 || ((State->PrefixFlags & FAST486_PREFIX_REPNZ) && State->Flags.Zf))
5821 {
5822 /* REPZ with ZF = 0 or REPNZ with ZF = 1 */
5823 Repeat = FALSE;
5824 }
5825
5826 if (Repeat)
5827 {
5828 /* Repeat the instruction */
5829 State->InstPtr = State->SavedInstPtr;
5830 }
5831 }
5832}

◆ FAST486_OPCODE_HANDLER() [99/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeSetCarry  )

Definition at line 644 of file opcodes.c.

645{
646 /* Make sure this is the right instruction */
647 ASSERT(Opcode == 0xF9);
648
650
651 /* Set CF and return success*/
652 State->Flags.Cf = TRUE;
653}

◆ FAST486_OPCODE_HANDLER() [100/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeSetDir  )

Definition at line 738 of file opcodes.c.

739{
740 /* Make sure this is the right instruction */
741 ASSERT(Opcode == 0xFD);
742
744
745 /* Set DF */
746 State->Flags.Df = TRUE;
747}

◆ FAST486_OPCODE_HANDLER() [101/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeSetInt  )

Definition at line 697 of file opcodes.c.

698{
699 /* Make sure this is the right instruction */
700 ASSERT(Opcode == 0xFB);
701
703
704 /* Check for protected mode */
705 if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
706 {
707 /* Check IOPL */
708 if (State->Flags.Iopl >= Fast486GetCurrentPrivLevel(State))
709 {
710 /* Set the interrupt flag */
711 State->Flags.If = TRUE;
712 }
713 else
714 {
715 /* General Protection Fault */
716 Fast486Exception(State, FAST486_EXCEPTION_GP);
717 return;
718 }
719 }
720 else
721 {
722 /* Just set the interrupt flag */
723 State->Flags.If = TRUE;
724 }
725}

◆ FAST486_OPCODE_HANDLER() [102/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeShortConditionalJmp  )

Definition at line 537 of file opcodes.c.

538{
539 BOOLEAN Jump = FALSE;
540 CHAR Offset = 0;
541 BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
542
543 /* Make sure this is the right instruction */
544 ASSERT((Opcode & 0xF0) == 0x70);
545
547
548 /* Fetch the offset */
549 if (!Fast486FetchByte(State, (PUCHAR)&Offset))
550 {
551 /* An exception occurred */
552 return;
553 }
554
555 switch ((Opcode & 0x0F) >> 1)
556 {
557 /* JO / JNO */
558 case 0:
559 {
560 Jump = State->Flags.Of;
561 break;
562 }
563
564 /* JC / JNC */
565 case 1:
566 {
567 Jump = State->Flags.Cf;
568 break;
569 }
570
571 /* JZ / JNZ */
572 case 2:
573 {
574 Jump = State->Flags.Zf;
575 break;
576 }
577
578 /* JBE / JNBE */
579 case 3:
580 {
581 Jump = State->Flags.Cf || State->Flags.Zf;
582 break;
583 }
584
585 /* JS / JNS */
586 case 4:
587 {
588 Jump = State->Flags.Sf;
589 break;
590 }
591
592 /* JP / JNP */
593 case 5:
594 {
595 Jump = State->Flags.Pf;
596 break;
597 }
598
599 /* JL / JNL */
600 case 6:
601 {
602 Jump = State->Flags.Sf != State->Flags.Of;
603 break;
604 }
605
606 /* JLE / JNLE */
607 case 7:
608 {
609 Jump = (State->Flags.Sf != State->Flags.Of) || State->Flags.Zf;
610 break;
611 }
612 }
613
614 if (Opcode & 1)
615 {
616 /* Invert the result */
617 Jump = !Jump;
618 }
619
620 if (Jump)
621 {
622 /* Move the instruction pointer */
623 State->InstPtr.Long += Offset;
624
625 if (!Size)
626 {
627 /* Clear the top half of EIP */
628 State->InstPtr.Long &= 0xFFFF;
629 }
630 }
631}

◆ FAST486_OPCODE_HANDLER() [103/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeShortJump  )

Definition at line 943 of file opcodes.c.

944{
945 CHAR Offset = 0;
946 BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
947
949
950 /* Make sure this is the right instruction */
951 ASSERT(Opcode == 0xEB);
952
953 /* Fetch the offset */
954 if (!Fast486FetchByte(State, (PUCHAR)&Offset))
955 {
956 /* An exception occurred */
957 return;
958 }
959
960 /* Move the instruction pointer */
961 State->InstPtr.Long += Offset;
962
963 if (!Size)
964 {
965 /* Clear the top half of EIP */
966 State->InstPtr.Long &= 0xFFFF;
967 }
968}

◆ FAST486_OPCODE_HANDLER() [104/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeStos  )

Definition at line 5514 of file opcodes.c.

5515{
5517 BOOLEAN OperandSize, AddressSize;
5518
5519 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
5520
5521 /* Make sure this is the right instruction */
5522 ASSERT((Opcode & 0xFE) == 0xAA);
5523
5524 TOGGLE_OPSIZE(OperandSize);
5525 TOGGLE_ADSIZE(AddressSize);
5526
5527 /* Calculate the size */
5528 if (Opcode == 0xAA) DataSize = sizeof(UCHAR);
5529 else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);
5530
5531 if (State->PrefixFlags & (FAST486_PREFIX_REP | FAST486_PREFIX_REPNZ))
5532 {
5533 UCHAR Block[STRING_BLOCK_SIZE];
5534 ULONG Count = AddressSize ? State->GeneralRegs[FAST486_REG_ECX].Long
5535 : State->GeneralRegs[FAST486_REG_ECX].LowWord;
5536
5537 /* Fill the memory block with the data */
5538 if (DataSize == sizeof(UCHAR))
5539 {
5540 RtlFillMemory(Block, sizeof(Block), State->GeneralRegs[FAST486_REG_EAX].LowByte);
5541 }
5542 else
5543 {
5544 ULONG i;
5545
5546 for (i = 0; i < STRING_BLOCK_SIZE / DataSize; i++)
5547 {
5548 if (DataSize == sizeof(USHORT))
5549 {
5550 ((PUSHORT)Block)[i] = State->GeneralRegs[FAST486_REG_EAX].LowWord;
5551 }
5552 else
5553 {
5554 ((PULONG)Block)[i] = State->GeneralRegs[FAST486_REG_EAX].Long;
5555 }
5556 }
5557 }
5558
5559 /* Transfer until finished */
5560 while (Count)
5561 {
5562 ULONG Processed = min(Count, STRING_BLOCK_SIZE / DataSize);
5563
5564 /* Simulate the 16-bit wrap-around of DI in 16-bit address mode */
5565 if (!AddressSize)
5566 {
5567 ULONG MaxBytes = State->Flags.Df
5568 ? (ULONG)State->GeneralRegs[FAST486_REG_EDI].LowWord
5569 : (0x10000 - (ULONG)State->GeneralRegs[FAST486_REG_EDI].LowWord);
5570
5571 Processed = min(Processed, MaxBytes / DataSize);
5572 if (Processed == 0) Processed = 1;
5573 }
5574
5575 if (State->Flags.Df)
5576 {
5577 /* Set EDI to the starting location */
5578 if (AddressSize) State->GeneralRegs[FAST486_REG_EDI].Long -= (Processed - 1) * DataSize;
5579 else State->GeneralRegs[FAST486_REG_EDI].LowWord -= (Processed - 1) * DataSize;
5580 }
5581
5582 /* Write to memory */
5584 FAST486_REG_ES,
5585 AddressSize ? State->GeneralRegs[FAST486_REG_EDI].Long
5586 : State->GeneralRegs[FAST486_REG_EDI].LowWord,
5587 Block,
5588 Processed * DataSize))
5589 {
5590 /* Set ECX */
5591 if (AddressSize) State->GeneralRegs[FAST486_REG_ECX].Long = Count;
5592 else State->GeneralRegs[FAST486_REG_ECX].LowWord = LOWORD(Count);
5593
5594 /* Exception occurred */
5595 return;
5596 }
5597
5598 if (!State->Flags.Df)
5599 {
5600 /* Increase EDI by the number of bytes transfered */
5601 if (AddressSize) State->GeneralRegs[FAST486_REG_EDI].Long += Processed * DataSize;
5602 else State->GeneralRegs[FAST486_REG_EDI].LowWord += Processed * DataSize;
5603 }
5604 else
5605 {
5606 /* Reduce EDI */
5607 if (AddressSize) State->GeneralRegs[FAST486_REG_EDI].Long -= DataSize;
5608 else State->GeneralRegs[FAST486_REG_EDI].LowWord -= DataSize;
5609 }
5610
5611 /* Reduce the total count by the number processed in this run */
5612 Count -= Processed;
5613 }
5614
5615 /* Clear ECX */
5616 if (AddressSize) State->GeneralRegs[FAST486_REG_ECX].Long = 0;
5617 else State->GeneralRegs[FAST486_REG_ECX].LowWord = 0;
5618 }
5619 else
5620 {
5621 /* Write to the destination operand */
5623 FAST486_REG_ES,
5624 AddressSize ? State->GeneralRegs[FAST486_REG_EDI].Long
5625 : State->GeneralRegs[FAST486_REG_EDI].LowWord,
5626 &State->GeneralRegs[FAST486_REG_EAX].Long,
5627 DataSize))
5628 {
5629 /* Exception occurred */
5630 return;
5631 }
5632
5633 /* Increment/decrement EDI */
5634 if (AddressSize)
5635 {
5636 if (!State->Flags.Df) State->GeneralRegs[FAST486_REG_EDI].Long += DataSize;
5637 else State->GeneralRegs[FAST486_REG_EDI].Long -= DataSize;
5638 }
5639 else
5640 {
5641 if (!State->Flags.Df) State->GeneralRegs[FAST486_REG_EDI].LowWord += DataSize;
5642 else State->GeneralRegs[FAST486_REG_EDI].LowWord -= DataSize;
5643 }
5644 }
5645}
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:599

◆ FAST486_OPCODE_HANDLER() [105/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeTestAl  )

Definition at line 2016 of file opcodes.c.

2017{
2018 UCHAR FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowByte;
2019 UCHAR SecondValue, Result;
2020
2021 /* Make sure this is the right instruction */
2022 ASSERT(Opcode == 0xA8);
2023
2025
2026 if (!Fast486FetchByte(State, &SecondValue))
2027 {
2028 /* Exception occurred */
2029 return;
2030 }
2031
2032 /* Calculate the result */
2033 Result = FirstValue & SecondValue;
2034
2035 /* Update the flags */
2036 State->Flags.Cf = FALSE;
2037 State->Flags.Of = FALSE;
2038 State->Flags.Zf = (Result == 0);
2039 State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
2040 State->Flags.Pf = Fast486CalculateParity(Result);
2041}

◆ FAST486_OPCODE_HANDLER() [106/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeTestByteModrm  )

Definition at line 1910 of file opcodes.c.

1911{
1912 UCHAR FirstValue, SecondValue, Result;
1913 FAST486_MOD_REG_RM ModRegRm;
1914 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
1915
1916 /* Make sure this is the right instruction */
1917 ASSERT(Opcode == 0x84);
1918
1919 TOGGLE_ADSIZE(AddressSize);
1920
1921 /* Get the operands */
1922 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
1923 {
1924 /* Exception occurred */
1925 return;
1926 }
1927
1928 if (!Fast486ReadModrmByteOperands(State,
1929 &ModRegRm,
1930 &FirstValue,
1931 &SecondValue))
1932 {
1933 /* Exception occurred */
1934 return;
1935 }
1936 /* Calculate the result */
1937 Result = FirstValue & SecondValue;
1938
1939 /* Update the flags */
1940 State->Flags.Cf = FALSE;
1941 State->Flags.Of = FALSE;
1942 State->Flags.Zf = (Result == 0);
1943 State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
1944 State->Flags.Pf = Fast486CalculateParity(Result);
1945}

◆ FAST486_OPCODE_HANDLER() [107/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeTestEax  )

Definition at line 2043 of file opcodes.c.

2044{
2045 BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
2046
2047 /* Make sure this is the right instruction */
2048 ASSERT(Opcode == 0xA9);
2049
2052
2053 if (Size)
2054 {
2055 ULONG FirstValue = State->GeneralRegs[FAST486_REG_EAX].Long;
2056 ULONG SecondValue, Result;
2057
2058 if (!Fast486FetchDword(State, &SecondValue))
2059 {
2060 /* Exception occurred */
2061 return;
2062 }
2063
2064 /* Calculate the result */
2065 Result = FirstValue & SecondValue;
2066
2067 /* Update the flags */
2068 State->Flags.Cf = FALSE;
2069 State->Flags.Of = FALSE;
2070 State->Flags.Zf = (Result == 0);
2071 State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
2072 State->Flags.Pf = Fast486CalculateParity(Result);
2073 }
2074 else
2075 {
2076 USHORT FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowWord;
2077 USHORT SecondValue, Result;
2078
2079 if (!Fast486FetchWord(State, &SecondValue))
2080 {
2081 /* Exception occurred */
2082 return;
2083 }
2084
2085 /* Calculate the result */
2086 Result = FirstValue & SecondValue;
2087
2088 /* Update the flags */
2089 State->Flags.Cf = FALSE;
2090 State->Flags.Of = FALSE;
2091 State->Flags.Zf = (Result == 0);
2092 State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
2093 State->Flags.Pf = Fast486CalculateParity(Result);
2094 }
2095}

◆ FAST486_OPCODE_HANDLER() [108/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeTestModrm  )

Definition at line 1947 of file opcodes.c.

1948{
1949 FAST486_MOD_REG_RM ModRegRm;
1950 BOOLEAN OperandSize, AddressSize;
1951
1952 /* Make sure this is the right instruction */
1953 ASSERT(Opcode == 0x85);
1954
1955 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
1956
1957 TOGGLE_ADSIZE(AddressSize);
1958 TOGGLE_OPSIZE(OperandSize);
1959
1960 /* Get the operands */
1961 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
1962 {
1963 /* Exception occurred */
1964 return;
1965 }
1966
1967 /* Check the operand size */
1968 if (OperandSize)
1969 {
1970 ULONG FirstValue, SecondValue, Result;
1971
1972 if (!Fast486ReadModrmDwordOperands(State,
1973 &ModRegRm,
1974 &FirstValue,
1975 &SecondValue))
1976 {
1977 /* Exception occurred */
1978 return;
1979 }
1980
1981 /* Calculate the result */
1982 Result = FirstValue & SecondValue;
1983
1984 /* Update the flags */
1985 State->Flags.Cf = FALSE;
1986 State->Flags.Of = FALSE;
1987 State->Flags.Zf = (Result == 0);
1988 State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
1989 State->Flags.Pf = Fast486CalculateParity(Result);
1990 }
1991 else
1992 {
1993 USHORT FirstValue, SecondValue, Result;
1994
1995 if (!Fast486ReadModrmWordOperands(State,
1996 &ModRegRm,
1997 &FirstValue,
1998 &SecondValue))
1999 {
2000 /* Exception occurred */
2001 return;
2002 }
2003
2004 /* Calculate the result */
2005 Result = FirstValue & SecondValue;
2006
2007 /* Update the flags */
2008 State->Flags.Cf = FALSE;
2009 State->Flags.Of = FALSE;
2010 State->Flags.Zf = (Result == 0);
2011 State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
2012 State->Flags.Pf = Fast486CalculateParity(Result);
2013 }
2014}

◆ FAST486_OPCODE_HANDLER() [109/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeWait  )

Definition at line 3982 of file opcodes.c.

3983{
3984#ifndef FAST486_NO_FPU
3985 Fast486FpuExceptionCheck(State);
3986#endif
3987}

◆ FAST486_OPCODE_HANDLER() [110/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeXchgByteModrm  )

Definition at line 2097 of file opcodes.c.

2098{
2099 UCHAR FirstValue, SecondValue;
2100 FAST486_MOD_REG_RM ModRegRm;
2101 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
2102
2103 /* Make sure this is the right instruction */
2104 ASSERT(Opcode == 0x86);
2105
2106 TOGGLE_ADSIZE(AddressSize);
2107
2108 /* Get the operands */
2109 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
2110 {
2111 /* Exception occurred */
2112 return;
2113 }
2114
2115 if (!Fast486ReadModrmByteOperands(State,
2116 &ModRegRm,
2117 &FirstValue,
2118 &SecondValue))
2119 {
2120 /* Exception occurred */
2121 return;
2122 }
2123
2124 /* Write the value from the register to the R/M */
2125 if (!Fast486WriteModrmByteOperands(State,
2126 &ModRegRm,
2127 FALSE,
2128 FirstValue))
2129 {
2130 /* Exception occurred */
2131 return;
2132 }
2133
2134 /* Write the value from the R/M to the register */
2135 Fast486WriteModrmByteOperands(State,
2136 &ModRegRm,
2137 TRUE,
2138 SecondValue);
2139}

◆ FAST486_OPCODE_HANDLER() [111/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeXchgModrm  )

Definition at line 2141 of file opcodes.c.

2142{
2143 FAST486_MOD_REG_RM ModRegRm;
2144 BOOLEAN OperandSize, AddressSize;
2145
2146 /* Make sure this is the right instruction */
2147 ASSERT(Opcode == 0x87);
2148
2149 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
2150
2151 TOGGLE_ADSIZE(AddressSize);
2152 TOGGLE_OPSIZE(OperandSize);
2153
2154 /* Get the operands */
2155 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
2156 {
2157 /* Exception occurred */
2158 return;
2159 }
2160
2161 /* Check the operand size */
2162 if (OperandSize)
2163 {
2164 ULONG FirstValue, SecondValue;
2165
2166 if (!Fast486ReadModrmDwordOperands(State,
2167 &ModRegRm,
2168 &FirstValue,
2169 &SecondValue))
2170 {
2171 /* Exception occurred */
2172 return;
2173 }
2174
2175 /* Write the value from the register to the R/M */
2176 if (!Fast486WriteModrmDwordOperands(State,
2177 &ModRegRm,
2178 FALSE,
2179 FirstValue))
2180 {
2181 /* Exception occurred */
2182 return;
2183 }
2184
2185 /* Write the value from the R/M to the register */
2186 Fast486WriteModrmDwordOperands(State,
2187 &ModRegRm,
2188 TRUE,
2189 SecondValue);
2190 }
2191 else
2192 {
2193 USHORT FirstValue, SecondValue;
2194
2195 if (!Fast486ReadModrmWordOperands(State,
2196 &ModRegRm,
2197 &FirstValue,
2198 &SecondValue))
2199 {
2200 /* Exception occurred */
2201 return;
2202 }
2203
2204 /* Write the value from the register to the R/M */
2205 if (!Fast486WriteModrmWordOperands(State,
2206 &ModRegRm,
2207 FALSE,
2208 FirstValue))
2209 {
2210 /* Exception occurred */
2211 return;
2212 }
2213
2214 /* Write the value from the R/M to the register */
2215 Fast486WriteModrmWordOperands(State,
2216 &ModRegRm,
2217 TRUE,
2218 SecondValue);
2219 }
2220}

◆ FAST486_OPCODE_HANDLER() [112/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeXlat  )

Definition at line 4759 of file opcodes.c.

4760{
4761 UCHAR Value;
4762 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
4763
4764 TOGGLE_ADSIZE(AddressSize);
4765
4766 /* Read a byte from DS:[(E)BX + AL] */
4768 (State->PrefixFlags & FAST486_PREFIX_SEG)
4769 ? State->SegmentOverride : FAST486_REG_DS,
4770 (AddressSize ? State->GeneralRegs[FAST486_REG_EBX].Long
4771 : State->GeneralRegs[FAST486_REG_EBX].LowWord)
4772 + State->GeneralRegs[FAST486_REG_EAX].LowByte,
4773 FALSE,
4774 &Value,
4775 sizeof(UCHAR)))
4776 {
4777 /* Exception occurred */
4778 return;
4779 }
4780
4781 /* Set AL to the result */
4782 State->GeneralRegs[FAST486_REG_EAX].LowByte = Value;
4783}

◆ FAST486_OPCODE_HANDLER() [113/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeXorAl  )

Definition at line 1820 of file opcodes.c.

1821{
1822 UCHAR FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowByte;
1823 UCHAR SecondValue, Result;
1824
1825 /* Make sure this is the right instruction */
1826 ASSERT(Opcode == 0x34);
1827
1829
1830 if (!Fast486FetchByte(State, &SecondValue))
1831 {
1832 /* Exception occurred */
1833 return;
1834 }
1835
1836 /* Calculate the result */
1837 Result = FirstValue ^ SecondValue;
1838
1839 /* Update the flags */
1840 State->Flags.Cf = FALSE;
1841 State->Flags.Of = FALSE;
1842 State->Flags.Zf = (Result == 0);
1843 State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
1844 State->Flags.Pf = Fast486CalculateParity(Result);
1845
1846 /* Write back the result */
1847 State->GeneralRegs[FAST486_REG_EAX].LowByte = Result;
1848}

◆ FAST486_OPCODE_HANDLER() [114/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeXorByteModrm  )

Definition at line 1695 of file opcodes.c.

1696{
1697 UCHAR FirstValue, SecondValue, Result;
1698 FAST486_MOD_REG_RM ModRegRm;
1699 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
1700
1701 /* Make sure this is the right instruction */
1702 ASSERT((Opcode & 0xFD) == 0x30);
1703
1704 TOGGLE_ADSIZE(AddressSize);
1705
1706 /* Get the operands */
1707 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
1708 {
1709 /* Exception occurred */
1710 return;
1711 }
1712
1713 if (!Fast486ReadModrmByteOperands(State,
1714 &ModRegRm,
1715 &FirstValue,
1716 &SecondValue))
1717 {
1718 /* Exception occurred */
1719 return;
1720 }
1721
1722 /* Calculate the result */
1723 Result = FirstValue ^ SecondValue;
1724
1725 /* Update the flags */
1726 State->Flags.Cf = FALSE;
1727 State->Flags.Of = FALSE;
1728 State->Flags.Zf = (Result == 0);
1729 State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
1730 State->Flags.Pf = Fast486CalculateParity(Result);
1731
1732 /* Write back the result */
1733 Fast486WriteModrmByteOperands(State,
1734 &ModRegRm,
1736 Result);
1737}

◆ FAST486_OPCODE_HANDLER() [115/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeXorEax  )

Definition at line 1850 of file opcodes.c.

1851{
1852 BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
1853
1854 /* Make sure this is the right instruction */
1855 ASSERT(Opcode == 0x35);
1856
1859
1860 if (Size)
1861 {
1862 ULONG FirstValue = State->GeneralRegs[FAST486_REG_EAX].Long;
1863 ULONG SecondValue, Result;
1864
1865 if (!Fast486FetchDword(State, &SecondValue))
1866 {
1867 /* Exception occurred */
1868 return;
1869 }
1870
1871 /* Calculate the result */
1872 Result = FirstValue ^ SecondValue;
1873
1874 /* Update the flags */
1875 State->Flags.Cf = FALSE;
1876 State->Flags.Of = FALSE;
1877 State->Flags.Zf = (Result == 0);
1878 State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
1879 State->Flags.Pf = Fast486CalculateParity(Result);
1880
1881 /* Write back the result */
1882 State->GeneralRegs[FAST486_REG_EAX].Long = Result;
1883 }
1884 else
1885 {
1886 USHORT FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowWord;
1887 USHORT SecondValue, Result;
1888
1889 if (!Fast486FetchWord(State, &SecondValue))
1890 {
1891 /* Exception occurred */
1892 return;
1893 }
1894
1895 /* Calculate the result */
1896 Result = FirstValue ^ SecondValue;
1897
1898 /* Update the flags */
1899 State->Flags.Cf = FALSE;
1900 State->Flags.Of = FALSE;
1901 State->Flags.Zf = (Result == 0);
1902 State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
1903 State->Flags.Pf = Fast486CalculateParity(Result);
1904
1905 /* Write back the result */
1906 State->GeneralRegs[FAST486_REG_EAX].LowWord = Result;
1907 }
1908}

◆ FAST486_OPCODE_HANDLER() [116/116]

FAST486_OPCODE_HANDLER ( Fast486OpcodeXorModrm  )

Definition at line 1739 of file opcodes.c.

1740{
1741 FAST486_MOD_REG_RM ModRegRm;
1742 BOOLEAN OperandSize, AddressSize;
1743
1744 /* Make sure this is the right instruction */
1745 ASSERT((Opcode & 0xFD) == 0x31);
1746
1747 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
1748
1749 TOGGLE_ADSIZE(AddressSize);
1750 TOGGLE_OPSIZE(OperandSize);
1751
1752 /* Get the operands */
1753 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
1754 {
1755 /* Exception occurred */
1756 return;
1757 }
1758
1759 /* Check the operand size */
1760 if (OperandSize)
1761 {
1762 ULONG FirstValue, SecondValue, Result;
1763
1764 if (!Fast486ReadModrmDwordOperands(State,
1765 &ModRegRm,
1766 &FirstValue,
1767 &SecondValue))
1768 {
1769 /* Exception occurred */
1770 return;
1771 }
1772
1773 /* Calculate the result */
1774 Result = FirstValue ^ SecondValue;
1775
1776 /* Update the flags */
1777 State->Flags.Cf = FALSE;
1778 State->Flags.Of = FALSE;
1779 State->Flags.Zf = (Result == 0);
1780 State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
1781 State->Flags.Pf = Fast486CalculateParity(Result);
1782
1783 /* Write back the result */
1784 Fast486WriteModrmDwordOperands(State,
1785 &ModRegRm,
1787 Result);
1788 }
1789 else
1790 {
1791 USHORT FirstValue, SecondValue, Result;
1792
1793 if (!Fast486ReadModrmWordOperands(State,
1794 &ModRegRm,
1795 &FirstValue,
1796 &SecondValue))
1797 {
1798 /* Exception occurred */
1799 return;
1800 }
1801
1802 /* Calculate the result */
1803 Result = FirstValue ^ SecondValue;
1804
1805 /* Update the flags */
1806 State->Flags.Cf = FALSE;
1807 State->Flags.Of = FALSE;
1808 State->Flags.Zf = (Result == 0);
1809 State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
1810 State->Flags.Pf = Fast486CalculateParity(Result);
1811
1812 /* Write back the result */
1813 Fast486WriteModrmWordOperands(State,
1814 &ModRegRm,
1816 Result);
1817 }
1818}

Variable Documentation

◆ Fast486OpcodeHandlers

Definition at line 39 of file opcodes.c.

Referenced by Fast486ExecutionControl().