--- trunk/src/cpu.c 2007/10/08 16:18:51 14 +++ trunk/src/cpu.c 2007/10/08 16:20:40 30 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 Anders Gavare. All rights reserved. + * Copyright (C) 2005-2006 Anders Gavare. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -25,7 +25,7 @@ * SUCH DAMAGE. * * - * $Id: cpu.c,v 1.321 2005/10/03 01:07:40 debug Exp $ + * $Id: cpu.c,v 1.349 2006/07/26 23:21:47 debug Exp $ * * Common routines for CPU emulation. (Not specific to any CPU type.) */ @@ -33,6 +33,7 @@ #include #include #include +#include #include #include "cpu.h" @@ -41,10 +42,6 @@ #include "misc.h" -extern int quiet_mode; -extern int show_opcode_statistics; - - static struct cpu_family *first_cpu_family = NULL; @@ -80,7 +77,6 @@ cpu->machine = machine; cpu->cpu_id = cpu_id; cpu->byte_order = EMUL_LITTLE_ENDIAN; - cpu->bootstrap_cpu_flag = 0; cpu->running = 0; cpu_create_or_reset_tc(cpu); @@ -97,30 +93,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; } @@ -165,14 +152,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); } @@ -181,8 +168,8 @@ * * Dump cpu registers in a relatively readable format. * - * gprs: set to non-zero to dump GPRs. (CPU dependant.) - * coprocs: set bit 0..x to dump registers in coproc 0..x. (CPU dependant.) + * gprs: set to non-zero to dump GPRs. (CPU dependent.) + * coprocs: set bit 0..x to dump registers in coproc 0..x. (CPU dependent.) */ void cpu_register_dump(struct machine *m, struct cpu *cpu, int gprs, int coprocs) @@ -195,6 +182,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. @@ -256,9 +261,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("("); @@ -266,6 +271,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 } @@ -294,9 +304,10 @@ */ void cpu_create_or_reset_tc(struct cpu *cpu) { + size_t s = DYNTRANS_CACHE_SIZE + DYNTRANS_CACHE_MARGIN; + if (cpu->translation_cache == NULL) - cpu->translation_cache = zeroed_alloc(DYNTRANS_CACHE_SIZE + - DYNTRANS_CACHE_MARGIN); + 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) @@ -315,28 +326,10 @@ /* - * 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) - * 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. */ void cpu_dumpinfo(struct machine *m, struct cpu *cpu) { @@ -358,7 +351,7 @@ void cpu_list_available_types(void) { struct cpu_family *fp; - int iadd = 4; + int iadd = DEBUG_INDENTATION; fp = first_cpu_family; @@ -393,9 +386,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], @@ -404,14 +399,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); } @@ -430,18 +420,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); @@ -454,15 +437,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; @@ -475,8 +460,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); */ } @@ -484,14 +469,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; @@ -499,7 +483,7 @@ s = ms / 1000; ms -= 1000 * s; - printf("emulated time = %02i:%02i:%02i.%03i; ", h, m, s, ms); + printf(", emulated time = %02i:%02i:%02i.%03i; ", h, m, s, ms); } /* Instructions per second, and average so far: */ @@ -509,15 +493,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) @@ -538,38 +522,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; } @@ -691,6 +650,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