25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: cpu.c,v 1.295 2005/06/02 00:08:41 debug Exp $ |
* $Id: cpu.c,v 1.298 2005/06/27 10:43:16 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 |
*/ |
*/ |
56 |
struct cpu *cpu_new(struct memory *mem, struct machine *machine, |
struct cpu *cpu_new(struct memory *mem, struct machine *machine, |
57 |
int cpu_id, char *name) |
int cpu_id, char *name) |
58 |
{ |
{ |
59 |
struct cpu *c; |
struct cpu *cpu; |
60 |
struct cpu_family *fp; |
struct cpu_family *fp; |
61 |
char *cpu_type_name; |
char *cpu_type_name; |
62 |
|
|
71 |
exit(1); |
exit(1); |
72 |
} |
} |
73 |
|
|
74 |
|
cpu = malloc(sizeof(struct cpu)); |
75 |
|
if (cpu == NULL) { |
76 |
|
fprintf(stderr, "out of memory\n"); |
77 |
|
exit(1); |
78 |
|
} |
79 |
|
|
80 |
|
memset(cpu, 0, sizeof(struct cpu)); |
81 |
|
cpu->memory_rw = NULL; |
82 |
|
cpu->name = cpu_type_name; |
83 |
|
cpu->mem = mem; |
84 |
|
cpu->machine = machine; |
85 |
|
cpu->cpu_id = cpu_id; |
86 |
|
cpu->byte_order = EMUL_LITTLE_ENDIAN; |
87 |
|
cpu->bootstrap_cpu_flag = 0; |
88 |
|
cpu->running = 0; |
89 |
|
|
90 |
fp = first_cpu_family; |
fp = first_cpu_family; |
91 |
|
|
92 |
while (fp != NULL) { |
while (fp != NULL) { |
93 |
if (fp->cpu_new != NULL) { |
if (fp->cpu_new != NULL) { |
94 |
c = fp->cpu_new(mem, machine, cpu_id, cpu_type_name); |
if (fp->cpu_new(cpu, mem, machine, cpu_id, |
95 |
if (c != NULL) { |
cpu_type_name)) { |
96 |
/* Some sanity-checks: */ |
/* Sanity check: */ |
97 |
if (c->memory_rw == NULL) { |
if (cpu->memory_rw == NULL) { |
98 |
fatal("No memory_rw?\n"); |
fatal("\ncpu_new(): memory_rw == " |
99 |
|
"NULL\n"); |
100 |
exit(1); |
exit(1); |
101 |
} |
} |
102 |
|
return cpu; |
|
return c; |
|
103 |
} |
} |
104 |
} |
} |
105 |
|
|
323 |
debug("cpu_run_deinit(): All CPUs halted.\n"); |
debug("cpu_run_deinit(): All CPUs halted.\n"); |
324 |
|
|
325 |
if (machine->show_nr_of_instructions || !quiet_mode) |
if (machine->show_nr_of_instructions || !quiet_mode) |
326 |
cpu_show_cycles(machine, &machine->starttime, |
cpu_show_cycles(machine, 1); |
|
machine->ncycles, 1); |
|
327 |
|
|
328 |
if (show_opcode_statistics) |
if (show_opcode_statistics) |
329 |
cpu_show_full_statistics(machine); |
cpu_show_full_statistics(machine); |
340 |
* line to stdout about how many instructions/cycles have been executed so |
* line to stdout about how many instructions/cycles have been executed so |
341 |
* far. |
* far. |
342 |
*/ |
*/ |
343 |
void cpu_show_cycles(struct machine *machine, |
void cpu_show_cycles(struct machine *machine, int forced) |
|
struct timeval *starttime, int64_t ncycles, int forced) |
|
344 |
{ |
{ |
345 |
uint64_t offset, pc; |
uint64_t offset, pc; |
346 |
int is_32bit = 0, instrs_per_cycle; |
int is_32bit = 0, instrs_per_cycle = 1; |
347 |
char *symbol; |
char *symbol; |
348 |
int64_t mseconds, ninstrs; |
int64_t mseconds, ninstrs; |
349 |
struct timeval tv; |
struct timeval tv; |
352 |
static int64_t mseconds_last = 0; |
static int64_t mseconds_last = 0; |
353 |
static int64_t ninstrs_last = -1; |
static int64_t ninstrs_last = -1; |
354 |
|
|
355 |
if (machine->arch != ARCH_MIPS) { |
switch (machine->arch) { |
356 |
fatal("cpu_show_cycles(): not yet for !MIPS\n"); |
case ARCH_MIPS: |
357 |
return; |
if (machine->cpus[machine->bootstrap_cpu]->cd.mips. |
358 |
|
cpu_type.isa_level < 3 || machine->cpus[machine-> |
359 |
|
bootstrap_cpu]->cd.mips.cpu_type.isa_level == 32) |
360 |
|
is_32bit = 1; |
361 |
|
instrs_per_cycle = machine->cpus[machine->bootstrap_cpu]-> |
362 |
|
cd.mips.cpu_type.instrs_per_cycle; |
363 |
|
break; |
364 |
|
case ARCH_ARM: |
365 |
|
is_32bit = 1; |
366 |
|
break; |
367 |
} |
} |
368 |
|
|
|
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; |
|
369 |
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; |
|
370 |
|
|
371 |
gettimeofday(&tv, NULL); |
gettimeofday(&tv, NULL); |
372 |
mseconds = (tv.tv_sec - starttime->tv_sec) * 1000 |
mseconds = (tv.tv_sec - machine->starttime.tv_sec) * 1000 |
373 |
+ (tv.tv_usec - starttime->tv_usec) / 1000; |
+ (tv.tv_usec - machine->starttime.tv_usec) / 1000; |
374 |
|
|
375 |
if (mseconds == 0) |
if (mseconds == 0) |
376 |
mseconds = 1; |
mseconds = 1; |
378 |
if (mseconds - mseconds_last == 0) |
if (mseconds - mseconds_last == 0) |
379 |
mseconds ++; |
mseconds ++; |
380 |
|
|
381 |
ninstrs = ncycles * instrs_per_cycle; |
ninstrs = machine->ncycles_since_gettimeofday * instrs_per_cycle; |
382 |
|
|
383 |
if (machine->automatic_clock_adjustment) { |
if (machine->automatic_clock_adjustment) { |
384 |
static int first_adjustment = 1; |
static int first_adjustment = 1; |
408 |
if (!machine->show_nr_of_instructions && !forced) |
if (!machine->show_nr_of_instructions && !forced) |
409 |
goto do_return; |
goto do_return; |
410 |
|
|
411 |
|
printf("[ %lli instrs", |
412 |
printf("[ "); |
(long long)(machine->ncycles * instrs_per_cycle)); |
413 |
|
|
414 |
if (!machine->automatic_clock_adjustment) { |
if (!machine->automatic_clock_adjustment) { |
415 |
d = machine->emulated_hz / 1000; |
d = machine->emulated_hz / 1000; |
416 |
if (d < 1) |
if (d < 1) |
417 |
d = 1; |
d = 1; |
418 |
ms = ncycles / d; |
ms = machine->ncycles / d; |
419 |
h = ms / 3600000; |
h = ms / 3600000; |
420 |
ms -= 3600000 * h; |
ms -= 3600000 * h; |
421 |
m = ms / 60000; |
m = ms / 60000; |
426 |
printf("emulated time = %02i:%02i:%02i.%03i; ", h, m, s, ms); |
printf("emulated time = %02i:%02i:%02i.%03i; ", h, m, s, ms); |
427 |
} |
} |
428 |
|
|
|
printf("cycles=%lli", (long long) ncycles); |
|
|
|
|
|
if (instrs_per_cycle > 1) |
|
|
printf(" (%lli instrs)", (long long) ninstrs); |
|
|
|
|
429 |
/* Instructions per second, and average so far: */ |
/* Instructions per second, and average so far: */ |
430 |
printf("; i/s=%lli avg=%lli", |
printf("; i/s=%lli avg=%lli; ", |
431 |
(long long) ((long long)1000 * (ninstrs-ninstrs_last) |
(long long) ((long long)1000 * (ninstrs-ninstrs_last) |
432 |
/ (mseconds-mseconds_last)), |
/ (mseconds-mseconds_last)), |
433 |
(long long) ((long long)1000 * ninstrs / mseconds)); |
(long long) ((long long)1000 * ninstrs / mseconds)); |
435 |
symbol = get_symbol_name(&machine->symbol_context, pc, &offset); |
symbol = get_symbol_name(&machine->symbol_context, pc, &offset); |
436 |
|
|
437 |
if (is_32bit) |
if (is_32bit) |
438 |
printf("; pc=%08x", (int)pc); |
printf("pc=0x%08x", (int)pc); |
439 |
else |
else |
440 |
printf("; pc=%016llx", (long long)pc); |
printf("pc=0x%016llx", (long long)pc); |
441 |
|
|
442 |
printf(" <%s> ]\n", symbol? symbol : "no symbol"); |
if (symbol != NULL) |
443 |
|
printf(" <%s>", symbol); |
444 |
|
printf(" ]\n"); |
445 |
|
|
446 |
do_return: |
do_return: |
447 |
ninstrs_last = ninstrs; |
ninstrs_last = ninstrs; |
488 |
|
|
489 |
/* For performance measurement: */ |
/* For performance measurement: */ |
490 |
gettimeofday(&machine->starttime, NULL); |
gettimeofday(&machine->starttime, NULL); |
491 |
|
machine->ncycles_since_gettimeofday = 0; |
492 |
} |
} |
493 |
|
|
494 |
|
|
565 |
void cpu_init(void) |
void cpu_init(void) |
566 |
{ |
{ |
567 |
/* Note: These are registered in alphabetic order. */ |
/* Note: These are registered in alphabetic order. */ |
|
add_cpu_family(alpha_cpu_family_init, ARCH_ALPHA); |
|
568 |
add_cpu_family(arm_cpu_family_init, ARCH_ARM); |
add_cpu_family(arm_cpu_family_init, ARCH_ARM); |
|
add_cpu_family(hppa_cpu_family_init, ARCH_HPPA); |
|
569 |
add_cpu_family(mips_cpu_family_init, ARCH_MIPS); |
add_cpu_family(mips_cpu_family_init, ARCH_MIPS); |
570 |
add_cpu_family(ppc_cpu_family_init, ARCH_PPC); |
add_cpu_family(ppc_cpu_family_init, ARCH_PPC); |
|
add_cpu_family(sparc_cpu_family_init, ARCH_SPARC); |
|
571 |
add_cpu_family(urisc_cpu_family_init, ARCH_URISC); |
add_cpu_family(urisc_cpu_family_init, ARCH_URISC); |
572 |
add_cpu_family(x86_cpu_family_init, ARCH_X86); |
add_cpu_family(x86_cpu_family_init, ARCH_X86); |
573 |
} |
} |