/[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 28 by dpavlin, Mon Oct 8 16:20:26 2007 UTC revision 42 by dpavlin, Mon Oct 8 16:22:32 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.49 2006/07/21 20:39:40 debug Exp $   *  $Id: cpu_mips_coproc.c,v 1.69 2007/06/15 18:07:08 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"
   
 #ifndef ENABLE_MIPS  
   
   
 struct mips_coproc *mips_coproc_new(struct cpu *cpu, int coproc_nr)  
 { return NULL; }  
   
 void mips_coproc_tlb_set_entry(struct cpu *cpu, int entrynr, int size,  
         uint64_t vaddr, uint64_t paddr0, uint64_t paddr1,  
         int valid0, int valid1, int dirty0, int dirty1, int global, int asid,  
         int cachealgo0, int cachealgo1) { }  
   
   
 #else   /*  ENABLE_MIPS  */  
49    
50    
51  extern volatile int single_step;  extern volatile int single_step;
# Line 98  static void initialize_cop0_config(struc Line 84  static void initialize_cop0_config(struc
84                      ;                      ;
85                  /*  Config select 1: caches etc. TODO: Don't use                  /*  Config select 1: caches etc. TODO: Don't use
86                          cpu->machine for this stuff!  */                          cpu->machine for this stuff!  */
87                  IB = cpu->machine->cache_picache_linesize - 1;                  IB = cpu->cd.mips.cache_picache_linesize - 1;
88                  IB = IB < 0? 0 : (IB > 7? 7 : IB);                  IB = IB < 0? 0 : (IB > 7? 7 : IB);
89                  DB = cpu->machine->cache_pdcache_linesize - 1;                  DB = cpu->cd.mips.cache_pdcache_linesize - 1;
90                  DB = DB < 0? 0 : (DB > 7? 7 : DB);                  DB = DB < 0? 0 : (DB > 7? 7 : DB);
91                  IC = cpu->machine->cache_picache -                  IC = cpu->cd.mips.cache_picache -
92                      cpu->machine->cache_picache_linesize - 7;                      cpu->cd.mips.cache_picache_linesize - 7;
93                  DC = cpu->machine->cache_pdcache -                  DC = cpu->cd.mips.cache_pdcache -
94                      cpu->machine->cache_pdcache_linesize - 7;                      cpu->cd.mips.cache_pdcache_linesize - 7;
95                  IA = cpu->cd.mips.cpu_type.piways - 1;                  IA = cpu->cd.mips.cpu_type.piways - 1;
96                  DA = cpu->cd.mips.cpu_type.pdways - 1;                  DA = cpu->cd.mips.cpu_type.pdways - 1;
97                  cpu->cd.mips.cop0_config_select1 =                  cpu->cd.mips.cop0_config_select1 =
# Line 133  static void initialize_cop0_config(struc Line 119  static void initialize_cop0_config(struc
119                  break;                  break;
120          case MIPS_R4000:        /*  according to the R4000 manual  */          case MIPS_R4000:        /*  according to the R4000 manual  */
121          case MIPS_R4600:          case MIPS_R4600:
122                  IB = cpu->machine->cache_picache_linesize - 4;                  IB = cpu->cd.mips.cache_picache_linesize - 4;
123                  IB = IB < 0? 0 : (IB > 1? 1 : IB);                  IB = IB < 0? 0 : (IB > 1? 1 : IB);
124                  DB = cpu->machine->cache_pdcache_linesize - 4;                  DB = cpu->cd.mips.cache_pdcache_linesize - 4;
125                  DB = DB < 0? 0 : (DB > 1? 1 : DB);                  DB = DB < 0? 0 : (DB > 1? 1 : DB);
126                  SB = cpu->machine->cache_secondary_linesize - 4;                  SB = cpu->cd.mips.cache_secondary_linesize - 4;
127                  SB = SB < 0? 0 : (SB > 3? 3 : SB);                  SB = SB < 0? 0 : (SB > 3? 3 : SB);
128                  IC = cpu->machine->cache_picache - 12;                  IC = cpu->cd.mips.cache_picache - 12;
129                  IC = IC < 0? 0 : (IC > 7? 7 : IC);                  IC = IC < 0? 0 : (IC > 7? 7 : IC);
130                  DC = cpu->machine->cache_pdcache - 12;                  DC = cpu->cd.mips.cache_pdcache - 12;
131                  DC = DC < 0? 0 : (DC > 7? 7 : DC);                  DC = DC < 0? 0 : (DC > 7? 7 : DC);
132                  SC = cpu->machine->cache_secondary? 0 : 1;                  SC = cpu->cd.mips.cache_secondary? 0 : 1;
133                  c->reg[COP0_CONFIG] =                  c->reg[COP0_CONFIG] =
134                        (   0 << 31)      /*  Master/Checker present bit  */                        (   0 << 31)      /*  Master/Checker present bit  */
135                      | (0x00 << 28)      /*  EC: system clock divisor,                      | (0x00 << 28)      /*  EC: system clock divisor,
# Line 175  static void initialize_cop0_config(struc Line 161  static void initialize_cop0_config(struc
161                      ;                      ;
162                  break;                  break;
163          case MIPS_R4100:        /*  According to the VR4131 manual:  */          case MIPS_R4100:        /*  According to the VR4131 manual:  */
164                  IB = cpu->machine->cache_picache_linesize - 4;                  IB = cpu->cd.mips.cache_picache_linesize - 4;
165                  IB = IB < 0? 0 : (IB > 1? 1 : IB);                  IB = IB < 0? 0 : (IB > 1? 1 : IB);
166                  DB = cpu->machine->cache_pdcache_linesize - 4;                  DB = cpu->cd.mips.cache_pdcache_linesize - 4;
167                  DB = DB < 0? 0 : (DB > 1? 1 : DB);                  DB = DB < 0? 0 : (DB > 1? 1 : DB);
168                  IC = cpu->machine->cache_picache - 10;                  IC = cpu->cd.mips.cache_picache - 10;
169                  IC = IC < 0? 0 : (IC > 7? 7 : IC);                  IC = IC < 0? 0 : (IC > 7? 7 : IC);
170                  DC = cpu->machine->cache_pdcache - 10;                  DC = cpu->cd.mips.cache_pdcache - 10;
171                  DC = DC < 0? 0 : (DC > 7? 7 : DC);                  DC = DC < 0? 0 : (DC > 7? 7 : DC);
172                  c->reg[COP0_CONFIG] =                  c->reg[COP0_CONFIG] =
173                        (   0 << 31)      /*  IS: Instruction Streaming bit  */                        (   0 << 31)      /*  IS: Instruction Streaming bit  */
# Line 246  static void initialize_cop0_config(struc Line 232  static void initialize_cop0_config(struc
232          case MIPS_R10000:          case MIPS_R10000:
233          case MIPS_R12000:          case MIPS_R12000:
234          case MIPS_R14000:          case MIPS_R14000:
235                  IC = cpu->machine->cache_picache - 12;                  IC = cpu->cd.mips.cache_picache - 12;
236                  IC = IC < 0? 0 : (IC > 7? 7 : IC);                  IC = IC < 0? 0 : (IC > 7? 7 : IC);
237                  DC = cpu->machine->cache_pdcache - 12;                  DC = cpu->cd.mips.cache_pdcache - 12;
238                  DC = DC < 0? 0 : (DC > 7? 7 : DC);                  DC = DC < 0? 0 : (DC > 7? 7 : DC);
239                  SC = cpu->machine->cache_secondary - 19;                  SC = cpu->cd.mips.cache_secondary - 19;
240                  SC = SC < 0? 0 : (SC > 7? 7 : SC);                  SC = SC < 0? 0 : (SC > 7? 7 : SC);
241                  /*  According to the R10000 User's Manual:  */                  /*  According to the R10000 User's Manual:  */
242                  c->reg[COP0_CONFIG] =                  c->reg[COP0_CONFIG] =
# Line 373  struct mips_coproc *mips_coproc_new(stru Line 359  struct mips_coproc *mips_coproc_new(stru
359  {  {
360          struct mips_coproc *c;          struct mips_coproc *c;
361    
362          c = malloc(sizeof(struct mips_coproc));          CHECK_ALLOCATION(c = malloc(sizeof(struct mips_coproc)));
         if (c == NULL) {  
                 fprintf(stderr, "out of memory\n");  
                 exit(1);  
         }  
   
363          memset(c, 0, sizeof(struct mips_coproc));          memset(c, 0, sizeof(struct mips_coproc));
364    
365          c->coproc_nr = coproc_nr;          c->coproc_nr = coproc_nr;
366    
367          if (coproc_nr == 0) {          if (coproc_nr == 0) {
# Line 438  struct mips_coproc *mips_coproc_new(stru Line 420  struct mips_coproc *mips_coproc_new(stru
420    
421    
422  /*  /*
423     *  mips_timer_tick():
424     */
425    static void mips_timer_tick(struct timer *timer, void *extra)
426    {
427            struct cpu *cpu = (struct cpu *) extra;
428    
429            cpu->cd.mips.compare_interrupts_pending ++;
430    
431            if ((int32_t) (cpu->cd.mips.coproc[0]->reg[COP0_COUNT] -
432                cpu->cd.mips.coproc[0]->reg[COP0_COMPARE]) < 0) {
433                    cpu->cd.mips.coproc[0]->reg[COP0_COUNT] =
434                        cpu->cd.mips.coproc[0]->reg[COP0_COMPARE];
435            }
436    }
437    
438    
439    /*
440   *  mips_coproc_tlb_set_entry():   *  mips_coproc_tlb_set_entry():
441   *   *
442   *  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 516  void mips_coproc_tlb_set_entry(struct cp
516   *   *
517   *  Note: In the R3000 case, the asid argument is shifted 6 bits.   *  Note: In the R3000 case, the asid argument is shifted 6 bits.
518   */   */
519  static void invalidate_asid(struct cpu *cpu, int asid)  static void invalidate_asid(struct cpu *cpu, unsigned int asid)
520  {  {
521          struct mips_coproc *cp = cpu->cd.mips.coproc[0];          struct mips_coproc *cp = cpu->cd.mips.coproc[0];
522          int i, ntlbs = cp->nr_of_tlbs;          unsigned int i, ntlbs = cp->nr_of_tlbs;
523          struct mips_tlb *tlb = cp->tlbs;          struct mips_tlb *tlb = cp->tlbs;
524    
525          if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {          if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
# Line 536  static void invalidate_asid(struct cpu * Line 535  static void invalidate_asid(struct cpu *
535                  int non4kpages = 0;                  int non4kpages = 0;
536                  uint64_t topbit = 1, fillmask = 0xffffff0000000000ULL;                  uint64_t topbit = 1, fillmask = 0xffffff0000000000ULL;
537    
538                  if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) {                  if (cpu->is_32bit) {
539                            topbit = 0x80000000;
540                            fillmask = 0xffffffff00000000ULL;
541                    } else if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) {
542                          topbit <<= 43;                          topbit <<= 43;
543                          fillmask <<= 4;                          fillmask <<= 4;
544                  } else {                  } else {
# Line 592  void coproc_register_read(struct cpu *cp Line 594  void coproc_register_read(struct cpu *cp
594          if (cp->coproc_nr==0 && reg_nr==COP0_PAGEMASK)  unimpl = 0;          if (cp->coproc_nr==0 && reg_nr==COP0_PAGEMASK)  unimpl = 0;
595          if (cp->coproc_nr==0 && reg_nr==COP0_WIRED)     unimpl = 0;          if (cp->coproc_nr==0 && reg_nr==COP0_WIRED)     unimpl = 0;
596          if (cp->coproc_nr==0 && reg_nr==COP0_BADVADDR)  unimpl = 0;          if (cp->coproc_nr==0 && reg_nr==COP0_BADVADDR)  unimpl = 0;
597          if (cp->coproc_nr==0 && reg_nr==COP0_COUNT)     unimpl = 0;          if (cp->coproc_nr==0 && reg_nr==COP0_COUNT) {
598                    /*  TODO: Increase count in a more meaningful way!  */
599                    cp->reg[COP0_COUNT] = (int32_t) (cp->reg[COP0_COUNT] + 1);
600                    unimpl = 0;
601            }
602          if (cp->coproc_nr==0 && reg_nr==COP0_ENTRYHI)   unimpl = 0;          if (cp->coproc_nr==0 && reg_nr==COP0_ENTRYHI)   unimpl = 0;
603          if (cp->coproc_nr==0 && reg_nr==COP0_COMPARE)   unimpl = 0;          if (cp->coproc_nr==0 && reg_nr==COP0_COMPARE)   unimpl = 0;
604          if (cp->coproc_nr==0 && reg_nr==COP0_STATUS)    unimpl = 0;          if (cp->coproc_nr==0 && reg_nr==COP0_STATUS)    unimpl = 0;
# Line 658  void coproc_register_write(struct cpu *c Line 664  void coproc_register_write(struct cpu *c
664          int readonly = 0;          int readonly = 0;
665          uint64_t tmp = *ptr;          uint64_t tmp = *ptr;
666          uint64_t tmp2 = 0, old;          uint64_t tmp2 = 0, old;
667          int inval = 0, old_asid, oldmode;          int inval = 0;
668            unsigned int old_asid;
669            uint64_t oldmode;
670    
671          switch (cp->coproc_nr) {          switch (cp->coproc_nr) {
672          case 0:          case 0:
# Line 750  void coproc_register_write(struct cpu *c Line 758  void coproc_register_write(struct cpu *c
758                          unimpl = 0;                          unimpl = 0;
759                          break;                          break;
760                  case COP0_COMPARE:                  case COP0_COMPARE:
761                          /*  Clear the timer interrupt bit (bit 7):  */                          if (cpu->machine->emulated_hz > 0) {
762                          cpu->cd.mips.compare_register_set = 1;                                  int32_t compare_diff = tmp -
763                          mips_cpu_interrupt_ack(cpu, 7);                                      cp->reg[COP0_COMPARE];
764                                    double hz;
765    
766                                    if (compare_diff < 0)
767                                            hz = tmp - cp->reg[COP0_COUNT];
768    
769                                    if (compare_diff == 0)
770                                            hz = 0;
771                                    else
772                                            hz = (double)cpu->machine->emulated_hz
773                                                / (double)compare_diff;
774    /*
775     *  TODO: DON'T HARDCODE THIS!
776     */
777    hz = 100.0;
778    
779                                    /*  Initialize or re-set the periodic timer:  */
780                                    if (hz > 0) {
781                                            if (cpu->cd.mips.timer == NULL)
782                                                    cpu->cd.mips.timer = timer_add(
783                                                        hz, mips_timer_tick, cpu);
784                                            else
785                                                    timer_update_frequency(
786                                                        cpu->cd.mips.timer, hz);
787                                    }
788                            }
789    
790                            /*  Ack the periodic timer, if it was asserted:  */
791                            if (cp->reg[COP0_CAUSE] & 0x8000 &&
792                                cpu->cd.mips.compare_interrupts_pending > 0)
793                                    cpu->cd.mips.compare_interrupts_pending --;
794    
795                            /*  Clear the timer interrupt assertion (bit 7):  */
796                            cp->reg[COP0_CAUSE] &= ~0x8000;
797    
798                          if (tmp != (uint64_t)(int64_t)(int32_t)tmp)                          if (tmp != (uint64_t)(int64_t)(int32_t)tmp)
799                                  fatal("WARNING: trying to write a 64-bit value"                                  fatal("WARNING: trying to write a 64-bit value"
800                                      " to the COMPARE register!\n");                                      " to the COMPARE register!\n");
801    
802                          tmp = (int64_t)(int32_t)tmp;                          tmp = (int64_t)(int32_t)tmp;
803                            cpu->cd.mips.compare_register_set = 1;
804                          unimpl = 0;                          unimpl = 0;
805                          break;                          break;
806                  case COP0_ENTRYHI:                  case COP0_ENTRYHI:
# Line 916  void coproc_register_write(struct cpu *c Line 960  void coproc_register_write(struct cpu *c
960                      cp->coproc_nr, reg_nr, cp->coproc_nr==0?                      cp->coproc_nr, reg_nr, cp->coproc_nr==0?
961                      cop0_names[reg_nr] : "?", (long long)tmp);                      cop0_names[reg_nr] : "?", (long long)tmp);
962    
963                  mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0,                  /*  mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0,
964                      cp->coproc_nr, 0, 0, 0);                      cp->coproc_nr, 0, 0, 0);
965                  return;                  return;  */
966          }          }
967    
968          if (readonly) {          if (readonly) {
# Line 1201  static int fpu_function(struct cpu *cpu, Line 1245  static int fpu_function(struct cpu *cpu,
1245    
1246          /*  bc1f, bc1t, bc1fl, bc1tl:  */          /*  bc1f, bc1t, bc1fl, bc1tl:  */
1247          if ((function & 0x03e00000) == 0x01000000) {          if ((function & 0x03e00000) == 0x01000000) {
1248                  int nd, tf, imm, cond_true;                  int nd, tf, imm;
1249                  char *instr_mnem;                  char *instr_mnem;
1250    
1251                  /*  cc are bits 20..18:  */                  /*  cc are bits 20..18:  */
# Line 1224  static int fpu_function(struct cpu *cpu, Line 1268  static int fpu_function(struct cpu *cpu,
1268                  if (unassemble_only)                  if (unassemble_only)
1269                          return 1;                          return 1;
1270    
1271                  if (cpu->delay_slot) {                  fatal("INTERNAL ERROR: MIPS coprocessor branches should not"
1272                          fatal("%s: jump inside a jump's delay slot, "                      " be implemented in cpu_mips_coproc.c, but in"
1273                              "or similar. TODO\n", instr_mnem);                      " cpu_mips_instr.c!\n");
1274                          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;  
1275          }          }
1276    
1277          /*  add.fmt: Floating-point add  */          /*  add.fmt: Floating-point add  */
# Line 1467  void coproc_tlbpr(struct cpu *cpu, int r Line 1485  void coproc_tlbpr(struct cpu *cpu, int r
1485                              R2K3K_INDEX_SHIFT;                              R2K3K_INDEX_SHIFT;
1486                          if (i >= cp->nr_of_tlbs) {                          if (i >= cp->nr_of_tlbs) {
1487                                  /*  TODO:  exception?  */                                  /*  TODO:  exception?  */
1488                                  fatal("warning: tlbr from index %i (too "                                  fatal("[ warning: tlbr from index %i (too "
1489                                      "high)\n", i);                                      "high) ]\n", i);
1490                                  return;                                  return;
1491                          }                          }
1492    
1493                          /*                          cp->reg[COP0_ENTRYHI]  = cp->tlbs[i].hi;
1494                           *  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; */  
1495                  } else {                  } else {
1496                          /*  R4000:  */                          /*  R4000:  */
1497                          i = cp->reg[COP0_INDEX] & INDEX_MASK;                          i = cp->reg[COP0_INDEX] & INDEX_MASK;
# Line 1651  void coproc_tlbwri(struct cpu *cpu, int Line 1663  void coproc_tlbwri(struct cpu *cpu, int
1663                      (cp->reg[COP0_ENTRYHI] & R2K3K_ENTRYHI_ASID_MASK) ))                      (cp->reg[COP0_ENTRYHI] & R2K3K_ENTRYHI_ASID_MASK) ))
1664                          cpu->invalidate_translation_caches(cpu, oldvaddr,                          cpu->invalidate_translation_caches(cpu, oldvaddr,
1665                              INVALIDATE_VADDR);                              INVALIDATE_VADDR);
1666    
1667                  break;                  break;
1668    
1669          default:if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) {          default:if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) {
1670                          oldvaddr = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK_R10K;                          oldvaddr = cp->tlbs[index].hi &
1671                                (ENTRYHI_VPN2_MASK_R10K | ENTRYHI_R_MASK);
1672                          /*  44 addressable bits:  */                          /*  44 addressable bits:  */
1673                          if (oldvaddr & 0x80000000000ULL)                          if (oldvaddr & 0x80000000000ULL)
1674                                  oldvaddr |= 0xfffff00000000000ULL;                                  oldvaddr |= 0x3ffff00000000000ULL;
1675                  } else if (cpu->is_32bit) {                  } else if (cpu->is_32bit) {
1676                          /*  MIPS32 etc.:  */                          /*  MIPS32 etc.:  */
1677                          oldvaddr = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK;                          oldvaddr = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK;
1678                          oldvaddr = (int32_t)oldvaddr;                          oldvaddr = (int32_t)oldvaddr;
1679                  } else {                  } else {
1680                          /*  Assume MMU4K  */                          /*  Assume MMU4K  */
1681                          oldvaddr = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK;                          oldvaddr = cp->tlbs[index].hi &
1682                                (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK);
1683                          /*  40 addressable bits:  */                          /*  40 addressable bits:  */
1684                          if (oldvaddr & 0x8000000000ULL)                          if (oldvaddr & 0x8000000000ULL)
1685                                  oldvaddr |= 0xffffff0000000000ULL;                                  oldvaddr |= 0x3fffff0000000000ULL;
1686                  }                  }
1687    
 #if 0  
                 /*  TODO: FIX THIS! It shouldn't be needed!  */  
                 cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);  
 #else  
1688                  /*                  /*
1689                   *  TODO: non-4KB page sizes!                   *  TODO: non-4KB page sizes!
1690                   */                   */
# Line 1683  void coproc_tlbwri(struct cpu *cpu, int Line 1694  void coproc_tlbwri(struct cpu *cpu, int
1694                  if (cp->tlbs[index].lo1 & ENTRYLO_V)                  if (cp->tlbs[index].lo1 & ENTRYLO_V)
1695                          cpu->invalidate_translation_caches(cpu, oldvaddr|0x1000,                          cpu->invalidate_translation_caches(cpu, oldvaddr|0x1000,
1696                              INVALIDATE_VADDR);                              INVALIDATE_VADDR);
 #endif  
1697          }          }
1698    
1699  #if 0  #if 0
# Line 1701  void coproc_tlbwri(struct cpu *cpu, int Line 1711  void coproc_tlbwri(struct cpu *cpu, int
1711                  int i;                  int i;
1712                  unsigned int asid;                  unsigned int asid;
1713    
1714                  vaddr1 = cp->reg[COP0_ENTRYHI] & ENTRYHI_VPN2_MASK_R10K;                  vaddr1 = cp->reg[COP0_ENTRYHI] &
1715                        (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK_R10K);
1716                  asid = cp->reg[COP0_ENTRYHI] & ENTRYHI_ASID;                  asid = cp->reg[COP0_ENTRYHI] & ENTRYHI_ASID;
1717                  /*  Since this is just a warning, it's probably not necessary                  /*  Since this is just a warning, it's probably not necessary
1718                      to use R4000 masks etc.  */                      to use R4000 masks etc.  */
# Line 1714  void coproc_tlbwri(struct cpu *cpu, int Line 1725  void coproc_tlbwri(struct cpu *cpu, int
1725                              (cp->tlbs[i].hi & ENTRYHI_ASID) != asid)                              (cp->tlbs[i].hi & ENTRYHI_ASID) != asid)
1726                                  continue;                                  continue;
1727    
1728                          vaddr2 = cp->tlbs[i].hi & ENTRYHI_VPN2_MASK_R10K;                          vaddr2 = cp->tlbs[i].hi &
1729                                (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK_R10K);
1730                          if (vaddr1 == vaddr2 && ((cp->tlbs[i].lo0 &                          if (vaddr1 == vaddr2 && ((cp->tlbs[i].lo0 &
1731                              ENTRYLO_V) || (cp->tlbs[i].lo1 & ENTRYLO_V)))                              ENTRYLO_V) || (cp->tlbs[i].lo1 & ENTRYLO_V)))
1732                                  fatal("\n[ WARNING! tlbw%s to index 0x%02x "                                  fatal("\n[ WARNING! tlbw%s to index 0x%02x "
# Line 1748  void coproc_tlbwri(struct cpu *cpu, int Line 1760  void coproc_tlbwri(struct cpu *cpu, int
1760                              INVALIDATE_PADDR);                              INVALIDATE_PADDR);
1761                  }                  }
1762    
1763                    /*  Set new last_written_tlb_index hint:  */
1764                    cpu->cd.mips.last_written_tlb_index = index;
1765    
1766                  if (cp->reg[COP0_STATUS] & MIPS1_ISOL_CACHES) {                  if (cp->reg[COP0_STATUS] & MIPS1_ISOL_CACHES) {
1767                          fatal("Wow! Interesting case; tlbw* while caches"                          fatal("Wow! Interesting case; tlbw* while caches"
1768                              " are isolated. TODO\n");                              " are isolated. TODO\n");
# Line 1768  void coproc_tlbwri(struct cpu *cpu, int Line 1783  void coproc_tlbwri(struct cpu *cpu, int
1783                  int pfn_shift = 12, vpn_shift = 12;                  int pfn_shift = 12, vpn_shift = 12;
1784                  int wf0, wf1, mask;                  int wf0, wf1, mask;
1785                  uint64_t vaddr0, vaddr1, paddr0, paddr1, ptmp;                  uint64_t vaddr0, vaddr1, paddr0, paddr1, ptmp;
1786                    uint64_t psize;
1787    
1788                  cp->tlbs[index].mask = cp->reg[COP0_PAGEMASK];                  cp->tlbs[index].mask = cp->reg[COP0_PAGEMASK];
1789                  cp->tlbs[index].hi   = cp->reg[COP0_ENTRYHI];                  cp->tlbs[index].hi   = cp->reg[COP0_ENTRYHI];
# Line 1806  void coproc_tlbwri(struct cpu *cpu, int Line 1822  void coproc_tlbwri(struct cpu *cpu, int
1822                  }                  }
1823    
1824                  paddr0 = ((cp->tlbs[index].lo0 & ENTRYLO_PFN_MASK)                  paddr0 = ((cp->tlbs[index].lo0 & ENTRYLO_PFN_MASK)
1825                      >> ENTRYLO_PFN_SHIFT) << pfn_shift;                      >> ENTRYLO_PFN_SHIFT) << pfn_shift
1826                        >> vpn_shift << vpn_shift;
1827                  paddr1 = ((cp->tlbs[index].lo1 & ENTRYLO_PFN_MASK)                  paddr1 = ((cp->tlbs[index].lo1 & ENTRYLO_PFN_MASK)
1828                      >> ENTRYLO_PFN_SHIFT) << pfn_shift;                      >> ENTRYLO_PFN_SHIFT) << pfn_shift
1829                        >> vpn_shift << vpn_shift;
1830    
1831                  if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) {                  if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) {
1832                          vaddr0 = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK_R10K;                          vaddr0 = cp->tlbs[index].hi &
1833                                (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK_R10K);
1834                          /*  44 addressable bits:  */                          /*  44 addressable bits:  */
1835                          if (vaddr0 & 0x80000000000ULL)                          if (vaddr0 & 0x80000000000ULL)
1836                                  vaddr0 |= 0xfffff00000000000ULL;                                  vaddr0 |= 0x3ffff00000000000ULL;
1837                  } else if (cpu->is_32bit) {                  } else if (cpu->is_32bit) {
1838                          /*  MIPS32 etc.:  */                          /*  MIPS32 etc.:  */
1839                          vaddr0 = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK;                          vaddr0 = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK;
1840                          vaddr0 = (int32_t)vaddr0;                          vaddr0 = (int32_t)vaddr0;
1841                  } else {                  } else {
1842                          /*  Assume MMU4K  */                          /*  Assume MMU4K  */
1843                          vaddr0 = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK;                          vaddr0 = cp->tlbs[index].hi &
1844                                (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK);
1845                          /*  40 addressable bits:  */                          /*  40 addressable bits:  */
1846                          if (vaddr0 & 0x8000000000ULL)                          if (vaddr0 & 0x8000000000ULL)
1847                                  vaddr0 |= 0xffffff0000000000ULL;                                  vaddr0 |= 0x3fffff0000000000ULL;
1848                  }                  }
1849    
1850                  vaddr1 = vaddr0 | (1 << vpn_shift);                  vaddr1 = vaddr0 | (1 << vpn_shift);
# Line 1849  void coproc_tlbwri(struct cpu *cpu, int Line 1869  void coproc_tlbwri(struct cpu *cpu, int
1869                   *  Invalidate any code translations, if we are writing Dirty                   *  Invalidate any code translations, if we are writing Dirty
1870                   *  pages to the TLB:  (TODO: 4KB hardcoded... ugly)                   *  pages to the TLB:  (TODO: 4KB hardcoded... ugly)
1871                   */                   */
1872                  for (ptmp = 0; ptmp < (1 << pfn_shift); ptmp += 0x1000) {                  psize = 1 << pfn_shift;
1873                    for (ptmp = 0; ptmp < psize; ptmp += 0x1000) {
1874                          if (wf0)                          if (wf0)
1875                                  cpu->invalidate_code_translation(cpu,                                  cpu->invalidate_code_translation(cpu,
1876                                      paddr0 + ptmp, INVALIDATE_PADDR);                                      paddr0 + ptmp, INVALIDATE_PADDR);
# Line 1876  void coproc_tlbwri(struct cpu *cpu, int Line 1897  void coproc_tlbwri(struct cpu *cpu, int
1897                  if (memblock != NULL && cp->reg[COP0_ENTRYLO1] & ENTRYLO_V)                  if (memblock != NULL && cp->reg[COP0_ENTRYLO1] & ENTRYLO_V)
1898                          cpu->update_translation_table(cpu, vaddr1, memblock,                          cpu->update_translation_table(cpu, vaddr1, memblock,
1899                              wf1, paddr1);                              wf1, paddr1);
1900    
1901                    /*  Set new last_written_tlb_index hint:  */
1902                    cpu->cd.mips.last_written_tlb_index = index;
1903          }          }
1904  }  }
1905    
# Line 2098  void coproc_function(struct cpu *cpu, st Line 2122  void coproc_function(struct cpu *cpu, st
2122    
2123          /*  TLB operations and other things:  */          /*  TLB operations and other things:  */
2124          if (cp->coproc_nr == 0) {          if (cp->coproc_nr == 0) {
2125                  op = (function) & 0xff;                  if (!unassemble_only) {
2126                            fatal("FATAL INTERNAL ERROR: Should be implemented"
2127                                " with dyntrans instead.\n");
2128                            exit(1);
2129                    }
2130    
2131                  switch (co_bit) {                  switch (co_bit) {
2132                    case 0:
2133                            if ((function & 0x03e0ffdf) == 0x01606000) {
2134                                    debug("%ci", function & 0x20? 'e' : 'd');
2135                                    if (rt != MIPS_GPR_ZERO)
2136                                            debug("\t%s", regnames[rt]);
2137                                    debug("\n");
2138                                    return;
2139                            }
2140                            break;
2141                  case 1:                  case 1:
2142                            op = (function) & 0xff;
2143                          switch (op) {                          switch (op) {
2144                          case COP0_TLBR:         /*  Read indexed TLB entry  */                          case COP0_TLBR:         /*  Read indexed TLB entry  */
2145                                  if (unassemble_only) {                                  debug("tlbr\n");
                                         debug("tlbr\n");  
                                         return;  
                                 }  
                                 coproc_tlbpr(cpu, 1);  
2146                                  return;                                  return;
2147                          case COP0_TLBWI:        /*  Write indexed  */                          case COP0_TLBWI:        /*  Write indexed  */
2148                          case COP0_TLBWR:        /*  Write random  */                          case COP0_TLBWR:        /*  Write random  */
2149                                  if (unassemble_only) {                                  if (op == COP0_TLBWI)
2150                                          if (op == COP0_TLBWI)                                          debug("tlbwi");
2151                                                  debug("tlbwi");                                  else
2152                                          else                                          debug("tlbwr");
2153                                                  debug("tlbwr");                                  if (!running) {
2154                                          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]);  
2155                                          return;                                          return;
2156                                  }                                  }
2157                                  coproc_tlbwri(cpu, op == COP0_TLBWR);                                  debug("\tindex=%08llx",
2158                                        (long long)cp->reg[COP0_INDEX]);
2159                                    debug(", random=%08llx",
2160                                        (long long)cp->reg[COP0_RANDOM]);
2161                                    debug(", mask=%016llx",
2162                                        (long long)cp->reg[COP0_PAGEMASK]);
2163                                    debug(", hi=%016llx",
2164                                        (long long)cp->reg[COP0_ENTRYHI]);
2165                                    debug(", lo0=%016llx",
2166                                        (long long)cp->reg[COP0_ENTRYLO0]);
2167                                    debug(", lo1=%016llx\n",
2168                                        (long long)cp->reg[COP0_ENTRYLO1]);
2169                                  return;                                  return;
2170                          case COP0_TLBP:         /*  Probe TLB for                          case COP0_TLBP:         /*  Probe TLB for
2171                                                      matching entry  */                                                      matching entry  */
2172                                  if (unassemble_only) {                                  debug("tlbp\n");
                                         debug("tlbp\n");  
                                         return;  
                                 }  
                                 coproc_tlbpr(cpu, 0);  
2173                                  return;                                  return;
2174                          case COP0_RFE:          /*  R2000/R3000 only:                          case COP0_RFE:          /*  R2000/R3000 only:
2175                                                      Return from Exception  */                                                      Return from Exception  */
2176                                  if (unassemble_only) {                                  debug("rfe\n");
2177                                          debug("rfe\n");                                  return;
                                         return;  
                                 }  
                                 fatal("Internal error (rfe): Should be "  
                                     "implemented in dyntrans instead.\n");  
                                 exit(1);  
2178                          case COP0_ERET: /*  R4000: Return from exception  */                          case COP0_ERET: /*  R4000: Return from exception  */
2179                                  if (unassemble_only) {                                  debug("eret\n");
2180                                          debug("eret\n");                                  return;
                                         return;  
                                 }  
                                 fatal("Internal error (eret): Should be "  
                                     "implemented in dyntrans instead.\n");  
                                 exit(1);  
2181                          case COP0_DERET:                          case COP0_DERET:
2182                                  if (unassemble_only) {                                  debug("deret\n");
2183                                          debug("deret\n");                                  return;
2184                                          return;                          case COP0_WAIT:
2185                                    {
2186                                            int code = (function >> 6) & 0x7ffff;
2187                                            debug("wait");
2188                                            if (code > 0)
2189                                                    debug("\t0x%x", code);
2190                                            debug("\n");
2191                                  }                                  }
                                 /*  
                                  *  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;  
2192                                  return;                                  return;
2193                          case COP0_STANDBY:                          case COP0_STANDBY:
2194                                  if (unassemble_only) {                                  debug("standby\n");
                                         debug("standby\n");  
                                         return;  
                                 }  
                                 /*  TODO: Hm. Do something here?  */  
2195                                  return;                                  return;
2196                          case COP0_SUSPEND:                          case COP0_SUSPEND:
2197                                  if (unassemble_only) {                                  debug("suspend\n");
                                         debug("suspend\n");  
                                         return;  
                                 }  
                                 /*  TODO: Hm. Do something here?  */  
2198                                  return;                                  return;
2199                          case COP0_HIBERNATE:                          case COP0_HIBERNATE:
2200                                  if (unassemble_only) {                                  debug("hibernate\n");
                                         debug("hibernate\n");  
                                         return;  
                                 }  
                                 /*  TODO: Hm. Do something here?  */  
2201                                  return;                                  return;
2202                          default:                          default:
2203                                  ;                                  ;
2204                          }                          }
2205                  default:                          break;
                         ;  
2206                  }                  }
2207          }          }
2208    
# Line 2219  void coproc_function(struct cpu *cpu, st Line 2216  void coproc_function(struct cpu *cpu, st
2216                  return;                  return;
2217          }          }
2218    
         /*  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;  
         }  
   
2219          if (unassemble_only) {          if (unassemble_only) {
2220                  debug("cop%i\t0x%08x (unimplemented)\n", cpnr, (int)function);                  debug("cop%i\t0x%08x (unimplemented)\n", cpnr, (int)function);
2221                  return;                  return;
# Line 2242  void coproc_function(struct cpu *cpu, st Line 2228  void coproc_function(struct cpu *cpu, st
2228          mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cp->coproc_nr, 0, 0, 0);          mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cp->coproc_nr, 0, 0, 0);
2229  }  }
2230    
 #endif  /*  ENABLE_MIPS  */  

Legend:
Removed from v.28  
changed lines
  Added in v.42

  ViewVC Help
Powered by ViewVC 1.1.26