--- trunk/src/include/cpu.h 2007/10/08 16:19:37 22 +++ trunk/src/include/cpu.h 2007/10/08 16:19:56 24 @@ -28,7 +28,7 @@ * SUCH DAMAGE. * * - * $Id: cpu.h,v 1.62 2006/02/09 22:40:27 debug Exp $ + * $Id: cpu.h,v 1.75 2006/06/16 18:31:26 debug Exp $ * * CPU-related definitions. */ @@ -43,6 +43,17 @@ /* * Dyntrans misc declarations, used throughout the dyntrans code. + * + * Note that there is place for all instruction calls within a page, + * and then 2 more. The first one of these "extra" instruction slots is + * the end-of-page slot. It transfers control to the first instruction + * slot on the next (virtual) page. + * + * The second of these extra instruction slots is an additional + * end-of-page slot for delay-slot architectures. On e.g. MIPS, a branch + * instruction can "nullify" (skip) the delay-slot. If the end-of-page + * slot is skipped, then we end up one step after that. That's where the + * end_of_page2 slot is. :) */ #define DYNTRANS_MISC_DECLARATIONS(arch,ARCH,addrtype) struct \ arch ## _instr_call { \ @@ -52,7 +63,7 @@ \ /* Translation cache struct for each physical page: */ \ struct arch ## _tc_physpage { \ - struct arch ## _instr_call ics[ARCH ## _IC_ENTRIES_PER_PAGE+1];\ + struct arch ## _instr_call ics[ARCH ## _IC_ENTRIES_PER_PAGE+2];\ uint32_t next_ofs; /* (0 for end of chain) */ \ int flags; \ addrtype physaddr; \ @@ -67,6 +78,22 @@ int64_t timestamp; \ }; +#define DYNTRANS_MISC64_DECLARATIONS(arch,ARCH,tlbindextype) \ + struct arch ## _l3_64_table { \ + unsigned char *host_load[1 << ARCH ## _L3N]; \ + unsigned char *host_store[1 << ARCH ## _L3N]; \ + uint64_t phys_addr[1 << ARCH ## _L3N]; \ + tlbindextype vaddr_to_tlbindex[1 << ARCH ## _L3N]; \ + struct arch ## _tc_physpage *phys_page[1 << ARCH ## _L3N]; \ + struct arch ## _l3_64_table *next; \ + int refcount; \ + }; \ + struct arch ## _l2_64_table { \ + struct arch ## _l3_64_table *l3[1 << ARCH ## _L2N]; \ + struct arch ## _l2_64_table *next; \ + int refcount; \ + }; + /* * Dyntrans "Instruction Translation Cache": * @@ -144,11 +171,22 @@ * Usage: e.g. VPH64(alpha,ALPHA,uint8_t) * or VPH64(sparc,SPARC,uint16_t) * - * TODO + * l1_64 is an array containing poiners to l2 tables. + * + * l2_64_dummy is a pointer to a "dummy l2 table". Instead of having NULL + * pointers in l1_64 for unused slots, a pointer to the dummy table can be + * used. */ -#define VPH64(arch,ARCH,tlbindextype) \ - int dummy; +#define DYNTRANS_L1N 17 +#define VPH64(arch,ARCH,tlbindextype) \ + struct arch ## _l3_64_table *l3_64_dummy; \ + struct arch ## _l3_64_table *next_free_l3; \ + struct arch ## _l2_64_table *l2_64_dummy; \ + struct arch ## _l2_64_table *next_free_l2; \ + struct arch ## _l2_64_table *l1_64[1 << DYNTRANS_L1N]; + +/* Include all CPUs' header files here: */ #include "cpu_alpha.h" #include "cpu_arm.h" #include "cpu_avr.h" @@ -183,13 +221,12 @@ uint64_t *valuep, int *match_register); int (*disassemble_instr)(struct cpu *cpu, unsigned char *instr, int running, - uint64_t dumpaddr, int bintrans); + uint64_t dumpaddr); void (*register_dump)(struct cpu *cpu, int gprs, int coprocs); int (*run)(struct emul *emul, struct machine *machine); void (*dumpinfo)(struct cpu *cpu); - void (*show_full_statistics)(struct machine *m); void (*tlbdump)(struct machine *m, int x, int rawflag); int (*interrupt)(struct cpu *cpu, uint64_t irq_nr); @@ -197,6 +234,7 @@ uint64_t irq_nr); void (*functioncall_trace)(struct cpu *, uint64_t f, int n_args); + char *(*gdb_stub)(struct cpu *, char *cmd); }; @@ -211,6 +249,15 @@ #define TRANSLATIONS 1 #define COMBINATIONS 2 +/* Meaning of delay_slot: */ +#define NOT_DELAYED 0 +#define DELAYED 1 +#define TO_BE_DELAYED 2 +#define EXCEPTION_IN_DELAY_SLOT 0x100 + +#define N_SAFE_DYNTRANS_LIMIT_SHIFT 14 +#define N_SAFE_DYNTRANS_LIMIT ((1 << (N_SAFE_DYNTRANS_LIMIT_SHIFT - 1)) - 1) + #define DYNTRANS_CACHE_SIZE (16*1048576) #define DYNTRANS_CACHE_MARGIN 300000 @@ -218,55 +265,6 @@ #define PAGENR_TO_TABLE_INDEX(a) ((a) & (N_BASE_TABLE_ENTRIES-1)) -#ifdef DYNTRANS_BACKEND - -/* TODO: convert this into a fixed-size array? Might increase performace. */ -struct dtb_fixup { - struct dtb_fixup *next; - int type; /* Fixup type [optional] */ - void *addr; /* Address of the instruction - (in host memory) */ - size_t data; /* Emulation data. */ -}; - -struct translation_context { - /* Current address of where to emit host instructions: */ - /* (NULL means no translation is currently being done.) */ - void *p; - - /* index of the instr_call of the first translated instruction: */ - void *ic_page; - int start_instr_call_index; - - /* Fixups needed after first translation pass: */ - struct dtb_fixup *fixups; - - int n_simple; - - /* translation_buffer should have room for max_size bytes, - plus some margin. */ - unsigned char *translation_buffer; - size_t cur_size; -}; - -#define DTB_TRANSLATION_SIZE_MAX 3072 -#define DTB_TRANSLATION_SIZE_MARGIN 1024 - -void cpu_dtb_add_fixup(struct cpu *cpu, int type, void *addr, size_t data); -void cpu_dtb_do_fixups(struct cpu *cpu); - -void dtb_host_cacheinvalidate(void *p, size_t len); -int dtb_function_prologue(struct translation_context *ctx, size_t *sizep); -int dtb_function_epilogue(struct translation_context *ctx, size_t *sizep); -int dtb_generate_fcall(struct cpu *cpu, struct translation_context *ctx, - size_t *sizep, size_t f, size_t instr_call_ptr); -int dtb_generate_ptr_inc(struct cpu *cpu, struct translation_context *ctx, - size_t *sizep, void *ptr, int amount); - -#endif /* DYNTRANS_BACKEND */ - - - /* * The generic CPU struct: */ @@ -298,15 +296,11 @@ void (*invalidate_code_translation)(struct cpu *, uint64_t paddr, int flags); void (*useremul_syscall)(struct cpu *cpu, uint32_t code); + int (*instruction_has_delayslot)(struct cpu *cpu, + unsigned char *ib); uint64_t pc; -#ifdef TRACE_NULL_CRASHES - /* TODO: remove this, it's MIPS only */ - int trace_null_index; - uint64_t trace_null_addr[TRACE_NULL_N_ENTRIES]; -#endif - int trace_tree_depth; /* @@ -316,9 +310,9 @@ int n_translated_instrs; unsigned char *translation_cache; size_t translation_cache_cur_ofs; -#ifdef DYNTRANS_BACKEND - struct translation_context translation_context; -#endif + + uint64_t delay_jmpaddr; /* only used if delay_slot > 0 */ + int delay_slot; /* * CPU-family dependent: @@ -343,14 +337,14 @@ /* cpu.c: */ struct cpu *cpu_new(struct memory *mem, struct machine *machine, int cpu_id, char *cpu_type_name); -void cpu_show_full_statistics(struct machine *m); void cpu_tlbdump(struct machine *m, int x, int rawflag); void cpu_register_match(struct machine *m, char *name, int writeflag, uint64_t *valuep, int *match_register); void cpu_register_dump(struct machine *m, struct cpu *cpu, int gprs, int coprocs); 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); +char *cpu_gdb_stub(struct cpu *cpu, char *cmd); int cpu_interrupt(struct cpu *cpu, uint64_t irq_nr); int cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr); void cpu_functioncall_trace(struct cpu *cpu, uint64_t f); @@ -389,25 +383,8 @@ fp->interrupt = n ## _cpu_interrupt; \ fp->interrupt_ack = n ## _cpu_interrupt_ack; \ fp->functioncall_trace = n ## _cpu_functioncall_trace; \ - return 1; \ - } - -#define CPU_OLD_FAMILY_INIT(n,s) int n ## _cpu_family_init( \ - struct cpu_family *fp) { \ - /* Fill in the cpu_family struct with valid data for this arch. */ \ - fp->name = s; \ - fp->cpu_new = n ## _cpu_new; \ - fp->list_available_types = n ## _cpu_list_available_types; \ - fp->register_match = n ## _cpu_register_match; \ - fp->disassemble_instr = n ## _cpu_disassemble_instr; \ - fp->register_dump = n ## _cpu_register_dump; \ - fp->run = n ## _OLD_cpu_run; \ - fp->dumpinfo = n ## _cpu_dumpinfo; \ - fp->show_full_statistics = n ## _cpu_show_full_statistics; \ + fp->gdb_stub = n ## _cpu_gdb_stub; \ fp->tlbdump = n ## _cpu_tlbdump; \ - fp->interrupt = n ## _cpu_interrupt; \ - fp->interrupt_ack = n ## _cpu_interrupt_ack; \ - fp->functioncall_trace = n ## _cpu_functioncall_trace; \ return 1; \ }