}
if(fault) *fault = true;
- if(reg == SS)
- {
- I386_SREG stack;
-
- memset(&stack, 0, sizeof(stack));
- stack.selector = selector;
- i386_load_protected_mode_segment(cpustate,&stack,NULL);
- DPL = (stack.flags >> 5) & 0x03;
- //logdebug("SReg load: SELECTOR=%04X FLAGS=%04X BASE=%08X LIMIT=%08X VALID=%s %s\n", stack.selector, stack.flags, stack.base, stack.limit, (stack.valid) ? "YES" : "NO", (stack.d == 0) ? "16bit SP" : "32bit ESP");
- if((selector & ~0x0003) == 0)
+// if(reg == SS)
+ switch(reg) {
+ case SS:
{
- logerror("SReg Load (%08x): Selector is null.\n",cpustate->pc);
- FAULT(FAULT_GP,0)
- }
- if(selector & 0x0004) // LDT
- {
- if((selector & ~0x0007) > cpustate->ldtr.limit)
+ I386_SREG stack;
+
+ memset(&stack, 0, sizeof(stack));
+ stack.selector = selector;
+ i386_load_protected_mode_segment(cpustate,&stack,NULL);
+ DPL = (stack.flags >> 5) & 0x03;
+ //logdebug("SReg load: SELECTOR=%04X FLAGS=%04X BASE=%08X LIMIT=%08X VALID=%s %s\n", stack.selector, stack.flags, stack.base, stack.limit, (stack.valid) ? "YES" : "NO", (stack.d == 0) ? "16bit SP" : "32bit ESP");
+ if((selector & ~0x0003) == 0)
{
- logerror("SReg Load (SS)(%08x): Selector is out of LDT bounds.LDTR.limit=%4X : selector=%04X\n",cpustate->pc, cpustate->ldtr.limit, selector);
- FAULT(FAULT_GP,selector & ~0x03)
+ logerror("SReg Load (%08x): Selector is null.\n",cpustate->pc);
+ FAULT(FAULT_GP,0)
+ }
+ if(selector & 0x0004) // LDT
+ {
+ if((selector & ~0x0007) > cpustate->ldtr.limit)
+ {
+ logerror("SReg Load (SS)(%08x): Selector is out of LDT bounds.LDTR.limit=%4X : selector=%04X\n",cpustate->pc, cpustate->ldtr.limit, selector);
+ FAULT(FAULT_GP,selector & ~0x03)
+ }
}
- }
- else // GDT
- {
- if((selector & ~0x0007) > cpustate->gdtr.limit)
+ else // GDT
{
- logerror("SReg Load (%08x): Selector is out of bounds. GDT GDTR.limit=%04X : %04X\n",cpustate->pc, cpustate->gdtr.limit, selector);
- FAULT(FAULT_GP,selector & ~0x03)
+ if((selector & ~0x0007) > cpustate->gdtr.limit)
+ {
+ logerror("SReg Load (%08x): Selector is out of bounds. GDT GDTR.limit=%04X : %04X\n",cpustate->pc, cpustate->gdtr.limit, selector);
+ FAULT(FAULT_GP,selector & ~0x03)
+ }
}
+ if (RPL != CPL)
+ {
+ logerror("SReg Load (%08x): Selector RPL does not equal CPL.\n",cpustate->pc);
+ FAULT(FAULT_GP,selector & ~0x03)
+ }
+ if(((stack.flags & 0x0018) != 0x10) && (stack.flags & 0x0002) != 0)
+ {
+ logerror("SReg Load (%08x): Segment is not a writable data segment.\n",cpustate->pc);
+ FAULT(FAULT_GP,selector & ~0x03)
+ }
+ if(DPL != CPL)
+ {
+ logerror("SReg Load (%08x): Segment DPL does not equal CPL.\n",cpustate->pc);
+ FAULT(FAULT_GP,selector & ~0x03)
+ }
+ if(!(stack.flags & 0x0080))
+ {
+ logerror("SReg Load (%08x): Segment is not present.\n",cpustate->pc);
+ FAULT(FAULT_SS,selector & ~0x03)
+ }
}
- if (RPL != CPL)
- {
- logerror("SReg Load (%08x): Selector RPL does not equal CPL.\n",cpustate->pc);
- FAULT(FAULT_GP,selector & ~0x03)
- }
- if(((stack.flags & 0x0018) != 0x10) && (stack.flags & 0x0002) != 0)
- {
- logerror("SReg Load (%08x): Segment is not a writable data segment.\n",cpustate->pc);
- FAULT(FAULT_GP,selector & ~0x03)
- }
- if(DPL != CPL)
- {
- logerror("SReg Load (%08x): Segment DPL does not equal CPL.\n",cpustate->pc);
- FAULT(FAULT_GP,selector & ~0x03)
- }
- if(!(stack.flags & 0x0080))
+ break;
+ case DS:
+ case ES:
+ case FS:
+ case GS:
+ //if(reg == DS || reg == ES || reg == FS || reg == GS)
{
- logerror("SReg Load (%08x): Segment is not present.\n",cpustate->pc);
- FAULT(FAULT_SS,selector & ~0x03)
- }
- }
- if(reg == DS || reg == ES || reg == FS || reg == GS)
- {
- I386_SREG desc;
+ I386_SREG desc;
- if((selector & ~0x0003) == 0)
- {
- cpustate->sreg[reg].selector = selector;
- i386_load_segment_descriptor(cpustate, reg );
- if(fault) *fault = false;
- return;
- }
+ if((selector & ~0x0003) == 0)
+ {
+ cpustate->sreg[reg].selector = selector;
+ i386_load_segment_descriptor(cpustate, reg );
+ if(fault) *fault = false;
+ return;
+ }
- memset(&desc, 0, sizeof(desc));
- desc.selector = selector;
- i386_load_protected_mode_segment(cpustate,&desc,NULL);
- DPL = (desc.flags >> 5) & 0x03;
+ memset(&desc, 0, sizeof(desc));
+ desc.selector = selector;
+ i386_load_protected_mode_segment(cpustate,&desc,NULL);
+ DPL = (desc.flags >> 5) & 0x03;
- if(selector & 0x0004) // LDT
- {
- if((selector & ~0x0007) > cpustate->ldtr.limit)
+ if(selector & 0x0004) // LDT
{
- logerror("SReg Load (other SS)(%08x): Selector is out of LDT bounds.LDTR.limit=%04X : %04X\n",cpustate->pc, cpustate->ldtr.limit, selector);
- FAULT(FAULT_GP,selector & ~0x03)
+ if((selector & ~0x0007) > cpustate->ldtr.limit)
+ {
+ logerror("SReg Load (other SS)(%08x): Selector is out of LDT bounds.LDTR.limit=%04X : %04X\n",cpustate->pc, cpustate->ldtr.limit, selector);
+ FAULT(FAULT_GP,selector & ~0x03)
+ }
}
- }
- else // GDT
- {
- if((selector & ~0x0007) > cpustate->gdtr.limit)
+ else // GDT
{
- logerror("SReg Load (%08x): Selector is out of GDT bounds.\n",cpustate->pc);
- FAULT(FAULT_GP,selector & ~0x03)
+ if((selector & ~0x0007) > cpustate->gdtr.limit)
+ {
+ logerror("SReg Load (%08x): Selector is out of GDT bounds.\n",cpustate->pc);
+ FAULT(FAULT_GP,selector & ~0x03)
+ }
}
- }
- if((desc.flags & 0x0018) != 0x10)
- {
- if((((desc.flags & 0x0002) != 0) && ((desc.flags & 0x0018) != 0x18)) || !(desc.flags & 0x10))
+ if((desc.flags & 0x0018) != 0x10)
{
- logerror("SReg Load (%08x): Segment is not a data segment or readable code segment.\n",cpustate->pc);
- FAULT(FAULT_GP,selector & ~0x03)
+ if((((desc.flags & 0x0002) != 0) && ((desc.flags & 0x0018) != 0x18)) || !(desc.flags & 0x10))
+ {
+ logerror("SReg Load (%08x): Segment is not a data segment or readable code segment.\n",cpustate->pc);
+ FAULT(FAULT_GP,selector & ~0x03)
+ }
}
- }
- if(((desc.flags & 0x0018) == 0x10) || ((!(desc.flags & 0x0004)) && ((desc.flags & 0x0018) == 0x18)))
- {
- // if data or non-conforming code segment
- if((RPL > DPL) || (CPL > DPL))
+ if(((desc.flags & 0x0018) == 0x10) || ((!(desc.flags & 0x0004)) && ((desc.flags & 0x0018) == 0x18)))
{
- logerror("SReg Load (%08x): Selector RPL or CPL is not less or equal to segment DPL.\n",cpustate->pc);
- FAULT(FAULT_GP,selector & ~0x03)
+ // if data or non-conforming code segment
+ if((RPL > DPL) || (CPL > DPL))
+ {
+ logerror("SReg Load (%08x): Selector RPL or CPL is not less or equal to segment DPL.\n",cpustate->pc);
+ FAULT(FAULT_GP,selector & ~0x03)
+ }
}
+ if(!(desc.flags & 0x0080))
+ {
+ logerror("SReg Load (%08x): Segment is not present.\n",cpustate->pc);
+ FAULT(FAULT_NP,selector & ~0x03)
+ }
}
- if(!(desc.flags & 0x0080))
- {
- logerror("SReg Load (%08x): Segment is not present.\n",cpustate->pc);
- FAULT(FAULT_NP,selector & ~0x03)
- }
+ break;
+ default:
+ break;
}
cpustate->sreg[reg].selector = selector;
if(fault) *fault = false;
}
-/*static*/INLINE void i386_trap(i386_state *cpustate,int irq, int irq_gate, int trap_level)
+static void i386_trap(i386_state *cpustate,int irq, int irq_gate, int trap_level)
{
/* I386 Interrupts/Traps/Faults:
*
#define MXCSR_RC (3<<13) // Rounding Control
#define MXCSR_FZ (1<<15) // Flush to Zero
+// https://wiki.osdev.org/Global_Descriptor_Table
+#define SREG_BITPOS_LIMIT_LOW 0
+#define SREG_BITPOS_LIMIT_HIGH 48
+#define SREG_BITSIZE_LIMIT_LOW 16
+#define SREG_BITSIZE_LIMIT_HIGH 4
+#define SREG_BITPOS_BASE_POS_LOW 16
+#define SREG_BITPOS_BASE_POS_MID 32
+#define SREG_BITPOS_BASE_POS_HIGH 56
+#define SREG_BITSIZE_BASE_LOW 16
+#define SREG_BITSIZE_BASE_MID 8
+#define SREG_BITSIZE_BASE_HIGH 8
+#define SREG_BITPOS_ACCESS_BYTE 40
+#define SREG_BITSIZE_ACCESS_BYTE 8
+#define SREG_BITPOS_FLAGS 52
+#define SREG_BITSIZE_FLAGS 4
+
+// ARGS are pair32_t
+INLINE UINT32 sreg_get_base(UINT32 high, UINT32 low)
+{
+ pair32_t ret;
+ pair32_t phigh;
+ pair32_t plow;
+ phigh.d = high;
+ plow.d = low;
+ ret.b.h3 = phigh.b.h3; /* high */
+ ret.b.h2 = phigh.b.l; /* mid */
+ ret.b.h = plow.b.h3; /* high of low */
+ ret.b.l = plow.b.h2; /* low of low */
+ return ret.d;
+}
+
+INLINE UINT32 sreg_get_base_from_u64(UINT64 src)
+{
+ pair32_t ret;
+ pair64_t pa;
+
+ pa.q = src;
+ ret.w.l = pa.w.h;
+ ret.b.h2 = pa.b.h4;
+ ret.b.h3 = pa.b.h7;
+ return ret.d;
+}
+
+INLINE UINT32 sreg_get_limit(UINT32 high, UINT32 low)
+{
+ pair32_t ret;
+ pair32_t phigh;
+ pair32_t plow;
+ phigh.d = high;
+ plow.d = low;
+
+ ret.w.l = plow.w.l; /* low */
+ ret.b.h2 = phigh.b.h2 & 0x0f;
+ return ret.d;
+}
+
+INLINE UINT32 sreg_get_limit_from_u64(UINT64 src)
+{
+ pair32_t ret;
+ pair64_t pa;
+
+ pa.q = src;
+ ret.w.l = pa.w.l;
+ ret.b.h2 = pa.b.h6 & 0x0f;
+ return ret.d;
+}
+
+INLINE UINT8 sreg_get_flags(UINT32 high)
+{
+ pair32_t phigh;
+ phigh.d = high;
+ return ((phigh.b.h2 & 0xf0) >> 4);
+}
+
+INLINE UINT8 sreg_get_flags_from_u64(UINT64 src)
+{
+ pair32_t ret;
+ pair64_t pa;
+
+ pa.q = src;
+ return ((pa.b.h6 & 0xf0) >> 4);
+}
+
+INLINE UINT8 sreg_get_access_byte(UINT32 high)
+{
+ pair32_t phigh;
+ phigh.d = high;
+ return phigh.b.h;
+}
+
+INLINE UINT8 sreg_get_access_byte_from_u64(UINT64 src)
+{
+ pair64_t pa;
+
+ pa.q = src;
+ return pa.b.h5;
+}
+
+
+// IN SEGMENT DESCRIPTOR TABLE
+// ACCESS BYTE BITFIELDS (bit40-47)
+#define SREG_FLAGS_AC 0x0001 /* '1' is before accessed */
+#define SREG_FLAGS_RW 0x0002 /* READABLE for CODE SEGMENT/WRITABLE for DATA SEGMENT*/
+#define SREG_FLAGS_DC 0x0004 /* '1' to expand down, '0' to expand up */
+#define SREG_FLAGS_EX 0x0008 /* '1' to executable */
+#define SREG_FLAGS_NS 0x0010 /* '0' to system-segment */
+#define SREG_FLAGS_PRIV_LO 0x0020 /* PRIVILEGE (0 to 3) */
+#define SREG_FLAGS_PRIV_HI 0x0040
+#define SREG_FLAGS_PR 0x0080 /* '1' = valid segment */
+
+// FLAGS (bit52-55)
+#define SREG_FLAGS_RESV1 0x1000
+#define SREG_FLAGS_RESV2 0x2000
+#define SREG_FLAGS_SZ 0x4000 /* '1' at 32bit protected mode */
+#define SREG_FLAGS_GR 0x8000 /* '1' at limit multiplies to $1000 */
+
+
struct I386_SREG {
UINT16 selector;
UINT16 flags;
#define VTLB_FLAG_DIRTY 0x100
-INLINE vtlb_entry get_permissions(UINT32 pte, int wp)
+vtlb_entry get_permissions(UINT32 pte, int wp)
{
vtlb_entry ret = VTLB_READ_ALLOWED | ((pte & 4) ? VTLB_USER_READ_ALLOWED : 0);
if(!wp)