ReactOS 0.4.16-dev-91-g764881a
common.h File Reference
#include <pshpack1.h>
#include <poppack.h>
#include "common.inl"
Include dependency graph for common.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  _FAST486_MOD_REG_RM
 
union  _FAST486_PAGE_DIR
 
union  _FAST486_PAGE_TABLE
 

Macros

#define SIGN_FLAG_BYTE   0x80
 
#define SIGN_FLAG_WORD   0x8000
 
#define SIGN_FLAG_LONG   0x80000000
 
#define REAL_MODE_FLAGS_MASK   0x57FD5
 
#define PROT_MODE_FLAGS_MASK   0x50DD5
 
#define STRING_BLOCK_SIZE   4096
 
#define GET_SEGMENT_RPL(s)   ((s) & 3u)
 
#define GET_SEGMENT_INDEX(s)   ((s) & 0xFFF8u)
 
#define SEGMENT_TABLE_INDICATOR   (1 << 2)
 
#define EXCEPTION_HAS_ERROR_CODE(x)   (((x) == 8) || ((x) >= 10 && (x) <= 14))
 
#define NO_LOCK_PREFIX()
 
#define TOGGLE_OPSIZE(x)    if (State->PrefixFlags & FAST486_PREFIX_OPSIZE) x = !x;
 
#define TOGGLE_ADSIZE(x)    if (State->PrefixFlags & FAST486_PREFIX_ADSIZE) x = !x;
 
#define SWAP(x, y)   { (x) ^= (y); (y) ^= (x); (x) ^= (y); }
 
#define ALIGNMENT_CHECK(x, a)
 
#define PAGE_ALIGN(x)   ((x) & 0xFFFFF000)
 
#define PAGE_OFFSET(x)   ((x) & 0x00000FFF)
 
#define GET_ADDR_PDE(x)   ((x) >> 22)
 
#define GET_ADDR_PTE(x)   (((x) >> 12) & 0x3FF)
 
#define INVALID_TLB_FIELD   0xFFFFFFFF
 
#define NUM_TLB_ENTRIES   0x100000
 

Typedefs

typedef struct _FAST486_MOD_REG_RM FAST486_MOD_REG_RM
 
typedef struct _FAST486_MOD_REG_RMPFAST486_MOD_REG_RM
 
typedef enum _FAST486_TASK_SWITCH_TYPE FAST486_TASK_SWITCH_TYPE
 
typedef enum _FAST486_TASK_SWITCH_TYPEPFAST486_TASK_SWITCH_TYPE
 
typedef union _FAST486_PAGE_DIR FAST486_PAGE_DIR
 
typedef union _FAST486_PAGE_DIRPFAST486_PAGE_DIR
 
typedef union _FAST486_PAGE_TABLE FAST486_PAGE_TABLE
 
typedef union _FAST486_PAGE_TABLEPFAST486_PAGE_TABLE
 

Enumerations

enum  _FAST486_TASK_SWITCH_TYPE { FAST486_TASK_JUMP , FAST486_TASK_CALL , FAST486_TASK_RETURN }
 

Functions

 C_ASSERT (sizeof(FAST486_PAGE_DIR)==sizeof(ULONG))
 
BOOLEAN FASTCALL Fast486ReadMemory (PFAST486_STATE State, FAST486_SEG_REGS SegmentReg, ULONG Offset, BOOLEAN InstFetch, PVOID Buffer, ULONG Size)
 
BOOLEAN FASTCALL Fast486WriteMemory (PFAST486_STATE State, FAST486_SEG_REGS SegmentReg, ULONG Offset, PVOID Buffer, ULONG Size)
 
BOOLEAN FASTCALL Fast486PerformInterrupt (PFAST486_STATE State, UCHAR Number)
 
VOID FASTCALL Fast486ExceptionWithErrorCode (PFAST486_STATE State, FAST486_EXCEPTIONS ExceptionCode, ULONG ErrorCode)
 
BOOLEAN FASTCALL Fast486TaskSwitch (PFAST486_STATE State, FAST486_TASK_SWITCH_TYPE Type, USHORT Selector)
 
BOOLEAN FASTCALL Fast486CallGate (PFAST486_STATE State, PFAST486_CALL_GATE Gate, BOOLEAN Call)
 

Macro Definition Documentation

◆ ALIGNMENT_CHECK

#define ALIGNMENT_CHECK (   x,
  a 
)
Value:
if (State->Flags.Ac \
&& (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_AM)\
&& (State->Cpl == 3)\
&& (((x) % (a)) != 0))\
{\
Fast486Exception(State, FAST486_EXCEPTION_AC);\
return FALSE;\
}
#define FALSE
Definition: types.h:117
#define FAST486_CR0_AM
Definition: fast486.h:53
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204

Definition at line 58 of file common.h.

◆ EXCEPTION_HAS_ERROR_CODE

#define EXCEPTION_HAS_ERROR_CODE (   x)    (((x) == 8) || ((x) >= 10 && (x) <= 14))

Definition at line 41 of file common.h.

◆ GET_ADDR_PDE

#define GET_ADDR_PDE (   x)    ((x) >> 22)

Definition at line 69 of file common.h.

◆ GET_ADDR_PTE

#define GET_ADDR_PTE (   x)    (((x) >> 12) & 0x3FF)

Definition at line 70 of file common.h.

◆ GET_SEGMENT_INDEX

#define GET_SEGMENT_INDEX (   s)    ((s) & 0xFFF8u)

Definition at line 39 of file common.h.

◆ GET_SEGMENT_RPL

#define GET_SEGMENT_RPL (   s)    ((s) & 3u)

Definition at line 38 of file common.h.

◆ INVALID_TLB_FIELD

#define INVALID_TLB_FIELD   0xFFFFFFFF

Definition at line 71 of file common.h.

◆ NO_LOCK_PREFIX

#define NO_LOCK_PREFIX ( )
Value:
if (State->PrefixFlags & FAST486_PREFIX_LOCK)\
{\
Fast486Exception(State, FAST486_EXCEPTION_UD);\
return;\
}
#define FAST486_PREFIX_LOCK
Definition: fast486.h:101

Definition at line 43 of file common.h.

◆ NUM_TLB_ENTRIES

#define NUM_TLB_ENTRIES   0x100000

Definition at line 72 of file common.h.

◆ PAGE_ALIGN

#define PAGE_ALIGN (   x)    ((x) & 0xFFFFF000)

Definition at line 67 of file common.h.

◆ PAGE_OFFSET

#define PAGE_OFFSET (   x)    ((x) & 0x00000FFF)

Definition at line 68 of file common.h.

◆ PROT_MODE_FLAGS_MASK

#define PROT_MODE_FLAGS_MASK   0x50DD5

Definition at line 33 of file common.h.

◆ REAL_MODE_FLAGS_MASK

#define REAL_MODE_FLAGS_MASK   0x57FD5

Definition at line 32 of file common.h.

◆ SEGMENT_TABLE_INDICATOR

#define SEGMENT_TABLE_INDICATOR   (1 << 2)

Definition at line 40 of file common.h.

◆ SIGN_FLAG_BYTE

#define SIGN_FLAG_BYTE   0x80

Definition at line 29 of file common.h.

◆ SIGN_FLAG_LONG

#define SIGN_FLAG_LONG   0x80000000

Definition at line 31 of file common.h.

◆ SIGN_FLAG_WORD

#define SIGN_FLAG_WORD   0x8000

Definition at line 30 of file common.h.

◆ STRING_BLOCK_SIZE

#define STRING_BLOCK_SIZE   4096

Definition at line 36 of file common.h.

◆ SWAP

#define SWAP (   x,
  y 
)    { (x) ^= (y); (y) ^= (x); (x) ^= (y); }

Definition at line 56 of file common.h.

◆ TOGGLE_ADSIZE

#define TOGGLE_ADSIZE (   x)     if (State->PrefixFlags & FAST486_PREFIX_ADSIZE) x = !x;

Definition at line 53 of file common.h.

◆ TOGGLE_OPSIZE

#define TOGGLE_OPSIZE (   x)     if (State->PrefixFlags & FAST486_PREFIX_OPSIZE) x = !x;

Definition at line 50 of file common.h.

Typedef Documentation

◆ FAST486_MOD_REG_RM

◆ FAST486_PAGE_DIR

◆ FAST486_PAGE_TABLE

◆ FAST486_TASK_SWITCH_TYPE

◆ PFAST486_MOD_REG_RM

◆ PFAST486_PAGE_DIR

◆ PFAST486_PAGE_TABLE

◆ PFAST486_TASK_SWITCH_TYPE

Enumeration Type Documentation

◆ _FAST486_TASK_SWITCH_TYPE

Enumerator
FAST486_TASK_JUMP 
FAST486_TASK_CALL 
FAST486_TASK_RETURN 

Definition at line 85 of file common.h.

86{
enum _FAST486_TASK_SWITCH_TYPE FAST486_TASK_SWITCH_TYPE
@ FAST486_TASK_JUMP
Definition: common.h:87
@ FAST486_TASK_RETURN
Definition: common.h:89
@ FAST486_TASK_CALL
Definition: common.h:88
enum _FAST486_TASK_SWITCH_TYPE * PFAST486_TASK_SWITCH_TYPE

Function Documentation

◆ C_ASSERT()

C_ASSERT ( sizeof(FAST486_PAGE_DIR = =sizeof(ULONG))

◆ Fast486CallGate()

BOOLEAN FASTCALL Fast486CallGate ( PFAST486_STATE  State,
PFAST486_CALL_GATE  Gate,
BOOLEAN  Call 
)

Definition at line 1116 of file common.c.

1119{
1120 BOOLEAN Valid;
1121 FAST486_GDT_ENTRY NewCodeSegment;
1122 BOOLEAN GateSize = (Gate->Type == FAST486_CALL_GATE_SIGNATURE);
1123 FAST486_TSS Tss;
1124 PFAST486_LEGACY_TSS LegacyTss = (PFAST486_LEGACY_TSS)&Tss;
1125 USHORT OldCs = State->SegmentRegs[FAST486_REG_CS].Selector;
1126 ULONG OldEip = State->InstPtr.Long;
1127 USHORT OldCpl = State->Cpl;
1128 USHORT OldSs = State->SegmentRegs[FAST486_REG_SS].Selector;
1129 ULONG OldEsp = State->GeneralRegs[FAST486_REG_ESP].Long;
1130 ULONG ParamBuffer[32]; /* Maximum possible size - 32 DWORDs */
1131 PULONG LongParams = (PULONG)ParamBuffer;
1132 PUSHORT ShortParams = (PUSHORT)ParamBuffer;
1133
1134 if (!Gate->Selector)
1135 {
1136 /* The code segment is NULL */
1137 Fast486Exception(State, FAST486_EXCEPTION_GP);
1138 return FALSE;
1139 }
1140
1141 if (!Fast486ReadDescriptorEntry(State, Gate->Selector, &Valid, &NewCodeSegment))
1142 {
1143 /* Exception occurred */
1144 return FALSE;
1145 }
1146
1147 if (!Valid || (NewCodeSegment.Dpl > Fast486GetCurrentPrivLevel(State)))
1148 {
1149 /* Code segment invalid */
1150 Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Gate->Selector);
1151 return FALSE;
1152 }
1153
1154 if (Call && Gate->ParamCount)
1155 {
1156 /* Read the parameters */
1158 FAST486_REG_SS,
1159 OldEsp,
1160 FALSE,
1161 ParamBuffer,
1162 Gate->ParamCount * (GateSize ? sizeof(ULONG) : sizeof(USHORT))))
1163 {
1164 /* Exception occurred */
1165 return FALSE;
1166 }
1167 }
1168
1169 /* Check if the new code segment is more privileged */
1170 if (NewCodeSegment.Dpl < OldCpl)
1171 {
1172 if (Call)
1173 {
1174 USHORT NewSs;
1175 ULONG NewEsp;
1176
1177 /* Read the TSS */
1178 if (!Fast486ReadLinearMemory(State,
1179 State->TaskReg.Base,
1180 &Tss,
1181 State->TaskReg.Modern
1182 ? sizeof(FAST486_TSS) : sizeof(FAST486_LEGACY_TSS),
1183 FALSE))
1184 {
1185 /* Exception occurred */
1186 return FALSE;
1187 }
1188
1189 /* Switch to the new privilege level */
1190 State->Cpl = NewCodeSegment.Dpl;
1191
1192 /* Check the new (higher) privilege level */
1193 switch (State->Cpl)
1194 {
1195 case 0:
1196 {
1197 if (State->TaskReg.Modern)
1198 {
1199 NewSs = Tss.Ss0;
1200 NewEsp = Tss.Esp0;
1201 }
1202 else
1203 {
1204 NewSs = LegacyTss->Ss0;
1205 NewEsp = LegacyTss->Sp0;
1206 }
1207
1208 break;
1209 }
1210
1211 case 1:
1212 {
1213 if (State->TaskReg.Modern)
1214 {
1215 NewSs = Tss.Ss1;
1216 NewEsp = Tss.Esp1;
1217 }
1218 else
1219 {
1220 NewSs = LegacyTss->Ss1;
1221 NewEsp = LegacyTss->Sp1;
1222 }
1223
1224 break;
1225 }
1226
1227 case 2:
1228 {
1229 if (State->TaskReg.Modern)
1230 {
1231 NewSs = Tss.Ss2;
1232 NewEsp = Tss.Esp2;
1233 }
1234 else
1235 {
1236 NewSs = LegacyTss->Ss2;
1237 NewEsp = LegacyTss->Sp2;
1238 }
1239
1240 break;
1241 }
1242
1243 default:
1244 {
1245 /* Should never reach here! */
1246 ASSERT(FALSE);
1247 }
1248 }
1249
1250 if (!Fast486LoadSegment(State, FAST486_REG_SS, NewSs))
1251 {
1252 /* Exception occurred */
1253 return FALSE;
1254 }
1255
1256 State->GeneralRegs[FAST486_REG_ESP].Long = NewEsp;
1257 }
1258 else if (!NewCodeSegment.DirConf)
1259 {
1260 /* This is not allowed for jumps */
1261 Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Gate->Selector);
1262 return FALSE;
1263 }
1264 }
1265
1266 /* Load new CS */
1267 if (!Fast486LoadSegment(State, FAST486_REG_CS, Gate->Selector))
1268 {
1269 /* An exception occurred during the jump */
1270 return FALSE;
1271 }
1272
1273 /* Set the instruction pointer */
1274 if (GateSize) State->InstPtr.Long = MAKELONG(Gate->Offset, Gate->OffsetHigh);
1275 else State->InstPtr.Long = Gate->Offset;
1276
1277 if (Call)
1278 {
1279 INT i;
1280
1281 /* Check if the new code segment is more privileged (again) */
1282 if (NewCodeSegment.Dpl < OldCpl)
1283 {
1284 /* Push SS selector */
1285 if (!Fast486StackPushInternal(State, GateSize, OldSs)) return FALSE;
1286
1287 /* Push stack pointer */
1288 if (!Fast486StackPushInternal(State, GateSize, OldEsp)) return FALSE;
1289 }
1290
1291 /* Push the parameters in reverse order */
1292 for (i = Gate->ParamCount - 1; i >= 0; i--)
1293 {
1294 if (!Fast486StackPushInternal(State,
1295 GateSize,
1296 GateSize ? LongParams[i] : ShortParams[i]))
1297 {
1298 /* Exception occurred */
1299 return FALSE;
1300 }
1301 }
1302
1303 /* Push CS selector */
1304 if (!Fast486StackPushInternal(State, GateSize, OldCs)) return FALSE;
1305
1306 /* Push the instruction pointer */
1307 if (!Fast486StackPushInternal(State, GateSize, OldEip)) return FALSE;
1308 }
1309
1310 return TRUE;
1311}
unsigned char BOOLEAN
#define TRUE
Definition: types.h:120
#define FAST486_CALL_GATE_SIGNATURE
Definition: fast486.h:94
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
#define ASSERT(a)
Definition: mode.c:44
unsigned short USHORT
Definition: pedump.c:61
VOID FASTCALL Fast486ExceptionWithErrorCode(PFAST486_STATE State, FAST486_EXCEPTIONS ExceptionCode, ULONG ErrorCode)
Definition: common.c:557
BOOLEAN FASTCALL Fast486ReadMemory(PFAST486_STATE State, FAST486_SEG_REGS SegmentReg, ULONG Offset, BOOLEAN InstFetch, PVOID Buffer, ULONG Size)
Definition: common.c:36
uint32_t * PULONG
Definition: typedefs.h:59
int32_t INT
Definition: typedefs.h:58
uint16_t * PUSHORT
Definition: typedefs.h:56
#define MAKELONG(a, b)
Definition: typedefs.h:249
uint32_t ULONG
Definition: typedefs.h:59

◆ Fast486ExceptionWithErrorCode()

VOID FASTCALL Fast486ExceptionWithErrorCode ( PFAST486_STATE  State,
FAST486_EXCEPTIONS  ExceptionCode,
ULONG  ErrorCode 
)

Definition at line 557 of file common.c.

560{
561 FAST486_IDT_ENTRY IdtEntry;
562
563 /* Increment the exception count */
564 State->ExceptionCount++;
565
566 /* Check if the exception occurred more than once */
567 if (State->ExceptionCount > 1)
568 {
569 /* Then this is a double fault */
570 ExceptionCode = FAST486_EXCEPTION_DF;
571 }
572
573 /* Check if this is a triple fault */
574 if (State->ExceptionCount == 3)
575 {
576 DPRINT("Fast486ExceptionWithErrorCode(%04X:%08X) -- Triple fault\n",
577 State->SegmentRegs[FAST486_REG_CS].Selector,
578 State->InstPtr.Long);
579
580 /* Reset the CPU */
582 return;
583 }
584
585 /* Clear the prefix flags */
586 State->PrefixFlags = 0;
587
588 /* Restore the IP to the saved IP */
589 State->InstPtr = State->SavedInstPtr;
590
591 /* Restore the SP to the saved SP */
592 State->GeneralRegs[FAST486_REG_ESP] = State->SavedStackPtr;
593
594 /* Get the interrupt vector */
595 if (!Fast486GetIntVector(State, ExceptionCode, &IdtEntry))
596 {
597 /*
598 * If this function failed, that means Fast486Exception
599 * was called again, so just return in this case.
600 */
601 return;
602 }
603
604 /* Perform the interrupt */
606 &IdtEntry,
608 && (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE),
609 ErrorCode))
610 {
611 /*
612 * If this function failed, that means Fast486Exception
613 * was called again, so just return in this case.
614 */
615 return;
616 }
617
618 /* Reset the exception count */
619 State->ExceptionCount = 0;
620}
_Inout_ PIRP _In_ NTSTATUS ExceptionCode
Definition: cdprocs.h:1774
VOID NTAPI Fast486Reset(PFAST486_STATE State)
Definition: fast486.c:131
#define FAST486_CR0_PE
Definition: fast486.h:46
_In_ NDIS_ERROR_CODE ErrorCode
Definition: ndis.h:4436
static BOOLEAN FASTCALL Fast486InterruptInternal(PFAST486_STATE State, PFAST486_IDT_ENTRY IdtEntry, BOOLEAN PushErrorCode, ULONG ErrorCode)
Definition: common.c:298
static BOOLEAN FASTCALL Fast486GetIntVector(PFAST486_STATE State, UCHAR Number, PFAST486_IDT_ENTRY IdtEntry)
Definition: common.c:251
#define EXCEPTION_HAS_ERROR_CODE(x)
Definition: common.h:41
#define DPRINT
Definition: sndvol32.h:73

Referenced by FAST486_OPCODE_HANDLER(), Fast486CallGate(), and Fast486TaskSwitch().

◆ Fast486PerformInterrupt()

BOOLEAN FASTCALL Fast486PerformInterrupt ( PFAST486_STATE  State,
UCHAR  Number 
)

Definition at line 533 of file common.c.

535{
536 FAST486_IDT_ENTRY IdtEntry;
537
538 /* Get the interrupt vector */
539 if (!Fast486GetIntVector(State, Number, &IdtEntry))
540 {
541 /* Exception occurred */
542 return FALSE;
543 }
544
545 /* Perform the interrupt */
546 if (!Fast486InterruptInternal(State, &IdtEntry, FALSE, 0))
547 {
548 /* Exception occurred */
549 return FALSE;
550 }
551
552 return TRUE;
553}
_In_opt_ PENTER_STATE_SYSTEM_HANDLER _In_opt_ PVOID _In_ LONG _In_opt_ LONG volatile * Number
Definition: ntpoapi.h:207

Referenced by FAST486_OPCODE_HANDLER(), and Fast486ExecutionControl().

◆ Fast486ReadMemory()

BOOLEAN FASTCALL Fast486ReadMemory ( PFAST486_STATE  State,
FAST486_SEG_REGS  SegmentReg,
ULONG  Offset,
BOOLEAN  InstFetch,
PVOID  Buffer,
ULONG  Size 
)

Definition at line 36 of file common.c.

42{
43 ULONG LinearAddress;
44 PFAST486_SEG_REG CachedDescriptor;
45 FAST486_EXCEPTIONS Exception = SegmentReg != FAST486_REG_SS
46 ? FAST486_EXCEPTION_GP : FAST486_EXCEPTION_SS;
47
48 ASSERT(SegmentReg < FAST486_NUM_SEG_REGS);
49
50 /* Get the cached descriptor */
51 CachedDescriptor = &State->SegmentRegs[SegmentReg];
52
53 if (InstFetch || CachedDescriptor->Executable || !CachedDescriptor->DirConf)
54 {
55 if ((Offset + Size - 1) > CachedDescriptor->Limit)
56 {
57 /* Read beyond limit */
58 Fast486Exception(State, Exception);
59 return FALSE;
60 }
61 }
62 else
63 {
64 if (Offset < CachedDescriptor->Limit)
65 {
66 /* Read beyond limit */
67 Fast486Exception(State, Exception);
68 return FALSE;
69 }
70 }
71
72 /* Check for protected mode */
73 if ((State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) && !State->Flags.Vm)
74 {
75 /* Privilege checks */
76
77 if (!CachedDescriptor->Present)
78 {
79 Fast486Exception(State, Exception);
80 return FALSE;
81 }
82
83 if ((!InstFetch && (CachedDescriptor->Rpl > CachedDescriptor->Dpl))
84 || (Fast486GetCurrentPrivLevel(State) > CachedDescriptor->Dpl))
85 {
86 Fast486Exception(State, Exception);
87 return FALSE;
88 }
89
90 if (InstFetch)
91 {
92 if (!CachedDescriptor->Executable)
93 {
94 /* Data segment not executable */
95 Fast486Exception(State, Exception);
96 return FALSE;
97 }
98 }
99 else
100 {
101 if (CachedDescriptor->Executable && (!CachedDescriptor->ReadWrite))
102 {
103 /* Code segment not readable */
104 Fast486Exception(State, Exception);
105 return FALSE;
106 }
107 }
108 }
109
110 /* Find the linear address */
111 LinearAddress = CachedDescriptor->Base + Offset;
112
113#ifndef FAST486_NO_PREFETCH
114 if (InstFetch && ((Offset + FAST486_CACHE_SIZE - 1) <= CachedDescriptor->Limit))
115 {
116 State->PrefetchAddress = LinearAddress;
117
118 if ((State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PG)
119 && (PAGE_OFFSET(State->PrefetchAddress) > (FAST486_PAGE_SIZE - FAST486_CACHE_SIZE)))
120 {
121 /* We mustn't prefetch across a page boundary */
122 State->PrefetchAddress = PAGE_ALIGN(State->PrefetchAddress)
124
125 if ((LinearAddress - State->PrefetchAddress + Size) >= FAST486_CACHE_SIZE)
126 {
127 /* We can't prefetch without possibly violating page permissions */
128 State->PrefetchValid = FALSE;
129 return Fast486ReadLinearMemory(State, LinearAddress, Buffer, Size, TRUE);
130 }
131 }
132
133 /* Prefetch */
134 if (Fast486ReadLinearMemory(State,
135 State->PrefetchAddress,
136 State->PrefetchCache,
138 TRUE))
139 {
140 State->PrefetchValid = TRUE;
141
143 &State->PrefetchCache[LinearAddress - State->PrefetchAddress],
144 Size);
145 return TRUE;
146 }
147 else
148 {
149 State->PrefetchValid = FALSE;
150 return FALSE;
151 }
152 }
153 else
154#endif
155 {
156 /* Read from the linear address */
157 return Fast486ReadLinearMemory(State, LinearAddress, Buffer, Size, TRUE);
158 }
159}
Definition: bufpool.h:45
#define FAST486_CACHE_SIZE
Definition: fast486.h:108
#define FAST486_NUM_SEG_REGS
Definition: fast486.h:41
#define FAST486_PAGE_SIZE
Definition: fast486.h:107
#define FAST486_CR0_PG
Definition: fast486.h:56
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
#define PAGE_OFFSET(x)
Definition: common.h:68
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
_In_ LONG _In_ LONG Limit
Definition: kefuncs.h:304
#define PAGE_ALIGN(Va)

Referenced by FAST486_OPCODE_HANDLER(), Fast486CallGate(), and Fast486FpuLoadEnvironment().

◆ Fast486TaskSwitch()

BOOLEAN FASTCALL Fast486TaskSwitch ( PFAST486_STATE  State,
FAST486_TASK_SWITCH_TYPE  Type,
USHORT  Selector 
)

Definition at line 624 of file common.c.

625{
626 ULONG NewTssAddress;
627 ULONG NewTssLimit;
628 FAST486_SYSTEM_DESCRIPTOR NewTssDescriptor;
629 FAST486_TSS OldTss;
630 PFAST486_LEGACY_TSS OldLegacyTss = (PFAST486_LEGACY_TSS)&OldTss;
631 FAST486_TSS NewTss;
632 PFAST486_LEGACY_TSS NewLegacyTss = (PFAST486_LEGACY_TSS)&NewTss;
633 USHORT NewLdtr, NewEs, NewCs, NewSs, NewDs;
634
635 if ((State->TaskReg.Modern && State->TaskReg.Limit < (sizeof(FAST486_TSS) - 1))
636 || (!State->TaskReg.Modern && State->TaskReg.Limit < (sizeof(FAST486_LEGACY_TSS) - 1)))
637 {
638 /* Invalid task register limit */
639 Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_TS, State->TaskReg.Selector);
640 return FALSE;
641 }
642
643 /* Read the old TSS */
644 if (!Fast486ReadLinearMemory(State,
645 State->TaskReg.Base,
646 &OldTss,
647 State->TaskReg.Modern
648 ? sizeof(FAST486_TSS) : sizeof(FAST486_LEGACY_TSS),
649 FALSE))
650 {
651 /* Exception occurred */
652 return FALSE;
653 }
654
655
656 /* If this is a task return, use the linked previous selector */
658 {
659 if (State->TaskReg.Modern) Selector = LOWORD(OldTss.Link);
660 else Selector = OldLegacyTss->Link;
661 }
662
663 /* Make sure the entry exists in the GDT (not LDT!) */
664 if ((GET_SEGMENT_INDEX(Selector) == 0)
665 || (Selector & SEGMENT_TABLE_INDICATOR)
666 || GET_SEGMENT_INDEX(Selector) >= (State->Gdtr.Size + 1u))
667 {
668 Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_TS, Selector);
669 return FALSE;
670 }
671
672 /* Get the TSS descriptor from the GDT */
673 if (!Fast486ReadLinearMemory(State,
674 State->Gdtr.Address + GET_SEGMENT_INDEX(Selector),
675 &NewTssDescriptor,
676 sizeof(NewTssDescriptor),
677 FALSE))
678 {
679 /* Exception occurred */
680 return FALSE;
681 }
682
683 if (!NewTssDescriptor.Present)
684 {
685 /* Incoming task TSS not present */
686 Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_NP, Selector);
687 return FALSE;
688 }
689
690 /* Calculate the linear address of the new TSS */
691 NewTssAddress = NewTssDescriptor.Base;
692 NewTssAddress |= NewTssDescriptor.BaseMid << 16;
693 NewTssAddress |= NewTssDescriptor.BaseHigh << 24;
694
695 /* Calculate the limit of the new TSS */
696 NewTssLimit = NewTssDescriptor.Limit | (NewTssDescriptor.LimitHigh << 16);
697
698 if (NewTssDescriptor.Granularity)
699 {
700 NewTssLimit <<= 12;
701 NewTssLimit |= 0x00000FFF;
702 }
703
704 if (NewTssLimit < (sizeof(FAST486_TSS) - 1)
705 && NewTssLimit != (sizeof(FAST486_LEGACY_TSS) - 1))
706 {
707 /* TSS limit invalid */
708 Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_TS, Selector);
709 return FALSE;
710 }
711
712 /*
713 * The incoming task shouldn't be busy if we're executing it as a
714 * new task, and it should be busy if we're returning to it.
715 */
716 if ((((NewTssDescriptor.Signature != FAST486_TSS_SIGNATURE)
717 && (NewTssDescriptor.Signature != FAST486_TSS_16_SIGNATURE))
719 && (((NewTssDescriptor.Signature != FAST486_BUSY_TSS_SIGNATURE)
720 && (NewTssDescriptor.Signature != FAST486_BUSY_TSS_16_SIGNATURE))
721 || (Type != FAST486_TASK_RETURN)))
722 {
723 Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
724 return FALSE;
725 }
726
727 /* Read the new TSS */
728 if (!Fast486ReadLinearMemory(State,
729 NewTssAddress,
730 &NewTss,
731 (NewTssDescriptor.Signature == FAST486_TSS_SIGNATURE)
732 || (NewTssDescriptor.Signature == FAST486_BUSY_TSS_SIGNATURE)
733 ? sizeof(FAST486_TSS) : sizeof(FAST486_LEGACY_TSS),
734 FALSE))
735 {
736 /* Exception occurred */
737 return FALSE;
738 }
739
740 if (Type != FAST486_TASK_CALL)
741 {
742 /* Clear the busy bit of the outgoing task */
743 FAST486_SYSTEM_DESCRIPTOR OldTssDescriptor;
744
745 if (!Fast486ReadLinearMemory(State,
746 State->Gdtr.Address
747 + GET_SEGMENT_INDEX(State->TaskReg.Selector),
748 &OldTssDescriptor,
749 sizeof(OldTssDescriptor),
750 FALSE))
751 {
752 /* Exception occurred */
753 return FALSE;
754 }
755
756 OldTssDescriptor.Signature = FAST486_TSS_SIGNATURE;
757
758 if (!Fast486WriteLinearMemory(State,
759 State->Gdtr.Address
760 + GET_SEGMENT_INDEX(State->TaskReg.Selector),
761 &OldTssDescriptor,
762 sizeof(OldTssDescriptor),
763 FALSE))
764 {
765 /* Exception occurred */
766 return FALSE;
767 }
768 }
769 else
770 {
771 /* Store the link */
772 if ((NewTssDescriptor.Signature == FAST486_TSS_SIGNATURE)
773 || (NewTssDescriptor.Signature == FAST486_BUSY_TSS_SIGNATURE))
774 {
775 NewTss.Link = State->TaskReg.Selector;
776
777 /* Write back the new TSS link */
778 if (!Fast486WriteLinearMemory(State,
779 NewTssAddress,
780 &NewTss.Link,
781 sizeof(NewTss.Link),
782 FALSE))
783 {
784 /* Exception occurred */
785 return FALSE;
786 }
787 }
788 else
789 {
790 NewLegacyTss->Link = State->TaskReg.Selector;
791
792 /* Write back the new legacy TSS link */
793 if (!Fast486WriteLinearMemory(State,
794 NewTssAddress,
795 &NewLegacyTss->Link,
796 sizeof(NewLegacyTss->Link),
797 FALSE))
798 {
799 /* Exception occurred */
800 return FALSE;
801 }
802 }
803 }
804
805 /* Save the current task into the TSS */
806 if (State->TaskReg.Modern)
807 {
808 OldTss.Cr3 = State->ControlRegisters[FAST486_REG_CR3];
809 OldTss.Eip = State->InstPtr.Long;
810 OldTss.Eflags = State->Flags.Long;
811 OldTss.Eax = State->GeneralRegs[FAST486_REG_EAX].Long;
812 OldTss.Ecx = State->GeneralRegs[FAST486_REG_ECX].Long;
813 OldTss.Edx = State->GeneralRegs[FAST486_REG_EDX].Long;
814 OldTss.Ebx = State->GeneralRegs[FAST486_REG_EBX].Long;
815 OldTss.Esp = State->GeneralRegs[FAST486_REG_ESP].Long;
816 OldTss.Ebp = State->GeneralRegs[FAST486_REG_EBP].Long;
817 OldTss.Esi = State->GeneralRegs[FAST486_REG_ESI].Long;
818 OldTss.Edi = State->GeneralRegs[FAST486_REG_EDI].Long;
819 OldTss.Es = State->SegmentRegs[FAST486_REG_ES].Selector;
820 OldTss.Cs = State->SegmentRegs[FAST486_REG_CS].Selector;
821 OldTss.Ss = State->SegmentRegs[FAST486_REG_SS].Selector;
822 OldTss.Ds = State->SegmentRegs[FAST486_REG_DS].Selector;
823 OldTss.Fs = State->SegmentRegs[FAST486_REG_FS].Selector;
824 OldTss.Gs = State->SegmentRegs[FAST486_REG_GS].Selector;
825 OldTss.Ldtr = State->Ldtr.Selector;
826 }
827 else
828 {
829 OldLegacyTss->Ip = State->InstPtr.LowWord;
830 OldLegacyTss->Flags = State->Flags.LowWord;
831 OldLegacyTss->Ax = State->GeneralRegs[FAST486_REG_EAX].LowWord;
832 OldLegacyTss->Cx = State->GeneralRegs[FAST486_REG_ECX].LowWord;
833 OldLegacyTss->Dx = State->GeneralRegs[FAST486_REG_EDX].LowWord;
834 OldLegacyTss->Bx = State->GeneralRegs[FAST486_REG_EBX].LowWord;
835 OldLegacyTss->Sp = State->GeneralRegs[FAST486_REG_ESP].LowWord;
836 OldLegacyTss->Bp = State->GeneralRegs[FAST486_REG_EBP].LowWord;
837 OldLegacyTss->Si = State->GeneralRegs[FAST486_REG_ESI].LowWord;
838 OldLegacyTss->Di = State->GeneralRegs[FAST486_REG_EDI].LowWord;
839 OldLegacyTss->Es = State->SegmentRegs[FAST486_REG_ES].Selector;
840 OldLegacyTss->Cs = State->SegmentRegs[FAST486_REG_CS].Selector;
841 OldLegacyTss->Ss = State->SegmentRegs[FAST486_REG_SS].Selector;
842 OldLegacyTss->Ds = State->SegmentRegs[FAST486_REG_DS].Selector;
843 OldLegacyTss->Ldtr = State->Ldtr.Selector;
844 }
845
846 /* Write back the old TSS */
847 if (!Fast486WriteLinearMemory(State,
848 State->TaskReg.Base,
849 &OldTss,
850 State->TaskReg.Modern
851 ? sizeof(FAST486_TSS) : sizeof(FAST486_LEGACY_TSS),
852 FALSE))
853 {
854 /* Exception occurred */
855 return FALSE;
856 }
857
858 /* Mark the new task as busy */
859 if (NewTssDescriptor.Signature == FAST486_TSS_SIGNATURE
860 || NewTssDescriptor.Signature == FAST486_BUSY_TSS_SIGNATURE)
861 {
862 /* 32-bit TSS */
863 NewTssDescriptor.Signature = FAST486_BUSY_TSS_SIGNATURE;
864 }
865 else
866 {
867 /* 16-bit TSS */
868 NewTssDescriptor.Signature = FAST486_BUSY_TSS_16_SIGNATURE;
869 }
870
871 /* Write back the new TSS descriptor */
872 if (!Fast486WriteLinearMemory(State,
873 State->Gdtr.Address + GET_SEGMENT_INDEX(Selector),
874 &NewTssDescriptor,
875 sizeof(NewTssDescriptor),
876 FALSE))
877 {
878 /* Exception occurred */
879 return FALSE;
880 }
881
882 /* Set the task switch bit */
883 State->ControlRegisters[FAST486_REG_CR0] |= FAST486_CR0_TS;
884
885 /* Load the task register with the new values */
886 State->TaskReg.Selector = Selector;
887 State->TaskReg.Base = NewTssAddress;
888 State->TaskReg.Limit = NewTssLimit;
889 State->TaskReg.Modern = (NewTssDescriptor.Signature == FAST486_BUSY_TSS_SIGNATURE);
890
891 if (NewTssDescriptor.Signature == FAST486_BUSY_TSS_SIGNATURE)
892 {
893 /* Change the page directory */
894 State->ControlRegisters[FAST486_REG_CR3] = NewTss.Cr3;
895 }
896
897 /* Flush the TLB */
898 Fast486FlushTlb(State);
899
900 /* Update the CPL */
901 if (NewTssDescriptor.Signature == FAST486_BUSY_TSS_SIGNATURE)
902 {
903 State->Cpl = GET_SEGMENT_RPL(NewTss.Cs);
904 }
905 else
906 {
907 State->Cpl = GET_SEGMENT_RPL(NewLegacyTss->Cs);
908 }
909
910#ifndef FAST486_NO_PREFETCH
911 /* Context switching invalidates the prefetch */
912 State->PrefetchValid = FALSE;
913#endif
914
915 /* Load the registers */
916 if (NewTssDescriptor.Signature == FAST486_BUSY_TSS_SIGNATURE)
917 {
918 State->InstPtr.Long = State->SavedInstPtr.Long = NewTss.Eip;
919 State->Flags.Long = NewTss.Eflags;
920 State->GeneralRegs[FAST486_REG_EAX].Long = NewTss.Eax;
921 State->GeneralRegs[FAST486_REG_ECX].Long = NewTss.Ecx;
922 State->GeneralRegs[FAST486_REG_EDX].Long = NewTss.Edx;
923 State->GeneralRegs[FAST486_REG_EBX].Long = NewTss.Ebx;
924 State->GeneralRegs[FAST486_REG_EBP].Long = NewTss.Ebp;
925 State->GeneralRegs[FAST486_REG_ESI].Long = NewTss.Esi;
926 State->GeneralRegs[FAST486_REG_EDI].Long = NewTss.Edi;
927 NewEs = NewTss.Es;
928 NewCs = NewTss.Cs;
929 NewDs = NewTss.Ds;
930 NewLdtr = NewTss.Ldtr;
931
932 if (Type == FAST486_TASK_CALL && State->Cpl < 3)
933 {
934 switch (State->Cpl)
935 {
936 case 0:
937 {
938 State->GeneralRegs[FAST486_REG_ESP].Long = NewTss.Esp0;
939 NewSs = NewTss.Ss0;
940 break;
941 }
942
943 case 1:
944 {
945 State->GeneralRegs[FAST486_REG_ESP].Long = NewTss.Esp1;
946 NewSs = NewTss.Ss1;
947 break;
948 }
949
950 case 2:
951 {
952 State->GeneralRegs[FAST486_REG_ESP].Long = NewTss.Esp2;
953 NewSs = NewTss.Ss2;
954 break;
955 }
956 }
957 }
958 else
959 {
960 State->GeneralRegs[FAST486_REG_ESP].Long = NewTss.Esp;
961 NewSs = NewTss.Ss;
962 }
963 }
964 else
965 {
966 State->InstPtr.LowWord = State->SavedInstPtr.LowWord = NewLegacyTss->Ip;
967 State->Flags.LowWord = NewLegacyTss->Flags;
968 State->GeneralRegs[FAST486_REG_EAX].LowWord = NewLegacyTss->Ax;
969 State->GeneralRegs[FAST486_REG_ECX].LowWord = NewLegacyTss->Cx;
970 State->GeneralRegs[FAST486_REG_EDX].LowWord = NewLegacyTss->Dx;
971 State->GeneralRegs[FAST486_REG_EBX].LowWord = NewLegacyTss->Bx;
972 State->GeneralRegs[FAST486_REG_EBP].LowWord = NewLegacyTss->Bp;
973 State->GeneralRegs[FAST486_REG_ESI].LowWord = NewLegacyTss->Si;
974 State->GeneralRegs[FAST486_REG_EDI].LowWord = NewLegacyTss->Di;
975 NewEs = NewLegacyTss->Es;
976 NewCs = NewLegacyTss->Cs;
977 NewDs = NewLegacyTss->Ds;
978 NewLdtr = NewLegacyTss->Ldtr;
979
980 if (Type == FAST486_TASK_CALL && State->Cpl < 3)
981 {
982 switch (State->Cpl)
983 {
984 case 0:
985 {
986 State->GeneralRegs[FAST486_REG_ESP].Long = NewLegacyTss->Sp0;
987 NewSs = NewLegacyTss->Ss0;
988 break;
989 }
990
991 case 1:
992 {
993 State->GeneralRegs[FAST486_REG_ESP].Long = NewLegacyTss->Sp1;
994 NewSs = NewLegacyTss->Ss1;
995 break;
996 }
997
998 case 2:
999 {
1000 State->GeneralRegs[FAST486_REG_ESP].Long = NewLegacyTss->Sp2;
1001 NewSs = NewLegacyTss->Ss2;
1002 break;
1003 }
1004 }
1005 }
1006 else
1007 {
1008 State->GeneralRegs[FAST486_REG_ESP].Long = NewLegacyTss->Sp;
1009 NewSs = NewLegacyTss->Ss;
1010 }
1011 }
1012
1013 /* Set the NT flag if nesting */
1014 if (Type == FAST486_TASK_CALL) State->Flags.Nt = TRUE;
1015
1016 if (GET_SEGMENT_INDEX(NewLdtr) != 0)
1017 {
1018 BOOLEAN Valid;
1019 FAST486_SYSTEM_DESCRIPTOR GdtEntry;
1020
1021 if (NewLdtr & SEGMENT_TABLE_INDICATOR)
1022 {
1023 /* This selector doesn't point to the GDT */
1024 Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_TS, NewLdtr);
1025 return FALSE;
1026 }
1027
1028 if (!Fast486ReadDescriptorEntry(State, NewLdtr, &Valid, (PFAST486_GDT_ENTRY)&GdtEntry))
1029 {
1030 /* Exception occurred */
1031 return FALSE;
1032 }
1033
1034 if (!Valid)
1035 {
1036 /* Invalid selector */
1037 Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_TS, NewLdtr);
1038 return FALSE;
1039 }
1040
1041 if (GdtEntry.Signature != FAST486_LDT_SIGNATURE)
1042 {
1043 /* This is not an LDT descriptor */
1044 Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_TS, NewLdtr);
1045 return FALSE;
1046 }
1047
1048 if (!GdtEntry.Present)
1049 {
1050 Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_TS, NewLdtr);
1051 return FALSE;
1052 }
1053
1054 /* Update the LDTR */
1055 State->Ldtr.Selector = NewLdtr;
1056 State->Ldtr.Base = GdtEntry.Base | (GdtEntry.BaseMid << 16) | (GdtEntry.BaseHigh << 24);
1057 State->Ldtr.Limit = GdtEntry.Limit | (GdtEntry.LimitHigh << 16);
1058
1059 if (GdtEntry.Granularity)
1060 {
1061 State->Ldtr.Limit <<= 12;
1062 State->Ldtr.Limit |= 0x00000FFF;
1063 }
1064 }
1065 else
1066 {
1067 /* The LDT of this task is empty */
1068 RtlZeroMemory(&State->Ldtr, sizeof(State->Ldtr));
1069 }
1070
1071 /* Load the new segments */
1072 if (!Fast486LoadSegmentInternal(State, FAST486_REG_CS, NewCs, FAST486_EXCEPTION_TS))
1073 {
1074 return FALSE;
1075 }
1076
1077 if (!Fast486LoadSegmentInternal(State, FAST486_REG_SS, NewSs, FAST486_EXCEPTION_TS))
1078 {
1079 return FALSE;
1080 }
1081
1082 if (!Fast486LoadSegmentInternal(State, FAST486_REG_ES, NewEs, FAST486_EXCEPTION_TS))
1083 {
1084 return FALSE;
1085 }
1086
1087 if (!Fast486LoadSegmentInternal(State, FAST486_REG_DS, NewDs, FAST486_EXCEPTION_TS))
1088 {
1089 return FALSE;
1090 }
1091
1092 if (NewTssDescriptor.Signature == FAST486_BUSY_TSS_SIGNATURE)
1093 {
1094 if (!Fast486LoadSegmentInternal(State,
1095 FAST486_REG_FS,
1096 NewTss.Fs,
1097 FAST486_EXCEPTION_TS))
1098 {
1099 return FALSE;
1100 }
1101
1102 if (!Fast486LoadSegmentInternal(State,
1103 FAST486_REG_GS,
1104 NewTss.Gs,
1105 FAST486_EXCEPTION_TS))
1106 {
1107 return FALSE;
1108 }
1109 }
1110
1111 return TRUE;
1112}
Type
Definition: Type.h:7
#define FAST486_BUSY_TSS_16_SIGNATURE
Definition: fast486.h:87
#define FAST486_TSS_SIGNATURE
Definition: fast486.h:92
#define FAST486_TSS_16_SIGNATURE
Definition: fast486.h:85
#define FAST486_LDT_SIGNATURE
Definition: fast486.h:86
#define FAST486_BUSY_TSS_SIGNATURE
Definition: fast486.h:93
#define FAST486_CR0_TS
Definition: fast486.h:49
#define LOWORD(l)
Definition: pedump.c:82
#define GET_SEGMENT_RPL(s)
Definition: common.h:38
#define GET_SEGMENT_INDEX(s)
Definition: common.h:39
#define SEGMENT_TABLE_INDICATOR
Definition: common.h:40
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262

Referenced by FAST486_OPCODE_HANDLER(), and Fast486InterruptInternal().

◆ Fast486WriteMemory()

BOOLEAN FASTCALL Fast486WriteMemory ( PFAST486_STATE  State,
FAST486_SEG_REGS  SegmentReg,
ULONG  Offset,
PVOID  Buffer,
ULONG  Size 
)

Definition at line 163 of file common.c.

168{
169 ULONG LinearAddress;
170 PFAST486_SEG_REG CachedDescriptor;
171 FAST486_EXCEPTIONS Exception = SegmentReg != FAST486_REG_SS
172 ? FAST486_EXCEPTION_GP : FAST486_EXCEPTION_SS;
173
174 ASSERT(SegmentReg < FAST486_NUM_SEG_REGS);
175
176 /* Get the cached descriptor */
177 CachedDescriptor = &State->SegmentRegs[SegmentReg];
178
179 if (CachedDescriptor->Executable || !CachedDescriptor->DirConf)
180 {
181 if ((Offset + Size - 1) > CachedDescriptor->Limit)
182 {
183 /* Write beyond limit */
184 Fast486Exception(State, Exception);
185 return FALSE;
186 }
187 }
188 else
189 {
190 if (Offset < CachedDescriptor->Limit)
191 {
192 /* Write beyond limit */
193 Fast486Exception(State, Exception);
194 return FALSE;
195 }
196 }
197
198 /* Check for protected mode */
199 if ((State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) && !State->Flags.Vm)
200 {
201 /* Privilege checks */
202
203 if (!CachedDescriptor->Present)
204 {
205 Fast486Exception(State, Exception);
206 return FALSE;
207 }
208
209 if ((CachedDescriptor->Rpl > CachedDescriptor->Dpl)
210 || (Fast486GetCurrentPrivLevel(State) > CachedDescriptor->Dpl))
211 {
212 Fast486Exception(State, Exception);
213 return FALSE;
214 }
215
216 if (CachedDescriptor->Executable)
217 {
218 /* Code segment not writable */
219 Fast486Exception(State, Exception);
220 return FALSE;
221 }
222 else if (!CachedDescriptor->ReadWrite)
223 {
224 /* Data segment not writeable */
225 Fast486Exception(State, Exception);
226 return FALSE;
227 }
228 }
229
230 /* Find the linear address */
231 LinearAddress = CachedDescriptor->Base + Offset;
232
233#ifndef FAST486_NO_PREFETCH
234 if (State->PrefetchValid
235 && (LinearAddress >= State->PrefetchAddress)
236 && ((LinearAddress + Size) <= (State->PrefetchAddress + FAST486_CACHE_SIZE)))
237 {
238 /* Update the prefetch */
239 RtlMoveMemory(&State->PrefetchCache[LinearAddress - State->PrefetchAddress],
240 Buffer,
241 min(Size, FAST486_CACHE_SIZE + State->PrefetchAddress - LinearAddress));
242 }
243#endif
244
245 /* Write to the linear address */
246 return Fast486WriteLinearMemory(State, LinearAddress, Buffer, Size, TRUE);
247}
#define min(a, b)
Definition: monoChain.cc:55

Referenced by FAST486_OPCODE_HANDLER(), and Fast486FpuSaveEnvironment().