/[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 14 by dpavlin, Mon Oct 8 16:18:51 2007 UTC revision 22 by dpavlin, Mon Oct 8 16:19:37 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: cpu_mips_coproc.c,v 1.2 2005/09/11 10:37:37 debug Exp $   *  $Id: cpu_mips_coproc.c,v 1.10 2005/12/26 12:32:10 debug Exp $
29   *   *
30   *  Emulation of MIPS coprocessors.   *  Emulation of MIPS coprocessors.
31   */   */
# Line 40  Line 40 
40  #include "cpu.h"  #include "cpu.h"
41  #include "cpu_mips.h"  #include "cpu_mips.h"
42  #include "emul.h"  #include "emul.h"
43    #include "float_emul.h"
44  #include "machine.h"  #include "machine.h"
45  #include "memory.h"  #include "memory.h"
46  #include "mips_cpu_types.h"  #include "mips_cpu_types.h"
# Line 93  static void initialize_cop0_config(struc Line 94  static void initialize_cop0_config(struc
94          /*  Default values:  */          /*  Default values:  */
95          c->reg[COP0_CONFIG] =          c->reg[COP0_CONFIG] =
96                (   0 << 31)      /*  config1 present  */                (   0 << 31)      /*  config1 present  */
97              | (0x00 << 16)      /*  implementation dependant  */              | (0x00 << 16)      /*  implementation dependent  */
98              | ((cpu->byte_order==EMUL_BIG_ENDIAN? 1 : 0) << 15)              | ((cpu->byte_order==EMUL_BIG_ENDIAN? 1 : 0) << 15)
99                                  /*  endian mode  */                                  /*  endian mode  */
100              | (   2 << 13)      /*  0 = MIPS32,              | (   2 << 13)      /*  0 = MIPS32,
# Line 414  struct mips_coproc *mips_coproc_new(stru Line 415  struct mips_coproc *mips_coproc_new(stru
415    
416          if (coproc_nr == 0) {          if (coproc_nr == 0) {
417                  c->nr_of_tlbs = cpu->cd.mips.cpu_type.nr_of_tlb_entries;                  c->nr_of_tlbs = cpu->cd.mips.cpu_type.nr_of_tlb_entries;
418                  c->tlbs = malloc(c->nr_of_tlbs * sizeof(struct mips_tlb));                  c->tlbs = zeroed_alloc(c->nr_of_tlbs * sizeof(struct mips_tlb));
                 if (c->tlbs == NULL) {  
                         fprintf(stderr, "mips_coproc_new(): out of memory\n");  
                         exit(1);  
                 }  
419    
420                  /*                  /*
421                   *  Start with nothing in the status register. This makes sure                   *  Start with nothing in the status register. This makes sure
# Line 603  static void old_update_translation_table Line 600  static void old_update_translation_table
600          if (writeflag == -1) {          if (writeflag == -1) {
601                  /*  Forced downgrade to read-only:  */                  /*  Forced downgrade to read-only:  */
602                  tbl1->haddr_entry[b*2 + 1] = NULL;                  tbl1->haddr_entry[b*2 + 1] = NULL;
603                  if (cpu->cd.mips.host_store ==                  if (cpu->cd.mips.host_OLD_store ==
604                      cpu->cd.mips.host_store_orig)                      cpu->cd.mips.host_store_orig)
605                          cpu->cd.mips.host_store[index] = NULL;                          cpu->cd.mips.host_OLD_store[index] = NULL;
606          } else if (writeflag==0 && p_w != NULL && host_page != NULL) {          } else if (writeflag==0 && p_w != NULL && host_page != NULL) {
607                  /*  Don't degrade a page from writable to readonly.  */                  /*  Don't degrade a page from writable to readonly.  */
608          } else {          } else {
609                  if (host_page != NULL) {                  if (host_page != NULL) {
610                          tbl1->haddr_entry[b*2] = host_page;                          tbl1->haddr_entry[b*2] = host_page;
611                          if (cpu->cd.mips.host_load ==                          if (cpu->cd.mips.host_OLD_load ==
612                              cpu->cd.mips.host_load_orig)                              cpu->cd.mips.host_load_orig)
613                                  cpu->cd.mips.host_load[index] = host_page;                                  cpu->cd.mips.host_OLD_load[index] = host_page;
614                          if (writeflag) {                          if (writeflag) {
615                                  tbl1->haddr_entry[b*2+1] = host_page;                                  tbl1->haddr_entry[b*2+1] = host_page;
616                                  if (cpu->cd.mips.host_store ==                                  if (cpu->cd.mips.host_OLD_store ==
617                                      cpu->cd.mips.host_store_orig)                                      cpu->cd.mips.host_store_orig)
618                                          cpu->cd.mips.host_store[index] =                                          cpu->cd.mips.host_OLD_store[index] =
619                                              host_page;                                              host_page;
620                          } else {                          } else {
621                                  tbl1->haddr_entry[b*2+1] = NULL;                                  tbl1->haddr_entry[b*2+1] = NULL;
622                                  if (cpu->cd.mips.host_store ==                                  if (cpu->cd.mips.host_OLD_store ==
623                                      cpu->cd.mips.host_store_orig)                                      cpu->cd.mips.host_store_orig)
624                                          cpu->cd.mips.host_store[index] = NULL;                                          cpu->cd.mips.host_OLD_store[index] =
625                                                NULL;
626                          }                          }
627                  } else {                  } else {
628                          tbl1->haddr_entry[b*2] = NULL;                          tbl1->haddr_entry[b*2] = NULL;
629                          tbl1->haddr_entry[b*2+1] = NULL;                          tbl1->haddr_entry[b*2+1] = NULL;
630                          if (cpu->cd.mips.host_store ==                          if (cpu->cd.mips.host_OLD_store ==
631                              cpu->cd.mips.host_store_orig) {                              cpu->cd.mips.host_store_orig) {
632                                  cpu->cd.mips.host_load[index] = NULL;                                  cpu->cd.mips.host_OLD_load[index] = NULL;
633                                  cpu->cd.mips.host_store[index] = NULL;                                  cpu->cd.mips.host_OLD_store[index] = NULL;
634                          }                          }
635                  }                  }
636                  tbl1->paddr_entry[b] = paddr_page;                  tbl1->paddr_entry[b] = paddr_page;
# Line 642  static void old_update_translation_table Line 640  static void old_update_translation_table
640    
641    
642  /*  /*
643   *  mips_update_translation_table():   *  mips_OLD_update_translation_table():
644   */   */
645  void mips_update_translation_table(struct cpu *cpu, uint64_t vaddr_page,  void mips_OLD_update_translation_table(struct cpu *cpu, uint64_t vaddr_page,
646          unsigned char *host_page, int writeflag, uint64_t paddr_page)          unsigned char *host_page, int writeflag, uint64_t paddr_page)
647  {  {
648          if (!cpu->machine->bintrans_enable)          if (!cpu->machine->bintrans_enable)
# Line 751  void clear_all_chunks_from_all_tables(st Line 749  void clear_all_chunks_from_all_tables(st
749                                  tbl1->paddr_entry[b] = 0;                                  tbl1->paddr_entry[b] = 0;
750                                  tbl1->bintrans_chunks[b] = NULL;                                  tbl1->bintrans_chunks[b] = NULL;
751    
752                                  if (cpu->cd.mips.host_store ==                                  if (cpu->cd.mips.host_OLD_store ==
753                                      cpu->cd.mips.host_store_orig) {                                      cpu->cd.mips.host_store_orig) {
754                                          index = (a << 10) + b;                                          index = (a << 10) + b;
755                                          cpu->cd.mips.host_load[index] = NULL;                                          cpu->cd.mips.host_OLD_load[index] =
756                                          cpu->cd.mips.host_store[index] = NULL;                                              NULL;
757                                            cpu->cd.mips.host_OLD_store[index] =
758                                                NULL;
759                                  }                                  }
760                          }                          }
761                  }                  }
# Line 798  void mips_invalidate_translation_caches_ Line 798  void mips_invalidate_translation_caches_
798                                  int psize = 12;                                  int psize = 12;
799                                  int or_pmask = 0x1fff;                                  int or_pmask = 0x1fff;
800                                  int phys_shift = 12;                                  int phys_shift = 12;
801                                    int tmp_pmask = cpu->cd.mips.coproc[0]->
802                                        tlbs[i].mask | or_pmask;
803    
804                                  if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {                                  if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
805                                          or_pmask = 0x7ff;                                          or_pmask = 0x7ff;
806                                          phys_shift = 10;                                          phys_shift = 10;
807                                  }                                  }
808                                  switch (cpu->cd.mips.coproc[0]->                                  switch (tmp_pmask) {
                                     tlbs[i].mask | or_pmask) {  
809                                  case 0x000007ff:        psize = 10; break;                                  case 0x000007ff:        psize = 10; break;
810                                  case 0x00001fff:        psize = 12; break;                                  case 0x00001fff:        psize = 12; break;
811                                  case 0x00007fff:        psize = 14; break;                                  case 0x00007fff:        psize = 14; break;
# Line 816  void mips_invalidate_translation_caches_ Line 817  void mips_invalidate_translation_caches_
817                                  case 0x07ffffff:        psize = 26; break;                                  case 0x07ffffff:        psize = 26; break;
818                                  default:                                  default:
819                                          printf("invalidate_translation_caches"                                          printf("invalidate_translation_caches"
820                                              "_paddr(): bad pagemask?\n");                                              "_paddr(): bad pagemask: 0x%x\n",
821                                                (int)tmp_pmask);
822                                  }                                  }
823                                  tlb_paddr0 = (cpu->cd.mips.coproc[0]->tlbs[i].                                  tlb_paddr0 = (cpu->cd.mips.coproc[0]->tlbs[i].
824                                      lo0 & ENTRYLO_PFN_MASK)>>ENTRYLO_PFN_SHIFT;                                      lo0 & ENTRYLO_PFN_MASK)>>ENTRYLO_PFN_SHIFT;
# Line 1017  void coproc_register_read(struct cpu *cp Line 1019  void coproc_register_read(struct cpu *cp
1019          if (cp->coproc_nr==0 && reg_nr==COP0_WIRED)     unimpl = 0;          if (cp->coproc_nr==0 && reg_nr==COP0_WIRED)     unimpl = 0;
1020          if (cp->coproc_nr==0 && reg_nr==COP0_BADVADDR)  unimpl = 0;          if (cp->coproc_nr==0 && reg_nr==COP0_BADVADDR)  unimpl = 0;
1021          if (cp->coproc_nr==0 && reg_nr==COP0_COUNT) {          if (cp->coproc_nr==0 && reg_nr==COP0_COUNT) {
1022    #if 0
1023                  /*                  /*
1024                   *  This speeds up delay-loops that just read the count                   *  This speeds up delay-loops that just read the count
1025                   *  register until it has reached a certain value. (Only for                   *  register until it has reached a certain value. (Only for
# Line 1037  void coproc_register_read(struct cpu *cp Line 1040  void coproc_register_read(struct cpu *cp
1040                          cp->reg[COP0_COUNT] = (int64_t)                          cp->reg[COP0_COUNT] = (int64_t)
1041                              (int32_t)(cp->reg[COP0_COUNT] + increase);                              (int32_t)(cp->reg[COP0_COUNT] + increase);
1042                  }                  }
1043    #endif
1044                  unimpl = 0;                  unimpl = 0;
1045          }          }
1046          if (cp->coproc_nr==0 && reg_nr==COP0_ENTRYHI)   unimpl = 0;          if (cp->coproc_nr==0 && reg_nr==COP0_ENTRYHI)   unimpl = 0;
# Line 1191  void coproc_register_write(struct cpu *c Line 1194  void coproc_register_write(struct cpu *c
1194                          unimpl = 0;                          unimpl = 0;
1195                          break;                          break;
1196                  case COP0_COUNT:                  case COP0_COUNT:
1197                          if (tmp != (int64_t)(int32_t)tmp)                          if (tmp != (uint64_t)(int64_t)(int32_t)tmp)
1198                                  fatal("WARNING: trying to write a 64-bit value"                                  fatal("WARNING: trying to write a 64-bit value"
1199                                      " to the COUNT register!\n");                                      " to the COUNT register!\n");
1200                          tmp = (int64_t)(int32_t)tmp;                          tmp = (int64_t)(int32_t)tmp;
# Line 1201  void coproc_register_write(struct cpu *c Line 1204  void coproc_register_write(struct cpu *c
1204                          /*  Clear the timer interrupt bit (bit 7):  */                          /*  Clear the timer interrupt bit (bit 7):  */
1205                          cpu->cd.mips.compare_register_set = 1;                          cpu->cd.mips.compare_register_set = 1;
1206                          mips_cpu_interrupt_ack(cpu, 7);                          mips_cpu_interrupt_ack(cpu, 7);
1207                          if (tmp != (int64_t)(int32_t)tmp)                          if (tmp != (uint64_t)(int64_t)(int32_t)tmp)
1208                                  fatal("WARNING: trying to write a 64-bit value"                                  fatal("WARNING: trying to write a 64-bit value"
1209                                      " to the COMPARE register!\n");                                      " to the COMPARE register!\n");
1210                          tmp = (int64_t)(int32_t)tmp;                          tmp = (int64_t)(int32_t)tmp;
# Line 1306  void coproc_register_write(struct cpu *c Line 1309  void coproc_register_write(struct cpu *c
1309  #endif  #endif
1310    
1311                          if (cpu->cd.mips.cpu_type.mmu_model == MMU3K &&                          if (cpu->cd.mips.cpu_type.mmu_model == MMU3K &&
1312                              (oldmode & MIPS1_ISOL_CACHES) !=                              ((uint32_t)oldmode & MIPS1_ISOL_CACHES) !=
1313                              (tmp & MIPS1_ISOL_CACHES)) {                              (tmp & MIPS1_ISOL_CACHES)) {
1314                                  /*  R3000-style caches when isolated are                                  /*  R3000-style caches when isolated are
1315                                      treated in bintrans mode by changing                                      treated in bintrans mode by changing
# Line 1321  void coproc_register_write(struct cpu *c Line 1324  void coproc_register_write(struct cpu *c
1324                                            vaddr_to_hostaddr_table0_cacheisol_d;                                            vaddr_to_hostaddr_table0_cacheisol_d;
1325    
1326                                          /*  1M-entry table:  */                                          /*  1M-entry table:  */
1327                                          cpu->cd.mips.host_load =                                          cpu->cd.mips.host_OLD_load =
1328                                              cpu->cd.mips.host_store =                                              cpu->cd.mips.host_OLD_store =
1329                                              cpu->cd.mips.huge_r2k3k_cache_table;                                              cpu->cd.mips.huge_r2k3k_cache_table;
1330                                  } else {                                  } else {
1331                                          /*  2-level table:  */                                          /*  2-level table:  */
# Line 1334  void coproc_register_write(struct cpu *c Line 1337  void coproc_register_write(struct cpu *c
1337                                              vaddr_to_hostaddr_table0_user;  */                                              vaddr_to_hostaddr_table0_user;  */
1338    
1339                                          /*  1M-entry table:  */                                          /*  1M-entry table:  */
1340                                          cpu->cd.mips.host_load =                                          cpu->cd.mips.host_OLD_load =
1341                                              cpu->cd.mips.host_load_orig;                                              cpu->cd.mips.host_load_orig;
1342                                          cpu->cd.mips.host_store =                                          cpu->cd.mips.host_OLD_store =
1343                                              cpu->cd.mips.host_store_orig;                                              cpu->cd.mips.host_store_orig;
1344                                  }                                  }
1345                          }                          }
# Line 1426  void coproc_register_write(struct cpu *c Line 1429  void coproc_register_write(struct cpu *c
1429   *   *
1430   *  TODO:  Move this to some other file?   *  TODO:  Move this to some other file?
1431   */   */
1432    static int mips_fmt_to_ieee_fmt[32] = {
1433            0, 0, 0, 0,  0, 0, 0, 0,
1434            0, 0, 0, 0,  0, 0, 0, 0,
1435            IEEE_FMT_S, IEEE_FMT_D, 0, 0,
1436            IEEE_FMT_W, IEEE_FMT_L, /* PS (Paired Single) */ 0, 0,
1437            0, 0, 0, 0,  0, 0, 0, 0  };
1438    
1439    /*  MIPS floating point types:  */
1440  #define FMT_S           16  #define FMT_S           16
1441  #define FMT_D           17  #define FMT_D           17
1442  #define FMT_W           20  #define FMT_W           20
# Line 1442  void coproc_register_write(struct cpu *c Line 1453  void coproc_register_write(struct cpu *c
1453  #define FPU_OP_C        8  #define FPU_OP_C        8
1454  #define FPU_OP_ABS      9  #define FPU_OP_ABS      9
1455  #define FPU_OP_NEG      10  #define FPU_OP_NEG      10
1456  /*  TODO: CEIL.L, CEIL.W, FLOOR.L, FLOOR.W, RECIP, ROUND.L, ROUND.W,  /*  TODO: CEIL.L, CEIL.W, FLOOR.L, FLOOR.W, RECIP, ROUND.L, ROUND.W, RSQRT  */
  RSQRT  */  
   
   
 struct internal_float_value {  
         double  f;  
         int     nan;  
 };  
   
   
 /*  
  *  fpu_interpret_float_value():  
  *  
  *  Interprets a float value from binary IEEE format into an  
  *  internal_float_value struct.  
  */  
 static void fpu_interpret_float_value(uint64_t reg,  
         struct internal_float_value *fvp, int fmt)  
 {  
         int n_frac = 0, n_exp = 0;  
         int i, nan, sign = 0, exponent;  
         double fraction;  
   
         memset(fvp, 0, sizeof(struct internal_float_value));  
   
         /*  n_frac and n_exp:  */  
         switch (fmt) {  
         case FMT_S:     n_frac = 23; n_exp = 8; break;  
         case FMT_W:     n_frac = 31; n_exp = 0; break;  
         case FMT_D:     n_frac = 52; n_exp = 11; break;  
         case FMT_L:     n_frac = 63; n_exp = 0; break;  
         default:  
                 fatal("fpu_interpret_float_value(): "  
                     "unimplemented format %i\n", fmt);  
         }  
   
         /*  exponent:  */  
         exponent = 0;  
         switch (fmt) {  
         case FMT_W:  
                 reg &= 0xffffffffULL;  
         case FMT_L:  
                 break;  
         case FMT_S:  
                 reg &= 0xffffffffULL;  
         case FMT_D:  
                 exponent = (reg >> n_frac) & ((1 << n_exp) - 1);  
                 exponent -= (1 << (n_exp-1)) - 1;  
                 break;  
         default:  
                 fatal("fpu_interpret_float_value(): unimplemented "  
                     "format %i\n", fmt);  
         }  
   
         /*  nan:  */  
         nan = 0;  
         switch (fmt) {  
         case FMT_S:  
                 if (reg == 0x7fffffffULL || reg == 0x7fbfffffULL)  
                         nan = 1;  
                 break;  
         case FMT_D:  
                 if (reg == 0x7fffffffffffffffULL ||  
                     reg == 0x7ff7ffffffffffffULL)  
                         nan = 1;  
                 break;  
         }  
   
         if (nan) {  
                 fvp->f = 1.0;  
                 goto no_reasonable_result;  
         }  
   
         /*  fraction:  */  
         fraction = 0.0;  
         switch (fmt) {  
         case FMT_W:  
                 {  
                         int32_t r_int = reg;  
                         fraction = r_int;  
                 }  
                 break;  
         case FMT_L:  
                 {  
                         int64_t r_int = reg;  
                         fraction = r_int;  
                 }  
                 break;  
         case FMT_S:  
         case FMT_D:  
                 /*  sign:  */  
                 sign = (reg >> 31) & 1;  
                 if (fmt == FMT_D)  
                         sign = (reg >> 63) & 1;  
   
                 fraction = 0.0;  
                 for (i=0; i<n_frac; i++) {  
                         int bit = (reg >> i) & 1;  
                         fraction /= 2.0;  
                         if (bit)  
                                 fraction += 1.0;  
                 }  
                 /*  Add implicit bit 0:  */  
                 fraction = (fraction / 2.0) + 1.0;  
                 break;  
         default:  
                 fatal("fpu_interpret_float_value(): "  
                     "unimplemented format %i\n", fmt);  
         }  
   
         /*  form the value:  */  
         fvp->f = fraction;  
   
         /*  fatal("load  reg=%016llx sign=%i exponent=%i fraction=%f ",  
             (long long)reg, sign, exponent, fraction);  */  
   
         /*  TODO: this is awful for exponents of large magnitude.  */  
         if (exponent > 0) {  
                 /*  
                  *  NOTE / TODO:  
                  *  
                  *  This is an ulgy workaround on Alpha, where it seems that  
                  *  multiplying by 2, 1024 times causes a floating point  
                  *  exception. (Triggered by running for example NetBSD/pmax  
                  *  2.0 on an Alpha.)  
                  */  
                 if (exponent == 1024)  
                         exponent = 1023;  
   
                 while (exponent-- > 0)  
                         fvp->f *= 2.0;  
         } else if (exponent < 0) {  
                 while (exponent++ < 0)  
                         fvp->f /= 2.0;  
         }  
   
         if (sign)  
                 fvp->f = -fvp->f;  
   
 no_reasonable_result:  
         fvp->nan = nan;  
   
         /*  fatal("f = %f\n", fvp->f);  */  
 }  
1457    
1458    
1459  /*  /*
# Line 1596  no_reasonable_result: Line 1464  no_reasonable_result:
1464  static void fpu_store_float_value(struct mips_coproc *cp, int fd,  static void fpu_store_float_value(struct mips_coproc *cp, int fd,
1465          double nf, int fmt, int nan)          double nf, int fmt, int nan)
1466  {  {
1467          int n_frac = 0, n_exp = 0, signofs=0;          int ieee_fmt = mips_fmt_to_ieee_fmt[fmt];
1468          int i, exponent;          uint64_t r = ieee_store_float_value(nf, ieee_fmt, nan);
         uint64_t r = 0, r2;  
         int64_t r3;  
   
         /*  n_frac and n_exp:  */  
         switch (fmt) {  
         case FMT_S:     n_frac = 23; n_exp = 8; signofs = 31; break;  
         case FMT_W:     n_frac = 31; n_exp = 0; signofs = 31; break;  
         case FMT_D:     n_frac = 52; n_exp = 11; signofs = 63; break;  
         case FMT_L:     n_frac = 63; n_exp = 0; signofs = 63; break;  
         default:  
                 fatal("fpu_store_float_value(): unimplemented format"  
                     " %i\n", fmt);  
         }  
   
         if ((fmt == FMT_S || fmt == FMT_D) && nan)  
                 goto store_nan;  
   
         /*  fraction:  */  
         switch (fmt) {  
         case FMT_W:  
         case FMT_L:  
                 /*  
                  *  This causes an implicit conversion of double to integer.  
                  *  If nf < 0.0, then r2 will begin with a sequence of binary  
                  *  1's, which is ok.  
                  */  
                 r3 = nf;  
                 r2 = r3;  
                 r |= r2;  
   
                 if (fmt == FMT_W)  
                         r &= 0xffffffffULL;  
                 break;  
         case FMT_S:  
         case FMT_D:  
                 /*  fatal("store f=%f ", nf);  */  
   
                 /*  sign bit:  */  
                 if (nf < 0.0) {  
                         r |= ((uint64_t)1 << signofs);  
                         nf = -nf;  
                 }  
   
                 /*  
                  *  How to convert back from double to exponent + fraction:  
                  *  We want fraction to be 1.xxx, that is  
                  *  1.0 <= fraction < 2.0  
                  *  
                  *  This method is very slow but should work:  
                  */  
                 exponent = 0;  
                 while (nf < 1.0 && exponent > -1023) {  
                         nf *= 2.0;  
                         exponent --;  
                 }  
                 while (nf >= 2.0 && exponent < 1023) {  
                         nf /= 2.0;  
                         exponent ++;  
                 }  
   
                 /*  Here:   1.0 <= nf < 2.0  */  
                 /*  fatal(" nf=%f", nf);  */  
                 nf -= 1.0;      /*  remove implicit first bit  */  
                 for (i=n_frac-1; i>=0; i--) {  
                         nf *= 2.0;  
                         if (nf >= 1.0) {  
                                 r |= ((uint64_t)1 << i);  
                                 nf -= 1.0;  
                         }  
                         /*  printf("\n i=%2i r=%016llx\n", i, (long long)r);  */  
                 }  
   
                 /*  Insert the exponent into the resulting word:  */  
                 /*  (First bias, then make sure it's within range)  */  
                 exponent += (((uint64_t)1 << (n_exp-1)) - 1);  
                 if (exponent < 0)  
                         exponent = 0;  
                 if (exponent >= ((int64_t)1 << n_exp))  
                         exponent = ((int64_t)1 << n_exp) - 1;  
                 r |= (uint64_t)exponent << n_frac;  
   
                 /*  Special case for 0.0:  */  
                 if (exponent == 0)  
                         r = 0;  
   
                 /*  fatal(" exp=%i, r = %016llx\n", exponent, (long long)r);  */  
   
                 break;  
         default:  
                 /*  TODO  */  
                 fatal("fpu_store_float_value(): unimplemented format "  
                     "%i\n", fmt);  
         }  
   
 store_nan:  
         if (nan) {  
                 if (fmt == FMT_S)  
                         r = 0x7fffffffULL;  
                 else if (fmt == FMT_D)  
                         r = 0x7fffffffffffffffULL;  
                 else  
                         r = 0x7fffffffULL;  
         }  
1469    
1470          /*          /*
1471           *  TODO:  this is for 32-bit mode. It has to be updated later           *  TODO: This is for 32-bit mode. It has to be updated later
1472           *              for 64-bit coprocessor stuff.           *        for 64-bit coprocessor functionality!
1473           */           */
1474          if (fmt == FMT_D || fmt == FMT_L) {          if (fmt == FMT_D || fmt == FMT_L) {
1475                  cp->reg[fd] = r & 0xffffffffULL;                  cp->reg[fd] = r & 0xffffffffULL;
# Line 1726  store_nan: Line 1491  store_nan:
1491  /*  /*
1492   *  fpu_op():   *  fpu_op():
1493   *   *
1494   *  Perform a floating-point operation.  For those of fs and ft   *  Perform a floating-point operation. For those of fs and ft that are >= 0,
1495   *  that are >= 0, those numbers are interpreted into local   *  those numbers are interpreted into local variables.
  *  variables.  
1496   *   *
1497   *  Only FPU_OP_C (compare) returns anything of interest, 1 for   *  Only FPU_OP_C (compare) returns anything of interest, 1 for true, 0 for
1498   *  true, 0 for false.   *  false.
1499   */   */
1500  static int fpu_op(struct cpu *cpu, struct mips_coproc *cp, int op, int fmt,  static int fpu_op(struct cpu *cpu, struct mips_coproc *cp, int op, int fmt,
1501          int ft, int fs, int fd, int cond, int output_fmt)          int ft, int fs, int fd, int cond, int output_fmt)
1502  {  {
1503          /*  Potentially two input registers, fs and ft  */          /*  Potentially two input registers, fs and ft  */
1504          struct internal_float_value float_value[2];          struct ieee_float_value float_value[2];
1505          int unordered, nan;          int unordered, nan, ieee_fmt = mips_fmt_to_ieee_fmt[fmt];
1506          uint64_t fs_v = 0;          uint64_t fs_v = 0;
1507          double nf;          double nf;
1508    
# Line 1749  static int fpu_op(struct cpu *cpu, struc Line 1513  static int fpu_op(struct cpu *cpu, struc
1513                  if (fmt == FMT_D || fmt == FMT_L)                  if (fmt == FMT_D || fmt == FMT_L)
1514                          fs_v = (fs_v & 0xffffffffULL) +                          fs_v = (fs_v & 0xffffffffULL) +
1515                              (cp->reg[(fs + 1) & 31] << 32);                              (cp->reg[(fs + 1) & 31] << 32);
1516                  fpu_interpret_float_value(fs_v, &float_value[0], fmt);                  ieee_interpret_float_value(fs_v, &float_value[0], ieee_fmt);
1517          }          }
1518          if (ft >= 0) {          if (ft >= 0) {
1519                  uint64_t v = cp->reg[ft];                  uint64_t v = cp->reg[ft];
# Line 1758  static int fpu_op(struct cpu *cpu, struc Line 1522  static int fpu_op(struct cpu *cpu, struc
1522                  if (fmt == FMT_D || fmt == FMT_L)                  if (fmt == FMT_D || fmt == FMT_L)
1523                          v = (v & 0xffffffffULL) +                          v = (v & 0xffffffffULL) +
1524                              (cp->reg[(ft + 1) & 31] << 32);                              (cp->reg[(ft + 1) & 31] << 32);
1525                  fpu_interpret_float_value(v, &float_value[1], fmt);                  ieee_interpret_float_value(v, &float_value[1], ieee_fmt);
1526          }          }
1527    
1528          switch (op) {          switch (op) {
# Line 2402  void coproc_tlbwri(struct cpu *cpu, int Line 2166  void coproc_tlbwri(struct cpu *cpu, int
2166          if (cpu->cd.mips.cpu_type.mmu_model != MMU3K &&          if (cpu->cd.mips.cpu_type.mmu_model != MMU3K &&
2167              cpu->cd.mips.cpu_type.rev != MIPS_R4100) {              cpu->cd.mips.cpu_type.rev != MIPS_R4100) {
2168                  uint64_t vaddr1, vaddr2;                  uint64_t vaddr1, vaddr2;
2169                  int i, asid;                  int i;
2170                    unsigned int asid;
2171    
2172                  vaddr1 = cp->reg[COP0_ENTRYHI] & ENTRYHI_VPN2_MASK_R10K;                  vaddr1 = cp->reg[COP0_ENTRYHI] & ENTRYHI_VPN2_MASK_R10K;
2173                  asid = cp->reg[COP0_ENTRYHI] & ENTRYHI_ASID;                  asid = cp->reg[COP0_ENTRYHI] & ENTRYHI_ASID;

Legend:
Removed from v.14  
changed lines
  Added in v.22

  ViewVC Help
Powered by ViewVC 1.1.26