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

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


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

  ViewVC Help
Powered by ViewVC 1.1.26