/[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 26 - (hide annotations)
Mon Oct 8 16:20:10 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 19065 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1264 2006/06/25 11:08:04 debug Exp $
20060624	Replacing the error-prone machine type initialization stuff
		with something more reasonable.
		Finally removing the old "cpu_run" kludge; moving around stuff
		in machine.c and emul.c to better suit the dyntrans system.
		Various minor dyntrans cleanups (renaming translate_address to
		translate_v2p, and experimenting with template physpages).
20060625	Removing the speed hack which separated the vph entries into
		two halves (code vs data); things seem a lot more stable now.
		Minor performance hack: R2000/R3000 cache isolation now only
		clears address translations when going into isolation, not
		when going out of it.
		Fixing the MIPS interrupt problems by letting mtc0 immediately
		cause interrupts.

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

  ViewVC Help
Powered by ViewVC 1.1.26