/[gxemul]/trunk/src/cpus/cpu_sparc.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_sparc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 38 - (hide annotations)
Mon Oct 8 16:21:53 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 19374 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1515 2007/04/14 05:39:46 debug Exp $
20070324	Adding a "--debug" option to the configure script, to disable
		optimizations in unstable development builds.
		Moving out SCSI-specific stuff from diskimage.c into a new
		diskimage_scsicmd.c.
		Applying Hĺvard Eidnes' patch for SCSICDROM_READ_DISKINFO and
		SCSICDROM_READ_TRACKINFO. (Not really tested yet.)
		Implementing disk image "overlays" (to allow simple roll-back
		to previous disk state). Adding a 'V' disk flag for this, and
		updating the man page and misc.html.
20070325	Stability fix to cpu_dyntrans.c, when multiple physical pages
		share the same initial table entry. (The ppp == NULL check
		should be physpage_ofs == 0.) Bug found by analysing GXemul
		against a version patched for Godson.
		Fixing a second occurance of the same problem (also in
		cpu_dyntrans.c).
		Fixing a MAJOR physical page leak in cpu_dyntrans.c; pages
		weren't _added_ to the set of translated pages, they _replaced_
		all previous pages. It's amazing that this bug has been able
		to live for this long. (Triggered when emulating >128MB RAM.)
20070326	Removing the GDB debugging stub support; it was too hackish
		and ugly.
20070328	Moving around some native code generation skeleton code.
20070329	The -lm check in the configure script now also checks for sin()
		in addition to sqrt(). (Thanks to Nigel Horne for noticing that
		sqrt was not enough on Fedora Core 6.) (Not verified yet.)
20070330	Fixing an indexing bug in dev_sh4.c, found by using gcc version
		4.3.0 20070323.
20070331	Some more experimentation with native code generation.
20070404	Attempting to fix some more SH4 SCIF interrupt bugs; rewriting
		the SH interrupt assertion/deassertion code somewhat.
20070410	Splitting src/file.c into separate files in src/file/.
		Cleanup: Removing the dummy TS7200, Walnut, PB1000, and
		Meshcube emulation modes, and dev_epcom and dev_au1x00.
		Removing the experimental CHIP8/RCA180x code; it wasn't really
		working much lately, anyway. It was fun while it lasted.
		Also removing the experimental Transputer CPU support.
20070412	Moving the section about how the dynamic translation system
		works from intro.html to a separate translation.html file.
		Minor SH fixes; attempting to get OpenBSD/landisk to run
		without randomly bugging out, but no success yet.
20070413	SH SCI (serial bit interface) should now work together with a
		(new) RS5C313 clock device (for Landisk emulation).
20070414	Moving Redhat/MIPS down from supported to experimental, in
		guestoses.html.
		Preparing for a new release; doing some regression testing etc.

==============  RELEASE 0.4.5  ==============


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 38 * $Id: cpu_sparc.c,v 1.44 2007/03/26 02:18:44 debug Exp $
29 dpavlin 14 *
30     * SPARC CPU emulation.
31     */
32    
33     #include <stdio.h>
34     #include <stdlib.h>
35     #include <string.h>
36     #include <ctype.h>
37    
38     #include "cpu.h"
39     #include "machine.h"
40     #include "memory.h"
41     #include "misc.h"
42 dpavlin 32 #include "settings.h"
43 dpavlin 14 #include "symbol.h"
44    
45 dpavlin 22
46 dpavlin 14 #define DYNTRANS_DUALMODE_32
47 dpavlin 24 #define DYNTRANS_DELAYSLOT
48 dpavlin 14 #include "tmp_sparc_head.c"
49    
50    
51 dpavlin 22 static char *sparc_regnames[N_SPARC_REG] = SPARC_REG_NAMES;
52 dpavlin 24 static char *sparc_pregnames[N_SPARC_PREG] = SPARC_PREG_NAMES;
53 dpavlin 22 static char *sparc_regbranch_names[N_SPARC_REGBRANCH_TYPES] =
54     SPARC_REGBRANCH_NAMES;
55     static char *sparc_branch_names[N_SPARC_BRANCH_TYPES] = SPARC_BRANCH_NAMES;
56     static char *sparc_alu_names[N_ALU_INSTR_TYPES] = SPARC_ALU_NAMES;
57     static char *sparc_loadstore_names[N_LOADSTORE_TYPES] = SPARC_LOADSTORE_NAMES;
58    
59    
60 dpavlin 14 /*
61     * sparc_cpu_new():
62     *
63     * Create a new SPARC cpu object.
64     *
65     * Returns 1 on success, 0 if there was no matching SPARC processor with
66     * this cpu_type_name.
67     */
68     int sparc_cpu_new(struct cpu *cpu, struct memory *mem, struct machine *machine,
69     int cpu_id, char *cpu_type_name)
70     {
71 dpavlin 22 int any_cache = 0;
72     int i = 0;
73     struct sparc_cpu_type_def cpu_type_defs[] = SPARC_CPU_TYPE_DEFS;
74    
75     /* Scan the cpu_type_defs list for this cpu type: */
76     while (cpu_type_defs[i].name != NULL) {
77     if (strcasecmp(cpu_type_defs[i].name, cpu_type_name) == 0) {
78     break;
79     }
80     i++;
81     }
82     if (cpu_type_defs[i].name == NULL)
83 dpavlin 14 return 0;
84    
85     cpu->memory_rw = sparc_memory_rw;
86    
87 dpavlin 22 cpu->cd.sparc.cpu_type = cpu_type_defs[i];
88     cpu->name = cpu->cd.sparc.cpu_type.name;
89     cpu->byte_order = EMUL_BIG_ENDIAN;
90     cpu->is_32bit = (cpu->cd.sparc.cpu_type.bits == 32)? 1 : 0;
91 dpavlin 14
92 dpavlin 24 cpu->instruction_has_delayslot = sparc_cpu_instruction_has_delayslot;
93    
94 dpavlin 32 /* TODO: Separate this into 64-bit vs 32-bit? */
95     cpu->translate_v2p = sparc_translate_v2p;
96    
97 dpavlin 22 if (cpu->is_32bit) {
98 dpavlin 28 cpu->run_instr = sparc32_run_instr;
99 dpavlin 22 cpu->update_translation_table =
100     sparc32_update_translation_table;
101     cpu->invalidate_translation_caches =
102     sparc32_invalidate_translation_caches;
103     cpu->invalidate_code_translation =
104     sparc32_invalidate_code_translation;
105     } else {
106 dpavlin 28 cpu->run_instr = sparc_run_instr;
107 dpavlin 22 cpu->update_translation_table = sparc_update_translation_table;
108     cpu->invalidate_translation_caches =
109     sparc_invalidate_translation_caches;
110     cpu->invalidate_code_translation =
111     sparc_invalidate_code_translation;
112     }
113    
114 dpavlin 14 /* Only show name and caches etc for CPU nr 0 (in SMP machines): */
115     if (cpu_id == 0) {
116     debug("%s", cpu->name);
117 dpavlin 22
118     if (cpu->cd.sparc.cpu_type.icache_shift != 0)
119     any_cache = 1;
120     if (cpu->cd.sparc.cpu_type.dcache_shift != 0)
121     any_cache = 1;
122     if (cpu->cd.sparc.cpu_type.l2cache_shift != 0)
123     any_cache = 1;
124    
125     if (any_cache) {
126     debug(" (I+D = %i+%i KB", (int)
127     (1 << (cpu->cd.sparc.cpu_type.icache_shift-10)),
128     (int)(1<<(cpu->cd.sparc.cpu_type.dcache_shift-10)));
129     if (cpu->cd.sparc.cpu_type.l2cache_shift != 0) {
130     debug(", L2 = %i KB",
131     (int)(1 << (cpu->cd.sparc.cpu_type.
132     l2cache_shift-10)));
133     }
134     debug(")");
135     }
136 dpavlin 14 }
137    
138 dpavlin 24 /* After a reset, the Tick register is not readable by user code: */
139     cpu->cd.sparc.tick |= SPARC_TICK_NPT;
140    
141     /* Insert number of Windows and Trap levels into the version reg.: */
142 dpavlin 36 cpu->cd.sparc.ver |= N_REG_WINDOWS | (MAXTL << SPARC_VER_MAXTL_SHIFT);
143 dpavlin 24
144 dpavlin 28 /* Misc. initial settings suitable for userland emulation: */
145 dpavlin 36 cpu->cd.sparc.cansave = cpu->cd.sparc.cpu_type.nwindows - 2;
146     cpu->cd.sparc.canrestore = 0;
147     cpu->cd.sparc.cleanwin = 1;
148     cpu->cd.sparc.otherwin = 0;
149 dpavlin 28
150 dpavlin 36 if (cpu->cd.sparc.cansave + cpu->cd.sparc.canrestore
151     + cpu->cd.sparc.otherwin != cpu->cd.sparc.cpu_type.nwindows - 2) {
152     fatal("Fatal internal error: inconsistent windowing "
153     "parameters!\n");
154     exit(1);
155     }
156    
157     if (cpu->cd.sparc.cpu_type.nwindows > N_REG_WINDOWS) {
158 dpavlin 28 fatal("Fatal internal error: nwindows = %1 is more than %i\n",
159 dpavlin 36 cpu->cd.sparc.cpu_type.nwindows, N_REG_WINDOWS);
160 dpavlin 28 exit(1);
161     }
162    
163 dpavlin 32 CPU_SETTINGS_ADD_REGISTER64("pc", cpu->pc);
164     CPU_SETTINGS_ADD_REGISTER64("y", cpu->cd.sparc.y);
165     CPU_SETTINGS_ADD_REGISTER64("pstate", cpu->cd.sparc.pstate);
166     for (i=0; i<N_SPARC_REG; i++)
167     CPU_SETTINGS_ADD_REGISTER64(sparc_regnames[i],
168     cpu->cd.sparc.r[i]);
169     /* TODO: Handler for writes to the zero register! */
170    
171 dpavlin 14 return 1;
172     }
173    
174    
175     /*
176     * sparc_cpu_list_available_types():
177     *
178     * Print a list of available SPARC CPU types.
179     */
180     void sparc_cpu_list_available_types(void)
181     {
182 dpavlin 22 int i, j;
183     struct sparc_cpu_type_def tdefs[] = SPARC_CPU_TYPE_DEFS;
184    
185     i = 0;
186     while (tdefs[i].name != NULL) {
187     debug("%s", tdefs[i].name);
188 dpavlin 24 for (j=16 - strlen(tdefs[i].name); j>0; j--)
189 dpavlin 22 debug(" ");
190     i++;
191 dpavlin 24 if ((i % 4) == 0 || tdefs[i].name == NULL)
192 dpavlin 22 debug("\n");
193     }
194 dpavlin 14 }
195    
196    
197     /*
198     * sparc_cpu_dumpinfo():
199     */
200     void sparc_cpu_dumpinfo(struct cpu *cpu)
201     {
202 dpavlin 22 debug(", %i-bit\n", cpu->cd.sparc.cpu_type.bits);
203 dpavlin 14 }
204    
205    
206     /*
207     * sparc_cpu_register_dump():
208     *
209     * Dump cpu registers in a relatively readable format.
210     *
211     * gprs: set to non-zero to dump GPRs and some special-purpose registers.
212     * coprocs: set bit 0..3 to dump registers in coproc 0..3.
213     */
214     void sparc_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
215     {
216     char *symbol;
217 dpavlin 20 uint64_t offset;
218 dpavlin 22 int i, x = cpu->cpu_id;
219     int bits32 = cpu->is_32bit;
220 dpavlin 14
221     if (gprs) {
222     /* Special registers (pc, ...) first: */
223     symbol = get_symbol_name(&cpu->machine->symbol_context,
224     cpu->pc, &offset);
225    
226 dpavlin 22 debug("cpu%i: pc = 0x", x);
227 dpavlin 14 if (bits32)
228 dpavlin 24 debug("%08"PRIx32, (uint32_t) cpu->pc);
229 dpavlin 14 else
230 dpavlin 24 debug("%016"PRIx64, (uint64_t) cpu->pc);
231 dpavlin 14 debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
232    
233 dpavlin 24 debug("cpu%i: y = 0x%08"PRIx32" ",
234     x, (uint32_t)cpu->cd.sparc.y);
235     debug("icc = ");
236     debug(cpu->cd.sparc.ccr & SPARC_CCR_N? "N" : "n");
237     debug(cpu->cd.sparc.ccr & SPARC_CCR_Z? "Z" : "z");
238     debug(cpu->cd.sparc.ccr & SPARC_CCR_V? "V" : "v");
239     debug(cpu->cd.sparc.ccr & SPARC_CCR_C? "C" : "c");
240     if (!bits32) {
241     debug(" xcc = ");
242     debug((cpu->cd.sparc.ccr >> SPARC_CCR_XCC_SHIFT)
243     & SPARC_CCR_N? "N" : "n");
244     debug((cpu->cd.sparc.ccr >> SPARC_CCR_XCC_SHIFT)
245     & SPARC_CCR_Z? "Z" : "z");
246     debug((cpu->cd.sparc.ccr >> SPARC_CCR_XCC_SHIFT)
247     & SPARC_CCR_V? "V" : "v");
248     debug((cpu->cd.sparc.ccr >> SPARC_CCR_XCC_SHIFT)
249     & SPARC_CCR_C? "C" : "c");
250     }
251     debug("\n");
252    
253     if (bits32)
254     debug("cpu%i: psr = 0x%08"PRIx32"\n",
255     x, (uint32_t) cpu->cd.sparc.psr);
256     else
257     debug("cpu%i: pstate = 0x%016"PRIx64"\n",
258     x, (uint64_t) cpu->cd.sparc.pstate);
259    
260 dpavlin 22 if (bits32) {
261     for (i=0; i<N_SPARC_REG; i++) {
262     if ((i & 3) == 0)
263     debug("cpu%i: ", x);
264     /* Skip the zero register: */
265 dpavlin 24 if (i == SPARC_ZEROREG) {
266 dpavlin 22 debug(" ");
267     continue;
268     }
269     debug("%s=", sparc_regnames[i]);
270     debug("0x%08x", (int) cpu->cd.sparc.r[i]);
271     if ((i & 3) < 3)
272     debug(" ");
273     else
274     debug("\n");
275     }
276     } else {
277     for (i=0; i<N_SPARC_REG; i++) {
278     int r = ((i >> 1) & 15) | ((i&1) << 4);
279     if ((i & 1) == 0)
280     debug("cpu%i: ", x);
281 dpavlin 24
282 dpavlin 22 /* Skip the zero register: */
283 dpavlin 24 if (i == SPARC_ZEROREG) {
284 dpavlin 22 debug(" ");
285     continue;
286     }
287 dpavlin 24
288 dpavlin 22 debug("%s = ", sparc_regnames[r]);
289 dpavlin 24 debug("0x%016"PRIx64, (uint64_t)
290 dpavlin 22 cpu->cd.sparc.r[r]);
291 dpavlin 24
292 dpavlin 22 if ((i & 1) < 1)
293     debug(" ");
294     else
295     debug("\n");
296     }
297     }
298 dpavlin 14 }
299 dpavlin 36
300     if (coprocs & 1) {
301     int sum;
302    
303     debug("cpu%i: cwp = 0x%02x\n", x, cpu->cd.sparc.cwp);
304     debug("cpu%i: cansave = 0x%02x\n", x, cpu->cd.sparc.cansave);
305     debug("cpu%i: canrestore = 0x%02x\n", x,
306     cpu->cd.sparc.canrestore);
307     debug("cpu%i: otherwin = 0x%02x\n", x,
308     cpu->cd.sparc.otherwin);
309     debug("cpu%i: cleanwin = 0x%02x\n", x,
310     cpu->cd.sparc.cleanwin);
311    
312     sum = cpu->cd.sparc.cansave + cpu->cd.sparc.canrestore +
313     cpu->cd.sparc.otherwin;
314     debug("cpu%i: cansave + canrestore + otherwin = %i + %i + %i"
315     " = %i", x, cpu->cd.sparc.cansave, cpu->cd.sparc.canrestore,
316     cpu->cd.sparc.otherwin, sum);
317     if (sum == cpu->cd.sparc.cpu_type.nwindows - 2)
318     debug(" (consistent)\n");
319     else
320     debug(" (INCONSISTENT!)\n");
321    
322     debug("cpu%i: wstate: other = %i, normal = %i\n",
323     x, (cpu->cd.sparc.wstate & SPARC_WSTATE_OTHER_MASK)
324     >> SPARC_WSTATE_OTHER_SHIFT, cpu->cd.sparc.wstate &
325     SPARC_WSTATE_NORMAL_MASK);
326    
327     debug("cpu%i: asi = 0x%02x\n", x, cpu->cd.sparc.asi);
328     debug("cpu%i: tl = 0x%02x\n", x, cpu->cd.sparc.tl);
329     debug("cpu%i: pil = 0x%02x\n", x, cpu->cd.sparc.pil);
330    
331     for (i=0; i<MAXTL; i++) {
332     debug("cpu%i: tpc[%i] = 0x", x, i);
333     if (bits32)
334     debug("%08"PRIx32"\n",
335     (uint32_t) cpu->cd.sparc.tpc[i]);
336     else
337     debug("%016"PRIx64"\n",
338     (uint64_t) cpu->cd.sparc.tpc[i]);
339    
340     debug("cpu%i: tnpc[%i] = 0x", x, i);
341     if (bits32)
342     debug("%08"PRIx32"\n",
343     (uint32_t) cpu->cd.sparc.tnpc[i]);
344     else
345     debug("%016"PRIx64"\n",
346     (uint64_t) cpu->cd.sparc.tnpc[i]);
347    
348     debug("cpu%i: tstate[%i] = 0x", x, i);
349     if (bits32)
350     debug("%08"PRIx32"\n",
351     (uint32_t) cpu->cd.sparc.tstate[i]);
352     else
353     debug("%016"PRIx64"\n",
354     (uint64_t) cpu->cd.sparc.tstate[i]);
355    
356     debug("cpu%i: ttype[%i] = 0x"PRIx32"\n",
357     x, i, cpu->cd.sparc.ttype[i]);
358     }
359    
360     debug("cpu%i: tba = 0x", x);
361     if (bits32)
362     debug("%08"PRIx32"\n", (uint32_t) cpu->cd.sparc.tba);
363     else
364     debug("%016"PRIx64"\n", (uint64_t) cpu->cd.sparc.tba);
365     }
366 dpavlin 14 }
367    
368    
369     /*
370 dpavlin 24 * sparc_cpu_tlbdump():
371     *
372     * Called from the debugger to dump the TLB in a readable format.
373     * x is the cpu number to dump, or -1 to dump all CPUs.
374     *
375     * If rawflag is nonzero, then the TLB contents isn't formated nicely,
376     * just dumped.
377     */
378     void sparc_cpu_tlbdump(struct machine *m, int x, int rawflag)
379     {
380     }
381    
382    
383     /*
384     * sparc_cpu_instruction_has_delayslot():
385     *
386     * Return 1 if an opcode is a branch, 0 otherwise.
387     */
388     int sparc_cpu_instruction_has_delayslot(struct cpu *cpu, unsigned char *ib)
389     {
390     uint32_t iword = *((uint32_t *)&ib[0]);
391     int hi2, op2;
392    
393     iword = BE32_TO_HOST(iword);
394    
395     hi2 = iword >> 30;
396     op2 = (hi2 == 0)? ((iword >> 22) & 7) : ((iword >> 19) & 0x3f);
397    
398     switch (hi2) {
399     case 0: /* conditional branch */
400     switch (op2) {
401     case 1:
402     case 2:
403     case 3: return 1;
404     }
405     break;
406     case 1: /* call */
407     return 1;
408     case 2: /* misc alu instructions */
409     switch (op2) {
410     case 56:/* jump and link */
411     return 1;
412 dpavlin 32 case 57:/* return */
413     return 1;
414 dpavlin 24 }
415     break;
416     }
417    
418     return 0;
419     }
420    
421    
422     /*
423 dpavlin 14 * sparc_cpu_disassemble_instr():
424     *
425     * Convert an instruction word into human readable format, for instruction
426     * tracing.
427     *
428     * If running is 1, cpu->pc should be the address of the instruction.
429     *
430     * If running is 0, things that depend on the runtime environment (eg.
431     * register contents) will not be shown, and addr will be used instead of
432     * cpu->pc for relative addresses.
433     */
434     int sparc_cpu_disassemble_instr(struct cpu *cpu, unsigned char *instr,
435 dpavlin 24 int running, uint64_t dumpaddr)
436 dpavlin 14 {
437 dpavlin 22 uint64_t offset, tmp;
438 dpavlin 14 uint32_t iword;
439 dpavlin 22 int hi2, op2, rd, rs1, rs2, siconst, btype, tmps, no_rd = 0;
440     int asi, no_rs1 = 0, no_rs2 = 0, jmpl = 0, shift_x = 0, cc, p;
441 dpavlin 24 char *symbol, *mnem, *rd_name, *rs_name;
442 dpavlin 14
443     if (running)
444     dumpaddr = cpu->pc;
445    
446     symbol = get_symbol_name(&cpu->machine->symbol_context,
447     dumpaddr, &offset);
448     if (symbol != NULL && offset==0)
449     debug("<%s>\n", symbol);
450    
451     if (cpu->machine->ncpus > 1 && running)
452     debug("cpu%i: ", cpu->cpu_id);
453    
454 dpavlin 22 if (cpu->is_32bit)
455 dpavlin 24 debug("%08"PRIx32, (uint32_t) dumpaddr);
456 dpavlin 14 else
457 dpavlin 24 debug("%016"PRIx64, (uint64_t) dumpaddr);
458 dpavlin 14
459 dpavlin 22 iword = *(uint32_t *)&instr[0];
460     iword = BE32_TO_HOST(iword);
461 dpavlin 14
462 dpavlin 24 debug(": %08x", iword);
463 dpavlin 14
464 dpavlin 24 if (running && cpu->delay_slot)
465     debug(" (d)");
466    
467     debug("\t");
468    
469    
470 dpavlin 14 /*
471     * Decode the instruction:
472 dpavlin 22 *
473     * http://www.cs.unm.edu/~maccabe/classes/341/labman/node9.html is a
474     * good quick description of SPARC instruction encoding.
475 dpavlin 14 */
476    
477 dpavlin 22 hi2 = iword >> 30;
478     rd = (iword >> 25) & 31;
479     btype = rd & (N_SPARC_BRANCH_TYPES - 1);
480     rs1 = (iword >> 14) & 31;
481     asi = (iword >> 5) & 0xff;
482     rs2 = iword & 31;
483     siconst = (int16_t)((iword & 0x1fff) << 3) >> 3;
484     op2 = (hi2 == 0)? ((iword >> 22) & 7) : ((iword >> 19) & 0x3f);
485     cc = (iword >> 20) & 3;
486     p = (iword >> 19) & 1;
487 dpavlin 14
488 dpavlin 22 switch (hi2) {
489    
490     case 0: switch (op2) {
491    
492     case 0: debug("illtrap\t0x%x", iword & 0x3fffff);
493     break;
494    
495     case 1:
496     case 2:
497     case 3: if (op2 == 3)
498     debug("%s", sparc_regbranch_names[btype & 7]);
499     else
500     debug("%s", sparc_branch_names[btype]);
501     if (rd & 16)
502     debug(",a");
503     tmps = iword;
504     switch (op2) {
505     case 1: tmps <<= 13;
506     tmps >>= 11;
507     if (!p)
508     debug(",pn");
509     debug("\t%%%s,", cc==0 ? "icc" :
510     (cc==2 ? "xcc" : "UNKNOWN"));
511     break;
512     case 2: tmps <<= 10;
513     tmps >>= 8;
514     debug("\t");
515     break;
516     case 3: if (btype & 8)
517     debug("(INVALID)");
518     if (!p)
519     debug(",pn");
520     debug("\t%%%s,", sparc_regnames[rs1]);
521     tmps = ((iword & 0x300000) >> 6)
522     | (iword & 0x3fff);
523     tmps <<= 16;
524     tmps >>= 14;
525     break;
526     }
527     tmp = (int64_t)(int32_t)tmps;
528     tmp += dumpaddr;
529 dpavlin 24 debug("0x%"PRIx64, (uint64_t) tmp);
530 dpavlin 22 symbol = get_symbol_name(&cpu->machine->
531     symbol_context, tmp, &offset);
532     if (symbol != NULL)
533     debug(" \t<%s>", symbol);
534     break;
535    
536     case 4: if (rd == 0) {
537     debug("nop");
538     break;
539     }
540     debug("sethi\t%%hi(0x%x),", (iword & 0x3fffff) << 10);
541     debug("%%%s", sparc_regnames[rd]);
542     break;
543    
544     default:debug("UNIMPLEMENTED hi2=%i, op2=0x%x", hi2, op2);
545     }
546     break;
547    
548     case 1: tmp = (int32_t)iword << 2;
549     tmp += dumpaddr;
550 dpavlin 24 debug("call\t0x%"PRIx64, (uint64_t) tmp);
551 dpavlin 22 symbol = get_symbol_name(&cpu->machine->symbol_context,
552     tmp, &offset);
553     if (symbol != NULL)
554     debug(" \t<%s>", symbol);
555     break;
556    
557     case 2: mnem = sparc_alu_names[op2];
558 dpavlin 24 rs_name = sparc_regnames[rs1];
559     rd_name = sparc_regnames[rd];
560 dpavlin 22 switch (op2) {
561     case 0: /* add */
562     if (rd == rs1 && (iword & 0x3fff) == 0x2001) {
563     mnem = "inc";
564     no_rs1 = no_rs2 = 1;
565     }
566     break;
567     case 2: /* or */
568     if (rs1 == 0) {
569     mnem = "mov";
570     no_rs1 = 1;
571     }
572     break;
573     case 4: /* sub */
574     if (rd == rs1 && (iword & 0x3fff) == 0x2001) {
575     mnem = "dec";
576     no_rs1 = no_rs2 = 1;
577     }
578     break;
579     case 20:/* subcc */
580     if (rd == 0) {
581     mnem = "cmp";
582     no_rd = 1;
583     }
584     break;
585     case 37:/* sll */
586     case 38:/* srl */
587     case 39:/* sra */
588     if (siconst & 0x1000) {
589     siconst &= 0x3f;
590     shift_x = 1;
591     } else
592     siconst &= 0x1f;
593     break;
594 dpavlin 24 case 40:/* rd on pre-sparcv9, membar etc on sparcv9 */
595     no_rs2 = 1;
596     rs_name = "UNIMPLEMENTED";
597     switch (rs1) {
598     case 0: rs_name = "y"; break;
599     case 2: rs_name = "ccr"; break;
600     case 3: rs_name = "asi"; break;
601     case 4: rs_name = "tick"; break;
602     case 5: rs_name = "pc"; break;
603     case 6: rs_name = "fprs"; break;
604     case 15:/* membar etc. */
605     if ((iword >> 13) & 1) {
606     no_rd = 1;
607     mnem = "membar";
608     rs_name = "#TODO";
609     }
610     break;
611     case 23:rs_name = "tick_cmpr"; break; /* v9 ? */
612     }
613     break;
614     case 41:rs_name = "psr";
615     no_rs2 = 1;
616     break;
617 dpavlin 30 case 42:/* TODO: something with wim only, on sparc v8? */
618     rs_name = sparc_pregnames[rs1];
619 dpavlin 24 no_rs2 = 1;
620     break;
621 dpavlin 22 case 43:/* ? */
622 dpavlin 24 /* TODO: pre-sparcv9: rd, rs_name = "tbr"; */
623 dpavlin 22 if (iword == 0x81580000) {
624     mnem = "flushw";
625     no_rs1 = no_rs2 = no_rd = 1;
626     }
627     break;
628 dpavlin 24 case 48:/* wr* (SPARCv8) */
629     mnem = "wr";
630     if (rs1 == SPARC_ZEROREG)
631     no_rs1 = 1;
632     switch (rd) {
633     case 0: rd_name = "y"; break;
634     case 2: rd_name = "ccr"; break;
635     case 3: rd_name = "asi"; break;
636     case 6: rd_name = "fprs"; break;
637     case 23:rd_name = "tick_cmpr"; break; /* v9 ? */
638     default:rd_name = "UNIMPLEMENTED";
639     }
640     break;
641 dpavlin 22 case 49:/* ? */
642     if (iword == 0x83880000) {
643     mnem = "restored";
644     no_rs1 = no_rs2 = no_rd = 1;
645     }
646     break;
647 dpavlin 24 case 50:/* wrpr */
648     rd_name = sparc_pregnames[rd];
649     if (rs1 == SPARC_ZEROREG)
650     no_rs1 = 1;
651     break;
652 dpavlin 22 case 56:/* jmpl */
653     jmpl = 1;
654     if (iword == 0x81c7e008) {
655     mnem = "ret";
656     no_rs1 = no_rs2 = no_rd = 1;
657     }
658     if (iword == 0x81c3e008) {
659     mnem = "retl";
660     no_rs1 = no_rs2 = no_rd = 1;
661     }
662     break;
663     case 61:/* restore */
664     if (iword == 0x81e80000)
665     no_rs1 = no_rs2 = no_rd = 1;
666     break;
667     case 62:if (iword == 0x83f00000) {
668     mnem = "retry";
669     no_rs1 = no_rs2 = no_rd = 1;
670     }
671     break;
672     }
673     debug("%s", mnem);
674     if (shift_x)
675     debug("x");
676     debug("\t");
677     if (!no_rs1)
678 dpavlin 24 debug("%%%s", rs_name);
679 dpavlin 22 if (!no_rs1 && !no_rs2) {
680     if (jmpl)
681     debug("+");
682     else
683     debug(",");
684     }
685     if (!no_rs2) {
686     if ((iword >> 13) & 1) {
687     if (siconst >= -9 && siconst <= 9)
688     debug("%i", siconst);
689 dpavlin 28 else if (siconst < 0 && (op2 == 0 ||
690     op2 == 4 || op2 == 20 || op2 == 60))
691     debug("-0x%x", -siconst);
692 dpavlin 22 else
693     debug("0x%x", siconst);
694     } else {
695     debug("%%%s", sparc_regnames[rs2]);
696     }
697     }
698     if ((!no_rs1 || !no_rs2) && !no_rd)
699     debug(",");
700     if (!no_rd)
701 dpavlin 24 debug("%%%s", rd_name);
702 dpavlin 22 break;
703    
704 dpavlin 28 case 3: mnem = sparc_loadstore_names[op2];
705     switch (op2) {
706     case 0: /* 'lduw' was called only 'ld' in pre-v9 */
707     if (cpu->cd.sparc.cpu_type.v < 9)
708     mnem = "ld";
709     break;
710     }
711     debug("%s\t", mnem);
712 dpavlin 22 if (op2 & 4)
713     debug("%%%s,", sparc_regnames[rd]);
714     debug("[%%%s", sparc_regnames[rs1]);
715     if ((iword >> 13) & 1) {
716     if (siconst > 0)
717     debug("+");
718     if (siconst != 0)
719     debug("%i", siconst);
720     } else {
721     if (rs2 != 0)
722     debug("+%%%s", sparc_regnames[rs2]);
723     }
724     debug("]");
725 dpavlin 28 if ((op2 & 0x30) == 0x10)
726 dpavlin 22 debug("(%i)", asi);
727     if (!(op2 & 4))
728     debug(",%%%s", sparc_regnames[rd]);
729     break;
730 dpavlin 14 }
731    
732     debug("\n");
733     return sizeof(iword);
734     }
735    
736    
737 dpavlin 24 /*
738     * sparc_update_pstate():
739     *
740     * Update the pstate register (64-bit sparcs).
741     */
742     static void sparc_update_pstate(struct cpu *cpu, uint64_t new_pstate)
743     {
744     /* uint64_t old_pstate = cpu->cd.sparc.pstate; */
745    
746     /* TODO: Check individual bits. */
747    
748     cpu->cd.sparc.pstate = new_pstate;
749     }
750    
751    
752 dpavlin 14 #include "tmp_sparc_tail.c"
753    

  ViewVC Help
Powered by ViewVC 1.1.26