/[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 30 by dpavlin, Mon Oct 8 16:20:40 2007 UTC revision 40 by dpavlin, Mon Oct 8 16:22:11 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2003-2006  Anders Gavare.  All rights reserved.   *  Copyright (C) 2003-2007  Anders Gavare.  All rights reserved.
3   *   *
4   *  Redistribution and use in source and binary forms, with or without   *  Redistribution and use in source and binary forms, with or without
5   *  modification, are permitted provided that the following conditions are met:   *  modification, are permitted provided that the following conditions are met:
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: cpu_mips_coproc.c,v 1.53 2006/08/11 17:43:30 debug Exp $   *  $Id: cpu_mips_coproc.c,v 1.64 2007/04/28 09:19:51 debug Exp $
29   *   *
30   *  Emulation of MIPS coprocessors.   *  Emulation of MIPS coprocessors.
31   */   */
# Line 45  Line 45 
45  #include "mips_cpu_types.h"  #include "mips_cpu_types.h"
46  #include "misc.h"  #include "misc.h"
47  #include "opcodes_mips.h"  #include "opcodes_mips.h"
48    #include "timer.h"
49    
50    
51  #ifndef ENABLE_MIPS  #ifndef ENABLE_MIPS
# Line 438  struct mips_coproc *mips_coproc_new(stru Line 439  struct mips_coproc *mips_coproc_new(stru
439    
440    
441  /*  /*
442     *  mips_timer_tick():
443     */
444    static void mips_timer_tick(struct timer *timer, void *extra)
445    {
446            struct cpu *cpu = (struct cpu *) extra;
447    
448            cpu->cd.mips.compare_interrupts_pending ++;
449    
450            if ((int32_t) (cpu->cd.mips.coproc[0]->reg[COP0_COUNT] -
451                cpu->cd.mips.coproc[0]->reg[COP0_COMPARE]) < 0) {
452                    cpu->cd.mips.coproc[0]->reg[COP0_COUNT] =
453                        cpu->cd.mips.coproc[0]->reg[COP0_COMPARE];
454            }
455    }
456    
457    
458    /*
459   *  mips_coproc_tlb_set_entry():   *  mips_coproc_tlb_set_entry():
460   *   *
461   *  Used by machine setup code, if a specific machine emulation starts up   *  Used by machine setup code, if a specific machine emulation starts up
# Line 517  void mips_coproc_tlb_set_entry(struct cp Line 535  void mips_coproc_tlb_set_entry(struct cp
535   *   *
536   *  Note: In the R3000 case, the asid argument is shifted 6 bits.   *  Note: In the R3000 case, the asid argument is shifted 6 bits.
537   */   */
538  static void invalidate_asid(struct cpu *cpu, int asid)  static void invalidate_asid(struct cpu *cpu, unsigned int asid)
539  {  {
540          struct mips_coproc *cp = cpu->cd.mips.coproc[0];          struct mips_coproc *cp = cpu->cd.mips.coproc[0];
541          int i, ntlbs = cp->nr_of_tlbs;          unsigned int i, ntlbs = cp->nr_of_tlbs;
542          struct mips_tlb *tlb = cp->tlbs;          struct mips_tlb *tlb = cp->tlbs;
543    
544          if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {          if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
# Line 595  void coproc_register_read(struct cpu *cp Line 613  void coproc_register_read(struct cpu *cp
613          if (cp->coproc_nr==0 && reg_nr==COP0_PAGEMASK)  unimpl = 0;          if (cp->coproc_nr==0 && reg_nr==COP0_PAGEMASK)  unimpl = 0;
614          if (cp->coproc_nr==0 && reg_nr==COP0_WIRED)     unimpl = 0;          if (cp->coproc_nr==0 && reg_nr==COP0_WIRED)     unimpl = 0;
615          if (cp->coproc_nr==0 && reg_nr==COP0_BADVADDR)  unimpl = 0;          if (cp->coproc_nr==0 && reg_nr==COP0_BADVADDR)  unimpl = 0;
616          if (cp->coproc_nr==0 && reg_nr==COP0_COUNT)     unimpl = 0;          if (cp->coproc_nr==0 && reg_nr==COP0_COUNT) {
617                    /*  TODO: Increase count in a more meaningful way!  */
618                    cp->reg[COP0_COUNT] = (int32_t) (cp->reg[COP0_COUNT] + 1);
619                    unimpl = 0;
620            }
621          if (cp->coproc_nr==0 && reg_nr==COP0_ENTRYHI)   unimpl = 0;          if (cp->coproc_nr==0 && reg_nr==COP0_ENTRYHI)   unimpl = 0;
622          if (cp->coproc_nr==0 && reg_nr==COP0_COMPARE)   unimpl = 0;          if (cp->coproc_nr==0 && reg_nr==COP0_COMPARE)   unimpl = 0;
623          if (cp->coproc_nr==0 && reg_nr==COP0_STATUS)    unimpl = 0;          if (cp->coproc_nr==0 && reg_nr==COP0_STATUS)    unimpl = 0;
# Line 661  void coproc_register_write(struct cpu *c Line 683  void coproc_register_write(struct cpu *c
683          int readonly = 0;          int readonly = 0;
684          uint64_t tmp = *ptr;          uint64_t tmp = *ptr;
685          uint64_t tmp2 = 0, old;          uint64_t tmp2 = 0, old;
686          int inval = 0, old_asid, oldmode;          int inval = 0;
687            unsigned int old_asid;
688            uint64_t oldmode;
689    
690          switch (cp->coproc_nr) {          switch (cp->coproc_nr) {
691          case 0:          case 0:
# Line 753  void coproc_register_write(struct cpu *c Line 777  void coproc_register_write(struct cpu *c
777                          unimpl = 0;                          unimpl = 0;
778                          break;                          break;
779                  case COP0_COMPARE:                  case COP0_COMPARE:
780                          /*  Clear the timer interrupt bit (bit 7):  */                          if (cpu->machine->emulated_hz > 0) {
781                          cpu->cd.mips.compare_register_set = 1;                                  int32_t compare_diff = tmp -
782                          mips_cpu_interrupt_ack(cpu, 7);                                      cp->reg[COP0_COMPARE];
783                                    double hz;
784    
785                                    if (compare_diff < 0)
786                                            hz = tmp - cp->reg[COP0_COUNT];
787    
788                                    if (compare_diff == 0)
789                                            hz = 0;
790                                    else
791                                            hz = (double)cpu->machine->emulated_hz
792                                                / (double)compare_diff;
793    /*
794     *  TODO: DON'T HARDCODE THIS!
795     */
796    hz = 100.0;
797    
798                                    /*  Initialize or re-set the periodic timer:  */
799                                    if (hz > 0) {
800                                            if (cpu->cd.mips.timer == NULL)
801                                                    cpu->cd.mips.timer = timer_add(
802                                                        hz, mips_timer_tick, cpu);
803                                            else
804                                                    timer_update_frequency(
805                                                        cpu->cd.mips.timer, hz);
806                                    }
807                            }
808    
809                            /*  Ack the periodic timer, if it was asserted:  */
810                            if (cp->reg[COP0_CAUSE] & 0x8000 &&
811                                cpu->cd.mips.compare_interrupts_pending > 0)
812                                    cpu->cd.mips.compare_interrupts_pending --;
813    
814                            /*  Clear the timer interrupt assertion (bit 7):  */
815                            cp->reg[COP0_CAUSE] &= ~0x8000;
816    
817                          if (tmp != (uint64_t)(int64_t)(int32_t)tmp)                          if (tmp != (uint64_t)(int64_t)(int32_t)tmp)
818                                  fatal("WARNING: trying to write a 64-bit value"                                  fatal("WARNING: trying to write a 64-bit value"
819                                      " to the COMPARE register!\n");                                      " to the COMPARE register!\n");
820    
821                          tmp = (int64_t)(int32_t)tmp;                          tmp = (int64_t)(int32_t)tmp;
822                            cpu->cd.mips.compare_register_set = 1;
823                          unimpl = 0;                          unimpl = 0;
824                          break;                          break;
825                  case COP0_ENTRYHI:                  case COP0_ENTRYHI:
# Line 1622  void coproc_tlbwri(struct cpu *cpu, int Line 1682  void coproc_tlbwri(struct cpu *cpu, int
1682                      (cp->reg[COP0_ENTRYHI] & R2K3K_ENTRYHI_ASID_MASK) ))                      (cp->reg[COP0_ENTRYHI] & R2K3K_ENTRYHI_ASID_MASK) ))
1683                          cpu->invalidate_translation_caches(cpu, oldvaddr,                          cpu->invalidate_translation_caches(cpu, oldvaddr,
1684                              INVALIDATE_VADDR);                              INVALIDATE_VADDR);
1685    
1686                  break;                  break;
1687    
1688          default:if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) {          default:if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) {
1689                          oldvaddr = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK_R10K;                          oldvaddr = cp->tlbs[index].hi &
1690                                (ENTRYHI_VPN2_MASK_R10K | ENTRYHI_R_MASK);
1691                          /*  44 addressable bits:  */                          /*  44 addressable bits:  */
1692                          if (oldvaddr & 0x80000000000ULL)                          if (oldvaddr & 0x80000000000ULL)
1693                                  oldvaddr |= 0xfffff00000000000ULL;                                  oldvaddr |= 0x3ffff00000000000ULL;
1694                  } else if (cpu->is_32bit) {                  } else if (cpu->is_32bit) {
1695                          /*  MIPS32 etc.:  */                          /*  MIPS32 etc.:  */
1696                          oldvaddr = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK;                          oldvaddr = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK;
1697                          oldvaddr = (int32_t)oldvaddr;                          oldvaddr = (int32_t)oldvaddr;
1698                  } else {                  } else {
1699                          /*  Assume MMU4K  */                          /*  Assume MMU4K  */
1700                          oldvaddr = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK;                          oldvaddr = cp->tlbs[index].hi &
1701                                (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK);
1702                          /*  40 addressable bits:  */                          /*  40 addressable bits:  */
1703                          if (oldvaddr & 0x8000000000ULL)                          if (oldvaddr & 0x8000000000ULL)
1704                                  oldvaddr |= 0xffffff0000000000ULL;                                  oldvaddr |= 0x3fffff0000000000ULL;
1705                  }                  }
1706    
 #if 0  
                 /*  TODO: FIX THIS! It shouldn't be needed!  */  
                 cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);  
 #else  
1707                  /*                  /*
1708                   *  TODO: non-4KB page sizes!                   *  TODO: non-4KB page sizes!
1709                   */                   */
# Line 1654  void coproc_tlbwri(struct cpu *cpu, int Line 1713  void coproc_tlbwri(struct cpu *cpu, int
1713                  if (cp->tlbs[index].lo1 & ENTRYLO_V)                  if (cp->tlbs[index].lo1 & ENTRYLO_V)
1714                          cpu->invalidate_translation_caches(cpu, oldvaddr|0x1000,                          cpu->invalidate_translation_caches(cpu, oldvaddr|0x1000,
1715                              INVALIDATE_VADDR);                              INVALIDATE_VADDR);
 #endif  
1716          }          }
1717    
1718  #if 0  #if 0
# Line 1672  void coproc_tlbwri(struct cpu *cpu, int Line 1730  void coproc_tlbwri(struct cpu *cpu, int
1730                  int i;                  int i;
1731                  unsigned int asid;                  unsigned int asid;
1732    
1733                  vaddr1 = cp->reg[COP0_ENTRYHI] & ENTRYHI_VPN2_MASK_R10K;                  vaddr1 = cp->reg[COP0_ENTRYHI] &
1734                        (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK_R10K);
1735                  asid = cp->reg[COP0_ENTRYHI] & ENTRYHI_ASID;                  asid = cp->reg[COP0_ENTRYHI] & ENTRYHI_ASID;
1736                  /*  Since this is just a warning, it's probably not necessary                  /*  Since this is just a warning, it's probably not necessary
1737                      to use R4000 masks etc.  */                      to use R4000 masks etc.  */
# Line 1685  void coproc_tlbwri(struct cpu *cpu, int Line 1744  void coproc_tlbwri(struct cpu *cpu, int
1744                              (cp->tlbs[i].hi & ENTRYHI_ASID) != asid)                              (cp->tlbs[i].hi & ENTRYHI_ASID) != asid)
1745                                  continue;                                  continue;
1746    
1747                          vaddr2 = cp->tlbs[i].hi & ENTRYHI_VPN2_MASK_R10K;                          vaddr2 = cp->tlbs[i].hi &
1748                                (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK_R10K);
1749                          if (vaddr1 == vaddr2 && ((cp->tlbs[i].lo0 &                          if (vaddr1 == vaddr2 && ((cp->tlbs[i].lo0 &
1750                              ENTRYLO_V) || (cp->tlbs[i].lo1 & ENTRYLO_V)))                              ENTRYLO_V) || (cp->tlbs[i].lo1 & ENTRYLO_V)))
1751                                  fatal("\n[ WARNING! tlbw%s to index 0x%02x "                                  fatal("\n[ WARNING! tlbw%s to index 0x%02x "
# Line 1719  void coproc_tlbwri(struct cpu *cpu, int Line 1779  void coproc_tlbwri(struct cpu *cpu, int
1779                              INVALIDATE_PADDR);                              INVALIDATE_PADDR);
1780                  }                  }
1781    
1782                    /*  Set new last_written_tlb_index hint:  */
1783                    cpu->cd.mips.last_written_tlb_index = index;
1784    
1785                  if (cp->reg[COP0_STATUS] & MIPS1_ISOL_CACHES) {                  if (cp->reg[COP0_STATUS] & MIPS1_ISOL_CACHES) {
1786                          fatal("Wow! Interesting case; tlbw* while caches"                          fatal("Wow! Interesting case; tlbw* while caches"
1787                              " are isolated. TODO\n");                              " are isolated. TODO\n");
# Line 1739  void coproc_tlbwri(struct cpu *cpu, int Line 1802  void coproc_tlbwri(struct cpu *cpu, int
1802                  int pfn_shift = 12, vpn_shift = 12;                  int pfn_shift = 12, vpn_shift = 12;
1803                  int wf0, wf1, mask;                  int wf0, wf1, mask;
1804                  uint64_t vaddr0, vaddr1, paddr0, paddr1, ptmp;                  uint64_t vaddr0, vaddr1, paddr0, paddr1, ptmp;
1805                    uint64_t psize;
1806    
1807                  cp->tlbs[index].mask = cp->reg[COP0_PAGEMASK];                  cp->tlbs[index].mask = cp->reg[COP0_PAGEMASK];
1808                  cp->tlbs[index].hi   = cp->reg[COP0_ENTRYHI];                  cp->tlbs[index].hi   = cp->reg[COP0_ENTRYHI];
# Line 1777  void coproc_tlbwri(struct cpu *cpu, int Line 1841  void coproc_tlbwri(struct cpu *cpu, int
1841                  }                  }
1842    
1843                  paddr0 = ((cp->tlbs[index].lo0 & ENTRYLO_PFN_MASK)                  paddr0 = ((cp->tlbs[index].lo0 & ENTRYLO_PFN_MASK)
1844                      >> ENTRYLO_PFN_SHIFT) << pfn_shift;                      >> ENTRYLO_PFN_SHIFT) << pfn_shift
1845                        >> vpn_shift << vpn_shift;
1846                  paddr1 = ((cp->tlbs[index].lo1 & ENTRYLO_PFN_MASK)                  paddr1 = ((cp->tlbs[index].lo1 & ENTRYLO_PFN_MASK)
1847                      >> ENTRYLO_PFN_SHIFT) << pfn_shift;                      >> ENTRYLO_PFN_SHIFT) << pfn_shift
1848                        >> vpn_shift << vpn_shift;
1849    
1850                  if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) {                  if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) {
1851                          vaddr0 = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK_R10K;                          vaddr0 = cp->tlbs[index].hi &
1852                                (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK_R10K);
1853                          /*  44 addressable bits:  */                          /*  44 addressable bits:  */
1854                          if (vaddr0 & 0x80000000000ULL)                          if (vaddr0 & 0x80000000000ULL)
1855                                  vaddr0 |= 0xfffff00000000000ULL;                                  vaddr0 |= 0x3ffff00000000000ULL;
1856                  } else if (cpu->is_32bit) {                  } else if (cpu->is_32bit) {
1857                          /*  MIPS32 etc.:  */                          /*  MIPS32 etc.:  */
1858                          vaddr0 = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK;                          vaddr0 = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK;
1859                          vaddr0 = (int32_t)vaddr0;                          vaddr0 = (int32_t)vaddr0;
1860                  } else {                  } else {
1861                          /*  Assume MMU4K  */                          /*  Assume MMU4K  */
1862                          vaddr0 = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK;                          vaddr0 = cp->tlbs[index].hi &
1863                                (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK);
1864                          /*  40 addressable bits:  */                          /*  40 addressable bits:  */
1865                          if (vaddr0 & 0x8000000000ULL)                          if (vaddr0 & 0x8000000000ULL)
1866                                  vaddr0 |= 0xffffff0000000000ULL;                                  vaddr0 |= 0x3fffff0000000000ULL;
1867                  }                  }
1868    
1869                  vaddr1 = vaddr0 | (1 << vpn_shift);                  vaddr1 = vaddr0 | (1 << vpn_shift);
# Line 1820  void coproc_tlbwri(struct cpu *cpu, int Line 1888  void coproc_tlbwri(struct cpu *cpu, int
1888                   *  Invalidate any code translations, if we are writing Dirty                   *  Invalidate any code translations, if we are writing Dirty
1889                   *  pages to the TLB:  (TODO: 4KB hardcoded... ugly)                   *  pages to the TLB:  (TODO: 4KB hardcoded... ugly)
1890                   */                   */
1891                  for (ptmp = 0; ptmp < (1 << pfn_shift); ptmp += 0x1000) {                  psize = 1 << pfn_shift;
1892                    for (ptmp = 0; ptmp < psize; ptmp += 0x1000) {
1893                          if (wf0)                          if (wf0)
1894                                  cpu->invalidate_code_translation(cpu,                                  cpu->invalidate_code_translation(cpu,
1895                                      paddr0 + ptmp, INVALIDATE_PADDR);                                      paddr0 + ptmp, INVALIDATE_PADDR);
# Line 1847  void coproc_tlbwri(struct cpu *cpu, int Line 1916  void coproc_tlbwri(struct cpu *cpu, int
1916                  if (memblock != NULL && cp->reg[COP0_ENTRYLO1] & ENTRYLO_V)                  if (memblock != NULL && cp->reg[COP0_ENTRYLO1] & ENTRYLO_V)
1917                          cpu->update_translation_table(cpu, vaddr1, memblock,                          cpu->update_translation_table(cpu, vaddr1, memblock,
1918                              wf1, paddr1);                              wf1, paddr1);
1919    
1920                    /*  Set new last_written_tlb_index hint:  */
1921                    cpu->cd.mips.last_written_tlb_index = index;
1922          }          }
1923  }  }
1924    

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

  ViewVC Help
Powered by ViewVC 1.1.26