2 * Fast486 386/486 CPU Emulation Library
5 * Copyright (C) 2014 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 /* INCLUDES *******************************************************************/
32 /* PUBLIC FUNCTIONS ***********************************************************/
35 Fast486ReadMemory(PFAST486_STATE State
,
36 FAST486_SEG_REGS SegmentReg
,
43 PFAST486_SEG_REG CachedDescriptor
;
45 ASSERT(SegmentReg
< FAST486_NUM_SEG_REGS
);
47 /* Get the cached descriptor */
48 CachedDescriptor
= &State
->SegmentRegs
[SegmentReg
];
50 if ((Offset
+ Size
- 1) > CachedDescriptor
->Limit
)
52 /* Read beyond limit */
53 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
57 /* Check for protected mode */
58 if (State
->ControlRegisters
[FAST486_REG_CR0
] & FAST486_CR0_PE
)
60 /* Privilege checks */
62 if (!CachedDescriptor
->Present
)
64 Fast486Exception(State
, FAST486_EXCEPTION_NP
);
68 if ((!InstFetch
&& (CachedDescriptor
->Rpl
> CachedDescriptor
->Dpl
))
69 || (Fast486GetCurrentPrivLevel(State
) > CachedDescriptor
->Dpl
))
71 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
77 if (!CachedDescriptor
->Executable
)
79 /* Data segment not executable */
80 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
86 if (CachedDescriptor
->Executable
&& (!CachedDescriptor
->ReadWrite
))
88 /* Code segment not readable */
89 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
95 /* Find the linear address */
96 LinearAddress
= CachedDescriptor
->Base
+ Offset
;
98 #ifndef FAST486_NO_PREFETCH
99 if (InstFetch
&& ((Offset
+ FAST486_CACHE_SIZE
- 1) <= CachedDescriptor
->Limit
))
101 State
->PrefetchAddress
= LinearAddress
;
103 if ((State
->ControlRegisters
[FAST486_REG_CR0
] & FAST486_CR0_PG
)
104 && (PAGE_OFFSET(State
->PrefetchAddress
) > (FAST486_PAGE_SIZE
- FAST486_CACHE_SIZE
)))
106 /* We mustn't prefetch across a page boundary */
107 State
->PrefetchAddress
= PAGE_ALIGN(State
->PrefetchAddress
)
108 | (FAST486_PAGE_SIZE
- FAST486_CACHE_SIZE
);
110 if ((LinearAddress
- State
->PrefetchAddress
+ Size
) >= FAST486_CACHE_SIZE
)
112 /* We can't prefetch without possibly violating page permissions */
113 State
->PrefetchValid
= FALSE
;
114 return Fast486ReadLinearMemory(State
, LinearAddress
, Buffer
, Size
);
119 if (Fast486ReadLinearMemory(State
,
120 State
->PrefetchAddress
,
121 State
->PrefetchCache
,
124 State
->PrefetchValid
= TRUE
;
126 RtlMoveMemory(Buffer
,
127 &State
->PrefetchCache
[LinearAddress
- State
->PrefetchAddress
],
133 State
->PrefetchValid
= FALSE
;
140 /* Read from the linear address */
141 return Fast486ReadLinearMemory(State
, LinearAddress
, Buffer
, Size
);
146 Fast486WriteMemory(PFAST486_STATE State
,
147 FAST486_SEG_REGS SegmentReg
,
153 PFAST486_SEG_REG CachedDescriptor
;
155 ASSERT(SegmentReg
< FAST486_NUM_SEG_REGS
);
157 /* Get the cached descriptor */
158 CachedDescriptor
= &State
->SegmentRegs
[SegmentReg
];
160 if ((Offset
+ Size
- 1) > CachedDescriptor
->Limit
)
162 /* Write beyond limit */
163 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
167 /* Check for protected mode */
168 if (State
->ControlRegisters
[FAST486_REG_CR0
] & FAST486_CR0_PE
)
170 /* Privilege checks */
172 if (!CachedDescriptor
->Present
)
174 Fast486Exception(State
, FAST486_EXCEPTION_NP
);
178 if ((CachedDescriptor
->Rpl
> CachedDescriptor
->Dpl
)
179 || (Fast486GetCurrentPrivLevel(State
) > CachedDescriptor
->Dpl
))
181 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
185 if (CachedDescriptor
->Executable
)
187 /* Code segment not writable */
188 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
191 else if (!CachedDescriptor
->ReadWrite
)
193 /* Data segment not writeable */
194 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
199 /* Find the linear address */
200 LinearAddress
= CachedDescriptor
->Base
+ Offset
;
202 #ifndef FAST486_NO_PREFETCH
203 if (State
->PrefetchValid
204 && (LinearAddress
>= State
->PrefetchAddress
)
205 && ((LinearAddress
+ Size
) <= (State
->PrefetchAddress
+ FAST486_CACHE_SIZE
)))
207 /* Update the prefetch */
208 RtlMoveMemory(&State
->PrefetchCache
[LinearAddress
- State
->PrefetchAddress
],
210 min(Size
, FAST486_CACHE_SIZE
+ State
->PrefetchAddress
- LinearAddress
));
214 /* Write to the linear address */
215 return Fast486WriteLinearMemory(State
, LinearAddress
, Buffer
, Size
);
218 static inline BOOLEAN
220 Fast486GetIntVector(PFAST486_STATE State
,
222 PFAST486_IDT_ENTRY IdtEntry
)
224 /* Check for protected mode */
225 if (State
->ControlRegisters
[FAST486_REG_CR0
] & FAST486_CR0_PE
)
227 /* Read from the IDT */
228 if (!Fast486ReadLinearMemory(State
,
230 + Number
* sizeof(*IdtEntry
),
234 /* Exception occurred */
240 /* Read from the real-mode IVT */
243 /* Paging is always disabled in real mode */
244 State
->MemReadCallback(State
,
246 + Number
* sizeof(FarPointer
),
250 /* Fill a fake IDT entry */
251 IdtEntry
->Offset
= LOWORD(FarPointer
);
252 IdtEntry
->Selector
= HIWORD(FarPointer
);
254 IdtEntry
->Type
= FAST486_IDT_INT_GATE
;
255 IdtEntry
->Storage
= FALSE
;
257 IdtEntry
->Present
= TRUE
;
258 IdtEntry
->OffsetHigh
= 0;
264 static inline BOOLEAN
266 Fast486InterruptInternal(PFAST486_STATE State
,
267 PFAST486_IDT_ENTRY IdtEntry
)
269 USHORT SegmentSelector
= IdtEntry
->Selector
;
270 ULONG Offset
= MAKELONG(IdtEntry
->Offset
, IdtEntry
->OffsetHigh
);
271 ULONG GateType
= IdtEntry
->Type
;
272 BOOLEAN GateSize
= (GateType
== FAST486_IDT_INT_GATE_32
) ||
273 (GateType
== FAST486_IDT_TRAP_GATE_32
);
275 BOOLEAN Success
= FALSE
;
276 ULONG OldPrefixFlags
= State
->PrefixFlags
;
278 /* Check for protected mode */
279 if (State
->ControlRegisters
[FAST486_REG_CR0
] & FAST486_CR0_PE
)
282 USHORT OldSs
= State
->SegmentRegs
[FAST486_REG_SS
].Selector
;
283 ULONG OldEsp
= State
->GeneralRegs
[FAST486_REG_ESP
].Long
;
285 if (GateType
== FAST486_TASK_GATE_SIGNATURE
)
288 return Fast486TaskSwitch(State
, FAST486_TASK_CALL
, IdtEntry
->Selector
);
291 if (GateSize
!= (State
->SegmentRegs
[FAST486_REG_CS
].Size
))
293 /* The gate size doesn't match the current operand size, so set the OPSIZE flag. */
294 State
->PrefixFlags
|= FAST486_PREFIX_OPSIZE
;
297 /* Check if the interrupt handler is more privileged or if we're in V86 mode */
298 if ((Fast486GetCurrentPrivLevel(State
) > GET_SEGMENT_RPL(SegmentSelector
))
302 if (!Fast486ReadLinearMemory(State
,
307 /* Exception occurred */
311 /* Switch to the new privilege level */
312 State
->Cpl
= GET_SEGMENT_RPL(SegmentSelector
);
316 /* Clear the VM flag */
317 State
->Flags
.Vm
= FALSE
;
319 /* Push GS, FS, DS and ES */
320 if (!Fast486StackPush(State
, State
->SegmentRegs
[FAST486_REG_GS
].Selector
)) goto Cleanup
;
321 if (!Fast486StackPush(State
, State
->SegmentRegs
[FAST486_REG_FS
].Selector
)) goto Cleanup
;
322 if (!Fast486StackPush(State
, State
->SegmentRegs
[FAST486_REG_DS
].Selector
)) goto Cleanup
;
323 if (!Fast486StackPush(State
, State
->SegmentRegs
[FAST486_REG_ES
].Selector
)) goto Cleanup
;
325 /* Now load them with NULL selectors, since they are useless in protected mode */
326 if (!Fast486LoadSegment(State
, FAST486_REG_GS
, 0)) goto Cleanup
;
327 if (!Fast486LoadSegment(State
, FAST486_REG_FS
, 0)) goto Cleanup
;
328 if (!Fast486LoadSegment(State
, FAST486_REG_DS
, 0)) goto Cleanup
;
329 if (!Fast486LoadSegment(State
, FAST486_REG_ES
, 0)) goto Cleanup
;
332 /* Check the new (higher) privilege level */
337 if (!Fast486LoadSegment(State
, FAST486_REG_SS
, Tss
.Ss0
))
339 /* Exception occurred */
342 State
->GeneralRegs
[FAST486_REG_ESP
].Long
= Tss
.Esp0
;
349 if (!Fast486LoadSegment(State
, FAST486_REG_SS
, Tss
.Ss1
))
351 /* Exception occurred */
354 State
->GeneralRegs
[FAST486_REG_ESP
].Long
= Tss
.Esp1
;
361 if (!Fast486LoadSegment(State
, FAST486_REG_SS
, Tss
.Ss2
))
363 /* Exception occurred */
366 State
->GeneralRegs
[FAST486_REG_ESP
].Long
= Tss
.Esp2
;
373 /* Should never reach here! */
378 /* Push SS selector */
379 if (!Fast486StackPush(State
, OldSs
)) goto Cleanup
;
381 /* Push stack pointer */
382 if (!Fast486StackPush(State
, OldEsp
)) goto Cleanup
;
387 if (State
->SegmentRegs
[FAST486_REG_CS
].Size
)
389 /* Set OPSIZE, because INT always pushes 16-bit values in real mode */
390 State
->PrefixFlags
|= FAST486_PREFIX_OPSIZE
;
395 if (!Fast486StackPush(State
, State
->Flags
.Long
)) goto Cleanup
;
397 /* Push CS selector */
398 if (!Fast486StackPush(State
, State
->SegmentRegs
[FAST486_REG_CS
].Selector
)) goto Cleanup
;
400 /* Push the instruction pointer */
401 if (!Fast486StackPush(State
, State
->InstPtr
.Long
)) goto Cleanup
;
403 if ((GateType
== FAST486_IDT_INT_GATE
) || (GateType
== FAST486_IDT_INT_GATE_32
))
405 /* Disable interrupts after a jump to an interrupt gate handler */
406 State
->Flags
.If
= FALSE
;
410 if (!Fast486LoadSegment(State
, FAST486_REG_CS
, SegmentSelector
))
412 /* An exception occurred during the jump */
418 /* 32-bit code segment, use EIP */
419 State
->InstPtr
.Long
= Offset
;
423 /* 16-bit code segment, use IP */
424 State
->InstPtr
.LowWord
= LOWORD(Offset
);
430 /* Restore the prefix flags */
431 State
->PrefixFlags
= OldPrefixFlags
;
438 Fast486PerformInterrupt(PFAST486_STATE State
,
441 FAST486_IDT_ENTRY IdtEntry
;
443 /* Get the interrupt vector */
444 if (!Fast486GetIntVector(State
, Number
, &IdtEntry
))
446 /* Exception occurred */
450 /* Perform the interrupt */
451 if (!Fast486InterruptInternal(State
, &IdtEntry
))
453 /* Exception occurred */
462 Fast486ExceptionWithErrorCode(PFAST486_STATE State
,
463 FAST486_EXCEPTIONS ExceptionCode
,
466 /* Increment the exception count */
467 State
->ExceptionCount
++;
469 /* Check if the exception occurred more than once */
470 if (State
->ExceptionCount
> 1)
472 /* Then this is a double fault */
473 ExceptionCode
= FAST486_EXCEPTION_DF
;
476 /* Check if this is a triple fault */
477 if (State
->ExceptionCount
== 3)
479 DPRINT("Fast486ExceptionWithErrorCode(%04X:%08X) -- Triple fault\n",
480 State
->SegmentRegs
[FAST486_REG_CS
].Selector
,
481 State
->InstPtr
.Long
);
488 /* Clear the prefix flags */
489 State
->PrefixFlags
= 0;
491 /* Restore the IP to the saved IP */
492 State
->InstPtr
= State
->SavedInstPtr
;
494 /* Perform the interrupt */
495 if (!Fast486PerformInterrupt(State
, ExceptionCode
))
498 * If this function failed, that means Fast486Exception
499 * was called again, so just return in this case.
504 if (EXCEPTION_HAS_ERROR_CODE(ExceptionCode
)
505 && (State
->ControlRegisters
[FAST486_REG_CR0
] & FAST486_CR0_PE
))
507 /* Push the error code */
508 if (!Fast486StackPush(State
, ErrorCode
))
511 * If this function failed, that means Fast486Exception
512 * was called again, so just return in this case.
518 /* Reset the exception count */
519 State
->ExceptionCount
= 0;
524 Fast486TaskSwitch(PFAST486_STATE State
, FAST486_TASK_SWITCH_TYPE Type
, USHORT Selector
)
530 FAST486_SYSTEM_DESCRIPTOR NewTssDescriptor
;
532 /* Read the old TSS */
533 if (!Fast486ReadLinearMemory(State
,
538 /* Exception occurred */
542 /* If this is a task return, use the linked previous selector */
543 if (Type
== FAST486_TASK_RETURN
) Selector
= LOWORD(OldTss
.Link
);
545 /* Make sure the entry exists in the GDT (not LDT!) */
546 if ((GET_SEGMENT_INDEX(Selector
) == 0)
547 || (Selector
& SEGMENT_TABLE_INDICATOR
)
548 || GET_SEGMENT_INDEX(Selector
) >= (State
->Gdtr
.Size
+ 1))
550 Fast486ExceptionWithErrorCode(State
, FAST486_EXCEPTION_TS
, Selector
);
554 /* Get the TSS descriptor from the GDT */
555 if (!Fast486ReadLinearMemory(State
,
556 State
->Gdtr
.Address
+ GET_SEGMENT_INDEX(Selector
),
558 sizeof(NewTssDescriptor
)))
560 /* Exception occurred */
564 if (!NewTssDescriptor
.Present
)
566 /* Incoming task TSS not present */
567 Fast486ExceptionWithErrorCode(State
, FAST486_EXCEPTION_NP
, Selector
);
571 /* Calculate the linear address of the new TSS */
572 NewTssAddress
= NewTssDescriptor
.Base
;
573 NewTssAddress
|= NewTssDescriptor
.BaseMid
<< 16;
574 NewTssAddress
|= NewTssDescriptor
.BaseHigh
<< 24;
576 /* Calculate the limit of the new TSS */
577 NewTssLimit
= NewTssDescriptor
.Limit
| (NewTssDescriptor
.LimitHigh
<< 16);
579 if (NewTssDescriptor
.Granularity
)
582 NewTssLimit
|= 0x00000FFF;
585 if (NewTssLimit
< sizeof(FAST486_TSS
))
587 /* TSS limit too small */
588 Fast486ExceptionWithErrorCode(State
, FAST486_EXCEPTION_TS
, Selector
);
593 * The incoming task shouldn't be busy if we're executing it as a
594 * new task, and it should be busy if we're returning to it.
596 if (((NewTssDescriptor
.Signature
!= FAST486_TSS_SIGNATURE
)
597 || (Type
== FAST486_TASK_RETURN
))
598 && ((NewTssDescriptor
.Signature
!= FAST486_BUSY_TSS_SIGNATURE
)
599 || (Type
!= FAST486_TASK_RETURN
)))
601 Fast486ExceptionWithErrorCode(State
, FAST486_EXCEPTION_GP
, Selector
);
605 /* Read the new TSS */
606 if (!Fast486ReadLinearMemory(State
,
611 /* Exception occurred */
615 if (Type
!= FAST486_TASK_CALL
)
617 /* Clear the busy bit of the outgoing task */
618 FAST486_SYSTEM_DESCRIPTOR OldTssDescriptor
;
620 if (!Fast486ReadLinearMemory(State
,
622 + GET_SEGMENT_INDEX(State
->TaskReg
.Selector
),
624 sizeof(OldTssDescriptor
)))
626 /* Exception occurred */
630 OldTssDescriptor
.Signature
= FAST486_TSS_SIGNATURE
;
632 if (!Fast486WriteLinearMemory(State
,
634 + GET_SEGMENT_INDEX(State
->TaskReg
.Selector
),
636 sizeof(OldTssDescriptor
)))
638 /* Exception occurred */
645 NewTss
.Link
= State
->TaskReg
.Selector
;
648 /* Save the current task into the TSS */
649 OldTss
.Cr3
= State
->ControlRegisters
[FAST486_REG_CR3
];
650 OldTss
.Eip
= State
->InstPtr
.Long
;
651 OldTss
.Eflags
= State
->Flags
.Long
;
652 OldTss
.Eax
= State
->GeneralRegs
[FAST486_REG_EAX
].Long
;
653 OldTss
.Ecx
= State
->GeneralRegs
[FAST486_REG_ECX
].Long
;
654 OldTss
.Edx
= State
->GeneralRegs
[FAST486_REG_EDX
].Long
;
655 OldTss
.Ebx
= State
->GeneralRegs
[FAST486_REG_EBX
].Long
;
656 OldTss
.Esp
= State
->GeneralRegs
[FAST486_REG_ESP
].Long
;
657 OldTss
.Ebp
= State
->GeneralRegs
[FAST486_REG_EBP
].Long
;
658 OldTss
.Esi
= State
->GeneralRegs
[FAST486_REG_ESI
].Long
;
659 OldTss
.Edi
= State
->GeneralRegs
[FAST486_REG_EDI
].Long
;
660 OldTss
.Es
= State
->SegmentRegs
[FAST486_REG_ES
].Selector
;
661 OldTss
.Cs
= State
->SegmentRegs
[FAST486_REG_CS
].Selector
;
662 OldTss
.Ss
= State
->SegmentRegs
[FAST486_REG_SS
].Selector
;
663 OldTss
.Ds
= State
->SegmentRegs
[FAST486_REG_DS
].Selector
;
664 OldTss
.Fs
= State
->SegmentRegs
[FAST486_REG_FS
].Selector
;
665 OldTss
.Gs
= State
->SegmentRegs
[FAST486_REG_GS
].Selector
;
666 OldTss
.Ldtr
= State
->Ldtr
.Selector
;
668 /* Write back the old TSS */
669 if (!Fast486WriteLinearMemory(State
,
674 /* Exception occurred */
678 /* Mark the new task as busy */
679 NewTssDescriptor
.Signature
= FAST486_BUSY_TSS_SIGNATURE
;
681 /* Write back the new TSS descriptor */
682 if (!Fast486WriteLinearMemory(State
,
683 State
->Gdtr
.Address
+ GET_SEGMENT_INDEX(Selector
),
685 sizeof(NewTssDescriptor
)))
687 /* Exception occurred */
691 /* Set the task switch bit */
692 State
->ControlRegisters
[FAST486_REG_CR0
] |= FAST486_CR0_TS
;
694 /* Load the task register with the new values */
695 State
->TaskReg
.Selector
= Selector
;
696 State
->TaskReg
.Base
= NewTssAddress
;
697 State
->TaskReg
.Limit
= NewTssLimit
;
699 /* Change the page directory */
700 State
->ControlRegisters
[FAST486_REG_CR3
] = NewTss
.Cr3
;
703 if (State
->Tlb
) RtlZeroMemory(State
->Tlb
, NUM_TLB_ENTRIES
* sizeof(ULONG
));
705 #ifndef FAST486_NO_PREFETCH
706 /* Context switching invalidates the prefetch */
707 State
->PrefetchValid
= FALSE
;
710 /* Load the registers */
711 State
->InstPtr
.Long
= State
->SavedInstPtr
.Long
= NewTss
.Eip
;
712 State
->Flags
.Long
= NewTss
.Eflags
;
713 State
->GeneralRegs
[FAST486_REG_EAX
].Long
= NewTss
.Eax
;
714 State
->GeneralRegs
[FAST486_REG_ECX
].Long
= NewTss
.Ecx
;
715 State
->GeneralRegs
[FAST486_REG_EDX
].Long
= NewTss
.Edx
;
716 State
->GeneralRegs
[FAST486_REG_EBX
].Long
= NewTss
.Ebx
;
717 State
->GeneralRegs
[FAST486_REG_ESP
].Long
= NewTss
.Esp
;
718 State
->GeneralRegs
[FAST486_REG_EBP
].Long
= NewTss
.Ebp
;
719 State
->GeneralRegs
[FAST486_REG_ESI
].Long
= NewTss
.Esi
;
720 State
->GeneralRegs
[FAST486_REG_EDI
].Long
= NewTss
.Edi
;
722 /* Set the NT flag if nesting */
723 if (Type
== FAST486_TASK_CALL
) State
->Flags
.Nt
= TRUE
;
725 if (GET_SEGMENT_INDEX(NewTss
.Ldtr
) != 0)
728 FAST486_SYSTEM_DESCRIPTOR GdtEntry
;
730 if (NewTss
.Ldtr
& SEGMENT_TABLE_INDICATOR
)
732 /* This selector doesn't point to the GDT */
733 Fast486ExceptionWithErrorCode(State
, FAST486_EXCEPTION_TS
, NewTss
.Ldtr
);
737 if (!Fast486ReadDescriptorEntry(State
,
740 (PFAST486_GDT_ENTRY
)&GdtEntry
))
742 /* Exception occurred */
748 /* Invalid selector */
749 Fast486ExceptionWithErrorCode(State
, FAST486_EXCEPTION_TS
, NewTss
.Ldtr
);
753 if (GdtEntry
.Signature
!= FAST486_LDT_SIGNATURE
)
755 /* This is not an LDT descriptor */
756 Fast486ExceptionWithErrorCode(State
, FAST486_EXCEPTION_TS
, NewTss
.Ldtr
);
760 if (!GdtEntry
.Present
)
762 Fast486ExceptionWithErrorCode(State
, FAST486_EXCEPTION_TS
, NewTss
.Ldtr
);
766 /* Update the LDTR */
767 State
->Ldtr
.Selector
= NewTss
.Ldtr
;
768 State
->Ldtr
.Base
= GdtEntry
.Base
| (GdtEntry
.BaseMid
<< 16) | (GdtEntry
.BaseHigh
<< 24);
769 State
->Ldtr
.Limit
= GdtEntry
.Limit
| (GdtEntry
.LimitHigh
<< 16);
771 if (GdtEntry
.Granularity
)
773 State
->Ldtr
.Limit
<<= 12;
774 State
->Ldtr
.Limit
|= 0x00000FFF;
779 /* The LDT of this task is empty */
780 RtlZeroMemory(&State
->Ldtr
, sizeof(State
->Ldtr
));
783 /* Load the new segments */
784 if (!Fast486LoadSegmentInternal(State
,
787 FAST486_EXCEPTION_TS
))
792 if (!Fast486LoadSegmentInternal(State
,
795 FAST486_EXCEPTION_TS
))
800 if (!Fast486LoadSegmentInternal(State
,
803 FAST486_EXCEPTION_TS
))
808 if (!Fast486LoadSegmentInternal(State
,
811 FAST486_EXCEPTION_TS
))
816 if (!Fast486LoadSegmentInternal(State
,
819 FAST486_EXCEPTION_TS
))
824 if (!Fast486LoadSegmentInternal(State
,
827 FAST486_EXCEPTION_TS
))