/[gxemul]/trunk/src/cpu.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /trunk/src/cpu.c

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

revision 22 by dpavlin, Mon Oct 8 16:19:37 2007 UTC revision 26 by dpavlin, Mon Oct 8 16:20:10 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: cpu.c,v 1.329 2006/01/16 04:48:08 debug Exp $   *  $Id: cpu.c,v 1.344 2006/06/24 21:47:22 debug Exp $
29   *   *
30   *  Common routines for CPU emulation. (Not specific to any CPU type.)   *  Common routines for CPU emulation. (Not specific to any CPU type.)
31   */   */
# Line 43  Line 43 
43    
44    
45  extern int quiet_mode;  extern int quiet_mode;
 extern int show_opcode_statistics;  
 extern int dyntrans_backend_enable;  
46    
47  static struct cpu_family *first_cpu_family = NULL;  static struct cpu_family *first_cpu_family = NULL;
48    
# Line 98  struct cpu *cpu_new(struct memory *mem, Line 96  struct cpu *cpu_new(struct memory *mem,
96                                              "NULL\n");                                              "NULL\n");
97                                          exit(1);                                          exit(1);
98                                  }                                  }
99                                  return cpu;                                  break;
100                          }                          }
101                  }                  }
102    
103                  fp = fp->next;                  fp = fp->next;
104          }          }
105    
106          fatal("\ncpu_new(): unknown cpu type '%s'\n", cpu_type_name);          if (fp == NULL) {
107          exit(1);                  fatal("\ncpu_new(): unknown cpu type '%s'\n", cpu_type_name);
108  }                  return NULL;
109            }
110    
111            fp->init_tables(cpu);
112    
113  /*          return cpu;
  *  cpu_show_full_statistics():  
  *  
  *  Show detailed statistics on opcode usage on each cpu.  
  */  
 void cpu_show_full_statistics(struct machine *m)  
 {  
         if (m->cpu_family == NULL ||  
             m->cpu_family->show_full_statistics == NULL)  
                 fatal("cpu_show_full_statistics(): NULL\n");  
         else  
                 m->cpu_family->show_full_statistics(m);  
114  }  }
115    
116    
# Line 166  void cpu_register_match(struct machine * Line 155  void cpu_register_match(struct machine *
155   *  tracing.   *  tracing.
156   */   */
157  int cpu_disassemble_instr(struct machine *m, struct cpu *cpu,  int cpu_disassemble_instr(struct machine *m, struct cpu *cpu,
158          unsigned char *instr, int running, uint64_t addr, int bintrans)          unsigned char *instr, int running, uint64_t addr)
159  {  {
160          if (m->cpu_family == NULL || m->cpu_family->disassemble_instr == NULL) {          if (m->cpu_family == NULL || m->cpu_family->disassemble_instr == NULL) {
161                  fatal("cpu_disassemble_instr(): NULL\n");                  fatal("cpu_disassemble_instr(): NULL\n");
162                  return 0;                  return 0;
163          } else          } else
164                  return m->cpu_family->disassemble_instr(cpu, instr,                  return m->cpu_family->disassemble_instr(cpu, instr,
165                      running, addr, bintrans);                      running, addr);
166  }  }
167    
168    
# Line 196  void cpu_register_dump(struct machine *m Line 185  void cpu_register_dump(struct machine *m
185    
186    
187  /*  /*
188     *  cpu_gdb_stub():
189     *
190     *  Execute a "remote GDB" command. Return value is a pointer to a newly
191     *  allocated response string, if the command was successfully executed. If
192     *  there was an error, NULL is returned.
193     */
194    char *cpu_gdb_stub(struct cpu *cpu, char *cmd)
195    {
196            if (cpu->machine->cpu_family == NULL ||
197                cpu->machine->cpu_family->gdb_stub == NULL) {
198                    fatal("cpu_gdb_stub(): NULL\n");
199                    return NULL;
200            } else
201                    return cpu->machine->cpu_family->gdb_stub(cpu, cmd);
202    }
203    
204    
205    /*
206   *  cpu_interrupt():   *  cpu_interrupt():
207   *   *
208   *  Assert an interrupt.   *  Assert an interrupt.
# Line 257  void cpu_functioncall_trace(struct cpu * Line 264  void cpu_functioncall_trace(struct cpu *
264                  fatal("%s", symbol);                  fatal("%s", symbol);
265          else {          else {
266                  if (cpu->is_32bit)                  if (cpu->is_32bit)
267                          fatal("0x%08x", (int)f);                          fatal("0x%"PRIx32, (uint32_t) f);
268                  else                  else
269                          fatal("0x%llx", (long long)f);                          fatal("0x%"PRIx64, (uint64_t) f);
270          }          }
271          fatal("(");          fatal("(");
272    
# Line 267  void cpu_functioncall_trace(struct cpu * Line 274  void cpu_functioncall_trace(struct cpu *
274                  cpu->machine->cpu_family->functioncall_trace(cpu, f, n_args);                  cpu->machine->cpu_family->functioncall_trace(cpu, f, n_args);
275    
276          fatal(")>\n");          fatal(")>\n");
277    
278    #ifdef PRINT_MEMORY_CHECKSUM
279            /*  Temporary hack for finding bugs:  */
280            fatal("call chksum=%016"PRIx64"\n", memory_checksum(cpu->mem));
281    #endif
282  }  }
283    
284    
# Line 297  void cpu_create_or_reset_tc(struct cpu * Line 309  void cpu_create_or_reset_tc(struct cpu *
309  {  {
310          size_t s = DYNTRANS_CACHE_SIZE + DYNTRANS_CACHE_MARGIN;          size_t s = DYNTRANS_CACHE_SIZE + DYNTRANS_CACHE_MARGIN;
311    
312          if (cpu->translation_cache == NULL) {          if (cpu->translation_cache == NULL)
313  #ifdef DYNTRANS_BACKEND                  cpu->translation_cache = zeroed_alloc(s);
                 if (dyntrans_backend_enable) {  
                         cpu->translation_cache = (unsigned char *) mmap(NULL,  
                             s, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON |  
                             MAP_PRIVATE, -1, 0);  
                         if (cpu->translation_cache == NULL) {  
                                 dyntrans_backend_enable = 0;  
                                 fatal("%\n%  WARNING! Dyntrans backend disabled"  
                                     ", because mmap() failed.\n%\n");  
                         }  
                 }  
 #endif  
                 if (cpu->translation_cache == NULL)  
                         cpu->translation_cache = zeroed_alloc(s);  
         }  
314    
315          /*  Create an empty table at the beginning of the translation cache:  */          /*  Create an empty table at the beginning of the translation cache:  */
316          memset(cpu->translation_cache, 0, sizeof(uint32_t)          memset(cpu->translation_cache, 0, sizeof(uint32_t)
# Line 331  void cpu_create_or_reset_tc(struct cpu * Line 329  void cpu_create_or_reset_tc(struct cpu *
329    
330    
331  /*  /*
  *  cpu_run():  
  *  
  *  Run instructions on all CPUs in this machine, for a "medium duration"  
  *  (or until all CPUs have halted).  
  *  
  *  Return value is 1 if anything happened, 0 if all CPUs are stopped.  
  */  
 int cpu_run(struct emul *emul, struct machine *m)  
 {  
         if (m->cpu_family == NULL || m->cpu_family->run == NULL) {  
                 fatal("cpu_run(): NULL\n");  
                 return 0;  
         } else  
                 return m->cpu_family->run(emul, m);  
 }  
   
   
 /*  
332   *  cpu_dumpinfo():   *  cpu_dumpinfo():
333   *   *
334   *  Dumps info about a CPU using debug(). "cpu0: CPUNAME, running" (or similar)   *  Dumps info about a CPU using debug(). "cpu0: CPUNAME, running" (or similar)
# Line 425  void cpu_run_deinit(struct machine *mach Line 405  void cpu_run_deinit(struct machine *mach
405          if (machine->show_nr_of_instructions || !quiet_mode)          if (machine->show_nr_of_instructions || !quiet_mode)
406                  cpu_show_cycles(machine, 1);                  cpu_show_cycles(machine, 1);
407    
         if (show_opcode_statistics)  
                 cpu_show_full_statistics(machine);  
   
408          fflush(stdout);          fflush(stdout);
409  }  }
410    
# Line 446  void cpu_show_cycles(struct machine *mac Line 423  void cpu_show_cycles(struct machine *mac
423          char *symbol;          char *symbol;
424          int64_t mseconds, ninstrs, is, avg;          int64_t mseconds, ninstrs, is, avg;
425          struct timeval tv;          struct timeval tv;
426          int h, m, s, ms, d, instrs_per_cycle = 1;          int h, m, s, ms, d;
427    
428          static int64_t mseconds_last = 0;          static int64_t mseconds_last = 0;
429          static int64_t ninstrs_last = -1;          static int64_t ninstrs_last = -1;
430    
         switch (machine->arch) {  
         case ARCH_MIPS:  
                 instrs_per_cycle = machine->cpus[machine->bootstrap_cpu]->  
                     cd.mips.cpu_type.instrs_per_cycle;  
                 break;  
         }  
   
431          pc = machine->cpus[machine->bootstrap_cpu]->pc;          pc = machine->cpus[machine->bootstrap_cpu]->pc;
432    
433          gettimeofday(&tv, NULL);          gettimeofday(&tv, NULL);
# Line 470  void cpu_show_cycles(struct machine *mac Line 440  void cpu_show_cycles(struct machine *mac
440          if (mseconds - mseconds_last == 0)          if (mseconds - mseconds_last == 0)
441                  mseconds ++;                  mseconds ++;
442    
443          ninstrs = machine->ncycles_since_gettimeofday * instrs_per_cycle;          ninstrs = machine->ncycles_since_gettimeofday;
444    
445          if (machine->automatic_clock_adjustment) {          if (machine->automatic_clock_adjustment) {
446                  static int first_adjustment = 1;                  static int first_adjustment = 1;
447    
448                  /*  Current nr of cycles per second:  */                  /*  Current nr of cycles per second:  */
449                  int64_t cur_cycles_per_second = 1000 *                  int64_t cur_cycles_per_second = 1000 *
450                      (ninstrs-ninstrs_last) / (mseconds-mseconds_last)                      (ninstrs-ninstrs_last) / (mseconds-mseconds_last);
451                      / instrs_per_cycle;  
452                    /*  fatal("[ CYCLES PER SECOND = %"PRIi64" ]\n",
453                        cur_cycles_per_second);  */
454    
455                  if (cur_cycles_per_second < 1000000)                  if (cur_cycles_per_second < 1000000)
456                          cur_cycles_per_second = 1000000;                          cur_cycles_per_second = 1000000;
# Line 491  void cpu_show_cycles(struct machine *mac Line 463  void cpu_show_cycles(struct machine *mac
463                              cur_cycles_per_second) / 16;                              cur_cycles_per_second) / 16;
464                  }                  }
465    
466                  /*  debug("[ updating emulated_hz to %lli Hz ]\n",                  /*  fatal("[ updating emulated_hz to %"PRIi64" Hz ]\n",
467                      (long long)machine->emulated_hz);  */                      machine->emulated_hz);  */
468          }          }
469    
470    
# Line 500  void cpu_show_cycles(struct machine *mac Line 472  void cpu_show_cycles(struct machine *mac
472          if (!machine->show_nr_of_instructions && !forced)          if (!machine->show_nr_of_instructions && !forced)
473                  goto do_return;                  goto do_return;
474    
475          printf("[ %lli instrs",          printf("[ %"PRIi64" instrs", (int64_t)machine->ncycles);
             (long long)(machine->ncycles * instrs_per_cycle));  
476    
477          if (!machine->automatic_clock_adjustment) {          if (!machine->automatic_clock_adjustment) {
478                  d = machine->emulated_hz / 1000;                  d = machine->emulated_hz / 1000;
# Line 525  void cpu_show_cycles(struct machine *mac Line 496  void cpu_show_cycles(struct machine *mac
496                  is = 0;                  is = 0;
497          if (avg < 0)          if (avg < 0)
498                  avg = 0;                  avg = 0;
499          printf("; i/s=%lli avg=%lli", (long long)is, (long long)avg);          printf("; i/s=%"PRIi64" avg=%"PRIi64, is, avg);
500    
501          symbol = get_symbol_name(&machine->symbol_context, pc, &offset);          symbol = get_symbol_name(&machine->symbol_context, pc, &offset);
502    
503          if (machine->ncpus == 1) {          if (machine->ncpus == 1) {
504                  if (machine->cpus[machine->bootstrap_cpu]->is_32bit)                  if (machine->cpus[machine->bootstrap_cpu]->is_32bit)
505                          printf("; pc=0x%08x", (int)pc);                          printf("; pc=0x%08"PRIx32, (uint32_t) pc);
506                  else                  else
507                          printf("; pc=0x%016llx", (long long)pc);                          printf("; pc=0x%016"PRIx64, (uint64_t) pc);
508          }          }
509    
510          if (symbol != NULL)          if (symbol != NULL)
# Line 577  void cpu_run_init(struct machine *machin Line 548  void cpu_run_init(struct machine *machin
548          if (machine->a_few_cycles < 1)          if (machine->a_few_cycles < 1)
549                  machine->a_few_cycles = 1;                  machine->a_few_cycles = 1;
550    
551          if (ncpus > 1 && machine->max_random_cycles_per_chunk == 0)          if (ncpus > 1)
552                  machine->a_few_cycles = 1;                  machine->a_few_cycles = 1;
553    
554          /*  debug("cpu_run_init(): a_few_cycles = %i\n",          /*  debug("cpu_run_init(): a_few_cycles = %i\n",
# Line 654  struct cpu_family *cpu_family_ptr_by_num Line 625  struct cpu_family *cpu_family_ptr_by_num
625  }  }
626    
627    
 #ifdef DYNTRANS_BACKEND  
 /*  
  *  cpu_dtb_add_fixup():  
  *  
  *  Add a fixup entry to a currently ongoing dyntrans backend translation.  
  */  
 void cpu_dtb_add_fixup(struct cpu *cpu, int type, void *addr, size_t data)  
 {  
         struct dtb_fixup *fixup = malloc(sizeof (struct dtb_fixup));  
         if (fixup == NULL) {  
                 fprintf(stderr, "out of memory\n"),  
                 exit(1);  
         }  
   
         /*  memset(fixup, 0, sizeof(struct dtb_fixup));  */  
   
         fixup->next = cpu->translation_context.fixups;  
         cpu->translation_context.fixups = fixup;  
   
         fixup->type = type;  
         fixup->addr = addr;  
         fixup->data = data;  
   
         /*  printf("{ fixup added: host addr %p, data=%p }\n", addr,  
             (void *)data);  */  
 }  
   
   
 /*  
  *  cpu_dtb_do_fixups():  
  *  
  *  This function should be called when a chunk of code has been translated,  
  *  and post-fixup is to be applied (i.e. add data which for some reason was  
  *  not included in the generated code).  
  *  
  *  If no fixup is necessary for a specific host platform, then it still needs  
  *  an empty do_fixups routine here (just set done = 1).  
  */  
 void cpu_dtb_do_fixups(struct cpu *cpu)  
 {  
         for (;;) {  
                 int done = 0;  
                 size_t omit_addr;  
   
                 struct dtb_fixup *fixup = cpu->translation_context.fixups;  
                 if (fixup == NULL)  
                         break;  
   
                 cpu->translation_context.fixups = fixup->next;  
   
 #ifdef DYNTRANS_BACKEND_ALPHA  
                 /*  Add the data at the end of the new translation:  */  
 /*printf("%p %p\n", fixup->addr, fixup->data);*/  
                 omit_addr = (size_t)cpu->translation_context.p -  
                     (size_t)cpu->translation_context.translation_buffer;  
 /*printf("omit_addr = %016llx\n", (long long)omit_addr);*/  
                 omit_addr = ((omit_addr - 1) | (sizeof(uint64_t) - 1)) + 1;  
 /*printf("omit_addr = %016llx\n", (long long)omit_addr);*/  
                 {  
                         uint64_t *x = (void *)(omit_addr + (size_t)cpu->  
                             translation_context.translation_buffer);  
                         uint32_t *fixup_instr = (void *)fixup->addr;  
                         size_t ofs = omit_addr;  
                         if (ofs > 0x7fff) {  
                                 fatal("Alpha fixup > 0x7fff!\n");  
                                 exit(1);  
                         }  
                         *x = fixup->data;  
 /*printf("orig instr = 0x%08x\n", *fixup_instr);*/  
                         (*fixup_instr) &= ~0xffff;  
                         (*fixup_instr) |= ofs;  
 /*printf("new instr = 0x%08x\n", *fixup_instr);*/  
                 }  
                 omit_addr += sizeof(uint64_t);  
                 cpu->translation_context.p = (void *)  
                     ((size_t)cpu->translation_context.translation_buffer  
                     + omit_addr);  
                 done = 1;  
 #endif  /*  DYNTRANS_BACKEND_ALPHA  */  
   
                 if (!done)  
                         fatal("!!! cpu_dtb_do_fixups() not implemented yet"  
                             " for this host architecture!\n");  
         }  
 }  
   
 #endif  /*  DYNTRANS_BACKEND  */  
   
   
628  /*  /*
629   *  cpu_init():   *  cpu_init():
630   *   *

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

  ViewVC Help
Powered by ViewVC 1.1.26