/[gxemul]/trunk/src/cpus/cpu_mips_coproc.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /trunk/src/cpus/cpu_mips_coproc.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 26 by dpavlin, Mon Oct 8 16:20:10 2007 UTC revision 30 by dpavlin, Mon Oct 8 16:20:40 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: cpu_mips_coproc.c,v 1.37 2006/06/25 02:46:07 debug Exp $   *  $Id: cpu_mips_coproc.c,v 1.53 2006/08/11 17:43:30 debug Exp $
29   *   *
30   *  Emulation of MIPS coprocessors.   *  Emulation of MIPS coprocessors.
31   */   */
# Line 533  static void invalidate_asid(struct cpu * Line 533  static void invalidate_asid(struct cpu *
533                                      INVALIDATE_VADDR);                                      INVALIDATE_VADDR);
534                          }                          }
535          } else {          } else {
536                  /*  TODO: Implement support for other.  */                  int non4kpages = 0;
537                  cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);                  uint64_t topbit = 1, fillmask = 0xffffff0000000000ULL;
538    
539                    if (cpu->is_32bit) {
540                            topbit = 0x80000000;
541                            fillmask = 0xffffffff00000000ULL;
542                    } else if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) {
543                            topbit <<= 43;
544                            fillmask <<= 4;
545                    } else {
546                            topbit <<= 39;
547                    }
548    
549                    for (i=0; i<ntlbs; i++) {
550                            if (tlb[i].mask != 0 && tlb[i].mask != 0x1800) {
551                                    non4kpages = 1;
552                                    continue;
553                            }
554    
555                            if ((tlb[i].hi & ENTRYHI_ASID) == asid &&
556                                !(tlb[i].hi & TLB_G)) {
557                                    uint64_t vaddr0, vaddr1;
558                                    vaddr0 = cp->tlbs[i].hi & ~fillmask;
559                                    if (vaddr0 & topbit)
560                                            vaddr0 |= fillmask;
561                                    vaddr1 = vaddr0 | 0x1000;  /*  TODO: mask  */
562    
563                                    if (tlb[i].lo0 & ENTRYLO_V)
564                                            cpu->invalidate_translation_caches(cpu,
565                                                vaddr0, INVALIDATE_VADDR);
566                                    if (tlb[i].lo1 & ENTRYLO_V)
567                                            cpu->invalidate_translation_caches(cpu,
568                                                vaddr1, INVALIDATE_VADDR);
569                            }
570                    }
571    
572                    if (non4kpages) {
573                            cpu->invalidate_translation_caches(cpu,
574                                0, INVALIDATE_ALL);
575                    }
576          }          }
577  }  }
578    
# Line 821  void coproc_register_write(struct cpu *c Line 859  void coproc_register_write(struct cpu *c
859                                          cpu->invalidate_translation_caches(                                          cpu->invalidate_translation_caches(
860                                              cpu, 0, INVALIDATE_ALL);                                              cpu, 0, INVALIDATE_ALL);
861                                  }                                  }
   
 #if 1  
                                 /*  
                                  *  NOTE: This is not needed for NetBSD, but  
                                  *  Ultrix and Linux still needs this. They  
                                  *  shouldn't, though. Something else is buggy.  
                                  */  
                                 cpu_create_or_reset_tc(cpu);  
 #endif  
862                          }                          }
863                          unimpl = 0;                          unimpl = 0;
864                          break;                          break;
# Line 1175  static int fpu_function(struct cpu *cpu, Line 1204  static int fpu_function(struct cpu *cpu,
1204    
1205          /*  bc1f, bc1t, bc1fl, bc1tl:  */          /*  bc1f, bc1t, bc1fl, bc1tl:  */
1206          if ((function & 0x03e00000) == 0x01000000) {          if ((function & 0x03e00000) == 0x01000000) {
1207                  int nd, tf, imm, cond_true;                  int nd, tf, imm;
1208                  char *instr_mnem;                  char *instr_mnem;
1209    
1210                  /*  cc are bits 20..18:  */                  /*  cc are bits 20..18:  */
# Line 1198  static int fpu_function(struct cpu *cpu, Line 1227  static int fpu_function(struct cpu *cpu,
1227                  if (unassemble_only)                  if (unassemble_only)
1228                          return 1;                          return 1;
1229    
1230                  if (cpu->delay_slot) {                  fatal("INTERNAL ERROR: MIPS coprocessor branches should not"
1231                          fatal("%s: jump inside a jump's delay slot, "                      " be implemented in cpu_mips_coproc.c, but in"
1232                              "or similar. TODO\n", instr_mnem);                      " cpu_mips_instr.c!\n");
1233                          cpu->running = 0;                  exit(1);
                         return 1;  
                 }  
   
                 /*  Both the FCCR and FCSR contain condition code bits...  */  
                 if (cc == 0)  
                         cond_true = (cp->fcr[MIPS_FPU_FCSR] >>  
                             MIPS_FCSR_FCC0_SHIFT) & 1;  
                 else  
                         cond_true = (cp->fcr[MIPS_FPU_FCSR] >>  
                             (MIPS_FCSR_FCC1_SHIFT + cc-1)) & 1;  
   
                 if (!tf)  
                         cond_true = !cond_true;  
   
                 if (cond_true) {  
                         cpu->delay_slot = TO_BE_DELAYED;  
                         cpu->delay_jmpaddr = cpu->pc + (imm << 2);  
                 } else {  
                         /*  "likely":  */  
                         if (nd) {  
                                 /*  nullify the delay slot  */  
                                 cpu->cd.mips.nullify_next = 1;  
                         }  
                 }  
   
                 return 1;  
1234          }          }
1235    
1236          /*  add.fmt: Floating-point add  */          /*  add.fmt: Floating-point add  */
# Line 1441  void coproc_tlbpr(struct cpu *cpu, int r Line 1444  void coproc_tlbpr(struct cpu *cpu, int r
1444                              R2K3K_INDEX_SHIFT;                              R2K3K_INDEX_SHIFT;
1445                          if (i >= cp->nr_of_tlbs) {                          if (i >= cp->nr_of_tlbs) {
1446                                  /*  TODO:  exception?  */                                  /*  TODO:  exception?  */
1447                                  fatal("warning: tlbr from index %i (too "                                  fatal("[ warning: tlbr from index %i (too "
1448                                      "high)\n", i);                                      "high) ]\n", i);
1449                                  return;                                  return;
1450                          }                          }
1451    
1452                          /*                          cp->reg[COP0_ENTRYHI]  = cp->tlbs[i].hi;
1453                           *  TODO: Hm. Earlier I had an & ~0x3f on the high                          cp->reg[COP0_ENTRYLO0] = cp->tlbs[i].lo0;
                          *  assignment and an & ~0xff on the lo0 assignment.  
                          *  I wonder why.  
                          */  
   
                         cp->reg[COP0_ENTRYHI]  = cp->tlbs[i].hi; /* & ~0x3f; */  
                         cp->reg[COP0_ENTRYLO0] = cp->tlbs[i].lo0;/* & ~0xff; */  
1454                  } else {                  } else {
1455                          /*  R4000:  */                          /*  R4000:  */
1456                          i = cp->reg[COP0_INDEX] & INDEX_MASK;                          i = cp->reg[COP0_INDEX] & INDEX_MASK;
# Line 1550  void coproc_tlbpr(struct cpu *cpu, int r Line 1547  void coproc_tlbpr(struct cpu *cpu, int r
1547  void coproc_tlbwri(struct cpu *cpu, int randomflag)  void coproc_tlbwri(struct cpu *cpu, int randomflag)
1548  {  {
1549          struct mips_coproc *cp = cpu->cd.mips.coproc[0];          struct mips_coproc *cp = cpu->cd.mips.coproc[0];
1550          int index, g_bit, old_asid = -1;          int index, g_bit;
1551          uint64_t oldvaddr;          uint64_t oldvaddr;
1552    
1553          if (randomflag) {          if (randomflag) {
1554                  if (cpu->cd.mips.cpu_type.exc_model == EXC3K) {                  if (cpu->cd.mips.cpu_type.exc_model == EXC3K) {
1555                          cp->reg[COP0_RANDOM] =                          index = ((cp->reg[COP0_RANDOM] & R2K3K_RANDOM_MASK)
1556                              ((random() % (cp->nr_of_tlbs - 8)) + 8)                              >> R2K3K_RANDOM_SHIFT) - 1;
1557                              << R2K3K_RANDOM_SHIFT;                          /*  R3000 always has 8 wired entries:  */
1558                          index = (cp->reg[COP0_RANDOM] & R2K3K_RANDOM_MASK)                          if (index < 8)
1559                              >> R2K3K_RANDOM_SHIFT;                                  index = cp->nr_of_tlbs - 1;
1560                            cp->reg[COP0_RANDOM] = index << R2K3K_RANDOM_SHIFT;
1561                  } else {                  } else {
1562                          cp->reg[COP0_RANDOM] = cp->reg[COP0_WIRED] + (random()                          cp->reg[COP0_RANDOM] = cp->reg[COP0_WIRED] + (random()
1563                              % (cp->nr_of_tlbs - cp->reg[COP0_WIRED]));                              % (cp->nr_of_tlbs - cp->reg[COP0_WIRED]));
# Line 1606  void coproc_tlbwri(struct cpu *cpu, int Line 1604  void coproc_tlbwri(struct cpu *cpu, int
1604          /*          /*
1605           *  Any virtual address translation for the old TLB entry must be           *  Any virtual address translation for the old TLB entry must be
1606           *  invalidated first:           *  invalidated first:
1607             *
1608             *  (Only Valid entries need to be invalidated, and only those that
1609             *  are either Global, or have the same ASID as the new entry will
1610             *  have. No other address translations should be active anyway.)
1611           */           */
1612    
1613          switch (cpu->cd.mips.cpu_type.mmu_model) {          switch (cpu->cd.mips.cpu_type.mmu_model) {
1614    
1615          case MMU3K:          case MMU3K:
1616                  oldvaddr = cp->tlbs[index].hi & R2K3K_ENTRYHI_VPN_MASK;                  oldvaddr = cp->tlbs[index].hi & R2K3K_ENTRYHI_VPN_MASK;
1617                  oldvaddr &= 0xffffffffULL;                  oldvaddr = (int32_t) oldvaddr;
                 if (oldvaddr & 0x80000000ULL)  
                         oldvaddr |= 0xffffffff00000000ULL;  
                 old_asid = (cp->tlbs[index].hi & R2K3K_ENTRYHI_ASID_MASK)  
                     >> R2K3K_ENTRYHI_ASID_SHIFT;  
1618    
1619                  cpu->invalidate_translation_caches(cpu, oldvaddr,                  if (cp->tlbs[index].lo0 & R2K3K_ENTRYLO_V &&
1620                      INVALIDATE_VADDR);                      (cp->tlbs[index].lo0 & R2K3K_ENTRYLO_G ||
1621                        (cp->tlbs[index].hi & R2K3K_ENTRYHI_ASID_MASK) ==
1622                        (cp->reg[COP0_ENTRYHI] & R2K3K_ENTRYHI_ASID_MASK) ))
1623                            cpu->invalidate_translation_caches(cpu, oldvaddr,
1624                                INVALIDATE_VADDR);
1625                  break;                  break;
1626    
1627          default:if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) {          default:if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) {
# Line 1639  void coproc_tlbwri(struct cpu *cpu, int Line 1641  void coproc_tlbwri(struct cpu *cpu, int
1641                                  oldvaddr |= 0xffffff0000000000ULL;                                  oldvaddr |= 0xffffff0000000000ULL;
1642                  }                  }
1643    
1644  #if 1  #if 0
1645                    /*  TODO: FIX THIS! It shouldn't be needed!  */
1646                  cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);                  cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);
1647  #else  #else
1648                  /*                  /*
1649                   *  TODO: non-4KB page sizes!                   *  TODO: non-4KB page sizes!
1650                   */                   */
1651                  cpu->invalidate_translation_caches(cpu, oldvaddr,                  if (cp->tlbs[index].lo0 & ENTRYLO_V)
1652                      INVALIDATE_VADDR);                          cpu->invalidate_translation_caches(cpu, oldvaddr,
1653                  cpu->invalidate_translation_caches(cpu, oldvaddr | 0x1000,                              INVALIDATE_VADDR);
1654                      INVALIDATE_VADDR);                  if (cp->tlbs[index].lo1 & ENTRYLO_V)
1655                            cpu->invalidate_translation_caches(cpu, oldvaddr|0x1000,
1656                                INVALIDATE_VADDR);
1657  #endif  #endif
1658          }          }
1659    
1660    #if 0
1661          /*          /*
1662           *  Check for duplicate entries.  (There should not be two mappings           *  Check for duplicate entries.  (There should not be two mappings
1663           *  from one virtual address to physical addresses.)           *  from one virtual address to physical addresses.)
# Line 1690  void coproc_tlbwri(struct cpu *cpu, int Line 1695  void coproc_tlbwri(struct cpu *cpu, int
1695                                      (long long)vaddr1, asid, i);                                      (long long)vaddr1, asid, i);
1696                  }                  }
1697          }          }
1698    #endif
1699    
1700          /*  Write the new entry:  */          /*  Write the new entry:  */
1701    
# Line 1714  void coproc_tlbwri(struct cpu *cpu, int Line 1719  void coproc_tlbwri(struct cpu *cpu, int
1719                              INVALIDATE_PADDR);                              INVALIDATE_PADDR);
1720                  }                  }
1721    
1722                    if (cp->reg[COP0_STATUS] & MIPS1_ISOL_CACHES) {
1723                            fatal("Wow! Interesting case; tlbw* while caches"
1724                                " are isolated. TODO\n");
1725                            /*  Don't update the translation table in this
1726                                case...  */
1727                            exit(1);
1728                    }
1729    
1730                  /*  If we have a memblock (host page) for the physical                  /*  If we have a memblock (host page) for the physical
1731                      page, then add a translation for it immediately:  */                      page, then add a translation for it immediately:  */
1732                  if (memblock != NULL &&                  if (memblock != NULL &&
1733                      cp->reg[COP0_ENTRYLO0] & R2K3K_ENTRYLO_V) {                      cp->reg[COP0_ENTRYLO0] & R2K3K_ENTRYLO_V)
                         memblock += (paddr & ((1 << BITS_PER_PAGETABLE) - 1));  
1734                          cpu->update_translation_table(cpu, vaddr, memblock,                          cpu->update_translation_table(cpu, vaddr, memblock,
1735                              wf, paddr);                              wf, paddr);
                 }  
1736          } else {          } else {
1737                  /*  R4000:  */                  /*  R4000 etc.:  */
1738                  g_bit = (cp->reg[COP0_ENTRYLO0] &                  unsigned char *memblock = NULL;
1739                      cp->reg[COP0_ENTRYLO1]) & ENTRYLO_G;                  int pfn_shift = 12, vpn_shift = 12;
1740                    int wf0, wf1, mask;
1741                    uint64_t vaddr0, vaddr1, paddr0, paddr1, ptmp;
1742    
1743                  cp->tlbs[index].mask = cp->reg[COP0_PAGEMASK];                  cp->tlbs[index].mask = cp->reg[COP0_PAGEMASK];
1744                  cp->tlbs[index].hi   = cp->reg[COP0_ENTRYHI];                  cp->tlbs[index].hi   = cp->reg[COP0_ENTRYHI];
1745                  cp->tlbs[index].lo1  = cp->reg[COP0_ENTRYLO1];                  cp->tlbs[index].lo1  = cp->reg[COP0_ENTRYLO1];
1746                  cp->tlbs[index].lo0  = cp->reg[COP0_ENTRYLO0];                  cp->tlbs[index].lo0  = cp->reg[COP0_ENTRYLO0];
1747    
1748                    wf0 = cp->tlbs[index].lo0 & ENTRYLO_D;
1749                    wf1 = cp->tlbs[index].lo1 & ENTRYLO_D;
1750    
1751                    mask = cp->reg[COP0_PAGEMASK];
1752                  if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {                  if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
1753                          /*  NOTE: The VR4131 (and possibly others) don't have                          pfn_shift = 10;
1754                              a Global bit in entryhi  */                          mask |= 0x07ff;
                         cp->tlbs[index].hi &= ~cp->reg[COP0_PAGEMASK];  
1755                  } else {                  } else {
1756                          cp->tlbs[index].lo0 &= ~ENTRYLO_G;                          mask |= 0x1fff;
                         cp->tlbs[index].lo1 &= ~ENTRYLO_G;  
   
                         cp->tlbs[index].hi &= ~TLB_G;  
                         if (g_bit)  
                                 cp->tlbs[index].hi |= TLB_G;  
1757                  }                  }
1758                    switch (mask) {
1759                  /*  Invalidate any code translations, if we are writing                  case 0x00007ff:
1760                      Dirty pages to the TLB:  */                          if (cp->tlbs[index].lo0 & ENTRYLO_V ||
1761                  if (cp->reg[COP0_PAGEMASK] != 0 &&                              cp->tlbs[index].lo1 & ENTRYLO_V) {
1762                      cp->reg[COP0_PAGEMASK] != 0x1800) {                                  fatal("1KB pages don't work with dyntrans.\n");
1763                          printf("TODO: MASK = %08"PRIx32"\n",                                  exit(1);
1764                              (uint32_t)cp->reg[COP0_PAGEMASK]);                          }
1765                            vpn_shift = 10;
1766                            break;
1767                    case 0x0001fff: break;
1768                    case 0x0007fff: vpn_shift = 14; break;
1769                    case 0x001ffff: vpn_shift = 16; break;
1770                    case 0x007ffff: vpn_shift = 18; break;
1771                    case 0x01fffff: vpn_shift = 20; break;
1772                    case 0x07fffff: vpn_shift = 22; break;
1773                    case 0x1ffffff: vpn_shift = 24; break;
1774                    case 0x7ffffff: vpn_shift = 26; break;
1775                    default:fatal("Unimplemented MASK = 0x%016x\n", mask);
1776                          exit(1);                          exit(1);
1777                  }                  }
1778    
1779                  if (cp->tlbs[index].lo0 & ENTRYLO_D)                  paddr0 = ((cp->tlbs[index].lo0 & ENTRYLO_PFN_MASK)
1780                          cpu->invalidate_code_translation(cpu,                      >> ENTRYLO_PFN_SHIFT) << pfn_shift;
1781                              ((cp->tlbs[index].lo0 & ENTRYLO_PFN_MASK)                  paddr1 = ((cp->tlbs[index].lo1 & ENTRYLO_PFN_MASK)
1782                              >> ENTRYLO_PFN_SHIFT) << 12,                      >> ENTRYLO_PFN_SHIFT) << pfn_shift;
                             INVALIDATE_PADDR);  
                 if (cp->tlbs[index].lo1 & ENTRYLO_D)  
                         cpu->invalidate_code_translation(cpu,  
                             ((cp->tlbs[index].lo1 & ENTRYLO_PFN_MASK)  
                             >> ENTRYLO_PFN_SHIFT) << 12,  
                             INVALIDATE_PADDR);  
1783    
1784  #if 1                  if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) {
1785          if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) {                          vaddr0 = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK_R10K;
                         oldvaddr = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK_R10K;  
1786                          /*  44 addressable bits:  */                          /*  44 addressable bits:  */
1787                          if (oldvaddr & 0x80000000000ULL)                          if (vaddr0 & 0x80000000000ULL)
1788                                  oldvaddr |= 0xfffff00000000000ULL;                                  vaddr0 |= 0xfffff00000000000ULL;
1789                  } else if (cpu->is_32bit) {                  } else if (cpu->is_32bit) {
1790                          /*  MIPS32 etc.:  */                          /*  MIPS32 etc.:  */
1791                          oldvaddr = (int32_t)oldvaddr;                          vaddr0 = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK;
1792                            vaddr0 = (int32_t)vaddr0;
1793                  } else {                  } else {
1794                          /*  Assume MMU4K  */                          /*  Assume MMU4K  */
1795                          oldvaddr = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK;                          vaddr0 = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK;
1796                          /*  40 addressable bits:  */                          /*  40 addressable bits:  */
1797                          if (oldvaddr & 0x8000000000ULL)                          if (vaddr0 & 0x8000000000ULL)
1798                                  oldvaddr |= 0xffffff0000000000ULL;                                  vaddr0 |= 0xffffff0000000000ULL;
1799                  }                  }
1800    
1801  cpu->invalidate_translation_caches(cpu, ((cp->tlbs[index].lo0 &                  vaddr1 = vaddr0 | (1 << vpn_shift);
 ENTRYLO_PFN_MASK) >> ENTRYLO_PFN_SHIFT) << 12, INVALIDATE_PADDR);  
 cpu->invalidate_translation_caches(cpu, ((cp->tlbs[index].lo1 &  
 ENTRYLO_PFN_MASK) >> ENTRYLO_PFN_SHIFT) << 12, INVALIDATE_PADDR);  
1802    
1803  #endif                  g_bit = (cp->reg[COP0_ENTRYLO0] &
1804          }                      cp->reg[COP0_ENTRYLO1]) & ENTRYLO_G;
 }  
1805    
1806                    if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
1807                            /*  NOTE: The VR4131 (and possibly others) don't have
1808                                a Global bit in entryhi  */
1809                            cp->tlbs[index].hi &= ~cp->reg[COP0_PAGEMASK];
1810                    } else {
1811                            cp->tlbs[index].lo0 &= ~ENTRYLO_G;
1812                            cp->tlbs[index].lo1 &= ~ENTRYLO_G;
1813    
1814  /*                          cp->tlbs[index].hi &= ~TLB_G;
1815   *  coproc_rfe():                          if (g_bit)
1816   *                                  cp->tlbs[index].hi |= TLB_G;
1817   *  Return from exception. (R3000 etc.)                  }
1818   */  
1819  void coproc_rfe(struct cpu *cpu)                  /*
1820  {                   *  Invalidate any code translations, if we are writing Dirty
1821          cpu->cd.mips.coproc[0]->reg[COP0_STATUS] =                   *  pages to the TLB:  (TODO: 4KB hardcoded... ugly)
1822              (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & ~0x3f) |                   */
1823              ((cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & 0x3c) >> 2);                  for (ptmp = 0; ptmp < (1 << pfn_shift); ptmp += 0x1000) {
1824                            if (wf0)
1825                                    cpu->invalidate_code_translation(cpu,
1826                                        paddr0 + ptmp, INVALIDATE_PADDR);
1827                            if (wf1)
1828                                    cpu->invalidate_code_translation(cpu,
1829                                        paddr1 + ptmp, INVALIDATE_PADDR);
1830                    }
1831    
1832                    /*
1833                     *  If we have a memblock (host page) for the physical page,
1834                     *  then add a translation for it immediately, to save some
1835                     *  time. (It would otherwise be added later on anyway,
1836                     *  because of a translation miss.)
1837                     *
1838                     *  NOTE/TODO: This is only for 4KB pages so far. It would
1839                     *             be too expensive to add e.g. 16MB pages like
1840                     *             this.
1841                     */
1842                    memblock = memory_paddr_to_hostaddr(cpu->mem, paddr0, 0);
1843                    if (memblock != NULL && cp->reg[COP0_ENTRYLO0] & ENTRYLO_V)
1844                            cpu->update_translation_table(cpu, vaddr0, memblock,
1845                                wf0, paddr0);
1846                    memblock = memory_paddr_to_hostaddr(cpu->mem, paddr1, 0);
1847                    if (memblock != NULL && cp->reg[COP0_ENTRYLO1] & ENTRYLO_V)
1848                            cpu->update_translation_table(cpu, vaddr1, memblock,
1849                                wf1, paddr1);
1850            }
1851  }  }
1852    
1853    
# Line 2022  void coproc_function(struct cpu *cpu, st Line 2069  void coproc_function(struct cpu *cpu, st
2069    
2070          /*  TLB operations and other things:  */          /*  TLB operations and other things:  */
2071          if (cp->coproc_nr == 0) {          if (cp->coproc_nr == 0) {
2072                    if (!unassemble_only) {
2073                            fatal("FATAL INTERNAL ERROR: Should be implemented"
2074                                " with dyntrans instead.\n");
2075                            exit(1);
2076                    }
2077    
2078                  op = (function) & 0xff;                  op = (function) & 0xff;
2079                  switch (co_bit) {                  switch (co_bit) {
2080                  case 1:                  case 1:
2081                          switch (op) {                          switch (op) {
2082                          case COP0_TLBR:         /*  Read indexed TLB entry  */                          case COP0_TLBR:         /*  Read indexed TLB entry  */
2083                                  if (unassemble_only) {                                  debug("tlbr\n");
                                         debug("tlbr\n");  
                                         return;  
                                 }  
                                 coproc_tlbpr(cpu, 1);  
2084                                  return;                                  return;
2085                          case COP0_TLBWI:        /*  Write indexed  */                          case COP0_TLBWI:        /*  Write indexed  */
2086                          case COP0_TLBWR:        /*  Write random  */                          case COP0_TLBWR:        /*  Write random  */
2087                                  if (unassemble_only) {                                  if (op == COP0_TLBWI)
2088                                          if (op == COP0_TLBWI)                                          debug("tlbwi");
2089                                                  debug("tlbwi");                                  else
2090                                          else                                          debug("tlbwr");
2091                                                  debug("tlbwr");                                  if (!running) {
2092                                          if (!running) {                                          debug("\n");
                                                 debug("\n");  
                                                 return;  
                                         }  
                                         debug("\tindex=%08llx",  
                                             (long long)cp->reg[COP0_INDEX]);  
                                         debug(", random=%08llx",  
                                             (long long)cp->reg[COP0_RANDOM]);  
                                         debug(", mask=%016llx",  
                                             (long long)cp->reg[COP0_PAGEMASK]);  
                                         debug(", hi=%016llx",  
                                             (long long)cp->reg[COP0_ENTRYHI]);  
                                         debug(", lo0=%016llx",  
                                             (long long)cp->reg[COP0_ENTRYLO0]);  
                                         debug(", lo1=%016llx\n",  
                                             (long long)cp->reg[COP0_ENTRYLO1]);  
2093                                          return;                                          return;
2094                                  }                                  }
2095                                  coproc_tlbwri(cpu, op == COP0_TLBWR);                                  debug("\tindex=%08llx",
2096                                        (long long)cp->reg[COP0_INDEX]);
2097                                    debug(", random=%08llx",
2098                                        (long long)cp->reg[COP0_RANDOM]);
2099                                    debug(", mask=%016llx",
2100                                        (long long)cp->reg[COP0_PAGEMASK]);
2101                                    debug(", hi=%016llx",
2102                                        (long long)cp->reg[COP0_ENTRYHI]);
2103                                    debug(", lo0=%016llx",
2104                                        (long long)cp->reg[COP0_ENTRYLO0]);
2105                                    debug(", lo1=%016llx\n",
2106                                        (long long)cp->reg[COP0_ENTRYLO1]);
2107                                  return;                                  return;
2108                          case COP0_TLBP:         /*  Probe TLB for                          case COP0_TLBP:         /*  Probe TLB for
2109                                                      matching entry  */                                                      matching entry  */
2110                                  if (unassemble_only) {                                  debug("tlbp\n");
                                         debug("tlbp\n");  
                                         return;  
                                 }  
                                 coproc_tlbpr(cpu, 0);  
2111                                  return;                                  return;
2112                          case COP0_RFE:          /*  R2000/R3000 only:                          case COP0_RFE:          /*  R2000/R3000 only:
2113                                                      Return from Exception  */                                                      Return from Exception  */
2114                                  if (unassemble_only) {                                  debug("rfe\n");
                                         debug("rfe\n");  
                                         return;  
                                 }  
                                 coproc_rfe(cpu);  
2115                                  return;                                  return;
2116                          case COP0_ERET: /*  R4000: Return from exception  */                          case COP0_ERET: /*  R4000: Return from exception  */
2117                                  if (unassemble_only) {                                  debug("eret\n");
                                         debug("eret\n");  
                                         return;  
                                 }  
                                 coproc_eret(cpu);  
2118                                  return;                                  return;
2119                          case COP0_DERET:                          case COP0_DERET:
2120                                  if (unassemble_only) {                                  debug("deret\n");
2121                                          debug("deret\n");                                  return;
2122                                          return;                          case COP0_WAIT:
2123                                    {
2124                                            int code = (function >> 6) & 0x7ffff;
2125                                            debug("wait");
2126                                            if (code > 0)
2127                                                    debug("\t0x%x", code);
2128                                            debug("\n");
2129                                  }                                  }
                                 /*  
                                  *  According to the MIPS64 manual, deret  
                                  *  loads PC from the DEPC cop0 register, and  
                                  *  jumps there immediately. No delay slot.  
                                  *  
                                  *  TODO: This instruction is only available  
                                  *  if the processor is in debug mode. (What  
                                  *  does that mean?) TODO: This instruction  
                                  *  is undefined in a delay slot.  
                                  */  
                                 cpu->pc = cp->reg[COP0_DEPC];  
                                 cpu->delay_slot = 0;  
                                 cp->reg[COP0_STATUS] &= ~STATUS_EXL;  
2130                                  return;                                  return;
2131                          case COP0_STANDBY:                          case COP0_STANDBY:
2132                                  if (unassemble_only) {                                  debug("standby\n");
                                         debug("standby\n");  
                                         return;  
                                 }  
                                 /*  TODO: Hm. Do something here?  */  
2133                                  return;                                  return;
2134                          case COP0_SUSPEND:                          case COP0_SUSPEND:
2135                                  if (unassemble_only) {                                  debug("suspend\n");
                                         debug("suspend\n");  
                                         return;  
                                 }  
                                 /*  TODO: Hm. Do something here?  */  
2136                                  return;                                  return;
2137                          case COP0_HIBERNATE:                          case COP0_HIBERNATE:
2138                                  if (unassemble_only) {                                  debug("hibernate\n");
                                         debug("hibernate\n");  
                                         return;  
                                 }  
                                 /*  TODO: Hm. Do something here?  */  
2139                                  return;                                  return;
2140                          default:                          default:
2141                                  ;                                  ;
# Line 2141  void coproc_function(struct cpu *cpu, st Line 2155  void coproc_function(struct cpu *cpu, st
2155                  return;                  return;
2156          }          }
2157    
         /*  TODO: RM5200 idle (?)  */  
         if ((cp->coproc_nr==0 || cp->coproc_nr==3) && function == 0x02000020) {  
                 if (unassemble_only) {  
                         debug("idle(?)\n");     /*  TODO  */  
                         return;  
                 }  
   
                 /*  Idle? TODO  */  
                 return;  
         }  
   
2158          if (unassemble_only) {          if (unassemble_only) {
2159                  debug("cop%i\t0x%08x (unimplemented)\n", cpnr, (int)function);                  debug("cop%i\t0x%08x (unimplemented)\n", cpnr, (int)function);
2160                  return;                  return;

Legend:
Removed from v.26  
changed lines
  Added in v.30

  ViewVC Help
Powered by ViewVC 1.1.26