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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 44 - (show 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 /*
2 * Copyright (C) 2005-2007 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: cpu_sh.c,v 1.76 2007/06/28 13:36:47 debug Exp $
29 *
30 * Hitachi SuperH ("SH") CPU emulation.
31 *
32 * TODO: It would be nice if this could encompass both 64-bit SH5, and
33 * 32-bit SH encodings. Right now, it only really supports 32-bit mode.
34 *
35 * TODO: This actually only works or SH4 so far, not SH3.
36 */
37
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <ctype.h>
42 #include <unistd.h>
43
44 #include "cpu.h"
45 #include "device.h"
46 #include "float_emul.h"
47 #include "interrupt.h"
48 #include "machine.h"
49 #include "memory.h"
50 #include "misc.h"
51 #include "settings.h"
52 #include "symbol.h"
53
54 #include "sh4_exception.h"
55 #include "sh4_mmu.h"
56
57
58 #define DYNTRANS_32
59 #define DYNTRANS_DELAYSLOT
60 #include "tmp_sh_head.c"
61
62
63 extern int quiet_mode;
64
65 void sh_pc_to_pointers(struct cpu *);
66
67 void sh3_cpu_interrupt_assert(struct interrupt *interrupt);
68 void sh3_cpu_interrupt_deassert(struct interrupt *interrupt);
69
70
71 /*
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 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 return 0;
94
95 cpu->memory_rw = sh_memory_rw;
96
97 cpu->cd.sh.cpu_type = cpu_type_defs[i];
98 cpu->byte_order = EMUL_LITTLE_ENDIAN;
99 cpu->is_32bit = cpu->cd.sh.cpu_type.bits == 32;
100
101 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 cpu->translate_v2p = sh_translate_v2p;
109
110 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
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 /* Initial value of FPSCR (according to the SH4 manual): */
123 cpu->cd.sh.fpscr = 0x00040001;
124
125 /* (Initial value of the program counter on reboot is 0xA0000000.) */
126
127 /* Start in Privileged Mode: */
128 cpu->cd.sh.sr = SH_SR_MD | SH_SR_IMASK;
129
130 /* 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 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 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 /* Register the CPU's interrupts: */
178 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 struct interrupt template;
194 memset(&template, 0, sizeof(template));
195 template.line = i;
196 template.name = cpu->path;
197 template.extra = cpu;
198 template.interrupt_assert = sh3_cpu_interrupt_assert;
199 template.interrupt_deassert = sh3_cpu_interrupt_deassert;
200 interrupt_handler_register(&template);
201 }
202
203 /* SH4-specific memory mapped registers, TLBs, caches, etc: */
204 if (cpu->cd.sh.cpu_type.arch == 4) {
205 cpu->cd.sh.pcic_pcibus = device_add(machine, "sh4");
206
207 /*
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 return 1;
226 }
227
228
229 /*
230 * 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 */
249 void sh_update_interrupt_priorities(struct cpu *cpu)
250 {
251 int i;
252
253 /*
254 * Set priorities of known interrupts, without affecting the
255 * SH_INT_ASSERTED bit:
256 */
257
258 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
264 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
269 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
274 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 }
285
286
287 /*
288 * 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 * sh_cpu_interrupt_assert():
303 */
304 void sh_cpu_interrupt_assert(struct interrupt *interrupt)
305 {
306 struct cpu *cpu = interrupt->extra;
307 unsigned int irq_nr = interrupt->line;
308 unsigned int index = irq_nr / 0x20;
309 unsigned int prio;
310
311 /* 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
315 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
321 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
327
328 /*
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
337 /* 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
341 /* 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 }
354 }
355 }
356 }
357
358
359 /*
360 * 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 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 }
378
379
380 /*
381 * sh_cpu_dumpinfo():
382 */
383 void sh_cpu_dumpinfo(struct cpu *cpu)
384 {
385 debug(" (%s-endian)\n",
386 cpu->byte_order == EMUL_BIG_ENDIAN? "Big" : "Little");
387 }
388
389
390 /*
391 * 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 * 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 uint64_t offset;
456 int i, x = cpu->cpu_id;
457
458 if (gprs) {
459 /* Special registers (pc, ...) first: */
460 symbol = get_symbol_name(&cpu->machine->symbol_context,
461 cpu->pc, &offset);
462
463 debug("cpu%i: pc = 0x%08"PRIx32, x, (uint32_t)cpu->pc);
464 debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
465
466 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 (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 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 for (i=0; i<SH_N_GPRS; i++) {
488 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 }
494 }
495
496 if (coprocs & 1) {
497 /* Floating point: */
498 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
505 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
513 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
522 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
532 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 }
540 }
541 }
542
543
544 /*
545 * 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 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 }
575
576
577 /*
578 * sh_update_sr():
579 *
580 * Writes a new value to the status register.
581 */
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 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 }
594
595 cpu->cd.sh.sr = new_sr;
596 }
597
598
599 /*
600 * 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 *
627 * vaddr contains the faulting address, on TLB exceptions.
628 */
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 debug(", pc=0x%08"PRIx32" ", (uint32_t)cpu->pc);
640 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 fatal("[ sh_exception(): BL bit already set. ]\n");
648
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
673 /*
674 * Stuff common to all exceptions:
675 */
676
677 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
681 if (intevt > 0) {
682 cpu->cd.sh.intevt = intevt;
683 expevt = -1;
684 } else {
685 cpu->cd.sh.expevt = expevt;
686 }
687
688 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
694 /* 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 /*
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 cpu->cd.sh.spc += sizeof(uint16_t);
728 break;
729
730 case EXPEVT_RES_INST:
731 /*
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 break;
742 #endif
743
744 case EXPEVT_FPU_DISABLE:
745 break;
746
747 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 * sh_cpu_disassemble_instr():
758 *
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 *
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 */
772 int sh_cpu_disassemble_instr(struct cpu *cpu, unsigned char *instr,
773 int running, uint64_t dumpaddr)
774 {
775 char *symbol;
776 uint64_t offset, addr;
777 uint16_t iword;
778 int hi4, lo4, lo8, r8, r4;
779
780 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 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 debug(": %04x %s\t", iword, cpu->delay_slot? "(d)" : "");
799 hi4 = iword >> 12; lo4 = iword & 15; lo8 = iword & 255;
800 r8 = (iword >> 8) & 15; r4 = (iword >> 4) & 15;
801
802
803 /*
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 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 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 }
832 debug("\n");
833 } else if (lo4 == 0x7)
834 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 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 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 }
862 debug("\n");
863 } else if (lo8 == 0x12)
864 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 else if (iword == 0x001b)
872 debug("sleep\n");
873 else if (lo8 == 0x22)
874 debug("stc\tvbr,r%i\n", r8);
875 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 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 else if (iword == 0x003b)
890 debug("brk\n");
891 else if (lo8 == 0x42)
892 debug("stc\tspc,r%i\n", r8);
893 else if (iword == 0x0048)
894 debug("clrs\n");
895 else if (iword == 0x0058)
896 debug("sets\n");
897 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 else if (lo8 == 0x83)
904 debug("pref\t@r%i\n", r8);
905 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 else if (iword == SH_INVALID_INSTR)
916 debug("gxemul_dreamcast_prom_emul\n");
917 else
918 debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x\n", hi4, lo8);
919 break;
920 case 0x1:
921 debug("mov.l\tr%i,@(%i,r%i)", r4, lo4 * 4, r8);
922 if (running) {
923 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 }
932 debug("\n");
933 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 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 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 else if (lo8 == 0x07)
1016 debug("ldc.l\t@r%i+,sr\n", r8);
1017 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 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 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 else if (lo8 == 0x17)
1044 debug("ldc.l\t@r%i+,gbr\n", r8);
1045 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 else if (lo8 == 0x23)
1062 debug("stc.l\tvbr,@-r%i\n", r8);
1063 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 else if (lo8 == 0x27)
1070 debug("ldc.l\t@r%i+,vbr\n", r8);
1071 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 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 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 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 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 else if (lo8 == 0x6a)
1112 debug("lds\tr%i,fpscr\n", r8);
1113 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 else
1122 debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x\n", hi4, lo8);
1123 break;
1124 case 0x5:
1125 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 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 else if (lo4 == 0x5)
1144 debug("mov.w\t@r%i+,r%i\n", r4, r8);
1145 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 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 } else if (r8 == 0x8) {
1193 debug("cmp/eq\t#%i,r0\n", (int8_t)lo8);
1194 } else if (r8 == 0x9 || r8 == 0xb || r8 == 0xd || r8 == 0xf) {
1195 addr = (int8_t)lo8;
1196 addr = dumpaddr + 4 + (addr << 1);
1197 debug("b%s%s\t0x%x",
1198 (r8 == 0x9 || r8 == 0xd)? "t" : "f",
1199 (r8 == 0x9 || r8 == 0xb)? "" : "/s", (int)addr);
1200 symbol = get_symbol_name(&cpu->machine->symbol_context,
1201 addr, &offset);
1202 if (symbol != NULL)
1203 debug("\t; <%s>", symbol);
1204 debug("\n");
1205 } else
1206 debug("UNIMPLEMENTED hi4=0x%x,0x%x\n", hi4, r8);
1207 break;
1208 case 0x9:
1209 case 0xd:
1210 addr = lo8 * (hi4==9? 2 : 4);
1211 addr += (dumpaddr & ~(hi4==9? 1 : 3)) + 4;
1212 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 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 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 break;
1232 case 0xc:
1233 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 debug("trapa\t#%i\n", (uint8_t)lo8);
1241 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 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 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 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 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 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