Previous 15994 Revisions Next

r15082 Thursday 3rd May, 2012 at 00:57:11 UTC by Barry Rodewald
i386: Big pmode update. OS/2 2.1 more or less runs now. [Carl]
[src/emu/cpu/i386]i386.c i386priv.h

src/emu/cpu/i386/i386priv.h
r15081r15082
240240
241241   UINT8 performed_intersegment_jump;
242242   UINT8 delayed_interrupt_enable;
243   UINT8 old_tf;
244243
245244   UINT32 cr[5];      // Control registers
246245   UINT32 dr[8];      // Debug registers
r15081r15082
419418   UINT32 offset = a & 0xfff;
420419   UINT32 page_entry;
421420   UINT32 ret = 1;
421   bool user = (cpustate->CPL == 3);
422422   *error = 0;
423423
424424   // TODO: cr0 wp bit, 486 and higher
425425   UINT32 page_dir = cpustate->program->read_dword(pdbr + directory * 4);
426   if(page_dir & 1)
426   if((page_dir & 1) && ((page_dir & 4) || !user))
427427   {
428428      if (!(cpustate->cr[4] & 0x10))
429429      {
430430         page_entry = cpustate->program->read_dword((page_dir & 0xfffff000) + (table * 4));
431431         if(!(page_entry & 1))
432432            ret = 0;
433         else if(!(page_entry & 2) && cpustate->CPL && (rwn == 1))
433         else if((!(page_entry & 2) && user && (rwn == 1)) || (!(page_entry & 4) && user))
434434         {
435435            *error = 1;
436436            ret = 0;
r15081r15082
450450      {
451451         if (page_dir & 0x80)
452452         {
453            if(!(page_dir & 2) && cpustate->CPL && (rwn == 1))
453            if(!(page_dir & 2) && user && (rwn == 1))
454454            {
455455               *error = 1;
456456               ret = 0;
r15081r15082
469469            page_entry = cpustate->program->read_dword((page_dir & 0xfffff000) + (table * 4));
470470            if(!(page_entry & 1))
471471               ret = 0;
472            else if(!(page_entry & 2) && cpustate->CPL && (rwn == 1))
472            else if((!(page_entry & 2) && user && (rwn == 1)) || (!(page_entry & 4) && user))
473473            {
474474               *error = 1;
475475               ret = 0;
r15081r15082
488488      }
489489   }
490490   else
491   {
492      if(page_dir & 1)
493         *error = 1;
491494      ret = 0;
495   }
492496   if(!ret)
493497   {
494498      if(rwn != -1)
495         *error |= ((rwn & 1)<<1) | ((cpustate->CPL==3)?1<<2:0);
499         *error |= ((rwn & 1)<<1) | (user<<2);
496500      return 0;
497501   }
498502   return 1;
r15081r15082
672676   return value;
673677}
674678
679INLINE void WRITE_TEST(i386_state *cpustate,UINT32 ea)
680{
681   UINT32 address = ea, error;
682   if (cpustate->cr[0] & 0x80000000)      // page translation enabled
683   {
684      if(!translate_address(cpustate,1,&address,&error))
685         PF_THROW(error);
686   }
687}
688
675689INLINE void WRITE8(i386_state *cpustate,UINT32 ea, UINT8 value)
676690{
677691   UINT32 address = ea, error;
src/emu/cpu/i386/i386.c
r15081r15082
5252   entry = seg->selector & ~0x7;
5353   if (limit == 0 || entry + 7 > limit)
5454      return 0;
55   
56   int cpl = cpustate->CPL;
57   cpustate->CPL = 0;
5558
5659   v1 = READ32(cpustate, base + entry );
5760   v2 = READ32(cpustate, base + entry + 4 );
5861
62   cpustate->CPL = cpl;
63
5964   seg->flags = (v2 >> 8) & 0xf0ff;
6065   seg->base = (v2 & 0xff000000) | ((v2 & 0xff) << 16) | ((v1 >> 16) & 0xffff);
6166   seg->limit = (v2 & 0xf0000) | (v1 & 0xffff);
r15081r15082
8893   if (limit == 0 || entry + 7 > limit)
8994      return;
9095
96   int cpl = cpustate->CPL;
97   cpustate->CPL = 0;
98
9199   v1 = READ32(cpustate, base + entry );
92100   v2 = READ32(cpustate, base + entry + 4 );
93101
102   cpustate->CPL = cpl;
103
94104   /* Note that for task gates, offset and dword_count are not used */
95105   gate->selector = (v1 >> 16) & 0xffff;
96106   gate->offset = (v1 & 0x0000ffff) | (v2 & 0xffff0000);
r15081r15082
129139/* Retrieves the stack selector located in the current TSS */
130140static UINT32 i386_get_stack_segment(i386_state* cpustate, UINT8 privilege)
131141{
142   UINT32 ret;
132143   if(privilege >= 3)
133144      return 0;
134145
135   return READ32(cpustate,(cpustate->task.base+8) + (8*privilege));
136}
146   int cpl = cpustate->CPL;
147   cpustate->CPL = 0;
137148
138static UINT16 i286_get_stack_segment(i386_state* cpustate, UINT8 privilege)
139{
140   if(privilege >= 3)
141      return 0;
149   if(cpustate->task.flags & 8)
150      ret = READ32(cpustate,(cpustate->task.base+8) + (8*privilege));
151   else
152      ret = READ16(cpustate,(cpustate->task.base+4) + (4*privilege));
142153
143   return READ16(cpustate,(cpustate->task.base+4) + (4*privilege));
154   cpustate->CPL = cpl;
155   return ret;
144156}
145157
146158/* Retrieves the stack pointer located in the current TSS */
147159static UINT32 i386_get_stack_ptr(i386_state* cpustate, UINT8 privilege)
148160{
161   UINT32 ret;
149162   if(privilege >= 3)
150163      return 0;
151164
152   return READ32(cpustate,(cpustate->task.base+4) + (8*privilege));
153}
165   int cpl = cpustate->CPL;
166   cpustate->CPL = 0;
154167
155static UINT16 i286_get_stack_ptr(i386_state* cpustate, UINT8 privilege)
156{
157   if(privilege >= 3)
158      return 0;
168   if(cpustate->task.flags & 8)
169      ret = READ32(cpustate,(cpustate->task.base+4) + (8*privilege));
170   else
171      ret = READ16(cpustate,(cpustate->task.base+2) + (4*privilege));
159172
160   return READ16(cpustate,(cpustate->task.base+2) + (4*privilege));
173   cpustate->CPL = cpl;
174   return ret;
161175}
162176
163177static UINT32 get_flags(i386_state *cpustate)
r15081r15082
596610      UINT8 CPL = cpustate->CPL, DPL = 0; //, RPL = 0;
597611
598612      /* 32-bit */
613      cpustate->CPL = 0;
599614      v1 = READ32(cpustate, cpustate->idtr.base + entry );
600615      v2 = READ32(cpustate, cpustate->idtr.base + entry + 4 );
616      cpustate->CPL = CPL;
601617      offset = (v2 & 0xffff0000) | (v1 & 0xffff);
602618      segment = (v1 >> 16) & 0xffff;
603619      type = (v2>>8) & 0x1F;
r15081r15082
661677         /* Get privilege level 0 stack pointer from TSS */
662678         cpustate->sreg[SS].selector = i386_get_stack_segment(cpustate,0);
663679         REG32(ESP) = i386_get_stack_ptr(cpustate,0);
680         cpustate->CPL = segment & 0x03;
664681         i386_load_segment_descriptor(cpustate,SS);
665682         PUSH32(cpustate,cpustate->sreg[GS].selector & 0xffff);
666683         PUSH32(cpustate,cpustate->sreg[FS].selector & 0xffff);
r15081r15082
686703         cpustate->sreg[CS].selector = segment;
687704         cpustate->eip = offset;
688705         // CPL set to CS RPL?
689         cpustate->CPL = segment & 0x03;
690706
691707         i386_load_segment_descriptor(cpustate,CS);
692708         CHANGE_PC(cpustate,cpustate->eip);
r15081r15082
702718         if(segment & 0x04)
703719         {
704720            logerror("IRQ: Task gate: TSS is not in the GDT.\n");
705            FAULT_EXP(FAULT_TS,segment & ~0x07);
721            FAULT_EXP(FAULT_TS,segment & ~0x03);
706722         }
707723         else
708724         {
709725            if(segment > cpustate->gdtr.limit)
710726            {
711727               logerror("IRQ: Task gate: TSS is past GDT limit.\n");
712               FAULT_EXP(FAULT_TS,segment & ~0x07);
728               FAULT_EXP(FAULT_TS,segment & ~0x03);
713729            }
714730         }
715731         if((desc.flags & 0x000f) != 0x09 && (desc.flags & 0x000f) != 0x01)
716732         {
717733            logerror("IRQ: Task gate: TSS is not an available TSS.\n");
718            FAULT_EXP(FAULT_TS,segment & ~0x07);
734            FAULT_EXP(FAULT_TS,segment & ~0x03);
719735         }
720736         if((desc.flags & 0x0080) == 0)
721737         {
722738            logerror("IRQ: Task gate: TSS is not present.\n");
723            FAULT_EXP(FAULT_NP,segment & ~0x07);
739            FAULT_EXP(FAULT_NP,segment & ~0x03);
724740         }
725741         if(!(irq == 3 || irq == 4 || irq == 9 || irq_gate == 1))
726742            cpustate->eip = cpustate->prev_eip;
r15081r15082
750766            if((segment & ~0x07) > cpustate->ldtr.limit)
751767            {
752768               logerror("IRQ: Gate segment is past LDT limit.\n");
753               FAULT_EXP(FAULT_GP,(segment & 0x07)+cpustate->ext)
769               FAULT_EXP(FAULT_GP,(segment & 0x03)+cpustate->ext)
754770            }
755771         }
756772         else
r15081r15082
758774            if((segment & ~0x07) > cpustate->gdtr.limit)
759775            {
760776               logerror("IRQ: Gate segment is past GDT limit.\n");
761               FAULT_EXP(FAULT_GP,(segment & 0x07)+cpustate->ext)
777               FAULT_EXP(FAULT_GP,(segment & 0x03)+cpustate->ext)
762778            }
763779         }
764780         if((desc.flags & 0x0018) != 0x18)
765781         {
766782            logerror("IRQ: Gate descriptor is not a code segment.\n");
767            FAULT_EXP(FAULT_GP,(segment & 0x07)+cpustate->ext)
783            FAULT_EXP(FAULT_GP,(segment & 0x03)+cpustate->ext)
768784         }
769785         if((desc.flags & 0x0080) == 0)
770786         {
771787            logerror("IRQ: Gate segment is not present.\n");
772            FAULT_EXP(FAULT_NP,(segment & 0x07)+cpustate->ext)
788            FAULT_EXP(FAULT_NP,(segment & 0x03)+cpustate->ext)
773789         }
774790         if((desc.flags & 0x0004) == 0 && (DPL < CPL))
775791         {
r15081r15082
779795
780796            /* Check new stack segment in TSS */
781797            memset(&stack, 0, sizeof(stack));
782            if(flags & 0x0008)
783               stack.selector = i386_get_stack_segment(cpustate,DPL);
784            else
785               stack.selector = i286_get_stack_segment(cpustate,DPL);
798            stack.selector = i386_get_stack_segment(cpustate,DPL);
786799            i386_load_protected_mode_segment(cpustate,&stack,NULL);
787800            oldSS = cpustate->sreg[SS].selector;
788801            if(flags & 0x0008)
789802               oldESP = REG32(ESP);
790803            else
791804               oldESP = REG16(SP);
792            if((stack.selector & ~0x07) == 0)
805            if((stack.selector & ~0x03) == 0)
793806            {
794807               logerror("IRQ: New stack selector is null.\n");
795808               FAULT_EXP(FAULT_GP,cpustate->ext)
r15081r15082
799812               if((stack.selector & ~0x07) > cpustate->ldtr.base)
800813               {
801814                  logerror("IRQ: New stack selector is past LDT limit.\n");
802                  FAULT_EXP(FAULT_TS,(stack.selector & ~0x07)+cpustate->ext)
815                  FAULT_EXP(FAULT_TS,(stack.selector & ~0x03)+cpustate->ext)
803816               }
804817            }
805818            else
r15081r15082
807820               if((stack.selector & ~0x07) > cpustate->gdtr.base)
808821               {
809822                  logerror("IRQ: New stack selector is past GDT limit.\n");
810                  FAULT_EXP(FAULT_TS,(stack.selector & ~0x07)+cpustate->ext)
823                  FAULT_EXP(FAULT_TS,(stack.selector & ~0x03)+cpustate->ext)
811824               }
812825            }
813826            if((stack.selector & 0x03) != DPL)
814827            {
815828               logerror("IRQ: New stack selector RPL is not equal to code segment DPL.\n");
816               FAULT_EXP(FAULT_TS,(stack.selector & ~0x07)+cpustate->ext)
829               FAULT_EXP(FAULT_TS,(stack.selector & ~0x03)+cpustate->ext)
817830            }
818831            if(((stack.flags >> 5) & 0x03) != DPL)
819832            {
820833               logerror("IRQ: New stack segment DPL is not equal to code segment DPL.\n");
821               FAULT_EXP(FAULT_TS,(stack.selector & ~0x07)+cpustate->ext)
834               FAULT_EXP(FAULT_TS,(stack.selector & ~0x03)+cpustate->ext)
822835            }
823836            if(((stack.flags & 0x0018) != 0x10) && (stack.flags & 0x0002) != 0)
824837            {
825838               logerror("IRQ: New stack segment is not a writable data segment.\n");
826               FAULT_EXP(FAULT_TS,(stack.selector & ~0x07)+cpustate->ext) // #TS(stack selector + EXT)
839               FAULT_EXP(FAULT_TS,(stack.selector & ~0x03)+cpustate->ext) // #TS(stack selector + EXT)
827840            }
828841            if((stack.flags & 0x0080) == 0)
829842            {
830843               logerror("IRQ: New stack segment is not present.\n");
831               FAULT_EXP(FAULT_SS,(stack.selector & ~0x07)+cpustate->ext) // #TS(stack selector + EXT)
844               FAULT_EXP(FAULT_SS,(stack.selector & ~0x03)+cpustate->ext) // #TS(stack selector + EXT)
832845            }
846            newESP = i386_get_stack_ptr(cpustate,DPL);
833847            if(type & 0x08) // 32-bit gate
834848            {
835               newESP = i386_get_stack_ptr(cpustate,DPL);
836849               if(newESP < 20)
837850               {
838851                  logerror("IRQ: New stack has no space for return addresses.\n");
r15081r15082
841854            }
842855            else // 16-bit gate
843856            {
844               newESP = i286_get_stack_ptr(cpustate,DPL);
857               newESP &= 0xffff;
845858               if(newESP < 10)
846859               {
847860                  logerror("IRQ: New stack has no space for return addresses.\n");
r15081r15082
853866               logerror("IRQ: New EIP is past code segment limit.\n");
854867               FAULT_EXP(FAULT_GP,0)
855868            }
869            /* change CPL before accessing the stack */
870            cpustate->CPL = DPL;
871            /* check for page fault at new stack TODO: check if stack frame crosses page boundary */
872            WRITE_TEST(cpustate, stack.base+newESP-1);
856873            /* Load new stack segment descriptor */
857874            cpustate->sreg[SS].selector = stack.selector;
858875            i386_load_segment_descriptor(cpustate,SS);
859876            if(flags & 0x0008)
860877               REG32(ESP) = i386_get_stack_ptr(cpustate,DPL);
861878            else
862               REG16(SP) = i286_get_stack_ptr(cpustate,DPL);
879               REG16(SP) = i386_get_stack_ptr(cpustate,DPL);
863880            if(type & 0x08)
864881            {
865882               // 32-bit gate
r15081r15082
872889               PUSH16(cpustate,oldSS);
873890               PUSH16(cpustate,oldESP);
874891            }
875            cpustate->CPL = DPL;
876892            SetRPL = 1;
877893         }
878894         else
r15081r15082
951967      {
952968         UINT32 entry = irq * 8;
953969         UINT32 v2,type;
970         int cpl = cpustate->CPL;
971         cpustate->CPL = 0;
954972         v2 = READ32(cpustate, cpustate->idtr.base + entry + 4 );
955973         type = (v2>>8) & 0x1F;
956974         if(type == 5)
r15081r15082
959977            v2 = READ32(cpustate, cpustate->gdtr.base + ((v2 >> 16) & 0xfff8) + 4);
960978            type = (v2>>8) & 0x1F;
961979         }
980         cpustate->CPL = cpl;
962981         if(type >= 9)
963982            PUSH32(cpustate,error);
964983         else
r15081r15082
11361155   cpustate->cr[0] |= 0x08;
11371156
11381157   /* Load incoming task state from the new task's TSS */
1158   cpustate->CPL = 0;
11391159   tss = cpustate->task.base;
11401160   cpustate->ldtr.segment = READ32(cpustate,tss+0x60) & 0xffff;
11411161   seg.selector = cpustate->ldtr.segment;
r15081r15082
13511371            }
13521372            if(call_gate.selector & 0x04)
13531373            {
1354               /* check GDT limit */
1355               if((call_gate.selector & ~0x07) > cpustate->gdtr.limit)
1374               if((call_gate.selector & ~0x07) > cpustate->ldtr.limit)
13561375               {
1357                  logerror("JMP: Call Gate: Gate Selector is past GDT segment limit\n");
1376                  logerror("JMP: Call Gate: Gate Selector is past LDT segment limit\n");
13581377                  FAULT(FAULT_GP,call_gate.selector & 0xfffc)
13591378               }
13601379            }
13611380            else
13621381            {
1363               /* check LDT limit */
1364               if((call_gate.selector & ~0x07) > cpustate->ldtr.limit)
1382               if((call_gate.selector & ~0x07) > cpustate->gdtr.limit)
13651383               {
1366                  logerror("JMP: Call Gate: Gate Selector is past LDT segment limit\n");
1384                  logerror("JMP: Call Gate: Gate Selector is past GDT segment limit\n");
13671385                  FAULT(FAULT_GP,call_gate.selector & 0xfffc)
13681386               }
13691387            }
r15081r15082
16381656               FAULT(FAULT_NP,desc.selector & ~0x03)  // #GP(selector)
16391657            }
16401658            desc.selector = gate.selector;
1641            if((gate.selector & ~0x07) == 0)
1659            if((gate.selector & ~0x03) == 0)
16421660            {
16431661               logerror("CALL: Call gate: Segment is null.\n");
16441662               FAULT(FAULT_GP,0)  // #GP(0)
r15081r15082
16841702               /* more privilege */
16851703               /* Check new SS segment for privilege level from TSS */
16861704               memset(&stack, 0, sizeof(stack));
1687               if(operand32 != 0)
1688                  stack.selector = i386_get_stack_segment(cpustate,DPL);
1689               else
1690                  stack.selector = i286_get_stack_segment(cpustate,DPL);
1705               stack.selector = i386_get_stack_segment(cpustate,DPL);
16911706               i386_load_protected_mode_segment(cpustate,&stack,NULL);
1692               if((stack.selector & ~0x07) == 0)
1707               if((stack.selector & ~0x03) == 0)
16931708               {
16941709                  logerror("CALL: Call gate: TSS selector is null\n");
16951710                  FAULT(FAULT_TS,0)  // #TS(0)
r15081r15082
17301745                  logerror("CALL: Call gate: Stack segment is not present\n");
17311746                  FAULT(FAULT_SS,stack.selector)  // #SS(SS selector)
17321747               }
1748               UINT32 newESP = i386_get_stack_ptr(cpustate,DPL);
17331749               if(operand32 != 0)
17341750               {
1735                  UINT32 newESP = i386_get_stack_ptr(cpustate,DPL);
17361751                  if(newESP < ((gate.dword_count & 0x1f) + 16))
17371752                  {
17381753                     logerror("CALL: Call gate: New stack has no room for 32-bit return address and parameters.\n");
r15081r15082
17461761               }
17471762               else
17481763               {
1749                  UINT32 newESP = i286_get_stack_ptr(cpustate,DPL) & 0x0000ffff;
1764                  newESP &= 0x0000ffff;
17501765                  if(newESP < ((gate.dword_count & 0x1f) + 8))
17511766                  {
17521767                     logerror("CALL: Call gate: New stack has no room for 16-bit return address and parameters.\n");
r15081r15082
17611776               selector = gate.selector;
17621777               offset = gate.offset;
17631778
1779               cpustate->CPL = (stack.flags >> 5) & 0x03;
1780               /* check for page fault at new stack TODO: check if stack frame crosses page boundary */
1781               WRITE_TEST(cpustate, stack.base+newESP-1);
17641782               /* switch to new stack */
17651783               oldSS = cpustate->sreg[SS].selector;
1784               cpustate->sreg[SS].selector = i386_get_stack_segment(cpustate,gate.selector & 0x03);
17661785               if(operand32 != 0)
17671786               {
17681787                  oldESP = REG32(ESP);
1769                  cpustate->sreg[SS].selector = i386_get_stack_segment(cpustate,gate.selector & 0x03);
17701788               }
17711789               else
17721790               {
17731791                  oldESP = REG16(SP);
1774                  cpustate->sreg[SS].selector = i286_get_stack_segment(cpustate,gate.selector & 0x03);
17751792               }
17761793               i386_load_segment_descriptor(cpustate, SS );
17771794               if(operand32 != 0)
17781795                  REG32(ESP) = i386_get_stack_ptr(cpustate,gate.selector & 0x03);
17791796               else
1780                  REG16(SP) = i286_get_stack_ptr(cpustate,gate.selector & 0x03) & 0x0000ffff;
1797                  REG16(SP) = i386_get_stack_ptr(cpustate,gate.selector & 0x03) & 0x0000ffff;
17811798
17821799               if(operand32 != 0)
17831800               {
r15081r15082
17961813               /* copy parameters from old stack to new stack */
17971814               for(x=(gate.dword_count & 0x1f)-1;x>=0;x--)
17981815               {
1799                  UINT32 addr = temp.base + oldESP + (x*2);
1800                  PUSH16(cpustate,READ16(cpustate,addr));
1816                  UINT32 addr = oldESP + (operand32?(x*4):(x*2));
1817                  addr = temp.base + (temp.d?addr:(addr&0xffff));
1818                  if(operand32)
1819                     PUSH32(cpustate,READ32(cpustate,addr));
1820                  else
1821                     PUSH16(cpustate,READ16(cpustate,addr));
18011822               }
1802               cpustate->CPL = (stack.flags >> 5) & 0x03;
18031823               SetRPL = 1;
18041824            }
18051825            else
r15081r15082
18421862            if(DPL < CPL)
18431863            {
18441864               logerror("CALL: Task Gate: Gate DPL is less than CPL.\n");
1845               FAULT(FAULT_TS,selector & ~0x07) // #TS(selector)
1865               FAULT(FAULT_TS,selector & ~0x03) // #TS(selector)
18461866            }
18471867            if(DPL < RPL)
18481868            {
18491869               logerror("CALL: Task Gate: Gate DPL is less than RPL.\n");
1850               FAULT(FAULT_TS,selector & ~0x07) // #TS(selector)
1870               FAULT(FAULT_TS,selector & ~0x03) // #TS(selector)
18511871            }
18521872            if(gate.ar & 0x0080)
18531873            {
18541874               logerror("CALL: Task Gate: Gate is not present.\n");
1855               FAULT(FAULT_NP,selector & ~0x07) // #NP(selector)
1875               FAULT(FAULT_NP,selector & ~0x03) // #NP(selector)
18561876            }
18571877            /* Check the TSS that the task gate points to */
18581878            desc.selector = gate.selector;
r15081r15082
18601880            if(gate.selector & 0x04)
18611881            {
18621882               logerror("CALL: Task Gate: TSS is not global.\n");
1863               FAULT(FAULT_TS,gate.selector & ~0x07) // #TS(selector)
1883               FAULT(FAULT_TS,gate.selector & ~0x03) // #TS(selector)
18641884            }
18651885            else
18661886            {
18671887               if((gate.selector & ~0x07) > cpustate->gdtr.limit)
18681888               {
18691889                  logerror("CALL: Task Gate: TSS is past GDT limit.\n");
1870                  FAULT(FAULT_TS,gate.selector & ~0x07) // #TS(selector)
1890                  FAULT(FAULT_TS,gate.selector & ~0x03) // #TS(selector)
18711891               }
18721892            }
18731893            if(desc.flags & 0x0002)
18741894            {
18751895               logerror("CALL: Task Gate: TSS is busy.\n");
1876               FAULT(FAULT_TS,gate.selector & ~0x07) // #TS(selector)
1896               FAULT(FAULT_TS,gate.selector & ~0x03) // #TS(selector)
18771897            }
18781898            if(desc.flags & 0x0080)
18791899            {
18801900               logerror("CALL: Task Gate: TSS is not present.\n");
1881               FAULT(FAULT_NP,gate.selector & ~0x07) // #TS(selector)
1901               FAULT(FAULT_NP,gate.selector & ~0x03) // #TS(selector)
18821902            }
18831903            if(desc.flags & 0x08)
18841904               i386_task_switch(cpustate,desc.selector,1);  // with nesting
r15081r15082
19812001      }
19822002      if(desc.flags & 0x0004)
19832003      {
1984         if(DPL > CPL)
2004         if(DPL > RPL)
19852005         {
1986            logerror("RETF: Conforming code segment DPL is greater than CPL.\n");
2006            logerror("RETF: Conforming code segment DPL is greater than CS RPL.\n");
19872007            FAULT(FAULT_GP,newCS & ~0x03)
19882008         }
19892009      }
19902010      else
19912011      {
1992         if(DPL != CPL)
2012         if(DPL != RPL)
19932013         {
1994            logerror("RETF: Non-conforming code segment DPL does not equal CPL.\n");
2014            logerror("RETF: Non-conforming code segment DPL does not equal CS RPL.\n");
19952015            FAULT(FAULT_GP,newCS & ~0x03)
19962016         }
19972017      }
r15081r15082
20612081         if((newCS & ~0x07) >= cpustate->ldtr.limit)
20622082         {
20632083            logerror("RETF: CS segment selector is past LDT limit.\n");
2064            FAULT(FAULT_GP,newCS & ~0x07)
2084            FAULT(FAULT_GP,newCS & ~0x03)
20652085         }
20662086      }
20672087      else
r15081r15082
20692089         if((newCS & ~0x07) >= cpustate->gdtr.limit)
20702090         {
20712091            logerror("RETF: CS segment selector is past GDT limit.\n");
2072            FAULT(FAULT_GP,newCS & ~0x07)
2092            FAULT(FAULT_GP,newCS & ~0x03)
20732093         }
20742094      }
20752095      if((desc.flags & 0x0018) != 0x0018)
20762096      {
20772097         logerror("RETF: CS segment is not a code segment.\n");
2078         FAULT(FAULT_GP,newCS & ~0x07)
2098         FAULT(FAULT_GP,newCS & ~0x03)
20792099      }
20802100      if(desc.flags & 0x0004)
20812101      {
20822102         if(DPL > RPL)
20832103         {
20842104            logerror("RETF: Conforming CS segment DPL is greater than return selector RPL.\n");
2085            FAULT(FAULT_GP,newCS & ~0x07)
2105            FAULT(FAULT_GP,newCS & ~0x03)
20862106         }
20872107      }
20882108      else
r15081r15082
20902110         if(DPL != RPL)
20912111         {
20922112            logerror("RETF: Non-conforming CS segment DPL is not equal to return selector RPL.\n");
2093            FAULT(FAULT_GP,newCS & ~0x07)
2113            FAULT(FAULT_GP,newCS & ~0x03)
20942114         }
20952115      }
20962116      if((desc.flags & 0x0080) == 0)
20972117      {
20982118         logerror("RETF: CS segment is not present.\n");
2099         FAULT(FAULT_NP,newCS & ~0x07)
2119         FAULT(FAULT_NP,newCS & ~0x03)
21002120      }
21012121      if(newEIP > desc.limit)
21022122      {
r15081r15082
21312151         if((newSS & ~0x07) > cpustate->ldtr.limit)
21322152         {
21332153            logerror("RETF (%08x): SS segment selector is past LDT limit.\n",cpustate->pc);
2134            FAULT(FAULT_GP,newSS & ~0x07)
2154            FAULT(FAULT_GP,newSS & ~0x03)
21352155         }
21362156      }
21372157      else
r15081r15082
21392159         if((newSS & ~0x07) > cpustate->gdtr.limit)
21402160         {
21412161            logerror("RETF (%08x): SS segment selector is past GDT limit.\n",cpustate->pc);
2142            FAULT(FAULT_GP,newSS & ~0x07)
2162            FAULT(FAULT_GP,newSS & ~0x03)
21432163         }
21442164      }
21452165      if((newSS & 0x03) != RPL)
21462166      {
21472167         logerror("RETF: SS segment RPL is not equal to CS segment RPL.\n");
2148         FAULT(FAULT_GP,newSS & ~0x07)
2168         FAULT(FAULT_GP,newSS & ~0x03)
21492169      }
21502170      if((desc.flags & 0x0018) != 0x0010 || (desc.flags & 0x0002) == 0)
21512171      {
21522172         logerror("RETF: SS segment is not a writable data segment.\n");
2153         FAULT(FAULT_GP,newSS & ~0x07)
2173         FAULT(FAULT_GP,newSS & ~0x03)
21542174      }
21552175      if(((desc.flags >> 5) & 0x03) != RPL)
21562176      {
21572177         logerror("RETF: SS DPL is not equal to CS segment RPL.\n");
2158         FAULT(FAULT_GP,newSS & ~0x07)
2178         FAULT(FAULT_GP,newSS & ~0x03)
21592179      }
21602180      if((desc.flags & 0x0080) == 0)
21612181      {
21622182         logerror("RETF: SS segment is not present.\n");
2163         FAULT(FAULT_GP,newSS & ~0x07)
2183         FAULT(FAULT_GP,newSS & ~0x03)
21642184      }
21652185      cpustate->CPL = newCS & 0x03;
21662186
r15081r15082
22492269      if(task & 0x04)
22502270      {
22512271         logerror("IRET: Task return: Back-linked TSS is not in GDT.\n");
2252         FAULT(FAULT_TS,task & ~0x07)
2272         FAULT(FAULT_TS,task & ~0x03)
22532273      }
22542274      if((task & ~0x07) >= cpustate->gdtr.limit)
22552275      {
22562276         logerror("IRET: Task return: Back-linked TSS is not in GDT.\n");
2257         FAULT(FAULT_TS,task & ~0x07)
2277         FAULT(FAULT_TS,task & ~0x03)
22582278      }
22592279      memset(&desc, 0, sizeof(desc));
22602280      desc.selector = task;
r15081r15082
22622282      if((desc.flags & 0x001f) != 0x000b)
22632283      {
22642284         logerror("IRET (%08x): Task return: Back-linked TSS is not a busy TSS.\n",cpustate->pc);
2265         FAULT(FAULT_TS,task & ~0x07)
2285         FAULT(FAULT_TS,task & ~0x03)
22662286      }
22672287      if((desc.flags & 0x0080) == 0)
22682288      {
22692289         logerror("IRET: Task return: Back-linked TSS is not present.\n");
2270         FAULT(FAULT_NP,task & ~0x07)
2290         FAULT(FAULT_NP,task & ~0x03)
22712291      }
22722292      if(desc.flags & 0x08)
22732293         i386_task_switch(cpustate,desc.selector,0);
r15081r15082
24622482         if(RPL < CPL)
24632483         {
24642484            logerror("IRET (%08x): Return CS RPL is less than CPL.\n",cpustate->pc);
2465            FAULT(FAULT_GP,newCS & ~0x07)
2485            FAULT(FAULT_GP,newCS & ~0x03)
24662486         }
24672487         if(RPL == CPL)
24682488         {
r15081r15082
24952515               if((newCS & ~0x07) >= cpustate->ldtr.limit)
24962516               {
24972517                  logerror("IRET: Return CS selector (%04x) is past LDT limit.\n",newCS);
2498                  FAULT(FAULT_GP,newCS & ~0x07)
2518                  FAULT(FAULT_GP,newCS & ~0x03)
24992519               }
25002520            }
25012521            else
r15081r15082
25032523               if((newCS & ~0x07) >= cpustate->gdtr.limit)
25042524               {
25052525                  logerror("IRET: Return CS selector is past GDT limit.\n");
2506                  FAULT(FAULT_GP,newCS & ~0x07)
2526                  FAULT(FAULT_GP,newCS & ~0x03)
25072527               }
25082528            }
25092529            memset(&desc, 0, sizeof(desc));
r15081r15082
25182538            }
25192539            if(desc.flags & 0x0004)
25202540            {
2521               if(DPL > CPL)
2541               if(DPL > RPL)
25222542               {
2523                  logerror("IRET: Conforming return CS DPL is greater than CPL.\n");
2524                  FAULT(FAULT_GP,newCS & ~0x07)
2543                  logerror("IRET: Conforming return CS DPL is greater than CS RPL.\n");
2544                  FAULT(FAULT_GP,newCS & ~0x03)
25252545               }
25262546            }
25272547            else
25282548            {
2529               if(DPL != CPL)
2549               if(DPL != RPL)
25302550               {
2531                  logerror("IRET: Non-conforming return CS DPL is not equal to CPL.\n");
2532                  FAULT(FAULT_GP,newCS & ~0x07)
2551                  logerror("IRET: Non-conforming return CS DPL is not equal to CS RPL.\n");
2552                  FAULT(FAULT_GP,newCS & ~0x03)
25332553               }
25342554            }
25352555            if((desc.flags & 0x0080) == 0)
25362556            {
25372557               logerror("IRET: Return CS segment is not present.\n");
2538               FAULT(FAULT_NP,newCS & ~0x07)
2558               FAULT(FAULT_NP,newCS & ~0x03)
25392559            }
25402560            if(newEIP > desc.limit)
25412561            {
r15081r15082
26012621               if((newCS & ~0x07) >= cpustate->ldtr.limit)
26022622               {
26032623                  logerror("IRET: Return CS selector is past LDT limit.\n");
2604                  FAULT(FAULT_GP,newCS & ~0x07);
2624                  FAULT(FAULT_GP,newCS & ~0x03);
26052625               }
26062626            }
26072627            else
r15081r15082
26092629               if((newCS & ~0x07) >= cpustate->gdtr.limit)
26102630               {
26112631                  logerror("IRET: Return CS selector is past GDT limit.\n");
2612                  FAULT(FAULT_GP,newCS & ~0x07);
2632                  FAULT(FAULT_GP,newCS & ~0x03);
26132633               }
26142634            }
26152635            if((desc.flags & 0x0018) != 0x0018)
26162636            {
26172637               logerror("IRET: Return CS segment is not a code segment.\n");
2618               FAULT(FAULT_GP,newCS & ~0x07)
2638               FAULT(FAULT_GP,newCS & ~0x03)
26192639            }
26202640            if(desc.flags & 0x0004)
26212641            {
2622               if(DPL <= CPL)
2642               if(DPL > RPL)
26232643               {
2624                  logerror("IRET: Conforming return CS DPL is not greater than CPL.\n");
2625                  FAULT(FAULT_GP,newCS & ~0x07)
2644                  logerror("IRET: Conforming return CS DPL is greater than CS RPL.\n");
2645                  FAULT(FAULT_GP,newCS & ~0x03)
26262646               }
26272647            }
26282648            else
r15081r15082
26302650               if(DPL != RPL)
26312651               {
26322652                  logerror("IRET: Non-conforming return CS DPL does not equal CS RPL.\n");
2633                  FAULT(FAULT_GP,newCS & ~0x07)
2653                  FAULT(FAULT_GP,newCS & ~0x03)
26342654               }
26352655            }
26362656            if((desc.flags & 0x0080) == 0)
26372657            {
26382658               logerror("IRET: Return CS segment is not present.\n");
2639               FAULT(FAULT_NP,newCS & ~0x07)
2659               FAULT(FAULT_NP,newCS & ~0x03)
26402660            }
26412661
26422662            /* Check SS selector and descriptor */
r15081r15082
26642684               if((newSS & ~0x07) >= cpustate->ldtr.limit)
26652685               {
26662686                  logerror("IRET: Return SS selector is past LDT limit.\n");
2667                  FAULT(FAULT_GP,newSS & ~0x07);
2687                  FAULT(FAULT_GP,newSS & ~0x03);
26682688               }
26692689            }
26702690            else
r15081r15082
26722692               if((newSS & ~0x07) >= cpustate->gdtr.limit)
26732693               {
26742694                  logerror("IRET: Return SS selector is past GDT limit.\n");
2675                  FAULT(FAULT_GP,newSS & ~0x07);
2695                  FAULT(FAULT_GP,newSS & ~0x03);
26762696               }
26772697            }
26782698            if((newSS & 0x03) != RPL)
26792699            {
26802700               logerror("IRET: Return SS RPL is not equal to return CS RPL.\n");
2681               FAULT(FAULT_GP,newSS & ~0x07)
2701               FAULT(FAULT_GP,newSS & ~0x03)
26822702            }
26832703            if((stack.flags & 0x0018) != 0x0010)
26842704            {
26852705               logerror("IRET: Return SS segment is not a data segment.\n");
2686               FAULT(FAULT_GP,newSS & ~0x07)
2706               FAULT(FAULT_GP,newSS & ~0x03)
26872707            }
26882708            if((stack.flags & 0x0002) == 0)
26892709            {
26902710               logerror("IRET: Return SS segment is not writable.\n");
2691               FAULT(FAULT_GP,newSS & ~0x07)
2711               FAULT(FAULT_GP,newSS & ~0x03)
26922712            }
26932713            if(DPL != RPL)
26942714            {
26952715               logerror("IRET: Return SS DPL does not equal SS RPL.\n");
2696               FAULT(FAULT_GP,newSS & ~0x07)
2716               FAULT(FAULT_GP,newSS & ~0x03)
26972717            }
26982718            if((stack.flags & 0x0080) == 0)
26992719            {
27002720               logerror("IRET: Return SS segment is not present.\n");
2701               FAULT(FAULT_NP,newSS & ~0x07)
2721               FAULT(FAULT_NP,newSS & ~0x03)
27022722            }
27032723            if(newEIP > desc.limit)
27042724            {
r15081r15082
31273147      cpustate->address_prefix = 0;
31283148
31293149      cpustate->ext = 1;
3130      cpustate->old_tf = cpustate->TF;
3150      int old_tf = cpustate->TF;
31313151
31323152      cpustate->segment_prefix = 0;
31333153      cpustate->prev_eip = cpustate->eip;
r15081r15082
31423162      try
31433163      {
31443164         I386OP(decode_opcode)(cpustate);
3145         if(cpustate->TF && cpustate->old_tf)
3165         if(cpustate->TF && old_tf)
31463166         {
31473167            cpustate->prev_eip = cpustate->eip;
31483168            cpustate->ext = 1;

Previous 15994 Revisions Next


© 1998-2018 The MESS Team