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

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

revision 30 by dpavlin, Mon Oct 8 16:20:40 2007 UTC revision 44 by dpavlin, Mon Oct 8 16:22:56 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.c,v 1.63 2006/08/12 11:43:13 debug Exp $   *  $Id: cpu_mips.c,v 1.84 2007/06/28 13:36:46 debug Exp $
29   *   *
30   *  MIPS core CPU emulation.   *  MIPS core CPU emulation.
31   */   */
# Line 50  Line 50 
50  #include "memory.h"  #include "memory.h"
51  #include "mips_cpu_types.h"  #include "mips_cpu_types.h"
52  #include "opcodes_mips.h"  #include "opcodes_mips.h"
53    #include "settings.h"
54  #include "symbol.h"  #include "symbol.h"
55    
56    
 extern volatile int single_step;  
   
57  static char *exception_names[] = EXCEPTION_NAMES;  static char *exception_names[] = EXCEPTION_NAMES;
58    
59  static char *hi6_names[] = HI6_NAMES;  static char *hi6_names[] = HI6_NAMES;
60  static char *regimm_names[] = REGIMM_NAMES;  static char *regimm_names[] = REGIMM_NAMES;
61  static char *special_names[] = SPECIAL_NAMES;  static char *special_names[] = SPECIAL_NAMES;
62    static char *special_rot_names[] = SPECIAL_ROT_NAMES;
63  static char *special2_names[] = SPECIAL2_NAMES;  static char *special2_names[] = SPECIAL2_NAMES;
64  static char *mmi_names[] = MMI_NAMES;  static char *mmi_names[] = MMI_NAMES;
65  static char *mmi0_names[] = MMI0_NAMES;  static char *mmi0_names[] = MMI0_NAMES;
# Line 81  void mips32_pc_to_pointers(struct cpu *) Line 81  void mips32_pc_to_pointers(struct cpu *)
81    
82    
83  /*  /*
  *  regname():  
  *  
  *  Convert a register number into either 'r0', 'r31' etc, or a symbolic  
  *  name, depending on machine->show_symbolic_register_names.  
  *  
  *  NOTE: _NOT_ reentrant.  
  */  
 static char *regname(struct machine *machine, int r)  
 {  
         static char ch[4];  
         ch[3] = ch[2] = '\0';  
   
         if (r<0 || r>=32)  
                 strlcpy(ch, "xx", sizeof(ch));  
         else if (machine->show_symbolic_register_names)  
                 strlcpy(ch, regnames[r], sizeof(ch));  
         else  
                 snprintf(ch, sizeof(ch), "r%i", r);  
   
         return ch;  
 }  
   
   
 /*  
84   *  mips_cpu_new():   *  mips_cpu_new():
85   *   *
86   *  Create a new MIPS cpu object.   *  Create a new MIPS cpu object.
# Line 180  int mips_cpu_new(struct cpu *cpu, struct Line 156  int mips_cpu_new(struct cpu *cpu, struct
156          x = DEFAULT_PCACHE_SIZE;          x = DEFAULT_PCACHE_SIZE;
157          if (cpu->cd.mips.cpu_type.pdcache)          if (cpu->cd.mips.cpu_type.pdcache)
158                  x = cpu->cd.mips.cpu_type.pdcache;                  x = cpu->cd.mips.cpu_type.pdcache;
159          if (machine->cache_pdcache == 0)          if (cpu->cd.mips.cache_pdcache == 0)
160                  machine->cache_pdcache = x;                  cpu->cd.mips.cache_pdcache = x;
161    
162          x = DEFAULT_PCACHE_SIZE;          x = DEFAULT_PCACHE_SIZE;
163          if (cpu->cd.mips.cpu_type.picache)          if (cpu->cd.mips.cpu_type.picache)
164                  x = cpu->cd.mips.cpu_type.picache;                  x = cpu->cd.mips.cpu_type.picache;
165          if (machine->cache_picache == 0)          if (cpu->cd.mips.cache_picache == 0)
166                  machine->cache_picache = x;                  cpu->cd.mips.cache_picache = x;
167    
168          if (machine->cache_secondary == 0)          if (cpu->cd.mips.cache_secondary == 0)
169                  machine->cache_secondary = cpu->cd.mips.cpu_type.scache;                  cpu->cd.mips.cache_secondary = cpu->cd.mips.cpu_type.scache;
170    
171          linesize = DEFAULT_PCACHE_LINESIZE;          linesize = DEFAULT_PCACHE_LINESIZE;
172          if (cpu->cd.mips.cpu_type.pdlinesize)          if (cpu->cd.mips.cpu_type.pdlinesize)
173                  linesize = cpu->cd.mips.cpu_type.pdlinesize;                  linesize = cpu->cd.mips.cpu_type.pdlinesize;
174          if (machine->cache_pdcache_linesize == 0)          if (cpu->cd.mips.cache_pdcache_linesize == 0)
175                  machine->cache_pdcache_linesize = linesize;                  cpu->cd.mips.cache_pdcache_linesize = linesize;
176    
177          linesize = DEFAULT_PCACHE_LINESIZE;          linesize = DEFAULT_PCACHE_LINESIZE;
178          if (cpu->cd.mips.cpu_type.pilinesize)          if (cpu->cd.mips.cpu_type.pilinesize)
179                  linesize = cpu->cd.mips.cpu_type.pilinesize;                  linesize = cpu->cd.mips.cpu_type.pilinesize;
180          if (machine->cache_picache_linesize == 0)          if (cpu->cd.mips.cache_picache_linesize == 0)
181                  machine->cache_picache_linesize = linesize;                  cpu->cd.mips.cache_picache_linesize = linesize;
182    
183          linesize = 0;          linesize = 0;
184          if (cpu->cd.mips.cpu_type.slinesize)          if (cpu->cd.mips.cpu_type.slinesize)
185                  linesize = cpu->cd.mips.cpu_type.slinesize;                  linesize = cpu->cd.mips.cpu_type.slinesize;
186          if (machine->cache_secondary_linesize == 0)          if (cpu->cd.mips.cache_secondary_linesize == 0)
187                  machine->cache_secondary_linesize = linesize;                  cpu->cd.mips.cache_secondary_linesize = linesize;
188    
189    
190          /*          /*
# Line 217  int mips_cpu_new(struct cpu *cpu, struct Line 193  int mips_cpu_new(struct cpu *cpu, struct
193          for (i=CACHE_DATA; i<=CACHE_INSTRUCTION; i++) {          for (i=CACHE_DATA; i<=CACHE_INSTRUCTION; i++) {
194                  switch (i) {                  switch (i) {
195                  case CACHE_DATA:                  case CACHE_DATA:
196                          x = 1 << machine->cache_pdcache;                          x = 1 << cpu->cd.mips.cache_pdcache;
197                          linesize = 1 << machine->cache_pdcache_linesize;                          linesize = 1 << cpu->cd.mips.cache_pdcache_linesize;
198                          break;                          break;
199                  case CACHE_INSTRUCTION:                  case CACHE_INSTRUCTION:
200                          x = 1 << machine->cache_picache;                          x = 1 << cpu->cd.mips.cache_picache;
201                          linesize = 1 << machine->cache_picache_linesize;                          linesize = 1 << cpu->cd.mips.cache_picache_linesize;
202                          break;                          break;
203                  }                  }
204    
# Line 236  int mips_cpu_new(struct cpu *cpu, struct Line 212  int mips_cpu_new(struct cpu *cpu, struct
212                          size_per_cache_line = sizeof(struct r3000_cache_line);                          size_per_cache_line = sizeof(struct r3000_cache_line);
213                          break;                          break;
214                  default:                  default:
215                          size_per_cache_line = sizeof(struct r4000_cache_line);                          size_per_cache_line = 32;       /*  TODO  */
216                  }                  }
217    
218                  cpu->cd.mips.cache_mask[i] = cpu->cd.mips.cache_size[i] - 1;                  cpu->cd.mips.cache_mask[i] = cpu->cd.mips.cache_size[i] - 1;
                 cpu->cd.mips.cache_miss_penalty[i] = 10;        /*  TODO ?  */  
219    
220                  cpu->cd.mips.cache[i] = malloc(cpu->cd.mips.cache_size[i]);                  CHECK_ALLOCATION(cpu->cd.mips.cache[i] =
221                  if (cpu->cd.mips.cache[i] == NULL) {                      malloc(cpu->cd.mips.cache_size[i]));
                         fprintf(stderr, "out of memory\n");  
                 }  
222    
223                  n_cache_lines = cpu->cd.mips.cache_size[i] /                  n_cache_lines = cpu->cd.mips.cache_size[i] /
224                      cpu->cd.mips.cache_linesize[i];                      cpu->cd.mips.cache_linesize[i];
225                  tags_size = n_cache_lines * size_per_cache_line;                  tags_size = n_cache_lines * size_per_cache_line;
226    
227                  cpu->cd.mips.cache_tags[i] = malloc(tags_size);                  CHECK_ALLOCATION(cpu->cd.mips.cache_tags[i] =
228                  if (cpu->cd.mips.cache_tags[i] == NULL) {                      malloc(tags_size));
                         fprintf(stderr, "out of memory\n");  
                 }  
229    
230                  /*  Initialize the cache tags:  */                  /*  Initialize the cache tags:  */
231                  switch (cpu->cd.mips.cpu_type.rev) {                  switch (cpu->cd.mips.cpu_type.rev) {
# Line 280  int mips_cpu_new(struct cpu *cpu, struct Line 251  int mips_cpu_new(struct cpu *cpu, struct
251           *  Secondary cache:           *  Secondary cache:
252           */           */
253          secondary_cache_size = 0;          secondary_cache_size = 0;
254          if (machine->cache_secondary)          if (cpu->cd.mips.cache_secondary)
255                  secondary_cache_size = 1 << machine->cache_secondary;                  secondary_cache_size = 1 << cpu->cd.mips.cache_secondary;
256          /*  TODO: linesize...  */          /*  TODO: linesize...  */
257    
258          if (cpu_id == 0) {          if (cpu_id == 0) {
# Line 302  int mips_cpu_new(struct cpu *cpu, struct Line 273  int mips_cpu_new(struct cpu *cpu, struct
273                  debug(")");                  debug(")");
274          }          }
275    
276            /*  Register the CPU's interrupts:  */
277            for (i=2; i<8; i++) {
278                    struct interrupt template;
279                    char name[50];
280                    snprintf(name, sizeof(name), "%s.%i", cpu->path, i);
281                    memset(&template, 0, sizeof(template));
282                    template.line = 1 << (STATUS_IM_SHIFT + i);
283                    template.name = name;
284                    template.extra = cpu;
285                    template.interrupt_assert = mips_cpu_interrupt_assert;
286                    template.interrupt_deassert = mips_cpu_interrupt_deassert;
287                    interrupt_handler_register(&template);
288    
289                    if (i == 7)
290                            INTERRUPT_CONNECT(name, cpu->cd.mips.irq_compare);
291            }
292    
293          /*  System coprocessor (0), and FPU (1):  */          /*  System coprocessor (0), and FPU (1):  */
294          cpu->cd.mips.coproc[0] = mips_coproc_new(cpu, 0);          cpu->cd.mips.coproc[0] = mips_coproc_new(cpu, 0);
295          cpu->cd.mips.coproc[1] = mips_coproc_new(cpu, 1);          cpu->cd.mips.coproc[1] = mips_coproc_new(cpu, 1);
# Line 323  int mips_cpu_new(struct cpu *cpu, struct Line 311  int mips_cpu_new(struct cpu *cpu, struct
311                          cpu->translate_v2p = translate_v2p_generic;                          cpu->translate_v2p = translate_v2p_generic;
312          }          }
313    
314            if (cpu->machine->prom_emulation) {
315                    /*
316                     *  Default behaviour of jumping to 0xbfc00000 should be
317                     *  a reboot, unless machine-specific initialization code
318                     *  overrides this.
319                     *
320                     *  Note: Specifically big-endian machines should override
321                     *  this, since the default MIPS CPU is little-endian!
322                     */
323                    store_32bit_word(cpu, 0xffffffff9fc00000ULL, 0x00c0de0d);
324            }
325    
326            /*  Add all register names to the settings:  */
327            CPU_SETTINGS_ADD_REGISTER64("pc", cpu->pc);
328            CPU_SETTINGS_ADD_REGISTER64("hi", cpu->cd.mips.hi);
329            CPU_SETTINGS_ADD_REGISTER64("lo", cpu->cd.mips.lo);
330            for (i=0; i<N_MIPS_GPRS; i++)
331                    CPU_SETTINGS_ADD_REGISTER64(regnames[i], cpu->cd.mips.gpr[i]);
332            /*  TODO: Write via special handler function!  */
333            for (i=0; i<N_MIPS_COPROC_REGS; i++)
334                    CPU_SETTINGS_ADD_REGISTER64(cop0_names[i],
335                        cpu->cd.mips.coproc[0]->reg[i]);
336    
337          return 1;          return 1;
338  }  }
339    
# Line 491  void mips_cpu_tlbdump(struct machine *m, Line 502  void mips_cpu_tlbdump(struct machine *m,
502          /*  Raw output:  */          /*  Raw output:  */
503          if (rawflag) {          if (rawflag) {
504                  for (i=0; i<m->ncpus; i++) {                  for (i=0; i<m->ncpus; i++) {
505                            struct mips_coproc *cop0 =
506                                m->cpus[i]->cd.mips.coproc[0];
507    
508                          if (x >= 0 && i != x)                          if (x >= 0 && i != x)
509                                  continue;                                  continue;
510    
# Line 498  void mips_cpu_tlbdump(struct machine *m, Line 512  void mips_cpu_tlbdump(struct machine *m,
512                          printf("cpu%i: (", i);                          printf("cpu%i: (", i);
513    
514                          if (m->cpus[i]->is_32bit)                          if (m->cpus[i]->is_32bit)
515                                  printf("index=0x%08x random=0x%08x", (int)m->                                  printf("index=0x%08x random=0x%08x",
516                                      cpus[i]->cd.mips.coproc[0]->reg[COP0_INDEX],                                      (int) cop0->reg[COP0_INDEX],
517                                      (int)m->cpus[i]->cd.mips.coproc[0]->reg                                      (int) cop0->reg[COP0_RANDOM]);
                                     [COP0_RANDOM]);  
518                          else                          else
519                                  printf("index=0x%016"PRIx64                                  printf("index=0x%016"PRIx64
520                                      " random=0x%016"PRIx64,                                      " random=0x%016"PRIx64,
521                                      (uint64_t)m->cpus[i]->cd.mips.coproc[0]->                                      (uint64_t) cop0->reg[COP0_INDEX],
522                                      reg[COP0_INDEX], (uint64_t)m->cpus[i]->                                      (uint64_t) cop0->reg[COP0_RANDOM]);
                                     cd.mips.coproc[0]->reg[COP0_RANDOM]);  
523    
524                          if (m->cpus[i]->cd.mips.cpu_type.isa_level >= 3)                          if (m->cpus[i]->cd.mips.cpu_type.isa_level >= 3)
525                                  printf(" wired=0x%"PRIx64, (uint64_t) m->cpus                                  printf(" wired=0x%"PRIx64,
526                                      [i]->cd.mips.coproc[0]->reg[COP0_WIRED]);                                      (uint64_t) cop0->reg[COP0_WIRED]);
527    
528                          printf(")\n");                          printf(")\n");
529    
# Line 519  void mips_cpu_tlbdump(struct machine *m, Line 531  void mips_cpu_tlbdump(struct machine *m,
531                              nr_of_tlb_entries; j++) {                              nr_of_tlb_entries; j++) {
532                                  if (m->cpus[i]->cd.mips.cpu_type.mmu_model ==                                  if (m->cpus[i]->cd.mips.cpu_type.mmu_model ==
533                                      MMU3K)                                      MMU3K)
534                                          printf("%3i: hi=0x%08x lo=0x%08x\n", j,                                          printf("%3i: hi=0x%08"PRIx32" lo=0x%08"
535                                              (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].hi,                                              PRIx32"\n", j,
536                                              (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo0);                                              (uint32_t) cop0->tlbs[j].hi,
537                                                (uint32_t) cop0->tlbs[j].lo0);
538                                  else if (m->cpus[i]->is_32bit)                                  else if (m->cpus[i]->is_32bit)
539                                          printf("%3i: hi=0x%08x mask=0x%08x "                                          printf("%3i: hi=0x%08"PRIx32" mask=0x"
540                                              "lo0=0x%08x lo1=0x%08x\n", j,                                              "%08"PRIx32" lo0=0x%08"PRIx32
541                                              (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].hi,                                              " lo1=0x%08"PRIx32"\n", j,
542                                              (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].mask,                                              (uint32_t) cop0->tlbs[j].hi,
543                                              (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo0,                                              (uint32_t) cop0->tlbs[j].mask,
544                                              (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo1);                                              (uint32_t) cop0->tlbs[j].lo0,
545                                                (uint32_t) cop0->tlbs[j].lo1);
546                                  else                                  else
547                                          printf("%3i: hi=0x%016"PRIx64" mask=0x%016"PRIx64" "                                          printf("%3i: hi=0x%016"PRIx64" mask="
548                                              "lo0=0x%016"PRIx64" lo1=0x%016"PRIx64"\n", j,                                              "0x%016"PRIx64" lo0=0x%016"PRIx64
549                                              (uint64_t)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].hi,                                              " lo1=0x%016"PRIx64"\n", j,
550                                              (uint64_t)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].mask,                                              (uint64_t) cop0->tlbs[j].hi,
551                                              (uint64_t)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo0,                                              (uint64_t) cop0->tlbs[j].mask,
552                                              (uint64_t)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo1);                                              (uint64_t) cop0->tlbs[j].lo0,
553                                                (uint64_t) cop0->tlbs[j].lo1);
554                          }                          }
555                  }                  }
556    
557                  return;                  return;
558          }          }
559    
560          /*  Nicely formatted output:  */          /*  Nicely formatted output:  */
561          for (i=0; i<m->ncpus; i++) {          for (i=0; i<m->ncpus; i++) {
562                  int pageshift = 12;                  int pageshift = 12;
563                    struct mips_coproc *cop0 = m->cpus[i]->cd.mips.coproc[0];
564    
565                  if (x >= 0 && i != x)                  if (x >= 0 && i != x)
566                          continue;                          continue;
# Line 556  void mips_cpu_tlbdump(struct machine *m, Line 573  void mips_cpu_tlbdump(struct machine *m,
573                  switch (m->cpus[i]->cd.mips.cpu_type.isa_level) {                  switch (m->cpus[i]->cd.mips.cpu_type.isa_level) {
574                  case 1:                  case 1:
575                  case 2: printf("index=0x%x random=0x%x",                  case 2: printf("index=0x%x random=0x%x",
576                              (int) ((m->cpus[i]->cd.mips.coproc[0]->                              (int) ((cop0->reg[COP0_INDEX] & R2K3K_INDEX_MASK)
                             reg[COP0_INDEX] & R2K3K_INDEX_MASK)  
577                              >> R2K3K_INDEX_SHIFT),                              >> R2K3K_INDEX_SHIFT),
578                              (int) ((m->cpus[i]->cd.mips.coproc[0]->                              (int) ((cop0->reg[COP0_RANDOM] & R2K3K_RANDOM_MASK)
                             reg[COP0_RANDOM] & R2K3K_RANDOM_MASK)  
579                              >> R2K3K_RANDOM_SHIFT));                              >> R2K3K_RANDOM_SHIFT));
580                          break;                          break;
581                  default:printf("index=0x%x random=0x%x",                  default:printf("index=0x%x random=0x%x",
582                              (int) (m->cpus[i]->cd.mips.coproc[0]->                              (int) (cop0->reg[COP0_INDEX] & INDEX_MASK),
583                              reg[COP0_INDEX] & INDEX_MASK),                              (int) (cop0->reg[COP0_RANDOM] & RANDOM_MASK));
584                              (int) (m->cpus[i]->cd.mips.coproc[0]->                          printf(" wired=0x%"PRIx64,
585                              reg[COP0_RANDOM] & RANDOM_MASK));                              (uint64_t) cop0->reg[COP0_WIRED]);
                         printf(" wired=0x%"PRIx64, (uint64_t)  
                             m->cpus[i]->cd.mips.coproc[0]->reg[COP0_WIRED]);  
586                  }                  }
587    
588                  printf(")\n");                  printf(")\n");
589    
590                  for (j=0; j<m->cpus[i]->cd.mips.cpu_type.                  for (j=0; j<m->cpus[i]->cd.mips.cpu_type.
591                      nr_of_tlb_entries; j++) {                      nr_of_tlb_entries; j++) {
592                          uint64_t hi,lo0,lo1,mask;                          uint64_t hi = cop0->tlbs[j].hi;
593                          hi = m->cpus[i]->cd.mips.coproc[0]->tlbs[j].hi;                          uint64_t lo0 = cop0->tlbs[j].lo0;
594                          lo0 = m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo0;                          uint64_t lo1 = cop0->tlbs[j].lo1;
595                          lo1 = m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo1;                          uint64_t mask = cop0->tlbs[j].mask;
596                          mask = m->cpus[i]->cd.mips.coproc[0]->tlbs[j].mask;                          uint64_t psize;
597    
598                            mask |= (1 << (pageshift+1)) - 1;
599                            /*  here mask = e.g. 0x1fff for 4KB pages  */
600    
601                          printf("%3i: ", j);                          printf("%3i: ", j);
602    
603                          switch (m->cpus[i]->cd.mips.cpu_type.mmu_model) {                          switch (m->cpus[i]->cd.mips.cpu_type.mmu_model) {
604                          case MMU3K:                          case MMU3K:
605                                  if (!(lo0 & R2K3K_ENTRYLO_V)) {                                  if (!(lo0 & R2K3K_ENTRYLO_V)) {
# Line 606  void mips_cpu_tlbdump(struct machine *m, Line 623  void mips_cpu_tlbdump(struct machine *m,
623                                  printf("\n");                                  printf("\n");
624                                  break;                                  break;
625                          default:switch (m->cpus[i]->cd.mips.cpu_type.mmu_model){                          default:switch (m->cpus[i]->cd.mips.cpu_type.mmu_model){
                                 case MMU10K:  
                                         printf("vaddr=0x%1x..%011"PRIx64" ",  
                                             (int) (hi >> 60), (uint64_t)  
                                             (hi&ENTRYHI_VPN2_MASK_R10K));  
                                         break;  
626                                  case MMU32:                                  case MMU32:
627                                          printf("vaddr=0x%08"PRIx32" ",                                          printf("vaddr=0x%08"PRIx32" ",
628                                              (uint32_t)(hi&ENTRYHI_VPN2_MASK));                                              (uint32_t) (hi & ~mask));
629                                          break;                                          break;
630                                  default:/*  R4000 etc.  */                                  default:/*  R4x00, R1x000, MIPS64, etc.  */
631                                          printf("vaddr=0x%1x..%010"PRIx64" ",                                          printf("vaddr=%016"PRIx64" ",
632                                              (int) (hi >> 60),                                              (uint64_t) (hi & ~mask));
                                             (uint64_t) (hi&ENTRYHI_VPN2_MASK));  
633                                  }                                  }
634                                  if (hi & TLB_G)                                  if (hi & TLB_G)
635                                          printf("(global): ");                                          printf("(global): ");
# Line 630  void mips_cpu_tlbdump(struct machine *m, Line 641  void mips_cpu_tlbdump(struct machine *m,
641    
642                                  if (!(lo0 & ENTRYLO_V))                                  if (!(lo0 & ENTRYLO_V))
643                                          printf(" p0=(invalid)   ");                                          printf(" p0=(invalid)   ");
644                                  else                                  else {
645                                          printf(" p0=0x%09"PRIx64" ", (uint64_t)                                          uint64_t paddr = lo0 & ENTRYLO_PFN_MASK;
646                                              (((lo0&ENTRYLO_PFN_MASK) >>                                          paddr >>= ENTRYLO_PFN_SHIFT;
647                                              ENTRYLO_PFN_SHIFT) << pageshift));                                          paddr <<= pageshift;
648                                            paddr &= ~(mask >> 1);
649                                            printf(" p0=0x%09"PRIx64" ",
650                                                (uint64_t) paddr);
651                                    }
652                                  printf(lo0 & ENTRYLO_D? "D" : " ");                                  printf(lo0 & ENTRYLO_D? "D" : " ");
653    
654                                  if (!(lo1 & ENTRYLO_V))                                  if (!(lo1 & ENTRYLO_V))
655                                          printf(" p1=(invalid)   ");                                          printf(" p1=(invalid)   ");
656                                  else                                  else {
657                                          printf(" p1=0x%09"PRIx64" ", (uint64_t)                                          uint64_t paddr = lo1 & ENTRYLO_PFN_MASK;
658                                              (((lo1&ENTRYLO_PFN_MASK) >>                                          paddr >>= ENTRYLO_PFN_SHIFT;
659                                              ENTRYLO_PFN_SHIFT) << pageshift));                                          paddr <<= pageshift;
660                                  printf(lo1 & ENTRYLO_D? "D" : " ");                                          paddr &= ~(mask >> 1);
661                                  mask |= (1 << (pageshift+1)) - 1;                                          printf(" p1=0x%09"PRIx64" ",
662                                  switch (mask) {                                              (uint64_t) paddr);
                                 case 0x7ff:     printf(" (1KB)"); break;  
                                 case 0x1fff:    printf(" (4KB)"); break;  
                                 case 0x7fff:    printf(" (16KB)"); break;  
                                 case 0x1ffff:   printf(" (64KB)"); break;  
                                 case 0x7ffff:   printf(" (256KB)"); break;  
                                 case 0x1fffff:  printf(" (1MB)"); break;  
                                 case 0x7fffff:  printf(" (4MB)"); break;  
                                 case 0x1ffffff: printf(" (16MB)"); break;  
                                 case 0x7ffffff: printf(" (64MB)"); break;  
                                 default:printf(" (mask=%08x?)", (int)mask);  
663                                  }                                  }
664                                  printf("\n");                                  printf(lo1 & ENTRYLO_D? "D" : " ");
                         }  
                 }  
         }  
 }  
   
   
 /*  
  *  mips_cpu_register_match():  
  */  
 void mips_cpu_register_match(struct machine *m, char *name,  
         int writeflag, uint64_t *valuep, int *match_register)  
 {  
         int cpunr = 0;  
   
         /*  CPU number:  */  
665    
666          /*  TODO  */                                  /*  convert e.g. 0x1fff to 4096  */
667                                    psize = (mask + 1) >> 1;
668    
669          /*  Register name:  */                                  if (psize >= 1024 && psize <= 256*1024)
670          if (strcasecmp(name, "pc") == 0) {                                          printf(" (%iKB)", (int) (psize >> 10));
671                  if (writeflag) {                                  else if (psize >= 1024*1024 && psize <=
672                          m->cpus[cpunr]->pc = *valuep;                                      64*1024*1024)
673                          if (m->cpus[cpunr]->delay_slot) {                                          printf(" (%iMB)", (int) (psize >> 20));
                                 printf("NOTE: Clearing the delay slot"  
                                     " flag! (It was set before.)\n");  
                                 m->cpus[cpunr]->delay_slot = 0;  
                         }  
                         if (m->cpus[cpunr]->cd.mips.nullify_next) {  
                                 printf("NOTE: Clearing the nullify-ne"  
                                     "xt flag! (It was set before.)\n");  
                                 m->cpus[cpunr]->cd.mips.nullify_next = 0;  
                         }  
                 } else  
                         *valuep = m->cpus[cpunr]->pc;  
                 *match_register = 1;  
         } else if (strcasecmp(name, "hi") == 0) {  
                 if (writeflag)  
                         m->cpus[cpunr]->cd.mips.hi = *valuep;  
                 else  
                         *valuep = m->cpus[cpunr]->cd.mips.hi;  
                 *match_register = 1;  
         } else if (strcasecmp(name, "lo") == 0) {  
                 if (writeflag)  
                         m->cpus[cpunr]->cd.mips.lo = *valuep;  
                 else  
                         *valuep = m->cpus[cpunr]->cd.mips.lo;  
                 *match_register = 1;  
         } else if (name[0] == 'r' && isdigit((int)name[1])) {  
                 int nr = atoi(name + 1);  
                 if (nr >= 0 && nr < N_MIPS_GPRS) {  
                         if (writeflag) {  
                                 if (nr != 0)  
                                         m->cpus[cpunr]->cd.mips.gpr[nr] = *valuep;  
674                                  else                                  else
675                                          printf("WARNING: Attempt to modify r0.\n");                                          printf(" (?)");
                         } else  
                                 *valuep = m->cpus[cpunr]->cd.mips.gpr[nr];  
                         *match_register = 1;  
                 }  
         } else {  
                 /*  Check for a symbolic name such as "t6" or "at":  */  
                 int nr;  
                 for (nr=0; nr<N_MIPS_GPRS; nr++)  
                         if (strcmp(name, regnames[nr]) == 0) {  
                                 if (writeflag) {  
                                         if (nr != 0)  
                                                 m->cpus[cpunr]->cd.mips.gpr[nr] = *valuep;  
                                         else  
                                                 printf("WARNING: Attempt to modify r0.\n");  
                                 } else  
                                         *valuep = m->cpus[cpunr]->cd.mips.gpr[nr];  
                                 *match_register = 1;  
                         }  
         }  
676    
677          if (!(*match_register)) {                                  printf("\n");
                 /*  Check for a symbolic coproc0 name:  */  
                 int nr;  
                 for (nr=0; nr<32; nr++)  
                         if (strcmp(name, cop0_names[nr]) == 0) {  
                                 if (writeflag) {  
                                         coproc_register_write(m->cpus[cpunr],  
                                             m->cpus[cpunr]->cd.mips.coproc[0], nr,  
                                             valuep, 1, 0);  
                                 } else {  
                                         /*  TODO: Use coproc_register_read instead?  */  
                                         *valuep = m->cpus[cpunr]->cd.mips.coproc[0]->reg[nr];  
                                 }  
                                 *match_register = 1;  
678                          }                          }
679          }                  }
   
         /*  TODO: Coprocessor 1,2,3 registers.  */  
   
         /*  Only return lowest 32 bits when doing 32-bit emulation:  */  
         if (!writeflag && m->cpus[cpunr]->is_32bit)  
                 *valuep = (uint32_t) (*valuep);  
 }  
   
   
 /*  
  *  cpu_flags():  
  *  
  *  Returns a pointer to a string containing "(d)" "(j)" "(dj)" or "",  
  *  depending on the cpu's current delay_slot and last_was_jumptoself  
  *  flags.  
  */  
 static const char *cpu_flags(struct cpu *cpu)  
 {  
         if (cpu->delay_slot) {  
                 if (cpu->cd.mips.last_was_jumptoself)  
                         return " (dj)";  
                 else  
                         return " (d)";  
         } else {  
                 if (cpu->cd.mips.last_was_jumptoself)  
                         return " (j)";  
                 else  
                         return "";  
680          }          }
681  }  }
682    
# Line 797  static const char *cpu_flags(struct cpu Line 698  static const char *cpu_flags(struct cpu
698  int mips_cpu_disassemble_instr(struct cpu *cpu, unsigned char *originstr,  int mips_cpu_disassemble_instr(struct cpu *cpu, unsigned char *originstr,
699          int running, uint64_t dumpaddr)          int running, uint64_t dumpaddr)
700  {  {
701          int hi6, special6, regimm5;          int hi6, special6, regimm5, sub;
702          int rt, rd, rs, sa, imm, copz, cache_op, which_cache, showtag;          int rt, rd, rs, sa, imm, copz, cache_op, which_cache, showtag;
703          uint64_t addr, offset;          uint64_t addr, offset;
704          uint32_t instrword;          uint32_t instrword;
# Line 839  int mips_cpu_disassemble_instr(struct cp Line 740  int mips_cpu_disassemble_instr(struct cp
740          debug(": %02x%02x%02x%02x",          debug(": %02x%02x%02x%02x",
741              instr[3], instr[2], instr[1], instr[0]);              instr[3], instr[2], instr[1], instr[0]);
742    
743          if (running)          if (running && cpu->delay_slot)
744                  debug("%s", cpu_flags(cpu));                  debug(" (d)");
745    
746          debug("\t");          debug("\t");
747    
# Line 848  int mips_cpu_disassemble_instr(struct cp Line 749  int mips_cpu_disassemble_instr(struct cp
749           *  Decode the instruction:           *  Decode the instruction:
750           */           */
751    
         if (cpu->cd.mips.nullify_next && running) {  
                 debug("(nullified)");  
                 goto disasm_ret;  
         }  
   
752          hi6 = (instr[3] >> 2) & 0x3f;          hi6 = (instr[3] >> 2) & 0x3f;
753    
754          switch (hi6) {          switch (hi6) {
# Line 868  int mips_cpu_disassemble_instr(struct cp Line 764  int mips_cpu_disassemble_instr(struct cp
764                  case SPECIAL_DSLL32:                  case SPECIAL_DSLL32:
765                  case SPECIAL_DSRL32:                  case SPECIAL_DSRL32:
766                  case SPECIAL_DSRA32:                  case SPECIAL_DSRA32:
767                            sub = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
768                          rt = instr[2] & 31;                          rt = instr[2] & 31;
769                          rd = (instr[1] >> 3) & 31;                          rd = (instr[1] >> 3) & 31;
770                          sa = ((instr[1] & 7) << 2) + ((instr[0] >> 6) & 3);                          sa = ((instr[1] & 7) << 2) + ((instr[0] >> 6) & 3);
# Line 881  int mips_cpu_disassemble_instr(struct cp Line 778  int mips_cpu_disassemble_instr(struct cp
778                                          debug("ehb");                                          debug("ehb");
779                                  else                                  else
780                                          debug("nop (weird, sa=%i)", sa);                                          debug("nop (weird, sa=%i)", sa);
781                                  goto disasm_ret;                                  break;
782                          } else                          }
783    
784                            switch (sub) {
785                            case 0x00:
786                                    debug("%s\t%s,", special_names[special6],
787                                        regnames[rd]);
788                                    debug("%s,%i", regnames[rt], sa);
789                                    break;
790                            case 0x01:
791                                  debug("%s\t%s,",                                  debug("%s\t%s,",
792                                      special_names[special6],                                      special_rot_names[special6],
793                                      regname(cpu->machine, rd));                                      regnames[rd]);
794                                  debug("%s,%i", regname(cpu->machine, rt), sa);                                  debug("%s,%i", regnames[rt], sa);
795                                    break;
796                            default:debug("UNIMPLEMENTED special, sub=0x%02x\n",
797                                        sub);
798                            }
799                          break;                          break;
800                  case SPECIAL_DSRLV:                  case SPECIAL_DSRLV:
801                  case SPECIAL_DSRAV:                  case SPECIAL_DSRAV:
# Line 897  int mips_cpu_disassemble_instr(struct cp Line 806  int mips_cpu_disassemble_instr(struct cp
806                          rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);                          rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
807                          rt = instr[2] & 31;                          rt = instr[2] & 31;
808                          rd = (instr[1] >> 3) & 31;                          rd = (instr[1] >> 3) & 31;
809                          debug("%s\t%s",                          sub = ((instr[1] & 7) << 2) + ((instr[0] >> 6) & 3);
810                              special_names[special6], regname(cpu->machine, rd));  
811                          debug(",%s", regname(cpu->machine, rt));                          switch (sub) {
812                          debug(",%s", regname(cpu->machine, rs));                          case 0x00:
813                                    debug("%s\t%s", special_names[special6],
814                                        regnames[rd]);
815                                    debug(",%s", regnames[rt]);
816                                    debug(",%s", regnames[rs]);
817                                    break;
818                            case 0x01:
819                                    debug("%s\t%s", special_rot_names[special6],
820                                        regnames[rd]);
821                                    debug(",%s", regnames[rt]);
822                                    debug(",%s", regnames[rs]);
823                                    break;
824                            default:debug("UNIMPLEMENTED special, sub=0x%02x\n",
825                                        sub);
826                            }
827                          break;                          break;
828                  case SPECIAL_JR:                  case SPECIAL_JR:
829                          rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);                          rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
830                          symbol = get_symbol_name(&cpu->machine->symbol_context,                          symbol = get_symbol_name(&cpu->machine->symbol_context,
831                              cpu->cd.mips.gpr[rs], &offset);                              cpu->cd.mips.gpr[rs], &offset);
832                          debug("jr\t%s", regname(cpu->machine, rs));                          /*  .hb = hazard barrier hint on MIPS32/64 rev 2  */
833                            debug("jr%s\t%s",
834                                (instr[1] & 0x04) ? ".hb" : "",
835                                regnames[rs]);
836                          if (running && symbol != NULL)                          if (running && symbol != NULL)
837                                  debug("\t<%s>", symbol);                                  debug("\t<%s>", symbol);
838                          break;                          break;
# Line 915  int mips_cpu_disassemble_instr(struct cp Line 841  int mips_cpu_disassemble_instr(struct cp
841                          rd = (instr[1] >> 3) & 31;                          rd = (instr[1] >> 3) & 31;
842                          symbol = get_symbol_name(&cpu->machine->symbol_context,                          symbol = get_symbol_name(&cpu->machine->symbol_context,
843                              cpu->cd.mips.gpr[rs], &offset);                              cpu->cd.mips.gpr[rs], &offset);
844                          debug("jalr\t%s", regname(cpu->machine, rd));                          /*  .hb = hazard barrier hint on MIPS32/64 rev 2  */
845                          debug(",%s", regname(cpu->machine, rs));                          debug("jalr%s\t%s",
846                                (instr[1] & 0x04) ? ".hb" : "",
847                                regnames[rd]);
848                            debug(",%s", regnames[rs]);
849                          if (running && symbol != NULL)                          if (running && symbol != NULL)
850                                  debug("\t<%s>", symbol);                                  debug("\t<%s>", symbol);
851                          break;                          break;
852                  case SPECIAL_MFHI:                  case SPECIAL_MFHI:
853                  case SPECIAL_MFLO:                  case SPECIAL_MFLO:
854                          rd = (instr[1] >> 3) & 31;                          rd = (instr[1] >> 3) & 31;
855                          debug("%s\t%s", special_names[special6],                          debug("%s\t%s", special_names[special6], regnames[rd]);
                             regname(cpu->machine, rd));  
856                          break;                          break;
857                  case SPECIAL_MTLO:                  case SPECIAL_MTLO:
858                  case SPECIAL_MTHI:                  case SPECIAL_MTHI:
859                          rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);                          rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
860                          debug("%s\t%s", special_names[special6],                          debug("%s\t%s", special_names[special6], regnames[rs]);
                             regname(cpu->machine, rs));  
861                          break;                          break;
862                  case SPECIAL_ADD:                  case SPECIAL_ADD:
863                  case SPECIAL_ADDU:                  case SPECIAL_ADDU:
# Line 955  int mips_cpu_disassemble_instr(struct cp Line 882  int mips_cpu_disassemble_instr(struct cp
882                              special6 == SPECIAL_SUBU) && rt == 0) {                              special6 == SPECIAL_SUBU) && rt == 0) {
883                                  /*  Special case 1: addu/subu with                                  /*  Special case 1: addu/subu with
884                                      rt = the zero register ==> move  */                                      rt = the zero register ==> move  */
885                                  debug("move\t%s", regname(cpu->machine, rd));                                  debug("move\t%s", regnames[rd]);
886                                  debug(",%s", regname(cpu->machine, rs));                                  debug(",%s", regnames[rs]);
887                          } else if (special6 == SPECIAL_ADDU && cpu->is_32bit                          } else if (special6 == SPECIAL_ADDU && cpu->is_32bit
888                              && rs == 0) {                              && rs == 0) {
889                                  /*  Special case 2: addu with                                  /*  Special case 2: addu with
890                                      rs = the zero register ==> move  */                                      rs = the zero register ==> move  */
891                                  debug("move\t%s", regname(cpu->machine, rd));                                  debug("move\t%s", regnames[rd]);
892                                  debug(",%s", regname(cpu->machine, rt));                                  debug(",%s", regnames[rt]);
893                          } else {                          } else {
894                                  debug("%s\t%s", special_names[special6],                                  debug("%s\t%s", special_names[special6],
895                                      regname(cpu->machine, rd));                                      regnames[rd]);
896                                  debug(",%s", regname(cpu->machine, rs));                                  debug(",%s", regnames[rs]);
897                                  debug(",%s", regname(cpu->machine, rt));                                  debug(",%s", regnames[rt]);
898                          }                          }
899                          break;                          break;
900                  case SPECIAL_MULT:                  case SPECIAL_MULT:
# Line 992  int mips_cpu_disassemble_instr(struct cp Line 919  int mips_cpu_disassemble_instr(struct cp
919                                  if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {                                  if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
920                                          if (special6 == SPECIAL_MULT ||                                          if (special6 == SPECIAL_MULT ||
921                                              special6 == SPECIAL_MULTU)                                              special6 == SPECIAL_MULTU)
922                                                  debug("%s,",                                                  debug("%s,", regnames[rd]);
                                                     regname(cpu->machine, rd));  
923                                          else                                          else
924                                                  debug("WEIRD_R5900_RD,");                                                  debug("WEIRD_R5900_RD,");
925                                  } else {                                  } else {
926                                          debug("WEIRD_RD_NONZERO,");                                          debug("WEIRD_RD_NONZERO,");
927                                  }                                  }
928                          }                          }
929                          debug("%s", regname(cpu->machine, rs));                          debug("%s", regnames[rs]);
930                          debug(",%s", regname(cpu->machine, rt));                          debug(",%s", regnames[rt]);
931                          break;                          break;
932                  case SPECIAL_SYNC:                  case SPECIAL_SYNC:
933                          imm = ((instr[1] & 7) << 2) + (instr[0] >> 6);                          imm = ((instr[1] & 7) << 2) + (instr[0] >> 6);
# Line 1026  int mips_cpu_disassemble_instr(struct cp Line 952  int mips_cpu_disassemble_instr(struct cp
952                  case SPECIAL_MFSA:                  case SPECIAL_MFSA:
953                          if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {                          if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
954                                  rd = (instr[1] >> 3) & 31;                                  rd = (instr[1] >> 3) & 31;
955                                  debug("mfsa\t%s", regname(cpu->machine, rd));                                  debug("mfsa\t%s", regnames[rd]);
956                          } else {                          } else {
957                                  debug("unimplemented special 0x28");                                  debug("unimplemented special 0x28");
958                          }                          }
# Line 1035  int mips_cpu_disassemble_instr(struct cp Line 961  int mips_cpu_disassemble_instr(struct cp
961                          if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {                          if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
962                                  rs = ((instr[3] & 3) << 3) +                                  rs = ((instr[3] & 3) << 3) +
963                                      ((instr[2] >> 5) & 7);                                      ((instr[2] >> 5) & 7);
964                                  debug("mtsa\t%s", regname(cpu->machine, rs));                                  debug("mtsa\t%s", regnames[rs]);
965                          } else {                          } else {
966                                  debug("unimplemented special 0x29");                                  debug("unimplemented special 0x29");
967                          }                          }
# Line 1069  int mips_cpu_disassemble_instr(struct cp Line 995  int mips_cpu_disassemble_instr(struct cp
995                          case HI6_BEQL:                          case HI6_BEQL:
996                          case HI6_BNE:                          case HI6_BNE:
997                          case HI6_BNEL:                          case HI6_BNEL:
998                                  debug("%s,", regname(cpu->machine, rt));                                  debug("%s,", regnames[rt]);
999                          }                          }
1000                          debug("%s,", regname(cpu->machine, rs));                          debug("%s,", regnames[rs]);
1001                  }                  }
1002    
1003                  if (cpu->is_32bit)                  if (cpu->is_32bit)
# Line 1098  int mips_cpu_disassemble_instr(struct cp Line 1024  int mips_cpu_disassemble_instr(struct cp
1024                  imm = (instr[1] << 8) + instr[0];                  imm = (instr[1] << 8) + instr[0];
1025                  if (imm >= 32768)                  if (imm >= 32768)
1026                          imm -= 65536;                          imm -= 65536;
1027                  debug("%s\t%s,", hi6_names[hi6], regname(cpu->machine, rt));                  debug("%s\t%s,", hi6_names[hi6], regnames[rt]);
1028                  debug("%s,", regname(cpu->machine, rs));                  debug("%s,", regnames[rs]);
1029                  if (hi6 == HI6_ANDI || hi6 == HI6_ORI || hi6 == HI6_XORI)                  if (hi6 == HI6_ANDI || hi6 == HI6_ORI || hi6 == HI6_XORI)
1030                          debug("0x%04x", imm & 0xffff);                          debug("0x%04x", imm & 0xffff);
1031                  else                  else
# Line 1108  int mips_cpu_disassemble_instr(struct cp Line 1034  int mips_cpu_disassemble_instr(struct cp
1034          case HI6_LUI:          case HI6_LUI:
1035                  rt = instr[2] & 31;                  rt = instr[2] & 31;
1036                  imm = (instr[1] << 8) + instr[0];                  imm = (instr[1] << 8) + instr[0];
1037                  debug("lui\t%s,0x%x", regname(cpu->machine, rt), imm);                  debug("lui\t%s,0x%x", regnames[rt], imm);
1038                  break;                  break;
1039          case HI6_LB:          case HI6_LB:
1040          case HI6_LBU:          case HI6_LBU:
# Line 1152  int mips_cpu_disassemble_instr(struct cp Line 1078  int mips_cpu_disassemble_instr(struct cp
1078                  }                  }
1079                  if (hi6 == HI6_SQ_SPECIAL3 &&                  if (hi6 == HI6_SQ_SPECIAL3 &&
1080                      cpu->cd.mips.cpu_type.rev != MIPS_R5900) {                      cpu->cd.mips.cpu_type.rev != MIPS_R5900) {
1081                            int msbd, lsb, sub10;
1082                          special6 = instr[0] & 0x3f;                          special6 = instr[0] & 0x3f;
                         debug("%s", special3_names[special6]);  
1083                          rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);                          rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
1084                          rt = instr[2] & 31;                          rt = instr[2] & 31;
1085                          rd = (instr[1] >> 3) & 31;                          rd = msbd = (instr[1] >> 3) & 31;
1086                            lsb = ((instr[1] & 7) << 2) | (instr[0] >> 6);
1087                            sub10 = (rs << 5) | lsb;
1088    
1089                          switch (special6) {                          switch (special6) {
1090    
1091                            case SPECIAL3_EXT:
1092                            case SPECIAL3_DEXT:
1093                            case SPECIAL3_DEXTM:
1094                            case SPECIAL3_DEXTU:
1095                                    debug("%s", special3_names[special6]);
1096                                    if (special6 == SPECIAL3_DEXTM)
1097                                            msbd += 32;
1098                                    if (special6 == SPECIAL3_DEXTU)
1099                                            lsb += 32;
1100                                    debug("\t%s", regnames[rt]);
1101                                    debug(",%s", regnames[rs]);
1102                                    debug(",%i,%i", lsb, msbd + 1);
1103                                    break;
1104    
1105                            case SPECIAL3_INS:
1106                            case SPECIAL3_DINS:
1107                            case SPECIAL3_DINSM:
1108                            case SPECIAL3_DINSU:
1109                                    debug("%s", special3_names[special6]);
1110                                    if (special6 == SPECIAL3_DINSM)
1111                                            msbd += 32;
1112                                    if (special6 == SPECIAL3_DINSU) {
1113                                            lsb += 32;
1114                                            msbd += 32;
1115                                    }
1116                                    msbd -= lsb;
1117                                    debug("\t%s", regnames[rt]);
1118                                    debug(",%s", regnames[rs]);
1119                                    debug(",%i,%i", lsb, msbd + 1);
1120                                    break;
1121    
1122                            case SPECIAL3_BSHFL:
1123                                    switch (sub10) {
1124                                    case BSHFL_WSBH:
1125                                    case BSHFL_SEB:
1126                                    case BSHFL_SEH:
1127                                            switch (sub10) {
1128                                            case BSHFL_WSBH: debug("wsbh"); break;
1129                                            case BSHFL_SEB:  debug("seb"); break;
1130                                            case BSHFL_SEH:  debug("seh"); break;
1131                                            }
1132                                            debug("\t%s", regnames[rd]);
1133                                            debug(",%s", regnames[rt]);
1134                                            break;
1135                                    default:debug("%s", special3_names[special6]);
1136                                            debug("\t(UNIMPLEMENTED)");
1137                                    }
1138                                    break;
1139    
1140                            case SPECIAL3_DBSHFL:
1141                                    switch (sub10) {
1142                                    case BSHFL_DSBH:
1143                                    case BSHFL_DSHD:
1144                                            switch (sub10) {
1145                                            case BSHFL_DSBH: debug("dsbh"); break;
1146                                            case BSHFL_DSHD: debug("dshd"); break;
1147                                            }
1148                                            debug("\t%s", regnames[rd]);
1149                                            debug(",%s", regnames[rt]);
1150                                            break;
1151                                    default:debug("%s", special3_names[special6]);
1152                                            debug("\t(UNIMPLEMENTED)");
1153                                    }
1154                                    break;
1155    
1156                          case SPECIAL3_RDHWR:                          case SPECIAL3_RDHWR:
1157                                  debug("\t%s", regname(cpu->machine, rt));                                  debug("%s", special3_names[special6]);
1158                                    debug("\t%s", regnames[rt]);
1159                                  debug(",hwr%i", rd);                                  debug(",hwr%i", rd);
1160                                  break;                                  break;
1161    
1162                          default:                          default:debug("%s", special3_names[special6]);
1163                                  debug("\t(UNIMPLEMENTED)");                                  debug("\t(UNIMPLEMENTED)");
1164                          }                          }
1165                          break;                          break;
# Line 1183  int mips_cpu_disassemble_instr(struct cp Line 1177  int mips_cpu_disassemble_instr(struct cp
1177                  /*  TODO: Which ISAs? IV? V? 32? 64?  */                  /*  TODO: Which ISAs? IV? V? 32? 64?  */
1178                  if (cpu->cd.mips.cpu_type.isa_level >= 4 && hi6 == HI6_LWC3) {                  if (cpu->cd.mips.cpu_type.isa_level >= 4 && hi6 == HI6_LWC3) {
1179                          debug("pref\t0x%x,%i(%s)",                          debug("pref\t0x%x,%i(%s)",
1180                              rt, imm, regname(cpu->machine, rs));                              rt, imm, regnames[rs]);
1181    
1182                          if (running) {                          if (running) {
1183                                  debug("\t[0x%016"PRIx64" = %s]",                                  debug("\t[0x%016"PRIx64" = %s]",
# Line 1203  int mips_cpu_disassemble_instr(struct cp Line 1197  int mips_cpu_disassemble_instr(struct cp
1197                      hi6 == HI6_LDC1 || hi6 == HI6_LDC2)                      hi6 == HI6_LDC1 || hi6 == HI6_LDC2)
1198                          debug("r%i", rt);                          debug("r%i", rt);
1199                  else                  else
1200                          debug("%s", regname(cpu->machine, rt));                          debug("%s", regnames[rt]);
1201    
1202                  debug(",%i(%s)", imm, regname(cpu->machine, rs));                  debug(",%i(%s)", imm, regnames[rs]);
1203    
1204                  if (running) {                  if (running) {
1205                          debug("\t[");                          debug("\t[");
# Line 1265  int mips_cpu_disassemble_instr(struct cp Line 1259  int mips_cpu_disassemble_instr(struct cp
1259                  cache_op    = copz >> 2;                  cache_op    = copz >> 2;
1260                  which_cache = copz & 3;                  which_cache = copz & 3;
1261                  showtag = 0;                  showtag = 0;
1262                  debug("cache\t0x%02x,0x%04x(%s)", copz, imm,                  debug("cache\t0x%02x,0x%04x(%s)", copz, imm, regnames[rt]);
                     regname(cpu->machine, rt));  
1263                  if (which_cache==0)     debug("  [ primary I-cache");                  if (which_cache==0)     debug("  [ primary I-cache");
1264                  if (which_cache==1)     debug("  [ primary D-cache");                  if (which_cache==1)     debug("  [ primary D-cache");
1265                  if (which_cache==2)     debug("  [ secondary I-cache");                  if (which_cache==2)     debug("  [ secondary I-cache");
# Line 1277  int mips_cpu_disassemble_instr(struct cp Line 1270  int mips_cpu_disassemble_instr(struct cp
1270                  if (cache_op==2)        debug("index store tag"), showtag=1;                  if (cache_op==2)        debug("index store tag"), showtag=1;
1271                  if (cache_op==3)        debug("create dirty exclusive");                  if (cache_op==3)        debug("create dirty exclusive");
1272                  if (cache_op==4)        debug("hit invalidate");                  if (cache_op==4)        debug("hit invalidate");
1273                  if (cache_op==5)        debug("fill OR hit writeback invalidate");                  if (cache_op==5)     debug("fill OR hit writeback invalidate");
1274                  if (cache_op==6)        debug("hit writeback");                  if (cache_op==6)        debug("hit writeback");
1275                  if (cache_op==7)        debug("hit set virtual");                  if (cache_op==7)        debug("hit set virtual");
1276                  if (running)                  if (running)
# Line 1309  int mips_cpu_disassemble_instr(struct cp Line 1302  int mips_cpu_disassemble_instr(struct cp
1302                          case MMI_MADD:                          case MMI_MADD:
1303                          case MMI_MADDU:                          case MMI_MADDU:
1304                                  if (rd != MIPS_GPR_ZERO) {                                  if (rd != MIPS_GPR_ZERO) {
1305                                          debug("%s,", regname(cpu->machine, rd));                                          debug("%s,", regnames[rd]);
1306                                  }                                  }
1307                                  debug("%s", regname(cpu->machine, rs));                                  debug("%s,%s", regnames[rs], regnames[rt]);
                                 debug(",%s", regname(cpu->machine, rt));  
1308                                  break;                                  break;
1309    
1310                          case MMI_MMI0:                          case MMI_MMI0:
# Line 1327  int mips_cpu_disassemble_instr(struct cp Line 1319  int mips_cpu_disassemble_instr(struct cp
1319                                  case MMI0_PPACB:                                  case MMI0_PPACB:
1320                                  case MMI0_PPACH:                                  case MMI0_PPACH:
1321                                  case MMI0_PPACW:                                  case MMI0_PPACW:
1322                                          debug("%s", regname(cpu->machine, rd));                                          debug("%s,%s,%s", regnames[rd],
1323                                          debug(",%s", regname(cpu->machine, rs));                                              regnames[rs], regnames[rt]);
                                         debug(",%s", regname(cpu->machine, rt));  
1324                                          break;                                          break;
1325    
1326                                  default:debug("(UNIMPLEMENTED)");                                  default:debug("(UNIMPLEMENTED)");
# Line 1345  int mips_cpu_disassemble_instr(struct cp Line 1336  int mips_cpu_disassemble_instr(struct cp
1336                                  case MMI1_PEXTUW:                                  case MMI1_PEXTUW:
1337                                  case MMI1_PMINH:                                  case MMI1_PMINH:
1338                                  case MMI1_PMINW:                                  case MMI1_PMINW:
1339                                          debug("%s", regname(cpu->machine, rd));                                          debug("%s,%s,%s", regnames[rd],
1340                                          debug(",%s", regname(cpu->machine, rs));                                              regnames[rs], regnames[rt]);
                                         debug(",%s", regname(cpu->machine, rt));  
1341                                          break;                                          break;
1342    
1343                                  default:debug("(UNIMPLEMENTED)");                                  default:debug("(UNIMPLEMENTED)");
# Line 1360  int mips_cpu_disassemble_instr(struct cp Line 1350  int mips_cpu_disassemble_instr(struct cp
1350    
1351                                  case MMI2_PMFHI:                                  case MMI2_PMFHI:
1352                                  case MMI2_PMFLO:                                  case MMI2_PMFLO:
1353                                          debug("%s", regname(cpu->machine, rd));                                          debug("%s", regnames[rd]);
1354                                          break;                                          break;
1355    
1356                                  case MMI2_PHMADH:                                  case MMI2_PHMADH:
# Line 1373  int mips_cpu_disassemble_instr(struct cp Line 1363  int mips_cpu_disassemble_instr(struct cp
1363                                  case MMI2_PMULTH:                                  case MMI2_PMULTH:
1364                                  case MMI2_PMULTW:                                  case MMI2_PMULTW:
1365                                  case MMI2_PSLLVW:                                  case MMI2_PSLLVW:
1366                                          debug("%s", regname(cpu->machine, rd));                                          debug("%s,%s,%s", regnames[rd],
1367                                          debug(",%s", regname(cpu->machine, rs));                                              regnames[rs], regnames[rt]);
                                         debug(",%s", regname(cpu->machine, rt));  
1368                                          break;                                          break;
1369    
1370                                  default:debug("(UNIMPLEMENTED)");                                  default:debug("(UNIMPLEMENTED)");
# Line 1388  int mips_cpu_disassemble_instr(struct cp Line 1377  int mips_cpu_disassemble_instr(struct cp
1377    
1378                                  case MMI3_PMTHI:                                  case MMI3_PMTHI:
1379                                  case MMI3_PMTLO:                                  case MMI3_PMTLO:
1380                                          debug("%s", regname(cpu->machine, rs));                                          debug("%s", regnames[rs]);
1381                                          break;                                          break;
1382    
1383                                  case MMI3_PINTEH:                                  case MMI3_PINTEH:
# Line 1397  int mips_cpu_disassemble_instr(struct cp Line 1386  int mips_cpu_disassemble_instr(struct cp
1386                                  case MMI3_PNOR:                                  case MMI3_PNOR:
1387                                  case MMI3_POR:                                  case MMI3_POR:
1388                                  case MMI3_PSRAVW:                                  case MMI3_PSRAVW:
1389                                          debug("%s", regname(cpu->machine, rd));                                          debug("%s,%s,%s", regnames[rd],
1390                                          debug(",%s", regname(cpu->machine, rs));                                              regnames[rs], regnames[rt]);
                                         debug(",%s", regname(cpu->machine, rt));  
1391                                          break;                                          break;
1392    
1393                                  default:debug("(UNIMPLEMENTED)");                                  default:debug("(UNIMPLEMENTED)");
# Line 1422  int mips_cpu_disassemble_instr(struct cp Line 1410  int mips_cpu_disassemble_instr(struct cp
1410                  case SPECIAL2_MSUBU:                  case SPECIAL2_MSUBU:
1411                          if (rd != MIPS_GPR_ZERO) {                          if (rd != MIPS_GPR_ZERO) {
1412                                  debug("WEIRD_NONZERO_RD(%s),",                                  debug("WEIRD_NONZERO_RD(%s),",
1413                                      regname(cpu->machine, rd));                                      regnames[rd]);
1414                          }                          }
1415                          debug("%s", regname(cpu->machine, rs));                          debug("%s,%s", regnames[rs], regnames[rt]);
                         debug(",%s", regname(cpu->machine, rt));  
1416                          break;                          break;
1417    
1418                  case SPECIAL2_MUL:                  case SPECIAL2_MUL:
1419                          /*  Apparently used both on R5900 and MIPS32:  */                          /*  Apparently used both on R5900 and MIPS32:  */
1420                          debug("%s", regname(cpu->machine, rd));                          debug("%s,%s,%s", regnames[rd],
1421                          debug(",%s", regname(cpu->machine, rs));                              regnames[rs], regnames[rt]);
                         debug(",%s", regname(cpu->machine, rt));  
1422                          break;                          break;
1423    
1424                  case SPECIAL2_CLZ:                  case SPECIAL2_CLZ:
1425                  case SPECIAL2_CLO:                  case SPECIAL2_CLO:
1426                  case SPECIAL2_DCLZ:                  case SPECIAL2_DCLZ:
1427                  case SPECIAL2_DCLO:                  case SPECIAL2_DCLO:
1428                          debug("%s", regname(cpu->machine, rd));                          debug("%s,%s", regnames[rd], regnames[rs]);
                         debug(",%s", regname(cpu->machine, rs));  
1429                          break;                          break;
1430    
1431                  default:                  default:
# Line 1450  int mips_cpu_disassemble_instr(struct cp Line 1435  int mips_cpu_disassemble_instr(struct cp
1435    
1436          case HI6_REGIMM:          case HI6_REGIMM:
1437                  regimm5 = instr[2] & 0x1f;                  regimm5 = instr[2] & 0x1f;
1438                    rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
1439                    imm = (instr[1] << 8) + instr[0];
1440                    if (imm >= 32768)              
1441                            imm -= 65536;
1442    
1443                  switch (regimm5) {                  switch (regimm5) {
1444    
1445                  case REGIMM_BLTZ:                  case REGIMM_BLTZ:
1446                  case REGIMM_BGEZ:                  case REGIMM_BGEZ:
1447                  case REGIMM_BLTZL:                  case REGIMM_BLTZL:
# Line 1459  int mips_cpu_disassemble_instr(struct cp Line 1450  int mips_cpu_disassemble_instr(struct cp
1450                  case REGIMM_BLTZALL:                  case REGIMM_BLTZALL:
1451                  case REGIMM_BGEZAL:                  case REGIMM_BGEZAL:
1452                  case REGIMM_BGEZALL:                  case REGIMM_BGEZALL:
1453                          rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);                          debug("%s\t%s,", regimm_names[regimm5], regnames[rs]);
                         imm = (instr[1] << 8) + instr[0];  
                         if (imm >= 32768)                
                                 imm -= 65536;  
   
                         debug("%s\t%s,", regimm_names[regimm5],  
                             regname(cpu->machine, rs));  
1454    
1455                          addr = (dumpaddr + 4) + (imm << 2);                          addr = (dumpaddr + 4) + (imm << 2);
1456    
# Line 1474  int mips_cpu_disassemble_instr(struct cp Line 1459  int mips_cpu_disassemble_instr(struct cp
1459                          else                          else
1460                                  debug("0x%016"PRIx64, (uint64_t) addr);                                  debug("0x%016"PRIx64, (uint64_t) addr);
1461                          break;                          break;
1462    
1463                    case REGIMM_SYNCI:
1464                            debug("%s\t%i(%s)", regimm_names[regimm5],
1465                                imm, regnames[rs]);
1466                            break;
1467    
1468                  default:                  default:
1469                          debug("unimplemented regimm5 = 0x%02x", regimm5);                          debug("unimplemented regimm5 = 0x%02x", regimm5);
1470                  }                  }
# Line 1551  void mips_cpu_register_dump(struct cpu * Line 1542  void mips_cpu_register_dump(struct cpu *
1542                                              "          ");                                              "          ");
1543                                  else                                  else
1544                                          debug(" %3s=%016"PRIx64"%016"PRIx64,                                          debug(" %3s=%016"PRIx64"%016"PRIx64,
1545                                              regname(cpu->machine, r),                                              regnames[r], (uint64_t)
1546                                              (uint64_t)cpu->cd.mips.gpr_quadhi[r],                                              cpu->cd.mips.gpr_quadhi[r],
1547                                              (uint64_t)cpu->cd.mips.gpr[r]);                                              (uint64_t)cpu->cd.mips.gpr[r]);
1548                                  if ((i & 1) == 1)                                  if ((i & 1) == 1)
1549                                          debug("\n");                                          debug("\n");
# Line 1565  void mips_cpu_register_dump(struct cpu * Line 1556  void mips_cpu_register_dump(struct cpu *
1556                                  if (i == MIPS_GPR_ZERO)                                  if (i == MIPS_GPR_ZERO)
1557                                          debug("               ");                                          debug("               ");
1558                                  else                                  else
1559                                          debug(" %3s = %08"PRIx32,                                          debug(" %3s = %08"PRIx32, regnames[i],
                                             regname(cpu->machine, i),  
1560                                              (uint32_t)cpu->cd.mips.gpr[i]);                                              (uint32_t)cpu->cd.mips.gpr[i]);
1561                                  if ((i & 3) == 3)                                  if ((i & 3) == 3)
1562                                          debug("\n");                                          debug("\n");
# Line 1581  void mips_cpu_register_dump(struct cpu * Line 1571  void mips_cpu_register_dump(struct cpu *
1571                                          debug("                           ");                                          debug("                           ");
1572                                  else                                  else
1573                                          debug("   %3s = 0x%016"PRIx64,                                          debug("   %3s = 0x%016"PRIx64,
1574                                              regname(cpu->machine, r),                                              regnames[r],
1575                                              (uint64_t)cpu->cd.mips.gpr[r]);                                              (uint64_t)cpu->cd.mips.gpr[r]);
1576                                  if ((i & 1) == 1)                                  if ((i & 1) == 1)
1577                                          debug("\n");                                          debug("\n");
# Line 1609  void mips_cpu_register_dump(struct cpu * Line 1599  void mips_cpu_register_dump(struct cpu *
1599                          if ((i & nm1) == 0)                          if ((i & nm1) == 0)
1600                                  debug("cpu%i:", cpu->cpu_id);                                  debug("cpu%i:", cpu->cpu_id);
1601    
1602                          if (cpu->machine->show_symbolic_register_names &&                          if (coprocnr == 0)
                             coprocnr == 0)  
1603                                  debug(" %8s", cop0_names[i]);                                  debug(" %8s", cop0_names[i]);
1604                          else                          else
1605                                  debug(" c%i,%02i", coprocnr, i);                                  debug(" c%i,%02i", coprocnr, i);
1606    
1607                          if (bits32)                          if (bits32)
1608                                  debug("=%08x", (int)cpu->cd.mips.coproc[coprocnr]->reg[i]);                                  debug("=%08x", (int)cpu->cd.mips.
1609                                        coproc[coprocnr]->reg[i]);
1610                          else {                          else {
1611                                  if (coprocnr == 0 && (i == COP0_COUNT                                  if (coprocnr == 0 && (i == COP0_COUNT
1612                                      || i == COP0_COMPARE || i == COP0_INDEX                                      || i == COP0_COMPARE || i == COP0_INDEX
1613                                      || i == COP0_RANDOM || i == COP0_WIRED))                                      || i == COP0_RANDOM || i == COP0_WIRED))
1614                                          debug(" =         0x%08x", (int)cpu->cd.mips.coproc[coprocnr]->reg[i]);                                          debug(" =         0x%08x",
1615                                                (int) cpu->cd.mips.coproc[
1616                                                coprocnr]->reg[i]);
1617                                  else                                  else
1618                                          debug(" = 0x%016"PRIx64, (uint64_t)                                          debug(" = 0x%016"PRIx64, (uint64_t)
1619                                              cpu->cd.mips.coproc[coprocnr]->reg[i]);                                              cpu->cd.mips.coproc[
1620                                                coprocnr]->reg[i]);
1621                          }                          }
1622    
1623                          if ((i & nm1) == nm1)                          if ((i & nm1) == nm1)
# Line 1640  void mips_cpu_register_dump(struct cpu * Line 1633  void mips_cpu_register_dump(struct cpu *
1633                          debug("cpu%i: ", cpu->cpu_id);                          debug("cpu%i: ", cpu->cpu_id);
1634                          debug("config_select1 = 0x");                          debug("config_select1 = 0x");
1635                          if (cpu->is_32bit)                          if (cpu->is_32bit)
1636                                  debug("%08"PRIx32, (uint32_t)cpu->cd.mips.cop0_config_select1);                                  debug("%08"PRIx32,
1637                                        (uint32_t)cpu->cd.mips.cop0_config_select1);
1638                          else                          else
1639                                  debug("%016"PRIx64, (uint64_t)cpu->cd.mips.cop0_config_select1);                                  debug("%016"PRIx64,
1640                                        (uint64_t)cpu->cd.mips.cop0_config_select1);
1641                          debug("\n");                          debug("\n");
1642                  }                  }
1643    
# Line 1676  void mips_cpu_register_dump(struct cpu * Line 1671  void mips_cpu_register_dump(struct cpu *
1671  }  }
1672    
1673    
 static void add_response_word(struct cpu *cpu, char *r, uint64_t value,  
         size_t maxlen, int len)  
 {  
         char *format = (len == 4)? "%08"PRIx64 : "%016"PRIx64;  
         if (len == 4)  
                 value &= 0xffffffffULL;  
         if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {  
                 if (len == 4) {  
                         value = ((value & 0xff) << 24) +  
                                 ((value & 0xff00) << 8) +  
                                 ((value & 0xff0000) >> 8) +  
                                 ((value & 0xff000000) >> 24);  
                 } else {  
                         value = ((value & 0xff) << 56) +  
                                 ((value & 0xff00) << 40) +  
                                 ((value & 0xff0000) << 24) +  
                                 ((value & 0xff000000ULL) << 8) +  
                                 ((value & 0xff00000000ULL) >> 8) +  
                                 ((value & 0xff0000000000ULL) >> 24) +  
                                 ((value & 0xff000000000000ULL) >> 40) +  
                                 ((value & 0xff00000000000000ULL) >> 56);  
                 }  
         }  
         snprintf(r + strlen(r), maxlen - strlen(r), format, (uint64_t)value);  
 }  
   
   
1674  /*  /*
1675   *  mips_cpu_gdb_stub():   *  mips_cpu_interrupt_assert(), mips_cpu_interrupt_deassert():
1676   *   *
1677   *  Execute a "remote GDB" command. Returns 1 on success, 0 on error.   *  Assert or deassert a MIPS CPU interrupt by masking in or out bits
1678     *  in the CAUSE register of coprocessor 0.
1679   */   */
1680  char *mips_cpu_gdb_stub(struct cpu *cpu, char *cmd)  void mips_cpu_interrupt_assert(struct interrupt *interrupt)
1681  {  {
1682          if (strcmp(cmd, "g") == 0) {          struct cpu *cpu = interrupt->extra;
1683                  /*  76 registers:  gprs, sr, lo, hi, badvaddr, cause, pc,          cpu->cd.mips.coproc[0]->reg[COP0_CAUSE] |= interrupt->line;
                     fprs, fsr, fir, fp.  */  
                 int i;  
                 char *r;  
                 size_t wlen = cpu->is_32bit?  
                     sizeof(uint32_t) : sizeof(uint64_t);  
                 size_t len = 1 + 76 * wlen;  
                 r = malloc(len);  
                 if (r == NULL) {  
                         fprintf(stderr, "out of memory\n");  
                         exit(1);  
                 }  
                 r[0] = '\0';  
                 for (i=0; i<32; i++)  
                         add_response_word(cpu, r, cpu->cd.mips.gpr[i],  
                             len, wlen);  
                 add_response_word(cpu, r,  
                     cpu->cd.mips.coproc[0]->reg[COP0_STATUS], len, wlen);  
                 add_response_word(cpu, r, cpu->cd.mips.lo, len, wlen);  
                 add_response_word(cpu, r, cpu->cd.mips.hi, len, wlen);  
                 add_response_word(cpu, r,  
                     cpu->cd.mips.coproc[0]->reg[COP0_BADVADDR], len, wlen);  
                 add_response_word(cpu, r,  
                     cpu->cd.mips.coproc[0]->reg[COP0_CAUSE], len, wlen);  
                 add_response_word(cpu, r, cpu->pc, len, wlen);  
                 for (i=0; i<32; i++)  
                         add_response_word(cpu, r,  
                             cpu->cd.mips.coproc[1]->reg[i], len, wlen);  
                 add_response_word(cpu, r,  
                     cpu->cd.mips.coproc[1]->reg[31] /* fcsr */, len, wlen);  
                 add_response_word(cpu, r,  
                     cpu->cd.mips.coproc[1]->reg[0] /* fcir */, len, wlen);  
   
                 /*  TODO: fp = gpr 30?  */  
                 add_response_word(cpu, r, cpu->cd.mips.gpr[30], len, wlen);  
   
                 return r;  
         }  
   
         if (cmd[0] == 'p') {  
                 int regnr = strtol(cmd + 1, NULL, 16);  
                 size_t wlen = cpu->is_32bit? sizeof(uint32_t):sizeof(uint64_t);  
                 size_t len = 2 * wlen + 1;  
                 char *r = malloc(len);  
                 r[0] = '\0';  
                 if (regnr >= 0 && regnr <= 31) {  
                         add_response_word(cpu, r,  
                             cpu->cd.mips.gpr[regnr], len, wlen);  
                 } else if (regnr == 0x20) {  
                         add_response_word(cpu, r, cpu->cd.mips.coproc[0]->  
                             reg[COP0_STATUS], len, wlen);  
                 } else if (regnr == 0x21) {  
                         add_response_word(cpu, r, cpu->cd.mips.lo, len, wlen);  
                 } else if (regnr == 0x22) {  
                         add_response_word(cpu, r, cpu->cd.mips.hi, len, wlen);  
                 } else if (regnr == 0x23) {  
                         add_response_word(cpu, r, cpu->cd.mips.coproc[0]->  
                             reg[COP0_BADVADDR], len, wlen);  
                 } else if (regnr == 0x24) {  
                         add_response_word(cpu, r, cpu->cd.mips.coproc[0]->  
                             reg[COP0_CAUSE], len, wlen);  
                 } else if (regnr == 0x25) {  
                         add_response_word(cpu, r, cpu->pc, len, wlen);  
                 } else if (regnr >= 0x26 && regnr <= 0x45 &&  
                     cpu->cd.mips.coproc[1] != NULL) {  
                         add_response_word(cpu, r, cpu->cd.mips.coproc[1]->  
                             reg[regnr - 0x26], len, wlen);  
                 } else if (regnr == 0x46) {  
                         add_response_word(cpu, r, cpu->cd.mips.coproc[1]->  
                             fcr[MIPS_FPU_FCSR], len, wlen);  
                 } else if (regnr == 0x47) {  
                         add_response_word(cpu, r, cpu->cd.mips.coproc[1]->  
                             fcr[MIPS_FPU_FCIR], len, wlen);  
                 } else {  
                         /*  Unimplemented:  */  
                         add_response_word(cpu, r, 0xcc000 + regnr, len, wlen);  
                 }  
                 return r;  
         }  
   
         fatal("mips_cpu_gdb_stub(): cmd='%s' TODO\n", cmd);  
         return NULL;  
1684  }  }
1685    void mips_cpu_interrupt_deassert(struct interrupt *interrupt)
   
 /*  
  *  mips_cpu_interrupt():  
  *  
  *  Cause an interrupt. If irq_nr is 2..7, then it is a MIPS hardware  
  *  interrupt. 0 and 1 are ignored (software interrupts).  
  *  
  *  If irq_nr is >= 8, then this function calls md_interrupt().  
  */  
 int mips_cpu_interrupt(struct cpu *cpu, uint64_t irq_nr)  
1686  {  {
1687          if (irq_nr >= 8) {          struct cpu *cpu = interrupt->extra;
1688                  if (cpu->machine->md_interrupt != NULL)          cpu->cd.mips.coproc[0]->reg[COP0_CAUSE] &= ~interrupt->line;
                         cpu->machine->md_interrupt(cpu->machine,  
                             cpu, irq_nr, 1);  
                 else  
                         fatal("mips_cpu_interrupt(): irq_nr = %i, "  
                             "but md_interrupt = NULL ?\n", irq_nr);  
                 return 1;  
         }  
   
         if (irq_nr < 2)  
                 return 0;  
   
         cpu->cd.mips.coproc[0]->reg[COP0_CAUSE] |=  
             ((1 << irq_nr) << STATUS_IM_SHIFT);  
   
         return 1;  
 }  
   
   
 /*  
  *  mips_cpu_interrupt_ack():  
  *  
  *  Acknowledge an interrupt. If irq_nr is 2..7, then it is a MIPS hardware  
  *  interrupt.  Interrupts 0..1 are ignored (software interrupts).  
  *  
  *  If irq_nr is >= 8, then it is machine dependent, and md_interrupt() is  
  *  called.  
  */  
 int mips_cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr)  
 {  
         if (irq_nr >= 8) {  
                 if (cpu->machine->md_interrupt != NULL)  
                         cpu->machine->md_interrupt(cpu->machine, cpu,  
                             irq_nr, 0);  
                 else  
                         fatal("mips_cpu_interrupt_ack(): irq_nr = %i, "  
                             "but md_interrupt = NULL ?\n", irq_nr);  
                 return 1;  
         }  
   
         if (irq_nr < 2)  
                 return 0;  
   
         cpu->cd.mips.coproc[0]->reg[COP0_CAUSE] &=  
             ~((1 << irq_nr) << STATUS_IM_SHIFT);  
   
         return 1;  
1689  }  }
1690    
1691    
# Line 1905  void mips_cpu_exception(struct cpu *cpu, Line 1737  void mips_cpu_exception(struct cpu *cpu,
1737                  switch (exccode) {                  switch (exccode) {
1738    
1739                  case EXCEPTION_INT:                  case EXCEPTION_INT:
1740                          debug(" cause_im=0x%02x", (int)((reg[COP0_CAUSE] & CAUSE_IP_MASK) >> CAUSE_IP_SHIFT));                          debug(" cause_im=0x%02x", (int)
1741                                ((reg[COP0_CAUSE] & CAUSE_IP_MASK)
1742                                >> CAUSE_IP_SHIFT));
1743                          break;                          break;
1744    
1745                  case EXCEPTION_SYS:                  case EXCEPTION_SYS:
# Line 1995  void mips_cpu_exception(struct cpu *cpu, Line 1829  void mips_cpu_exception(struct cpu *cpu,
1829    
1830                  if (exc_model == EXC3K) {                  if (exc_model == EXC3K) {
1831                          reg[COP0_CONTEXT] &= ~R2K3K_CONTEXT_BADVPN_MASK;                          reg[COP0_CONTEXT] &= ~R2K3K_CONTEXT_BADVPN_MASK;
1832                          reg[COP0_CONTEXT] |= ((vaddr_vpn2 << R2K3K_CONTEXT_BADVPN_SHIFT) & R2K3K_CONTEXT_BADVPN_MASK);                          reg[COP0_CONTEXT] |= ((vaddr_vpn2 <<
1833                                R2K3K_CONTEXT_BADVPN_SHIFT) &
1834                                R2K3K_CONTEXT_BADVPN_MASK);
1835    
1836                          reg[COP0_ENTRYHI] = (vaddr & R2K3K_ENTRYHI_VPN_MASK)                          reg[COP0_ENTRYHI] = (vaddr & R2K3K_ENTRYHI_VPN_MASK)
1837                              | (vaddr_asid << R2K3K_ENTRYHI_ASID_SHIFT);                              | (vaddr_asid << R2K3K_ENTRYHI_ASID_SHIFT);
# Line 2005  void mips_cpu_exception(struct cpu *cpu, Line 1841  void mips_cpu_exception(struct cpu *cpu,
1841                          reg[COP0_ENTRYHI] = (int64_t)(int32_t)reg[COP0_ENTRYHI];                          reg[COP0_ENTRYHI] = (int64_t)(int32_t)reg[COP0_ENTRYHI];
1842                  } else {                  } else {
1843                          if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {                          if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
1844                                  reg[COP0_CONTEXT] &= ~CONTEXT_BADVPN2_MASK_R4100;                                  reg[COP0_CONTEXT] &=
1845                                  reg[COP0_CONTEXT] |= ((vaddr_vpn2 << CONTEXT_BADVPN2_SHIFT) & CONTEXT_BADVPN2_MASK_R4100);                                      ~CONTEXT_BADVPN2_MASK_R4100;
1846                                    reg[COP0_CONTEXT] |= ((vaddr_vpn2 <<
1847                                        CONTEXT_BADVPN2_SHIFT) &
1848                                        CONTEXT_BADVPN2_MASK_R4100);
1849    
1850                                  /*  TODO:  fix these  */                                  /*  TODO:  fix these  */
1851                                  reg[COP0_XCONTEXT] &= ~XCONTEXT_R_MASK;                                  reg[COP0_XCONTEXT] &= ~XCONTEXT_R_MASK;
# Line 2046  void mips_cpu_exception(struct cpu *cpu, Line 1885  void mips_cpu_exception(struct cpu *cpu,
1885                  /*  debug("[ warning: cpu%i exception while EXL is set,"                  /*  debug("[ warning: cpu%i exception while EXL is set,"
1886                      " not setting EPC ]\n", cpu->cpu_id);  */                      " not setting EPC ]\n", cpu->cpu_id);  */
1887          } else {          } else {
1888                  if (cpu->delay_slot || cpu->cd.mips.nullify_next) {                  if (cpu->delay_slot) {
1889                          reg[COP0_EPC] = cpu->pc - 4;                          reg[COP0_EPC] = cpu->pc - 4;
1890                          reg[COP0_CAUSE] |= CAUSE_BD;                          reg[COP0_CAUSE] |= CAUSE_BD;
   
                         /*  TODO: Should the BD flag actually be set  
                             on nullified slots?  */  
1891                  } else {                  } else {
1892                          reg[COP0_EPC] = cpu->pc;                          reg[COP0_EPC] = cpu->pc;
1893                          reg[COP0_CAUSE] &= ~CAUSE_BD;                          reg[COP0_CAUSE] &= ~CAUSE_BD;
# Line 2063  void mips_cpu_exception(struct cpu *cpu, Line 1899  void mips_cpu_exception(struct cpu *cpu,
1899          else          else
1900                  cpu->delay_slot = NOT_DELAYED;                  cpu->delay_slot = NOT_DELAYED;
1901    
         cpu->cd.mips.nullify_next = 0;  
   
1902          /*  TODO: This is true for MIPS64, but how about others?  */          /*  TODO: This is true for MIPS64, but how about others?  */
1903          if (reg[COP0_STATUS] & STATUS_BEV)          if (reg[COP0_STATUS] & STATUS_BEV)
1904                  base = 0xffffffffbfc00200ULL;                  base = 0xffffffffbfc00200ULL;

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

  ViewVC Help
Powered by ViewVC 1.1.26