/[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 4 by dpavlin, Mon Oct 8 16:18:00 2007 UTC revision 20 by dpavlin, Mon Oct 8 16:19:23 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: cpu.c,v 1.292 2005/04/14 21:01:53 debug Exp $   *  $Id: cpu.c,v 1.323 2005/11/13 22:34:21 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 37  Line 37 
37    
38  #include "cpu.h"  #include "cpu.h"
39  #include "machine.h"  #include "machine.h"
40    #include "memory.h"
41  #include "misc.h"  #include "misc.h"
42    
43    
# Line 56  static struct cpu_family *first_cpu_fami Line 57  static struct cpu_family *first_cpu_fami
57  struct cpu *cpu_new(struct memory *mem, struct machine *machine,  struct cpu *cpu_new(struct memory *mem, struct machine *machine,
58          int cpu_id, char *name)          int cpu_id, char *name)
59  {  {
60          struct cpu *c;          struct cpu *cpu;
61          struct cpu_family *fp;          struct cpu_family *fp;
62          char *cpu_type_name;          char *cpu_type_name;
63    
# Line 71  struct cpu *cpu_new(struct memory *mem, Line 72  struct cpu *cpu_new(struct memory *mem,
72                  exit(1);                  exit(1);
73          }          }
74    
75            cpu = zeroed_alloc(sizeof(struct cpu));
76    
77            cpu->memory_rw          = NULL;
78            cpu->name               = cpu_type_name;
79            cpu->mem                = mem;
80            cpu->machine            = machine;
81            cpu->cpu_id             = cpu_id;
82            cpu->byte_order         = EMUL_LITTLE_ENDIAN;
83            cpu->bootstrap_cpu_flag = 0;
84            cpu->running            = 0;
85    
86            cpu_create_or_reset_tc(cpu);
87    
88          fp = first_cpu_family;          fp = first_cpu_family;
89    
90          while (fp != NULL) {          while (fp != NULL) {
91                  if (fp->cpu_new != NULL) {                  if (fp->cpu_new != NULL) {
92                          c = fp->cpu_new(mem, machine, cpu_id, cpu_type_name);                          if (fp->cpu_new(cpu, mem, machine, cpu_id,
93                          if (c != NULL) {                              cpu_type_name)) {
94                                  /*  Some sanity-checks:  */                                  /*  Sanity check:  */
95                                  if (c->memory_rw == NULL) {                                  if (cpu->memory_rw == NULL) {
96                                          fatal("No memory_rw?\n");                                          fatal("\ncpu_new(): memory_rw == "
97                                                "NULL\n");
98                                          exit(1);                                          exit(1);
99                                  }                                  }
100                                    return cpu;
                                 return c;  
101                          }                          }
102                  }                  }
103    
104                  fp = fp->next;                  fp = fp->next;
105          }          }
106    
107          fprintf(stderr, "cpu_new(): unknown cpu type '%s'\n", cpu_type_name);          fatal("\ncpu_new(): unknown cpu type '%s'\n", cpu_type_name);
108          exit(1);          exit(1);
109  }  }
110    
# Line 167  int cpu_disassemble_instr(struct machine Line 181  int cpu_disassemble_instr(struct machine
181   *   *
182   *  Dump cpu registers in a relatively readable format.   *  Dump cpu registers in a relatively readable format.
183   *   *
184   *  gprs: set to non-zero to dump GPRs. (CPU dependant.)   *  gprs: set to non-zero to dump GPRs. (CPU dependent.)
185   *  coprocs: set bit 0..x to dump registers in coproc 0..x. (CPU dependant.)   *  coprocs: set bit 0..x to dump registers in coproc 0..x. (CPU dependent.)
186   */   */
187  void cpu_register_dump(struct machine *m, struct cpu *cpu,  void cpu_register_dump(struct machine *m, struct cpu *cpu,
188          int gprs, int coprocs)          int gprs, int coprocs)
# Line 215  int cpu_interrupt_ack(struct cpu *cpu, u Line 229  int cpu_interrupt_ack(struct cpu *cpu, u
229    
230    
231  /*  /*
232     *  cpu_functioncall_trace():
233     *
234     *  This function should be called if machine->show_trace_tree is enabled, and
235     *  a function call is being made. f contains the address of the function.
236     */
237    void cpu_functioncall_trace(struct cpu *cpu, uint64_t f)
238    {
239            int i, n_args = -1;
240            char *symbol;
241            uint64_t offset;
242    
243            if (cpu->machine->ncpus > 1)
244                    fatal("cpu%i:\t", cpu->cpu_id);
245    
246            cpu->trace_tree_depth ++;
247            if (cpu->trace_tree_depth > 100)
248                    cpu->trace_tree_depth = 100;
249            for (i=0; i<cpu->trace_tree_depth; i++)
250                    fatal("  ");
251    
252            fatal("<");
253            symbol = get_symbol_name_and_n_args(&cpu->machine->symbol_context,
254                f, &offset, &n_args);
255            if (symbol != NULL)
256                    fatal("%s", symbol);
257            else {
258                    if (cpu->is_32bit)
259                            fatal("0x%08x", (int)f);
260                    else
261                            fatal("0x%llx", (long long)f);
262            }
263            fatal("(");
264    
265            if (cpu->machine->cpu_family->functioncall_trace != NULL)
266                    cpu->machine->cpu_family->functioncall_trace(cpu, f, n_args);
267    
268            fatal(")>\n");
269    }
270    
271    
272    /*
273     *  cpu_functioncall_trace_return():
274     *
275     *  This function should be called if machine->show_trace_tree is enabled, and
276     *  a function is being returned from.
277     *
278     *  TODO: Print return value? This could be implemented similar to the
279     *  cpu->functioncall_trace function call above.
280     */
281    void cpu_functioncall_trace_return(struct cpu *cpu)
282    {
283            cpu->trace_tree_depth --;
284            if (cpu->trace_tree_depth < 0)
285                    cpu->trace_tree_depth = 0;
286    }
287    
288    
289    /*
290     *  cpu_create_or_reset_tc():
291     *
292     *  Create the translation cache in memory (ie allocate memory for it), if
293     *  necessary, and then reset it to an initial state.
294     */
295    void cpu_create_or_reset_tc(struct cpu *cpu)
296    {
297            if (cpu->translation_cache == NULL)
298                    cpu->translation_cache = zeroed_alloc(DYNTRANS_CACHE_SIZE +
299                        DYNTRANS_CACHE_MARGIN);
300    
301            /*  Create an empty table at the beginning of the translation cache:  */
302            memset(cpu->translation_cache, 0, sizeof(uint32_t)
303                * N_BASE_TABLE_ENTRIES);
304    
305            cpu->translation_cache_cur_ofs =
306                N_BASE_TABLE_ENTRIES * sizeof(uint32_t);
307    
308            /*
309             *  There might be other translation pointers that still point to
310             *  within the translation_cache region. Let's invalidate those too:
311             */
312            if (cpu->invalidate_code_translation != NULL)
313                    cpu->invalidate_code_translation(cpu, 0, INVALIDATE_ALL);
314    }
315    
316    
317    /*
318   *  cpu_run():   *  cpu_run():
319   *   *
320   *  Run instructions on all CPUs in this machine, for a "medium duration"   *  Run instructions on all CPUs in this machine, for a "medium duration"
# Line 236  int cpu_run(struct emul *emul, struct ma Line 336  int cpu_run(struct emul *emul, struct ma
336   *  cpu_dumpinfo():   *  cpu_dumpinfo():
337   *   *
338   *  Dumps info about a CPU using debug(). "cpu0: CPUNAME, running" (or similar)   *  Dumps info about a CPU using debug(). "cpu0: CPUNAME, running" (or similar)
339   *  is outputed, and it is up to CPU dependant code to complete the line.   *  is outputed, and it is up to CPU dependent code to complete the line.
340   */   */
341  void cpu_dumpinfo(struct machine *m, struct cpu *cpu)  void cpu_dumpinfo(struct machine *m, struct cpu *cpu)
342  {  {
# Line 288  void cpu_list_available_types(void) Line 388  void cpu_list_available_types(void)
388   *  Shuts down all CPUs in a machine when ending a simulation. (This function   *  Shuts down all CPUs in a machine when ending a simulation. (This function
389   *  should only need to be called once for each machine.)   *  should only need to be called once for each machine.)
390   */   */
391  void cpu_run_deinit(struct emul *emul, struct machine *machine)  void cpu_run_deinit(struct machine *machine)
392  {  {
393          int te;          int te;
394    
# Line 307  void cpu_run_deinit(struct emul *emul, s Line 407  void cpu_run_deinit(struct emul *emul, s
407          debug("cpu_run_deinit(): All CPUs halted.\n");          debug("cpu_run_deinit(): All CPUs halted.\n");
408    
409          if (machine->show_nr_of_instructions || !quiet_mode)          if (machine->show_nr_of_instructions || !quiet_mode)
410                  cpu_show_cycles(machine, &machine->starttime,                  cpu_show_cycles(machine, 1);
                     machine->ncycles, 1);  
411    
412          if (show_opcode_statistics)          if (show_opcode_statistics)
413                  cpu_show_full_statistics(machine);                  cpu_show_full_statistics(machine);
# Line 325  void cpu_run_deinit(struct emul *emul, s Line 424  void cpu_run_deinit(struct emul *emul, s
424   *  line to stdout about how many instructions/cycles have been executed so   *  line to stdout about how many instructions/cycles have been executed so
425   *  far.   *  far.
426   */   */
427  void cpu_show_cycles(struct machine *machine,  void cpu_show_cycles(struct machine *machine, int forced)
         struct timeval *starttime, int64_t ncycles, int forced)  
428  {  {
429          uint64_t offset, pc;          uint64_t offset, pc;
         int is_32bit = 0, instrs_per_cycle;  
430          char *symbol;          char *symbol;
431          int64_t mseconds, ninstrs;          int64_t mseconds, ninstrs, is, avg;
432          struct timeval tv;          struct timeval tv;
433          int h, m, s, ms, d;          int h, m, s, ms, d, instrs_per_cycle = 1;
434    
435          static int64_t mseconds_last = 0;          static int64_t mseconds_last = 0;
436          static int64_t ninstrs_last = -1;          static int64_t ninstrs_last = -1;
437    
438          if (machine->arch != ARCH_MIPS) {          switch (machine->arch) {
439                  fatal("cpu_show_cycles(): not yet for !MIPS\n");          case ARCH_MIPS:
440                  return;                  instrs_per_cycle = machine->cpus[machine->bootstrap_cpu]->
441                        cd.mips.cpu_type.instrs_per_cycle;
442                    break;
443          }          }
444    
         if (machine->cpus[machine->bootstrap_cpu]->cd.mips.cpu_type.isa_level  
             < 3 || machine->cpus[machine->bootstrap_cpu]->cd.mips.cpu_type.  
             isa_level == 32)  
                 is_32bit = 1;  
445          pc = machine->cpus[machine->bootstrap_cpu]->pc;          pc = machine->cpus[machine->bootstrap_cpu]->pc;
         instrs_per_cycle = machine->cpus[machine->bootstrap_cpu]->  
             cd.mips.cpu_type.instrs_per_cycle;  
446    
447          gettimeofday(&tv, NULL);          gettimeofday(&tv, NULL);
448          mseconds = (tv.tv_sec - starttime->tv_sec) * 1000          mseconds = (tv.tv_sec - machine->starttime.tv_sec) * 1000
449                   + (tv.tv_usec - starttime->tv_usec) / 1000;                   + (tv.tv_usec - machine->starttime.tv_usec) / 1000;
450    
451          if (mseconds == 0)          if (mseconds == 0)
452                  mseconds = 1;                  mseconds = 1;
# Line 361  void cpu_show_cycles(struct machine *mac Line 454  void cpu_show_cycles(struct machine *mac
454          if (mseconds - mseconds_last == 0)          if (mseconds - mseconds_last == 0)
455                  mseconds ++;                  mseconds ++;
456    
457          ninstrs = ncycles * instrs_per_cycle;          ninstrs = machine->ncycles_since_gettimeofday * instrs_per_cycle;
458    
459          if (machine->automatic_clock_adjustment) {          if (machine->automatic_clock_adjustment) {
460                  static int first_adjustment = 1;                  static int first_adjustment = 1;
# Line 382  void cpu_show_cycles(struct machine *mac Line 475  void cpu_show_cycles(struct machine *mac
475                              cur_cycles_per_second) / 16;                              cur_cycles_per_second) / 16;
476                  }                  }
477    
478                  debug("[ updating emulated_hz to %lli Hz ]\n",                  /*  debug("[ updating emulated_hz to %lli Hz ]\n",
479                      (long long)machine->emulated_hz);                      (long long)machine->emulated_hz);  */
480          }          }
481    
482    
# Line 391  void cpu_show_cycles(struct machine *mac Line 484  void cpu_show_cycles(struct machine *mac
484          if (!machine->show_nr_of_instructions && !forced)          if (!machine->show_nr_of_instructions && !forced)
485                  goto do_return;                  goto do_return;
486    
487            printf("[ %lli instrs",
488          printf("[ ");              (long long)(machine->ncycles * instrs_per_cycle));
489    
490          if (!machine->automatic_clock_adjustment) {          if (!machine->automatic_clock_adjustment) {
491                  d = machine->emulated_hz / 1000;                  d = machine->emulated_hz / 1000;
492                  if (d < 1)                  if (d < 1)
493                          d = 1;                          d = 1;
494                  ms = ncycles / d;                  ms = machine->ncycles / d;
495                  h = ms / 3600000;                  h = ms / 3600000;
496                  ms -= 3600000 * h;                  ms -= 3600000 * h;
497                  m = ms / 60000;                  m = ms / 60000;
# Line 409  void cpu_show_cycles(struct machine *mac Line 502  void cpu_show_cycles(struct machine *mac
502                  printf("emulated time = %02i:%02i:%02i.%03i; ", h, m, s, ms);                  printf("emulated time = %02i:%02i:%02i.%03i; ", h, m, s, ms);
503          }          }
504    
         printf("cycles=%lli", (long long) ncycles);  
   
         if (instrs_per_cycle > 1)  
                 printf(" (%lli instrs)", (long long) ninstrs);  
   
505          /*  Instructions per second, and average so far:  */          /*  Instructions per second, and average so far:  */
506          printf("; i/s=%lli avg=%lli",          is = 1000 * (ninstrs-ninstrs_last) / (mseconds-mseconds_last);
507              (long long) ((long long)1000 * (ninstrs-ninstrs_last)          avg = (long long)1000 * ninstrs / mseconds;
508                  / (mseconds-mseconds_last)),          if (is < 0)
509              (long long) ((long long)1000 * ninstrs / mseconds));                  is = 0;
510            if (avg < 0)
511                    avg = 0;
512            printf("; i/s=%lli avg=%lli", (long long)is, (long long)avg);
513    
514          symbol = get_symbol_name(&machine->symbol_context, pc, &offset);          symbol = get_symbol_name(&machine->symbol_context, pc, &offset);
515    
516          if (is_32bit)          if (machine->ncpus == 1) {
517                  printf("; pc=%08x", (int)pc);                  if (machine->cpus[machine->bootstrap_cpu]->is_32bit)
518          else                          printf("; pc=0x%08x", (int)pc);
519                  printf("; pc=%016llx", (long long)pc);                  else
520                            printf("; pc=0x%016llx", (long long)pc);
521            }
522    
523          printf(" <%s> ]\n", symbol? symbol : "no symbol");          if (symbol != NULL)
524                    printf(" <%s>", symbol);
525            printf(" ]\n");
526    
527  do_return:  do_return:
528          ninstrs_last = ninstrs;          ninstrs_last = ninstrs;
# Line 441  do_return: Line 536  do_return:
536   *  Prepare to run instructions on all CPUs in this machine. (This function   *  Prepare to run instructions on all CPUs in this machine. (This function
537   *  should only need to be called once for each machine.)   *  should only need to be called once for each machine.)
538   */   */
539  void cpu_run_init(struct emul *emul, struct machine *machine)  void cpu_run_init(struct machine *machine)
540  {  {
541          int ncpus = machine->ncpus;          int ncpus = machine->ncpus;
542          int te;          int te;
# Line 474  void cpu_run_init(struct emul *emul, str Line 569  void cpu_run_init(struct emul *emul, str
569    
570          /*  For performance measurement:  */          /*  For performance measurement:  */
571          gettimeofday(&machine->starttime, NULL);          gettimeofday(&machine->starttime, NULL);
572            machine->ncycles_since_gettimeofday = 0;
573  }  }
574    
575    
# Line 550  struct cpu_family *cpu_family_ptr_by_num Line 646  struct cpu_family *cpu_family_ptr_by_num
646  void cpu_init(void)  void cpu_init(void)
647  {  {
648          /*  Note: These are registered in alphabetic order.  */          /*  Note: These are registered in alphabetic order.  */
649    
650    #ifdef ENABLE_ALPHA
651          add_cpu_family(alpha_cpu_family_init, ARCH_ALPHA);          add_cpu_family(alpha_cpu_family_init, ARCH_ALPHA);
652    #endif
653    
654    #ifdef ENABLE_ARM
655            add_cpu_family(arm_cpu_family_init, ARCH_ARM);
656    #endif
657    
658    #ifdef ENABLE_AVR
659            add_cpu_family(avr_cpu_family_init, ARCH_AVR);
660    #endif
661    
662    #ifdef ENABLE_HPPA
663          add_cpu_family(hppa_cpu_family_init, ARCH_HPPA);          add_cpu_family(hppa_cpu_family_init, ARCH_HPPA);
664    #endif
665    
666    #ifdef ENABLE_I960
667            add_cpu_family(i960_cpu_family_init, ARCH_I960);
668    #endif
669    
670    #ifdef ENABLE_IA64
671            add_cpu_family(ia64_cpu_family_init, ARCH_IA64);
672    #endif
673    
674    #ifdef ENABLE_M68K
675            add_cpu_family(m68k_cpu_family_init, ARCH_M68K);
676    #endif
677    
678    #ifdef ENABLE_MIPS
679          add_cpu_family(mips_cpu_family_init, ARCH_MIPS);          add_cpu_family(mips_cpu_family_init, ARCH_MIPS);
680    #endif
681    
682    #ifdef ENABLE_NEWMIPS
683            add_cpu_family(newmips_cpu_family_init, ARCH_NEWMIPS);
684    #endif
685    
686    #ifdef ENABLE_PPC
687          add_cpu_family(ppc_cpu_family_init, ARCH_PPC);          add_cpu_family(ppc_cpu_family_init, ARCH_PPC);
688    #endif
689    
690    #ifdef ENABLE_SH
691            add_cpu_family(sh_cpu_family_init, ARCH_SH);
692    #endif
693    
694    #ifdef ENABLE_SPARC
695          add_cpu_family(sparc_cpu_family_init, ARCH_SPARC);          add_cpu_family(sparc_cpu_family_init, ARCH_SPARC);
696          add_cpu_family(urisc_cpu_family_init, ARCH_URISC);  #endif
697    
698    #ifdef ENABLE_X86
699          add_cpu_family(x86_cpu_family_init, ARCH_X86);          add_cpu_family(x86_cpu_family_init, ARCH_X86);
700    #endif
701  }  }
702    

Legend:
Removed from v.4  
changed lines
  Added in v.20

  ViewVC Help
Powered by ViewVC 1.1.26