25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $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 $ |
29 |
* |
* |
30 |
* Hitachi SuperH ("SH") CPU emulation. |
* Hitachi SuperH ("SH") CPU emulation. |
31 |
* |
* |
59 |
int sh_cpu_new(struct cpu *cpu, struct memory *mem, struct machine *machine, |
int sh_cpu_new(struct cpu *cpu, struct memory *mem, struct machine *machine, |
60 |
int cpu_id, char *cpu_type_name) |
int cpu_id, char *cpu_type_name) |
61 |
{ |
{ |
62 |
if (strcasecmp(cpu_type_name, "SH") != 0) |
int i = 0; |
63 |
|
struct sh_cpu_type_def cpu_type_defs[] = SH_CPU_TYPE_DEFS; |
64 |
|
|
65 |
|
/* Scan the cpu_type_defs list for this cpu type: */ |
66 |
|
while (cpu_type_defs[i].name != NULL) { |
67 |
|
if (strcasecmp(cpu_type_defs[i].name, cpu_type_name) == 0) { |
68 |
|
break; |
69 |
|
} |
70 |
|
i++; |
71 |
|
} |
72 |
|
if (cpu_type_defs[i].name == NULL) |
73 |
return 0; |
return 0; |
74 |
|
|
75 |
cpu->memory_rw = sh_memory_rw; |
cpu->memory_rw = sh_memory_rw; |
76 |
|
|
77 |
/* TODO: per CPU type? */ |
cpu->cd.sh.cpu_type = cpu_type_defs[i]; |
78 |
cpu->byte_order = EMUL_LITTLE_ENDIAN; |
cpu->byte_order = EMUL_LITTLE_ENDIAN; |
79 |
cpu->is_32bit = 1; |
cpu->is_32bit = cpu->cd.sh.cpu_type.bits == 32; |
80 |
cpu->cd.sh.bits = 32; |
cpu->cd.sh.compact = 1; /* Default to 16-bit opcode mode */ |
81 |
cpu->cd.sh.compact = 1; |
|
82 |
|
cpu->translate_v2p = sh_translate_v2p; |
83 |
|
|
84 |
if (cpu->is_32bit) { |
if (cpu->is_32bit) { |
85 |
|
cpu->run_instr = sh32_run_instr; |
86 |
cpu->update_translation_table = sh32_update_translation_table; |
cpu->update_translation_table = sh32_update_translation_table; |
87 |
cpu->invalidate_translation_caches = |
cpu->invalidate_translation_caches = |
88 |
sh32_invalidate_translation_caches; |
sh32_invalidate_translation_caches; |
89 |
cpu->invalidate_code_translation = |
cpu->invalidate_code_translation = |
90 |
sh32_invalidate_code_translation; |
sh32_invalidate_code_translation; |
91 |
} else { |
} else { |
92 |
|
cpu->run_instr = sh_run_instr; |
93 |
cpu->update_translation_table = sh_update_translation_table; |
cpu->update_translation_table = sh_update_translation_table; |
94 |
cpu->invalidate_translation_caches = |
cpu->invalidate_translation_caches = |
95 |
sh_invalidate_translation_caches; |
sh_invalidate_translation_caches; |
102 |
debug("%s", cpu->name); |
debug("%s", cpu->name); |
103 |
} |
} |
104 |
|
|
105 |
|
/* Initial value of FPSCR (according to the SH4 manual): */ |
106 |
|
cpu->cd.sh.fpscr = 0x00040001; |
107 |
|
|
108 |
|
/* Start in Privileged Mode: */ |
109 |
|
cpu->cd.sh.sr = SH_SR_MD; |
110 |
|
|
111 |
return 1; |
return 1; |
112 |
} |
} |
113 |
|
|
119 |
*/ |
*/ |
120 |
void sh_cpu_list_available_types(void) |
void sh_cpu_list_available_types(void) |
121 |
{ |
{ |
122 |
debug("SH\n"); |
int i = 0, j; |
123 |
/* TODO */ |
struct sh_cpu_type_def tdefs[] = SH_CPU_TYPE_DEFS; |
124 |
|
|
125 |
|
while (tdefs[i].name != NULL) { |
126 |
|
debug("%s", tdefs[i].name); |
127 |
|
for (j=10 - strlen(tdefs[i].name); j>0; j--) |
128 |
|
debug(" "); |
129 |
|
i ++; |
130 |
|
if ((i % 6) == 0 || tdefs[i].name == NULL) |
131 |
|
debug("\n"); |
132 |
|
} |
133 |
} |
} |
134 |
|
|
135 |
|
|
156 |
char *symbol; |
char *symbol; |
157 |
uint64_t offset; |
uint64_t offset; |
158 |
int i, x = cpu->cpu_id, nregs = cpu->cd.sh.compact? 16 : 64; |
int i, x = cpu->cpu_id, nregs = cpu->cd.sh.compact? 16 : 64; |
159 |
int bits32 = cpu->cd.sh.bits == 32; |
int bits32 = cpu->cd.sh.cpu_type.bits == 32; |
160 |
|
|
161 |
if (gprs) { |
if (gprs) { |
162 |
/* Special registers (pc, ...) first: */ |
/* Special registers (pc, ...) first: */ |
170 |
debug("%016llx", (long long)cpu->pc); |
debug("%016llx", (long long)cpu->pc); |
171 |
debug(" <%s>\n", symbol != NULL? symbol : " no symbol "); |
debug(" <%s>\n", symbol != NULL? symbol : " no symbol "); |
172 |
|
|
173 |
|
debug("cpu%i: sr = %s, %s, %s, %s, %s, %s, imask=0x%x, " |
174 |
|
"%s, %s\n", x, |
175 |
|
(cpu->cd.sh.sr & SH_SR_MD)? "MD" : "!md", |
176 |
|
(cpu->cd.sh.sr & SH_SR_RB)? "RB" : "!rb", |
177 |
|
(cpu->cd.sh.sr & SH_SR_BL)? "BL" : "!bl", |
178 |
|
(cpu->cd.sh.sr & SH_SR_FD)? "FD" : "!fd", |
179 |
|
(cpu->cd.sh.sr & SH_SR_M)? "M" : "!m", |
180 |
|
(cpu->cd.sh.sr & SH_SR_Q)? "Q" : "!q", |
181 |
|
(cpu->cd.sh.sr & SH_SR_IMASK) >> SH_SR_IMASK_SHIFT, |
182 |
|
(cpu->cd.sh.sr & SH_SR_S)? "S" : "!s", |
183 |
|
(cpu->cd.sh.sr & SH_SR_T)? "T" : "!t"); |
184 |
|
|
185 |
if (bits32) { |
if (bits32) { |
186 |
/* 32-bit: */ |
/* 32-bit: */ |
187 |
for (i=0; i<nregs; i++) { |
for (i=0; i<nregs; i++) { |
227 |
} else |
} else |
228 |
*valuep = m->cpus[cpunr]->pc; |
*valuep = m->cpus[cpunr]->pc; |
229 |
*match_register = 1; |
*match_register = 1; |
230 |
|
} else if (name[0] == 'r' && isdigit((int)name[1])) { |
231 |
|
int nr = atoi(name + 1); |
232 |
|
if (nr >= 0 && nr < SH_N_GPRS) { |
233 |
|
if (writeflag) |
234 |
|
m->cpus[cpunr]->cd.sh.r[nr] = *valuep; |
235 |
|
else |
236 |
|
*valuep = m->cpus[cpunr]->cd.sh.r[nr]; |
237 |
|
*match_register = 1; |
238 |
|
} |
239 |
} |
} |
240 |
} |
} |
241 |
|
|
288 |
|
|
289 |
|
|
290 |
/* |
/* |
291 |
|
* sh_update_sr(): |
292 |
|
*/ |
293 |
|
void sh_update_sr(struct cpu *cpu, uint32_t new_sr) |
294 |
|
{ |
295 |
|
uint32_t old_sr = cpu->cd.sh.sr; |
296 |
|
|
297 |
|
if ((new_sr & SH_SR_RB) != (old_sr & SH_SR_RB)) { |
298 |
|
fatal("sh_update_sr(): Register bank switching is not" |
299 |
|
" implemented yet! TODO\n"); |
300 |
|
exit(1); |
301 |
|
} |
302 |
|
|
303 |
|
cpu->cd.sh.sr = new_sr; |
304 |
|
} |
305 |
|
|
306 |
|
|
307 |
|
/* |
308 |
* sh_cpu_disassemble_instr_compact(): |
* sh_cpu_disassemble_instr_compact(): |
309 |
* |
* |
310 |
* SHcompact instruction disassembly. The top 4 bits of each 16-bit |
* SHcompact instruction disassembly. The top 4 bits of each 16-bit |
579 |
break; |
break; |
580 |
case 0x9: |
case 0x9: |
581 |
case 0xd: |
case 0xd: |
582 |
addr = ((int8_t)lo8) * (hi4==9? 2 : 4); |
addr = lo8 * (hi4==9? 2 : 4); |
583 |
addr += (dumpaddr & ~(hi4==9? 1 : 3)) + 4; |
addr += (dumpaddr & ~(hi4==9? 1 : 3)) + 4; |
584 |
debug("mov.%s\t0x%x,r%i\n", hi4==9? "w":"l", (int)addr, r8); |
debug("mov.%s\t0x%x,r%i\n", hi4==9? "w":"l", (int)addr, r8); |
585 |
break; |
break; |
652 |
if (cpu->machine->ncpus > 1 && running) |
if (cpu->machine->ncpus > 1 && running) |
653 |
debug("cpu%i: ", cpu->cpu_id); |
debug("cpu%i: ", cpu->cpu_id); |
654 |
|
|
655 |
if (cpu->cd.sh.bits == 32) |
if (cpu->cd.sh.cpu_type.bits == 32) |
656 |
debug("%08x", (int)dumpaddr); |
debug("%08x", (int)dumpaddr); |
657 |
else |
else |
658 |
debug("%016llx", (long long)dumpaddr); |
debug("%016llx", (long long)dumpaddr); |