--- trunk/src/cpus/cpu_sh.c 2007/10/08 16:20:10 26 +++ trunk/src/cpus/cpu_sh.c 2007/10/08 16:20:40 30 @@ -25,7 +25,7 @@ * SUCH DAMAGE. * * - * $Id: cpu_sh.c,v 1.16 2006/06/24 21:47:23 debug Exp $ + * $Id: cpu_sh.c,v 1.21 2006/07/25 21:49:14 debug Exp $ * * Hitachi SuperH ("SH") CPU emulation. * @@ -59,24 +59,37 @@ int sh_cpu_new(struct cpu *cpu, struct memory *mem, struct machine *machine, int cpu_id, char *cpu_type_name) { - if (strcasecmp(cpu_type_name, "SH") != 0) + int i = 0; + struct sh_cpu_type_def cpu_type_defs[] = SH_CPU_TYPE_DEFS; + + /* Scan the cpu_type_defs list for this cpu type: */ + while (cpu_type_defs[i].name != NULL) { + if (strcasecmp(cpu_type_defs[i].name, cpu_type_name) == 0) { + break; + } + i++; + } + if (cpu_type_defs[i].name == NULL) return 0; cpu->memory_rw = sh_memory_rw; - /* TODO: per CPU type? */ + cpu->cd.sh.cpu_type = cpu_type_defs[i]; cpu->byte_order = EMUL_LITTLE_ENDIAN; - cpu->is_32bit = 1; - cpu->cd.sh.bits = 32; - cpu->cd.sh.compact = 1; + cpu->is_32bit = cpu->cd.sh.cpu_type.bits == 32; + cpu->cd.sh.compact = 1; /* Default to 16-bit opcode mode */ + + cpu->translate_v2p = sh_translate_v2p; if (cpu->is_32bit) { + cpu->run_instr = sh32_run_instr; cpu->update_translation_table = sh32_update_translation_table; cpu->invalidate_translation_caches = sh32_invalidate_translation_caches; cpu->invalidate_code_translation = sh32_invalidate_code_translation; } else { + cpu->run_instr = sh_run_instr; cpu->update_translation_table = sh_update_translation_table; cpu->invalidate_translation_caches = sh_invalidate_translation_caches; @@ -89,6 +102,12 @@ debug("%s", cpu->name); } + /* Initial value of FPSCR (according to the SH4 manual): */ + cpu->cd.sh.fpscr = 0x00040001; + + /* Start in Privileged Mode: */ + cpu->cd.sh.sr = SH_SR_MD; + return 1; } @@ -100,8 +119,17 @@ */ void sh_cpu_list_available_types(void) { - debug("SH\n"); - /* TODO */ + int i = 0, j; + struct sh_cpu_type_def tdefs[] = SH_CPU_TYPE_DEFS; + + while (tdefs[i].name != NULL) { + debug("%s", tdefs[i].name); + for (j=10 - strlen(tdefs[i].name); j>0; j--) + debug(" "); + i ++; + if ((i % 6) == 0 || tdefs[i].name == NULL) + debug("\n"); + } } @@ -128,7 +156,7 @@ char *symbol; uint64_t offset; int i, x = cpu->cpu_id, nregs = cpu->cd.sh.compact? 16 : 64; - int bits32 = cpu->cd.sh.bits == 32; + int bits32 = cpu->cd.sh.cpu_type.bits == 32; if (gprs) { /* Special registers (pc, ...) first: */ @@ -142,6 +170,18 @@ debug("%016llx", (long long)cpu->pc); debug(" <%s>\n", symbol != NULL? symbol : " no symbol "); + debug("cpu%i: sr = %s, %s, %s, %s, %s, %s, imask=0x%x, " + "%s, %s\n", x, + (cpu->cd.sh.sr & SH_SR_MD)? "MD" : "!md", + (cpu->cd.sh.sr & SH_SR_RB)? "RB" : "!rb", + (cpu->cd.sh.sr & SH_SR_BL)? "BL" : "!bl", + (cpu->cd.sh.sr & SH_SR_FD)? "FD" : "!fd", + (cpu->cd.sh.sr & SH_SR_M)? "M" : "!m", + (cpu->cd.sh.sr & SH_SR_Q)? "Q" : "!q", + (cpu->cd.sh.sr & SH_SR_IMASK) >> SH_SR_IMASK_SHIFT, + (cpu->cd.sh.sr & SH_SR_S)? "S" : "!s", + (cpu->cd.sh.sr & SH_SR_T)? "T" : "!t"); + if (bits32) { /* 32-bit: */ for (i=0; icpus[cpunr]->pc; *match_register = 1; + } else if (name[0] == 'r' && isdigit((int)name[1])) { + int nr = atoi(name + 1); + if (nr >= 0 && nr < SH_N_GPRS) { + if (writeflag) + m->cpus[cpunr]->cd.sh.r[nr] = *valuep; + else + *valuep = m->cpus[cpunr]->cd.sh.r[nr]; + *match_register = 1; + } } } @@ -239,6 +288,23 @@ /* + * sh_update_sr(): + */ +void sh_update_sr(struct cpu *cpu, uint32_t new_sr) +{ + uint32_t old_sr = cpu->cd.sh.sr; + + if ((new_sr & SH_SR_RB) != (old_sr & SH_SR_RB)) { + fatal("sh_update_sr(): Register bank switching is not" + " implemented yet! TODO\n"); + exit(1); + } + + cpu->cd.sh.sr = new_sr; +} + + +/* * sh_cpu_disassemble_instr_compact(): * * SHcompact instruction disassembly. The top 4 bits of each 16-bit @@ -513,7 +579,7 @@ break; case 0x9: case 0xd: - addr = ((int8_t)lo8) * (hi4==9? 2 : 4); + addr = lo8 * (hi4==9? 2 : 4); addr += (dumpaddr & ~(hi4==9? 1 : 3)) + 4; debug("mov.%s\t0x%x,r%i\n", hi4==9? "w":"l", (int)addr, r8); break; @@ -586,7 +652,7 @@ if (cpu->machine->ncpus > 1 && running) debug("cpu%i: ", cpu->cpu_id); - if (cpu->cd.sh.bits == 32) + if (cpu->cd.sh.cpu_type.bits == 32) debug("%08x", (int)dumpaddr); else debug("%016llx", (long long)dumpaddr);