--- trunk/src/cpu.c 2007/10/08 16:19:37 22 +++ upstream/0.4.1/src/cpu.c 2007/10/08 16:20:32 29 @@ -25,7 +25,7 @@ * SUCH DAMAGE. * * - * $Id: cpu.c,v 1.329 2006/01/16 04:48:08 debug Exp $ + * $Id: cpu.c,v 1.348 2006/07/20 21:52:59 debug Exp $ * * Common routines for CPU emulation. (Not specific to any CPU type.) */ @@ -42,10 +42,6 @@ #include "misc.h" -extern int quiet_mode; -extern int show_opcode_statistics; -extern int dyntrans_backend_enable; - static struct cpu_family *first_cpu_family = NULL; @@ -98,30 +94,21 @@ "NULL\n"); exit(1); } - return cpu; + break; } } fp = fp->next; } - fatal("\ncpu_new(): unknown cpu type '%s'\n", cpu_type_name); - exit(1); -} + if (fp == NULL) { + fatal("\ncpu_new(): unknown cpu type '%s'\n", cpu_type_name); + return NULL; + } + fp->init_tables(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); + return cpu; } @@ -166,14 +153,14 @@ * tracing. */ int cpu_disassemble_instr(struct machine *m, struct cpu *cpu, - unsigned char *instr, int running, uint64_t addr, int bintrans) + unsigned char *instr, int running, uint64_t addr) { if (m->cpu_family == NULL || m->cpu_family->disassemble_instr == NULL) { fatal("cpu_disassemble_instr(): NULL\n"); return 0; } else return m->cpu_family->disassemble_instr(cpu, instr, - running, addr, bintrans); + running, addr); } @@ -196,6 +183,24 @@ /* + * cpu_gdb_stub(): + * + * Execute a "remote GDB" command. Return value is a pointer to a newly + * allocated response string, if the command was successfully executed. If + * there was an error, NULL is returned. + */ +char *cpu_gdb_stub(struct cpu *cpu, char *cmd) +{ + if (cpu->machine->cpu_family == NULL || + cpu->machine->cpu_family->gdb_stub == NULL) { + fatal("cpu_gdb_stub(): NULL\n"); + return NULL; + } else + return cpu->machine->cpu_family->gdb_stub(cpu, cmd); +} + + +/* * cpu_interrupt(): * * Assert an interrupt. @@ -257,9 +262,9 @@ fatal("%s", symbol); else { if (cpu->is_32bit) - fatal("0x%08x", (int)f); + fatal("0x%"PRIx32, (uint32_t) f); else - fatal("0x%llx", (long long)f); + fatal("0x%"PRIx64, (uint64_t) f); } fatal("("); @@ -267,6 +272,11 @@ cpu->machine->cpu_family->functioncall_trace(cpu, f, n_args); fatal(")>\n"); + +#ifdef PRINT_MEMORY_CHECKSUM + /* Temporary hack for finding bugs: */ + fatal("call chksum=%016"PRIx64"\n", memory_checksum(cpu->mem)); +#endif } @@ -297,22 +307,8 @@ { size_t s = DYNTRANS_CACHE_SIZE + DYNTRANS_CACHE_MARGIN; - if (cpu->translation_cache == NULL) { -#ifdef DYNTRANS_BACKEND - 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); - } + if (cpu->translation_cache == NULL) + cpu->translation_cache = zeroed_alloc(s); /* Create an empty table at the beginning of the translation cache: */ memset(cpu->translation_cache, 0, sizeof(uint32_t) @@ -331,24 +327,6 @@ /* - * 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); -} - - -/* * cpu_dumpinfo(): * * Dumps info about a CPU using debug(). "cpu0: CPUNAME, running" (or similar) @@ -409,9 +387,11 @@ int te; /* - * Two last ticks of every hardware device. This will allow - * framebuffers to draw the last updates to the screen before - * halting. + * Two last ticks of every hardware device. This will allow e.g. + * framebuffers to draw the last updates to the screen before halting. + * + * TODO: This should be refactored when redesigning the mainbus + * concepts! */ for (te=0; ten_tick_entries; te++) { machine->tick_func[te](machine->cpus[0], @@ -420,14 +400,9 @@ machine->tick_extra[te]); } - debug("cpu_run_deinit(): All CPUs halted.\n"); - - if (machine->show_nr_of_instructions || !quiet_mode) + if (machine->show_nr_of_instructions) cpu_show_cycles(machine, 1); - if (show_opcode_statistics) - cpu_show_full_statistics(machine); - fflush(stdout); } @@ -446,18 +421,11 @@ char *symbol; int64_t mseconds, ninstrs, is, avg; struct timeval tv; - int h, m, s, ms, d, instrs_per_cycle = 1; + int h, m, s, ms, d; static int64_t mseconds_last = 0; static int64_t ninstrs_last = -1; - switch (machine->arch) { - case ARCH_MIPS: - instrs_per_cycle = machine->cpus[machine->bootstrap_cpu]-> - cd.mips.cpu_type.instrs_per_cycle; - break; - } - pc = machine->cpus[machine->bootstrap_cpu]->pc; gettimeofday(&tv, NULL); @@ -470,15 +438,17 @@ if (mseconds - mseconds_last == 0) mseconds ++; - ninstrs = machine->ncycles_since_gettimeofday * instrs_per_cycle; + 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) - / instrs_per_cycle; + (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; @@ -491,8 +461,8 @@ cur_cycles_per_second) / 16; } - /* debug("[ updating emulated_hz to %lli Hz ]\n", - (long long)machine->emulated_hz); */ + /* fatal("[ updating emulated_hz to %"PRIi64" Hz ]\n", + machine->emulated_hz); */ } @@ -500,14 +470,13 @@ if (!machine->show_nr_of_instructions && !forced) goto do_return; - printf("[ %lli instrs", - (long long)(machine->ncycles * instrs_per_cycle)); + printf("[ %"PRIi64" instrs", (int64_t)machine->ninstrs); if (!machine->automatic_clock_adjustment) { d = machine->emulated_hz / 1000; if (d < 1) d = 1; - ms = machine->ncycles / d; + ms = machine->ninstrs / d; h = ms / 3600000; ms -= 3600000 * h; m = ms / 60000; @@ -525,15 +494,15 @@ is = 0; if (avg < 0) avg = 0; - printf("; i/s=%lli avg=%lli", (long long)is, (long long)avg); + 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) - printf("; pc=0x%08x", (int)pc); + printf("; pc=0x%08"PRIx32, (uint32_t) pc); else - printf("; pc=0x%016llx", (long long)pc); + printf("; pc=0x%016"PRIx64, (uint64_t) pc); } if (symbol != NULL) @@ -554,38 +523,13 @@ */ void cpu_run_init(struct machine *machine) { - int ncpus = machine->ncpus; - int te; - - machine->a_few_cycles = 1048576; - machine->ncycles_flush = 0; - machine->ncycles = 0; - machine->ncycles_show = 0; - - /* - * Instead of doing { one cycle, check hardware ticks }, we - * can do { n cycles, check hardware ticks }, as long as - * n is at most as much as the lowest number of cycles/tick - * for any hardware device. - */ - for (te=0; ten_tick_entries; te++) { - if (machine->ticks_reset_value[te] < machine->a_few_cycles) - machine->a_few_cycles = machine->ticks_reset_value[te]; - } - - machine->a_few_cycles >>= 1; - if (machine->a_few_cycles < 1) - machine->a_few_cycles = 1; - - if (ncpus > 1 && machine->max_random_cycles_per_chunk == 0) - machine->a_few_cycles = 1; - - /* debug("cpu_run_init(): a_few_cycles = %i\n", - machine->a_few_cycles); */ + machine->ninstrs_flush = 0; + machine->ninstrs = 0; + machine->ninstrs_show = 0; /* For performance measurement: */ gettimeofday(&machine->starttime, NULL); - machine->ncycles_since_gettimeofday = 0; + machine->ninstrs_since_gettimeofday = 0; } @@ -654,95 +598,6 @@ } -#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 */ - - /* * cpu_init(): * @@ -796,6 +651,10 @@ add_cpu_family(sparc_cpu_family_init, ARCH_SPARC); #endif +#ifdef ENABLE_TRANSPUTER + add_cpu_family(transputer_cpu_family_init, ARCH_TRANSPUTER); +#endif + #ifdef ENABLE_X86 add_cpu_family(x86_cpu_family_init, ARCH_X86); #endif