/[gxemul]/trunk/src/cpus/cpu_sh.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/src/cpus/cpu_sh.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 36 - (show annotations)
Mon Oct 8 16:21:34 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 36223 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1497 2007/03/18 03:41:36 debug Exp $
20070224	Minor update to the initialization of the ns16550 in
		machine_walnut.c, to allow that machine type to boot with the
		new interrupt system (although it is still a dummy machine).
		Adding a wdc at 0x14000000 to machine_landisk.c, and fixing
		the SCIF serial interrupts of the SH4 cpu enough to get
		NetBSD/landisk booting from a disk image :-)  Adding a
		preliminary install instruction skeleton to guestoses.html.
20070306	Adding SH-IPL+G PROM emulation, and also passing the "end"
		symbol in r5 on bootup, for Landisk emulation. This is enough
		to get OpenBSD/landisk to install :)  Adding a preliminary
		install instruction skeleton to the documentation. SuperH
		emulation is still shaky, though :-/
20070307	Fixed a strangeness in memory_sh.c (read/write was never
		returned for any page). (Unknown whether this fixes any actual
		problems, though.)
20070308	dev_ram.c fix: invalidate code translations on writes to
		RAM, emulated as separate devices. Linux/dreamcast gets
		further in the boot process than before, but still bugs out
		in userland.
		Fixing bugs in the "stc.l gbr,@-rN" and "ldc.l @rN+,gbr" SuperH 
		instructions (they should NOT check the MD bit), allowing the
		Linux/dreamcast Live CD to reach userland correctly :-)
20070310	Changing the cpu name "Alpha" in src/useremul.c to "21364" to
		unbreak userland syscall emulation of FreeBSD/Alpha binaries.
20070314	Applying a patch from Michael Yaroslavtsev which fixes the
		previous Linux lib64 patch to the configure script.
20070315	Adding a (dummy) sun4v machine type, and SPARC T1 cpu type.
20070316	Creating a new directory, src/disk, and moving diskimage.c
		to it. Separating out bootblock loading stuff from emul.c into
		new files in src/disk.
		Adding some more SPARC registers.
20070318	Preparing/testing for a minirelease, 0.4.4.1.

==============  RELEASE 0.4.4.1  ==============


1 /*
2 * Copyright (C) 2005-2007 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: cpu_sh.c,v 1.62 2007/03/08 19:04:09 debug Exp $
29 *
30 * Hitachi SuperH ("SH") CPU emulation.
31 *
32 * TODO: It would be nice if this could encompass both 64-bit SH5, and
33 * 32-bit SH encodings. Right now, it only really supports 32-bit mode.
34 */
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <ctype.h>
40 #include <unistd.h>
41
42 #include "cpu.h"
43 #include "device.h"
44 #include "float_emul.h"
45 #include "interrupt.h"
46 #include "machine.h"
47 #include "memory.h"
48 #include "misc.h"
49 #include "settings.h"
50 #include "symbol.h"
51
52 #include "sh4_exception.h"
53 #include "sh4_mmu.h"
54
55
56 #define DYNTRANS_32
57 #define DYNTRANS_DELAYSLOT
58 #include "tmp_sh_head.c"
59
60
61 extern int quiet_mode;
62
63 void sh_pc_to_pointers(struct cpu *);
64
65
66 /*
67 * sh_cpu_new():
68 *
69 * Create a new SH cpu object.
70 *
71 * Returns 1 on success, 0 if there was no matching SH processor with
72 * this cpu_type_name.
73 */
74 int sh_cpu_new(struct cpu *cpu, struct memory *mem, struct machine *machine,
75 int cpu_id, char *cpu_type_name)
76 {
77 int i = 0;
78 struct sh_cpu_type_def cpu_type_defs[] = SH_CPU_TYPE_DEFS;
79
80 /* Scan the cpu_type_defs list for this cpu type: */
81 while (cpu_type_defs[i].name != NULL) {
82 if (strcasecmp(cpu_type_defs[i].name, cpu_type_name) == 0) {
83 break;
84 }
85 i++;
86 }
87 if (cpu_type_defs[i].name == NULL)
88 return 0;
89
90 cpu->memory_rw = sh_memory_rw;
91
92 cpu->cd.sh.cpu_type = cpu_type_defs[i];
93 cpu->byte_order = EMUL_LITTLE_ENDIAN;
94 cpu->is_32bit = cpu->cd.sh.cpu_type.bits == 32;
95 cpu->cd.sh.compact = 1; /* Default to 16-bit opcode mode */
96
97 if (!cpu->is_32bit) {
98 fatal("SH64 emulation not implemented. Sorry.\n");
99 exit(1);
100 }
101
102 cpu->instruction_has_delayslot = sh_cpu_instruction_has_delayslot;
103
104 cpu->translate_v2p = sh_translate_v2p;
105
106 cpu->run_instr = sh_run_instr;
107 cpu->update_translation_table = sh_update_translation_table;
108 cpu->invalidate_translation_caches =
109 sh_invalidate_translation_caches;
110 cpu->invalidate_code_translation =
111 sh_invalidate_code_translation;
112
113 /* Only show name and caches etc for CPU nr 0 (in SMP machines): */
114 if (cpu_id == 0) {
115 debug("%s", cpu->name);
116 }
117
118 /* Initial value of FPSCR (according to the SH4 manual): */
119 cpu->cd.sh.fpscr = 0x00040001;
120
121 /* (Initial value of the program counter on reboot is 0xA0000000.) */
122
123 /* Start in Privileged Mode: */
124 cpu->cd.sh.sr = SH_SR_MD | SH_SR_IMASK;
125
126 /* Stack pointer at end of physical RAM: */
127 cpu->cd.sh.r[15] = cpu->machine->physical_ram_in_mb * 1048576 - 64;
128
129 CPU_SETTINGS_ADD_REGISTER64("pc", cpu->pc);
130 CPU_SETTINGS_ADD_REGISTER32("sr", cpu->cd.sh.sr);
131 CPU_SETTINGS_ADD_REGISTER32("pr", cpu->cd.sh.pr);
132 CPU_SETTINGS_ADD_REGISTER32("vbr", cpu->cd.sh.vbr);
133 CPU_SETTINGS_ADD_REGISTER32("gbr", cpu->cd.sh.gbr);
134 CPU_SETTINGS_ADD_REGISTER32("macl", cpu->cd.sh.macl);
135 CPU_SETTINGS_ADD_REGISTER32("mach", cpu->cd.sh.mach);
136 CPU_SETTINGS_ADD_REGISTER32("expevt", cpu->cd.sh.expevt);
137 CPU_SETTINGS_ADD_REGISTER32("intevt", cpu->cd.sh.intevt);
138 CPU_SETTINGS_ADD_REGISTER32("tra", cpu->cd.sh.tra);
139 CPU_SETTINGS_ADD_REGISTER32("fpscr", cpu->cd.sh.fpscr);
140 CPU_SETTINGS_ADD_REGISTER32("fpul", cpu->cd.sh.fpul);
141 for (i=0; i<SH_N_GPRS; i++) {
142 char tmpstr[5];
143 snprintf(tmpstr, sizeof(tmpstr), "r%i", i);
144 CPU_SETTINGS_ADD_REGISTER32(tmpstr, cpu->cd.sh.r[i]);
145 }
146 for (i=0; i<SH_N_GPRS_BANKED; i++) {
147 char tmpstr[15];
148 snprintf(tmpstr, sizeof(tmpstr), "r%i_bank", i);
149 CPU_SETTINGS_ADD_REGISTER32(tmpstr, cpu->cd.sh.r_bank[i]);
150 }
151 for (i=0; i<SH_N_FPRS; i++) {
152 char tmpstr[6];
153 snprintf(tmpstr, sizeof(tmpstr), "fr%i", i);
154 CPU_SETTINGS_ADD_REGISTER32(tmpstr, cpu->cd.sh.fr[i]);
155 snprintf(tmpstr, sizeof(tmpstr), "xf%i", i);
156 CPU_SETTINGS_ADD_REGISTER32(tmpstr, cpu->cd.sh.xf[i]);
157 }
158 for (i=0; i<SH_N_ITLB_ENTRIES; i++) {
159 char tmpstr[15];
160 snprintf(tmpstr, sizeof(tmpstr), "itlb_hi_%i", i);
161 CPU_SETTINGS_ADD_REGISTER32(tmpstr, cpu->cd.sh.itlb_hi[i]);
162 snprintf(tmpstr, sizeof(tmpstr), "itlb_lo_%i", i);
163 CPU_SETTINGS_ADD_REGISTER32(tmpstr, cpu->cd.sh.itlb_lo[i]);
164 }
165 for (i=0; i<SH_N_UTLB_ENTRIES; i++) {
166 char tmpstr[15];
167 snprintf(tmpstr, sizeof(tmpstr), "utlb_hi_%i", i);
168 CPU_SETTINGS_ADD_REGISTER32(tmpstr, cpu->cd.sh.utlb_hi[i]);
169 snprintf(tmpstr, sizeof(tmpstr), "utlb_lo_%i", i);
170 CPU_SETTINGS_ADD_REGISTER32(tmpstr, cpu->cd.sh.utlb_lo[i]);
171 }
172
173 /* Register the CPU's interrupts: */
174 for (i=SH_INTEVT_NMI; i<0x1000; i+=0x20) {
175 struct interrupt template;
176 char name[100];
177 snprintf(name, sizeof(name), "%s.irq[0x%x]", cpu->path, i);
178 memset(&template, 0, sizeof(template));
179 template.line = i;
180 template.name = name;
181 template.extra = cpu;
182 template.interrupt_assert = sh_cpu_interrupt_assert;
183 template.interrupt_deassert = sh_cpu_interrupt_deassert;
184 interrupt_handler_register(&template);
185 }
186
187 /* SH4-specific memory mapped registers, TLBs, caches, etc: */
188 if (cpu->cd.sh.cpu_type.arch == 4)
189 device_add(machine, "sh4");
190
191 return 1;
192 }
193
194
195 /*
196 * sh_cpu_interrupt_assert():
197 */
198 void sh_cpu_interrupt_assert(struct interrupt *interrupt)
199 {
200 struct cpu *cpu = interrupt->extra;
201 int irq_nr = interrupt->line;
202 int word_index, bit_index;
203
204 /*
205 * Note: This gives higher interrupt priority to lower number
206 * interrupts. Hopefully this is correct.
207 */
208
209 if (cpu->cd.sh.int_to_assert == 0 || irq_nr < cpu->cd.sh.int_to_assert)
210 cpu->cd.sh.int_to_assert = irq_nr;
211
212 /*
213 * TODO: Keep track of all pending interrupts at multiple levels...
214 *
215 * This is just a quick hack:
216 */
217 cpu->cd.sh.int_level = 1;
218 if (irq_nr == SH_INTEVT_TMU0_TUNI0)
219 cpu->cd.sh.int_level = (cpu->cd.sh.intc_ipra >> 12) & 0xf;
220 if (irq_nr == SH_INTEVT_TMU1_TUNI1)
221 cpu->cd.sh.int_level = (cpu->cd.sh.intc_ipra >> 8) & 0xf;
222 if (irq_nr == SH_INTEVT_TMU2_TUNI2)
223 cpu->cd.sh.int_level = (cpu->cd.sh.intc_ipra >> 4) & 0xf;
224 if (irq_nr >= SH4_INTEVT_SCIF_ERI &&
225 irq_nr <= SH4_INTEVT_SCIF_TXI)
226 cpu->cd.sh.int_level = (cpu->cd.sh.intc_iprc >> 4) & 0xf;
227
228 irq_nr /= 0x20;
229 word_index = irq_nr / (sizeof(uint32_t)*8);
230 bit_index = irq_nr & ((sizeof(uint32_t)*8) - 1);
231
232 cpu->cd.sh.int_pending[word_index] |= (1 << bit_index);
233 }
234
235
236 /*
237 * sh_cpu_interrupt_deassert():
238 */
239 void sh_cpu_interrupt_deassert(struct interrupt *interrupt)
240 {
241 struct cpu *cpu = interrupt->extra;
242 int irq_nr = interrupt->line;
243 int word_index, bit_index;
244
245 if (cpu->cd.sh.int_to_assert == irq_nr) {
246 /*
247 * Rescan all interrupts to see if any are still asserted.
248 *
249 * Note: The scan only has to go from irq_nr + 0x20 to the max
250 * index, since any lower interrupt cannot be asserted
251 * at this time.
252 */
253 int i, max = 0x1000;
254 cpu->cd.sh.int_to_assert = 0;
255
256 for (i=irq_nr+0x20; i<max; i+=0x20) {
257 int j = i / 0x20;
258 int word_index = j / (sizeof(uint32_t)*8);
259 int bit_index = j & ((sizeof(uint32_t)*8) - 1);
260
261 /* Skip entire word if no bits are set: */
262 if (bit_index == 0 &&
263 cpu->cd.sh.int_pending[word_index] == 0)
264 i += (sizeof(uint32_t)*8 - 1) * 0x20;
265 else if (cpu->cd.sh.int_pending[word_index]
266 & (1 << bit_index)) {
267 cpu->cd.sh.int_to_assert = i;
268
269
270 /* Hack. TODO: Fix. */
271 cpu->cd.sh.int_level = 1;
272 if (i == SH_INTEVT_TMU0_TUNI0)
273 cpu->cd.sh.int_level = (cpu->cd.sh.intc_ipra >> 12) & 0xf;
274 if (i == SH_INTEVT_TMU1_TUNI1)
275 cpu->cd.sh.int_level = (cpu->cd.sh.intc_ipra >> 8) & 0xf;
276 if (i == SH_INTEVT_TMU2_TUNI2)
277 cpu->cd.sh.int_level = (cpu->cd.sh.intc_ipra >> 4) & 0xf;
278 if (i >= SH4_INTEVT_SCIF_ERI &&
279 i <= SH4_INTEVT_SCIF_TXI)
280 cpu->cd.sh.int_level = (cpu->cd.sh.intc_iprc >> 4) & 0xf;
281
282
283 break;
284 }
285 }
286 }
287
288 irq_nr /= 0x20;
289 word_index = irq_nr / (sizeof(uint32_t)*8);
290 bit_index = irq_nr & ((sizeof(uint32_t)*8) - 1);
291
292 cpu->cd.sh.int_pending[word_index] &= ~(1 << bit_index);
293 }
294
295
296 /*
297 * sh_cpu_list_available_types():
298 *
299 * Print a list of available SH CPU types.
300 */
301 void sh_cpu_list_available_types(void)
302 {
303 int i = 0, j;
304 struct sh_cpu_type_def tdefs[] = SH_CPU_TYPE_DEFS;
305
306 while (tdefs[i].name != NULL) {
307 debug("%s", tdefs[i].name);
308 for (j=10 - strlen(tdefs[i].name); j>0; j--)
309 debug(" ");
310 i ++;
311 if ((i % 6) == 0 || tdefs[i].name == NULL)
312 debug("\n");
313 }
314 }
315
316
317 /*
318 * sh_cpu_dumpinfo():
319 */
320 void sh_cpu_dumpinfo(struct cpu *cpu)
321 {
322 debug(" (%s-endian)\n",
323 cpu->byte_order == EMUL_BIG_ENDIAN? "Big" : "Little");
324 }
325
326
327 /*
328 * sh_cpu_instruction_has_delayslot():
329 *
330 * Return 1 if an opcode is a branch, 0 otherwise.
331 */
332 int sh_cpu_instruction_has_delayslot(struct cpu *cpu, unsigned char *ib)
333 {
334 uint16_t iword = *((uint16_t *)&ib[0]);
335 int hi4, lo4, lo8;
336
337 if (!cpu->is_32bit)
338 return 0;
339
340 if (cpu->byte_order == EMUL_BIG_ENDIAN)
341 iword = BE16_TO_HOST(iword);
342 else
343 iword = LE16_TO_HOST(iword);
344
345 hi4 = iword >> 12; lo4 = iword & 15; lo8 = iword & 255;
346
347 switch (hi4) {
348 case 0x0:
349 if (iword == 0x000b) /* rts */
350 return 1;
351 if (iword == 0x002b) /* rte */
352 return 1;
353 if (lo8 == 0x03) /* bsrf */
354 return 1;
355 if (lo8 == 0x23) /* braf */
356 return 1;
357 break;
358 case 0x4:
359 switch (lo8) {
360 case 0x0b: /* jsr */
361 case 0x2b: /* jmp */
362 return 1;
363 }
364 break;
365 case 0x8:
366 switch ((iword >> 8) & 0xf) {
367 case 0xd: /* bt/s */
368 case 0xf: /* bf/s */
369 return 1;
370 }
371 break;
372 case 0xa: /* bra */
373 case 0xb: /* bsr */
374 return 1;
375 }
376
377 return 0;
378 }
379
380
381 /*
382 * sh_cpu_register_dump():
383 *
384 * Dump cpu registers in a relatively readable format.
385 *
386 * gprs: set to non-zero to dump GPRs and some special-purpose registers.
387 * coprocs: set bit 0..3 to dump registers in coproc 0..3.
388 */
389 void sh_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
390 {
391 char *symbol;
392 uint64_t offset;
393 int i, x = cpu->cpu_id, nregs = cpu->cd.sh.compact? 16 : 64;
394
395 if (gprs) {
396 /* Special registers (pc, ...) first: */
397 symbol = get_symbol_name(&cpu->machine->symbol_context,
398 cpu->pc, &offset);
399
400 debug("cpu%i: pc = 0x%08"PRIx32, x, (uint32_t)cpu->pc);
401 debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
402
403 debug("cpu%i: sr = 0x%08"PRIx32" (%s, %s, %s, %s, %s, %s,"
404 " imask=0x%x, %s, %s)\n", x, (int32_t)cpu->cd.sh.sr,
405 (cpu->cd.sh.sr & SH_SR_MD)? "MD" : "!md",
406 (cpu->cd.sh.sr & SH_SR_RB)? "RB" : "!rb",
407 (cpu->cd.sh.sr & SH_SR_BL)? "BL" : "!bl",
408 (cpu->cd.sh.sr & SH_SR_FD)? "FD" : "!fd",
409 (cpu->cd.sh.sr & SH_SR_M)? "M" : "!m",
410 (cpu->cd.sh.sr & SH_SR_Q)? "Q" : "!q",
411 (cpu->cd.sh.sr & SH_SR_IMASK) >> SH_SR_IMASK_SHIFT,
412 (cpu->cd.sh.sr & SH_SR_S)? "S" : "!s",
413 (cpu->cd.sh.sr & SH_SR_T)? "T" : "!t");
414
415 symbol = get_symbol_name(&cpu->machine->symbol_context,
416 cpu->cd.sh.pr, &offset);
417 debug("cpu%i: pr = 0x%08"PRIx32, x, (uint32_t)cpu->cd.sh.pr);
418 debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
419
420 debug("cpu%i: mach = 0x%08"PRIx32" macl = 0x%08"PRIx32
421 " gbr = 0x%08"PRIx32"\n", x, (uint32_t)cpu->cd.sh.mach,
422 (uint32_t)cpu->cd.sh.macl, (uint32_t)cpu->cd.sh.gbr);
423
424 for (i=0; i<nregs; i++) {
425 if ((i % 4) == 0)
426 debug("cpu%i:", x);
427 debug(" r%-2i = 0x%08x ", i, (int)cpu->cd.sh.r[i]);
428 if ((i % 4) == 3)
429 debug("\n");
430 }
431 }
432
433 if (coprocs & 1) {
434 /* Floating point: */
435 debug("cpu%i: fpscr = 0x%08"PRIx32" fpul = 0x%08"PRIx32
436 "\n", x, cpu->cd.sh.fpscr, cpu->cd.sh.fpul);
437
438 for (i=0; i<SH_N_FPRS; i++) {
439 if ((i % 4) == 0)
440 debug("cpu%i:", x);
441 debug(" fr%-2i=0x%08x ", i, (int)cpu->cd.sh.fr[i]);
442 if ((i % 4) == 3)
443 debug("\n");
444 }
445
446 for (i=0; i<SH_N_FPRS; i++) {
447 if ((i % 4) == 0)
448 debug("cpu%i:", x);
449 debug(" xf%-2i=0x%08x ", i, (int)cpu->cd.sh.xf[i]);
450 if ((i % 4) == 3)
451 debug("\n");
452 }
453 }
454
455 if (coprocs & 2) {
456 /* System registers, etc: */
457 debug("cpu%i: vbr = 0x%08"PRIx32" sgr = 0x%08"PRIx32
458 "\n", x, cpu->cd.sh.vbr, cpu->cd.sh.sgr);
459 debug("cpu%i: spc = 0x%08"PRIx32" ssr = 0x%08"PRIx32"\n",
460 x, cpu->cd.sh.spc, cpu->cd.sh.ssr);
461 debug("cpu%i: expevt = 0x%"PRIx32" intevt = 0x%"PRIx32
462 " tra = 0x%"PRIx32"\n", x, cpu->cd.sh.expevt,
463 cpu->cd.sh.intevt, cpu->cd.sh.tra);
464
465 for (i=0; i<SH_N_GPRS_BANKED; i++) {
466 if ((i % 2) == 0)
467 debug("cpu%i:", x);
468 debug(" r%i_bank = 0x%08x ", i,
469 (int)cpu->cd.sh.r_bank[i]);
470 if ((i % 2) == 1)
471 debug("\n");
472 }
473 }
474 }
475
476
477 /*
478 * sh_cpu_tlbdump():
479 *
480 * Called from the debugger to dump the TLB in a readable format.
481 * x is the cpu number to dump, or -1 to dump all CPUs.
482 *
483 * If rawflag is nonzero, then the TLB contents isn't formated nicely,
484 * just dumped.
485 */
486 void sh_cpu_tlbdump(struct machine *m, int x, int rawflag)
487 {
488 int i, j;
489
490 for (j=0; j<m->ncpus; j++) {
491 struct cpu *cpu = m->cpus[j];
492
493 if (x >= 0 && j != x)
494 continue;
495
496 for (i=0; i<SH_N_ITLB_ENTRIES; i++)
497 printf("cpu%i: itlb_hi_%-2i = 0x%08"PRIx32" "
498 "itlb_lo_%-2i = 0x%08"PRIx32"\n", j, i,
499 (uint32_t) cpu->cd.sh.itlb_hi[i], i,
500 (uint32_t) cpu->cd.sh.itlb_lo[i]);
501 for (i=0; i<SH_N_UTLB_ENTRIES; i++)
502 printf("cpu%i: utlb_hi_%-2i = 0x%08"PRIx32" "
503 "utlb_lo_%-2i = 0x%08"PRIx32"\n", j, i,
504 (uint32_t) cpu->cd.sh.utlb_hi[i], i,
505 (uint32_t) cpu->cd.sh.utlb_lo[i]);
506 }
507 }
508
509
510 /*
511 * sh_cpu_gdb_stub():
512 *
513 * Execute a "remote GDB" command. Returns a newly allocated response string
514 * on success, NULL on failure.
515 */
516 char *sh_cpu_gdb_stub(struct cpu *cpu, char *cmd)
517 {
518 fatal("sh_cpu_gdb_stub(): TODO\n");
519 return NULL;
520 }
521
522
523 /*
524 * sh_update_sr():
525 *
526 * Writes a new value to the status register.
527 */
528 void sh_update_sr(struct cpu *cpu, uint32_t new_sr)
529 {
530 uint32_t old_sr = cpu->cd.sh.sr;
531
532 if ((new_sr & SH_SR_RB) != (old_sr & SH_SR_RB)) {
533 int i;
534 for (i=0; i<SH_N_GPRS_BANKED; i++) {
535 uint32_t tmp = cpu->cd.sh.r[i];
536 cpu->cd.sh.r[i] = cpu->cd.sh.r_bank[i];
537 cpu->cd.sh.r_bank[i] = tmp;
538 }
539 }
540
541 cpu->cd.sh.sr = new_sr;
542 }
543
544
545 /*
546 * sh_update_fpscr():
547 *
548 * Writes a new value to the floating-point status/control register.
549 */
550 void sh_update_fpscr(struct cpu *cpu, uint32_t new_fpscr)
551 {
552 uint32_t old_fpscr = cpu->cd.sh.fpscr;
553
554 if ((new_fpscr & SH_FPSCR_FR) != (old_fpscr & SH_FPSCR_FR)) {
555 int i;
556 for (i=0; i<SH_N_FPRS; i++) {
557 uint32_t tmp = cpu->cd.sh.fr[i];
558 cpu->cd.sh.fr[i] = cpu->cd.sh.xf[i];
559 cpu->cd.sh.xf[i] = tmp;
560 }
561 }
562
563 cpu->cd.sh.fpscr = new_fpscr;
564 }
565
566
567 /*
568 * sh_exception():
569 *
570 * Causes a transfer of control to an exception or interrupt handler.
571 * If intevt > 0, then it is an interrupt, otherwise an exception.
572 */
573 void sh_exception(struct cpu *cpu, int expevt, int intevt, uint32_t vaddr)
574 {
575 uint32_t vbr = cpu->cd.sh.vbr;
576
577 if (!quiet_mode) {
578 if (intevt > 0)
579 debug("[ interrupt 0x%03x", intevt);
580 else
581 debug("[ exception 0x%03x", expevt);
582
583 debug(", pc=0x%08"PRIx32" ", (uint32_t)vaddr);
584 if (intevt == 0)
585 debug("vaddr=0x%08"PRIx32" ", vaddr);
586
587 debug(" ]\n");
588 }
589
590 if (cpu->cd.sh.sr & SH_SR_BL) {
591 fatal("sh_exception(): BL bit already set. TODO\n");
592
593 /* This is actually OK in two cases: a User Break,
594 or on NMI interrupts if a special flag is set? */
595 /* TODO */
596
597 expevt = EXPEVT_RESET_POWER;
598 }
599
600 if (cpu->is_halted) {
601 /*
602 * If the exception occurred on a 'sleep' instruction, then let
603 * the instruction following the sleep instruction be the one
604 * where execution resumes when the interrupt service routine
605 * returns.
606 */
607 cpu->is_halted = 0;
608 cpu->pc += sizeof(uint16_t);
609 }
610
611 if (cpu->delay_slot) {
612 cpu->delay_slot = EXCEPTION_IN_DELAY_SLOT;
613 cpu->pc -= sizeof(uint16_t);
614 }
615
616 /* Stuff common to all exceptions: */
617 cpu->cd.sh.spc = cpu->pc;
618 cpu->cd.sh.ssr = cpu->cd.sh.sr;
619 cpu->cd.sh.sgr = cpu->cd.sh.r[15];
620 if (intevt > 0) {
621 cpu->cd.sh.intevt = intevt;
622 expevt = -1;
623 } else
624 cpu->cd.sh.expevt = expevt;
625 sh_update_sr(cpu, cpu->cd.sh.sr | SH_SR_MD | SH_SR_RB | SH_SR_BL);
626
627 /* Most exceptions set PC to VBR + 0x100. */
628 cpu->pc = vbr + 0x100;
629
630 /* Specific cases: */
631 switch (expevt) {
632
633 case -1: /* Interrupt */
634 cpu->pc = vbr + 0x600;
635 break;
636
637 case EXPEVT_RESET_POWER:
638 case EXPEVT_RESET_MANUAL:
639 cpu->pc = 0xa0000000;
640 cpu->cd.sh.vbr = 0x00000000;
641 sh_update_sr(cpu, (cpu->cd.sh.sr | SH_SR_IMASK) & ~SH_SR_FD);
642 break;
643
644 case EXPEVT_TLB_MISS_LD:
645 case EXPEVT_TLB_MISS_ST:
646 cpu->pc = vbr + 0x400;
647 case EXPEVT_TLB_PROT_LD:
648 case EXPEVT_TLB_PROT_ST:
649 case EXPEVT_TLB_MOD:
650 cpu->cd.sh.tea = vaddr;
651 cpu->cd.sh.pteh &= ~SH4_PTEH_VPN_MASK;
652 cpu->cd.sh.pteh |= (vaddr & SH4_PTEH_VPN_MASK);
653 break;
654
655 case EXPEVT_TRAPA:
656 /* Note: The TRA register is already set by the
657 implementation of the trapa instruction. See
658 cpu_sh_instr.c. */
659 cpu->cd.sh.spc += sizeof(uint16_t);
660 break;
661
662 case EXPEVT_RES_INST:
663 /*
664 * Note: Having this code here makes it possible to catch
665 * reserved instructions; during normal instruction execution,
666 * these are not very common.
667 */
668 #if 1
669 printf("\nRESERVED SuperH instruction at spc=%08"PRIx32"\n",
670 cpu->cd.sh.spc);
671 exit(1);
672 #else
673 break;
674 #endif
675
676 case EXPEVT_FPU_DISABLE:
677 break;
678
679 default:fatal("sh_exception(): exception 0x%x is not yet "
680 "implemented.\n", expevt);
681 exit(1);
682 }
683
684 sh_pc_to_pointers(cpu);
685 }
686
687
688 /*
689 * sh_cpu_disassemble_instr_compact():
690 *
691 * SHcompact instruction disassembly. The top 4 bits of each 16-bit
692 * instruction word is used as the main opcode. For most instructions, the
693 * lowest 4 or 8 bits then select sub-opcode.
694 */
695 int sh_cpu_disassemble_instr_compact(struct cpu *cpu, unsigned char *instr,
696 int running, uint64_t dumpaddr)
697 {
698 uint64_t addr;
699 uint16_t iword;
700 int hi4, lo4, lo8, r8, r4;
701
702 if (cpu->byte_order == EMUL_BIG_ENDIAN)
703 iword = (instr[0] << 8) + instr[1];
704 else
705 iword = (instr[1] << 8) + instr[0];
706
707 debug(": %04x %s\t", iword, cpu->delay_slot? "(d)" : "");
708 hi4 = iword >> 12; lo4 = iword & 15; lo8 = iword & 255;
709 r8 = (iword >> 8) & 15; r4 = (iword >> 4) & 15;
710
711 /*
712 * Decode the instruction:
713 */
714
715 switch (hi4) {
716 case 0x0:
717 if (lo8 == 0x02)
718 debug("stc\tsr,r%i\n", r8);
719 else if (lo8 == 0x03)
720 debug("bsrf\tr%i\n", r8);
721 else if (lo4 >= 4 && lo4 <= 6) {
722 if (lo4 == 0x4)
723 debug("mov.b\tr%i,@(r0,r%i)", r4, r8);
724 else if (lo4 == 0x5)
725 debug("mov.w\tr%i,@(r0,r%i)", r4, r8);
726 else if (lo4 == 0x6)
727 debug("mov.l\tr%i,@(r0,r%i)", r4, r8);
728 if (running) {
729 debug("\t; r0+r%i = 0x%08"PRIx32, r8,
730 cpu->cd.sh.r[0] + cpu->cd.sh.r[r8]);
731 }
732 debug("\n");
733 } else if (lo4 == 0x7)
734 debug("mul.l\tr%i,r%i\n", r4, r8);
735 else if (iword == 0x0008)
736 debug("clrt\n");
737 else if (iword == 0x0009)
738 debug("nop\n");
739 else if (lo8 == 0x0a)
740 debug("sts\tmach,r%i\n", r8);
741 else if (iword == 0x000b)
742 debug("rts\n");
743 else if (lo4 >= 0xc && lo4 <= 0xe) {
744 if (lo4 == 0xc)
745 debug("mov.b\t@(r0,r%i),r%i", r4, r8);
746 else if (lo4 == 0xd)
747 debug("mov.w\t@(r0,r%i),r%i", r4, r8);
748 else if (lo4 == 0xe)
749 debug("mov.l\t@(r0,r%i),r%i", r4, r8);
750 if (running) {
751 debug("\t; r0+r%i = 0x%08"PRIx32, r4,
752 cpu->cd.sh.r[0] + cpu->cd.sh.r[r4]);
753 }
754 debug("\n");
755 } else if (lo8 == 0x12)
756 debug("stc\tgbr,r%i\n", r8);
757 else if (iword == 0x0018)
758 debug("sett\n");
759 else if (iword == 0x0019)
760 debug("div0u\n");
761 else if (lo8 == 0x1a)
762 debug("sts\tmacl,r%i\n", r8);
763 else if (iword == 0x001b)
764 debug("sleep\n");
765 else if (lo8 == 0x22)
766 debug("stc\tvbr,r%i\n", r8);
767 else if (lo8 == 0x23)
768 debug("braf\tr%i\n", r8);
769 else if (iword == 0x0028)
770 debug("clrmac\n");
771 else if (lo8 == 0x29)
772 debug("movt\tr%i\n", r8);
773 else if (lo8 == 0x2a)
774 debug("sts\tpr,r%i\n", r8);
775 else if (iword == 0x002b)
776 debug("rte\n");
777 else if (lo8 == 0x32)
778 debug("stc\tssr,r%i\n", r8);
779 else if (iword == 0x0038)
780 debug("ldtlb\n");
781 else if (iword == 0x003b)
782 debug("brk\n");
783 else if (lo8 == 0x42)
784 debug("stc\tspc,r%i\n", r8);
785 else if (iword == 0x0048)
786 debug("clrs\n");
787 else if (iword == 0x0058)
788 debug("sets\n");
789 else if (lo8 == 0x5a)
790 debug("sts\tfpul,r%i\n", r8);
791 else if (lo8 == 0x6a)
792 debug("sts\tfpscr,r%i\n", r8);
793 else if ((lo8 & 0x8f) == 0x82)
794 debug("stc\tr%i_bank,r%i\n", (lo8 >> 4) & 7, r8);
795 else if (lo8 == 0x83)
796 debug("pref\t@r%i\n", r8);
797 else if (lo8 == 0x93)
798 debug("ocbi\t@r%i\n", r8);
799 else if (lo8 == 0xa3)
800 debug("ocbp\t@r%i\n", r8);
801 else if (lo8 == 0xb3)
802 debug("ocbwb\t@r%i\n", r8);
803 else if (lo8 == 0xc3)
804 debug("movca.l\tr0,@r%i\n", r8);
805 else if (lo8 == 0xfa)
806 debug("stc\tdbr,r%i\n", r8);
807 else if (iword == SH_INVALID_INSTR)
808 debug("gxemul_dreamcast_prom_emul\n");
809 else
810 debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x\n", hi4, lo8);
811 break;
812 case 0x1:
813 debug("mov.l\tr%i,@(%i,r%i)", r4, lo4 * 4, r8);
814 if (running) {
815 debug("\t; r%i+%i = 0x%08"PRIx32, r8, lo4 * 4,
816 cpu->cd.sh.r[r8] + lo4 * 4);
817 }
818 debug("\n");
819 break;
820 case 0x2:
821 if (lo4 == 0x0)
822 debug("mov.b\tr%i,@r%i\n", r4, r8);
823 else if (lo4 == 0x1)
824 debug("mov.w\tr%i,@r%i\n", r4, r8);
825 else if (lo4 == 0x2)
826 debug("mov.l\tr%i,@r%i\n", r4, r8);
827 else if (lo4 == 0x4)
828 debug("mov.b\tr%i,@-r%i\n", r4, r8);
829 else if (lo4 == 0x5)
830 debug("mov.w\tr%i,@-r%i\n", r4, r8);
831 else if (lo4 == 0x6)
832 debug("mov.l\tr%i,@-r%i\n", r4, r8);
833 else if (lo4 == 0x7)
834 debug("div0s\tr%i,r%i\n", r4, r8);
835 else if (lo4 == 0x8)
836 debug("tst\tr%i,r%i\n", r4, r8);
837 else if (lo4 == 0x9)
838 debug("and\tr%i,r%i\n", r4, r8);
839 else if (lo4 == 0xa)
840 debug("xor\tr%i,r%i\n", r4, r8);
841 else if (lo4 == 0xb)
842 debug("or\tr%i,r%i\n", r4, r8);
843 else if (lo4 == 0xc)
844 debug("cmp/str\tr%i,r%i\n", r4, r8);
845 else if (lo4 == 0xd)
846 debug("xtrct\tr%i,r%i\n", r4, r8);
847 else if (lo4 == 0xe)
848 debug("mulu.w\tr%i,r%i\n", r4, r8);
849 else if (lo4 == 0xf)
850 debug("muls.w\tr%i,r%i\n", r4, r8);
851 else
852 debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x\n", hi4, lo8);
853 break;
854 case 0x3:
855 if (lo4 == 0x0)
856 debug("cmp/eq\tr%i,r%i\n", r4, r8);
857 else if (lo4 == 0x2)
858 debug("cmp/hs\tr%i,r%i\n", r4, r8);
859 else if (lo4 == 0x3)
860 debug("cmp/ge\tr%i,r%i\n", r4, r8);
861 else if (lo4 == 0x4)
862 debug("div1\tr%i,r%i\n", r4, r8);
863 else if (lo4 == 0x5)
864 debug("dmulu.l\tr%i,r%i\n", r4, r8);
865 else if (lo4 == 0x6)
866 debug("cmp/hi\tr%i,r%i\n", r4, r8);
867 else if (lo4 == 0x7)
868 debug("cmp/gt\tr%i,r%i\n", r4, r8);
869 else if (lo4 == 0x8)
870 debug("sub\tr%i,r%i\n", r4, r8);
871 else if (lo4 == 0xa)
872 debug("subc\tr%i,r%i\n", r4, r8);
873 else if (lo4 == 0xb)
874 debug("subv\tr%i,r%i\n", r4, r8);
875 else if (lo4 == 0xc)
876 debug("add\tr%i,r%i\n", r4, r8);
877 else if (lo4 == 0xd)
878 debug("dmuls.l\tr%i,r%i\n", r4, r8);
879 else if (lo4 == 0xe)
880 debug("addc\tr%i,r%i\n", r4, r8);
881 else if (lo4 == 0xf)
882 debug("addv\tr%i,r%i\n", r4, r8);
883 else
884 debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x\n", hi4, lo8);
885 break;
886 case 0x4:
887 if (lo8 == 0x00)
888 debug("shll\tr%i\n", r8);
889 else if (lo8 == 0x01)
890 debug("shlr\tr%i\n", r8);
891 else if (lo8 == 0x02)
892 debug("sts.l\tmach,@-r%i\n", r8);
893 else if (lo8 == 0x03)
894 debug("stc.l\tsr,@-r%i\n", r8);
895 else if (lo8 == 0x04)
896 debug("rotl\tr%i\n", r8);
897 else if (lo8 == 0x05)
898 debug("rotr\tr%i\n", r8);
899 else if (lo8 == 0x06)
900 debug("lds.l\t@r%i+,mach\n", r8);
901 else if (lo8 == 0x07)
902 debug("ldc.l\t@r%i+,sr\n", r8);
903 else if (lo8 == 0x08)
904 debug("shll2\tr%i\n", r8);
905 else if (lo8 == 0x09)
906 debug("shlr2\tr%i\n", r8);
907 else if (lo8 == 0x0a)
908 debug("lds\tr%i,mach\n", r8);
909 else if (lo8 == 0x0b)
910 debug("jsr\t@r%i\n", r8);
911 else if (lo4 == 0xc)
912 debug("shad\tr%i,r%i\n", r4, r8);
913 else if (lo4 == 0xd)
914 debug("shld\tr%i,r%i\n", r4, r8);
915 else if (lo8 == 0x0e)
916 debug("ldc\tr%i,sr\n", r8);
917 else if (lo8 == 0x10)
918 debug("dt\tr%i\n", r8);
919 else if (lo8 == 0x11)
920 debug("cmp/pz\tr%i\n", r8);
921 else if (lo8 == 0x12)
922 debug("sts.l\tmacl,@-r%i\n", r8);
923 else if (lo8 == 0x13)
924 debug("stc.l\tgbr,@-r%i\n", r8);
925 else if (lo8 == 0x15)
926 debug("cmp/pl\tr%i\n", r8);
927 else if (lo8 == 0x16)
928 debug("lds.l\t@r%i+,macl\n", r8);
929 else if (lo8 == 0x17)
930 debug("ldc.l\t@r%i+,gbr\n", r8);
931 else if (lo8 == 0x18)
932 debug("shll8\tr%i\n", r8);
933 else if (lo8 == 0x19)
934 debug("shlr8\tr%i\n", r8);
935 else if (lo8 == 0x1a)
936 debug("lds\tr%i,macl\n", r8);
937 else if (lo8 == 0x1b)
938 debug("tas.b\t@r%i\n", r8);
939 else if (lo8 == 0x1e)
940 debug("ldc\tr%i,gbr\n", r8);
941 else if (lo8 == 0x20)
942 debug("shal\tr%i\n", r8);
943 else if (lo8 == 0x21)
944 debug("shar\tr%i\n", r8);
945 else if (lo8 == 0x22)
946 debug("sts.l\tpr,@-r%i\n", r8);
947 else if (lo8 == 0x23)
948 debug("stc.l\tvbr,@-r%i\n", r8);
949 else if (lo8 == 0x24)
950 debug("rotcl\tr%i\n", r8);
951 else if (lo8 == 0x25)
952 debug("rotcr\tr%i\n", r8);
953 else if (lo8 == 0x26)
954 debug("lds.l\t@r%i+,pr\n", r8);
955 else if (lo8 == 0x27)
956 debug("ldc.l\t@r%i+,vbr\n", r8);
957 else if (lo8 == 0x28)
958 debug("shll16\tr%i\n", r8);
959 else if (lo8 == 0x29)
960 debug("shlr16\tr%i\n", r8);
961 else if (lo8 == 0x2a)
962 debug("lds\tr%i,pr\n", r8);
963 else if (lo8 == 0x2b)
964 debug("jmp\t@r%i\n", r8);
965 else if (lo8 == 0x2e)
966 debug("ldc\tr%i,vbr\n", r8);
967 else if (lo8 == 0x33)
968 debug("stc.l\tssr,@-r%i\n", r8);
969 else if (lo8 == 0x37)
970 debug("ldc.l\t@r%i+,ssr\n", r8);
971 else if (lo8 == 0x3e)
972 debug("ldc\tr%i,ssr\n", r8);
973 else if (lo8 == 0x43)
974 debug("stc.l\tspc,@-r%i\n", r8);
975 else if (lo8 == 0x47)
976 debug("ldc.l\t@r%i+,spc\n", r8);
977 else if (lo8 == 0x4e)
978 debug("ldc\tr%i,spc\n", r8);
979 else if (lo8 == 0x52)
980 debug("sts.l\tfpul,@-r%i\n", r8);
981 else if (lo8 == 0x56)
982 debug("lds.l\t@r%i+,fpul\n", r8);
983 else if (lo8 == 0x5a)
984 debug("lds\tr%i,fpul\n", r8);
985 else if (lo8 == 0x62)
986 debug("sts.l\tfpscr,@-r%i\n", r8);
987 else if (lo8 == 0x66)
988 debug("lds.l\t@r%i+,fpscr\n", r8);
989 else if (lo8 == 0x6a)
990 debug("lds\tr%i,fpscr\n", r8);
991 else if ((lo8 & 0x8f) == 0x83)
992 debug("stc.l\tr%i_bank,@-r%i\n", (lo8 >> 4) & 7, r8);
993 else if ((lo8 & 0x8f) == 0x87)
994 debug("ldc.l\t@r%i,r%i_bank\n", r8, (lo8 >> 4) & 7, r8);
995 else if ((lo8 & 0x8f) == 0x8e)
996 debug("ldc\tr%i,r%i_bank\n", r8, (lo8 >> 4) & 7);
997 else if (lo8 == 0xfa)
998 debug("ldc\tr%i,dbr\n", r8);
999 else
1000 debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x\n", hi4, lo8);
1001 break;
1002 case 0x5:
1003 debug("mov.l\t@(%i,r%i),r%i", lo4 * 4, r4, r8);
1004 if (running) {
1005 debug("\t; r%i+%i = 0x%08"PRIx32, r4, lo4 * 4,
1006 cpu->cd.sh.r[r4] + lo4 * 4);
1007 }
1008 debug("\n");
1009 break;
1010 case 0x6:
1011 if (lo4 == 0x0)
1012 debug("mov.b\t@r%i,r%i\n", r4, r8);
1013 else if (lo4 == 0x1)
1014 debug("mov.w\t@r%i,r%i\n", r4, r8);
1015 else if (lo4 == 0x2)
1016 debug("mov.l\t@r%i,r%i\n", r4, r8);
1017 else if (lo4 == 0x3)
1018 debug("mov\tr%i,r%i\n", r4, r8);
1019 else if (lo4 == 0x4)
1020 debug("mov.b\t@r%i+,r%i\n", r4, r8);
1021 else if (lo4 == 0x5)
1022 debug("mov.w\t@r%i+,r%i\n", r4, r8);
1023 else if (lo4 == 0x6)
1024 debug("mov.l\t@r%i+,r%i\n", r4, r8);
1025 else if (lo4 == 0x7)
1026 debug("not\tr%i,r%i\n", r4, r8);
1027 else if (lo4 == 0x8)
1028 debug("swap.b\tr%i,r%i\n", r4, r8);
1029 else if (lo4 == 0x9)
1030 debug("swap.w\tr%i,r%i\n", r4, r8);
1031 else if (lo4 == 0xa)
1032 debug("negc\tr%i,r%i\n", r4, r8);
1033 else if (lo4 == 0xb)
1034 debug("neg\tr%i,r%i\n", r4, r8);
1035 else if (lo4 == 0xc)
1036 debug("extu.b\tr%i,r%i\n", r4, r8);
1037 else if (lo4 == 0xd)
1038 debug("extu.w\tr%i,r%i\n", r4, r8);
1039 else if (lo4 == 0xe)
1040 debug("exts.b\tr%i,r%i\n", r4, r8);
1041 else if (lo4 == 0xf)
1042 debug("exts.w\tr%i,r%i\n", r4, r8);
1043 else
1044 debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x\n", hi4, lo8);
1045 break;
1046 case 0x7:
1047 debug("add\t#%i,r%i\n", (int8_t)lo8, r8);
1048 break;
1049 case 0x8:
1050 if (r8 == 0 || r8 == 4) {
1051 if (r8 == 0x0)
1052 debug("mov.b\tr0,@(%i,r%i)", lo4, r4);
1053 else if (r8 == 0x4)
1054 debug("mov.b\t@(%i,r%i),r0", lo4, r4);
1055 if (running) {
1056 debug("\t; r%i+%i = 0x%08"PRIx32, r4, lo4,
1057 cpu->cd.sh.r[r4] + lo4);
1058 }
1059 debug("\n");
1060 } else if (r8 == 1 || r8 == 5) {
1061 if (r8 == 0x1)
1062 debug("mov.w\tr0,@(%i,r%i)", lo4 * 2, r4);
1063 else if (r8 == 0x5)
1064 debug("mov.w\t@(%i,r%i),r0", lo4 * 2, r4);
1065 if (running) {
1066 debug("\t; r%i+%i = 0x%08"PRIx32, r4, lo4 * 2,
1067 cpu->cd.sh.r[r4] + lo4 * 2);
1068 }
1069 debug("\n");
1070 } else if (r8 == 0x8) {
1071 debug("cmp/eq\t#%i,r0\n", (int8_t)lo8);
1072 } else if (r8 == 0x9 || r8 == 0xb || r8 == 0xd || r8 == 0xf) {
1073 addr = (int8_t)lo8;
1074 addr = dumpaddr + 4 + (addr << 1);
1075 debug("b%s%s\t0x%x\n",
1076 (r8 == 0x9 || r8 == 0xd)? "t" : "f",
1077 (r8 == 0x9 || r8 == 0xb)? "" : "/s", (int)addr);
1078 } else
1079 debug("UNIMPLEMENTED hi4=0x%x,0x%x\n", hi4, r8);
1080 break;
1081 case 0x9:
1082 case 0xd:
1083 addr = lo8 * (hi4==9? 2 : 4);
1084 addr += (dumpaddr & ~(hi4==9? 1 : 3)) + 4;
1085 debug("mov.%s\t0x%x,r%i\n", hi4==9? "w":"l", (int)addr, r8);
1086 break;
1087 case 0xa:
1088 case 0xb:
1089 addr = (int32_t)(int16_t)((iword & 0xfff) << 4);
1090 addr = ((int32_t)addr >> 3);
1091 addr += dumpaddr + 4;
1092 debug("%s\t0x%x\n", hi4==0xa? "bra":"bsr", (int)addr);
1093 break;
1094 case 0xc:
1095 if (r8 == 0x0)
1096 debug("mov.b\tr0,@(%i,gbr)\n", lo8);
1097 else if (r8 == 0x1)
1098 debug("mov.w\tr0,@(%i,gbr)\n", lo8 * 2);
1099 else if (r8 == 0x2)
1100 debug("mov.l\tr0,@(%i,gbr)\n", lo8 * 4);
1101 else if (r8 == 0x3)
1102 debug("trapa\t#%i\n", (uint8_t)lo8);
1103 else if (r8 == 0x4)
1104 debug("mov.b\t(%i,gbr),r0\n", lo8);
1105 else if (r8 == 0x5)
1106 debug("mov.w\t(%i,gbr),r0\n", lo8 * 2);
1107 else if (r8 == 0x6)
1108 debug("mov.l\t(%i,gbr),r0\n", lo8 * 4);
1109 else if (r8 == 0x7) {
1110 addr = lo8 * 4 + (dumpaddr & ~3) + 4;
1111 debug("mova\t0x%x,r0\n", (int)addr);
1112 } else if (r8 == 0x8)
1113 debug("tst\t#%i,r0\n", (uint8_t)lo8);
1114 else if (r8 == 0x9)
1115 debug("and\t#%i,r0\n", (uint8_t)lo8);
1116 else if (r8 == 0xa)
1117 debug("xor\t#%i,r0\n", (uint8_t)lo8);
1118 else if (r8 == 0xb)
1119 debug("or\t#%i,r0\n", (uint8_t)lo8);
1120 else if (r8 == 0xc)
1121 debug("tst.b\t#%i,@(r0,gbr)\n", (uint8_t)lo8);
1122 else if (r8 == 0xd)
1123 debug("and.b\t#%i,@(r0,gbr)\n", (uint8_t)lo8);
1124 else if (r8 == 0xe)
1125 debug("xor.b\t#%i,@(r0,gbr)\n", (uint8_t)lo8);
1126 else if (r8 == 0xf)
1127 debug("or.b\t#%i,@(r0,gbr)\n", (uint8_t)lo8);
1128 else
1129 debug("UNIMPLEMENTED hi4=0x%x,0x%x\n", hi4, r8);
1130 break;
1131 case 0xe:
1132 debug("mov\t#%i,r%i\n", (int8_t)lo8, r8);
1133 break;
1134 case 0xf:
1135 if (lo4 == 0x0)
1136 debug("fadd\t%sr%i,%sr%i\n",
1137 cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r4,
1138 cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1139 else if (lo4 == 0x1)
1140 debug("fsub\t%sr%i,%sr%i\n",
1141 cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r4,
1142 cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1143 else if (lo4 == 0x2)
1144 debug("fmul\t%sr%i,%sr%i\n",
1145 cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r4,
1146 cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1147 else if (lo4 == 0x3)
1148 debug("fdiv\t%sr%i,%sr%i\n",
1149 cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r4,
1150 cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1151 else if (lo4 == 0x4)
1152 debug("fcmp/eq\t%sr%i,%sr%i\n",
1153 cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r4,
1154 cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1155 else if (lo4 == 0x5)
1156 debug("fcmp/gt\t%sr%i,%sr%i\n",
1157 cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r4,
1158 cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1159 else if (lo4 == 0x6) {
1160 char *n = "fr";
1161 if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1162 n = (r8 & 1)? "xd" : "dr";
1163 r8 &= ~1;
1164 }
1165 debug("fmov\t@(r0,r%i),%s%i\n", r4, n, r8);
1166 } else if (lo4 == 0x7) {
1167 char *n = "fr";
1168 if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1169 n = (r4 & 1)? "xd" : "dr";
1170 r4 &= ~1;
1171 }
1172 debug("fmov\t%s%i,@(r0,r%i)\n", n, r4, r8);
1173 } else if (lo4 == 0x8) {
1174 char *n = "fr";
1175 if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1176 n = (r8 & 1)? "xd" : "dr";
1177 r8 &= ~1;
1178 }
1179 debug("fmov\t@r%i,%s%i\n", r4, n, r8);
1180 } else if (lo4 == 0x9) {
1181 char *n = "fr";
1182 if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1183 n = (r8 & 1)? "xd" : "dr";
1184 r8 &= ~1;
1185 }
1186 debug("fmov\t@r%i+,%s%i\n", r4, n, r8);
1187 } else if (lo4 == 0xa) {
1188 char *n = "fr";
1189 if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1190 n = (r4 & 1)? "xd" : "dr";
1191 r4 &= ~1;
1192 }
1193 debug("fmov\t%s%i,@r%i\n", n, r4, r8);
1194 } else if (lo4 == 0xb) {
1195 char *n = "fr";
1196 if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1197 n = (r4 & 1)? "xd" : "dr";
1198 r4 &= ~1;
1199 }
1200 debug("fmov\t%s%i,@-r%i\n", n, r4, r8);
1201 } else if (lo4 == 0xc) {
1202 char *n1 = "fr", *n2 = "fr";
1203 if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1204 n1 = (r4 & 1)? "xd" : "dr";
1205 n2 = (r8 & 1)? "xd" : "dr";
1206 r4 &= ~1; r8 &= ~1;
1207 }
1208 debug("fmov\t%s%i,%s%i\n", n1, r4, n2, r8);
1209 } else if (lo8 == 0x0d)
1210 debug("fsts\tfpul,fr%i\n", r8);
1211 else if (lo8 == 0x1d)
1212 debug("flds\tfr%i,fpul\n", r8);
1213 else if (lo8 == 0x2d)
1214 debug("float\tfpul,%sr%i\n",
1215 cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1216 else if (lo8 == 0x3d)
1217 debug("ftrc\t%sr%i,fpul\n",
1218 cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1219 else if (lo8 == 0x4d)
1220 debug("fneg\t%sr%i\n",
1221 cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1222 else if (lo8 == 0x5d)
1223 debug("fabs\t%sr%i\n",
1224 cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1225 else if (lo8 == 0x6d)
1226 debug("fsqrt\t%sr%i\n",
1227 cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1228 else if (lo8 == 0x8d)
1229 debug("fldi0\tfr%i\n", r8);
1230 else if (lo8 == 0x9d)
1231 debug("fldi1\tfr%i\n", r8);
1232 else if ((iword & 0x01ff) == 0x00fd)
1233 debug("fsca\tfpul,dr%i\n", r8);
1234 else if (iword == 0xf3fd)
1235 debug("fschg\n");
1236 else if (iword == 0xfbfd)
1237 debug("frchg\n");
1238 else if ((iword & 0xf3ff) == 0xf1fd)
1239 debug("ftrv\txmtrx,fv%i\n", r8 & 0xc);
1240 else if (lo4 == 0xe)
1241 debug("fmac\tfr0,fr%i,fr%i\n", r4, r8);
1242 else
1243 debug("UNIMPLEMENTED hi4=0x%x,0x%x\n", hi4, lo8);
1244 break;
1245 default:debug("UNIMPLEMENTED hi4=0x%x\n", hi4);
1246 }
1247
1248 return sizeof(iword);
1249 }
1250
1251
1252 /*
1253 * sh_cpu_disassemble_instr():
1254 *
1255 * Convert an instruction word into human readable format, for instruction
1256 * tracing.
1257 *
1258 * If running is 1, cpu->pc should be the address of the instruction.
1259 *
1260 * If running is 0, things that depend on the runtime environment (eg.
1261 * register contents) will not be shown, and addr will be used instead of
1262 * cpu->pc for relative addresses.
1263 */
1264 int sh_cpu_disassemble_instr(struct cpu *cpu, unsigned char *instr,
1265 int running, uint64_t dumpaddr)
1266 {
1267 uint64_t offset;
1268 uint32_t iword;
1269 char *symbol;
1270
1271 if (running)
1272 dumpaddr = cpu->pc;
1273
1274 symbol = get_symbol_name(&cpu->machine->symbol_context,
1275 dumpaddr, &offset);
1276 if (symbol != NULL && offset==0)
1277 debug("<%s>\n", symbol);
1278
1279 if (cpu->machine->ncpus > 1 && running)
1280 debug("cpu%i: ", cpu->cpu_id);
1281
1282 if (cpu->cd.sh.cpu_type.bits == 32)
1283 debug("%08x", (int)dumpaddr);
1284 else
1285 debug("%016llx", (long long)dumpaddr);
1286
1287 if (cpu->cd.sh.compact)
1288 return sh_cpu_disassemble_instr_compact(cpu, instr,
1289 running, dumpaddr);
1290
1291 if (cpu->byte_order == EMUL_BIG_ENDIAN)
1292 iword = (instr[0] << 24) + (instr[1] << 16) + (instr[2] << 8)
1293 + instr[3];
1294 else
1295 iword = (instr[3] << 24) + (instr[2] << 16) + (instr[1] << 8)
1296 + instr[0];
1297
1298 debug(": %08x\t", iword);
1299
1300 /*
1301 * Decode the instruction:
1302 */
1303
1304 debug("TODO\n");
1305
1306 return sizeof(iword);
1307 }
1308
1309
1310 #include "tmp_sh_tail.c"
1311

  ViewVC Help
Powered by ViewVC 1.1.26