--- trunk/src/cpu.c 2007/10/08 16:20:26 28 +++ trunk/src/cpu.c 2007/10/08 16:20:58 32 @@ -25,7 +25,7 @@ * SUCH DAMAGE. * * - * $Id: cpu.c,v 1.348 2006/07/20 21:52:59 debug Exp $ + * $Id: cpu.c,v 1.361 2006/10/25 09:24:05 debug Exp $ * * Common routines for CPU emulation. (Not specific to any CPU type.) */ @@ -40,6 +40,7 @@ #include "machine.h" #include "memory.h" #include "misc.h" +#include "settings.h" static struct cpu_family *first_cpu_family = NULL; @@ -50,6 +51,9 @@ * * Create a new cpu object. Each family is tried in sequence until a * CPU family recognizes the cpu_type_name. + * + * If there was no match, NULL is returned. Otherwise, a pointer to an + * initialized cpu struct is returned. */ struct cpu *cpu_new(struct memory *mem, struct machine *machine, int cpu_id, char *name) @@ -57,6 +61,7 @@ struct cpu *cpu; struct cpu_family *fp; char *cpu_type_name; + char tmpstr[30]; if (name == NULL) { fprintf(stderr, "cpu_new(): cpu name = NULL?\n"); @@ -71,14 +76,24 @@ cpu = zeroed_alloc(sizeof(struct cpu)); - cpu->memory_rw = NULL; - cpu->name = cpu_type_name; - cpu->mem = mem; - cpu->machine = machine; - cpu->cpu_id = cpu_id; - cpu->byte_order = EMUL_LITTLE_ENDIAN; - cpu->bootstrap_cpu_flag = 0; - cpu->running = 0; + cpu->memory_rw = NULL; + cpu->name = cpu_type_name; + cpu->mem = mem; + cpu->machine = machine; + cpu->cpu_id = cpu_id; + cpu->byte_order = EMUL_UNDEFINED_ENDIAN; + cpu->running = 0; + + /* Create settings, and attach to the machine: */ + cpu->settings = settings_new(); + snprintf(tmpstr, sizeof(tmpstr), "cpu[%i]", cpu_id); + settings_add(machine->settings, tmpstr, 1, + SETTINGS_TYPE_SUBSETTINGS, 0, cpu->settings); + + settings_add(cpu->settings, "name", 0, SETTINGS_TYPE_STRING, + SETTINGS_FORMAT_STRING, (void *) &cpu->name); + settings_add(cpu->settings, "running", 0, SETTINGS_TYPE_INT, + SETTINGS_FORMAT_YESNO, (void *) &cpu->running); cpu_create_or_reset_tc(cpu); @@ -108,11 +123,37 @@ fp->init_tables(cpu); + if (cpu->byte_order == EMUL_UNDEFINED_ENDIAN) { + fatal("\ncpu_new(): Internal bug: Endianness not set.\n"); + exit(1); + } + return cpu; } /* + * cpu_destroy(): + * + * Destroy a cpu object. + */ +void cpu_destroy(struct cpu *cpu) +{ + settings_remove(cpu->settings, "name"); + settings_remove(cpu->settings, "running"); + + /* Remove any remaining level-1 settings: */ + settings_remove_all(cpu->settings); + + settings_destroy(cpu->settings); + + /* TODO: This assumes that zeroed_alloc() actually succeeded + with using mmap(), and not malloc()! */ + munmap((void *)cpu, sizeof(struct cpu)); +} + + +/* * cpu_tlbdump(): * * Called from the debugger to dump the TLB in a readable format. @@ -131,22 +172,6 @@ /* - * cpu_register_match(): - * - * Used by the debugger. - */ -void cpu_register_match(struct machine *m, char *name, - int writeflag, uint64_t *valuep, int *match_register) -{ - if (m->cpu_family == NULL || m->cpu_family->register_match == NULL) - fatal("cpu_register_match(): NULL\n"); - else - m->cpu_family->register_match(m, name, writeflag, - valuep, match_register); -} - - -/* * cpu_disassemble_instr(): * * Convert an instruction word into human readable format, for instruction @@ -410,10 +435,8 @@ /* * cpu_show_cycles(): * - * If automatic adjustment of clock interrupts is turned on, then recalculate - * emulated_hz. Also, if show_nr_of_instructions is on, then print a - * line to stdout about how many instructions/cycles have been executed so - * far. + * If show_nr_of_instructions is on, then print a line to stdout about how + * many instructions/cycles have been executed so far. */ void cpu_show_cycles(struct machine *machine, int forced) { @@ -421,12 +444,12 @@ char *symbol; int64_t mseconds, ninstrs, is, avg; struct timeval tv; - int h, m, s, ms, d; + struct cpu *cpu = machine->cpus[machine->bootstrap_cpu]; static int64_t mseconds_last = 0; static int64_t ninstrs_last = -1; - pc = machine->cpus[machine->bootstrap_cpu]->pc; + pc = cpu->pc; gettimeofday(&tv, NULL); mseconds = (tv.tv_sec - machine->starttime.tv_sec) * 1000 @@ -440,53 +463,12 @@ ninstrs = machine->ninstrs_since_gettimeofday; - if (machine->automatic_clock_adjustment) { - static int first_adjustment = 1; - - /* Current nr of cycles per second: */ - int64_t cur_cycles_per_second = 1000 * - (ninstrs-ninstrs_last) / (mseconds-mseconds_last); - - /* fatal("[ CYCLES PER SECOND = %"PRIi64" ]\n", - cur_cycles_per_second); */ - - if (cur_cycles_per_second < 1000000) - cur_cycles_per_second = 1000000; - - if (first_adjustment) { - machine->emulated_hz = cur_cycles_per_second; - first_adjustment = 0; - } else { - machine->emulated_hz = (15 * machine->emulated_hz + - cur_cycles_per_second) / 16; - } - - /* fatal("[ updating emulated_hz to %"PRIi64" Hz ]\n", - machine->emulated_hz); */ - } - - /* RETURN here, unless show_nr_of_instructions (-N) is turned on: */ if (!machine->show_nr_of_instructions && !forced) goto do_return; printf("[ %"PRIi64" instrs", (int64_t)machine->ninstrs); - if (!machine->automatic_clock_adjustment) { - d = machine->emulated_hz / 1000; - if (d < 1) - d = 1; - ms = machine->ninstrs / d; - h = ms / 3600000; - ms -= 3600000 * h; - m = ms / 60000; - ms -= 60000 * m; - s = ms / 1000; - ms -= 1000 * s; - - printf(", emulated time = %02i:%02i:%02i.%03i; ", h, m, s, ms); - } - /* Instructions per second, and average so far: */ is = 1000 * (ninstrs-ninstrs_last) / (mseconds-mseconds_last); avg = (long long)1000 * ninstrs / mseconds; @@ -494,12 +476,17 @@ is = 0; if (avg < 0) avg = 0; - printf("; i/s=%"PRIi64" avg=%"PRIi64, is, avg); + + if (cpu->has_been_idling) { + printf("; idling"); + cpu->has_been_idling = 0; + } else + printf("; i/s=%"PRIi64" avg=%"PRIi64, is, avg); symbol = get_symbol_name(&machine->symbol_context, pc, &offset); if (machine->ncpus == 1) { - if (machine->cpus[machine->bootstrap_cpu]->is_32bit) + if (cpu->is_32bit) printf("; pc=0x%08"PRIx32, (uint32_t) pc); else printf("; pc=0x%016"PRIx64, (uint64_t) pc); @@ -602,6 +589,9 @@ * cpu_init(): * * Should be called before any other cpu_*() function. + * + * TODO: Make this nicer by moving out the conditional stuff to + * an automagically generated file? Or a define in config.h? */ void cpu_init(void) { @@ -619,6 +609,14 @@ add_cpu_family(avr_cpu_family_init, ARCH_AVR); #endif +#ifdef ENABLE_AVR32 + add_cpu_family(avr32_cpu_family_init, ARCH_AVR32); +#endif + +#ifdef ENABLE_RCA180X + add_cpu_family(rca180x_cpu_family_init, ARCH_RCA180X); +#endif + #ifdef ENABLE_HPPA add_cpu_family(hppa_cpu_family_init, ARCH_HPPA); #endif