Previous 199869 Revisions Next

r20643 Thursday 31st January, 2013 at 22:56:31 UTC by Carl
i386: add tlb [Carl]
vtlb: add direct dynamic entry load (nw)
vtlb_fill doesn't appear to provide an easy way to determine whether a failure is due to a presence or permission error
also entries need to be marked dirty or the performance improvement is minimal
[src/emu/cpu]vtlb.c vtlb.h
[src/emu/cpu/i386]i386.c i386ops.c i386priv.h i486ops.c

trunk/src/emu/cpu/i386/i386ops.c
r20642r20643
697697         CYCLES(cpustate,CYCLES_MOV_REG_CR0);
698698         break;
699699      case 2: CYCLES(cpustate,CYCLES_MOV_REG_CR2); break;
700      case 3: CYCLES(cpustate,CYCLES_MOV_REG_CR3); break;
700      case 3:
701         CYCLES(cpustate,CYCLES_MOV_REG_CR3);
702         vtlb_flush_dynamic(cpustate->vtlb);
703         break;
701704      case 4: CYCLES(cpustate,1); break; // TODO
702705      default:
703706         fatalerror("i386: mov_cr_r32 CR%d!\n", cr);
trunk/src/emu/cpu/i386/i486ops.c
r20642r20643
301301         }
302302      case 7:         /* INVLPG */
303303         {
304            // Nothing to do ?
304            if(PROTECTED_MODE && cpustate->CPL)
305               FAULT(FAULT_GP,0)
306            if(modrm >= 0xc0)
307            {
308               logerror("i486: invlpg with modrm %02X\n", modrm);
309               FAULT(FAULT_UD,0)
310            }
311            ea = GetEA(cpustate,modrm,-1);
312            CYCLES(cpustate,25); // TODO: add to cycles.h
313            vtlb_flush_address(cpustate->vtlb, ea);
305314            break;
306315         }
307316      default:
r20642r20643
410419         }
411420      case 7:         /* INVLPG */
412421         {
413            // Nothing to do ?
422            if(PROTECTED_MODE && cpustate->CPL)
423               FAULT(FAULT_GP,0)
424            if(modrm >= 0xc0)
425            {
426               logerror("i486: invlpg with modrm %02X\n", modrm);
427               FAULT(FAULT_UD,0)
428            }
429            ea = GetEA(cpustate,modrm,-1);
430            CYCLES(cpustate,25); // TODO: add to cycles.h
431            vtlb_flush_address(cpustate->vtlb, ea);
414432            break;
415433         }
416434      default:
r20642r20643
473491      FAULT(FAULT_GP, 0);
474492   UINT8 modrm = FETCH(cpustate);
475493   UINT8 cr = (modrm >> 3) & 0x7;
494   UINT32 oldcr = cpustate->cr[cr];
476495   cpustate->cr[cr] = LOAD_RM32(modrm);
477496   switch(cr)
478497   {
479      case 0: CYCLES(cpustate,CYCLES_MOV_REG_CR0); break;
498      case 0:
499         CYCLES(cpustate,CYCLES_MOV_REG_CR0);
500         if((oldcr ^ cpustate->cr[cr]) & 0x80010000)
501            vtlb_flush_dynamic(cpustate->vtlb);
502         break;
480503      case 2: CYCLES(cpustate,CYCLES_MOV_REG_CR2); break;
481      case 3: CYCLES(cpustate,CYCLES_MOV_REG_CR3); break;
504      case 3:
505         CYCLES(cpustate,CYCLES_MOV_REG_CR3);
506         vtlb_flush_dynamic(cpustate->vtlb);
507         break;
482508      case 4: CYCLES(cpustate,1); break; // TODO
483509      default:
484         fatalerror("i386: mov_cr_r32 CR%d !", cr);
510         fatalerror("i486: mov_cr_r32 CR%d !", cr);
485511         break;
486512   }
487513}
trunk/src/emu/cpu/i386/i386priv.h
r20642r20643
66#include "i386.h"
77#include "../../../lib/softfloat/milieu.h"
88#include "../../../lib/softfloat/softfloat.h"
9#include "cpu/vtlb.h"
910
1011//#define DEBUG_MISSING_OPCODE
1112
r20642r20643
360361   UINT8 *cycle_table_pm;
361362   UINT8 *cycle_table_rm;
362363
364   vtlb_state *vtlb;
365
363366   // bytes in current opcode, debug only
364367#ifdef DEBUG_MISSING_OPCODE
365368   UINT8 opcode_bytes[16];
r20642r20643
475478   return cpustate->sreg[segment].base + ip;
476479}
477480
478// rwn; read = 0, write = 1, none = -1, read at PL 0 = -2
479INLINE int translate_address(i386_state *cpustate, int rwn, UINT32 *address, UINT32 *error)
481#define VTLB_FLAG_DIRTY 0x100
482
483INLINE vtlb_entry get_permissions(UINT32 pte, int wp)
480484{
485   vtlb_entry ret = VTLB_READ_ALLOWED | ((pte & 4) ? VTLB_USER_READ_ALLOWED : 0);
486   if(!wp)
487      ret |= VTLB_WRITE_ALLOWED;
488   if(pte & 2)
489      ret |= VTLB_WRITE_ALLOWED | ((pte & 4) ? VTLB_USER_WRITE_ALLOWED : 0);
490   return ret;
491}
492
493static int i386_translate_address(i386_state *cpustate, int intention, offs_t *address, vtlb_entry *entry)
494{
481495   UINT32 a = *address;
482496   UINT32 pdbr = cpustate->cr[3] & 0xfffff000;
483497   UINT32 directory = (a >> 22) & 0x3ff;
484498   UINT32 table = (a >> 12) & 0x3ff;
485   UINT32 offset = a & 0xfff;
486   UINT32 page_entry;
487   UINT32 ret = 1;
488   bool user = (cpustate->CPL == 3) && (rwn >= 0);
489   *error = 0;
499   vtlb_entry perm = 0;
500   int ret = FALSE;
501   bool user = (intention & TRANSLATE_USER_MASK) ? true : false;
502   bool write = (intention & TRANSLATE_WRITE) ? true : false;
503   bool debug = (intention & TRANSLATE_DEBUG_MASK) ? true : false;
490504
505   if(!(cpustate->cr[0] & 0x80000000))
506   {
507      if(entry)
508         *entry = 0x77;
509      return TRUE;
510   }
511
491512   UINT32 page_dir = cpustate->program->read_dword(pdbr + directory * 4);
492   if((page_dir & 1) && ((page_dir & 4) || !user))
513   if(page_dir & 1)
493514   {
494      if (!(cpustate->cr[4] & 0x10))
515      if ((page_dir & 0x80) && (cpustate->cr[4] & 0x10))
495516      {
496         page_entry = cpustate->program->read_dword((page_dir & 0xfffff000) + (table * 4));
497         if(!(page_entry & 1))
498            ret = 0;
499         else if((!(page_entry & 2) && (user || WP) && (rwn == 1)) || (!(page_entry & 4) && user))
517         a = (page_dir & 0xffc00000) | (a & 0x003fffff);
518         if(debug)
500519         {
501            *error = 1;
502            ret = 0;
520            *address = a;
521            return TRUE;
503522         }
523         perm = get_permissions(page_dir, WP);
524         if(write && (!(perm & VTLB_WRITE_ALLOWED) || (user && !(perm & VTLB_USER_WRITE_ALLOWED))))
525            ret = FALSE;
526         else if(user && !(perm & VTLB_USER_READ_ALLOWED))
527            ret = FALSE;
504528         else
505529         {
506            if(!(page_dir & 0x20) && (rwn != -1))
530            if(!(page_dir & 0x40) && write)
531            {
532               cpustate->program->write_dword(pdbr + directory * 4, page_dir | 0x60);
533               perm |= VTLB_FLAG_DIRTY;
534            }
535            else if(!(page_dir & 0x20))
507536               cpustate->program->write_dword(pdbr + directory * 4, page_dir | 0x20);
508            if(!(page_entry & 0x40) && (rwn == 1))
509               cpustate->program->write_dword((page_dir & 0xfffff000) + (table * 4), page_entry | 0x60);
510            else if(!(page_entry & 0x20) && (rwn != -1))
511               cpustate->program->write_dword((page_dir & 0xfffff000) + (table * 4), page_entry | 0x20);
512            *address = (page_entry & 0xfffff000) | offset;
537            ret = TRUE;
513538         }
514539      }
515540      else
516541      {
517         if (page_dir & 0x80)
518         {
519            if(!(page_dir & 2) && (user || WP) && (rwn == 1))
520            {
521               *error = 1;
522               ret = 0;
523            }
524            else
525            {
526               if(!(page_dir & 0x40) && (rwn == 1))
527                  cpustate->program->write_dword(pdbr + directory * 4, page_dir | 0x60);
528               else if(!(page_dir & 0x20) && (rwn != -1))
529                  cpustate->program->write_dword(pdbr + directory * 4, page_dir | 0x20);
530               *address = (page_dir & 0xffc00000) | (a & 0x003fffff);
531            }
532         }
542         UINT32 page_entry = cpustate->program->read_dword((page_dir & 0xfffff000) + (table * 4));
543         if(!(page_entry & 1))
544            ret = FALSE;
533545         else
534546         {
535            page_entry = cpustate->program->read_dword((page_dir & 0xfffff000) + (table * 4));
536            if(!(page_entry & 1))
537               ret = 0;
538            else if((!(page_entry & 2) && (user || WP) && (rwn == 1)) || (!(page_entry & 4) && user))
547            a = (page_entry & 0xfffff000) | (a & 0xfff);
548            if(debug)
539549            {
540               *error = 1;
541               ret = 0;
550               *address = a;
551               return TRUE;
542552            }
553            perm = get_permissions(page_entry, WP);
554            if(write && (!(perm & VTLB_WRITE_ALLOWED) || (user && !(perm & VTLB_USER_WRITE_ALLOWED))))
555               ret = FALSE;
556            else if(user && !(perm & VTLB_USER_READ_ALLOWED))
557               ret = FALSE;
543558            else
544559            {
545               if(!(page_dir & 0x20) && (rwn != -1))
560               if(!(page_dir & 0x20))
546561                  cpustate->program->write_dword(pdbr + directory * 4, page_dir | 0x20);
547               if(!(page_entry & 0x40) && (rwn == 1))
562               if(!(page_entry & 0x40) && write)
563               {
548564                  cpustate->program->write_dword((page_dir & 0xfffff000) + (table * 4), page_entry | 0x60);
549               else if(!(page_entry & 0x20) && (rwn != -1))
565                  perm |= VTLB_FLAG_DIRTY;
566               }
567               else if(!(page_entry & 0x20))
550568                  cpustate->program->write_dword((page_dir & 0xfffff000) + (table * 4), page_entry | 0x20);
551               *address = (page_entry & 0xfffff000) | offset;
569               ret = TRUE;
552570            }
553571         }
554572      }
555573   }
556574   else
575      ret = FALSE;
576   if(entry)
577      *entry = perm;
578   if(ret)
579      *address = a;
580   return ret;
581}
582
583//#define TEST_TLB
584
585INLINE int translate_address(i386_state *cpustate, int pl, int type, UINT32 *address, UINT32 *error)
586{
587   const vtlb_entry *table = vtlb_table(cpustate->vtlb);
588   int index = *address >> 12;
589   vtlb_entry entry = table[index];
590   if(type == TRANSLATE_FETCH)
591      type = TRANSLATE_READ;
592   if(pl == 3)
593      type |= TRANSLATE_USER_MASK;
594#ifdef TEST_TLB
595   UINT32 test_addr = *address;
596#endif
597
598   if(!(entry & VTLB_FLAG_VALID) || ((type & TRANSLATE_WRITE) && !(entry & VTLB_FLAG_DIRTY)))
557599   {
558      if(page_dir & 1)
559         *error = 1;
560      ret = 0;
600      if(!i386_translate_address(cpustate, type, address, &entry))
601      {
602         *error = ((type & TRANSLATE_WRITE) ? 2 : 0) | ((cpustate->CPL == 3) ? 4 : 0);
603         if(entry)
604            *error |= 1;
605         return FALSE;
606      }
607      vtlb_dynload(cpustate->vtlb, index, *address, entry);
608      return TRUE;
561609   }
562   if(!ret)
610   if(!(entry & (1 << type)))
563611   {
564      if(rwn != -1)
565         *error |= ((rwn == 1)<<1) | ((cpustate->CPL == 3)<<2);
566      return 0;
612      *error = ((type & TRANSLATE_WRITE) ? 2 : 0) | ((cpustate->CPL == 3) ? 4 : 0) | 1;
613      return FALSE;
567614   }
568   return 1;
615   *address = (entry & 0xfffff000) | (*address & 0xfff);
616#ifdef TEST_TLB
617   int test_ret = i386_translate_address(cpustate, type | TRANSLATE_DEBUG_MASK, &test_addr, NULL);
618   if(!test_ret || (test_addr != *address))
619      logerror("TLB-PTE mismatch! %06X %06X %06x\n", *address, test_addr, cpustate->pc);
620#endif
621   return TRUE;
569622}
570623
571624INLINE void CHANGE_PC(i386_state *cpustate, UINT32 pc)
572625{
573   UINT32 address, error;
574626   cpustate->pc = i386_translate(cpustate, CS, pc, -1 );
575
576   address = cpustate->pc;
577
578   if (cpustate->cr[0] & 0x80000000)       // page translation enabled
579   {
580      translate_address(cpustate,-1,&address,&error);
581   }
582627}
583628
584629INLINE void NEAR_BRANCH(i386_state *cpustate, INT32 offs)
585630{
586   UINT32 address, error;
587631   /* TODO: limit */
588632   cpustate->eip += offs;
589633   cpustate->pc += offs;
590
591   address = cpustate->pc;
592
593   if (cpustate->cr[0] & 0x80000000)       // page translation enabled
594   {
595      translate_address(cpustate,-1,&address,&error);
596   }
597634}
598635
599636INLINE UINT8 FETCH(i386_state *cpustate)
r20642r20643
601638   UINT8 value;
602639   UINT32 address = cpustate->pc, error;
603640
604   if (cpustate->cr[0] & 0x80000000)       // page translation enabled
605   {
606      if(!translate_address(cpustate,0,&address,&error))
607         PF_THROW(error);
608   }
641   if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_FETCH,&address,&error))
642      PF_THROW(error);
609643
610644   value = cpustate->direct->read_decrypted_byte(address & cpustate->a20_mask);
611645#ifdef DEBUG_MISSING_OPCODE
r20642r20643
625659      value = (FETCH(cpustate) << 0) |
626660            (FETCH(cpustate) << 8);
627661   } else {
628      if (cpustate->cr[0] & 0x80000000)       // page translation enabled
629      {
630         if(!translate_address(cpustate,0,&address,&error))
631            PF_THROW(error);
632      }
662      if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_FETCH,&address,&error))
663         PF_THROW(error);
633664      address &= cpustate->a20_mask;
634665      value = cpustate->direct->read_decrypted_word(address);
635666      cpustate->eip += 2;
r20642r20643
648679            (FETCH(cpustate) << 16) |
649680            (FETCH(cpustate) << 24);
650681   } else {
651      if (cpustate->cr[0] & 0x80000000)       // page translation enabled
652      {
653         if(!translate_address(cpustate,0,&address,&error))
654            PF_THROW(error);
655      }
682      if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_FETCH,&address,&error))
683         PF_THROW(error);
656684
657685      address &= cpustate->a20_mask;
658686      value = cpustate->direct->read_decrypted_dword(address);
r20642r20643
666694{
667695   UINT32 address = ea, error;
668696
669   if (cpustate->cr[0] & 0x80000000)       // page translation enabled
670   {
671      if(!translate_address(cpustate,0,&address,&error))
672         PF_THROW(error);
673   }
697   if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_READ,&address, &error))
698      PF_THROW(error);
674699
675700   address &= cpustate->a20_mask;
676701   return cpustate->program->read_byte(address);
r20642r20643
684709      value = (READ8( cpustate, address+0 ) << 0) |
685710            (READ8( cpustate, address+1 ) << 8);
686711   } else {
687      if (cpustate->cr[0] & 0x80000000)       // page translation enabled
688      {
689         if(!translate_address(cpustate,0,&address,&error))
690            PF_THROW(error);
691      }
712      if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_READ,&address,&error))
713         PF_THROW(error);
692714
693715      address &= cpustate->a20_mask;
694716      value = cpustate->program->read_word( address );
r20642r20643
706728            (READ8( cpustate, address+2 ) << 16) |
707729            (READ8( cpustate, address+3 ) << 24);
708730   } else {
709      if (cpustate->cr[0] & 0x80000000)       // page translation enabled
710      {
711         if(!translate_address(cpustate,0,&address,&error))
712            PF_THROW(error);
713      }
731      if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_READ,&address,&error))
732         PF_THROW(error);
714733
715734      address &= cpustate->a20_mask;
716735      value = cpustate->program->read_dword( address );
r20642r20643
733752            (((UINT64) READ8( cpustate, address+6 )) << 48) |
734753            (((UINT64) READ8( cpustate, address+7 )) << 56);
735754   } else {
736      if (cpustate->cr[0] & 0x80000000)       // page translation enabled
737      {
738         if(!translate_address(cpustate,0,&address,&error))
739            PF_THROW(error);
740      }
755      if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_READ,&address,&error))
756         PF_THROW(error);
741757
742758      address &= cpustate->a20_mask;
743759      value = (((UINT64) cpustate->program->read_dword( address+0 )) << 0) |
r20642r20643
749765{
750766   UINT32 address = ea, error;
751767
752   if (cpustate->cr[0] & 0x80000000)       // page translation enabled
753   {
754      if(!translate_address(cpustate,-2,&address,&error))
755         PF_THROW(error);
756   }
768   if(!translate_address(cpustate,0,TRANSLATE_READ,&address,&error))
769      PF_THROW(error);
757770
758771   address &= cpustate->a20_mask;
759772   return cpustate->program->read_byte(address);
r20642r20643
767780      value = (READ8PL0( cpustate, address+0 ) << 0) |
768781            (READ8PL0( cpustate, address+1 ) << 8);
769782   } else {
770      if (cpustate->cr[0] & 0x80000000)       // page translation enabled
771      {
772         if(!translate_address(cpustate,-2,&address,&error))
773            PF_THROW(error);
774      }
783      if(!translate_address(cpustate,0,TRANSLATE_READ,&address,&error))
784         PF_THROW(error);
775785
776786      address &= cpustate->a20_mask;
777787      value = cpustate->program->read_word( address );
r20642r20643
789799            (READ8PL0( cpustate, address+2 ) << 16) |
790800            (READ8PL0( cpustate, address+3 ) << 24);
791801   } else {
792      if (cpustate->cr[0] & 0x80000000)       // page translation enabled
793      {
794         if(!translate_address(cpustate,-2,&address,&error))
795            PF_THROW(error);
796      }
802      if(!translate_address(cpustate,0,TRANSLATE_READ,&address,&error))
803         PF_THROW(error);
797804
798805      address &= cpustate->a20_mask;
799806      value = cpustate->program->read_dword( address );
r20642r20643
804811INLINE void WRITE_TEST(i386_state *cpustate,UINT32 ea)
805812{
806813   UINT32 address = ea, error;
807   if (cpustate->cr[0] & 0x80000000)       // page translation enabled
808   {
809      if(!translate_address(cpustate,1,&address,&error))
810         PF_THROW(error);
811   }
814   if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_WRITE,&address,&error))
815      PF_THROW(error);
812816}
813817
814818INLINE void WRITE8(i386_state *cpustate,UINT32 ea, UINT8 value)
815819{
816820   UINT32 address = ea, error;
817821
818   if (cpustate->cr[0] & 0x80000000)       // page translation enabled
819   {
820      if(!translate_address(cpustate,1,&address,&error))
821         PF_THROW(error);
822   }
822   if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_WRITE,&address,&error))
823      PF_THROW(error);
823824
824825   address &= cpustate->a20_mask;
825826   cpustate->program->write_byte(address, value);
r20642r20643
832833      WRITE8( cpustate, address+0, value & 0xff );
833834      WRITE8( cpustate, address+1, (value >> 8) & 0xff );
834835   } else {
835      if (cpustate->cr[0] & 0x80000000)       // page translation enabled
836      {
837         if(!translate_address(cpustate,1,&address,&error))
838            PF_THROW(error);
839      }
836      if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_WRITE,&address,&error))
837         PF_THROW(error);
840838
841839      address &= cpustate->a20_mask;
842840      cpustate->program->write_word(address, value);
r20642r20643
852850      WRITE8( cpustate, address+2, (value >> 16) & 0xff );
853851      WRITE8( cpustate, address+3, (value >> 24) & 0xff );
854852   } else {
855      if (cpustate->cr[0] & 0x80000000)       // page translation enabled
856      {
857         if(!translate_address(cpustate,1,&address,&error))
858            PF_THROW(error);
859      }
853      if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_WRITE,&address,&error))
854         PF_THROW(error);
860855
861856      ea &= cpustate->a20_mask;
862857      cpustate->program->write_dword(address, value);
r20642r20643
877872      WRITE8( cpustate, address+6, (value >> 48) & 0xff );
878873      WRITE8( cpustate, address+7, (value >> 56) & 0xff );
879874   } else {
880      if (cpustate->cr[0] & 0x80000000)       // page translation enabled
881      {
882         if(!translate_address(cpustate,1,&address,&error))
883            PF_THROW(error);
884      }
875      if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_WRITE,&address,&error))
876         PF_THROW(error);
885877
886878      ea &= cpustate->a20_mask;
887879      cpustate->program->write_dword(address+0, value & 0xffffffff);
trunk/src/emu/cpu/i386/i386.c
r20642r20643
108108static void i386_set_descriptor_accessed(i386_state *cpustate, UINT16 selector)
109109{
110110   // assume the selector is valid, we don't need to check it again
111   UINT32 base, addr, error;
111   UINT32 base, addr;
112112   UINT8 rights;
113113   if(!(selector & ~3))
114114      return;
r20642r20643
119119      base = cpustate->gdtr.base;
120120
121121   addr = base + (selector & ~7) + 5;
122   translate_address(cpustate, -2, &addr, &error);
122   i386_translate_address(cpustate, TRANSLATE_READ, &addr, NULL);
123123   rights = cpustate->program->read_byte(addr);
124124   // Should a fault be thrown if the table is read only?
125125   cpustate->program->write_byte(addr, rights | 1);
r20642r20643
11061106   I386_SREG seg;
11071107   UINT16 old_task;
11081108   UINT8 ar_byte;  // access rights byte
1109   UINT32 oldcr3 = cpustate->cr[3];
11091110
11101111   /* TODO: Task State Segment privilege checks */
11111112
r20642r20643
11661167   cpustate->ldtr.limit = seg.limit;
11671168   cpustate->ldtr.base = seg.base;
11681169   cpustate->ldtr.flags = seg.flags;
1169   cpustate->cr[3] = READ32(cpustate,tss+0x1c);  // CR3 (PDBR)
11701170   cpustate->eip = READ32(cpustate,tss+0x20);
11711171   set_flags(cpustate,READ32(cpustate,tss+0x24));
11721172   REG32(EAX) = READ32(cpustate,tss+0x28);
r20642r20643
11891189   i386_load_segment_descriptor(cpustate, FS);
11901190   cpustate->sreg[GS].selector = READ32(cpustate,tss+0x5c) & 0xffff;
11911191   i386_load_segment_descriptor(cpustate, GS);
1192   /* For nested tasks, we write the outgoing task's selector to the back-link field of the new TSS,
1193      and set the NT flag in the EFLAGS register before settings cr3 as the old tss address might be gone */
1194   if(nested != 0)
1195   {
1196      WRITE32(cpustate,tss+0,old_task);
1197      cpustate->NT = 1;
1198   }
1199   cpustate->cr[3] = READ32(cpustate,tss+0x1c);  // CR3 (PDBR)
1200   if(oldcr3 != cpustate->cr[3])
1201      vtlb_flush_dynamic(cpustate->vtlb);
11921202
11931203   /* Set the busy bit in the new task's descriptor */
11941204   if(selector & 0x0004)
r20642r20643
12021212      WRITE8(cpustate,cpustate->gdtr.base + (selector & ~0x0007) + 5,ar_byte | 0x02);
12031213   }
12041214
1205   /* For nested tasks, we write the outgoing task's selector to the back-link field of the new TSS,
1206      and set the NT flag in the EFLAGS register */
1207   if(nested != 0)
1208   {
1209      WRITE32(cpustate,tss+0,old_task);
1210      cpustate->NT = 1;
1211   }
12121215   CHANGE_PC(cpustate,cpustate->eip);
12131216
12141217   cpustate->CPL = cpustate->sreg[CS].selector & 0x03;
r20642r20643
13441347            return;
13451348         case 0x04:  // 286 Call Gate
13461349         case 0x0c:  // 386 Call Gate
1347            logerror("JMP: Call gate at %08x\n",cpustate->pc);
1350            //logerror("JMP: Call gate at %08x\n",cpustate->pc);
13481351            SetRPL = 1;
13491352            memset(&call_gate, 0, sizeof(call_gate));
13501353            call_gate.segment = segment;
r20642r20643
16391642            gate.segment = selector;
16401643            i386_load_call_gate(cpustate,&gate);
16411644            DPL = gate.dpl;
1642            logerror("CALL: Call gate at %08x (%i parameters)\n",cpustate->pc,gate.dword_count);
1645            //logerror("CALL: Call gate at %08x (%i parameters)\n",cpustate->pc,gate.dword_count);
16431646            if(DPL < CPL)
16441647            {
16451648               logerror("CALL: Call gate DPL %i is less than CPL %i.\n",DPL,CPL);
r20642r20643
27952798
27962799static UINT8 read8_debug(i386_state *cpustate, UINT32 ea, UINT8 *data)
27972800{
2798   UINT32 address = ea, error;
2801   UINT32 address = ea;
27992802
2800   if (cpustate->cr[0] & 0x80000000)       // page translation enabled
2801   {
2802      if(!translate_address(cpustate,-1,&address,&error))
2803         return 0;
2804   }
2803   if(!i386_translate_address(cpustate,TRANSLATE_DEBUG_MASK,&address,NULL))
2804      return 0;
28052805
2806   address &= cpustate->a20_mask;
28072806   *data = cpustate->program->read_byte(address);
28082807   return 1;
28092808}
r20642r20643
29412940{
29422941   legacy_cpu_device *device = (legacy_cpu_device *)ref;
29432942   i386_state *cpustate = get_safe_token(device);
2944   UINT32 result = param[0], error;
2943   UINT32 result = param[0];
29452944
2946   if (cpustate->cr[0] & 0x80000000)
2947   {
2948      if(!translate_address(cpustate,-1,&result,&error))
2949         return 0;
2950   }
2945   if(!i386_translate_address(cpustate,TRANSLATE_DEBUG_MASK,&result,NULL))
2946      return 0;
29512947   return result;
29522948}
29532949
r20642r20643
29692965   CHANGE_PC(cpustate,cpustate->eip);
29702966}
29712967
2972static CPU_INIT( i386 )
2968static void i386_common_init(legacy_cpu_device *device, device_irq_acknowledge_callback irqcallback, int tlbsize)
29732969{
29742970   int i, j;
29752971   static const int regs8[8] = {AL,CL,DL,BL,AH,CH,DH,BH};
r20642r20643
30032999   cpustate->program = &device->space(AS_PROGRAM);
30043000   cpustate->direct = &cpustate->program->direct();
30053001   cpustate->io = &device->space(AS_IO);
3002   cpustate->vtlb = vtlb_alloc(device, AS_PROGRAM, 0, tlbsize);
30063003
30073004   device->save_item(NAME( cpustate->reg.d));
30083005   device->save_item(NAME(cpustate->sreg[ES].selector));
r20642r20643
30613058   device->machine().save().register_postload(save_prepost_delegate(FUNC(i386_postload), cpustate));
30623059}
30633060
3061CPU_INIT( i386 )
3062{
3063   i386_common_init(device, irqcallback, 32);
3064}
3065
30643066static void build_opcode_table(i386_state *cpustate, UINT32 features)
30653067{
30663068   int i;
r20642r20643
31193121{
31203122   i386_state *cpustate = get_safe_token(device);
31213123   device_irq_acknowledge_callback save_irqcallback;
3124   vtlb_state *save_vtlb = cpustate->vtlb;
31223125
31233126   save_irqcallback = cpustate->irq_callback;
31243127   memset( cpustate, 0, sizeof(*cpustate) );
3128   vtlb_flush_dynamic(save_vtlb);
3129   cpustate->vtlb = save_vtlb;
31253130   cpustate->irq_callback = save_irqcallback;
31263131   cpustate->device = device;
31273132   cpustate->program = &device->space(AS_PROGRAM);
r20642r20643
31933198   {
31943199      cpustate->a20_mask = ~(1 << 20);
31953200   }
3201   // TODO: how does A20M and the tlb interact
3202   vtlb_flush_dynamic(cpustate->vtlb);
31963203}
31973204
31983205static CPU_EXECUTE( i386 )
r20642r20643
32603267static CPU_TRANSLATE( i386 )
32613268{
32623269   i386_state *cpustate = get_safe_token(device);
3263   int result = 1;
3264   UINT32 error;
3265   if (space == AS_PROGRAM)
3266   {
3267      if (cpustate->cr[0] & 0x80000000)
3268         result = translate_address(cpustate,-1,address,&error);
3269      *address &= cpustate->a20_mask;
3270   }
3271   return result;
3270   int ret = TRUE;
3271   if(space == AS_PROGRAM)
3272      ret = i386_translate_address(cpustate, intention, address, NULL);
3273   *address &= cpustate->a20_mask;
3274   return ret;
32723275}
32733276
32743277static CPU_DISASSEMBLE( i386 )
r20642r20643
36033606
36043607static CPU_INIT( i486 )
36053608{
3606   CPU_INIT_CALL(i386);
3609   i386_common_init(device, irqcallback, 32);
36073610}
36083611
36093612static CPU_RESET( i486 )
36103613{
36113614   i386_state *cpustate = get_safe_token(device);
36123615   device_irq_acknowledge_callback save_irqcallback;
3616   vtlb_state *save_vtlb = cpustate->vtlb;
36133617
36143618   save_irqcallback = cpustate->irq_callback;
36153619   memset( cpustate, 0, sizeof(*cpustate) );
3620   vtlb_flush_dynamic(save_vtlb);
3621   cpustate->vtlb = save_vtlb;
36163622   cpustate->irq_callback = save_irqcallback;
36173623   cpustate->device = device;
36183624   cpustate->program = &device->space(AS_PROGRAM);
r20642r20643
37103716
37113717static CPU_INIT( pentium )
37123718{
3713   CPU_INIT_CALL(i386);
3719   // 64 dtlb small, 8 dtlb large, 32 itlb
3720   i386_common_init(device, irqcallback, 96);
37143721}
37153722
37163723static CPU_RESET( pentium )
37173724{
37183725   i386_state *cpustate = get_safe_token(device);
37193726   device_irq_acknowledge_callback save_irqcallback;
3727   vtlb_state *save_vtlb = cpustate->vtlb;
37203728
37213729   save_irqcallback = cpustate->irq_callback;
37223730   memset( cpustate, 0, sizeof(*cpustate) );
3731   vtlb_flush_dynamic(save_vtlb);
3732   cpustate->vtlb = save_vtlb;
37233733   cpustate->irq_callback = save_irqcallback;
37243734   cpustate->device = device;
37253735   cpustate->program = &device->space(AS_PROGRAM);
r20642r20643
38333843
38343844static CPU_INIT( mediagx )
38353845{
3836   CPU_INIT_CALL(i386);
3846   // probably 32 unified
3847   i386_common_init(device, irqcallback, 32);
38373848}
38383849
38393850static CPU_RESET( mediagx )
38403851{
38413852   i386_state *cpustate = get_safe_token(device);
38423853   device_irq_acknowledge_callback save_irqcallback;
3854   vtlb_state *save_vtlb = cpustate->vtlb;
38433855
38443856   save_irqcallback = cpustate->irq_callback;
38453857   memset( cpustate, 0, sizeof(*cpustate) );
3858   vtlb_flush_dynamic(save_vtlb);
3859   cpustate->vtlb = save_vtlb;
38463860   cpustate->irq_callback = save_irqcallback;
38473861   cpustate->device = device;
38483862   cpustate->program = &device->space(AS_PROGRAM);
r20642r20643
39483962
39493963static CPU_INIT( pentium_pro )
39503964{
3951   CPU_INIT_CALL(pentium);
3965   // 64 dtlb small, 32 itlb
3966   i386_common_init(device, irqcallback, 96);
39523967}
39533968
39543969static CPU_RESET( pentium_pro )
39553970{
39563971   i386_state *cpustate = get_safe_token(device);
39573972   device_irq_acknowledge_callback save_irqcallback;
3973   vtlb_state *save_vtlb = cpustate->vtlb;
39583974
39593975   save_irqcallback = cpustate->irq_callback;
39603976   memset( cpustate, 0, sizeof(*cpustate) );
3977   vtlb_flush_dynamic(save_vtlb);
3978   cpustate->vtlb = save_vtlb;
39613979   cpustate->irq_callback = save_irqcallback;
39623980   cpustate->device = device;
39633981   cpustate->program = &device->space(AS_PROGRAM);
r20642r20643
40444062
40454063static CPU_INIT( pentium_mmx )
40464064{
4047   CPU_INIT_CALL(pentium);
4065   // 64 dtlb small, 8 dtlb large, 32 itlb small, 2 itlb large
4066   i386_common_init(device, irqcallback, 96);
40484067}
40494068
40504069static CPU_RESET( pentium_mmx )
40514070{
40524071   i386_state *cpustate = get_safe_token(device);
40534072   device_irq_acknowledge_callback save_irqcallback;
4073   vtlb_state *save_vtlb = cpustate->vtlb;
40544074
40554075   save_irqcallback = cpustate->irq_callback;
40564076   memset( cpustate, 0, sizeof(*cpustate) );
4077   vtlb_flush_dynamic(save_vtlb);
4078   cpustate->vtlb = save_vtlb;
40574079   cpustate->irq_callback = save_irqcallback;
40584080   cpustate->device = device;
40594081   cpustate->program = &device->space(AS_PROGRAM);
r20642r20643
41404162
41414163static CPU_INIT( pentium2 )
41424164{
4143   CPU_INIT_CALL(pentium);
4165   // 64 dtlb small, 8 dtlb large, 32 itlb small, 2 itlb large
4166   i386_common_init(device, irqcallback, 96);
41444167}
41454168
41464169static CPU_RESET( pentium2 )
41474170{
41484171   i386_state *cpustate = get_safe_token(device);
41494172   device_irq_acknowledge_callback save_irqcallback;
4173   vtlb_state *save_vtlb = cpustate->vtlb;
41504174
41514175   save_irqcallback = cpustate->irq_callback;
41524176   memset( cpustate, 0, sizeof(*cpustate) );
4177   vtlb_flush_dynamic(save_vtlb);
4178   cpustate->vtlb = save_vtlb;
41534179   cpustate->irq_callback = save_irqcallback;
41544180   cpustate->device = device;
41554181   cpustate->program = &device->space(AS_PROGRAM);
r20642r20643
42364262
42374263static CPU_INIT( pentium3 )
42384264{
4239   CPU_INIT_CALL(pentium);
4265   // 64 dtlb small, 8 dtlb large, 32 itlb small, 2 itlb large
4266   i386_common_init(device, irqcallback, 96);
42404267}
42414268
42424269static CPU_RESET( pentium3 )
42434270{
42444271   i386_state *cpustate = get_safe_token(device);
42454272   device_irq_acknowledge_callback save_irqcallback;
4273   vtlb_state *save_vtlb = cpustate->vtlb;
42464274
42474275   save_irqcallback = cpustate->irq_callback;
42484276   memset( cpustate, 0, sizeof(*cpustate) );
4277   vtlb_flush_dynamic(save_vtlb);
4278   cpustate->vtlb = save_vtlb;
42494279   cpustate->irq_callback = save_irqcallback;
42504280   cpustate->device = device;
42514281   cpustate->program = &device->space(AS_PROGRAM);
r20642r20643
43344364
43354365static CPU_INIT( pentium4 )
43364366{
4337   CPU_INIT_CALL(pentium);
4367   // 128 dtlb, 64 itlb
4368   i386_common_init(device, irqcallback, 196);
43384369}
43394370
43404371static CPU_RESET( pentium4 )
43414372{
43424373   i386_state *cpustate = get_safe_token(device);
43434374   device_irq_acknowledge_callback save_irqcallback;
4375   vtlb_state *save_vtlb = cpustate->vtlb;
43444376
43454377   save_irqcallback = cpustate->irq_callback;
43464378   memset( cpustate, 0, sizeof(*cpustate) );
4379   vtlb_flush_dynamic(save_vtlb);
4380   cpustate->vtlb = save_vtlb;
43474381   cpustate->irq_callback = save_irqcallback;
43484382   cpustate->device = device;
43494383   cpustate->program = &device->space(AS_PROGRAM);
trunk/src/emu/cpu/vtlb.c
r20642r20643
225225      vtlb->table[tableindex + pagenum] = value + (pagenum << vtlb->pageshift);
226226}
227227
228/*-------------------------------------------------
229    vtlb_dynload - load a dynamic VTLB entry
230-------------------------------------------------*/
228231
232void vtlb_dynload(vtlb_state *vtlb, int index, offs_t address, vtlb_entry value)
233{
234   vtlb_entry entry = vtlb->table[index];
235   value &= VTLB_FLAGS_MASK;
229236
237   if (vtlb->dynamic == 0)
238   {
239      if (PRINTF_TLB)
240         printf("failed: no dynamic entries\n");
241      return;
242   }
243
244   int liveindex = vtlb->dynindex++ % vtlb->dynamic;
245   /* is entry already live? */
246   if (!(entry & VTLB_FLAG_VALID))
247   {
248      /* if an entry already exists at this index, free it */
249      if (vtlb->live[liveindex] != 0)
250         vtlb->table[vtlb->live[liveindex] - 1] = 0;
251
252      /* claim this new entry */
253      vtlb->live[liveindex] = index + 1;
254   }
255   /* form a new blank entry */
256   entry = (address >> vtlb->pageshift) << vtlb->pageshift;
257   entry |= VTLB_FLAG_VALID | value;
258
259   if (PRINTF_TLB)
260      printf("success (%08X), new entry\n", address);
261
262   vtlb->table[index] = entry;
263}
264
230265/***************************************************************************
231266    FLUSHING
232267***************************************************************************/
trunk/src/emu/cpu/vtlb.h
r20642r20643
6969/* load a fixed VTLB entry */
7070void vtlb_load(vtlb_state *vtlb, int entrynum, int numpages, offs_t address, vtlb_entry value);
7171
72/* load a dynamic VTLB entry */
73void vtlb_dynload(vtlb_state *vtlb, int index, offs_t address, vtlb_entry value);
7274
7375/* ----- flushing ----- */
7476

Previous 199869 Revisions Next


© 1997-2024 The MAME Team