--- trunk/src/machine.c 2007/10/08 16:19:37 22 +++ trunk/src/machine.c 2007/10/08 16:20:10 26 @@ -25,7 +25,7 @@ * SUCH DAMAGE. * * - * $Id: machine.c,v 1.664 2006/02/05 10:26:35 debug Exp $ + * $Id: machine.c,v 1.673 2006/06/24 19:52:27 debug Exp $ */ #include @@ -44,6 +44,7 @@ #include "bus_isa.h" #include "bus_pci.h" #include "cpu.h" +#include "debugger.h" #include "device.h" #include "devices.h" #include "diskimage.h" @@ -90,10 +91,6 @@ m->serial_nr = 1; m->machine_type = MACHINE_NONE; m->machine_subtype = MACHINE_NONE; -#ifdef BINTRANS - m->bintrans_enable = 1; - m->old_bintrans_enable = 1; -#endif m->arch_pagesize = 4096; /* Should be overriden in emul.c for other pagesizes. */ m->dyntrans_alignment_check = 1; @@ -108,7 +105,6 @@ m->n_gfx_cards = 1; m->dbe_on_nonexistant_memaccess = 1; m->show_symbolic_register_names = 1; - m->bintrans_size = DEFAULT_BINTRANS_SIZE_IN_MB * 1048576; symbol_init(&m->symbol_context); return m; @@ -219,9 +215,15 @@ * * Adds a tick function (a function called every now and then, depending on * clock cycle count) to a machine. + * + * If tickshift is non-zero, a tick will occur every (1 << tickshift) cycles. + * This is used for the normal (fast dyntrans) emulation modes. + * + * If tickshift is zero, then this is a cycle-accurate tick function. + * The hz value is used in this case. */ void machine_add_tickfunction(struct machine *machine, void (*func) - (struct cpu *, void *), void *extra, int clockshift) + (struct cpu *, void *), void *extra, int tickshift, double hz) { int n = machine->n_tick_entries; @@ -231,17 +233,25 @@ exit(1); } - /* Don't use too low clockshifts, that would be too inefficient - with bintrans. */ - if (clockshift < N_SAFE_BINTRANS_LIMIT_SHIFT) - fatal("WARNING! clockshift = %i, less than " - "N_SAFE_BINTRANS_LIMIT_SHIFT (%i)\n", - clockshift, N_SAFE_BINTRANS_LIMIT_SHIFT); + if (!machine->cycle_accurate) { + /* + * The dyntrans subsystem wants to run code in relatively + * large chunks without checking for external interrupts, + * so we cannot allow too low tickshifts: + */ + if (tickshift < N_SAFE_DYNTRANS_LIMIT_SHIFT) { + fatal("ERROR! tickshift = %i, less than " + "N_SAFE_DYNTRANS_LIMIT_SHIFT (%i)\n", + tickshift, N_SAFE_DYNTRANS_LIMIT_SHIFT); + exit(1); + } + } machine->ticks_till_next[n] = 0; - machine->ticks_reset_value[n] = 1 << clockshift; + machine->ticks_reset_value[n] = 1 << tickshift; machine->tick_func[n] = func; machine->tick_extra[n] = extra; + machine->tick_hz[n] = hz; machine->n_tick_entries ++; } @@ -323,18 +333,6 @@ debug(", dbe_on_nonexistant_memaccess"); debug("\n"); - if (m->single_step_on_bad_addr) - debug("single-step on bad addresses\n"); - - if (m->arch == ARCH_MIPS) { - if (m->bintrans_enable) - debug("bintrans enabled (%i MB cache)\n", - (int) (m->bintrans_size / 1048576)); - else - debug("bintrans disabled, other speedtricks %s\n", - m->speed_tricks? "enabled" : "disabled"); - } - debug("clock: "); if (m->automatic_clock_adjustment) debug("adjusted automatically"); @@ -899,15 +897,78 @@ } +/*****************************************************************************/ + + +/* + * machine_run(): + * + * Run one or more instructions on all CPUs in this machine. (Usually, + * around N_SAFE_DYNTRANS_LIMIT instructions will be run by the dyntrans + * system.) + * + * Return value is 1 if any CPU in this machine is still running, + * or 0 if all CPUs are stopped. + */ +int machine_run(struct machine *machine) +{ + struct cpu **cpus = machine->cpus; + int ncpus = machine->ncpus, cpu0instrs = 0, i, te; + + for (i=0; irunning) { + int instrs_run = machine->cpu_family->run_instr( + machine->emul, cpus[i]); + if (i == 0) + cpu0instrs += instrs_run; + } + } + + /* + * Hardware 'ticks': (clocks, interrupt sources...) + * + * Here, cpu0instrs is the number of instructions + * executed on cpu0. (TODO: don't use cpu 0 for this, + * use some kind of "mainbus" instead.) + */ + + machine->ncycles += cpu0instrs; + + for (te=0; ten_tick_entries; te++) { + machine->ticks_till_next[te] -= cpu0instrs; + if (machine->ticks_till_next[te] <= 0) { + while (machine->ticks_till_next[te] <= 0) { + machine->ticks_till_next[te] += + machine->ticks_reset_value[te]; + } + + machine->tick_func[te](cpus[0], + machine->tick_extra[te]); + } + } + + /* Is any CPU still alive? */ + for (i=0; irunning) + return 1; + + return 0; +} + + +/*****************************************************************************/ + + /* * machine_entry_new(): * * This function creates a new machine_entry struct, and fills it with some * valid data; it is up to the caller to add additional data that weren't - * passed as arguments to this function. + * passed as arguments to this function, such as alias names and machine + * subtypes. */ -struct machine_entry *machine_entry_new(const char *name, - int arch, int oldstyle_type, int n_aliases, int n_subtypes) +struct machine_entry *machine_entry_new(const char *name, int arch, + int oldstyle_type) { struct machine_entry *me; @@ -922,43 +983,49 @@ me->name = name; me->arch = arch; me->machine_type = oldstyle_type; - me->n_aliases = n_aliases; - me->aliases = malloc(sizeof(char *) * n_aliases); - if (me->aliases == NULL) { - fprintf(stderr, "machine_entry_new(): out of memory (2)\n"); - exit(1); - } - me->n_subtypes = n_subtypes; + me->n_aliases = 0; + me->aliases = NULL; + me->n_subtypes = 0; me->setup = NULL; - if (n_subtypes > 0) { - me->subtype = malloc(sizeof(struct machine_entry_subtype *) * - n_subtypes); - if (me->subtype == NULL) { - fprintf(stderr, "machine_entry_new(): out of " - "memory (3)\n"); - exit(1); - } + return me; +} + + +/* + * machine_entry_add_alias(): + * + * This function adds an "alias" to a machine entry. + */ +void machine_entry_add_alias(struct machine_entry *me, const char *name) +{ + me->n_aliases ++; + me->aliases = realloc(me->aliases, sizeof(char *) * me->n_aliases); + if (me->aliases == NULL) { + fprintf(stderr, "out of memory\n"); + exit(1); } - return me; + me->aliases[me->n_aliases - 1] = (char *) name; } /* - * machine_entry_subtype_new(): + * machine_entry_add_subtype(): * - * This function creates a new machine_entry_subtype struct, and fills it with - * some valid data; it is up to the caller to add additional data that weren't - * passed as arguments to this function. + * This function adds a subtype to a machine entry. The argument list after + * oldstyle_subtype is a list of one or more char *, followed by NULL. E.g.: * - * For internal use. + * machine_entry_add_subtype(me, "Machine X", MACHINE_X, + * "machine-x", "x", NULL); */ -struct machine_entry_subtype *machine_entry_subtype_new( - const char *name, int oldstyle_type, int n_aliases) +void machine_entry_add_subtype(struct machine_entry *me, const char *name, + int oldstyle_subtype, ...) { + va_list argp; struct machine_entry_subtype *mes; + /* Allocate a new subtype struct: */ mes = malloc(sizeof(struct machine_entry_subtype)); if (mes == NULL) { fprintf(stderr, "machine_entry_subtype_new(): out " @@ -966,27 +1033,53 @@ exit(1); } + /* Add the subtype to the machine entry: */ + me->n_subtypes ++; + me->subtype = realloc(me->subtype, sizeof(struct + machine_entry_subtype *) * me->n_subtypes); + if (me->subtype == NULL) { + fprintf(stderr, "out of memory\n"); + exit(1); + } + me->subtype[me->n_subtypes - 1] = mes; + + /* Fill the struct with subtype data: */ memset(mes, 0, sizeof(struct machine_entry_subtype)); mes->name = name; - mes->machine_subtype = oldstyle_type; - mes->n_aliases = n_aliases; - mes->aliases = malloc(sizeof(char *) * n_aliases); - if (mes->aliases == NULL) { - fprintf(stderr, "machine_entry_subtype_new(): " - "out of memory (2)\n"); - exit(1); + mes->machine_subtype = oldstyle_subtype; + + /* ... and all aliases: */ + mes->n_aliases = 0; + mes->aliases = NULL; + + va_start(argp, oldstyle_subtype); + + for (;;) { + char *s = va_arg(argp, char *); + if (s == NULL) + break; + + mes->n_aliases ++; + mes->aliases = realloc(mes->aliases, sizeof(char *) * + mes->n_aliases); + if (mes->aliases == NULL) { + fprintf(stderr, "out of memory\n"); + exit(1); + } + + mes->aliases[mes->n_aliases - 1] = s; } - return mes; + va_end(argp); } /* - * machine_entry_add(): + * machine_entry_register(): * * Inserts a new machine_entry into the machine entries list. */ -void machine_entry_add(struct machine_entry *me, int arch) +void machine_entry_register(struct machine_entry *me, int arch) { struct machine_entry *prev, *next; @@ -1075,11 +1168,13 @@ "that actually work. Use the alias\nwhen selecting a machine type " "or subtype, not the real name.\n"); +#ifdef UNSTABLE_DEVEL debug("\n"); useremul_list_emuls(); debug("Userland emulation works for programs with the complexity" " of Hello World,\nbut not much more.\n"); +#endif }