OSDN Git Service

[VM][I386] i386_sreg_load() : Replace IF-branch to CASE branch, to be faster.
authorK.Ohta <whatisthis.sowhat@gmail.com>
Thu, 23 May 2019 20:29:56 +0000 (05:29 +0900)
committerK.Ohta <whatisthis.sowhat@gmail.com>
Thu, 23 May 2019 20:29:56 +0000 (05:29 +0900)
[VM][I386] i386priv.h : Add Segment descriptor table (GDT/LDT etc) bitfield description defines and bit value defines of sreg[foo].flags.
[VM][I386] Some functions change to static from INLINE, these seems not be used heavily, used sometimes.

source/src/vm/mame/emu/cpu/i386/i386.c
source/src/vm/mame/emu/cpu/i386/i386priv.h

index a906905..912d6e1 100644 (file)
@@ -589,112 +589,123 @@ static void i386_sreg_load(i386_state *cpustate, UINT16 selector, UINT8 reg, boo
        }
 
        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;
@@ -702,7 +713,7 @@ static void i386_sreg_load(i386_state *cpustate, UINT16 selector, UINT8 reg, boo
        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:
         *
index 2ce710a..3f9042d 100644 (file)
@@ -296,6 +296,123 @@ enum smram_intel_p5
 #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;
@@ -728,7 +845,7 @@ INLINE UINT32 i386_translate(i386_state *cpustate, int segment, UINT32 ip, int r
 
 #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)