/[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 28 - (hide annotations)
Mon Oct 8 16:20:26 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 16060 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1298 2006/07/22 11:27:46 debug Exp $
20060626	Continuing on SPARC emulation (beginning on the 'save'
		instruction, register windows, etc).
20060629	Planning statistics gathering (new -s command line option),
		and renaming speed_tricks to allow_instruction_combinations.
20060630	Some minor manual page updates.
		Various cleanups.
		Implementing the -s command line option.
20060701	FINALLY found the bug which prevented Linux and Ultrix from
		running without the ugly hack in the R2000/R3000 cache isol
		code; it was the phystranslation hint array which was buggy.
		Removing the phystranslation hint code completely, for now.
20060702	Minor dyntrans cleanups; invalidation of physpages now only
		invalidate those parts of a page that have actually been
		translated. (32 parts per page.)
		Some MIPS non-R3000 speed fixes.
		Experimenting with MIPS instruction combination for some
		addiu+bne+sw loops, and sw+sw+sw.
		Adding support (again) for larger-than-4KB pages in MIPS tlbw*.
		Continuing on SPARC emulation: adding load/store instructions.
20060704	Fixing a virtual vs physical page shift bug in the new tlbw*
		implementation. Problem noticed by Jakub Jermar. (Many thanks.)
		Moving rfe and eret to cpu_mips_instr.c, since that is the
		only place that uses them nowadays.
20060705	Removing the BSD license from the "testmachine" include files,
		placing them in the public domain instead; this enables the
		testmachine stuff to be used from projects which are
		incompatible with the BSD license for some reason.
20060707	Adding instruction combinations for the R2000/R3000 L1
		I-cache invalidation code used by NetBSD/pmax 3.0, lui+addiu,
		various branches followed by addiu or nop, and jr ra followed
		by addiu. The time it takes to perform a full NetBSD/pmax R3000
		install on the laptop has dropped from 573 seconds to 539. :-)
20060708	Adding a framebuffer controller device (dev_fbctrl), which so
		far can be used to change the fb resolution during runtime, but
		in the future will also be useful for accelerated block fill/
		copy, and possibly also simplified character output.
		Adding an instruction combination for NetBSD/pmax' strlen.
20060709	Minor fixes: reading raw files in src/file.c wasn't memblock
		aligned, removing buggy multi_sw MIPS instruction combination,
		etc.
20060711	Adding a machine_qemu.c, which contains a "qemu_mips" machine.
		(It mimics QEMU's MIPS machine mode, so that a test kernel
		made for QEMU_MIPS also can run in GXemul... at least to some
		extent.)  Adding a short section about how to run this mode to
		doc/guestoses.html.
20060714	Misc. minor code cleanups.
20060715	Applying a patch which adds getchar() to promemul/yamon.c
		(from Oleksandr Tymoshenko).
		Adding yamon.h from NetBSD, and rewriting yamon.c to use it
		(instead of ugly hardcoded numbers) + some cleanup.
20060716	Found and fixed the bug which broke single-stepping of 64-bit
		programs between 0.4.0 and 0.4.0.1 (caused by too quick
		refactoring and no testing). Hopefully this fix will not
		break too many other things.
20060718	Continuing on the 8253 PIT; it now works with Linux/QEMU_MIPS.
		Re-adding the sw+sw+sw instr comb (the problem was that I had
		ignored endian issues); however, it doesn't seem to give any
		big performance gain.
20060720	Adding a dummy Transputer mode (T414, T800 etc) skeleton (only
		the 'j' and 'ldc' instructions are implemented so far). :-}
20060721	Adding gtreg.h from NetBSD, updating dev_gt.c to use it, plus
		misc. other updates to get Linux 2.6 for evbmips/malta working
		(thanks to Alec Voropay for the details).
		FINALLY found and fixed the bug which made tlbw* for non-R3000
		buggy; it was a reference count problem in the dyntrans core.
20060722	Testing stuff; things seem stable enough for a new release.

==============  RELEASE 0.4.1  ==============


1 dpavlin 14 /*
2 dpavlin 24 * Copyright (C) 2005-2006 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 28 * $Id: cpu_sh.c,v 1.17 2006/07/16 13:32:26 debug Exp $
29 dpavlin 14 *
30     * Hitachi SuperH ("SH") CPU emulation.
31     *
32     * TODO
33     */
34    
35     #include <stdio.h>
36     #include <stdlib.h>
37     #include <string.h>
38     #include <ctype.h>
39    
40     #include "cpu.h"
41     #include "machine.h"
42     #include "memory.h"
43     #include "misc.h"
44     #include "symbol.h"
45    
46    
47     #define DYNTRANS_DUALMODE_32
48     #include "tmp_sh_head.c"
49    
50    
51     /*
52     * sh_cpu_new():
53     *
54     * Create a new SH cpu object.
55     *
56     * Returns 1 on success, 0 if there was no matching SH processor with
57     * this cpu_type_name.
58     */
59     int sh_cpu_new(struct cpu *cpu, struct memory *mem, struct machine *machine,
60     int cpu_id, char *cpu_type_name)
61     {
62     if (strcasecmp(cpu_type_name, "SH") != 0)
63     return 0;
64    
65     cpu->memory_rw = sh_memory_rw;
66    
67     /* TODO: per CPU type? */
68     cpu->byte_order = EMUL_LITTLE_ENDIAN;
69     cpu->is_32bit = 1;
70     cpu->cd.sh.bits = 32;
71     cpu->cd.sh.compact = 1;
72    
73     if (cpu->is_32bit) {
74 dpavlin 28 cpu->run_instr = sh32_run_instr;
75 dpavlin 14 cpu->update_translation_table = sh32_update_translation_table;
76 dpavlin 18 cpu->invalidate_translation_caches =
77     sh32_invalidate_translation_caches;
78 dpavlin 14 cpu->invalidate_code_translation =
79     sh32_invalidate_code_translation;
80     } else {
81 dpavlin 28 cpu->run_instr = sh_run_instr;
82 dpavlin 14 cpu->update_translation_table = sh_update_translation_table;
83 dpavlin 18 cpu->invalidate_translation_caches =
84     sh_invalidate_translation_caches;
85 dpavlin 14 cpu->invalidate_code_translation =
86     sh_invalidate_code_translation;
87     }
88    
89     /* Only show name and caches etc for CPU nr 0 (in SMP machines): */
90     if (cpu_id == 0) {
91     debug("%s", cpu->name);
92     }
93    
94     return 1;
95     }
96    
97    
98     /*
99     * sh_cpu_list_available_types():
100     *
101     * Print a list of available SH CPU types.
102     */
103     void sh_cpu_list_available_types(void)
104     {
105     debug("SH\n");
106     /* TODO */
107     }
108    
109    
110     /*
111     * sh_cpu_dumpinfo():
112     */
113     void sh_cpu_dumpinfo(struct cpu *cpu)
114     {
115     debug("\n");
116     /* TODO */
117     }
118    
119    
120     /*
121     * sh_cpu_register_dump():
122     *
123     * Dump cpu registers in a relatively readable format.
124     *
125     * gprs: set to non-zero to dump GPRs and some special-purpose registers.
126     * coprocs: set bit 0..3 to dump registers in coproc 0..3.
127     */
128     void sh_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
129     {
130     char *symbol;
131 dpavlin 22 uint64_t offset;
132 dpavlin 14 int i, x = cpu->cpu_id, nregs = cpu->cd.sh.compact? 16 : 64;
133     int bits32 = cpu->cd.sh.bits == 32;
134    
135     if (gprs) {
136     /* Special registers (pc, ...) first: */
137     symbol = get_symbol_name(&cpu->machine->symbol_context,
138     cpu->pc, &offset);
139    
140     debug("cpu%i: pc = 0x", x);
141     if (bits32)
142     debug("%08x", (int)cpu->pc);
143     else
144     debug("%016llx", (long long)cpu->pc);
145     debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
146    
147     if (bits32) {
148     /* 32-bit: */
149     for (i=0; i<nregs; i++) {
150     if ((i % 4) == 0)
151     debug("cpu%i:", x);
152     debug(" r%02i = 0x%08x ", i,
153     (int)cpu->cd.sh.r[i]);
154     if ((i % 4) == 3)
155     debug("\n");
156     }
157     } else {
158     /* 64-bit: */
159     for (i=0; i<nregs; i++) {
160     int r = (i >> 1) + ((i & 1) << 4);
161     if ((i % 2) == 0)
162     debug("cpu%i:", x);
163     debug(" r%02i = 0x%016llx ", r,
164     (long long)cpu->cd.sh.r[r]);
165     if ((i % 2) == 1)
166     debug("\n");
167     }
168     }
169     }
170     }
171    
172    
173     /*
174     * sh_cpu_register_match():
175     */
176     void sh_cpu_register_match(struct machine *m, char *name,
177     int writeflag, uint64_t *valuep, int *match_register)
178     {
179     int cpunr = 0;
180    
181     /* CPU number: */
182    
183     /* TODO */
184    
185     /* Register name: */
186     if (strcasecmp(name, "pc") == 0) {
187     if (writeflag) {
188     m->cpus[cpunr]->pc = *valuep;
189     } else
190     *valuep = m->cpus[cpunr]->pc;
191     *match_register = 1;
192     }
193     }
194    
195    
196     /*
197 dpavlin 24 * sh_cpu_tlbdump():
198     *
199     * Called from the debugger to dump the TLB in a readable format.
200     * x is the cpu number to dump, or -1 to dump all CPUs.
201     *
202     * If rawflag is nonzero, then the TLB contents isn't formated nicely,
203     * just dumped.
204     */
205     void sh_cpu_tlbdump(struct machine *m, int x, int rawflag)
206     {
207     }
208    
209    
210     /*
211     * sh_cpu_gdb_stub():
212     *
213     * Execute a "remote GDB" command. Returns a newly allocated response string
214     * on success, NULL on failure.
215     */
216     char *sh_cpu_gdb_stub(struct cpu *cpu, char *cmd)
217     {
218     fatal("sh_cpu_gdb_stub(): TODO\n");
219     return NULL;
220     }
221    
222    
223     /*
224 dpavlin 14 * sh_cpu_interrupt():
225     */
226     int sh_cpu_interrupt(struct cpu *cpu, uint64_t irq_nr)
227     {
228     fatal("sh_cpu_interrupt(): TODO\n");
229     return 0;
230     }
231    
232    
233     /*
234     * sh_cpu_interrupt_ack():
235     */
236     int sh_cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr)
237     {
238     /* fatal("sh_cpu_interrupt_ack(): TODO\n"); */
239     return 0;
240     }
241    
242    
243     /*
244     * sh_cpu_disassemble_instr_compact():
245     *
246     * SHcompact instruction disassembly. The top 4 bits of each 16-bit
247     * instruction word is used as the main opcode. For most instructions, the
248     * lowest 4 or 8 bits then select sub-opcode.
249     */
250     int sh_cpu_disassemble_instr_compact(struct cpu *cpu, unsigned char *instr,
251 dpavlin 24 int running, uint64_t dumpaddr)
252 dpavlin 14 {
253 dpavlin 22 uint64_t addr;
254 dpavlin 14 uint16_t iword;
255     int hi4, lo4, lo8, r8, r4;
256    
257     if (cpu->byte_order == EMUL_BIG_ENDIAN)
258     iword = (instr[0] << 8) + instr[1];
259     else
260     iword = (instr[1] << 8) + instr[0];
261    
262     debug(": %04x \t", iword);
263     hi4 = iword >> 12; lo4 = iword & 15; lo8 = iword & 255;
264     r8 = (iword >> 8) & 15; r4 = (iword >> 4) & 15;
265    
266     /*
267     * Decode the instruction:
268     */
269    
270     switch (hi4) {
271     case 0x0:
272     if (lo8 == 0x02)
273     debug("stc\tsr,r%i\n", r8);
274     else if (lo8 == 0x03)
275     debug("bsrf\tr%i\n", r8);
276     else if (lo4 == 0x4)
277     debug("mov.b\tr%i,@(r0,r%i)\n", r4, r8);
278     else if (lo4 == 0x5)
279     debug("mov.w\tr%i,@(r0,r%i)\n", r4, r8);
280     else if (lo4 == 0x6)
281     debug("mov.l\tr%i,@(r0,r%i)\n", r4, r8);
282     else if (lo4 == 0x7)
283     debug("mul.l\tr%i,r%i\n", r4, r8);
284     else if (iword == 0x0008)
285     debug("clrt\n");
286     else if (iword == 0x0009)
287     debug("nop\n");
288     else if (lo8 == 0x0a)
289     debug("sts\tmach,r%i\n", r8);
290     else if (iword == 0x000b)
291     debug("rts\n");
292     else if (lo4 == 0xc)
293     debug("mov.b\t@(r0,r%i),r%i\n", r4, r8);
294     else if (lo4 == 0xd)
295     debug("mov.w\t@(r0,r%i),r%i\n", r4, r8);
296     else if (lo4 == 0xe)
297     debug("mov.l\t@(r0,r%i),r%i\n", r4, r8);
298     else if (lo8 == 0x12)
299     debug("stc\tgbr,r%i\n", r8);
300     else if (iword == 0x0018)
301     debug("sett\n");
302     else if (iword == 0x0019)
303     debug("div0u\n");
304     else if (lo8 == 0x1a)
305     debug("sts\tmacl,r%i\n", r8);
306     else if (lo8 == 0x23)
307     debug("braf\tr%i\n", r8);
308     else if (iword == 0x0028)
309     debug("clrmac\n");
310     else if (lo8 == 0x29)
311     debug("movt\tr%i\n", r8);
312     else if (iword == 0x003b)
313     debug("brk\n");
314     else if (iword == 0x0048)
315     debug("clrs\n");
316     else if (iword == 0x0058)
317     debug("sets\n");
318     else if (lo8 == 0x83)
319     debug("pref\t@r%i\n", r8);
320     else
321     debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x\n", hi4, lo8);
322     break;
323     case 0x1:
324     debug("mov.l\tr%i,@(%i,r%i)\n", r4, lo4 * 4, r8);
325     break;
326     case 0x2:
327     if (lo4 == 0x0)
328     debug("mov.b\tr%i,@r%i\n", r4, r8);
329     else if (lo4 == 0x1)
330     debug("mov.w\tr%i,@r%i\n", r4, r8);
331     else if (lo4 == 0x2)
332     debug("mov.l\tr%i,@r%i\n", r4, r8);
333     else if (lo4 == 0x4)
334     debug("mov.b\tr%i,@-r%i\n", r4, r8);
335     else if (lo4 == 0x5)
336     debug("mov.w\tr%i,@-r%i\n", r4, r8);
337     else if (lo4 == 0x6)
338     debug("mov.l\tr%i,@-r%i\n", r4, r8);
339     else if (lo4 == 0x7)
340     debug("div0s\tr%i,r%i\n", r4, r8);
341     else if (lo4 == 0x8)
342     debug("tst\tr%i,r%i\n", r4, r8);
343     else if (lo4 == 0x9)
344     debug("and\tr%i,r%i\n", r4, r8);
345     else if (lo4 == 0xa)
346     debug("xor\tr%i,r%i\n", r4, r8);
347     else if (lo4 == 0xb)
348     debug("or\tr%i,r%i\n", r4, r8);
349     else if (lo4 == 0xc)
350     debug("cmp/str\tr%i,r%i\n", r4, r8);
351     else if (lo4 == 0xd)
352     debug("xtrct\tr%i,r%i\n", r4, r8);
353     else if (lo4 == 0xe)
354     debug("mulu.w\tr%i,r%i\n", r4, r8);
355     else if (lo4 == 0xf)
356     debug("muls.w\tr%i,r%i\n", r4, r8);
357     else
358     debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x\n", hi4, lo8);
359     break;
360     case 0x3:
361     if (lo4 == 0x0)
362     debug("cmp/eq\tr%i,r%i\n", r4, r8);
363     else if (lo4 == 0x2)
364     debug("cmp/hs\tr%i,r%i\n", r4, r8);
365     else if (lo4 == 0x3)
366     debug("cmp/ge\tr%i,r%i\n", r4, r8);
367     else if (lo4 == 0x4)
368     debug("div1\tr%i,r%i\n", r4, r8);
369     else if (lo4 == 0x5)
370     debug("dmulu.l\tr%i,r%i\n", r4, r8);
371     else if (lo4 == 0x6)
372     debug("cmp/hi\tr%i,r%i\n", r4, r8);
373     else if (lo4 == 0x7)
374     debug("cmp/gt\tr%i,r%i\n", r4, r8);
375     else if (lo4 == 0x8)
376     debug("sub\tr%i,r%i\n", r4, r8);
377     else if (lo4 == 0xa)
378     debug("subc\tr%i,r%i\n", r4, r8);
379     else if (lo4 == 0xb)
380     debug("subv\tr%i,r%i\n", r4, r8);
381     else if (lo4 == 0xc)
382     debug("add\tr%i,r%i\n", r4, r8);
383     else if (lo4 == 0xd)
384     debug("dmuls.l\tr%i,r%i\n", r4, r8);
385     else if (lo4 == 0xe)
386     debug("addc\tr%i,r%i\n", r4, r8);
387     else if (lo4 == 0xf)
388     debug("addv\tr%i,r%i\n", r4, r8);
389     else
390     debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x\n", hi4, lo8);
391     break;
392     case 0x4:
393     if (lo8 == 0x00)
394     debug("shll\tr%i\n", r8);
395     else if (lo8 == 0x01)
396     debug("shlr\tr%i\n", r8);
397     else if (lo8 == 0x04)
398     debug("rotl\tr%i\n", r8);
399     else if (lo8 == 0x05)
400     debug("rotr\tr%i\n", r8);
401     else if (lo8 == 0x06)
402     debug("lds.l\t@r%i+,mach\n", r8);
403     else if (lo8 == 0x08)
404     debug("shll2\tr%i\n", r8);
405     else if (lo8 == 0x09)
406     debug("shlr2\tr%i\n", r8);
407     else if (lo8 == 0x0a)
408     debug("lds\tr%i,mach\n", r8);
409     else if (lo8 == 0x0b)
410     debug("jsr\t@r%i\n", r8);
411     else if (lo4 == 0xc)
412     debug("shad\tr%i,r%i\n", r4, r8);
413     else if (lo4 == 0xd)
414     debug("shld\tr%i,r%i\n", r4, r8);
415     else if (lo8 == 0x0e)
416     debug("ldc\tr%i,sr\n", r8);
417     else if (lo8 == 0x10)
418     debug("dt\tr%i\n", r8);
419     else if (lo8 == 0x11)
420     debug("cmp/pz\tr%i\n", r8);
421     else if (lo8 == 0x15)
422     debug("cmp/pl\tr%i\n", r8);
423     else if (lo8 == 0x16)
424     debug("lds.l\t@r%i+,macl\n", r8);
425     else if (lo8 == 0x18)
426     debug("shll8\tr%i\n", r8);
427     else if (lo8 == 0x19)
428     debug("shlr8\tr%i\n", r8);
429     else if (lo8 == 0x1a)
430     debug("lds\tr%i,macl\n", r8);
431     else if (lo8 == 0x1b)
432     debug("tas.b\t@r%i\n", r8);
433     else if (lo8 == 0x1e)
434     debug("ldc\tr%i,gbr\n", r8);
435     else if (lo8 == 0x20)
436     debug("shal\tr%i\n", r8);
437     else if (lo8 == 0x21)
438     debug("shar\tr%i\n", r8);
439     else if (lo8 == 0x22)
440     debug("sts.l\tpr,@-r%i\n", r8);
441     else if (lo8 == 0x24)
442     debug("rotcl\tr%i\n", r8);
443     else if (lo8 == 0x25)
444     debug("rotcr\tr%i\n", r8);
445     else if (lo8 == 0x26)
446     debug("lds.l\t@r%i+,pr\n", r8);
447     else if (lo8 == 0x28)
448     debug("shll16\tr%i\n", r8);
449     else if (lo8 == 0x29)
450     debug("shlr16\tr%i\n", r8);
451     else if (lo8 == 0x2a)
452     debug("lds\tr%i,pr\n", r8);
453     else if (lo8 == 0x2b)
454     debug("jmp\t@r%i\n", r8);
455     else if (lo8 == 0x56)
456     debug("lds.l\t@r%i+,fpul\n", r8);
457     else if (lo8 == 0x5a)
458     debug("lds\tr%i,fpul\n", r8);
459     else if (lo8 == 0x6a)
460     debug("lds\tr%i,fpscr\n", r8);
461     else
462     debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x\n", hi4, lo8);
463     break;
464     case 0x5:
465     debug("mov.l\t@(%i,r%i),r%i\n", lo4 * 4, r4, r8);
466     break;
467     case 0x6:
468     if (lo4 == 0x0)
469     debug("mov.b\t@r%i,r%i\n", r4, r8);
470     else if (lo4 == 0x1)
471     debug("mov.w\t@r%i,r%i\n", r4, r8);
472     else if (lo4 == 0x2)
473     debug("mov.l\t@r%i,r%i\n", r4, r8);
474     else if (lo4 == 0x3)
475     debug("mov\tr%i,r%i\n", r4, r8);
476     else if (lo4 == 0x4)
477     debug("mov.b\t@r%i+,r%i\n", r4, r8);
478     else if (lo4 == 0x6)
479     debug("mov.l\t@r%i+,r%i\n", r4, r8);
480     else if (lo4 == 0x7)
481     debug("not\tr%i,r%i\n", r4, r8);
482     else if (lo4 == 0x8)
483     debug("swap.b\tr%i,r%i\n", r4, r8);
484     else if (lo4 == 0x9)
485     debug("swap.w\tr%i,r%i\n", r4, r8);
486     else if (lo4 == 0xa)
487     debug("negc\tr%i,r%i\n", r4, r8);
488     else if (lo4 == 0xb)
489     debug("neg\tr%i,r%i\n", r4, r8);
490     else if (lo4 == 0xc)
491     debug("extu.b\tr%i,r%i\n", r4, r8);
492     else if (lo4 == 0xd)
493     debug("extu.w\tr%i,r%i\n", r4, r8);
494     else if (lo4 == 0xe)
495     debug("exts.b\tr%i,r%i\n", r4, r8);
496     else if (lo4 == 0xf)
497     debug("exts.w\tr%i,r%i\n", r4, r8);
498     else
499     debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x\n", hi4, lo8);
500     break;
501     case 0x7:
502     debug("add\t#%i,r%i\n", (int8_t)lo8, r8);
503     break;
504     case 0x8:
505     if (r8 == 0x8)
506     debug("cmp/eq\t#%i,r0\n", (int8_t)lo8);
507     else if (r8 == 0x9 || r8 == 0xb || r8 == 0xd || r8 == 0xf) {
508     addr = (int8_t)lo8;
509     addr = dumpaddr + 4 + (addr << 1);
510     debug("b%s%s\t0x%x\n",
511     (r8 == 0x9 || r8 == 0xd)? "t" : "f",
512     (r8 == 0x9 || r8 == 0xb)? "" : "/s", (int)addr);
513     } else
514     debug("UNIMPLEMENTED hi4=0x%x,0x%x\n", hi4, r8);
515     break;
516     case 0x9:
517     case 0xd:
518     addr = ((int8_t)lo8) * (hi4==9? 2 : 4);
519     addr += (dumpaddr & ~(hi4==9? 1 : 3)) + 4;
520     debug("mov.%s\t0x%x,r%i\n", hi4==9? "w":"l", (int)addr, r8);
521     break;
522     case 0xa:
523     case 0xb:
524     addr = (int32_t)(int16_t)((iword & 0xfff) << 4);
525     addr = ((int32_t)addr >> 3);
526     addr += dumpaddr + 4;
527     debug("%s\t0x%x\n", hi4==0xa? "bra":"bsr", (int)addr);
528     break;
529     case 0xc:
530     if (r8 == 0x3)
531     debug("trapa\t#%i\n", (uint8_t)lo8);
532     else if (r8 == 0x8)
533     debug("tst\t#%i,r0\n", (uint8_t)lo8);
534     else if (r8 == 0x9)
535     debug("and\t#%i,r0\n", (uint8_t)lo8);
536     else if (r8 == 0xa)
537     debug("xor\t#%i,r0\n", (uint8_t)lo8);
538     else if (r8 == 0xb)
539     debug("or\t#%i,r0\n", (uint8_t)lo8);
540     else if (r8 == 0xc)
541     debug("tst.b\t#%i,@(r0,gbr)\n", (uint8_t)lo8);
542     else if (r8 == 0xd)
543     debug("and.b\t#%i,@(r0,gbr)\n", (uint8_t)lo8);
544     else if (r8 == 0xe)
545     debug("xor.b\t#%i,@(r0,gbr)\n", (uint8_t)lo8);
546     else if (r8 == 0xf)
547     debug("or.b\t#%i,@(r0,gbr)\n", (uint8_t)lo8);
548     else
549     debug("UNIMPLEMENTED hi4=0x%x,0x%x\n", hi4, r8);
550     break;
551     case 0xe:
552     debug("mov\t#%i,r%i\n", (int8_t)lo8, r8);
553     break;
554     default:debug("UNIMPLEMENTED hi4=0x%x\n", hi4);
555     }
556    
557     return sizeof(iword);
558     }
559    
560    
561     /*
562     * sh_cpu_disassemble_instr():
563     *
564     * Convert an instruction word into human readable format, for instruction
565     * tracing.
566     *
567     * If running is 1, cpu->pc should be the address of the instruction.
568     *
569     * If running is 0, things that depend on the runtime environment (eg.
570     * register contents) will not be shown, and addr will be used instead of
571     * cpu->pc for relative addresses.
572     */
573     int sh_cpu_disassemble_instr(struct cpu *cpu, unsigned char *instr,
574 dpavlin 24 int running, uint64_t dumpaddr)
575 dpavlin 14 {
576 dpavlin 22 uint64_t offset;
577 dpavlin 14 uint32_t iword;
578 dpavlin 22 char *symbol;
579 dpavlin 14
580     if (running)
581     dumpaddr = cpu->pc;
582    
583     symbol = get_symbol_name(&cpu->machine->symbol_context,
584     dumpaddr, &offset);
585     if (symbol != NULL && offset==0)
586     debug("<%s>\n", symbol);
587    
588     if (cpu->machine->ncpus > 1 && running)
589     debug("cpu%i: ", cpu->cpu_id);
590    
591     if (cpu->cd.sh.bits == 32)
592     debug("%08x", (int)dumpaddr);
593     else
594     debug("%016llx", (long long)dumpaddr);
595    
596     if (cpu->cd.sh.compact)
597     return sh_cpu_disassemble_instr_compact(cpu, instr,
598 dpavlin 24 running, dumpaddr);
599 dpavlin 14
600     if (cpu->byte_order == EMUL_BIG_ENDIAN)
601     iword = (instr[0] << 24) + (instr[1] << 16) + (instr[2] << 8)
602     + instr[3];
603     else
604     iword = (instr[3] << 24) + (instr[2] << 16) + (instr[1] << 8)
605     + instr[0];
606    
607     debug(": %08x\t", iword);
608    
609     /*
610     * Decode the instruction:
611     */
612    
613     debug("TODO\n");
614    
615     return sizeof(iword);
616     }
617    
618    
619     #include "tmp_sh_tail.c"
620    

  ViewVC Help
Powered by ViewVC 1.1.26