--- trunk/src/cpu.c 2007/10/08 16:18:38 12 +++ trunk/src/cpu.c 2007/10/08 16:19:37 22 @@ -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.316 2005/08/16 05:37:09 debug Exp $ + * $Id: cpu.c,v 1.329 2006/01/16 04:48:08 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" @@ -43,7 +44,7 @@ extern int quiet_mode; extern int show_opcode_statistics; - +extern int dyntrans_backend_enable; static struct cpu_family *first_cpu_family = NULL; @@ -181,8 +182,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) @@ -244,6 +245,8 @@ fatal("cpu%i:\t", cpu->cpu_id); cpu->trace_tree_depth ++; + if (cpu->trace_tree_depth > 100) + cpu->trace_tree_depth = 100; for (i=0; itrace_tree_depth; i++) fatal(" "); @@ -292,9 +295,24 @@ */ void cpu_create_or_reset_tc(struct cpu *cpu) { - if (cpu->translation_cache == NULL) - cpu->translation_cache = zeroed_alloc(DYNTRANS_CACHE_SIZE + - DYNTRANS_CACHE_MARGIN); + 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); + } /* Create an empty table at the beginning of the translation cache: */ memset(cpu->translation_cache, 0, sizeof(uint32_t) @@ -307,8 +325,8 @@ * There might be other translation pointers that still point to * within the translation_cache region. Let's invalidate those too: */ - if (cpu->invalidate_code_translation_caches != NULL) - cpu->invalidate_code_translation_caches(cpu); + if (cpu->invalidate_code_translation != NULL) + cpu->invalidate_code_translation(cpu, 0, INVALIDATE_ALL); } @@ -334,7 +352,7 @@ * 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) { @@ -356,7 +374,7 @@ void cpu_list_available_types(void) { struct cpu_family *fp; - int iadd = 4; + int iadd = DEBUG_INDENTATION; fp = first_cpu_family; @@ -497,7 +515,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: */ @@ -636,6 +654,95 @@ } +#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(): * @@ -653,6 +760,18 @@ add_cpu_family(arm_cpu_family_init, ARCH_ARM); #endif +#ifdef ENABLE_AVR + add_cpu_family(avr_cpu_family_init, ARCH_AVR); +#endif + +#ifdef ENABLE_HPPA + add_cpu_family(hppa_cpu_family_init, ARCH_HPPA); +#endif + +#ifdef ENABLE_I960 + add_cpu_family(i960_cpu_family_init, ARCH_I960); +#endif + #ifdef ENABLE_IA64 add_cpu_family(ia64_cpu_family_init, ARCH_IA64); #endif @@ -669,6 +788,10 @@ add_cpu_family(ppc_cpu_family_init, ARCH_PPC); #endif +#ifdef ENABLE_SH + add_cpu_family(sh_cpu_family_init, ARCH_SH); +#endif + #ifdef ENABLE_SPARC add_cpu_family(sparc_cpu_family_init, ARCH_SPARC); #endif