/[gxemul]/trunk/src/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/cpu_mips_coproc.c

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

revision 3 by dpavlin, Mon Oct 8 16:17:48 2007 UTC revision 4 by dpavlin, Mon Oct 8 16:18:00 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: cpu_mips_coproc.c,v 1.11 2005/03/15 06:52:14 debug Exp $   *  $Id: cpu_mips_coproc.c,v 1.17 2005/04/22 16:03:43 debug Exp $
29   *   *
30   *  Emulation of MIPS coprocessors.   *  Emulation of MIPS coprocessors.
31   */   */
# Line 684  void clear_all_chunks_from_all_tables(st Line 684  void clear_all_chunks_from_all_tables(st
684          for (a=0; a<0x400; a++) {          for (a=0; a<0x400; a++) {
685                  tbl1 = cpu->cd.mips.vaddr_to_hostaddr_table0_kernel[a];                  tbl1 = cpu->cd.mips.vaddr_to_hostaddr_table0_kernel[a];
686                  if (tbl1 != cpu->cd.mips.vaddr_to_hostaddr_nulltable) {                  if (tbl1 != cpu->cd.mips.vaddr_to_hostaddr_nulltable) {
687                          for (b=0; b<0x400; b++)                          for (b=0; b<0x400; b++) {
688                                    tbl1->haddr_entry[b] = NULL;
689                                    tbl1->paddr_entry[b] = 0;
690                                  tbl1->bintrans_chunks[b] = NULL;                                  tbl1->bintrans_chunks[b] = NULL;
691                            }
692                  }                  }
693          }          }
694  }  }
# Line 949  void coproc_register_read(struct cpu *cp Line 952  void coproc_register_read(struct cpu *cp
952          if (cp->coproc_nr==0 && reg_nr==COP0_PAGEMASK)  unimpl = 0;          if (cp->coproc_nr==0 && reg_nr==COP0_PAGEMASK)  unimpl = 0;
953          if (cp->coproc_nr==0 && reg_nr==COP0_WIRED)     unimpl = 0;          if (cp->coproc_nr==0 && reg_nr==COP0_WIRED)     unimpl = 0;
954          if (cp->coproc_nr==0 && reg_nr==COP0_BADVADDR)  unimpl = 0;          if (cp->coproc_nr==0 && reg_nr==COP0_BADVADDR)  unimpl = 0;
955          if (cp->coproc_nr==0 && reg_nr==COP0_COUNT)     unimpl = 0;          if (cp->coproc_nr==0 && reg_nr==COP0_COUNT) {
956                    /*
957                     *  This speeds up delay-loops that just read the count
958                     *  register until it has reached a certain value. (Only for
959                     *  R4000 etc.)
960                     *
961                     *  TODO: Maybe this should be optional?
962                     */
963                    if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
964                            int increase = 500;
965                            int32_t x = cp->reg[COP0_COUNT];
966                            int32_t y = cp->reg[COP0_COMPARE];
967                            int32_t diff = x - y;
968                            if (diff < 0 && diff + increase >= 0
969                                && cpu->cd.mips.compare_register_set) {
970                                    mips_cpu_interrupt(cpu, 7);
971                                    cpu->cd.mips.compare_register_set = 0;
972                            }
973                            cp->reg[COP0_COUNT] = (int64_t)
974                                (int32_t)(cp->reg[COP0_COUNT] + increase);
975                    }
976    
977                    unimpl = 0;
978            }
979          if (cp->coproc_nr==0 && reg_nr==COP0_ENTRYHI)   unimpl = 0;          if (cp->coproc_nr==0 && reg_nr==COP0_ENTRYHI)   unimpl = 0;
980          if (cp->coproc_nr==0 && reg_nr==COP0_COMPARE)   unimpl = 0;          if (cp->coproc_nr==0 && reg_nr==COP0_COMPARE)   unimpl = 0;
981          if (cp->coproc_nr==0 && reg_nr==COP0_STATUS)    unimpl = 0;          if (cp->coproc_nr==0 && reg_nr==COP0_STATUS)    unimpl = 0;
# Line 1172  void coproc_register_write(struct cpu *c Line 1198  void coproc_register_write(struct cpu *c
1198                  case COP0_STATUS:                  case COP0_STATUS:
1199                          oldmode = cp->reg[COP0_STATUS];                          oldmode = cp->reg[COP0_STATUS];
1200                          tmp &= ~(1 << 21);      /*  bit 21 is read-only  */                          tmp &= ~(1 << 21);      /*  bit 21 is read-only  */
1201    #if 0
1202    /*  Why was this here? It should not be necessary.  */
1203    
1204                          /*  Changing from kernel to user mode? Then                          /*  Changing from kernel to user mode? Then
1205                              invalidate some translation caches:  */                              invalidate some translation caches:  */
1206                          if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {                          if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
# Line 1185  void coproc_register_write(struct cpu *c Line 1214  void coproc_register_write(struct cpu *c
1214                                          invalidate_translation_caches(                                          invalidate_translation_caches(
1215                                              cpu, 0, 0, 1, 0);                                              cpu, 0, 0, 1, 0);
1216                          }                          }
1217    #endif
1218    
1219    #ifdef BINTRANS
1220                            if (cpu->cd.mips.cpu_type.mmu_model == MMU3K &&
1221                                (oldmode & MIPS1_ISOL_CACHES) !=
1222                                (tmp & MIPS1_ISOL_CACHES)) {
1223                                    /*  R3000-style caches when isolated are
1224                                        treated in bintrans mode by changing
1225                                        the vaddr_to_hostaddr_table0 pointer:  */
1226                                    if (tmp & MIPS1_ISOL_CACHES) {
1227                                            /*  cpu->cd.mips.
1228                                                dont_run_next_bintrans = 1;  */
1229                                            cpu->cd.mips.vaddr_to_hostaddr_table0 =
1230                                              tmp & MIPS1_SWAP_CACHES?
1231                                              cpu->cd.mips.
1232                                              vaddr_to_hostaddr_table0_cacheisol_i
1233                                              : cpu->cd.mips.
1234                                              vaddr_to_hostaddr_table0_cacheisol_d;
1235                                    } else {
1236                                            cpu->cd.mips.vaddr_to_hostaddr_table0 =
1237                                                cpu->cd.mips.
1238                                                    vaddr_to_hostaddr_table0_kernel;
1239    
1240                                            /*  TODO: cpu->cd.mips.
1241                                                vaddr_to_hostaddr_table0_user;  */
1242                                    }
1243                            }
1244    #endif
1245                          unimpl = 0;                          unimpl = 0;
1246                          break;                          break;
1247                  case COP0_CAUSE:                  case COP0_CAUSE:
# Line 2207  void coproc_tlbwri(struct cpu *cpu, int Line 2264  void coproc_tlbwri(struct cpu *cpu, int
2264    
2265  /*  TODO: Bug? Why does this if need to be commented out?  */  /*  TODO: Bug? Why does this if need to be commented out?  */
2266    
2267                  /*  if (cp->tlbs[index].lo0 & ENTRYLO_V) */                  /*  if (cp->tlbs[index].lo0 & ENTRYLO_V)  */
2268                          invalidate_translation_caches(cpu, 0, oldvaddr, 0, 0);                          invalidate_translation_caches(cpu, 0, oldvaddr, 0, 0);
2269                  break;                  break;
2270          default:          default:
# Line 2236  void coproc_tlbwri(struct cpu *cpu, int Line 2293  void coproc_tlbwri(struct cpu *cpu, int
2293          }          }
2294    
2295    
2296            /*
2297             *  Check for duplicate entries.  (There should not be two mappings
2298             *  from one virtual address to physical addresses.)
2299             *
2300             *  TODO: Do this for MMU3K and R4100 too.
2301             *
2302             *  TODO: Make this detection more robust.
2303             */
2304            if (cpu->cd.mips.cpu_type.mmu_model != MMU3K &&
2305                cpu->cd.mips.cpu_type.rev != MIPS_R4100) {
2306                    uint64_t vaddr1, vaddr2;
2307                    int i, asid;
2308    
2309                    vaddr1 = cp->reg[COP0_ENTRYHI] & ENTRYHI_VPN2_MASK_R10K;
2310                    asid = cp->reg[COP0_ENTRYHI] & ENTRYHI_ASID;
2311                    /*  Since this is just a warning, it's probably not necessary
2312                        to use R4000 masks etc.  */
2313    
2314                    for (i=0; i<cp->nr_of_tlbs; i++) {
2315                            if (i == index && !randomflag)
2316                                    continue;
2317    
2318                            if (!(cp->tlbs[i].hi & TLB_G) &&
2319                                (cp->tlbs[i].hi & ENTRYHI_ASID) != asid)
2320                                    continue;
2321    
2322                            vaddr2 = cp->tlbs[i].hi & ENTRYHI_VPN2_MASK_R10K;
2323                            if (vaddr1 == vaddr2 && ((cp->tlbs[i].lo0 &
2324                                ENTRYLO_V) || (cp->tlbs[i].lo1 & ENTRYLO_V)))
2325                                    fatal("\n[ WARNING! tlbw%s vaddr=0x%llx is "
2326                                        "already in the TLB! ]\n\n", randomflag?
2327                                        "r" : "i", (long long)vaddr1);
2328                    }
2329            }
2330    
2331    
2332          /*  Write the new entry:  */          /*  Write the new entry:  */
2333    
2334          if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {          if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
# Line 2369  void coproc_eret(struct cpu *cpu) Line 2462  void coproc_eret(struct cpu *cpu)
2462              (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & 1) == 0)              (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & 1) == 0)
2463                  newmode = 1;                  newmode = 1;
2464    
2465    #if 0
2466          /*  Changing from kernel to user mode?          /*  Changing from kernel to user mode?
2467              Then this is necessary:  TODO  */              Then this is necessary:  TODO  */
2468          if (oldmode && !newmode)          if (oldmode && !newmode)
2469                  invalidate_translation_caches(cpu, 0, 0, 1, 0);                  invalidate_translation_caches(cpu, 0, 0, 1, 0);
2470    #endif
2471  }  }
2472    
2473    

Legend:
Removed from v.3  
changed lines
  Added in v.4

  ViewVC Help
Powered by ViewVC 1.1.26