--- trunk/src/cpu.c 2007/10/08 16:19:23 20 +++ 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.323 2005/11/13 22:34:21 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; @@ -294,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) @@ -358,7 +374,7 @@ void cpu_list_available_types(void) { struct cpu_family *fp; - int iadd = 4; + int iadd = DEBUG_INDENTATION; fp = first_cpu_family; @@ -499,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: */ @@ -638,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(): * @@ -679,10 +784,6 @@ add_cpu_family(mips_cpu_family_init, ARCH_MIPS); #endif -#ifdef ENABLE_NEWMIPS - add_cpu_family(newmips_cpu_family_init, ARCH_NEWMIPS); -#endif - #ifdef ENABLE_PPC add_cpu_family(ppc_cpu_family_init, ARCH_PPC); #endif