/[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 38 - (show annotations)
Mon Oct 8 16:21:53 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 37551 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1515 2007/04/14 05:39:46 debug Exp $
20070324	Adding a "--debug" option to the configure script, to disable
		optimizations in unstable development builds.
		Moving out SCSI-specific stuff from diskimage.c into a new
		diskimage_scsicmd.c.
		Applying Hĺvard Eidnes' patch for SCSICDROM_READ_DISKINFO and
		SCSICDROM_READ_TRACKINFO. (Not really tested yet.)
		Implementing disk image "overlays" (to allow simple roll-back
		to previous disk state). Adding a 'V' disk flag for this, and
		updating the man page and misc.html.
20070325	Stability fix to cpu_dyntrans.c, when multiple physical pages
		share the same initial table entry. (The ppp == NULL check
		should be physpage_ofs == 0.) Bug found by analysing GXemul
		against a version patched for Godson.
		Fixing a second occurance of the same problem (also in
		cpu_dyntrans.c).
		Fixing a MAJOR physical page leak in cpu_dyntrans.c; pages
		weren't _added_ to the set of translated pages, they _replaced_
		all previous pages. It's amazing that this bug has been able
		to live for this long. (Triggered when emulating >128MB RAM.)
20070326	Removing the GDB debugging stub support; it was too hackish
		and ugly.
20070328	Moving around some native code generation skeleton code.
20070329	The -lm check in the configure script now also checks for sin()
		in addition to sqrt(). (Thanks to Nigel Horne for noticing that
		sqrt was not enough on Fedora Core 6.) (Not verified yet.)
20070330	Fixing an indexing bug in dev_sh4.c, found by using gcc version
		4.3.0 20070323.
20070331	Some more experimentation with native code generation.
20070404	Attempting to fix some more SH4 SCIF interrupt bugs; rewriting
		the SH interrupt assertion/deassertion code somewhat.
20070410	Splitting src/file.c into separate files in src/file/.
		Cleanup: Removing the dummy TS7200, Walnut, PB1000, and
		Meshcube emulation modes, and dev_epcom and dev_au1x00.
		Removing the experimental CHIP8/RCA180x code; it wasn't really
		working much lately, anyway. It was fun while it lasted.
		Also removing the experimental Transputer CPU support.
20070412	Moving the section about how the dynamic translation system
		works from intro.html to a separate translation.html file.
		Minor SH fixes; attempting to get OpenBSD/landisk to run
		without randomly bugging out, but no success yet.
20070413	SH SCI (serial bit interface) should now work together with a
		(new) RS5C313 clock device (for Landisk emulation).
20070414	Moving Redhat/MIPS down from supported to experimental, in
		guestoses.html.
		Preparing for a new release; doing some regression testing etc.

==============  RELEASE 0.4.5  ==============


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.66 2007/04/13 07:06:31 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 /*
192 * Interrupt Controller initial values, according to the
193 * SH7760 manual:
194 */
195 cpu->cd.sh.intc_iprd = 0xda74;
196 cpu->cd.sh.intc_intmsk00 = 0xf3ff7fff;
197 cpu->cd.sh.intc_intmsk04 = 0x00ffffff;
198 /* All others are zero. */
199
200 /* TODO: Initial priorities? */
201 cpu->cd.sh.intc_intpri00 = 0x33333333;
202 cpu->cd.sh.intc_intpri04 = 0x33333333;
203 cpu->cd.sh.intc_intpri08 = 0x33333333;
204 cpu->cd.sh.intc_intpri0c = 0x33333333;
205 }
206
207 sh_update_interrupt_priorities(cpu);
208
209 return 1;
210 }
211
212
213 /*
214 * sh_update_interrupt_priorities():
215 *
216 * SH interrupts are a bit complicated; there are several intc registers
217 * controlling priorities for various peripherals:
218 *
219 * Register: Bits 15..12 11..8 7..4 3..0
220 * --------- ----------- ----- ---- ----
221 * ipra TMU0 TMU1 TMU2 Reserved
222 * iprb WDT REF Reserved Reserved
223 * iprc GPIO DMAC Reserved H-UDI
224 * iprd IRL0 IRL1 IRL2 IRL3
225 *
226 * Register: 31..28 27..24 23..20 19..16 15..12 11..8 7..4 3..0
227 * --------- ------ ------ ------ ------ ------ ----- ---- ----
228 * intpri00 IRQ4 IRQ5 IRQ6 IRQ7 Rsrvd. Rsrvd. Rsrvd. Reserved
229 * intpri04 HCAN2,0 HCAN2,1 SSI(0) SSI(1) HAC(0) HAC(1) I2C(0) I2C(1)
230 * intpri08 USB LCDC DMABRG SCIF(0) SCIF(1) SCIF(2) SIM HSPI
231 * intpri0c Reserv. Reserv. MMCIF Reserv. MFI Rsrvd. ADC CMT
232 */
233 void sh_update_interrupt_priorities(struct cpu *cpu)
234 {
235 int i;
236
237 /*
238 * Set priorities of known interrupts, without affecting the
239 * SH_INT_ASSERTED bit:
240 */
241
242 for (i=SH4_INTEVT_IRQ0; i<=SH4_INTEVT_IRQ14; i+=0x20) {
243 cpu->cd.sh.int_prio_and_pending[i/0x20] &= ~SH_INT_PRIO_MASK;
244 cpu->cd.sh.int_prio_and_pending[i/0x20] |= (15 - ((i -
245 SH4_INTEVT_IRQ0) / 0x20));
246 }
247
248 cpu->cd.sh.int_prio_and_pending[SH_INTEVT_TMU0_TUNI0 / 0x20] &=
249 ~SH_INT_PRIO_MASK;
250 cpu->cd.sh.int_prio_and_pending[SH_INTEVT_TMU0_TUNI0 / 0x20] |=
251 (cpu->cd.sh.intc_ipra >> 12) & 0xf;
252
253 cpu->cd.sh.int_prio_and_pending[SH_INTEVT_TMU1_TUNI1 / 0x20] &=
254 ~SH_INT_PRIO_MASK;
255 cpu->cd.sh.int_prio_and_pending[SH_INTEVT_TMU1_TUNI1 / 0x20] |=
256 (cpu->cd.sh.intc_ipra >> 8) & 0xf;
257
258 cpu->cd.sh.int_prio_and_pending[SH_INTEVT_TMU2_TUNI2 / 0x20] &=
259 ~SH_INT_PRIO_MASK;
260 cpu->cd.sh.int_prio_and_pending[SH_INTEVT_TMU2_TUNI2 / 0x20] |=
261 (cpu->cd.sh.intc_ipra >> 4) & 0xf;
262
263 for (i=SH4_INTEVT_SCIF_ERI; i<=SH4_INTEVT_SCIF_TXI; i+=0x20) {
264 cpu->cd.sh.int_prio_and_pending[i/0x20] &= ~SH_INT_PRIO_MASK;
265 cpu->cd.sh.int_prio_and_pending[i/0x20] |=
266 ((cpu->cd.sh.intc_intpri08 >> 16) & 0xf);
267 }
268 }
269
270
271 /*
272 * sh_cpu_interrupt_assert():
273 */
274 void sh_cpu_interrupt_assert(struct interrupt *interrupt)
275 {
276 struct cpu *cpu = interrupt->extra;
277 int irq_nr = interrupt->line;
278 int index = irq_nr / 0x20;
279 int prio;
280
281 /* Assert the interrupt, and check its priority level: */
282 cpu->cd.sh.int_prio_and_pending[index] |= SH_INT_ASSERTED;
283 prio = cpu->cd.sh.int_prio_and_pending[index] & SH_INT_PRIO_MASK;
284
285 if (prio == 0) {
286 /* Interrupt not implemented? Hm. */
287 fatal("[ SH interrupt 0x%x, prio 0 (?), aborting ]\n", irq_nr);
288 exit(1);
289 }
290
291 if (cpu->cd.sh.int_to_assert == 0 || prio > cpu->cd.sh.int_level) {
292 cpu->cd.sh.int_to_assert = irq_nr;
293 cpu->cd.sh.int_level = prio;
294 }
295 }
296
297
298 /*
299 * sh_cpu_interrupt_deassert():
300 */
301 void sh_cpu_interrupt_deassert(struct interrupt *interrupt)
302 {
303 struct cpu *cpu = interrupt->extra;
304 int irq_nr = interrupt->line;
305 int index = irq_nr / 0x20;
306
307 /* Deassert the interrupt: */
308 if (cpu->cd.sh.int_prio_and_pending[index] & SH_INT_ASSERTED) {
309 cpu->cd.sh.int_prio_and_pending[index] &= ~SH_INT_ASSERTED;
310
311 /* Calculate new interrupt assertion: */
312 cpu->cd.sh.int_to_assert = 0;
313 cpu->cd.sh.int_level = 0;
314
315 /* NOTE/TODO: This is slow, but should hopefully work: */
316 for (index=0; index<0x1000/0x20; index++) {
317 uint8_t x = cpu->cd.sh.int_prio_and_pending[index];
318 uint8_t prio = x & SH_INT_PRIO_MASK;
319 if (x & SH_INT_ASSERTED &&
320 prio > cpu->cd.sh.int_level) {
321 cpu->cd.sh.int_to_assert = index * 0x20;
322 cpu->cd.sh.int_level = prio;
323 }
324 }
325 }
326 }
327
328
329 /*
330 * sh_cpu_list_available_types():
331 *
332 * Print a list of available SH CPU types.
333 */
334 void sh_cpu_list_available_types(void)
335 {
336 int i = 0, j;
337 struct sh_cpu_type_def tdefs[] = SH_CPU_TYPE_DEFS;
338
339 while (tdefs[i].name != NULL) {
340 debug("%s", tdefs[i].name);
341 for (j=10 - strlen(tdefs[i].name); j>0; j--)
342 debug(" ");
343 i ++;
344 if ((i % 6) == 0 || tdefs[i].name == NULL)
345 debug("\n");
346 }
347 }
348
349
350 /*
351 * sh_cpu_dumpinfo():
352 */
353 void sh_cpu_dumpinfo(struct cpu *cpu)
354 {
355 debug(" (%s-endian)\n",
356 cpu->byte_order == EMUL_BIG_ENDIAN? "Big" : "Little");
357 }
358
359
360 /*
361 * sh_cpu_instruction_has_delayslot():
362 *
363 * Return 1 if an opcode is a branch, 0 otherwise.
364 */
365 int sh_cpu_instruction_has_delayslot(struct cpu *cpu, unsigned char *ib)
366 {
367 uint16_t iword = *((uint16_t *)&ib[0]);
368 int hi4, lo4, lo8;
369
370 if (!cpu->is_32bit)
371 return 0;
372
373 if (cpu->byte_order == EMUL_BIG_ENDIAN)
374 iword = BE16_TO_HOST(iword);
375 else
376 iword = LE16_TO_HOST(iword);
377
378 hi4 = iword >> 12; lo4 = iword & 15; lo8 = iword & 255;
379
380 switch (hi4) {
381 case 0x0:
382 if (iword == 0x000b) /* rts */
383 return 1;
384 if (iword == 0x002b) /* rte */
385 return 1;
386 if (lo8 == 0x03) /* bsrf */
387 return 1;
388 if (lo8 == 0x23) /* braf */
389 return 1;
390 break;
391 case 0x4:
392 switch (lo8) {
393 case 0x0b: /* jsr */
394 case 0x2b: /* jmp */
395 return 1;
396 }
397 break;
398 case 0x8:
399 switch ((iword >> 8) & 0xf) {
400 case 0xd: /* bt/s */
401 case 0xf: /* bf/s */
402 return 1;
403 }
404 break;
405 case 0xa: /* bra */
406 case 0xb: /* bsr */
407 return 1;
408 }
409
410 return 0;
411 }
412
413
414 /*
415 * sh_cpu_register_dump():
416 *
417 * Dump cpu registers in a relatively readable format.
418 *
419 * gprs: set to non-zero to dump GPRs and some special-purpose registers.
420 * coprocs: set bit 0..3 to dump registers in coproc 0..3.
421 */
422 void sh_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
423 {
424 char *symbol;
425 uint64_t offset;
426 int i, x = cpu->cpu_id, nregs = cpu->cd.sh.compact? 16 : 64;
427
428 if (gprs) {
429 /* Special registers (pc, ...) first: */
430 symbol = get_symbol_name(&cpu->machine->symbol_context,
431 cpu->pc, &offset);
432
433 debug("cpu%i: pc = 0x%08"PRIx32, x, (uint32_t)cpu->pc);
434 debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
435
436 debug("cpu%i: sr = 0x%08"PRIx32" (%s, %s, %s, %s, %s, %s,"
437 " imask=0x%x, %s, %s)\n", x, (int32_t)cpu->cd.sh.sr,
438 (cpu->cd.sh.sr & SH_SR_MD)? "MD" : "!md",
439 (cpu->cd.sh.sr & SH_SR_RB)? "RB" : "!rb",
440 (cpu->cd.sh.sr & SH_SR_BL)? "BL" : "!bl",
441 (cpu->cd.sh.sr & SH_SR_FD)? "FD" : "!fd",
442 (cpu->cd.sh.sr & SH_SR_M)? "M" : "!m",
443 (cpu->cd.sh.sr & SH_SR_Q)? "Q" : "!q",
444 (cpu->cd.sh.sr & SH_SR_IMASK) >> SH_SR_IMASK_SHIFT,
445 (cpu->cd.sh.sr & SH_SR_S)? "S" : "!s",
446 (cpu->cd.sh.sr & SH_SR_T)? "T" : "!t");
447
448 symbol = get_symbol_name(&cpu->machine->symbol_context,
449 cpu->cd.sh.pr, &offset);
450 debug("cpu%i: pr = 0x%08"PRIx32, x, (uint32_t)cpu->cd.sh.pr);
451 debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
452
453 debug("cpu%i: mach = 0x%08"PRIx32" macl = 0x%08"PRIx32
454 " gbr = 0x%08"PRIx32"\n", x, (uint32_t)cpu->cd.sh.mach,
455 (uint32_t)cpu->cd.sh.macl, (uint32_t)cpu->cd.sh.gbr);
456
457 for (i=0; i<nregs; i++) {
458 if ((i % 4) == 0)
459 debug("cpu%i:", x);
460 debug(" r%-2i = 0x%08x ", i, (int)cpu->cd.sh.r[i]);
461 if ((i % 4) == 3)
462 debug("\n");
463 }
464 }
465
466 if (coprocs & 1) {
467 /* Floating point: */
468 debug("cpu%i: fpscr = 0x%08"PRIx32" fpul = 0x%08"PRIx32
469 "\n", x, cpu->cd.sh.fpscr, cpu->cd.sh.fpul);
470
471 for (i=0; i<SH_N_FPRS; i++) {
472 if ((i % 4) == 0)
473 debug("cpu%i:", x);
474 debug(" fr%-2i=0x%08x ", i, (int)cpu->cd.sh.fr[i]);
475 if ((i % 4) == 3)
476 debug("\n");
477 }
478
479 for (i=0; i<SH_N_FPRS; i++) {
480 if ((i % 4) == 0)
481 debug("cpu%i:", x);
482 debug(" xf%-2i=0x%08x ", i, (int)cpu->cd.sh.xf[i]);
483 if ((i % 4) == 3)
484 debug("\n");
485 }
486 }
487
488 if (coprocs & 2) {
489 /* System registers, etc: */
490 debug("cpu%i: vbr = 0x%08"PRIx32" sgr = 0x%08"PRIx32
491 "\n", x, cpu->cd.sh.vbr, cpu->cd.sh.sgr);
492 debug("cpu%i: spc = 0x%08"PRIx32" ssr = 0x%08"PRIx32"\n",
493 x, cpu->cd.sh.spc, cpu->cd.sh.ssr);
494 debug("cpu%i: expevt = 0x%"PRIx32" intevt = 0x%"PRIx32
495 " tra = 0x%"PRIx32"\n", x, cpu->cd.sh.expevt,
496 cpu->cd.sh.intevt, cpu->cd.sh.tra);
497
498 for (i=0; i<SH_N_GPRS_BANKED; i++) {
499 if ((i % 2) == 0)
500 debug("cpu%i:", x);
501 debug(" r%i_bank = 0x%08x ", i,
502 (int)cpu->cd.sh.r_bank[i]);
503 if ((i % 2) == 1)
504 debug("\n");
505 }
506 }
507 }
508
509
510 /*
511 * sh_cpu_tlbdump():
512 *
513 * Called from the debugger to dump the TLB in a readable format.
514 * x is the cpu number to dump, or -1 to dump all CPUs.
515 *
516 * If rawflag is nonzero, then the TLB contents isn't formated nicely,
517 * just dumped.
518 */
519 void sh_cpu_tlbdump(struct machine *m, int x, int rawflag)
520 {
521 int i, j;
522
523 for (j=0; j<m->ncpus; j++) {
524 struct cpu *cpu = m->cpus[j];
525
526 if (x >= 0 && j != x)
527 continue;
528
529 for (i=0; i<SH_N_ITLB_ENTRIES; i++)
530 printf("cpu%i: itlb_hi_%-2i = 0x%08"PRIx32" "
531 "itlb_lo_%-2i = 0x%08"PRIx32"\n", j, i,
532 (uint32_t) cpu->cd.sh.itlb_hi[i], i,
533 (uint32_t) cpu->cd.sh.itlb_lo[i]);
534 for (i=0; i<SH_N_UTLB_ENTRIES; i++)
535 printf("cpu%i: utlb_hi_%-2i = 0x%08"PRIx32" "
536 "utlb_lo_%-2i = 0x%08"PRIx32"\n", j, i,
537 (uint32_t) cpu->cd.sh.utlb_hi[i], i,
538 (uint32_t) cpu->cd.sh.utlb_lo[i]);
539 }
540 }
541
542
543 /*
544 * sh_update_sr():
545 *
546 * Writes a new value to the status register.
547 */
548 void sh_update_sr(struct cpu *cpu, uint32_t new_sr)
549 {
550 uint32_t old_sr = cpu->cd.sh.sr;
551
552 if ((new_sr & SH_SR_RB) != (old_sr & SH_SR_RB)) {
553 int i;
554 for (i=0; i<SH_N_GPRS_BANKED; i++) {
555 uint32_t tmp = cpu->cd.sh.r[i];
556 cpu->cd.sh.r[i] = cpu->cd.sh.r_bank[i];
557 cpu->cd.sh.r_bank[i] = tmp;
558 }
559 }
560
561 cpu->cd.sh.sr = new_sr;
562 }
563
564
565 /*
566 * sh_update_fpscr():
567 *
568 * Writes a new value to the floating-point status/control register.
569 */
570 void sh_update_fpscr(struct cpu *cpu, uint32_t new_fpscr)
571 {
572 uint32_t old_fpscr = cpu->cd.sh.fpscr;
573
574 if ((new_fpscr & SH_FPSCR_FR) != (old_fpscr & SH_FPSCR_FR)) {
575 int i;
576 for (i=0; i<SH_N_FPRS; i++) {
577 uint32_t tmp = cpu->cd.sh.fr[i];
578 cpu->cd.sh.fr[i] = cpu->cd.sh.xf[i];
579 cpu->cd.sh.xf[i] = tmp;
580 }
581 }
582
583 cpu->cd.sh.fpscr = new_fpscr;
584 }
585
586
587 /*
588 * sh_exception():
589 *
590 * Causes a transfer of control to an exception or interrupt handler.
591 * If intevt > 0, then it is an interrupt, otherwise an exception.
592 *
593 * vaddr contains the faulting address, on TLB exceptions.
594 */
595 void sh_exception(struct cpu *cpu, int expevt, int intevt, uint32_t vaddr)
596 {
597 uint32_t vbr = cpu->cd.sh.vbr;
598
599 if (!quiet_mode) {
600 if (intevt > 0)
601 debug("[ interrupt 0x%03x", intevt);
602 else
603 debug("[ exception 0x%03x", expevt);
604
605 debug(", pc=0x%08"PRIx32" ", (uint32_t)cpu->pc);
606 if (intevt == 0)
607 debug("vaddr=0x%08"PRIx32" ", vaddr);
608
609 debug(" ]\n");
610 }
611
612 if (cpu->cd.sh.sr & SH_SR_BL) {
613 fatal("[ sh_exception(): BL bit already set. ]\n");
614
615 /* This is actually OK in two cases: a User Break,
616 or on NMI interrupts if a special flag is set? */
617 /* TODO */
618
619 expevt = EXPEVT_RESET_POWER;
620 }
621
622 if (cpu->is_halted) {
623 /*
624 * If the exception occurred on a 'sleep' instruction, then let
625 * the instruction following the sleep instruction be the one
626 * where execution resumes when the interrupt service routine
627 * returns.
628 */
629 cpu->is_halted = 0;
630 cpu->pc += sizeof(uint16_t);
631 }
632
633 if (cpu->delay_slot) {
634 cpu->delay_slot = EXCEPTION_IN_DELAY_SLOT;
635 cpu->pc -= sizeof(uint16_t);
636 }
637
638
639 /*
640 * Stuff common to all exceptions:
641 */
642
643 cpu->cd.sh.spc = cpu->pc;
644 cpu->cd.sh.ssr = cpu->cd.sh.sr;
645 cpu->cd.sh.sgr = cpu->cd.sh.r[15];
646
647 if (intevt > 0) {
648 cpu->cd.sh.intevt = intevt;
649 expevt = -1;
650 } else {
651 cpu->cd.sh.expevt = expevt;
652 }
653
654 sh_update_sr(cpu, cpu->cd.sh.sr | SH_SR_MD | SH_SR_RB | SH_SR_BL);
655
656 /* Most exceptions set PC to VBR + 0x100. */
657 cpu->pc = vbr + 0x100;
658
659
660 /* Specific cases: */
661 switch (expevt) {
662
663 case -1: /* Interrupt */
664 cpu->pc = vbr + 0x600;
665 break;
666
667 case EXPEVT_RESET_POWER:
668 case EXPEVT_RESET_MANUAL:
669 cpu->pc = 0xa0000000;
670 cpu->cd.sh.vbr = 0x00000000;
671 sh_update_sr(cpu, (cpu->cd.sh.sr | SH_SR_IMASK) & ~SH_SR_FD);
672 break;
673
674 case EXPEVT_TLB_MISS_LD:
675 case EXPEVT_TLB_MISS_ST:
676 cpu->pc = vbr + 0x400;
677 case EXPEVT_TLB_PROT_LD:
678 case EXPEVT_TLB_PROT_ST:
679 case EXPEVT_TLB_MOD:
680 cpu->cd.sh.tea = vaddr;
681 cpu->cd.sh.pteh &= ~SH4_PTEH_VPN_MASK;
682 cpu->cd.sh.pteh |= (vaddr & SH4_PTEH_VPN_MASK);
683 break;
684
685 case EXPEVT_TRAPA:
686 /*
687 * Note: The TRA register is already set by the implementation
688 * of the trapa instruction. See cpu_sh_instr.c for details.
689 * Here, spc is incremented, so that a return from the trap
690 * handler transfers control to the instruction _following_
691 * the trapa.
692 */
693 cpu->cd.sh.spc += sizeof(uint16_t);
694 break;
695
696 case EXPEVT_RES_INST:
697 /*
698 * Note: Having this code here makes it possible to catch
699 * reserved instructions; during normal instruction execution,
700 * these are not very common.
701 */
702 #if 1
703 printf("\nRESERVED SuperH instruction at spc=%08"PRIx32"\n",
704 cpu->cd.sh.spc);
705 exit(1);
706 #else
707 break;
708 #endif
709
710 case EXPEVT_FPU_DISABLE:
711 break;
712
713 default:fatal("sh_exception(): exception 0x%x is not yet "
714 "implemented.\n", expevt);
715 exit(1);
716 }
717
718 sh_pc_to_pointers(cpu);
719 }
720
721
722 /*
723 * sh_cpu_disassemble_instr_compact():
724 *
725 * SHcompact instruction disassembly. The top 4 bits of each 16-bit
726 * instruction word is used as the main opcode. For most instructions, the
727 * lowest 4 or 8 bits then select sub-opcode.
728 */
729 int sh_cpu_disassemble_instr_compact(struct cpu *cpu, unsigned char *instr,
730 int running, uint64_t dumpaddr)
731 {
732 uint64_t addr;
733 uint16_t iword;
734 int hi4, lo4, lo8, r8, r4;
735
736 if (cpu->byte_order == EMUL_BIG_ENDIAN)
737 iword = (instr[0] << 8) + instr[1];
738 else
739 iword = (instr[1] << 8) + instr[0];
740
741 debug(": %04x %s\t", iword, cpu->delay_slot? "(d)" : "");
742 hi4 = iword >> 12; lo4 = iword & 15; lo8 = iword & 255;
743 r8 = (iword >> 8) & 15; r4 = (iword >> 4) & 15;
744
745 /*
746 * Decode the instruction:
747 */
748
749 switch (hi4) {
750 case 0x0:
751 if (lo8 == 0x02)
752 debug("stc\tsr,r%i\n", r8);
753 else if (lo8 == 0x03)
754 debug("bsrf\tr%i\n", r8);
755 else if (lo4 >= 4 && lo4 <= 6) {
756 if (lo4 == 0x4)
757 debug("mov.b\tr%i,@(r0,r%i)", r4, r8);
758 else if (lo4 == 0x5)
759 debug("mov.w\tr%i,@(r0,r%i)", r4, r8);
760 else if (lo4 == 0x6)
761 debug("mov.l\tr%i,@(r0,r%i)", r4, r8);
762 if (running) {
763 debug("\t; r0+r%i = 0x%08"PRIx32, r8,
764 cpu->cd.sh.r[0] + cpu->cd.sh.r[r8]);
765 }
766 debug("\n");
767 } else if (lo4 == 0x7)
768 debug("mul.l\tr%i,r%i\n", r4, r8);
769 else if (iword == 0x0008)
770 debug("clrt\n");
771 else if (iword == 0x0009)
772 debug("nop\n");
773 else if (lo8 == 0x0a)
774 debug("sts\tmach,r%i\n", r8);
775 else if (iword == 0x000b)
776 debug("rts\n");
777 else if (lo4 >= 0xc && lo4 <= 0xe) {
778 if (lo4 == 0xc)
779 debug("mov.b\t@(r0,r%i),r%i", r4, r8);
780 else if (lo4 == 0xd)
781 debug("mov.w\t@(r0,r%i),r%i", r4, r8);
782 else if (lo4 == 0xe)
783 debug("mov.l\t@(r0,r%i),r%i", r4, r8);
784 if (running) {
785 debug("\t; r0+r%i = 0x%08"PRIx32, r4,
786 cpu->cd.sh.r[0] + cpu->cd.sh.r[r4]);
787 }
788 debug("\n");
789 } else if (lo8 == 0x12)
790 debug("stc\tgbr,r%i\n", r8);
791 else if (iword == 0x0018)
792 debug("sett\n");
793 else if (iword == 0x0019)
794 debug("div0u\n");
795 else if (lo8 == 0x1a)
796 debug("sts\tmacl,r%i\n", r8);
797 else if (iword == 0x001b)
798 debug("sleep\n");
799 else if (lo8 == 0x22)
800 debug("stc\tvbr,r%i\n", r8);
801 else if (lo8 == 0x23)
802 debug("braf\tr%i\n", r8);
803 else if (iword == 0x0028)
804 debug("clrmac\n");
805 else if (lo8 == 0x29)
806 debug("movt\tr%i\n", r8);
807 else if (lo8 == 0x2a)
808 debug("sts\tpr,r%i\n", r8);
809 else if (iword == 0x002b)
810 debug("rte\n");
811 else if (lo8 == 0x32)
812 debug("stc\tssr,r%i\n", r8);
813 else if (iword == 0x0038)
814 debug("ldtlb\n");
815 else if (iword == 0x003b)
816 debug("brk\n");
817 else if (lo8 == 0x42)
818 debug("stc\tspc,r%i\n", r8);
819 else if (iword == 0x0048)
820 debug("clrs\n");
821 else if (iword == 0x0058)
822 debug("sets\n");
823 else if (lo8 == 0x5a)
824 debug("sts\tfpul,r%i\n", r8);
825 else if (lo8 == 0x6a)
826 debug("sts\tfpscr,r%i\n", r8);
827 else if ((lo8 & 0x8f) == 0x82)
828 debug("stc\tr%i_bank,r%i\n", (lo8 >> 4) & 7, r8);
829 else if (lo8 == 0x83)
830 debug("pref\t@r%i\n", r8);
831 else if (lo8 == 0x93)
832 debug("ocbi\t@r%i\n", r8);
833 else if (lo8 == 0xa3)
834 debug("ocbp\t@r%i\n", r8);
835 else if (lo8 == 0xb3)
836 debug("ocbwb\t@r%i\n", r8);
837 else if (lo8 == 0xc3)
838 debug("movca.l\tr0,@r%i\n", r8);
839 else if (lo8 == 0xfa)
840 debug("stc\tdbr,r%i\n", r8);
841 else if (iword == SH_INVALID_INSTR)
842 debug("gxemul_dreamcast_prom_emul\n");
843 else
844 debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x\n", hi4, lo8);
845 break;
846 case 0x1:
847 debug("mov.l\tr%i,@(%i,r%i)", r4, lo4 * 4, r8);
848 if (running) {
849 debug("\t; r%i+%i = 0x%08"PRIx32, r8, lo4 * 4,
850 cpu->cd.sh.r[r8] + lo4 * 4);
851 }
852 debug("\n");
853 break;
854 case 0x2:
855 if (lo4 == 0x0)
856 debug("mov.b\tr%i,@r%i\n", r4, r8);
857 else if (lo4 == 0x1)
858 debug("mov.w\tr%i,@r%i\n", r4, r8);
859 else if (lo4 == 0x2)
860 debug("mov.l\tr%i,@r%i\n", r4, r8);
861 else if (lo4 == 0x4)
862 debug("mov.b\tr%i,@-r%i\n", r4, r8);
863 else if (lo4 == 0x5)
864 debug("mov.w\tr%i,@-r%i\n", r4, r8);
865 else if (lo4 == 0x6)
866 debug("mov.l\tr%i,@-r%i\n", r4, r8);
867 else if (lo4 == 0x7)
868 debug("div0s\tr%i,r%i\n", r4, r8);
869 else if (lo4 == 0x8)
870 debug("tst\tr%i,r%i\n", r4, r8);
871 else if (lo4 == 0x9)
872 debug("and\tr%i,r%i\n", r4, r8);
873 else if (lo4 == 0xa)
874 debug("xor\tr%i,r%i\n", r4, r8);
875 else if (lo4 == 0xb)
876 debug("or\tr%i,r%i\n", r4, r8);
877 else if (lo4 == 0xc)
878 debug("cmp/str\tr%i,r%i\n", r4, r8);
879 else if (lo4 == 0xd)
880 debug("xtrct\tr%i,r%i\n", r4, r8);
881 else if (lo4 == 0xe)
882 debug("mulu.w\tr%i,r%i\n", r4, r8);
883 else if (lo4 == 0xf)
884 debug("muls.w\tr%i,r%i\n", r4, r8);
885 else
886 debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x\n", hi4, lo8);
887 break;
888 case 0x3:
889 if (lo4 == 0x0)
890 debug("cmp/eq\tr%i,r%i\n", r4, r8);
891 else if (lo4 == 0x2)
892 debug("cmp/hs\tr%i,r%i\n", r4, r8);
893 else if (lo4 == 0x3)
894 debug("cmp/ge\tr%i,r%i\n", r4, r8);
895 else if (lo4 == 0x4)
896 debug("div1\tr%i,r%i\n", r4, r8);
897 else if (lo4 == 0x5)
898 debug("dmulu.l\tr%i,r%i\n", r4, r8);
899 else if (lo4 == 0x6)
900 debug("cmp/hi\tr%i,r%i\n", r4, r8);
901 else if (lo4 == 0x7)
902 debug("cmp/gt\tr%i,r%i\n", r4, r8);
903 else if (lo4 == 0x8)
904 debug("sub\tr%i,r%i\n", r4, r8);
905 else if (lo4 == 0xa)
906 debug("subc\tr%i,r%i\n", r4, r8);
907 else if (lo4 == 0xb)
908 debug("subv\tr%i,r%i\n", r4, r8);
909 else if (lo4 == 0xc)
910 debug("add\tr%i,r%i\n", r4, r8);
911 else if (lo4 == 0xd)
912 debug("dmuls.l\tr%i,r%i\n", r4, r8);
913 else if (lo4 == 0xe)
914 debug("addc\tr%i,r%i\n", r4, r8);
915 else if (lo4 == 0xf)
916 debug("addv\tr%i,r%i\n", r4, r8);
917 else
918 debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x\n", hi4, lo8);
919 break;
920 case 0x4:
921 if (lo8 == 0x00)
922 debug("shll\tr%i\n", r8);
923 else if (lo8 == 0x01)
924 debug("shlr\tr%i\n", r8);
925 else if (lo8 == 0x02)
926 debug("sts.l\tmach,@-r%i\n", r8);
927 else if (lo8 == 0x03)
928 debug("stc.l\tsr,@-r%i\n", r8);
929 else if (lo8 == 0x04)
930 debug("rotl\tr%i\n", r8);
931 else if (lo8 == 0x05)
932 debug("rotr\tr%i\n", r8);
933 else if (lo8 == 0x06)
934 debug("lds.l\t@r%i+,mach\n", r8);
935 else if (lo8 == 0x07)
936 debug("ldc.l\t@r%i+,sr\n", r8);
937 else if (lo8 == 0x08)
938 debug("shll2\tr%i\n", r8);
939 else if (lo8 == 0x09)
940 debug("shlr2\tr%i\n", r8);
941 else if (lo8 == 0x0a)
942 debug("lds\tr%i,mach\n", r8);
943 else if (lo8 == 0x0b)
944 debug("jsr\t@r%i\n", r8);
945 else if (lo4 == 0xc)
946 debug("shad\tr%i,r%i\n", r4, r8);
947 else if (lo4 == 0xd)
948 debug("shld\tr%i,r%i\n", r4, r8);
949 else if (lo8 == 0x0e)
950 debug("ldc\tr%i,sr\n", r8);
951 else if (lo8 == 0x10)
952 debug("dt\tr%i\n", r8);
953 else if (lo8 == 0x11)
954 debug("cmp/pz\tr%i\n", r8);
955 else if (lo8 == 0x12)
956 debug("sts.l\tmacl,@-r%i\n", r8);
957 else if (lo8 == 0x13)
958 debug("stc.l\tgbr,@-r%i\n", r8);
959 else if (lo8 == 0x15)
960 debug("cmp/pl\tr%i\n", r8);
961 else if (lo8 == 0x16)
962 debug("lds.l\t@r%i+,macl\n", r8);
963 else if (lo8 == 0x17)
964 debug("ldc.l\t@r%i+,gbr\n", r8);
965 else if (lo8 == 0x18)
966 debug("shll8\tr%i\n", r8);
967 else if (lo8 == 0x19)
968 debug("shlr8\tr%i\n", r8);
969 else if (lo8 == 0x1a)
970 debug("lds\tr%i,macl\n", r8);
971 else if (lo8 == 0x1b)
972 debug("tas.b\t@r%i\n", r8);
973 else if (lo8 == 0x1e)
974 debug("ldc\tr%i,gbr\n", r8);
975 else if (lo8 == 0x20)
976 debug("shal\tr%i\n", r8);
977 else if (lo8 == 0x21)
978 debug("shar\tr%i\n", r8);
979 else if (lo8 == 0x22)
980 debug("sts.l\tpr,@-r%i\n", r8);
981 else if (lo8 == 0x23)
982 debug("stc.l\tvbr,@-r%i\n", r8);
983 else if (lo8 == 0x24)
984 debug("rotcl\tr%i\n", r8);
985 else if (lo8 == 0x25)
986 debug("rotcr\tr%i\n", r8);
987 else if (lo8 == 0x26)
988 debug("lds.l\t@r%i+,pr\n", r8);
989 else if (lo8 == 0x27)
990 debug("ldc.l\t@r%i+,vbr\n", r8);
991 else if (lo8 == 0x28)
992 debug("shll16\tr%i\n", r8);
993 else if (lo8 == 0x29)
994 debug("shlr16\tr%i\n", r8);
995 else if (lo8 == 0x2a)
996 debug("lds\tr%i,pr\n", r8);
997 else if (lo8 == 0x2b)
998 debug("jmp\t@r%i\n", r8);
999 else if (lo8 == 0x2e)
1000 debug("ldc\tr%i,vbr\n", r8);
1001 else if (lo8 == 0x33)
1002 debug("stc.l\tssr,@-r%i\n", r8);
1003 else if (lo8 == 0x37)
1004 debug("ldc.l\t@r%i+,ssr\n", r8);
1005 else if (lo8 == 0x3e)
1006 debug("ldc\tr%i,ssr\n", r8);
1007 else if (lo8 == 0x43)
1008 debug("stc.l\tspc,@-r%i\n", r8);
1009 else if (lo8 == 0x47)
1010 debug("ldc.l\t@r%i+,spc\n", r8);
1011 else if (lo8 == 0x4e)
1012 debug("ldc\tr%i,spc\n", r8);
1013 else if (lo8 == 0x52)
1014 debug("sts.l\tfpul,@-r%i\n", r8);
1015 else if (lo8 == 0x56)
1016 debug("lds.l\t@r%i+,fpul\n", r8);
1017 else if (lo8 == 0x5a)
1018 debug("lds\tr%i,fpul\n", r8);
1019 else if (lo8 == 0x62)
1020 debug("sts.l\tfpscr,@-r%i\n", r8);
1021 else if (lo8 == 0x66)
1022 debug("lds.l\t@r%i+,fpscr\n", r8);
1023 else if (lo8 == 0x6a)
1024 debug("lds\tr%i,fpscr\n", r8);
1025 else if ((lo8 & 0x8f) == 0x83)
1026 debug("stc.l\tr%i_bank,@-r%i\n", (lo8 >> 4) & 7, r8);
1027 else if ((lo8 & 0x8f) == 0x87)
1028 debug("ldc.l\t@r%i,r%i_bank\n", r8, (lo8 >> 4) & 7, r8);
1029 else if ((lo8 & 0x8f) == 0x8e)
1030 debug("ldc\tr%i,r%i_bank\n", r8, (lo8 >> 4) & 7);
1031 else if (lo8 == 0xfa)
1032 debug("ldc\tr%i,dbr\n", r8);
1033 else
1034 debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x\n", hi4, lo8);
1035 break;
1036 case 0x5:
1037 debug("mov.l\t@(%i,r%i),r%i", lo4 * 4, r4, r8);
1038 if (running) {
1039 debug("\t; r%i+%i = 0x%08"PRIx32, r4, lo4 * 4,
1040 cpu->cd.sh.r[r4] + lo4 * 4);
1041 }
1042 debug("\n");
1043 break;
1044 case 0x6:
1045 if (lo4 == 0x0)
1046 debug("mov.b\t@r%i,r%i\n", r4, r8);
1047 else if (lo4 == 0x1)
1048 debug("mov.w\t@r%i,r%i\n", r4, r8);
1049 else if (lo4 == 0x2)
1050 debug("mov.l\t@r%i,r%i\n", r4, r8);
1051 else if (lo4 == 0x3)
1052 debug("mov\tr%i,r%i\n", r4, r8);
1053 else if (lo4 == 0x4)
1054 debug("mov.b\t@r%i+,r%i\n", r4, r8);
1055 else if (lo4 == 0x5)
1056 debug("mov.w\t@r%i+,r%i\n", r4, r8);
1057 else if (lo4 == 0x6)
1058 debug("mov.l\t@r%i+,r%i\n", r4, r8);
1059 else if (lo4 == 0x7)
1060 debug("not\tr%i,r%i\n", r4, r8);
1061 else if (lo4 == 0x8)
1062 debug("swap.b\tr%i,r%i\n", r4, r8);
1063 else if (lo4 == 0x9)
1064 debug("swap.w\tr%i,r%i\n", r4, r8);
1065 else if (lo4 == 0xa)
1066 debug("negc\tr%i,r%i\n", r4, r8);
1067 else if (lo4 == 0xb)
1068 debug("neg\tr%i,r%i\n", r4, r8);
1069 else if (lo4 == 0xc)
1070 debug("extu.b\tr%i,r%i\n", r4, r8);
1071 else if (lo4 == 0xd)
1072 debug("extu.w\tr%i,r%i\n", r4, r8);
1073 else if (lo4 == 0xe)
1074 debug("exts.b\tr%i,r%i\n", r4, r8);
1075 else if (lo4 == 0xf)
1076 debug("exts.w\tr%i,r%i\n", r4, r8);
1077 else
1078 debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x\n", hi4, lo8);
1079 break;
1080 case 0x7:
1081 debug("add\t#%i,r%i\n", (int8_t)lo8, r8);
1082 break;
1083 case 0x8:
1084 if (r8 == 0 || r8 == 4) {
1085 if (r8 == 0x0)
1086 debug("mov.b\tr0,@(%i,r%i)", lo4, r4);
1087 else if (r8 == 0x4)
1088 debug("mov.b\t@(%i,r%i),r0", lo4, r4);
1089 if (running) {
1090 debug("\t; r%i+%i = 0x%08"PRIx32, r4, lo4,
1091 cpu->cd.sh.r[r4] + lo4);
1092 }
1093 debug("\n");
1094 } else if (r8 == 1 || r8 == 5) {
1095 if (r8 == 0x1)
1096 debug("mov.w\tr0,@(%i,r%i)", lo4 * 2, r4);
1097 else if (r8 == 0x5)
1098 debug("mov.w\t@(%i,r%i),r0", lo4 * 2, r4);
1099 if (running) {
1100 debug("\t; r%i+%i = 0x%08"PRIx32, r4, lo4 * 2,
1101 cpu->cd.sh.r[r4] + lo4 * 2);
1102 }
1103 debug("\n");
1104 } else if (r8 == 0x8) {
1105 debug("cmp/eq\t#%i,r0\n", (int8_t)lo8);
1106 } else if (r8 == 0x9 || r8 == 0xb || r8 == 0xd || r8 == 0xf) {
1107 addr = (int8_t)lo8;
1108 addr = dumpaddr + 4 + (addr << 1);
1109 debug("b%s%s\t0x%x\n",
1110 (r8 == 0x9 || r8 == 0xd)? "t" : "f",
1111 (r8 == 0x9 || r8 == 0xb)? "" : "/s", (int)addr);
1112 } else
1113 debug("UNIMPLEMENTED hi4=0x%x,0x%x\n", hi4, r8);
1114 break;
1115 case 0x9:
1116 case 0xd:
1117 addr = lo8 * (hi4==9? 2 : 4);
1118 addr += (dumpaddr & ~(hi4==9? 1 : 3)) + 4;
1119 debug("mov.%s\t0x%x,r%i\n", hi4==9? "w":"l", (int)addr, r8);
1120 break;
1121 case 0xa:
1122 case 0xb:
1123 addr = (int32_t)(int16_t)((iword & 0xfff) << 4);
1124 addr = ((int32_t)addr >> 3);
1125 addr += dumpaddr + 4;
1126 debug("%s\t0x%x\n", hi4==0xa? "bra":"bsr", (int)addr);
1127 break;
1128 case 0xc:
1129 if (r8 == 0x0)
1130 debug("mov.b\tr0,@(%i,gbr)\n", lo8);
1131 else if (r8 == 0x1)
1132 debug("mov.w\tr0,@(%i,gbr)\n", lo8 * 2);
1133 else if (r8 == 0x2)
1134 debug("mov.l\tr0,@(%i,gbr)\n", lo8 * 4);
1135 else if (r8 == 0x3)
1136 debug("trapa\t#%i\n", (uint8_t)lo8);
1137 else if (r8 == 0x4)
1138 debug("mov.b\t(%i,gbr),r0\n", lo8);
1139 else if (r8 == 0x5)
1140 debug("mov.w\t(%i,gbr),r0\n", lo8 * 2);
1141 else if (r8 == 0x6)
1142 debug("mov.l\t(%i,gbr),r0\n", lo8 * 4);
1143 else if (r8 == 0x7) {
1144 addr = lo8 * 4 + (dumpaddr & ~3) + 4;
1145 debug("mova\t0x%x,r0\n", (int)addr);
1146 } else if (r8 == 0x8)
1147 debug("tst\t#%i,r0\n", (uint8_t)lo8);
1148 else if (r8 == 0x9)
1149 debug("and\t#%i,r0\n", (uint8_t)lo8);
1150 else if (r8 == 0xa)
1151 debug("xor\t#%i,r0\n", (uint8_t)lo8);
1152 else if (r8 == 0xb)
1153 debug("or\t#%i,r0\n", (uint8_t)lo8);
1154 else if (r8 == 0xc)
1155 debug("tst.b\t#%i,@(r0,gbr)\n", (uint8_t)lo8);
1156 else if (r8 == 0xd)
1157 debug("and.b\t#%i,@(r0,gbr)\n", (uint8_t)lo8);
1158 else if (r8 == 0xe)
1159 debug("xor.b\t#%i,@(r0,gbr)\n", (uint8_t)lo8);
1160 else if (r8 == 0xf)
1161 debug("or.b\t#%i,@(r0,gbr)\n", (uint8_t)lo8);
1162 else
1163 debug("UNIMPLEMENTED hi4=0x%x,0x%x\n", hi4, r8);
1164 break;
1165 case 0xe:
1166 debug("mov\t#%i,r%i\n", (int8_t)lo8, r8);
1167 break;
1168 case 0xf:
1169 if (lo4 == 0x0)
1170 debug("fadd\t%sr%i,%sr%i\n",
1171 cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r4,
1172 cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1173 else if (lo4 == 0x1)
1174 debug("fsub\t%sr%i,%sr%i\n",
1175 cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r4,
1176 cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1177 else if (lo4 == 0x2)
1178 debug("fmul\t%sr%i,%sr%i\n",
1179 cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r4,
1180 cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1181 else if (lo4 == 0x3)
1182 debug("fdiv\t%sr%i,%sr%i\n",
1183 cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r4,
1184 cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1185 else if (lo4 == 0x4)
1186 debug("fcmp/eq\t%sr%i,%sr%i\n",
1187 cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r4,
1188 cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1189 else if (lo4 == 0x5)
1190 debug("fcmp/gt\t%sr%i,%sr%i\n",
1191 cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r4,
1192 cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1193 else if (lo4 == 0x6) {
1194 char *n = "fr";
1195 if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1196 n = (r8 & 1)? "xd" : "dr";
1197 r8 &= ~1;
1198 }
1199 debug("fmov\t@(r0,r%i),%s%i\n", r4, n, r8);
1200 } else if (lo4 == 0x7) {
1201 char *n = "fr";
1202 if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1203 n = (r4 & 1)? "xd" : "dr";
1204 r4 &= ~1;
1205 }
1206 debug("fmov\t%s%i,@(r0,r%i)\n", n, r4, r8);
1207 } else if (lo4 == 0x8) {
1208 char *n = "fr";
1209 if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1210 n = (r8 & 1)? "xd" : "dr";
1211 r8 &= ~1;
1212 }
1213 debug("fmov\t@r%i,%s%i\n", r4, n, r8);
1214 } else if (lo4 == 0x9) {
1215 char *n = "fr";
1216 if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1217 n = (r8 & 1)? "xd" : "dr";
1218 r8 &= ~1;
1219 }
1220 debug("fmov\t@r%i+,%s%i\n", r4, n, r8);
1221 } else if (lo4 == 0xa) {
1222 char *n = "fr";
1223 if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1224 n = (r4 & 1)? "xd" : "dr";
1225 r4 &= ~1;
1226 }
1227 debug("fmov\t%s%i,@r%i\n", n, r4, r8);
1228 } else if (lo4 == 0xb) {
1229 char *n = "fr";
1230 if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1231 n = (r4 & 1)? "xd" : "dr";
1232 r4 &= ~1;
1233 }
1234 debug("fmov\t%s%i,@-r%i\n", n, r4, r8);
1235 } else if (lo4 == 0xc) {
1236 char *n1 = "fr", *n2 = "fr";
1237 if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1238 n1 = (r4 & 1)? "xd" : "dr";
1239 n2 = (r8 & 1)? "xd" : "dr";
1240 r4 &= ~1; r8 &= ~1;
1241 }
1242 debug("fmov\t%s%i,%s%i\n", n1, r4, n2, r8);
1243 } else if (lo8 == 0x0d)
1244 debug("fsts\tfpul,fr%i\n", r8);
1245 else if (lo8 == 0x1d)
1246 debug("flds\tfr%i,fpul\n", r8);
1247 else if (lo8 == 0x2d)
1248 debug("float\tfpul,%sr%i\n",
1249 cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1250 else if (lo8 == 0x3d)
1251 debug("ftrc\t%sr%i,fpul\n",
1252 cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1253 else if (lo8 == 0x4d)
1254 debug("fneg\t%sr%i\n",
1255 cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1256 else if (lo8 == 0x5d)
1257 debug("fabs\t%sr%i\n",
1258 cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1259 else if (lo8 == 0x6d)
1260 debug("fsqrt\t%sr%i\n",
1261 cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1262 else if (lo8 == 0x8d)
1263 debug("fldi0\tfr%i\n", r8);
1264 else if (lo8 == 0x9d)
1265 debug("fldi1\tfr%i\n", r8);
1266 else if ((iword & 0x01ff) == 0x00fd)
1267 debug("fsca\tfpul,dr%i\n", r8);
1268 else if (iword == 0xf3fd)
1269 debug("fschg\n");
1270 else if (iword == 0xfbfd)
1271 debug("frchg\n");
1272 else if ((iword & 0xf3ff) == 0xf1fd)
1273 debug("ftrv\txmtrx,fv%i\n", r8 & 0xc);
1274 else if (lo4 == 0xe)
1275 debug("fmac\tfr0,fr%i,fr%i\n", r4, r8);
1276 else
1277 debug("UNIMPLEMENTED hi4=0x%x,0x%x\n", hi4, lo8);
1278 break;
1279 default:debug("UNIMPLEMENTED hi4=0x%x\n", hi4);
1280 }
1281
1282 return sizeof(iword);
1283 }
1284
1285
1286 /*
1287 * sh_cpu_disassemble_instr():
1288 *
1289 * Convert an instruction word into human readable format, for instruction
1290 * tracing.
1291 *
1292 * If running is 1, cpu->pc should be the address of the instruction.
1293 *
1294 * If running is 0, things that depend on the runtime environment (eg.
1295 * register contents) will not be shown, and addr will be used instead of
1296 * cpu->pc for relative addresses.
1297 */
1298 int sh_cpu_disassemble_instr(struct cpu *cpu, unsigned char *instr,
1299 int running, uint64_t dumpaddr)
1300 {
1301 uint64_t offset;
1302 uint32_t iword;
1303 char *symbol;
1304
1305 if (running)
1306 dumpaddr = cpu->pc;
1307
1308 symbol = get_symbol_name(&cpu->machine->symbol_context,
1309 dumpaddr, &offset);
1310 if (symbol != NULL && offset==0)
1311 debug("<%s>\n", symbol);
1312
1313 if (cpu->machine->ncpus > 1 && running)
1314 debug("cpu%i: ", cpu->cpu_id);
1315
1316 if (cpu->cd.sh.cpu_type.bits == 32)
1317 debug("%08x", (int)dumpaddr);
1318 else
1319 debug("%016llx", (long long)dumpaddr);
1320
1321 if (cpu->cd.sh.compact)
1322 return sh_cpu_disassemble_instr_compact(cpu, instr,
1323 running, dumpaddr);
1324
1325 if (cpu->byte_order == EMUL_BIG_ENDIAN)
1326 iword = (instr[0] << 24) + (instr[1] << 16) + (instr[2] << 8)
1327 + instr[3];
1328 else
1329 iword = (instr[3] << 24) + (instr[2] << 16) + (instr[1] << 8)
1330 + instr[0];
1331
1332 debug(": %08x\t", iword);
1333
1334 /*
1335 * Decode the instruction:
1336 */
1337
1338 debug("TODO\n");
1339
1340 return sizeof(iword);
1341 }
1342
1343
1344 #include "tmp_sh_tail.c"
1345

  ViewVC Help
Powered by ViewVC 1.1.26