--- trunk/src/cpus/cpu_sh.c 2007/10/08 16:22:20 41 +++ trunk/src/cpus/cpu_sh.c 2007/10/08 16:22:32 42 @@ -25,12 +25,14 @@ * SUCH DAMAGE. * * - * $Id: cpu_sh.c,v 1.72 2007/04/28 09:44:35 debug Exp $ + * $Id: cpu_sh.c,v 1.75 2007/06/07 15:36:24 debug Exp $ * * Hitachi SuperH ("SH") CPU emulation. * * TODO: It would be nice if this could encompass both 64-bit SH5, and * 32-bit SH encodings. Right now, it only really supports 32-bit mode. + * + * TODO: This actually only works or SH4 so far, not SH3. */ #include @@ -48,6 +50,7 @@ #include "misc.h" #include "settings.h" #include "symbol.h" +#include "timer.h" #include "sh4_exception.h" #include "sh4_mmu.h" @@ -59,9 +62,13 @@ extern int quiet_mode; +extern int native_code_translation_enabled; void sh_pc_to_pointers(struct cpu *); +void sh3_cpu_interrupt_assert(struct interrupt *interrupt); +void sh3_cpu_interrupt_deassert(struct interrupt *interrupt); + /* * sh_cpu_new(): @@ -92,7 +99,6 @@ cpu->cd.sh.cpu_type = cpu_type_defs[i]; cpu->byte_order = EMUL_LITTLE_ENDIAN; cpu->is_32bit = cpu->cd.sh.cpu_type.bits == 32; - cpu->cd.sh.compact = 1; /* Default to 16-bit opcode mode */ if (!cpu->is_32bit) { fatal("SH64 emulation not implemented. Sorry.\n"); @@ -171,16 +177,28 @@ } /* Register the CPU's interrupts: */ - for (i=SH_INTEVT_NMI; i<0x1000; i+=0x20) { + if (cpu->cd.sh.cpu_type.arch == 4) { + for (i=SH_INTEVT_NMI; i<0x1000; i+=0x20) { + struct interrupt template; + char name[100]; + snprintf(name, sizeof(name), "%s.irq[0x%x]", + cpu->path, i); + memset(&template, 0, sizeof(template)); + template.line = i; + template.name = name; + template.extra = cpu; + template.interrupt_assert = sh_cpu_interrupt_assert; + template.interrupt_deassert = sh_cpu_interrupt_deassert; + interrupt_handler_register(&template); + } + } else { struct interrupt template; - char name[100]; - snprintf(name, sizeof(name), "%s.irq[0x%x]", cpu->path, i); memset(&template, 0, sizeof(template)); template.line = i; - template.name = name; + template.name = cpu->path; template.extra = cpu; - template.interrupt_assert = sh_cpu_interrupt_assert; - template.interrupt_deassert = sh_cpu_interrupt_deassert; + template.interrupt_assert = sh3_cpu_interrupt_assert; + template.interrupt_deassert = sh3_cpu_interrupt_deassert; interrupt_handler_register(&template); } @@ -206,6 +224,10 @@ sh_update_interrupt_priorities(cpu); + if (native_code_translation_enabled) + cpu->sampling_timer = timer_add(CPU_SAMPLE_TIMER_HZ, + sh_timer_sample_tick, cpu); + return 1; } @@ -269,6 +291,20 @@ /* + * sh3_cpu_interrupt_assert(): + * sh3_cpu_interrupt_deassert(): + */ +void sh3_cpu_interrupt_assert(struct interrupt *interrupt) +{ + /* TODO */ +} +void sh3_cpu_interrupt_deassert(struct interrupt *interrupt) +{ + /* TODO */ +} + + +/* * sh_cpu_interrupt_assert(): */ void sh_cpu_interrupt_assert(struct interrupt *interrupt) @@ -423,7 +459,7 @@ { char *symbol; uint64_t offset; - int i, x = cpu->cpu_id, nregs = cpu->cd.sh.compact? 16 : 64; + int i, x = cpu->cpu_id; if (gprs) { /* Special registers (pc, ...) first: */ @@ -454,7 +490,7 @@ " gbr = 0x%08"PRIx32"\n", x, (uint32_t)cpu->cd.sh.mach, (uint32_t)cpu->cd.sh.macl, (uint32_t)cpu->cd.sh.gbr); - for (i=0; icd.sh.r[i]); @@ -724,13 +760,22 @@ /* - * sh_cpu_disassemble_instr_compact(): + * sh_cpu_disassemble_instr(): * * SHcompact instruction disassembly. The top 4 bits of each 16-bit * instruction word is used as the main opcode. For most instructions, the * lowest 4 or 8 bits then select sub-opcode. + * + * This function convert an instruction word into human readable format, + * for instruction tracing. + * + * If running is 1, cpu->pc should be the address of the instruction. + * + * If running is 0, things that depend on the runtime environment (eg. + * register contents) will not be shown, and addr will be used instead of + * cpu->pc for relative addresses. */ -int sh_cpu_disassemble_instr_compact(struct cpu *cpu, unsigned char *instr, +int sh_cpu_disassemble_instr(struct cpu *cpu, unsigned char *instr, int running, uint64_t dumpaddr) { char *symbol; @@ -738,6 +783,19 @@ uint16_t iword; int hi4, lo4, lo8, r8, r4; + if (running) + dumpaddr = cpu->pc; + + symbol = get_symbol_name(&cpu->machine->symbol_context, + dumpaddr, &offset); + if (symbol != NULL && offset==0) + debug("<%s>\n", symbol); + + if (cpu->machine->ncpus > 1 && running) + debug("cpu%i: ", cpu->cpu_id); + + debug("%08"PRIx32, (uint32_t) dumpaddr); + if (cpu->byte_order == EMUL_BIG_ENDIAN) iword = (instr[0] << 8) + instr[1]; else @@ -747,6 +805,7 @@ hi4 = iword >> 12; lo4 = iword & 15; lo8 = iword & 255; r8 = (iword >> 8) & 15; r4 = (iword >> 4) & 15; + /* * Decode the instruction: */ @@ -1336,64 +1395,6 @@ return sizeof(iword); } - - -/* - * sh_cpu_disassemble_instr(): - * - * Convert an instruction word into human readable format, for instruction - * tracing. - * - * If running is 1, cpu->pc should be the address of the instruction. - * - * If running is 0, things that depend on the runtime environment (eg. - * register contents) will not be shown, and addr will be used instead of - * cpu->pc for relative addresses. - */ -int sh_cpu_disassemble_instr(struct cpu *cpu, unsigned char *instr, - int running, uint64_t dumpaddr) -{ - uint64_t offset; - uint32_t iword; - char *symbol; - - if (running) - dumpaddr = cpu->pc; - - symbol = get_symbol_name(&cpu->machine->symbol_context, - dumpaddr, &offset); - if (symbol != NULL && offset==0) - debug("<%s>\n", symbol); - - if (cpu->machine->ncpus > 1 && running) - debug("cpu%i: ", cpu->cpu_id); - - if (cpu->cd.sh.cpu_type.bits == 32) - debug("%08x", (int)dumpaddr); - else - debug("%016llx", (long long)dumpaddr); - - if (cpu->cd.sh.compact) - return sh_cpu_disassemble_instr_compact(cpu, instr, - running, dumpaddr); - - if (cpu->byte_order == EMUL_BIG_ENDIAN) - iword = (instr[0] << 24) + (instr[1] << 16) + (instr[2] << 8) - + instr[3]; - else - iword = (instr[3] << 24) + (instr[2] << 16) + (instr[1] << 8) - + instr[0]; - - debug(": %08x\t", iword); - - /* - * Decode the instruction: - */ - - debug("TODO\n"); - - return sizeof(iword); -} #include "tmp_sh_tail.c"