/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 30 - (show annotations)
Mon Oct 8 16:20:40 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 19863 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1325 2006/08/15 15:38:37 debug Exp $
20060723	More Transputer instructions (pfix, nfix, opr, mint, ldl, ldlp,
		eqc, rev, ajw, stl, stlf, sthf, sub, ldnl, ldnlp, ldpi, move,
		wcnt, add, bcnt).
		Adding more SPARC instructions (andcc, addcc, bl, rdpr).
		Progress on the igsfb framebuffer used by NetBSD/netwinder.
		Enabling 8-bit fills in dev_fb.
		NetBSD/netwinder 3.0.1 can now run from a disk image :-)
20060724	Cleanup/performance fix for 64-bit virtual translation table
		updates (by removing the "timestamp" stuff). A full NetBSD/pmax
		3.0.1 install for R4400 has dropped from 667 seconds to 584 :)
		Fixing the igsfb "almost vga" color (it is 24-bit, not 18-bit).
		Adding some MIPS instruction combinations (3*lw, and 3*addu).
		The 8048 keyboard now turns off interrupt enable between the
		KBR_ACK and the KBR_RSTDONE, to work better with Linux 2.6.
		Not causing PPC DEC interrupts if PPC_NO_DEC is set for a
		specific CPU; NetBSD/bebox gets slightly further than before.
		Adding some more SPARC instructions: branches, udiv.
20060725	Refreshing dev_pckbc.c a little.
		Cleanups for the SH emulation mode, and adding the first
		"compact" (16-bit) instructions: various simple movs, nop,
		shll, stc, or, ldc.
20060726	Adding dummy "pcn" (AMD PCnet NIC) PCI glue.
20060727	Various cleanups; removing stuff from cpu.h, such as
		running_translated (not really meaningful anymore), and
		page flags (breaking into the debugger clears all translations
		anyway).
		Minor MIPS instruction combination updates.
20060807	Expanding the 3*sw and 3*lw MIPS instruction combinations to
		work with 2* and 4* too, resulting in a minor performance gain.
		Implementing a usleep hack for the RM52xx/MIPS32/MIPS64 "wait"
		instruction (when emulating 1 cpu).
20060808	Experimenting with some more MIPS instruction combinations.
		Implementing support for showing a (hardcoded 12x22) text
		cursor in igsfb.
20060809	Simplifying the NetBSD/evbmips (Malta) install instructions
		somewhat (by using a NetBSD/pmax ramdisk install kernel).
20060812	Experimenting more with the MIPS 'wait' instruction.
		PCI configuration register writes can now be handled, which
		allow PCI IDE controllers to work with NetBSD/Malta 3.0.1 and
		NetBSD/cobalt 3.0.1. (Previously only NetBSD 2.1 worked.)
20060813	Updating dev_gt.c based on numbers from Alec Voropay, to enable
		Linux 2.6 to use PCI on Malta.
		Continuing on Algor interrupt stuff.
20060814	Adding support for routing ISA interrupts to two different
		interrupts, making it possible to run NetBSD/algor :-)
20060814-15	Testing for the release.

==============  RELEASE 0.4.2  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26