/[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 9 by dpavlin, Mon Oct 8 16:18:11 2007 UTC revision 10 by dpavlin, Mon Oct 8 16:18:27 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: cpu_mips_coproc.c,v 1.18 2005/05/07 02:13:22 debug Exp $   *  $Id: cpu_mips_coproc.c,v 1.23 2005/06/26 11:36:27 debug Exp $
29   *   *
30   *  Emulation of MIPS coprocessors.   *  Emulation of MIPS coprocessors.
31   */   */
# Line 88  static void initialize_cop0_config(struc Line 88  static void initialize_cop0_config(struc
88  #else  #else
89          const int m16 = 0;          const int m16 = 0;
90  #endif  #endif
91          int IB, DB, SB, IC, DC, SC;          int cpu_type, IB, DB, SB, IC, DC, SC;
92    
93          /*  Default values:  */          /*  Default values:  */
94          c->reg[COP0_CONFIG] =          c->reg[COP0_CONFIG] =
# Line 111  static void initialize_cop0_config(struc Line 111  static void initialize_cop0_config(struc
111                                  (TODO)  */                                  (TODO)  */
112              ;              ;
113    
114          switch (cpu->cd.mips.cpu_type.rev) {          cpu_type = cpu->cd.mips.cpu_type.rev & 0xff;
115    
116            /*  AU1x00 are treated as 4Kc (MIPS32 cores):  */
117            if ((cpu->cd.mips.cpu_type.rev & 0xffff) == 0x0301)
118                    cpu_type = MIPS_4Kc;
119    
120            switch (cpu_type) {
121          case MIPS_R4000:        /*  according to the R4000 manual  */          case MIPS_R4000:        /*  according to the R4000 manual  */
122          case MIPS_R4600:          case MIPS_R4600:
123                  IB = cpu->machine->cache_picache_linesize - 4;                  IB = cpu->machine->cache_picache_linesize - 4;
# Line 298  static void initialize_cop0_config(struc Line 304  static void initialize_cop0_config(struc
304                  break;                  break;
305          case MIPS_4Kc:          case MIPS_4Kc:
306          case MIPS_5Kc:          case MIPS_5Kc:
307                  /*  According to the MIPS64 5K User's Manual:  */                  /*  According to the MIPS64 (5K) User's Manual:  */
                 /*  TODO: How good does this work with 4K?  */  
308                  c->reg[COP0_CONFIG] =                  c->reg[COP0_CONFIG] =
309                        (   (uint32_t)1 << 31)/*  Config 1 present bit  */                        (   (uint32_t)1 << 31)/*  Config 1 present bit  */
310                      | (   0 << 20)      /*  ISD:  instruction scheduling                      | (   0 << 20)      /*  ISD:  instruction scheduling
311                                              disable (=1)  */                                              disable (=1)  */
312                      | (   0 << 17)      /*  DID:  dual issue disable  */                      | (   0 << 17)      /*  DID:  dual issue disable  */
313                      | (   0 << 16)      /*  BM:   burst mode  */                      | (   0 << 16)      /*  BM:   burst mode  */
314                      | ((cpu->byte_order==EMUL_BIG_ENDIAN? 1 : 0) << 15)                      | ((cpu->byte_order == EMUL_BIG_ENDIAN? 1 : 0) << 15)
315                                          /*  endian mode  */                                          /*  endian mode  */
316                      | ((cpu->cd.mips.cpu_type.rev==MIPS_5Kc?2:1) << 13)                      | ((cpu_type == MIPS_5Kc? 2 : 0) << 13)
317                                          /*  1=32-bit only, 2=32/64  */                                          /*  0=MIPS32, 1=64S, 2=64  */
318                      | (   0 << 10)      /*  Architecture revision  */                      | (   0 << 10)      /*  Architecture revision  */
319                      | (   1 <<  7)      /*  MMU type: 1=TLB, 3=FMT  */                      | (   1 <<  7)      /*  MMU type: 1=TLB, 3=FMT  */
320                      | (   2 <<  0)      /*  kseg0 cache coherency algorithm  */                      | (   2 <<  0)      /*  kseg0 cache coherency algorithm  */
321                      ;                      ;
322                  /*  TODO:  Config select 1: caches and such  */                  /*  Config select 1: caches etc. TODO: Associativity?  */
323                    IB = cpu->machine->cache_picache_linesize - 1;
324                    IB = IB < 0? 0 : (IB > 7? 7 : IB);
325                    DB = cpu->machine->cache_pdcache_linesize - 1;
326                    DB = DB < 0? 0 : (DB > 7? 7 : DB);
327                    IC = cpu->machine->cache_picache -
328                        cpu->machine->cache_picache_linesize - 7;
329                    DC = cpu->machine->cache_pdcache -
330                        cpu->machine->cache_pdcache_linesize - 7;
331                    cpu->cd.mips.cop0_config_select1 =
332                        ((cpu->cd.mips.cpu_type.nr_of_tlb_entries - 1) << 25)
333                        | (IC << 22)        /*  IS: I-cache sets per way  */
334                        | (IB << 19)        /*  IL: I-cache line-size  */
335                        | (1 << 16)         /*  IA: I-cache assoc. (ways-1)  */
336                        | (DC << 13)        /*  DS: D-cache sets per way  */
337                        | (DB << 10)        /*  DL: D-cache line-size  */
338                        | (1 <<  7)         /*  DA: D-cache assoc. (ways-1)  */
339                        | (16 * 0)          /*  Existance of PerformanceCounters  */
340                        | ( 8 * 0)          /*  Existance of Watch Registers  */
341                        | ( 4 * m16)        /*  Existance of MIPS16  */
342                        | ( 2 * 0)          /*  Existance of EJTAG  */
343                        | ( 1 * 1)          /*  Existance of FPU  */
344                        ;
345                  break;                  break;
346          default:          default:
347                  ;                  ;
# Line 505  void mips_coproc_tlb_set_entry(struct cp Line 532  void mips_coproc_tlb_set_entry(struct cp
532  }  }
533    
534    
535    #ifdef BINTRANS
536  /*  /*
537   *  old_update_translation_table():   *  old_update_translation_table():
538   */   */
539  static void old_update_translation_table(struct cpu *cpu, uint64_t vaddr_page,  static void old_update_translation_table(struct cpu *cpu, uint64_t vaddr_page,
540          unsigned char *host_page, int writeflag, uint64_t paddr_page)          unsigned char *host_page, int writeflag, uint64_t paddr_page)
541  {  {
 #ifdef BINTRANS  
542          int a, b;          int a, b;
543          struct vth32_table *tbl1;          struct vth32_table *tbl1;
544          void *p;          void *p_r, *p_w;
545          uint32_t p_paddr;          uint32_t p_paddr;
546    
547          /*  This table stuff only works for 32-bit mode:  */          /*  This table stuff only works for 32-bit mode:  */
# Line 555  static void old_update_translation_table Line 582  static void old_update_translation_table
582                          exit(1);                          exit(1);
583                  }                  }
584          }          }
585          p = tbl1->haddr_entry[b];          p_r = tbl1->haddr_entry[b*2];
586            p_w = tbl1->haddr_entry[b*2+1];
587          p_paddr = tbl1->paddr_entry[b];          p_paddr = tbl1->paddr_entry[b];
588          /* printf("   p = %p\n", p); */          /*  printf("   p_r=%p p_w=%p\n", p_r, p_w);  */
589          if (p == NULL && p_paddr == 0 &&          if (p_r == NULL && p_paddr == 0 &&
590              (host_page!=NULL || paddr_page!=0)) {              (host_page != NULL || paddr_page != 0)) {
591                  tbl1->refcount ++;                  tbl1->refcount ++;
592                  /*  printf("ADDING %08x -> %p wf=%i (refcount is "                  /*  printf("ADDING %08x -> %p wf=%i (refcount is "
593                      "now %i)\n", (int)vaddr_page, host_page,                      "now %i)\n", (int)vaddr_page, host_page,
# Line 567  static void old_update_translation_table Line 595  static void old_update_translation_table
595          }          }
596          if (writeflag == -1) {          if (writeflag == -1) {
597                  /*  Forced downgrade to read-only:  */                  /*  Forced downgrade to read-only:  */
598                  tbl1->haddr_entry[b] = (void *)                  tbl1->haddr_entry[b*2 + 1] = NULL;
599                      ((size_t)tbl1->haddr_entry[b] & ~1);          } else if (writeflag==0 && p_w != NULL && host_page != NULL) {
         } else if (writeflag==0 && (size_t)p&1 && host_page != NULL) {  
600                  /*  Don't degrade a page from writable to readonly.  */                  /*  Don't degrade a page from writable to readonly.  */
601          } else {          } else {
602                  if (host_page != NULL)                  if (host_page != NULL) {
603                          tbl1->haddr_entry[b] = (void *)                          tbl1->haddr_entry[b*2] = host_page;
604                              ((size_t)host_page + (writeflag?1:0));                          if (writeflag)
605                  else                                  tbl1->haddr_entry[b*2+1] = host_page;
606                          tbl1->haddr_entry[b] = NULL;                          else
607                                    tbl1->haddr_entry[b*2+1] = NULL;
608                    } else {
609                            tbl1->haddr_entry[b*2] = NULL;
610                            tbl1->haddr_entry[b*2+1] = NULL;
611                    }
612                  tbl1->paddr_entry[b] = paddr_page;                  tbl1->paddr_entry[b] = paddr_page;
613          }          }
614          tbl1->bintrans_chunks[b] = NULL;          tbl1->bintrans_chunks[b] = NULL;
 #endif  
615  }  }
616    #endif
617    
618    
619  /*  /*
# Line 617  static void invalidate_table_entry(struc Line 649  static void invalidate_table_entry(struc
649  {  {
650          int a, b;          int a, b;
651          struct vth32_table *tbl1;          struct vth32_table *tbl1;
652          void *p;          void *p_r, *p_w;
653          uint32_t p_paddr;          uint32_t p_paddr;
654    
655          if (!cpu->machine->old_bintrans_enable) {          if (!cpu->machine->old_bintrans_enable) {
# Line 647  static void invalidate_table_entry(struc Line 679  static void invalidate_table_entry(struc
679    
680          tbl1 = cpu->cd.mips.vaddr_to_hostaddr_table0_kernel[a];          tbl1 = cpu->cd.mips.vaddr_to_hostaddr_table0_kernel[a];
681          /*  printf("tbl1 = %p\n", tbl1);  */          /*  printf("tbl1 = %p\n", tbl1);  */
682          p = tbl1->haddr_entry[b];          p_r = tbl1->haddr_entry[b*2];
683            p_w = tbl1->haddr_entry[b*2+1];
684          p_paddr = tbl1->paddr_entry[b];          p_paddr = tbl1->paddr_entry[b];
685          tbl1->bintrans_chunks[b] = NULL;          tbl1->bintrans_chunks[b] = NULL;
686          /*  printf("   p = %p\n", p);  */          /*  printf("B:  p_r=%p p_w=%p\n", p_r,p_w);  */
687          if (p != NULL || p_paddr != 0) {          if (p_r != NULL || p_paddr != 0) {
688                  /*  printf("Found a mapping, "                  /*  printf("Found a mapping, "
689                      "vaddr = %08x, a = %03x, b = %03x\n", (int)vaddr,a, b);  */                      "vaddr = %08x, a = %03x, b = %03x\n", (int)vaddr,a, b);  */
690                  tbl1->haddr_entry[b] = NULL;                  tbl1->haddr_entry[b*2] = NULL;
691                    tbl1->haddr_entry[b*2+1] = NULL;
692                  tbl1->paddr_entry[b] = 0;                  tbl1->paddr_entry[b] = 0;
693                  tbl1->refcount --;                  tbl1->refcount --;
694                  if (tbl1->refcount == 0) {                  if (tbl1->refcount == 0) {
# Line 685  void clear_all_chunks_from_all_tables(st Line 719  void clear_all_chunks_from_all_tables(st
719                  tbl1 = cpu->cd.mips.vaddr_to_hostaddr_table0_kernel[a];                  tbl1 = cpu->cd.mips.vaddr_to_hostaddr_table0_kernel[a];
720                  if (tbl1 != cpu->cd.mips.vaddr_to_hostaddr_nulltable) {                  if (tbl1 != cpu->cd.mips.vaddr_to_hostaddr_nulltable) {
721                          for (b=0; b<0x400; b++) {                          for (b=0; b<0x400; b++) {
722                                  tbl1->haddr_entry[b] = NULL;                                  tbl1->haddr_entry[b*2] = NULL;
723                                    tbl1->haddr_entry[b*2+1] = NULL;
724                                  tbl1->paddr_entry[b] = 0;                                  tbl1->paddr_entry[b] = 0;
725                                  tbl1->bintrans_chunks[b] = NULL;                                  tbl1->bintrans_chunks[b] = NULL;
726                          }                          }
# Line 940  nobintrans: Line 975  nobintrans:
975   *  Read a value from a MIPS coprocessor register.   *  Read a value from a MIPS coprocessor register.
976   */   */
977  void coproc_register_read(struct cpu *cpu,  void coproc_register_read(struct cpu *cpu,
978          struct mips_coproc *cp, int reg_nr, uint64_t *ptr)          struct mips_coproc *cp, int reg_nr, uint64_t *ptr, int select)
979  {  {
980          int unimpl = 1;          int unimpl = 1;
981    
# Line 982  void coproc_register_read(struct cpu *cp Line 1017  void coproc_register_read(struct cpu *cp
1017          if (cp->coproc_nr==0 && reg_nr==COP0_CAUSE)     unimpl = 0;          if (cp->coproc_nr==0 && reg_nr==COP0_CAUSE)     unimpl = 0;
1018          if (cp->coproc_nr==0 && reg_nr==COP0_EPC)       unimpl = 0;          if (cp->coproc_nr==0 && reg_nr==COP0_EPC)       unimpl = 0;
1019          if (cp->coproc_nr==0 && reg_nr==COP0_PRID)      unimpl = 0;          if (cp->coproc_nr==0 && reg_nr==COP0_PRID)      unimpl = 0;
1020          if (cp->coproc_nr==0 && reg_nr==COP0_CONFIG)    unimpl = 0;          if (cp->coproc_nr==0 && reg_nr==COP0_CONFIG) {
1021                    if (select > 0) {
1022                            switch (select) {
1023                            case 1: *ptr = cpu->cd.mips.cop0_config_select1;
1024                                    break;
1025                            default:fatal("coproc_register_read(): unimplemented"
1026                                        " config register select %i\n", select);
1027                                    exit(1);
1028                            }
1029                            return;
1030                    }
1031                    unimpl = 0;
1032            }
1033          if (cp->coproc_nr==0 && reg_nr==COP0_LLADDR)    unimpl = 0;          if (cp->coproc_nr==0 && reg_nr==COP0_LLADDR)    unimpl = 0;
1034          if (cp->coproc_nr==0 && reg_nr==COP0_WATCHLO)   unimpl = 0;          if (cp->coproc_nr==0 && reg_nr==COP0_WATCHLO)   unimpl = 0;
1035          if (cp->coproc_nr==0 && reg_nr==COP0_WATCHHI)   unimpl = 0;          if (cp->coproc_nr==0 && reg_nr==COP0_WATCHHI)   unimpl = 0;
# Line 1022  void coproc_register_read(struct cpu *cp Line 1069  void coproc_register_read(struct cpu *cp
1069   *  Write a value to a MIPS coprocessor register.   *  Write a value to a MIPS coprocessor register.
1070   */   */
1071  void coproc_register_write(struct cpu *cpu,  void coproc_register_write(struct cpu *cpu,
1072          struct mips_coproc *cp, int reg_nr, uint64_t *ptr, int flag64)          struct mips_coproc *cp, int reg_nr, uint64_t *ptr, int flag64,
1073            int select)
1074  {  {
1075          int unimpl = 1;          int unimpl = 1;
1076          int readonly = 0;          int readonly = 0;
# Line 1188  void coproc_register_write(struct cpu *c Line 1236  void coproc_register_write(struct cpu *c
1236                          readonly = 1;                          readonly = 1;
1237                          break;                          break;
1238                  case COP0_CONFIG:                  case COP0_CONFIG:
1239                            if (select > 0) {
1240                                    switch (select) {
1241                                    case 1: cpu->cd.mips.cop0_config_select1 = tmp;
1242                                            break;
1243                                    default:fatal("coproc_register_write(): unimpl"
1244                                                "emented config register select "
1245                                                "%i\n", select);
1246                                            exit(1);
1247                                    }
1248                                    return;
1249                            }
1250    
1251                          /*  fatal("COP0_CONFIG: modifying K0 bits: "                          /*  fatal("COP0_CONFIG: modifying K0 bits: "
1252                              "0x%08x => ", cp->reg[reg_nr]);  */                              "0x%08x => ", cp->reg[reg_nr]);  */
1253                          tmp = *ptr;                          tmp = *ptr;
# Line 2515  void coproc_function(struct cpu *cpu, st Line 2575  void coproc_function(struct cpu *cpu, st
2575          if (cpnr < 2 && (((function & 0x03e007f8) == (COPz_MFCz << 21))          if (cpnr < 2 && (((function & 0x03e007f8) == (COPz_MFCz << 21))
2576                        || ((function & 0x03e007f8) == (COPz_DMFCz << 21)))) {                        || ((function & 0x03e007f8) == (COPz_DMFCz << 21)))) {
2577                  if (unassemble_only) {                  if (unassemble_only) {
2578                          debug("%s%i\t%s,%s\n",                          debug("%s%i\t%s,%s",
2579                              copz==COPz_DMFCz? "dmfc" : "mfc", cpnr,                              copz==COPz_DMFCz? "dmfc" : "mfc", cpnr,
2580                              regnames[rt], cop0_names[rd]);                              regnames[rt], cop0_names[rd]);
2581                            if (function & 7)
2582                                    debug(",%i", (int)(function & 7));
2583                            debug("\n");
2584                          return;                          return;
2585                  }                  }
2586                  coproc_register_read(cpu, cpu->cd.mips.coproc[cpnr],                  coproc_register_read(cpu, cpu->cd.mips.coproc[cpnr],
2587                      rd, &tmpvalue);                      rd, &tmpvalue, function & 7);
2588                  cpu->cd.mips.gpr[rt] = tmpvalue;                  cpu->cd.mips.gpr[rt] = tmpvalue;
2589                  if (copz == COPz_MFCz) {                  if (copz == COPz_MFCz) {
2590                          /*  Sign-extend:  */                          /*  Sign-extend:  */
# Line 2535  void coproc_function(struct cpu *cpu, st Line 2598  void coproc_function(struct cpu *cpu, st
2598          if (cpnr < 2 && (((function & 0x03e007f8) == (COPz_MTCz << 21))          if (cpnr < 2 && (((function & 0x03e007f8) == (COPz_MTCz << 21))
2599                        || ((function & 0x03e007f8) == (COPz_DMTCz << 21)))) {                        || ((function & 0x03e007f8) == (COPz_DMTCz << 21)))) {
2600                  if (unassemble_only) {                  if (unassemble_only) {
2601                          debug("%s%i\t%s,%s\n",                          debug("%s%i\t%s,%s",
2602                              copz==COPz_DMTCz? "dmtc" : "mtc", cpnr,                              copz==COPz_DMTCz? "dmtc" : "mtc", cpnr,
2603                              regnames[rt], cop0_names[rd]);                              regnames[rt], cop0_names[rd]);
2604                            if (function & 7)
2605                                    debug(",%i", (int)(function & 7));
2606                            debug("\n");
2607                          return;                          return;
2608                  }                  }
2609                  tmpvalue = cpu->cd.mips.gpr[rt];                  tmpvalue = cpu->cd.mips.gpr[rt];
# Line 2548  void coproc_function(struct cpu *cpu, st Line 2614  void coproc_function(struct cpu *cpu, st
2614                                  tmpvalue |= 0xffffffff00000000ULL;                                  tmpvalue |= 0xffffffff00000000ULL;
2615                  }                  }
2616                  coproc_register_write(cpu, cpu->cd.mips.coproc[cpnr], rd,                  coproc_register_write(cpu, cpu->cd.mips.coproc[cpnr], rd,
2617                      &tmpvalue, copz == COPz_DMTCz);                      &tmpvalue, copz == COPz_DMTCz, function & 7);
2618                  return;                  return;
2619          }          }
2620    

Legend:
Removed from v.9  
changed lines
  Added in v.10

  ViewVC Help
Powered by ViewVC 1.1.26