--- trunk/src/cpus/cpu_sh.c 2007/10/08 16:18:51 14 +++ trunk/src/cpus/cpu_sh.c 2007/10/08 16:20:40 30 @@ -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_sh.c,v 1.6 2005/09/04 14:38:17 debug Exp $ + * $Id: cpu_sh.c,v 1.21 2006/07/25 21:49:14 debug Exp $ * * Hitachi SuperH ("SH") CPU emulation. * @@ -59,27 +59,40 @@ 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_paddr = - sh32_invalidate_translation_caches_paddr; + 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_paddr = - sh_invalidate_translation_caches_paddr; + cpu->invalidate_translation_caches = + sh_invalidate_translation_caches; cpu->invalidate_code_translation = sh_invalidate_code_translation; } @@ -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"); + } } @@ -126,9 +154,9 @@ void sh_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs) { char *symbol; - uint64_t offset, tmp; + 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; + } } } /* - * sh_cpu_show_full_statistics(): - * - * Show detailed statistics on opcode usage on each cpu. - */ -void sh_cpu_show_full_statistics(struct machine *m) -{ - fatal("sh_cpu_show_full_statistics(): TODO\n"); -} - - -/* * sh_cpu_tlbdump(): * * Called from the debugger to dump the TLB in a readable format. @@ -213,7 +251,19 @@ */ void sh_cpu_tlbdump(struct machine *m, int x, int rawflag) { - fatal("sh_cpu_tlbdump(): TODO\n"); +} + + +/* + * sh_cpu_gdb_stub(): + * + * Execute a "remote GDB" command. Returns a newly allocated response string + * on success, NULL on failure. + */ +char *sh_cpu_gdb_stub(struct cpu *cpu, char *cmd) +{ + fatal("sh_cpu_gdb_stub(): TODO\n"); + return NULL; } @@ -238,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 @@ -245,12 +312,11 @@ * lowest 4 or 8 bits then select sub-opcode. */ int sh_cpu_disassemble_instr_compact(struct cpu *cpu, unsigned char *instr, - int running, uint64_t dumpaddr, int bintrans) + int running, uint64_t dumpaddr) { - uint64_t offset, addr; + uint64_t addr; uint16_t iword; int hi4, lo4, lo8, r8, r4; - char *symbol, *mnem = "ERROR"; if (cpu->byte_order == EMUL_BIG_ENDIAN) iword = (instr[0] << 8) + instr[1]; @@ -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; @@ -569,12 +635,11 @@ * cpu->pc for relative addresses. */ int sh_cpu_disassemble_instr(struct cpu *cpu, unsigned char *instr, - int running, uint64_t dumpaddr, int bintrans) + int running, uint64_t dumpaddr) { - uint64_t offset, addr; + uint64_t offset; uint32_t iword; - int hi6; - char *symbol, *mnem = "ERROR"; + char *symbol; if (running) dumpaddr = cpu->pc; @@ -587,14 +652,14 @@ 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); if (cpu->cd.sh.compact) return sh_cpu_disassemble_instr_compact(cpu, instr, - running, dumpaddr, bintrans); + running, dumpaddr); if (cpu->byte_order == EMUL_BIG_ENDIAN) iword = (instr[0] << 24) + (instr[1] << 16) + (instr[2] << 8)