/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 40 - (hide annotations)
Mon Oct 8 16:22:11 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 39131 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1539 2007/05/01 04:03:51 debug Exp $
20070415	Landisk PCLOCK should be 33.33 MHz, not 50 MHz. (This makes
		the clock run at correct speed.)
		FINALLY found and fixed the bug which caused OpenBSD/landisk
		to randomly bug out: an &-sign was missing in the special case
		handling of FPSCR in the 'LDS.L @Rm+,FPSCR' instruction.
		Adding similar special case handling for 'LDC.L @Rm+,SR'
		(calling sh_update_sr() instead of just loading).
		Implementing the 'FCNVSD FPUL,DRn' and 'FCNVDS DRm,FPUL'
		SuperH instructions.
		The 'LDC Rm,SR' instruction now immediately breaks out of the
		dyntrans loop if an interrupt is to be triggered.
20070416	In memory_rw.c, if mapping a page as writable, make sure to
		invalidate code translations even if the data access was a
		read.
		Minor SuperH updates.
20070418	Removing the dummy M68K emulation mode.
		Minor SH update (turning unnecessary sts_mach_rn, sts_macl_rn,
		and sts_pr_rn instruction handlers into mov_rm_rn).
20070419	Beginning to add a skeleton for an M88K mode: Adding a hack to
		allow OpenBSD/m88k a.out binaries to be loaded, and disassembly
		of a few simple 88K instructions.
		Commenting out the 'LDC Rm,SR' fix from a few days ago, because
		it made Linux/dreamcast bug out.
		Adding a hack to dev_sh4.c (an extra translation cache
		invalidation), which allows OpenBSD/landisk to boot ok after
		an install. Upgrading the Landisk machine mode to stable,
		updating documentation, etc.
20070420	Experimenting with adding a PCI controller (pcic) to dev_sh4.
		Adding a dummy Realtek 8139C+ skeleton device (dev_rtl8139c).
		Implementing the first M88K instructions (br, or[.u] imm), and
		adding disassembly of some more instructions.
20070421	Continuing a little on dev_rtl8139c.
20070422	Implementing the 9346 EEPROM "read" command for dev_rtl8139c.
		Finally found and fixed an old bug in the log n symbol search
		(it sometimes missed symbols). Debug trace (-i, -t etc) should
		now show more symbols. :-)
20070423	Continuing a little on M88K disassembly.
20070428	Fixing a memset arg order bug in src/net/net.c (thanks to
		Nigel Horne for noticing the bug).
		Applying parts of a patch from Carl van Schaik to clear out
		bottom bits of MIPS addresses more correctly, when using large
		page sizes, and doing some other minor cleanup/refactoring.
		Fixing a couple of warnings given by gcc with the -W option (a
		few more warnings than just plain -Wall).
		Reducing SuperH dyntrans physical address space from 64-bit to
		32-bit (since SH5/SH64 isn't imlemented yet anyway).
		Adding address-to-symbol annotation to a few more instructions
		in the SuperH instruction trace output.
		Beginning regression testing for the next release.
		Reverting the value of SCIF_DELAYED_TX_VALUE from 1 to 2,
		because OpenBSD/landisk may otherwise hang randomly.
20070429	The ugly hack/workaround to get OpenBSD/landisk booting without
		crashing does NOT work anymore (with the April 21 snapshot
		of OpenBSD/landisk). Strangely enough, removing the hack
		completely causes OpenBSD/landisk to work (!).
		More regression testing (re-testing everything SuperH-related,
		and some other things).
		Cobalt interrupts were actually broken; fixing by commenting
		out the DEC21143s in the Cobalt machine.
20070430	More regression testing.
20070501	Updating the OpenBSD/landisk install instructions to use
		4.1 instead of the current snapshot.
		GAAAH! OpenBSD/landisk 4.1 _needs_ the ugly hack/workaround;
		reintroducing it again. (The 4.1 kernel is actually from
		2007-03-11.)
		Simplifying the NetBSD/evbarm install instructions a bit.
		More regression testing.

==============  RELEASE 0.4.5.1  ==============


1 dpavlin 14 /*
2 dpavlin 34 * Copyright (C) 2005-2007 Anders Gavare. All rights reserved.
3 dpavlin 14 *
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 dpavlin 40 * $Id: cpu_sh.c,v 1.72 2007/04/28 09:44:35 debug Exp $
29 dpavlin 14 *
30     * Hitachi SuperH ("SH") CPU emulation.
31     *
32 dpavlin 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 dpavlin 14 */
35    
36     #include <stdio.h>
37     #include <stdlib.h>
38     #include <string.h>
39     #include <ctype.h>
40 dpavlin 32 #include <unistd.h>
41 dpavlin 14
42     #include "cpu.h"
43 dpavlin 32 #include "device.h"
44     #include "float_emul.h"
45 dpavlin 34 #include "interrupt.h"
46 dpavlin 14 #include "machine.h"
47     #include "memory.h"
48     #include "misc.h"
49 dpavlin 32 #include "settings.h"
50 dpavlin 14 #include "symbol.h"
51    
52 dpavlin 32 #include "sh4_exception.h"
53     #include "sh4_mmu.h"
54 dpavlin 14
55 dpavlin 32
56     #define DYNTRANS_32
57     #define DYNTRANS_DELAYSLOT
58 dpavlin 14 #include "tmp_sh_head.c"
59    
60    
61 dpavlin 32 extern int quiet_mode;
62    
63     void sh_pc_to_pointers(struct cpu *);
64    
65    
66 dpavlin 14 /*
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 dpavlin 30 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 dpavlin 14 return 0;
89    
90     cpu->memory_rw = sh_memory_rw;
91    
92 dpavlin 30 cpu->cd.sh.cpu_type = cpu_type_defs[i];
93 dpavlin 14 cpu->byte_order = EMUL_LITTLE_ENDIAN;
94 dpavlin 30 cpu->is_32bit = cpu->cd.sh.cpu_type.bits == 32;
95     cpu->cd.sh.compact = 1; /* Default to 16-bit opcode mode */
96 dpavlin 14
97 dpavlin 32 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 dpavlin 30 cpu->translate_v2p = sh_translate_v2p;
105    
106 dpavlin 32 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 dpavlin 14
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 dpavlin 30 /* Initial value of FPSCR (according to the SH4 manual): */
119     cpu->cd.sh.fpscr = 0x00040001;
120    
121 dpavlin 32 /* (Initial value of the program counter on reboot is 0xA0000000.) */
122    
123 dpavlin 30 /* Start in Privileged Mode: */
124 dpavlin 32 cpu->cd.sh.sr = SH_SR_MD | SH_SR_IMASK;
125 dpavlin 30
126 dpavlin 32 /* 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 dpavlin 34 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 dpavlin 32 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 dpavlin 34 /* 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 dpavlin 32 /* SH4-specific memory mapped registers, TLBs, caches, etc: */
188 dpavlin 38 if (cpu->cd.sh.cpu_type.arch == 4) {
189 dpavlin 40 cpu->cd.sh.pcic_pcibus = device_add(machine, "sh4");
190 dpavlin 32
191 dpavlin 38 /*
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 dpavlin 14 return 1;
210     }
211    
212    
213     /*
214 dpavlin 38 * 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 dpavlin 34 */
233 dpavlin 38 void sh_update_interrupt_priorities(struct cpu *cpu)
234 dpavlin 34 {
235 dpavlin 38 int i;
236 dpavlin 34
237     /*
238 dpavlin 38 * Set priorities of known interrupts, without affecting the
239     * SH_INT_ASSERTED bit:
240 dpavlin 34 */
241    
242 dpavlin 38 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 dpavlin 34
248 dpavlin 38 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 dpavlin 34
253 dpavlin 38 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 dpavlin 34
258 dpavlin 38 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 dpavlin 34 }
269    
270    
271     /*
272 dpavlin 38 * sh_cpu_interrupt_assert():
273 dpavlin 34 */
274 dpavlin 38 void sh_cpu_interrupt_assert(struct interrupt *interrupt)
275 dpavlin 34 {
276     struct cpu *cpu = interrupt->extra;
277 dpavlin 40 unsigned int irq_nr = interrupt->line;
278     unsigned int index = irq_nr / 0x20;
279     unsigned int prio;
280 dpavlin 34
281 dpavlin 38 /* 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 dpavlin 34
285 dpavlin 38 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 dpavlin 34
291 dpavlin 38 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 dpavlin 34
297    
298 dpavlin 38 /*
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 dpavlin 34
307 dpavlin 38 /* 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 dpavlin 34
311 dpavlin 38 /* 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 dpavlin 34 }
324     }
325     }
326     }
327    
328    
329     /*
330 dpavlin 14 * 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 dpavlin 30 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 dpavlin 14 }
348    
349    
350     /*
351     * sh_cpu_dumpinfo():
352     */
353     void sh_cpu_dumpinfo(struct cpu *cpu)
354     {
355 dpavlin 32 debug(" (%s-endian)\n",
356     cpu->byte_order == EMUL_BIG_ENDIAN? "Big" : "Little");
357 dpavlin 14 }
358    
359    
360     /*
361 dpavlin 32 * 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 dpavlin 14 * 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 dpavlin 22 uint64_t offset;
426 dpavlin 14 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 dpavlin 32 debug("cpu%i: pc = 0x%08"PRIx32, x, (uint32_t)cpu->pc);
434 dpavlin 14 debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
435    
436 dpavlin 32 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 dpavlin 30 (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 dpavlin 32 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 dpavlin 14 }
464     }
465    
466 dpavlin 32 if (coprocs & 1) {
467     /* Floating point: */
468 dpavlin 40 debug("cpu%i: fpscr = 0x%08"PRIx32" (%s,%s,%s) fpul = 0x%08"
469     PRIx32"\n", x, cpu->cd.sh.fpscr,
470     cpu->cd.sh.fpscr & SH_FPSCR_PR? "PR" : "!pr",
471     cpu->cd.sh.fpscr & SH_FPSCR_SZ? "SZ" : "!sz",
472     cpu->cd.sh.fpscr & SH_FPSCR_FR? "FR" : "!fr",
473     cpu->cd.sh.fpul);
474 dpavlin 14
475 dpavlin 32 for (i=0; i<SH_N_FPRS; i++) {
476     if ((i % 4) == 0)
477     debug("cpu%i:", x);
478     debug(" fr%-2i=0x%08x ", i, (int)cpu->cd.sh.fr[i]);
479     if ((i % 4) == 3)
480     debug("\n");
481     }
482 dpavlin 14
483 dpavlin 32 for (i=0; i<SH_N_FPRS; i++) {
484     if ((i % 4) == 0)
485     debug("cpu%i:", x);
486     debug(" xf%-2i=0x%08x ", i, (int)cpu->cd.sh.xf[i]);
487     if ((i % 4) == 3)
488     debug("\n");
489     }
490     }
491 dpavlin 14
492 dpavlin 32 if (coprocs & 2) {
493     /* System registers, etc: */
494     debug("cpu%i: vbr = 0x%08"PRIx32" sgr = 0x%08"PRIx32
495     "\n", x, cpu->cd.sh.vbr, cpu->cd.sh.sgr);
496     debug("cpu%i: spc = 0x%08"PRIx32" ssr = 0x%08"PRIx32"\n",
497     x, cpu->cd.sh.spc, cpu->cd.sh.ssr);
498     debug("cpu%i: expevt = 0x%"PRIx32" intevt = 0x%"PRIx32
499     " tra = 0x%"PRIx32"\n", x, cpu->cd.sh.expevt,
500     cpu->cd.sh.intevt, cpu->cd.sh.tra);
501 dpavlin 14
502 dpavlin 32 for (i=0; i<SH_N_GPRS_BANKED; i++) {
503     if ((i % 2) == 0)
504     debug("cpu%i:", x);
505     debug(" r%i_bank = 0x%08x ", i,
506     (int)cpu->cd.sh.r_bank[i]);
507     if ((i % 2) == 1)
508     debug("\n");
509 dpavlin 30 }
510 dpavlin 14 }
511     }
512    
513    
514     /*
515 dpavlin 24 * sh_cpu_tlbdump():
516     *
517     * Called from the debugger to dump the TLB in a readable format.
518     * x is the cpu number to dump, or -1 to dump all CPUs.
519     *
520     * If rawflag is nonzero, then the TLB contents isn't formated nicely,
521     * just dumped.
522     */
523     void sh_cpu_tlbdump(struct machine *m, int x, int rawflag)
524     {
525 dpavlin 32 int i, j;
526    
527     for (j=0; j<m->ncpus; j++) {
528     struct cpu *cpu = m->cpus[j];
529    
530     if (x >= 0 && j != x)
531     continue;
532    
533     for (i=0; i<SH_N_ITLB_ENTRIES; i++)
534     printf("cpu%i: itlb_hi_%-2i = 0x%08"PRIx32" "
535     "itlb_lo_%-2i = 0x%08"PRIx32"\n", j, i,
536     (uint32_t) cpu->cd.sh.itlb_hi[i], i,
537     (uint32_t) cpu->cd.sh.itlb_lo[i]);
538     for (i=0; i<SH_N_UTLB_ENTRIES; i++)
539     printf("cpu%i: utlb_hi_%-2i = 0x%08"PRIx32" "
540     "utlb_lo_%-2i = 0x%08"PRIx32"\n", j, i,
541     (uint32_t) cpu->cd.sh.utlb_hi[i], i,
542     (uint32_t) cpu->cd.sh.utlb_lo[i]);
543     }
544 dpavlin 24 }
545    
546    
547     /*
548 dpavlin 30 * sh_update_sr():
549 dpavlin 32 *
550     * Writes a new value to the status register.
551 dpavlin 30 */
552     void sh_update_sr(struct cpu *cpu, uint32_t new_sr)
553     {
554     uint32_t old_sr = cpu->cd.sh.sr;
555    
556     if ((new_sr & SH_SR_RB) != (old_sr & SH_SR_RB)) {
557 dpavlin 32 int i;
558     for (i=0; i<SH_N_GPRS_BANKED; i++) {
559     uint32_t tmp = cpu->cd.sh.r[i];
560     cpu->cd.sh.r[i] = cpu->cd.sh.r_bank[i];
561     cpu->cd.sh.r_bank[i] = tmp;
562     }
563 dpavlin 30 }
564    
565     cpu->cd.sh.sr = new_sr;
566     }
567    
568    
569     /*
570 dpavlin 32 * sh_update_fpscr():
571     *
572     * Writes a new value to the floating-point status/control register.
573     */
574     void sh_update_fpscr(struct cpu *cpu, uint32_t new_fpscr)
575     {
576     uint32_t old_fpscr = cpu->cd.sh.fpscr;
577    
578     if ((new_fpscr & SH_FPSCR_FR) != (old_fpscr & SH_FPSCR_FR)) {
579     int i;
580     for (i=0; i<SH_N_FPRS; i++) {
581     uint32_t tmp = cpu->cd.sh.fr[i];
582     cpu->cd.sh.fr[i] = cpu->cd.sh.xf[i];
583     cpu->cd.sh.xf[i] = tmp;
584     }
585     }
586    
587     cpu->cd.sh.fpscr = new_fpscr;
588     }
589    
590    
591     /*
592     * sh_exception():
593     *
594     * Causes a transfer of control to an exception or interrupt handler.
595     * If intevt > 0, then it is an interrupt, otherwise an exception.
596 dpavlin 38 *
597     * vaddr contains the faulting address, on TLB exceptions.
598 dpavlin 32 */
599     void sh_exception(struct cpu *cpu, int expevt, int intevt, uint32_t vaddr)
600     {
601     uint32_t vbr = cpu->cd.sh.vbr;
602    
603     if (!quiet_mode) {
604     if (intevt > 0)
605     debug("[ interrupt 0x%03x", intevt);
606     else
607     debug("[ exception 0x%03x", expevt);
608    
609 dpavlin 38 debug(", pc=0x%08"PRIx32" ", (uint32_t)cpu->pc);
610 dpavlin 32 if (intevt == 0)
611     debug("vaddr=0x%08"PRIx32" ", vaddr);
612    
613     debug(" ]\n");
614     }
615    
616     if (cpu->cd.sh.sr & SH_SR_BL) {
617 dpavlin 38 fatal("[ sh_exception(): BL bit already set. ]\n");
618 dpavlin 32
619     /* This is actually OK in two cases: a User Break,
620     or on NMI interrupts if a special flag is set? */
621     /* TODO */
622    
623     expevt = EXPEVT_RESET_POWER;
624     }
625    
626     if (cpu->is_halted) {
627     /*
628     * If the exception occurred on a 'sleep' instruction, then let
629     * the instruction following the sleep instruction be the one
630     * where execution resumes when the interrupt service routine
631     * returns.
632     */
633     cpu->is_halted = 0;
634     cpu->pc += sizeof(uint16_t);
635     }
636    
637     if (cpu->delay_slot) {
638     cpu->delay_slot = EXCEPTION_IN_DELAY_SLOT;
639     cpu->pc -= sizeof(uint16_t);
640     }
641    
642 dpavlin 38
643     /*
644     * Stuff common to all exceptions:
645     */
646    
647 dpavlin 32 cpu->cd.sh.spc = cpu->pc;
648     cpu->cd.sh.ssr = cpu->cd.sh.sr;
649     cpu->cd.sh.sgr = cpu->cd.sh.r[15];
650 dpavlin 38
651 dpavlin 32 if (intevt > 0) {
652     cpu->cd.sh.intevt = intevt;
653     expevt = -1;
654 dpavlin 38 } else {
655 dpavlin 32 cpu->cd.sh.expevt = expevt;
656 dpavlin 38 }
657    
658 dpavlin 32 sh_update_sr(cpu, cpu->cd.sh.sr | SH_SR_MD | SH_SR_RB | SH_SR_BL);
659    
660     /* Most exceptions set PC to VBR + 0x100. */
661     cpu->pc = vbr + 0x100;
662    
663 dpavlin 38
664 dpavlin 32 /* Specific cases: */
665     switch (expevt) {
666    
667     case -1: /* Interrupt */
668     cpu->pc = vbr + 0x600;
669     break;
670    
671     case EXPEVT_RESET_POWER:
672     case EXPEVT_RESET_MANUAL:
673     cpu->pc = 0xa0000000;
674     cpu->cd.sh.vbr = 0x00000000;
675     sh_update_sr(cpu, (cpu->cd.sh.sr | SH_SR_IMASK) & ~SH_SR_FD);
676     break;
677    
678     case EXPEVT_TLB_MISS_LD:
679     case EXPEVT_TLB_MISS_ST:
680     cpu->pc = vbr + 0x400;
681     case EXPEVT_TLB_PROT_LD:
682     case EXPEVT_TLB_PROT_ST:
683     case EXPEVT_TLB_MOD:
684     cpu->cd.sh.tea = vaddr;
685     cpu->cd.sh.pteh &= ~SH4_PTEH_VPN_MASK;
686     cpu->cd.sh.pteh |= (vaddr & SH4_PTEH_VPN_MASK);
687     break;
688    
689     case EXPEVT_TRAPA:
690 dpavlin 38 /*
691     * Note: The TRA register is already set by the implementation
692     * of the trapa instruction. See cpu_sh_instr.c for details.
693     * Here, spc is incremented, so that a return from the trap
694     * handler transfers control to the instruction _following_
695     * the trapa.
696     */
697 dpavlin 32 cpu->cd.sh.spc += sizeof(uint16_t);
698     break;
699    
700 dpavlin 34 case EXPEVT_RES_INST:
701 dpavlin 36 /*
702     * Note: Having this code here makes it possible to catch
703     * reserved instructions; during normal instruction execution,
704     * these are not very common.
705     */
706     #if 1
707     printf("\nRESERVED SuperH instruction at spc=%08"PRIx32"\n",
708     cpu->cd.sh.spc);
709     exit(1);
710     #else
711 dpavlin 34 break;
712     #endif
713    
714     case EXPEVT_FPU_DISABLE:
715     break;
716    
717 dpavlin 32 default:fatal("sh_exception(): exception 0x%x is not yet "
718     "implemented.\n", expevt);
719     exit(1);
720     }
721    
722     sh_pc_to_pointers(cpu);
723     }
724    
725    
726     /*
727 dpavlin 14 * sh_cpu_disassemble_instr_compact():
728     *
729     * SHcompact instruction disassembly. The top 4 bits of each 16-bit
730     * instruction word is used as the main opcode. For most instructions, the
731     * lowest 4 or 8 bits then select sub-opcode.
732     */
733     int sh_cpu_disassemble_instr_compact(struct cpu *cpu, unsigned char *instr,
734 dpavlin 24 int running, uint64_t dumpaddr)
735 dpavlin 14 {
736 dpavlin 40 char *symbol;
737     uint64_t offset, addr;
738 dpavlin 14 uint16_t iword;
739     int hi4, lo4, lo8, r8, r4;
740    
741     if (cpu->byte_order == EMUL_BIG_ENDIAN)
742     iword = (instr[0] << 8) + instr[1];
743     else
744     iword = (instr[1] << 8) + instr[0];
745    
746 dpavlin 32 debug(": %04x %s\t", iword, cpu->delay_slot? "(d)" : "");
747 dpavlin 14 hi4 = iword >> 12; lo4 = iword & 15; lo8 = iword & 255;
748     r8 = (iword >> 8) & 15; r4 = (iword >> 4) & 15;
749    
750     /*
751     * Decode the instruction:
752     */
753    
754     switch (hi4) {
755     case 0x0:
756     if (lo8 == 0x02)
757     debug("stc\tsr,r%i\n", r8);
758     else if (lo8 == 0x03)
759     debug("bsrf\tr%i\n", r8);
760 dpavlin 34 else if (lo4 >= 4 && lo4 <= 6) {
761     if (lo4 == 0x4)
762     debug("mov.b\tr%i,@(r0,r%i)", r4, r8);
763     else if (lo4 == 0x5)
764     debug("mov.w\tr%i,@(r0,r%i)", r4, r8);
765     else if (lo4 == 0x6)
766     debug("mov.l\tr%i,@(r0,r%i)", r4, r8);
767     if (running) {
768 dpavlin 40 uint32_t addr = cpu->cd.sh.r[0] +
769     cpu->cd.sh.r[r8];
770     debug("\t; r0+r%i = ", r8);
771     symbol = get_symbol_name(
772     &cpu->machine->symbol_context,
773     addr, &offset);
774     if (symbol != NULL)
775     debug("<%s>", symbol);
776     else
777     debug("0x%08"PRIx32, addr);
778 dpavlin 34 }
779     debug("\n");
780     } else if (lo4 == 0x7)
781 dpavlin 14 debug("mul.l\tr%i,r%i\n", r4, r8);
782     else if (iword == 0x0008)
783     debug("clrt\n");
784     else if (iword == 0x0009)
785     debug("nop\n");
786     else if (lo8 == 0x0a)
787     debug("sts\tmach,r%i\n", r8);
788     else if (iword == 0x000b)
789     debug("rts\n");
790 dpavlin 34 else if (lo4 >= 0xc && lo4 <= 0xe) {
791     if (lo4 == 0xc)
792     debug("mov.b\t@(r0,r%i),r%i", r4, r8);
793     else if (lo4 == 0xd)
794     debug("mov.w\t@(r0,r%i),r%i", r4, r8);
795     else if (lo4 == 0xe)
796     debug("mov.l\t@(r0,r%i),r%i", r4, r8);
797     if (running) {
798 dpavlin 40 uint32_t addr = cpu->cd.sh.r[0] +
799     cpu->cd.sh.r[r4];
800     debug("\t; r0+r%i = ", r4);
801     symbol = get_symbol_name(
802     &cpu->machine->symbol_context,
803     addr, &offset);
804     if (symbol != NULL)
805     debug("<%s>", symbol);
806     else
807     debug("0x%08"PRIx32, addr);
808 dpavlin 34 }
809     debug("\n");
810     } else if (lo8 == 0x12)
811 dpavlin 14 debug("stc\tgbr,r%i\n", r8);
812     else if (iword == 0x0018)
813     debug("sett\n");
814     else if (iword == 0x0019)
815     debug("div0u\n");
816     else if (lo8 == 0x1a)
817     debug("sts\tmacl,r%i\n", r8);
818 dpavlin 32 else if (iword == 0x001b)
819     debug("sleep\n");
820     else if (lo8 == 0x22)
821     debug("stc\tvbr,r%i\n", r8);
822 dpavlin 14 else if (lo8 == 0x23)
823     debug("braf\tr%i\n", r8);
824     else if (iword == 0x0028)
825     debug("clrmac\n");
826     else if (lo8 == 0x29)
827     debug("movt\tr%i\n", r8);
828 dpavlin 32 else if (lo8 == 0x2a)
829     debug("sts\tpr,r%i\n", r8);
830     else if (iword == 0x002b)
831     debug("rte\n");
832     else if (lo8 == 0x32)
833     debug("stc\tssr,r%i\n", r8);
834     else if (iword == 0x0038)
835     debug("ldtlb\n");
836 dpavlin 14 else if (iword == 0x003b)
837     debug("brk\n");
838 dpavlin 32 else if (lo8 == 0x42)
839     debug("stc\tspc,r%i\n", r8);
840 dpavlin 14 else if (iword == 0x0048)
841     debug("clrs\n");
842     else if (iword == 0x0058)
843     debug("sets\n");
844 dpavlin 32 else if (lo8 == 0x5a)
845     debug("sts\tfpul,r%i\n", r8);
846     else if (lo8 == 0x6a)
847     debug("sts\tfpscr,r%i\n", r8);
848     else if ((lo8 & 0x8f) == 0x82)
849     debug("stc\tr%i_bank,r%i\n", (lo8 >> 4) & 7, r8);
850 dpavlin 14 else if (lo8 == 0x83)
851     debug("pref\t@r%i\n", r8);
852 dpavlin 32 else if (lo8 == 0x93)
853     debug("ocbi\t@r%i\n", r8);
854     else if (lo8 == 0xa3)
855     debug("ocbp\t@r%i\n", r8);
856     else if (lo8 == 0xb3)
857     debug("ocbwb\t@r%i\n", r8);
858     else if (lo8 == 0xc3)
859     debug("movca.l\tr0,@r%i\n", r8);
860     else if (lo8 == 0xfa)
861     debug("stc\tdbr,r%i\n", r8);
862 dpavlin 34 else if (iword == SH_INVALID_INSTR)
863 dpavlin 32 debug("gxemul_dreamcast_prom_emul\n");
864 dpavlin 14 else
865     debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x\n", hi4, lo8);
866     break;
867     case 0x1:
868 dpavlin 34 debug("mov.l\tr%i,@(%i,r%i)", r4, lo4 * 4, r8);
869     if (running) {
870 dpavlin 40 uint32_t addr = cpu->cd.sh.r[r8] + lo4 * 4;
871     debug("\t; r%i+%i = ", r8, lo4 * 4);
872     symbol = get_symbol_name(&cpu->machine->symbol_context,
873     addr, &offset);
874     if (symbol != NULL)
875     debug("<%s>", symbol);
876     else
877     debug("0x%08"PRIx32, addr);
878 dpavlin 34 }
879     debug("\n");
880 dpavlin 14 break;
881     case 0x2:
882     if (lo4 == 0x0)
883     debug("mov.b\tr%i,@r%i\n", r4, r8);
884     else if (lo4 == 0x1)
885     debug("mov.w\tr%i,@r%i\n", r4, r8);
886     else if (lo4 == 0x2)
887     debug("mov.l\tr%i,@r%i\n", r4, r8);
888     else if (lo4 == 0x4)
889     debug("mov.b\tr%i,@-r%i\n", r4, r8);
890     else if (lo4 == 0x5)
891     debug("mov.w\tr%i,@-r%i\n", r4, r8);
892     else if (lo4 == 0x6)
893     debug("mov.l\tr%i,@-r%i\n", r4, r8);
894     else if (lo4 == 0x7)
895     debug("div0s\tr%i,r%i\n", r4, r8);
896     else if (lo4 == 0x8)
897     debug("tst\tr%i,r%i\n", r4, r8);
898     else if (lo4 == 0x9)
899     debug("and\tr%i,r%i\n", r4, r8);
900     else if (lo4 == 0xa)
901     debug("xor\tr%i,r%i\n", r4, r8);
902     else if (lo4 == 0xb)
903     debug("or\tr%i,r%i\n", r4, r8);
904     else if (lo4 == 0xc)
905     debug("cmp/str\tr%i,r%i\n", r4, r8);
906     else if (lo4 == 0xd)
907     debug("xtrct\tr%i,r%i\n", r4, r8);
908     else if (lo4 == 0xe)
909     debug("mulu.w\tr%i,r%i\n", r4, r8);
910     else if (lo4 == 0xf)
911     debug("muls.w\tr%i,r%i\n", r4, r8);
912     else
913     debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x\n", hi4, lo8);
914     break;
915     case 0x3:
916     if (lo4 == 0x0)
917     debug("cmp/eq\tr%i,r%i\n", r4, r8);
918     else if (lo4 == 0x2)
919     debug("cmp/hs\tr%i,r%i\n", r4, r8);
920     else if (lo4 == 0x3)
921     debug("cmp/ge\tr%i,r%i\n", r4, r8);
922     else if (lo4 == 0x4)
923     debug("div1\tr%i,r%i\n", r4, r8);
924     else if (lo4 == 0x5)
925     debug("dmulu.l\tr%i,r%i\n", r4, r8);
926     else if (lo4 == 0x6)
927     debug("cmp/hi\tr%i,r%i\n", r4, r8);
928     else if (lo4 == 0x7)
929     debug("cmp/gt\tr%i,r%i\n", r4, r8);
930     else if (lo4 == 0x8)
931     debug("sub\tr%i,r%i\n", r4, r8);
932     else if (lo4 == 0xa)
933     debug("subc\tr%i,r%i\n", r4, r8);
934     else if (lo4 == 0xb)
935     debug("subv\tr%i,r%i\n", r4, r8);
936     else if (lo4 == 0xc)
937     debug("add\tr%i,r%i\n", r4, r8);
938     else if (lo4 == 0xd)
939     debug("dmuls.l\tr%i,r%i\n", r4, r8);
940     else if (lo4 == 0xe)
941     debug("addc\tr%i,r%i\n", r4, r8);
942     else if (lo4 == 0xf)
943     debug("addv\tr%i,r%i\n", r4, r8);
944     else
945     debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x\n", hi4, lo8);
946     break;
947     case 0x4:
948     if (lo8 == 0x00)
949     debug("shll\tr%i\n", r8);
950     else if (lo8 == 0x01)
951     debug("shlr\tr%i\n", r8);
952 dpavlin 32 else if (lo8 == 0x02)
953     debug("sts.l\tmach,@-r%i\n", r8);
954     else if (lo8 == 0x03)
955     debug("stc.l\tsr,@-r%i\n", r8);
956 dpavlin 14 else if (lo8 == 0x04)
957     debug("rotl\tr%i\n", r8);
958     else if (lo8 == 0x05)
959     debug("rotr\tr%i\n", r8);
960     else if (lo8 == 0x06)
961     debug("lds.l\t@r%i+,mach\n", r8);
962 dpavlin 32 else if (lo8 == 0x07)
963     debug("ldc.l\t@r%i+,sr\n", r8);
964 dpavlin 14 else if (lo8 == 0x08)
965     debug("shll2\tr%i\n", r8);
966     else if (lo8 == 0x09)
967     debug("shlr2\tr%i\n", r8);
968     else if (lo8 == 0x0a)
969     debug("lds\tr%i,mach\n", r8);
970     else if (lo8 == 0x0b)
971     debug("jsr\t@r%i\n", r8);
972     else if (lo4 == 0xc)
973     debug("shad\tr%i,r%i\n", r4, r8);
974     else if (lo4 == 0xd)
975     debug("shld\tr%i,r%i\n", r4, r8);
976     else if (lo8 == 0x0e)
977     debug("ldc\tr%i,sr\n", r8);
978     else if (lo8 == 0x10)
979     debug("dt\tr%i\n", r8);
980     else if (lo8 == 0x11)
981     debug("cmp/pz\tr%i\n", r8);
982 dpavlin 32 else if (lo8 == 0x12)
983     debug("sts.l\tmacl,@-r%i\n", r8);
984     else if (lo8 == 0x13)
985     debug("stc.l\tgbr,@-r%i\n", r8);
986 dpavlin 14 else if (lo8 == 0x15)
987     debug("cmp/pl\tr%i\n", r8);
988     else if (lo8 == 0x16)
989     debug("lds.l\t@r%i+,macl\n", r8);
990 dpavlin 32 else if (lo8 == 0x17)
991     debug("ldc.l\t@r%i+,gbr\n", r8);
992 dpavlin 14 else if (lo8 == 0x18)
993     debug("shll8\tr%i\n", r8);
994     else if (lo8 == 0x19)
995     debug("shlr8\tr%i\n", r8);
996     else if (lo8 == 0x1a)
997     debug("lds\tr%i,macl\n", r8);
998     else if (lo8 == 0x1b)
999     debug("tas.b\t@r%i\n", r8);
1000     else if (lo8 == 0x1e)
1001     debug("ldc\tr%i,gbr\n", r8);
1002     else if (lo8 == 0x20)
1003     debug("shal\tr%i\n", r8);
1004     else if (lo8 == 0x21)
1005     debug("shar\tr%i\n", r8);
1006     else if (lo8 == 0x22)
1007     debug("sts.l\tpr,@-r%i\n", r8);
1008 dpavlin 32 else if (lo8 == 0x23)
1009     debug("stc.l\tvbr,@-r%i\n", r8);
1010 dpavlin 14 else if (lo8 == 0x24)
1011     debug("rotcl\tr%i\n", r8);
1012     else if (lo8 == 0x25)
1013     debug("rotcr\tr%i\n", r8);
1014     else if (lo8 == 0x26)
1015     debug("lds.l\t@r%i+,pr\n", r8);
1016 dpavlin 32 else if (lo8 == 0x27)
1017     debug("ldc.l\t@r%i+,vbr\n", r8);
1018 dpavlin 14 else if (lo8 == 0x28)
1019     debug("shll16\tr%i\n", r8);
1020     else if (lo8 == 0x29)
1021     debug("shlr16\tr%i\n", r8);
1022     else if (lo8 == 0x2a)
1023     debug("lds\tr%i,pr\n", r8);
1024 dpavlin 40 else if (lo8 == 0x2b) {
1025     debug("jmp\t@r%i", r8);
1026     if (running) {
1027     symbol = get_symbol_name(
1028     &cpu->machine->symbol_context,
1029     cpu->cd.sh.r[r8], &offset);
1030     if (symbol != NULL)
1031     debug("\t\t; <%s>", symbol);
1032     }
1033     debug("\n");
1034     } else if (lo8 == 0x2e)
1035 dpavlin 32 debug("ldc\tr%i,vbr\n", r8);
1036     else if (lo8 == 0x33)
1037     debug("stc.l\tssr,@-r%i\n", r8);
1038     else if (lo8 == 0x37)
1039     debug("ldc.l\t@r%i+,ssr\n", r8);
1040     else if (lo8 == 0x3e)
1041     debug("ldc\tr%i,ssr\n", r8);
1042     else if (lo8 == 0x43)
1043     debug("stc.l\tspc,@-r%i\n", r8);
1044     else if (lo8 == 0x47)
1045     debug("ldc.l\t@r%i+,spc\n", r8);
1046     else if (lo8 == 0x4e)
1047     debug("ldc\tr%i,spc\n", r8);
1048     else if (lo8 == 0x52)
1049     debug("sts.l\tfpul,@-r%i\n", r8);
1050 dpavlin 14 else if (lo8 == 0x56)
1051     debug("lds.l\t@r%i+,fpul\n", r8);
1052     else if (lo8 == 0x5a)
1053     debug("lds\tr%i,fpul\n", r8);
1054 dpavlin 32 else if (lo8 == 0x62)
1055     debug("sts.l\tfpscr,@-r%i\n", r8);
1056     else if (lo8 == 0x66)
1057     debug("lds.l\t@r%i+,fpscr\n", r8);
1058 dpavlin 14 else if (lo8 == 0x6a)
1059     debug("lds\tr%i,fpscr\n", r8);
1060 dpavlin 32 else if ((lo8 & 0x8f) == 0x83)
1061     debug("stc.l\tr%i_bank,@-r%i\n", (lo8 >> 4) & 7, r8);
1062     else if ((lo8 & 0x8f) == 0x87)
1063     debug("ldc.l\t@r%i,r%i_bank\n", r8, (lo8 >> 4) & 7, r8);
1064     else if ((lo8 & 0x8f) == 0x8e)
1065     debug("ldc\tr%i,r%i_bank\n", r8, (lo8 >> 4) & 7);
1066     else if (lo8 == 0xfa)
1067     debug("ldc\tr%i,dbr\n", r8);
1068 dpavlin 14 else
1069     debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x\n", hi4, lo8);
1070     break;
1071     case 0x5:
1072 dpavlin 34 debug("mov.l\t@(%i,r%i),r%i", lo4 * 4, r4, r8);
1073     if (running) {
1074     debug("\t; r%i+%i = 0x%08"PRIx32, r4, lo4 * 4,
1075     cpu->cd.sh.r[r4] + lo4 * 4);
1076     }
1077     debug("\n");
1078 dpavlin 14 break;
1079     case 0x6:
1080     if (lo4 == 0x0)
1081     debug("mov.b\t@r%i,r%i\n", r4, r8);
1082     else if (lo4 == 0x1)
1083     debug("mov.w\t@r%i,r%i\n", r4, r8);
1084     else if (lo4 == 0x2)
1085     debug("mov.l\t@r%i,r%i\n", r4, r8);
1086     else if (lo4 == 0x3)
1087     debug("mov\tr%i,r%i\n", r4, r8);
1088     else if (lo4 == 0x4)
1089     debug("mov.b\t@r%i+,r%i\n", r4, r8);
1090 dpavlin 32 else if (lo4 == 0x5)
1091     debug("mov.w\t@r%i+,r%i\n", r4, r8);
1092 dpavlin 14 else if (lo4 == 0x6)
1093     debug("mov.l\t@r%i+,r%i\n", r4, r8);
1094     else if (lo4 == 0x7)
1095     debug("not\tr%i,r%i\n", r4, r8);
1096     else if (lo4 == 0x8)
1097     debug("swap.b\tr%i,r%i\n", r4, r8);
1098     else if (lo4 == 0x9)
1099     debug("swap.w\tr%i,r%i\n", r4, r8);
1100     else if (lo4 == 0xa)
1101     debug("negc\tr%i,r%i\n", r4, r8);
1102     else if (lo4 == 0xb)
1103     debug("neg\tr%i,r%i\n", r4, r8);
1104     else if (lo4 == 0xc)
1105     debug("extu.b\tr%i,r%i\n", r4, r8);
1106     else if (lo4 == 0xd)
1107     debug("extu.w\tr%i,r%i\n", r4, r8);
1108     else if (lo4 == 0xe)
1109     debug("exts.b\tr%i,r%i\n", r4, r8);
1110     else if (lo4 == 0xf)
1111     debug("exts.w\tr%i,r%i\n", r4, r8);
1112     else
1113     debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x\n", hi4, lo8);
1114     break;
1115     case 0x7:
1116     debug("add\t#%i,r%i\n", (int8_t)lo8, r8);
1117     break;
1118     case 0x8:
1119 dpavlin 34 if (r8 == 0 || r8 == 4) {
1120     if (r8 == 0x0)
1121     debug("mov.b\tr0,@(%i,r%i)", lo4, r4);
1122     else if (r8 == 0x4)
1123     debug("mov.b\t@(%i,r%i),r0", lo4, r4);
1124     if (running) {
1125     debug("\t; r%i+%i = 0x%08"PRIx32, r4, lo4,
1126     cpu->cd.sh.r[r4] + lo4);
1127     }
1128     debug("\n");
1129     } else if (r8 == 1 || r8 == 5) {
1130     if (r8 == 0x1)
1131     debug("mov.w\tr0,@(%i,r%i)", lo4 * 2, r4);
1132     else if (r8 == 0x5)
1133     debug("mov.w\t@(%i,r%i),r0", lo4 * 2, r4);
1134     if (running) {
1135     debug("\t; r%i+%i = 0x%08"PRIx32, r4, lo4 * 2,
1136     cpu->cd.sh.r[r4] + lo4 * 2);
1137     }
1138     debug("\n");
1139 dpavlin 32 } else if (r8 == 0x8) {
1140 dpavlin 14 debug("cmp/eq\t#%i,r0\n", (int8_t)lo8);
1141 dpavlin 32 } else if (r8 == 0x9 || r8 == 0xb || r8 == 0xd || r8 == 0xf) {
1142 dpavlin 14 addr = (int8_t)lo8;
1143     addr = dumpaddr + 4 + (addr << 1);
1144 dpavlin 40 debug("b%s%s\t0x%x",
1145 dpavlin 14 (r8 == 0x9 || r8 == 0xd)? "t" : "f",
1146     (r8 == 0x9 || r8 == 0xb)? "" : "/s", (int)addr);
1147 dpavlin 40 symbol = get_symbol_name(&cpu->machine->symbol_context,
1148     addr, &offset);
1149     if (symbol != NULL)
1150     debug("\t; <%s>", symbol);
1151     debug("\n");
1152 dpavlin 14 } else
1153     debug("UNIMPLEMENTED hi4=0x%x,0x%x\n", hi4, r8);
1154     break;
1155     case 0x9:
1156     case 0xd:
1157 dpavlin 30 addr = lo8 * (hi4==9? 2 : 4);
1158 dpavlin 14 addr += (dumpaddr & ~(hi4==9? 1 : 3)) + 4;
1159 dpavlin 40 debug("mov.%s\t0x%x,r%i", hi4==9? "w":"l", (int)addr, r8);
1160     symbol = get_symbol_name(&cpu->machine->symbol_context,
1161     addr, &offset);
1162     if (symbol != NULL)
1163     debug("\t; <%s>", symbol);
1164     debug("\n");
1165 dpavlin 14 break;
1166     case 0xa:
1167     case 0xb:
1168     addr = (int32_t)(int16_t)((iword & 0xfff) << 4);
1169     addr = ((int32_t)addr >> 3);
1170     addr += dumpaddr + 4;
1171 dpavlin 40 debug("%s\t0x%x", hi4==0xa? "bra":"bsr", (int)addr);
1172    
1173     symbol = get_symbol_name(&cpu->machine->symbol_context,
1174     addr, &offset);
1175     if (symbol != NULL)
1176     debug("\t; <%s>", symbol);
1177     debug("\n");
1178 dpavlin 14 break;
1179     case 0xc:
1180 dpavlin 32 if (r8 == 0x0)
1181     debug("mov.b\tr0,@(%i,gbr)\n", lo8);
1182     else if (r8 == 0x1)
1183     debug("mov.w\tr0,@(%i,gbr)\n", lo8 * 2);
1184     else if (r8 == 0x2)
1185     debug("mov.l\tr0,@(%i,gbr)\n", lo8 * 4);
1186     else if (r8 == 0x3)
1187 dpavlin 14 debug("trapa\t#%i\n", (uint8_t)lo8);
1188 dpavlin 32 else if (r8 == 0x4)
1189     debug("mov.b\t(%i,gbr),r0\n", lo8);
1190     else if (r8 == 0x5)
1191     debug("mov.w\t(%i,gbr),r0\n", lo8 * 2);
1192     else if (r8 == 0x6)
1193     debug("mov.l\t(%i,gbr),r0\n", lo8 * 4);
1194     else if (r8 == 0x7) {
1195     addr = lo8 * 4 + (dumpaddr & ~3) + 4;
1196     debug("mova\t0x%x,r0\n", (int)addr);
1197     } else if (r8 == 0x8)
1198 dpavlin 14 debug("tst\t#%i,r0\n", (uint8_t)lo8);
1199     else if (r8 == 0x9)
1200     debug("and\t#%i,r0\n", (uint8_t)lo8);
1201     else if (r8 == 0xa)
1202     debug("xor\t#%i,r0\n", (uint8_t)lo8);
1203     else if (r8 == 0xb)
1204     debug("or\t#%i,r0\n", (uint8_t)lo8);
1205     else if (r8 == 0xc)
1206     debug("tst.b\t#%i,@(r0,gbr)\n", (uint8_t)lo8);
1207     else if (r8 == 0xd)
1208     debug("and.b\t#%i,@(r0,gbr)\n", (uint8_t)lo8);
1209     else if (r8 == 0xe)
1210     debug("xor.b\t#%i,@(r0,gbr)\n", (uint8_t)lo8);
1211     else if (r8 == 0xf)
1212     debug("or.b\t#%i,@(r0,gbr)\n", (uint8_t)lo8);
1213     else
1214     debug("UNIMPLEMENTED hi4=0x%x,0x%x\n", hi4, r8);
1215     break;
1216     case 0xe:
1217     debug("mov\t#%i,r%i\n", (int8_t)lo8, r8);
1218     break;
1219 dpavlin 32 case 0xf:
1220     if (lo4 == 0x0)
1221     debug("fadd\t%sr%i,%sr%i\n",
1222     cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r4,
1223     cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1224     else if (lo4 == 0x1)
1225     debug("fsub\t%sr%i,%sr%i\n",
1226     cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r4,
1227     cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1228     else if (lo4 == 0x2)
1229     debug("fmul\t%sr%i,%sr%i\n",
1230     cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r4,
1231     cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1232     else if (lo4 == 0x3)
1233     debug("fdiv\t%sr%i,%sr%i\n",
1234     cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r4,
1235     cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1236     else if (lo4 == 0x4)
1237     debug("fcmp/eq\t%sr%i,%sr%i\n",
1238     cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r4,
1239     cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1240     else if (lo4 == 0x5)
1241     debug("fcmp/gt\t%sr%i,%sr%i\n",
1242     cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r4,
1243     cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1244     else if (lo4 == 0x6) {
1245     char *n = "fr";
1246     if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1247     n = (r8 & 1)? "xd" : "dr";
1248     r8 &= ~1;
1249     }
1250     debug("fmov\t@(r0,r%i),%s%i\n", r4, n, r8);
1251     } else if (lo4 == 0x7) {
1252     char *n = "fr";
1253     if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1254     n = (r4 & 1)? "xd" : "dr";
1255     r4 &= ~1;
1256     }
1257     debug("fmov\t%s%i,@(r0,r%i)\n", n, r4, r8);
1258     } else if (lo4 == 0x8) {
1259     char *n = "fr";
1260     if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1261     n = (r8 & 1)? "xd" : "dr";
1262     r8 &= ~1;
1263     }
1264     debug("fmov\t@r%i,%s%i\n", r4, n, r8);
1265     } else if (lo4 == 0x9) {
1266     char *n = "fr";
1267     if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1268     n = (r8 & 1)? "xd" : "dr";
1269     r8 &= ~1;
1270     }
1271     debug("fmov\t@r%i+,%s%i\n", r4, n, r8);
1272     } else if (lo4 == 0xa) {
1273     char *n = "fr";
1274     if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1275     n = (r4 & 1)? "xd" : "dr";
1276     r4 &= ~1;
1277     }
1278     debug("fmov\t%s%i,@r%i\n", n, r4, r8);
1279     } else if (lo4 == 0xb) {
1280     char *n = "fr";
1281     if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1282     n = (r4 & 1)? "xd" : "dr";
1283     r4 &= ~1;
1284     }
1285     debug("fmov\t%s%i,@-r%i\n", n, r4, r8);
1286     } else if (lo4 == 0xc) {
1287     char *n1 = "fr", *n2 = "fr";
1288     if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1289     n1 = (r4 & 1)? "xd" : "dr";
1290     n2 = (r8 & 1)? "xd" : "dr";
1291     r4 &= ~1; r8 &= ~1;
1292     }
1293     debug("fmov\t%s%i,%s%i\n", n1, r4, n2, r8);
1294     } else if (lo8 == 0x0d)
1295     debug("fsts\tfpul,fr%i\n", r8);
1296     else if (lo8 == 0x1d)
1297     debug("flds\tfr%i,fpul\n", r8);
1298     else if (lo8 == 0x2d)
1299     debug("float\tfpul,%sr%i\n",
1300     cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1301     else if (lo8 == 0x3d)
1302     debug("ftrc\t%sr%i,fpul\n",
1303     cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1304     else if (lo8 == 0x4d)
1305     debug("fneg\t%sr%i\n",
1306     cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1307     else if (lo8 == 0x5d)
1308     debug("fabs\t%sr%i\n",
1309     cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1310     else if (lo8 == 0x6d)
1311     debug("fsqrt\t%sr%i\n",
1312     cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1313     else if (lo8 == 0x8d)
1314     debug("fldi0\tfr%i\n", r8);
1315     else if (lo8 == 0x9d)
1316     debug("fldi1\tfr%i\n", r8);
1317 dpavlin 40 else if (lo8 == 0xad)
1318     debug("fcnvsd\tfpul,dr%i\n", r8);
1319     else if (lo8 == 0xbd)
1320     debug("fcnvds\tdr%i,fpul\n", r8);
1321 dpavlin 32 else if ((iword & 0x01ff) == 0x00fd)
1322     debug("fsca\tfpul,dr%i\n", r8);
1323     else if (iword == 0xf3fd)
1324     debug("fschg\n");
1325     else if (iword == 0xfbfd)
1326     debug("frchg\n");
1327     else if ((iword & 0xf3ff) == 0xf1fd)
1328     debug("ftrv\txmtrx,fv%i\n", r8 & 0xc);
1329     else if (lo4 == 0xe)
1330     debug("fmac\tfr0,fr%i,fr%i\n", r4, r8);
1331     else
1332     debug("UNIMPLEMENTED hi4=0x%x,0x%x\n", hi4, lo8);
1333     break;
1334 dpavlin 14 default:debug("UNIMPLEMENTED hi4=0x%x\n", hi4);
1335     }
1336    
1337     return sizeof(iword);
1338     }
1339    
1340    
1341     /*
1342     * sh_cpu_disassemble_instr():
1343     *
1344     * Convert an instruction word into human readable format, for instruction
1345     * tracing.
1346     *
1347     * If running is 1, cpu->pc should be the address of the instruction.
1348     *
1349     * If running is 0, things that depend on the runtime environment (eg.
1350     * register contents) will not be shown, and addr will be used instead of
1351     * cpu->pc for relative addresses.
1352     */
1353     int sh_cpu_disassemble_instr(struct cpu *cpu, unsigned char *instr,
1354 dpavlin 24 int running, uint64_t dumpaddr)
1355 dpavlin 14 {
1356 dpavlin 22 uint64_t offset;
1357 dpavlin 14 uint32_t iword;
1358 dpavlin 22 char *symbol;
1359 dpavlin 14
1360     if (running)
1361     dumpaddr = cpu->pc;
1362    
1363     symbol = get_symbol_name(&cpu->machine->symbol_context,
1364     dumpaddr, &offset);
1365     if (symbol != NULL && offset==0)
1366     debug("<%s>\n", symbol);
1367    
1368     if (cpu->machine->ncpus > 1 && running)
1369     debug("cpu%i: ", cpu->cpu_id);
1370    
1371 dpavlin 30 if (cpu->cd.sh.cpu_type.bits == 32)
1372 dpavlin 14 debug("%08x", (int)dumpaddr);
1373     else
1374     debug("%016llx", (long long)dumpaddr);
1375    
1376     if (cpu->cd.sh.compact)
1377     return sh_cpu_disassemble_instr_compact(cpu, instr,
1378 dpavlin 24 running, dumpaddr);
1379 dpavlin 14
1380     if (cpu->byte_order == EMUL_BIG_ENDIAN)
1381     iword = (instr[0] << 24) + (instr[1] << 16) + (instr[2] << 8)
1382     + instr[3];
1383     else
1384     iword = (instr[3] << 24) + (instr[2] << 16) + (instr[1] << 8)
1385     + instr[0];
1386    
1387     debug(": %08x\t", iword);
1388    
1389     /*
1390     * Decode the instruction:
1391     */
1392    
1393     debug("TODO\n");
1394    
1395     return sizeof(iword);
1396     }
1397    
1398    
1399     #include "tmp_sh_tail.c"
1400    

  ViewVC Help
Powered by ViewVC 1.1.26