/[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 26 by dpavlin, Mon Oct 8 16:20:10 2007 UTC revision 42 by dpavlin, Mon Oct 8 16:22:32 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2003-2006  Anders Gavare.  All rights reserved.   *  Copyright (C) 2003-2007  Anders Gavare.  All rights reserved.
3   *   *
4   *  Redistribution and use in source and binary forms, with or without   *  Redistribution and use in source and binary forms, with or without
5   *  modification, are permitted provided that the following conditions are met:   *  modification, are permitted provided that the following conditions are met:
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: cpu_mips.c,v 1.58 2006/06/24 21:47:23 debug Exp $   *  $Id: cpu_mips.c,v 1.83 2007/06/15 18:07:08 debug Exp $
29   *   *
30   *  MIPS core CPU emulation.   *  MIPS core CPU emulation.
31   */   */
# Line 35  Line 35 
35  #include <string.h>  #include <string.h>
36  #include <sys/types.h>  #include <sys/types.h>
37  #include <ctype.h>  #include <ctype.h>
38    #include <unistd.h>
39    
40  #include "../../config.h"  #include "../../config.h"
41    
# Line 49  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    #include "timer.h"
56    
57    
58  extern volatile int single_step;  extern int native_code_translation_enabled;
59    
60  static char *exception_names[] = EXCEPTION_NAMES;  static char *exception_names[] = EXCEPTION_NAMES;
61    
62  static char *hi6_names[] = HI6_NAMES;  static char *hi6_names[] = HI6_NAMES;
63  static char *regimm_names[] = REGIMM_NAMES;  static char *regimm_names[] = REGIMM_NAMES;
64  static char *special_names[] = SPECIAL_NAMES;  static char *special_names[] = SPECIAL_NAMES;
65    static char *special_rot_names[] = SPECIAL_ROT_NAMES;
66  static char *special2_names[] = SPECIAL2_NAMES;  static char *special2_names[] = SPECIAL2_NAMES;
67  static char *mmi_names[] = MMI_NAMES;  static char *mmi_names[] = MMI_NAMES;
68  static char *mmi0_names[] = MMI0_NAMES;  static char *mmi0_names[] = MMI0_NAMES;
# Line 80  void mips32_pc_to_pointers(struct cpu *) Line 84  void mips32_pc_to_pointers(struct cpu *)
84    
85    
86  /*  /*
  *  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;  
 }  
   
   
 /*  
87   *  mips_cpu_new():   *  mips_cpu_new():
88   *   *
89   *  Create a new MIPS cpu object.   *  Create a new MIPS cpu object.
# Line 144  int mips_cpu_new(struct cpu *cpu, struct Line 124  int mips_cpu_new(struct cpu *cpu, struct
124                  cpu->is_32bit = 1;                  cpu->is_32bit = 1;
125    
126          if (cpu->is_32bit) {          if (cpu->is_32bit) {
127                    cpu->run_instr = mips32_run_instr;
128                  cpu->update_translation_table = mips32_update_translation_table;                  cpu->update_translation_table = mips32_update_translation_table;
129                  cpu->invalidate_translation_caches =                  cpu->invalidate_translation_caches =
130                      mips32_invalidate_translation_caches;                      mips32_invalidate_translation_caches;
131                  cpu->invalidate_code_translation =                  cpu->invalidate_code_translation =
132                      mips32_invalidate_code_translation;                      mips32_invalidate_code_translation;
133          } else {          } else {
134                    cpu->run_instr = mips_run_instr;
135                  cpu->update_translation_table = mips_update_translation_table;                  cpu->update_translation_table = mips_update_translation_table;
136                  cpu->invalidate_translation_caches =                  cpu->invalidate_translation_caches =
137                      mips_invalidate_translation_caches;                      mips_invalidate_translation_caches;
# Line 177  int mips_cpu_new(struct cpu *cpu, struct Line 159  int mips_cpu_new(struct cpu *cpu, struct
159          x = DEFAULT_PCACHE_SIZE;          x = DEFAULT_PCACHE_SIZE;
160          if (cpu->cd.mips.cpu_type.pdcache)          if (cpu->cd.mips.cpu_type.pdcache)
161                  x = cpu->cd.mips.cpu_type.pdcache;                  x = cpu->cd.mips.cpu_type.pdcache;
162          if (machine->cache_pdcache == 0)          if (cpu->cd.mips.cache_pdcache == 0)
163                  machine->cache_pdcache = x;                  cpu->cd.mips.cache_pdcache = x;
164    
165          x = DEFAULT_PCACHE_SIZE;          x = DEFAULT_PCACHE_SIZE;
166          if (cpu->cd.mips.cpu_type.picache)          if (cpu->cd.mips.cpu_type.picache)
167                  x = cpu->cd.mips.cpu_type.picache;                  x = cpu->cd.mips.cpu_type.picache;
168          if (machine->cache_picache == 0)          if (cpu->cd.mips.cache_picache == 0)
169                  machine->cache_picache = x;                  cpu->cd.mips.cache_picache = x;
170    
171          if (machine->cache_secondary == 0)          if (cpu->cd.mips.cache_secondary == 0)
172                  machine->cache_secondary = cpu->cd.mips.cpu_type.scache;                  cpu->cd.mips.cache_secondary = cpu->cd.mips.cpu_type.scache;
173    
174          linesize = DEFAULT_PCACHE_LINESIZE;          linesize = DEFAULT_PCACHE_LINESIZE;
175          if (cpu->cd.mips.cpu_type.pdlinesize)          if (cpu->cd.mips.cpu_type.pdlinesize)
176                  linesize = cpu->cd.mips.cpu_type.pdlinesize;                  linesize = cpu->cd.mips.cpu_type.pdlinesize;
177          if (machine->cache_pdcache_linesize == 0)          if (cpu->cd.mips.cache_pdcache_linesize == 0)
178                  machine->cache_pdcache_linesize = linesize;                  cpu->cd.mips.cache_pdcache_linesize = linesize;
179    
180          linesize = DEFAULT_PCACHE_LINESIZE;          linesize = DEFAULT_PCACHE_LINESIZE;
181          if (cpu->cd.mips.cpu_type.pilinesize)          if (cpu->cd.mips.cpu_type.pilinesize)
182                  linesize = cpu->cd.mips.cpu_type.pilinesize;                  linesize = cpu->cd.mips.cpu_type.pilinesize;
183          if (machine->cache_picache_linesize == 0)          if (cpu->cd.mips.cache_picache_linesize == 0)
184                  machine->cache_picache_linesize = linesize;                  cpu->cd.mips.cache_picache_linesize = linesize;
185    
186          linesize = 0;          linesize = 0;
187          if (cpu->cd.mips.cpu_type.slinesize)          if (cpu->cd.mips.cpu_type.slinesize)
188                  linesize = cpu->cd.mips.cpu_type.slinesize;                  linesize = cpu->cd.mips.cpu_type.slinesize;
189          if (machine->cache_secondary_linesize == 0)          if (cpu->cd.mips.cache_secondary_linesize == 0)
190                  machine->cache_secondary_linesize = linesize;                  cpu->cd.mips.cache_secondary_linesize = linesize;
191    
192    
193          /*          /*
# Line 214  int mips_cpu_new(struct cpu *cpu, struct Line 196  int mips_cpu_new(struct cpu *cpu, struct
196          for (i=CACHE_DATA; i<=CACHE_INSTRUCTION; i++) {          for (i=CACHE_DATA; i<=CACHE_INSTRUCTION; i++) {
197                  switch (i) {                  switch (i) {
198                  case CACHE_DATA:                  case CACHE_DATA:
199                          x = 1 << machine->cache_pdcache;                          x = 1 << cpu->cd.mips.cache_pdcache;
200                          linesize = 1 << machine->cache_pdcache_linesize;                          linesize = 1 << cpu->cd.mips.cache_pdcache_linesize;
201                          break;                          break;
202                  case CACHE_INSTRUCTION:                  case CACHE_INSTRUCTION:
203                          x = 1 << machine->cache_picache;                          x = 1 << cpu->cd.mips.cache_picache;
204                          linesize = 1 << machine->cache_picache_linesize;                          linesize = 1 << cpu->cd.mips.cache_picache_linesize;
205                          break;                          break;
206                  }                  }
207    
# Line 233  int mips_cpu_new(struct cpu *cpu, struct Line 215  int mips_cpu_new(struct cpu *cpu, struct
215                          size_per_cache_line = sizeof(struct r3000_cache_line);                          size_per_cache_line = sizeof(struct r3000_cache_line);
216                          break;                          break;
217                  default:                  default:
218                          size_per_cache_line = sizeof(struct r4000_cache_line);                          size_per_cache_line = 32;       /*  TODO  */
219                  }                  }
220    
221                  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 ?  */  
222    
223                  cpu->cd.mips.cache[i] = malloc(cpu->cd.mips.cache_size[i]);                  CHECK_ALLOCATION(cpu->cd.mips.cache[i] =
224                  if (cpu->cd.mips.cache[i] == NULL) {                      malloc(cpu->cd.mips.cache_size[i]));
                         fprintf(stderr, "out of memory\n");  
                 }  
225    
226                  n_cache_lines = cpu->cd.mips.cache_size[i] /                  n_cache_lines = cpu->cd.mips.cache_size[i] /
227                      cpu->cd.mips.cache_linesize[i];                      cpu->cd.mips.cache_linesize[i];
228                  tags_size = n_cache_lines * size_per_cache_line;                  tags_size = n_cache_lines * size_per_cache_line;
229    
230                  cpu->cd.mips.cache_tags[i] = malloc(tags_size);                  CHECK_ALLOCATION(cpu->cd.mips.cache_tags[i] =
231                  if (cpu->cd.mips.cache_tags[i] == NULL) {                      malloc(tags_size));
                         fprintf(stderr, "out of memory\n");  
                 }  
232    
233                  /*  Initialize the cache tags:  */                  /*  Initialize the cache tags:  */
234                  switch (cpu->cd.mips.cpu_type.rev) {                  switch (cpu->cd.mips.cpu_type.rev) {
# Line 277  int mips_cpu_new(struct cpu *cpu, struct Line 254  int mips_cpu_new(struct cpu *cpu, struct
254           *  Secondary cache:           *  Secondary cache:
255           */           */
256          secondary_cache_size = 0;          secondary_cache_size = 0;
257          if (machine->cache_secondary)          if (cpu->cd.mips.cache_secondary)
258                  secondary_cache_size = 1 << machine->cache_secondary;                  secondary_cache_size = 1 << cpu->cd.mips.cache_secondary;
259          /*  TODO: linesize...  */          /*  TODO: linesize...  */
260    
261          if (cpu_id == 0) {          if (cpu_id == 0) {
# Line 299  int mips_cpu_new(struct cpu *cpu, struct Line 276  int mips_cpu_new(struct cpu *cpu, struct
276                  debug(")");                  debug(")");
277          }          }
278    
279            /*  Register the CPU's interrupts:  */
280            for (i=2; i<8; i++) {
281                    struct interrupt template;
282                    char name[50];
283                    snprintf(name, sizeof(name), "%s.%i", cpu->path, i);
284                    memset(&template, 0, sizeof(template));
285                    template.line = 1 << (STATUS_IM_SHIFT + i);
286                    template.name = name;
287                    template.extra = cpu;
288                    template.interrupt_assert = mips_cpu_interrupt_assert;
289                    template.interrupt_deassert = mips_cpu_interrupt_deassert;
290                    interrupt_handler_register(&template);
291    
292                    if (i == 7)
293                            INTERRUPT_CONNECT(name, cpu->cd.mips.irq_compare);
294            }
295    
296          /*  System coprocessor (0), and FPU (1):  */          /*  System coprocessor (0), and FPU (1):  */
297          cpu->cd.mips.coproc[0] = mips_coproc_new(cpu, 0);          cpu->cd.mips.coproc[0] = mips_coproc_new(cpu, 0);
298          cpu->cd.mips.coproc[1] = mips_coproc_new(cpu, 1);          cpu->cd.mips.coproc[1] = mips_coproc_new(cpu, 1);
# Line 320  int mips_cpu_new(struct cpu *cpu, struct Line 314  int mips_cpu_new(struct cpu *cpu, struct
314                          cpu->translate_v2p = translate_v2p_generic;                          cpu->translate_v2p = translate_v2p_generic;
315          }          }
316    
317            if (cpu->machine->prom_emulation) {
318                    /*
319                     *  Default behaviour of jumping to 0xbfc00000 should be
320                     *  a reboot, unless machine-specific initialization code
321                     *  overrides this.
322                     *
323                     *  Note: Specifically big-endian machines should override
324                     *  this, since the default MIPS CPU is little-endian!
325                     */
326                    store_32bit_word(cpu, 0xffffffff9fc00000ULL, 0x00c0de0d);
327            }
328    
329            /*  Add all register names to the settings:  */
330            CPU_SETTINGS_ADD_REGISTER64("pc", cpu->pc);
331            CPU_SETTINGS_ADD_REGISTER64("hi", cpu->cd.mips.hi);
332            CPU_SETTINGS_ADD_REGISTER64("lo", cpu->cd.mips.lo);
333            for (i=0; i<N_MIPS_GPRS; i++)
334                    CPU_SETTINGS_ADD_REGISTER64(regnames[i], cpu->cd.mips.gpr[i]);
335            /*  TODO: Write via special handler function!  */
336            for (i=0; i<N_MIPS_COPROC_REGS; i++)
337                    CPU_SETTINGS_ADD_REGISTER64(cop0_names[i],
338                        cpu->cd.mips.coproc[0]->reg[i]);
339    
340            if (native_code_translation_enabled)
341                    cpu->sampling_timer = timer_add(CPU_SAMPLE_TIMER_HZ,
342                        mips_timer_sample_tick, cpu);
343    
344          return 1;          return 1;
345  }  }
346    
# Line 488  void mips_cpu_tlbdump(struct machine *m, Line 509  void mips_cpu_tlbdump(struct machine *m,
509          /*  Raw output:  */          /*  Raw output:  */
510          if (rawflag) {          if (rawflag) {
511                  for (i=0; i<m->ncpus; i++) {                  for (i=0; i<m->ncpus; i++) {
512                            struct mips_coproc *cop0 =
513                                m->cpus[i]->cd.mips.coproc[0];
514    
515                          if (x >= 0 && i != x)                          if (x >= 0 && i != x)
516                                  continue;                                  continue;
517    
# Line 495  void mips_cpu_tlbdump(struct machine *m, Line 519  void mips_cpu_tlbdump(struct machine *m,
519                          printf("cpu%i: (", i);                          printf("cpu%i: (", i);
520    
521                          if (m->cpus[i]->is_32bit)                          if (m->cpus[i]->is_32bit)
522                                  printf("index=0x%08x random=0x%08x", (int)m->                                  printf("index=0x%08x random=0x%08x",
523                                      cpus[i]->cd.mips.coproc[0]->reg[COP0_INDEX],                                      (int) cop0->reg[COP0_INDEX],
524                                      (int)m->cpus[i]->cd.mips.coproc[0]->reg                                      (int) cop0->reg[COP0_RANDOM]);
                                     [COP0_RANDOM]);  
525                          else                          else
526                                  printf("index=0x%016"PRIx64                                  printf("index=0x%016"PRIx64
527                                      " random=0x%016"PRIx64,                                      " random=0x%016"PRIx64,
528                                      (uint64_t)m->cpus[i]->cd.mips.coproc[0]->                                      (uint64_t) cop0->reg[COP0_INDEX],
529                                      reg[COP0_INDEX], (uint64_t)m->cpus[i]->                                      (uint64_t) cop0->reg[COP0_RANDOM]);
                                     cd.mips.coproc[0]->reg[COP0_RANDOM]);  
530    
531                          if (m->cpus[i]->cd.mips.cpu_type.isa_level >= 3)                          if (m->cpus[i]->cd.mips.cpu_type.isa_level >= 3)
532                                  printf(" wired=0x%"PRIx64, (uint64_t) m->cpus                                  printf(" wired=0x%"PRIx64,
533                                      [i]->cd.mips.coproc[0]->reg[COP0_WIRED]);                                      (uint64_t) cop0->reg[COP0_WIRED]);
534    
535                          printf(")\n");                          printf(")\n");
536    
# Line 516  void mips_cpu_tlbdump(struct machine *m, Line 538  void mips_cpu_tlbdump(struct machine *m,
538                              nr_of_tlb_entries; j++) {                              nr_of_tlb_entries; j++) {
539                                  if (m->cpus[i]->cd.mips.cpu_type.mmu_model ==                                  if (m->cpus[i]->cd.mips.cpu_type.mmu_model ==
540                                      MMU3K)                                      MMU3K)
541                                          printf("%3i: hi=0x%08x lo=0x%08x\n", j,                                          printf("%3i: hi=0x%08"PRIx32" lo=0x%08"
542                                              (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].hi,                                              PRIx32"\n", j,
543                                              (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo0);                                              (uint32_t) cop0->tlbs[j].hi,
544                                                (uint32_t) cop0->tlbs[j].lo0);
545                                  else if (m->cpus[i]->is_32bit)                                  else if (m->cpus[i]->is_32bit)
546                                          printf("%3i: hi=0x%08x mask=0x%08x "                                          printf("%3i: hi=0x%08"PRIx32" mask=0x"
547                                              "lo0=0x%08x lo1=0x%08x\n", j,                                              "%08"PRIx32" lo0=0x%08"PRIx32
548                                              (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].hi,                                              " lo1=0x%08"PRIx32"\n", j,
549                                              (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].mask,                                              (uint32_t) cop0->tlbs[j].hi,
550                                              (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo0,                                              (uint32_t) cop0->tlbs[j].mask,
551                                              (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo1);                                              (uint32_t) cop0->tlbs[j].lo0,
552                                                (uint32_t) cop0->tlbs[j].lo1);
553                                  else                                  else
554                                          printf("%3i: hi=0x%016"PRIx64" mask=0x%016"PRIx64" "                                          printf("%3i: hi=0x%016"PRIx64" mask="
555                                              "lo0=0x%016"PRIx64" lo1=0x%016"PRIx64"\n", j,                                              "0x%016"PRIx64" lo0=0x%016"PRIx64
556                                              (uint64_t)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].hi,                                              " lo1=0x%016"PRIx64"\n", j,
557                                              (uint64_t)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].mask,                                              (uint64_t) cop0->tlbs[j].hi,
558                                              (uint64_t)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo0,                                              (uint64_t) cop0->tlbs[j].mask,
559                                              (uint64_t)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo1);                                              (uint64_t) cop0->tlbs[j].lo0,
560                                                (uint64_t) cop0->tlbs[j].lo1);
561                          }                          }
562                  }                  }
563    
564                  return;                  return;
565          }          }
566    
567          /*  Nicely formatted output:  */          /*  Nicely formatted output:  */
568          for (i=0; i<m->ncpus; i++) {          for (i=0; i<m->ncpus; i++) {
569                  int pageshift = 12;                  int pageshift = 12;
570                    struct mips_coproc *cop0 = m->cpus[i]->cd.mips.coproc[0];
571    
572                  if (x >= 0 && i != x)                  if (x >= 0 && i != x)
573                          continue;                          continue;
# Line 553  void mips_cpu_tlbdump(struct machine *m, Line 580  void mips_cpu_tlbdump(struct machine *m,
580                  switch (m->cpus[i]->cd.mips.cpu_type.isa_level) {                  switch (m->cpus[i]->cd.mips.cpu_type.isa_level) {
581                  case 1:                  case 1:
582                  case 2: printf("index=0x%x random=0x%x",                  case 2: printf("index=0x%x random=0x%x",
583                              (int) ((m->cpus[i]->cd.mips.coproc[0]->                              (int) ((cop0->reg[COP0_INDEX] & R2K3K_INDEX_MASK)
                             reg[COP0_INDEX] & R2K3K_INDEX_MASK)  
584                              >> R2K3K_INDEX_SHIFT),                              >> R2K3K_INDEX_SHIFT),
585                              (int) ((m->cpus[i]->cd.mips.coproc[0]->                              (int) ((cop0->reg[COP0_RANDOM] & R2K3K_RANDOM_MASK)
                             reg[COP0_RANDOM] & R2K3K_RANDOM_MASK)  
586                              >> R2K3K_RANDOM_SHIFT));                              >> R2K3K_RANDOM_SHIFT));
587                          break;                          break;
588                  default:printf("index=0x%x random=0x%x",                  default:printf("index=0x%x random=0x%x",
589                              (int) (m->cpus[i]->cd.mips.coproc[0]->                              (int) (cop0->reg[COP0_INDEX] & INDEX_MASK),
590                              reg[COP0_INDEX] & INDEX_MASK),                              (int) (cop0->reg[COP0_RANDOM] & RANDOM_MASK));
591                              (int) (m->cpus[i]->cd.mips.coproc[0]->                          printf(" wired=0x%"PRIx64,
592                              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]);  
593                  }                  }
594    
595                  printf(")\n");                  printf(")\n");
596    
597                  for (j=0; j<m->cpus[i]->cd.mips.cpu_type.                  for (j=0; j<m->cpus[i]->cd.mips.cpu_type.
598                      nr_of_tlb_entries; j++) {                      nr_of_tlb_entries; j++) {
599                          uint64_t hi,lo0,lo1,mask;                          uint64_t hi = cop0->tlbs[j].hi;
600                          hi = m->cpus[i]->cd.mips.coproc[0]->tlbs[j].hi;                          uint64_t lo0 = cop0->tlbs[j].lo0;
601                          lo0 = m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo0;                          uint64_t lo1 = cop0->tlbs[j].lo1;
602                          lo1 = m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo1;                          uint64_t mask = cop0->tlbs[j].mask;
603                          mask = m->cpus[i]->cd.mips.coproc[0]->tlbs[j].mask;                          uint64_t psize;
604    
605                            mask |= (1 << (pageshift+1)) - 1;
606                            /*  here mask = e.g. 0x1fff for 4KB pages  */
607    
608                          printf("%3i: ", j);                          printf("%3i: ", j);
609    
610                          switch (m->cpus[i]->cd.mips.cpu_type.mmu_model) {                          switch (m->cpus[i]->cd.mips.cpu_type.mmu_model) {
611                          case MMU3K:                          case MMU3K:
612                                  if (!(lo0 & R2K3K_ENTRYLO_V)) {                                  if (!(lo0 & R2K3K_ENTRYLO_V)) {
# Line 603  void mips_cpu_tlbdump(struct machine *m, Line 630  void mips_cpu_tlbdump(struct machine *m,
630                                  printf("\n");                                  printf("\n");
631                                  break;                                  break;
632                          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;  
633                                  case MMU32:                                  case MMU32:
634                                          printf("vaddr=0x%08"PRIx32" ",                                          printf("vaddr=0x%08"PRIx32" ",
635                                              (uint32_t)(hi&ENTRYHI_VPN2_MASK));                                              (uint32_t) (hi & ~mask));
636                                          break;                                          break;
637                                  default:/*  R4000 etc.  */                                  default:/*  R4x00, R1x000, MIPS64, etc.  */
638                                          printf("vaddr=0x%1x..%010"PRIx64" ",                                          printf("vaddr=%016"PRIx64" ",
639                                              (int) (hi >> 60),                                              (uint64_t) (hi & ~mask));
                                             (uint64_t) (hi&ENTRYHI_VPN2_MASK));  
640                                  }                                  }
641                                  if (hi & TLB_G)                                  if (hi & TLB_G)
642                                          printf("(global): ");                                          printf("(global): ");
# Line 627  void mips_cpu_tlbdump(struct machine *m, Line 648  void mips_cpu_tlbdump(struct machine *m,
648    
649                                  if (!(lo0 & ENTRYLO_V))                                  if (!(lo0 & ENTRYLO_V))
650                                          printf(" p0=(invalid)   ");                                          printf(" p0=(invalid)   ");
651                                  else                                  else {
652                                          printf(" p0=0x%09"PRIx64" ", (uint64_t)                                          uint64_t paddr = lo0 & ENTRYLO_PFN_MASK;
653                                              (((lo0&ENTRYLO_PFN_MASK) >>                                          paddr >>= ENTRYLO_PFN_SHIFT;
654                                              ENTRYLO_PFN_SHIFT) << pageshift));                                          paddr <<= pageshift;
655                                            paddr &= ~(mask >> 1);
656                                            printf(" p0=0x%09"PRIx64" ",
657                                                (uint64_t) paddr);
658                                    }
659                                  printf(lo0 & ENTRYLO_D? "D" : " ");                                  printf(lo0 & ENTRYLO_D? "D" : " ");
660    
661                                  if (!(lo1 & ENTRYLO_V))                                  if (!(lo1 & ENTRYLO_V))
662                                          printf(" p1=(invalid)   ");                                          printf(" p1=(invalid)   ");
663                                  else                                  else {
664                                          printf(" p1=0x%09"PRIx64" ", (uint64_t)                                          uint64_t paddr = lo1 & ENTRYLO_PFN_MASK;
665                                              (((lo1&ENTRYLO_PFN_MASK) >>                                          paddr >>= ENTRYLO_PFN_SHIFT;
666                                              ENTRYLO_PFN_SHIFT) << pageshift));                                          paddr <<= pageshift;
667                                  printf(lo1 & ENTRYLO_D? "D" : " ");                                          paddr &= ~(mask >> 1);
668                                  mask |= (1 << (pageshift+1)) - 1;                                          printf(" p1=0x%09"PRIx64" ",
669                                  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);  
670                                  }                                  }
671                                  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:  */  
672    
673          /*  TODO  */                                  /*  convert e.g. 0x1fff to 4096  */
674                                    psize = (mask + 1) >> 1;
675    
676          /*  Register name:  */                                  if (psize >= 1024 && psize <= 256*1024)
677          if (strcasecmp(name, "pc") == 0) {                                          printf(" (%iKB)", (int) (psize >> 10));
678                  if (writeflag) {                                  else if (psize >= 1024*1024 && psize <=
679                          m->cpus[cpunr]->pc = *valuep;                                      64*1024*1024)
680                          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;  
681                                  else                                  else
682                                          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;  
                         }  
         }  
683    
684          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;  
685                          }                          }
686          }                  }
   
         /*  TODO: Coprocessor 1,2,3 registers.  */  
 }  
   
   
 /*  
  *  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 "";  
687          }          }
688  }  }
689    
# Line 790  static const char *cpu_flags(struct cpu Line 705  static const char *cpu_flags(struct cpu
705  int mips_cpu_disassemble_instr(struct cpu *cpu, unsigned char *originstr,  int mips_cpu_disassemble_instr(struct cpu *cpu, unsigned char *originstr,
706          int running, uint64_t dumpaddr)          int running, uint64_t dumpaddr)
707  {  {
708          int hi6, special6, regimm5;          int hi6, special6, regimm5, sub;
709          int rt, rd, rs, sa, imm, copz, cache_op, which_cache, showtag;          int rt, rd, rs, sa, imm, copz, cache_op, which_cache, showtag;
710          uint64_t addr, offset;          uint64_t addr, offset;
711          uint32_t instrword;          uint32_t instrword;
# Line 832  int mips_cpu_disassemble_instr(struct cp Line 747  int mips_cpu_disassemble_instr(struct cp
747          debug(": %02x%02x%02x%02x",          debug(": %02x%02x%02x%02x",
748              instr[3], instr[2], instr[1], instr[0]);              instr[3], instr[2], instr[1], instr[0]);
749    
750          if (running)          if (running && cpu->delay_slot)
751                  debug("%s", cpu_flags(cpu));                  debug(" (d)");
752    
753          debug("\t");          debug("\t");
754    
# Line 841  int mips_cpu_disassemble_instr(struct cp Line 756  int mips_cpu_disassemble_instr(struct cp
756           *  Decode the instruction:           *  Decode the instruction:
757           */           */
758    
         if (cpu->cd.mips.nullify_next && running) {  
                 debug("(nullified)");  
                 goto disasm_ret;  
         }  
   
759          hi6 = (instr[3] >> 2) & 0x3f;          hi6 = (instr[3] >> 2) & 0x3f;
760    
761          switch (hi6) {          switch (hi6) {
# Line 861  int mips_cpu_disassemble_instr(struct cp Line 771  int mips_cpu_disassemble_instr(struct cp
771                  case SPECIAL_DSLL32:                  case SPECIAL_DSLL32:
772                  case SPECIAL_DSRL32:                  case SPECIAL_DSRL32:
773                  case SPECIAL_DSRA32:                  case SPECIAL_DSRA32:
774                            sub = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
775                          rt = instr[2] & 31;                          rt = instr[2] & 31;
776                          rd = (instr[1] >> 3) & 31;                          rd = (instr[1] >> 3) & 31;
777                          sa = ((instr[1] & 7) << 2) + ((instr[0] >> 6) & 3);                          sa = ((instr[1] & 7) << 2) + ((instr[0] >> 6) & 3);
# Line 874  int mips_cpu_disassemble_instr(struct cp Line 785  int mips_cpu_disassemble_instr(struct cp
785                                          debug("ehb");                                          debug("ehb");
786                                  else                                  else
787                                          debug("nop (weird, sa=%i)", sa);                                          debug("nop (weird, sa=%i)", sa);
788                                  goto disasm_ret;                                  break;
789                          } else                          }
790    
791                            switch (sub) {
792                            case 0x00:
793                                    debug("%s\t%s,", special_names[special6],
794                                        regnames[rd]);
795                                    debug("%s,%i", regnames[rt], sa);
796                                    break;
797                            case 0x01:
798                                  debug("%s\t%s,",                                  debug("%s\t%s,",
799                                      special_names[special6],                                      special_rot_names[special6],
800                                      regname(cpu->machine, rd));                                      regnames[rd]);
801                                  debug("%s,%i", regname(cpu->machine, rt), sa);                                  debug("%s,%i", regnames[rt], sa);
802                                    break;
803                            default:debug("UNIMPLEMENTED special, sub=0x%02x\n",
804                                        sub);
805                            }
806                          break;                          break;
807                  case SPECIAL_DSRLV:                  case SPECIAL_DSRLV:
808                  case SPECIAL_DSRAV:                  case SPECIAL_DSRAV:
# Line 890  int mips_cpu_disassemble_instr(struct cp Line 813  int mips_cpu_disassemble_instr(struct cp
813                          rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);                          rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
814                          rt = instr[2] & 31;                          rt = instr[2] & 31;
815                          rd = (instr[1] >> 3) & 31;                          rd = (instr[1] >> 3) & 31;
816                          debug("%s\t%s",                          sub = ((instr[1] & 7) << 2) + ((instr[0] >> 6) & 3);
817                              special_names[special6], regname(cpu->machine, rd));  
818                          debug(",%s", regname(cpu->machine, rt));                          switch (sub) {
819                          debug(",%s", regname(cpu->machine, rs));                          case 0x00:
820                                    debug("%s\t%s", special_names[special6],
821                                        regnames[rd]);
822                                    debug(",%s", regnames[rt]);
823                                    debug(",%s", regnames[rs]);
824                                    break;
825                            case 0x01:
826                                    debug("%s\t%s", special_rot_names[special6],
827                                        regnames[rd]);
828                                    debug(",%s", regnames[rt]);
829                                    debug(",%s", regnames[rs]);
830                                    break;
831                            default:debug("UNIMPLEMENTED special, sub=0x%02x\n",
832                                        sub);
833                            }
834                          break;                          break;
835                  case SPECIAL_JR:                  case SPECIAL_JR:
836                          rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);                          rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
837                          symbol = get_symbol_name(&cpu->machine->symbol_context,                          symbol = get_symbol_name(&cpu->machine->symbol_context,
838                              cpu->cd.mips.gpr[rs], &offset);                              cpu->cd.mips.gpr[rs], &offset);
839                          debug("jr\t%s", regname(cpu->machine, rs));                          /*  .hb = hazard barrier hint on MIPS32/64 rev 2  */
840                            debug("jr%s\t%s",
841                                (instr[1] & 0x04) ? ".hb" : "",
842                                regnames[rs]);
843                          if (running && symbol != NULL)                          if (running && symbol != NULL)
844                                  debug("\t<%s>", symbol);                                  debug("\t<%s>", symbol);
845                          break;                          break;
# Line 908  int mips_cpu_disassemble_instr(struct cp Line 848  int mips_cpu_disassemble_instr(struct cp
848                          rd = (instr[1] >> 3) & 31;                          rd = (instr[1] >> 3) & 31;
849                          symbol = get_symbol_name(&cpu->machine->symbol_context,                          symbol = get_symbol_name(&cpu->machine->symbol_context,
850                              cpu->cd.mips.gpr[rs], &offset);                              cpu->cd.mips.gpr[rs], &offset);
851                          debug("jalr\t%s", regname(cpu->machine, rd));                          /*  .hb = hazard barrier hint on MIPS32/64 rev 2  */
852                          debug(",%s", regname(cpu->machine, rs));                          debug("jalr%s\t%s",
853                                (instr[1] & 0x04) ? ".hb" : "",
854                                regnames[rd]);
855                            debug(",%s", regnames[rs]);
856                          if (running && symbol != NULL)                          if (running && symbol != NULL)
857                                  debug("\t<%s>", symbol);                                  debug("\t<%s>", symbol);
858                          break;                          break;
859                  case SPECIAL_MFHI:                  case SPECIAL_MFHI:
860                  case SPECIAL_MFLO:                  case SPECIAL_MFLO:
861                          rd = (instr[1] >> 3) & 31;                          rd = (instr[1] >> 3) & 31;
862                          debug("%s\t%s", special_names[special6],                          debug("%s\t%s", special_names[special6], regnames[rd]);
                             regname(cpu->machine, rd));  
863                          break;                          break;
864                  case SPECIAL_MTLO:                  case SPECIAL_MTLO:
865                  case SPECIAL_MTHI:                  case SPECIAL_MTHI:
866                          rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);                          rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
867                          debug("%s\t%s", special_names[special6],                          debug("%s\t%s", special_names[special6], regnames[rs]);
                             regname(cpu->machine, rs));  
868                          break;                          break;
869                  case SPECIAL_ADD:                  case SPECIAL_ADD:
870                  case SPECIAL_ADDU:                  case SPECIAL_ADDU:
# Line 948  int mips_cpu_disassemble_instr(struct cp Line 889  int mips_cpu_disassemble_instr(struct cp
889                              special6 == SPECIAL_SUBU) && rt == 0) {                              special6 == SPECIAL_SUBU) && rt == 0) {
890                                  /*  Special case 1: addu/subu with                                  /*  Special case 1: addu/subu with
891                                      rt = the zero register ==> move  */                                      rt = the zero register ==> move  */
892                                  debug("move\t%s", regname(cpu->machine, rd));                                  debug("move\t%s", regnames[rd]);
893                                  debug(",%s", regname(cpu->machine, rs));                                  debug(",%s", regnames[rs]);
894                          } else if (special6 == SPECIAL_ADDU && cpu->is_32bit                          } else if (special6 == SPECIAL_ADDU && cpu->is_32bit
895                              && rs == 0) {                              && rs == 0) {
896                                  /*  Special case 2: addu with                                  /*  Special case 2: addu with
897                                      rs = the zero register ==> move  */                                      rs = the zero register ==> move  */
898                                  debug("move\t%s", regname(cpu->machine, rd));                                  debug("move\t%s", regnames[rd]);
899                                  debug(",%s", regname(cpu->machine, rt));                                  debug(",%s", regnames[rt]);
900                          } else {                          } else {
901                                  debug("%s\t%s", special_names[special6],                                  debug("%s\t%s", special_names[special6],
902                                      regname(cpu->machine, rd));                                      regnames[rd]);
903                                  debug(",%s", regname(cpu->machine, rs));                                  debug(",%s", regnames[rs]);
904                                  debug(",%s", regname(cpu->machine, rt));                                  debug(",%s", regnames[rt]);
905                          }                          }
906                          break;                          break;
907                  case SPECIAL_MULT:                  case SPECIAL_MULT:
# Line 985  int mips_cpu_disassemble_instr(struct cp Line 926  int mips_cpu_disassemble_instr(struct cp
926                                  if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {                                  if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
927                                          if (special6 == SPECIAL_MULT ||                                          if (special6 == SPECIAL_MULT ||
928                                              special6 == SPECIAL_MULTU)                                              special6 == SPECIAL_MULTU)
929                                                  debug("%s,",                                                  debug("%s,", regnames[rd]);
                                                     regname(cpu->machine, rd));  
930                                          else                                          else
931                                                  debug("WEIRD_R5900_RD,");                                                  debug("WEIRD_R5900_RD,");
932                                  } else {                                  } else {
933                                          debug("WEIRD_RD_NONZERO,");                                          debug("WEIRD_RD_NONZERO,");
934                                  }                                  }
935                          }                          }
936                          debug("%s", regname(cpu->machine, rs));                          debug("%s", regnames[rs]);
937                          debug(",%s", regname(cpu->machine, rt));                          debug(",%s", regnames[rt]);
938                          break;                          break;
939                  case SPECIAL_SYNC:                  case SPECIAL_SYNC:
940                          imm = ((instr[1] & 7) << 2) + (instr[0] >> 6);                          imm = ((instr[1] & 7) << 2) + (instr[0] >> 6);
# Line 1019  int mips_cpu_disassemble_instr(struct cp Line 959  int mips_cpu_disassemble_instr(struct cp
959                  case SPECIAL_MFSA:                  case SPECIAL_MFSA:
960                          if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {                          if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
961                                  rd = (instr[1] >> 3) & 31;                                  rd = (instr[1] >> 3) & 31;
962                                  debug("mfsa\t%s", regname(cpu->machine, rd));                                  debug("mfsa\t%s", regnames[rd]);
963                          } else {                          } else {
964                                  debug("unimplemented special 0x28");                                  debug("unimplemented special 0x28");
965                          }                          }
# Line 1028  int mips_cpu_disassemble_instr(struct cp Line 968  int mips_cpu_disassemble_instr(struct cp
968                          if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {                          if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
969                                  rs = ((instr[3] & 3) << 3) +                                  rs = ((instr[3] & 3) << 3) +
970                                      ((instr[2] >> 5) & 7);                                      ((instr[2] >> 5) & 7);
971                                  debug("mtsa\t%s", regname(cpu->machine, rs));                                  debug("mtsa\t%s", regnames[rs]);
972                          } else {                          } else {
973                                  debug("unimplemented special 0x29");                                  debug("unimplemented special 0x29");
974                          }                          }
# Line 1062  int mips_cpu_disassemble_instr(struct cp Line 1002  int mips_cpu_disassemble_instr(struct cp
1002                          case HI6_BEQL:                          case HI6_BEQL:
1003                          case HI6_BNE:                          case HI6_BNE:
1004                          case HI6_BNEL:                          case HI6_BNEL:
1005                                  debug("%s,", regname(cpu->machine, rt));                                  debug("%s,", regnames[rt]);
1006                          }                          }
1007                          debug("%s,", regname(cpu->machine, rs));                          debug("%s,", regnames[rs]);
1008                  }                  }
1009    
1010                  if (cpu->is_32bit)                  if (cpu->is_32bit)
# Line 1091  int mips_cpu_disassemble_instr(struct cp Line 1031  int mips_cpu_disassemble_instr(struct cp
1031                  imm = (instr[1] << 8) + instr[0];                  imm = (instr[1] << 8) + instr[0];
1032                  if (imm >= 32768)                  if (imm >= 32768)
1033                          imm -= 65536;                          imm -= 65536;
1034                  debug("%s\t%s,", hi6_names[hi6], regname(cpu->machine, rt));                  debug("%s\t%s,", hi6_names[hi6], regnames[rt]);
1035                  debug("%s,", regname(cpu->machine, rs));                  debug("%s,", regnames[rs]);
1036                  if (hi6 == HI6_ANDI || hi6 == HI6_ORI || hi6 == HI6_XORI)                  if (hi6 == HI6_ANDI || hi6 == HI6_ORI || hi6 == HI6_XORI)
1037                          debug("0x%04x", imm & 0xffff);                          debug("0x%04x", imm & 0xffff);
1038                  else                  else
# Line 1101  int mips_cpu_disassemble_instr(struct cp Line 1041  int mips_cpu_disassemble_instr(struct cp
1041          case HI6_LUI:          case HI6_LUI:
1042                  rt = instr[2] & 31;                  rt = instr[2] & 31;
1043                  imm = (instr[1] << 8) + instr[0];                  imm = (instr[1] << 8) + instr[0];
1044                  debug("lui\t%s,0x%x", regname(cpu->machine, rt), imm);                  debug("lui\t%s,0x%x", regnames[rt], imm);
1045                  break;                  break;
1046          case HI6_LB:          case HI6_LB:
1047          case HI6_LBU:          case HI6_LBU:
# Line 1145  int mips_cpu_disassemble_instr(struct cp Line 1085  int mips_cpu_disassemble_instr(struct cp
1085                  }                  }
1086                  if (hi6 == HI6_SQ_SPECIAL3 &&                  if (hi6 == HI6_SQ_SPECIAL3 &&
1087                      cpu->cd.mips.cpu_type.rev != MIPS_R5900) {                      cpu->cd.mips.cpu_type.rev != MIPS_R5900) {
1088                            int msbd, lsb, sub10;
1089                          special6 = instr[0] & 0x3f;                          special6 = instr[0] & 0x3f;
                         debug("%s", special3_names[special6]);  
1090                          rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);                          rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
1091                          rt = instr[2] & 31;                          rt = instr[2] & 31;
1092                          rd = (instr[1] >> 3) & 31;                          rd = msbd = (instr[1] >> 3) & 31;
1093                            lsb = ((instr[1] & 7) << 2) | (instr[0] >> 6);
1094                            sub10 = (rs << 5) | lsb;
1095    
1096                          switch (special6) {                          switch (special6) {
1097    
1098                            case SPECIAL3_EXT:
1099                            case SPECIAL3_DEXT:
1100                            case SPECIAL3_DEXTM:
1101                            case SPECIAL3_DEXTU:
1102                                    debug("%s", special3_names[special6]);
1103                                    if (special6 == SPECIAL3_DEXTM)
1104                                            msbd += 32;
1105                                    if (special6 == SPECIAL3_DEXTU)
1106                                            lsb += 32;
1107                                    debug("\t%s", regnames[rt]);
1108                                    debug(",%s", regnames[rs]);
1109                                    debug(",%i,%i", lsb, msbd + 1);
1110                                    break;
1111    
1112                            case SPECIAL3_INS:
1113                            case SPECIAL3_DINS:
1114                            case SPECIAL3_DINSM:
1115                            case SPECIAL3_DINSU:
1116                                    debug("%s", special3_names[special6]);
1117                                    if (special6 == SPECIAL3_DINSM)
1118                                            msbd += 32;
1119                                    if (special6 == SPECIAL3_DINSU) {
1120                                            lsb += 32;
1121                                            msbd += 32;
1122                                    }
1123                                    msbd -= lsb;
1124                                    debug("\t%s", regnames[rt]);
1125                                    debug(",%s", regnames[rs]);
1126                                    debug(",%i,%i", lsb, msbd + 1);
1127                                    break;
1128    
1129                            case SPECIAL3_BSHFL:
1130                                    switch (sub10) {
1131                                    case BSHFL_WSBH:
1132                                    case BSHFL_SEB:
1133                                    case BSHFL_SEH:
1134                                            switch (sub10) {
1135                                            case BSHFL_WSBH: debug("wsbh"); break;
1136                                            case BSHFL_SEB:  debug("seb"); break;
1137                                            case BSHFL_SEH:  debug("seh"); break;
1138                                            }
1139                                            debug("\t%s", regnames[rd]);
1140                                            debug(",%s", regnames[rt]);
1141                                            break;
1142                                    default:debug("%s", special3_names[special6]);
1143                                            debug("\t(UNIMPLEMENTED)");
1144                                    }
1145                                    break;
1146    
1147                            case SPECIAL3_DBSHFL:
1148                                    switch (sub10) {
1149                                    case BSHFL_DSBH:
1150                                    case BSHFL_DSHD:
1151                                            switch (sub10) {
1152                                            case BSHFL_DSBH: debug("dsbh"); break;
1153                                            case BSHFL_DSHD: debug("dshd"); break;
1154                                            }
1155                                            debug("\t%s", regnames[rd]);
1156                                            debug(",%s", regnames[rt]);
1157                                            break;
1158                                    default:debug("%s", special3_names[special6]);
1159                                            debug("\t(UNIMPLEMENTED)");
1160                                    }
1161                                    break;
1162    
1163                          case SPECIAL3_RDHWR:                          case SPECIAL3_RDHWR:
1164                                  debug("\t%s", regname(cpu->machine, rt));                                  debug("%s", special3_names[special6]);
1165                                    debug("\t%s", regnames[rt]);
1166                                  debug(",hwr%i", rd);                                  debug(",hwr%i", rd);
1167                                  break;                                  break;
1168    
1169                          default:                          default:debug("%s", special3_names[special6]);
1170                                  debug("\t(UNIMPLEMENTED)");                                  debug("\t(UNIMPLEMENTED)");
1171                          }                          }
1172                          break;                          break;
# Line 1176  int mips_cpu_disassemble_instr(struct cp Line 1184  int mips_cpu_disassemble_instr(struct cp
1184                  /*  TODO: Which ISAs? IV? V? 32? 64?  */                  /*  TODO: Which ISAs? IV? V? 32? 64?  */
1185                  if (cpu->cd.mips.cpu_type.isa_level >= 4 && hi6 == HI6_LWC3) {                  if (cpu->cd.mips.cpu_type.isa_level >= 4 && hi6 == HI6_LWC3) {
1186                          debug("pref\t0x%x,%i(%s)",                          debug("pref\t0x%x,%i(%s)",
1187                              rt, imm, regname(cpu->machine, rs));                              rt, imm, regnames[rs]);
1188    
1189                          if (running) {                          if (running) {
1190                                  debug("\t[0x%016"PRIx64" = %s]",                                  debug("\t[0x%016"PRIx64" = %s]",
# Line 1196  int mips_cpu_disassemble_instr(struct cp Line 1204  int mips_cpu_disassemble_instr(struct cp
1204                      hi6 == HI6_LDC1 || hi6 == HI6_LDC2)                      hi6 == HI6_LDC1 || hi6 == HI6_LDC2)
1205                          debug("r%i", rt);                          debug("r%i", rt);
1206                  else                  else
1207                          debug("%s", regname(cpu->machine, rt));                          debug("%s", regnames[rt]);
1208    
1209                  debug(",%i(%s)", imm, regname(cpu->machine, rs));                  debug(",%i(%s)", imm, regnames[rs]);
1210    
1211                  if (running) {                  if (running) {
1212                          debug("\t[");                          debug("\t[");
# Line 1258  int mips_cpu_disassemble_instr(struct cp Line 1266  int mips_cpu_disassemble_instr(struct cp
1266                  cache_op    = copz >> 2;                  cache_op    = copz >> 2;
1267                  which_cache = copz & 3;                  which_cache = copz & 3;
1268                  showtag = 0;                  showtag = 0;
1269                  debug("cache\t0x%02x,0x%04x(%s)", copz, imm,                  debug("cache\t0x%02x,0x%04x(%s)", copz, imm, regnames[rt]);
                     regname(cpu->machine, rt));  
1270                  if (which_cache==0)     debug("  [ primary I-cache");                  if (which_cache==0)     debug("  [ primary I-cache");
1271                  if (which_cache==1)     debug("  [ primary D-cache");                  if (which_cache==1)     debug("  [ primary D-cache");
1272                  if (which_cache==2)     debug("  [ secondary I-cache");                  if (which_cache==2)     debug("  [ secondary I-cache");
# Line 1270  int mips_cpu_disassemble_instr(struct cp Line 1277  int mips_cpu_disassemble_instr(struct cp
1277                  if (cache_op==2)        debug("index store tag"), showtag=1;                  if (cache_op==2)        debug("index store tag"), showtag=1;
1278                  if (cache_op==3)        debug("create dirty exclusive");                  if (cache_op==3)        debug("create dirty exclusive");
1279                  if (cache_op==4)        debug("hit invalidate");                  if (cache_op==4)        debug("hit invalidate");
1280                  if (cache_op==5)        debug("fill OR hit writeback invalidate");                  if (cache_op==5)     debug("fill OR hit writeback invalidate");
1281                  if (cache_op==6)        debug("hit writeback");                  if (cache_op==6)        debug("hit writeback");
1282                  if (cache_op==7)        debug("hit set virtual");                  if (cache_op==7)        debug("hit set virtual");
1283                  if (running)                  if (running)
# Line 1302  int mips_cpu_disassemble_instr(struct cp Line 1309  int mips_cpu_disassemble_instr(struct cp
1309                          case MMI_MADD:                          case MMI_MADD:
1310                          case MMI_MADDU:                          case MMI_MADDU:
1311                                  if (rd != MIPS_GPR_ZERO) {                                  if (rd != MIPS_GPR_ZERO) {
1312                                          debug("%s,", regname(cpu->machine, rd));                                          debug("%s,", regnames[rd]);
1313                                  }                                  }
1314                                  debug("%s", regname(cpu->machine, rs));                                  debug("%s,%s", regnames[rs], regnames[rt]);
                                 debug(",%s", regname(cpu->machine, rt));  
1315                                  break;                                  break;
1316    
1317                          case MMI_MMI0:                          case MMI_MMI0:
# Line 1320  int mips_cpu_disassemble_instr(struct cp Line 1326  int mips_cpu_disassemble_instr(struct cp
1326                                  case MMI0_PPACB:                                  case MMI0_PPACB:
1327                                  case MMI0_PPACH:                                  case MMI0_PPACH:
1328                                  case MMI0_PPACW:                                  case MMI0_PPACW:
1329                                          debug("%s", regname(cpu->machine, rd));                                          debug("%s,%s,%s", regnames[rd],
1330                                          debug(",%s", regname(cpu->machine, rs));                                              regnames[rs], regnames[rt]);
                                         debug(",%s", regname(cpu->machine, rt));  
1331                                          break;                                          break;
1332    
1333                                  default:debug("(UNIMPLEMENTED)");                                  default:debug("(UNIMPLEMENTED)");
# Line 1338  int mips_cpu_disassemble_instr(struct cp Line 1343  int mips_cpu_disassemble_instr(struct cp
1343                                  case MMI1_PEXTUW:                                  case MMI1_PEXTUW:
1344                                  case MMI1_PMINH:                                  case MMI1_PMINH:
1345                                  case MMI1_PMINW:                                  case MMI1_PMINW:
1346                                          debug("%s", regname(cpu->machine, rd));                                          debug("%s,%s,%s", regnames[rd],
1347                                          debug(",%s", regname(cpu->machine, rs));                                              regnames[rs], regnames[rt]);
                                         debug(",%s", regname(cpu->machine, rt));  
1348                                          break;                                          break;
1349    
1350                                  default:debug("(UNIMPLEMENTED)");                                  default:debug("(UNIMPLEMENTED)");
# Line 1353  int mips_cpu_disassemble_instr(struct cp Line 1357  int mips_cpu_disassemble_instr(struct cp
1357    
1358                                  case MMI2_PMFHI:                                  case MMI2_PMFHI:
1359                                  case MMI2_PMFLO:                                  case MMI2_PMFLO:
1360                                          debug("%s", regname(cpu->machine, rd));                                          debug("%s", regnames[rd]);
1361                                          break;                                          break;
1362    
1363                                  case MMI2_PHMADH:                                  case MMI2_PHMADH:
# Line 1366  int mips_cpu_disassemble_instr(struct cp Line 1370  int mips_cpu_disassemble_instr(struct cp
1370                                  case MMI2_PMULTH:                                  case MMI2_PMULTH:
1371                                  case MMI2_PMULTW:                                  case MMI2_PMULTW:
1372                                  case MMI2_PSLLVW:                                  case MMI2_PSLLVW:
1373                                          debug("%s", regname(cpu->machine, rd));                                          debug("%s,%s,%s", regnames[rd],
1374                                          debug(",%s", regname(cpu->machine, rs));                                              regnames[rs], regnames[rt]);
                                         debug(",%s", regname(cpu->machine, rt));  
1375                                          break;                                          break;
1376    
1377                                  default:debug("(UNIMPLEMENTED)");                                  default:debug("(UNIMPLEMENTED)");
# Line 1381  int mips_cpu_disassemble_instr(struct cp Line 1384  int mips_cpu_disassemble_instr(struct cp
1384    
1385                                  case MMI3_PMTHI:                                  case MMI3_PMTHI:
1386                                  case MMI3_PMTLO:                                  case MMI3_PMTLO:
1387                                          debug("%s", regname(cpu->machine, rs));                                          debug("%s", regnames[rs]);
1388                                          break;                                          break;
1389    
1390                                  case MMI3_PINTEH:                                  case MMI3_PINTEH:
# Line 1390  int mips_cpu_disassemble_instr(struct cp Line 1393  int mips_cpu_disassemble_instr(struct cp
1393                                  case MMI3_PNOR:                                  case MMI3_PNOR:
1394                                  case MMI3_POR:                                  case MMI3_POR:
1395                                  case MMI3_PSRAVW:                                  case MMI3_PSRAVW:
1396                                          debug("%s", regname(cpu->machine, rd));                                          debug("%s,%s,%s", regnames[rd],
1397                                          debug(",%s", regname(cpu->machine, rs));                                              regnames[rs], regnames[rt]);
                                         debug(",%s", regname(cpu->machine, rt));  
1398                                          break;                                          break;
1399    
1400                                  default:debug("(UNIMPLEMENTED)");                                  default:debug("(UNIMPLEMENTED)");
# Line 1415  int mips_cpu_disassemble_instr(struct cp Line 1417  int mips_cpu_disassemble_instr(struct cp
1417                  case SPECIAL2_MSUBU:                  case SPECIAL2_MSUBU:
1418                          if (rd != MIPS_GPR_ZERO) {                          if (rd != MIPS_GPR_ZERO) {
1419                                  debug("WEIRD_NONZERO_RD(%s),",                                  debug("WEIRD_NONZERO_RD(%s),",
1420                                      regname(cpu->machine, rd));                                      regnames[rd]);
1421                          }                          }
1422                          debug("%s", regname(cpu->machine, rs));                          debug("%s,%s", regnames[rs], regnames[rt]);
                         debug(",%s", regname(cpu->machine, rt));  
1423                          break;                          break;
1424    
1425                  case SPECIAL2_MUL:                  case SPECIAL2_MUL:
1426                          /*  Apparently used both on R5900 and MIPS32:  */                          /*  Apparently used both on R5900 and MIPS32:  */
1427                          debug("%s", regname(cpu->machine, rd));                          debug("%s,%s,%s", regnames[rd],
1428                          debug(",%s", regname(cpu->machine, rs));                              regnames[rs], regnames[rt]);
                         debug(",%s", regname(cpu->machine, rt));  
1429                          break;                          break;
1430    
1431                  case SPECIAL2_CLZ:                  case SPECIAL2_CLZ:
1432                  case SPECIAL2_CLO:                  case SPECIAL2_CLO:
1433                  case SPECIAL2_DCLZ:                  case SPECIAL2_DCLZ:
1434                  case SPECIAL2_DCLO:                  case SPECIAL2_DCLO:
1435                          debug("%s", regname(cpu->machine, rd));                          debug("%s,%s", regnames[rd], regnames[rs]);
                         debug(",%s", regname(cpu->machine, rs));  
1436                          break;                          break;
1437    
1438                  default:                  default:
# Line 1443  int mips_cpu_disassemble_instr(struct cp Line 1442  int mips_cpu_disassemble_instr(struct cp
1442    
1443          case HI6_REGIMM:          case HI6_REGIMM:
1444                  regimm5 = instr[2] & 0x1f;                  regimm5 = instr[2] & 0x1f;
1445                    rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
1446                    imm = (instr[1] << 8) + instr[0];
1447                    if (imm >= 32768)              
1448                            imm -= 65536;
1449    
1450                  switch (regimm5) {                  switch (regimm5) {
1451    
1452                  case REGIMM_BLTZ:                  case REGIMM_BLTZ:
1453                  case REGIMM_BGEZ:                  case REGIMM_BGEZ:
1454                  case REGIMM_BLTZL:                  case REGIMM_BLTZL:
# Line 1452  int mips_cpu_disassemble_instr(struct cp Line 1457  int mips_cpu_disassemble_instr(struct cp
1457                  case REGIMM_BLTZALL:                  case REGIMM_BLTZALL:
1458                  case REGIMM_BGEZAL:                  case REGIMM_BGEZAL:
1459                  case REGIMM_BGEZALL:                  case REGIMM_BGEZALL:
1460                          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));  
1461    
1462                          addr = (dumpaddr + 4) + (imm << 2);                          addr = (dumpaddr + 4) + (imm << 2);
1463    
# Line 1467  int mips_cpu_disassemble_instr(struct cp Line 1466  int mips_cpu_disassemble_instr(struct cp
1466                          else                          else
1467                                  debug("0x%016"PRIx64, (uint64_t) addr);                                  debug("0x%016"PRIx64, (uint64_t) addr);
1468                          break;                          break;
1469    
1470                    case REGIMM_SYNCI:
1471                            debug("%s\t%i(%s)", regimm_names[regimm5],
1472                                imm, regnames[rs]);
1473                            break;
1474    
1475                  default:                  default:
1476                          debug("unimplemented regimm5 = 0x%02x", regimm5);                          debug("unimplemented regimm5 = 0x%02x", regimm5);
1477                  }                  }
# Line 1544  void mips_cpu_register_dump(struct cpu * Line 1549  void mips_cpu_register_dump(struct cpu *
1549                                              "          ");                                              "          ");
1550                                  else                                  else
1551                                          debug(" %3s=%016"PRIx64"%016"PRIx64,                                          debug(" %3s=%016"PRIx64"%016"PRIx64,
1552                                              regname(cpu->machine, r),                                              regnames[r], (uint64_t)
1553                                              (uint64_t)cpu->cd.mips.gpr_quadhi[r],                                              cpu->cd.mips.gpr_quadhi[r],
1554                                              (uint64_t)cpu->cd.mips.gpr[r]);                                              (uint64_t)cpu->cd.mips.gpr[r]);
1555                                  if ((i & 1) == 1)                                  if ((i & 1) == 1)
1556                                          debug("\n");                                          debug("\n");
# Line 1558  void mips_cpu_register_dump(struct cpu * Line 1563  void mips_cpu_register_dump(struct cpu *
1563                                  if (i == MIPS_GPR_ZERO)                                  if (i == MIPS_GPR_ZERO)
1564                                          debug("               ");                                          debug("               ");
1565                                  else                                  else
1566                                          debug(" %3s = %08"PRIx32,                                          debug(" %3s = %08"PRIx32, regnames[i],
                                             regname(cpu->machine, i),  
1567                                              (uint32_t)cpu->cd.mips.gpr[i]);                                              (uint32_t)cpu->cd.mips.gpr[i]);
1568                                  if ((i & 3) == 3)                                  if ((i & 3) == 3)
1569                                          debug("\n");                                          debug("\n");
# Line 1574  void mips_cpu_register_dump(struct cpu * Line 1578  void mips_cpu_register_dump(struct cpu *
1578                                          debug("                           ");                                          debug("                           ");
1579                                  else                                  else
1580                                          debug("   %3s = 0x%016"PRIx64,                                          debug("   %3s = 0x%016"PRIx64,
1581                                              regname(cpu->machine, r),                                              regnames[r],
1582                                              (uint64_t)cpu->cd.mips.gpr[r]);                                              (uint64_t)cpu->cd.mips.gpr[r]);
1583                                  if ((i & 1) == 1)                                  if ((i & 1) == 1)
1584                                          debug("\n");                                          debug("\n");
# Line 1597  void mips_cpu_register_dump(struct cpu * Line 1601  void mips_cpu_register_dump(struct cpu *
1601                  }                  }
1602    
1603                  /*  Coprocessor registers:  */                  /*  Coprocessor registers:  */
                 /*  TODO: multiple selections per register?  */  
1604                  for (i=0; i<32; i++) {                  for (i=0; i<32; i++) {
1605                          /*  32-bit:  */                          /*  32-bit:  */
1606                          if ((i & nm1) == 0)                          if ((i & nm1) == 0)
1607                                  debug("cpu%i:", cpu->cpu_id);                                  debug("cpu%i:", cpu->cpu_id);
1608    
1609                          if (cpu->machine->show_symbolic_register_names &&                          if (coprocnr == 0)
                             coprocnr == 0)  
1610                                  debug(" %8s", cop0_names[i]);                                  debug(" %8s", cop0_names[i]);
1611                          else                          else
1612                                  debug(" c%i,%02i", coprocnr, i);                                  debug(" c%i,%02i", coprocnr, i);
1613    
1614                          if (bits32)                          if (bits32)
1615                                  debug("=%08x", (int)cpu->cd.mips.coproc[coprocnr]->reg[i]);                                  debug("=%08x", (int)cpu->cd.mips.
1616                                        coproc[coprocnr]->reg[i]);
1617                          else {                          else {
1618                                  if (coprocnr == 0 && (i == COP0_COUNT                                  if (coprocnr == 0 && (i == COP0_COUNT
1619                                      || i == COP0_COMPARE || i == COP0_INDEX                                      || i == COP0_COMPARE || i == COP0_INDEX
1620                                      || i == COP0_RANDOM || i == COP0_WIRED))                                      || i == COP0_RANDOM || i == COP0_WIRED))
1621                                          debug(" =         0x%08x", (int)cpu->cd.mips.coproc[coprocnr]->reg[i]);                                          debug(" =         0x%08x",
1622                                                (int) cpu->cd.mips.coproc[
1623                                                coprocnr]->reg[i]);
1624                                  else                                  else
1625                                          debug(" = 0x%016"PRIx64, (uint64_t)                                          debug(" = 0x%016"PRIx64, (uint64_t)
1626                                              cpu->cd.mips.coproc[coprocnr]->reg[i]);                                              cpu->cd.mips.coproc[
1627                                                coprocnr]->reg[i]);
1628                          }                          }
1629    
1630                          if ((i & nm1) == nm1)                          if ((i & nm1) == nm1)
# Line 1634  void mips_cpu_register_dump(struct cpu * Line 1640  void mips_cpu_register_dump(struct cpu *
1640                          debug("cpu%i: ", cpu->cpu_id);                          debug("cpu%i: ", cpu->cpu_id);
1641                          debug("config_select1 = 0x");                          debug("config_select1 = 0x");
1642                          if (cpu->is_32bit)                          if (cpu->is_32bit)
1643                                  debug("%08"PRIx32, (uint32_t)cpu->cd.mips.cop0_config_select1);                                  debug("%08"PRIx32,
1644                                        (uint32_t)cpu->cd.mips.cop0_config_select1);
1645                          else                          else
1646                                  debug("%016"PRIx64, (uint64_t)cpu->cd.mips.cop0_config_select1);                                  debug("%016"PRIx64,
1647                                        (uint64_t)cpu->cd.mips.cop0_config_select1);
1648                          debug("\n");                          debug("\n");
1649                  }                  }
1650    
# Line 1670  void mips_cpu_register_dump(struct cpu * Line 1678  void mips_cpu_register_dump(struct cpu *
1678  }  }
1679    
1680    
 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);  
 }  
   
   
1681  /*  /*
1682   *  mips_cpu_gdb_stub():   *  mips_cpu_interrupt_assert(), mips_cpu_interrupt_deassert():
1683   *   *
1684   *  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
1685     *  in the CAUSE register of coprocessor 0.
1686   */   */
1687  char *mips_cpu_gdb_stub(struct cpu *cpu, char *cmd)  void mips_cpu_interrupt_assert(struct interrupt *interrupt)
1688  {  {
1689          if (strcmp(cmd, "g") == 0) {          struct cpu *cpu = interrupt->extra;
1690                  /*  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;  
1691  }  }
1692    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)  
1693  {  {
1694          if (irq_nr >= 8) {          struct cpu *cpu = interrupt->extra;
1695                  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;  
1696  }  }
1697    
1698    
# Line 1873  void mips_cpu_exception(struct cpu *cpu, Line 1718  void mips_cpu_exception(struct cpu *cpu,
1718          uint64_t *reg = &cpu->cd.mips.coproc[0]->reg[0];          uint64_t *reg = &cpu->cd.mips.coproc[0]->reg[0];
1719          int exc_model = cpu->cd.mips.cpu_type.exc_model;          int exc_model = cpu->cd.mips.cpu_type.exc_model;
1720    
1721            if (cpu->is_halted) {
1722                    /*
1723                     *  If the exception occurred on a 'wait' instruction, then let
1724                     *  the instruction following the wait instruction be the one
1725                     *  we continue at when the interrupt service routine returns.
1726                     */
1727                    cpu->is_halted = 0;
1728                    cpu->pc += sizeof(uint32_t);
1729            }
1730    
1731          if (!quiet_mode) {          if (!quiet_mode) {
1732                  uint64_t offset;                  uint64_t offset;
1733                  int x;                  int x;
# Line 1889  void mips_cpu_exception(struct cpu *cpu, Line 1744  void mips_cpu_exception(struct cpu *cpu,
1744                  switch (exccode) {                  switch (exccode) {
1745    
1746                  case EXCEPTION_INT:                  case EXCEPTION_INT:
1747                          debug(" cause_im=0x%02x", (int)((reg[COP0_CAUSE] & CAUSE_IP_MASK) >> CAUSE_IP_SHIFT));                          debug(" cause_im=0x%02x", (int)
1748                                ((reg[COP0_CAUSE] & CAUSE_IP_MASK)
1749                                >> CAUSE_IP_SHIFT));
1750                          break;                          break;
1751    
1752                  case EXCEPTION_SYS:                  case EXCEPTION_SYS:
# Line 1979  void mips_cpu_exception(struct cpu *cpu, Line 1836  void mips_cpu_exception(struct cpu *cpu,
1836    
1837                  if (exc_model == EXC3K) {                  if (exc_model == EXC3K) {
1838                          reg[COP0_CONTEXT] &= ~R2K3K_CONTEXT_BADVPN_MASK;                          reg[COP0_CONTEXT] &= ~R2K3K_CONTEXT_BADVPN_MASK;
1839                          reg[COP0_CONTEXT] |= ((vaddr_vpn2 << R2K3K_CONTEXT_BADVPN_SHIFT) & R2K3K_CONTEXT_BADVPN_MASK);                          reg[COP0_CONTEXT] |= ((vaddr_vpn2 <<
1840                                R2K3K_CONTEXT_BADVPN_SHIFT) &
1841                                R2K3K_CONTEXT_BADVPN_MASK);
1842    
1843                          reg[COP0_ENTRYHI] = (vaddr & R2K3K_ENTRYHI_VPN_MASK)                          reg[COP0_ENTRYHI] = (vaddr & R2K3K_ENTRYHI_VPN_MASK)
1844                              | (vaddr_asid << R2K3K_ENTRYHI_ASID_SHIFT);                              | (vaddr_asid << R2K3K_ENTRYHI_ASID_SHIFT);
# Line 1989  void mips_cpu_exception(struct cpu *cpu, Line 1848  void mips_cpu_exception(struct cpu *cpu,
1848                          reg[COP0_ENTRYHI] = (int64_t)(int32_t)reg[COP0_ENTRYHI];                          reg[COP0_ENTRYHI] = (int64_t)(int32_t)reg[COP0_ENTRYHI];
1849                  } else {                  } else {
1850                          if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {                          if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
1851                                  reg[COP0_CONTEXT] &= ~CONTEXT_BADVPN2_MASK_R4100;                                  reg[COP0_CONTEXT] &=
1852                                  reg[COP0_CONTEXT] |= ((vaddr_vpn2 << CONTEXT_BADVPN2_SHIFT) & CONTEXT_BADVPN2_MASK_R4100);                                      ~CONTEXT_BADVPN2_MASK_R4100;
1853                                    reg[COP0_CONTEXT] |= ((vaddr_vpn2 <<
1854                                        CONTEXT_BADVPN2_SHIFT) &
1855                                        CONTEXT_BADVPN2_MASK_R4100);
1856    
1857                                  /*  TODO:  fix these  */                                  /*  TODO:  fix these  */
1858                                  reg[COP0_XCONTEXT] &= ~XCONTEXT_R_MASK;                                  reg[COP0_XCONTEXT] &= ~XCONTEXT_R_MASK;
# Line 2030  void mips_cpu_exception(struct cpu *cpu, Line 1892  void mips_cpu_exception(struct cpu *cpu,
1892                  /*  debug("[ warning: cpu%i exception while EXL is set,"                  /*  debug("[ warning: cpu%i exception while EXL is set,"
1893                      " not setting EPC ]\n", cpu->cpu_id);  */                      " not setting EPC ]\n", cpu->cpu_id);  */
1894          } else {          } else {
1895                  if (cpu->delay_slot || cpu->cd.mips.nullify_next) {                  if (cpu->delay_slot) {
1896                          reg[COP0_EPC] = cpu->pc - 4;                          reg[COP0_EPC] = cpu->pc - 4;
1897                          reg[COP0_CAUSE] |= CAUSE_BD;                          reg[COP0_CAUSE] |= CAUSE_BD;
   
                         /*  TODO: Should the BD flag actually be set  
                             on nullified slots?  */  
1898                  } else {                  } else {
1899                          reg[COP0_EPC] = cpu->pc;                          reg[COP0_EPC] = cpu->pc;
1900                          reg[COP0_CAUSE] &= ~CAUSE_BD;                          reg[COP0_CAUSE] &= ~CAUSE_BD;
# Line 2047  void mips_cpu_exception(struct cpu *cpu, Line 1906  void mips_cpu_exception(struct cpu *cpu,
1906          else          else
1907                  cpu->delay_slot = NOT_DELAYED;                  cpu->delay_slot = NOT_DELAYED;
1908    
         cpu->cd.mips.nullify_next = 0;  
   
1909          /*  TODO: This is true for MIPS64, but how about others?  */          /*  TODO: This is true for MIPS64, but how about others?  */
1910          if (reg[COP0_STATUS] & STATUS_BEV)          if (reg[COP0_STATUS] & STATUS_BEV)
1911                  base = 0xffffffffbfc00200ULL;                  base = 0xffffffffbfc00200ULL;

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

  ViewVC Help
Powered by ViewVC 1.1.26