/[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 44 - (hide annotations)
Mon Oct 8 16:22:56 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 39130 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1632 2007/09/11 21:46:35 debug Exp $
20070616	Implementing the MIPS32/64 revision 2 "ror" instruction.
20070617	Adding a struct for each physpage which keeps track of which
		ranges within that page (base offset, length) that are
		continuously translatable. When running with native code
		generation enabled (-b), a range is added after each read-
		ahead loop.
		Experimenting with using the physical program counter sample
		data (implemented 20070608) together with the "translatable
		range" information, to figure out which physical address ranges
		would be worth translating to native code (if the number of
		samples falling within a range is above a certain threshold).
20070618	Adding automagic building of .index comment files for
		src/file/, src/promemul/, src src/useremul/ as well.
		Adding a "has been translated" bit to the ranges, so that only
		not-yet-translated ranges will be sampled.
20070619	Moving src/cpu.c and src/memory_rw.c into src/cpus/,
		src/device.c into src/devices/, and src/machine.c into
		src/machines/.
		Creating a skeleton cc/ld native backend module; beginning on
		the function which will detect cc command line, etc.
20070620	Continuing on the native code generation infrastructure.
20070621	Moving src/x11.c and src/console.c into a new src/console/
		subdir (for everything that is console or framebuffer related).
		Moving src/symbol*.c into a new src/symbol/, which should
		contain anything that is symbol handling related.
20070624	Making the program counter sampling threshold a "settings
		variable" (sampling_threshold), i.e. it can now be changed
		during runtime.
		Switching the RELEASE notes format from plain text to HTML.
		If the TMPDIR environment variable is set, it is used instead
		of "/tmp" for temporary files.
		Continuing on the cc/ld backend: simple .c code is generated,
		the compiler and linker are called, etc.
		Adding detection of host architecture to the configure script
		(again), and adding icache invalidation support (only
		implemented for Alpha hosts so far).
20070625	Simplifying the program counter sampling mechanism.
20070626	Removing the cc/ld native code generation stuff, program
		counter sampling, etc; it would not have worked well in the
		general case.
20070627	Removing everything related to native code generation.
20070629	Removing the (practically unusable) support for multiple
		emulations. (The single emulation allowed now still supports
		multiple simultaneous machines, as before.)
		Beginning on PCCTWO and M88K interrupts.
20070723	Adding a dummy skeleton for emulation of M32R processors.
20070901	Fixing a warning found by "gcc version 4.3.0 20070817
		(experimental)" on amd64.
20070905	Removing some more traces of the old "multiple emulations"
		code.
		Also looking in /usr/local/include and /usr/local/lib for
		X11 libs, when running configure.
20070909	Minor updates to the guest OS install instructions, in
		preparation for the NetBSD 4.0 release.
20070918	More testing of NetBSD 4.0 RC1.

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

  ViewVC Help
Powered by ViewVC 1.1.26