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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 41 - (show annotations)
Mon Oct 8 16:22:20 2007 UTC (16 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 19374 byte(s)
0.4.5.1
1 /*
2 * Copyright (C) 2005-2007 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: cpu_sparc.c,v 1.44 2007/03/26 02:18:44 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 "settings.h"
43 #include "symbol.h"
44
45
46 #define DYNTRANS_DUALMODE_32
47 #define DYNTRANS_DELAYSLOT
48 #include "tmp_sparc_head.c"
49
50
51 static char *sparc_regnames[N_SPARC_REG] = SPARC_REG_NAMES;
52 static char *sparc_pregnames[N_SPARC_PREG] = SPARC_PREG_NAMES;
53 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 /*
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 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 return 0;
84
85 cpu->memory_rw = sparc_memory_rw;
86
87 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
92 cpu->instruction_has_delayslot = sparc_cpu_instruction_has_delayslot;
93
94 /* TODO: Separate this into 64-bit vs 32-bit? */
95 cpu->translate_v2p = sparc_translate_v2p;
96
97 if (cpu->is_32bit) {
98 cpu->run_instr = sparc32_run_instr;
99 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 cpu->run_instr = sparc_run_instr;
107 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 /* Only show name and caches etc for CPU nr 0 (in SMP machines): */
115 if (cpu_id == 0) {
116 debug("%s", cpu->name);
117
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 }
137
138 /* 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 cpu->cd.sparc.ver |= N_REG_WINDOWS | (MAXTL << SPARC_VER_MAXTL_SHIFT);
143
144 /* Misc. initial settings suitable for userland emulation: */
145 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
150 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 fatal("Fatal internal error: nwindows = %1 is more than %i\n",
159 cpu->cd.sparc.cpu_type.nwindows, N_REG_WINDOWS);
160 exit(1);
161 }
162
163 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 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 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 for (j=16 - strlen(tdefs[i].name); j>0; j--)
189 debug(" ");
190 i++;
191 if ((i % 4) == 0 || tdefs[i].name == NULL)
192 debug("\n");
193 }
194 }
195
196
197 /*
198 * sparc_cpu_dumpinfo():
199 */
200 void sparc_cpu_dumpinfo(struct cpu *cpu)
201 {
202 debug(", %i-bit\n", cpu->cd.sparc.cpu_type.bits);
203 }
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 uint64_t offset;
218 int i, x = cpu->cpu_id;
219 int bits32 = cpu->is_32bit;
220
221 if (gprs) {
222 /* Special registers (pc, ...) first: */
223 symbol = get_symbol_name(&cpu->machine->symbol_context,
224 cpu->pc, &offset);
225
226 debug("cpu%i: pc = 0x", x);
227 if (bits32)
228 debug("%08"PRIx32, (uint32_t) cpu->pc);
229 else
230 debug("%016"PRIx64, (uint64_t) cpu->pc);
231 debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
232
233 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 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 if (i == SPARC_ZEROREG) {
266 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
282 /* Skip the zero register: */
283 if (i == SPARC_ZEROREG) {
284 debug(" ");
285 continue;
286 }
287
288 debug("%s = ", sparc_regnames[r]);
289 debug("0x%016"PRIx64, (uint64_t)
290 cpu->cd.sparc.r[r]);
291
292 if ((i & 1) < 1)
293 debug(" ");
294 else
295 debug("\n");
296 }
297 }
298 }
299
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 }
367
368
369 /*
370 * 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 case 57:/* return */
413 return 1;
414 }
415 break;
416 }
417
418 return 0;
419 }
420
421
422 /*
423 * 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 int running, uint64_t dumpaddr)
436 {
437 uint64_t offset, tmp;
438 uint32_t iword;
439 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 char *symbol, *mnem, *rd_name, *rs_name;
442
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 if (cpu->is_32bit)
455 debug("%08"PRIx32, (uint32_t) dumpaddr);
456 else
457 debug("%016"PRIx64, (uint64_t) dumpaddr);
458
459 iword = *(uint32_t *)&instr[0];
460 iword = BE32_TO_HOST(iword);
461
462 debug(": %08x", iword);
463
464 if (running && cpu->delay_slot)
465 debug(" (d)");
466
467 debug("\t");
468
469
470 /*
471 * Decode the instruction:
472 *
473 * http://www.cs.unm.edu/~maccabe/classes/341/labman/node9.html is a
474 * good quick description of SPARC instruction encoding.
475 */
476
477 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
488 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 debug("0x%"PRIx64, (uint64_t) tmp);
530 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 debug("call\t0x%"PRIx64, (uint64_t) tmp);
551 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 rs_name = sparc_regnames[rs1];
559 rd_name = sparc_regnames[rd];
560 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 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 case 42:/* TODO: something with wim only, on sparc v8? */
618 rs_name = sparc_pregnames[rs1];
619 no_rs2 = 1;
620 break;
621 case 43:/* ? */
622 /* TODO: pre-sparcv9: rd, rs_name = "tbr"; */
623 if (iword == 0x81580000) {
624 mnem = "flushw";
625 no_rs1 = no_rs2 = no_rd = 1;
626 }
627 break;
628 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 case 49:/* ? */
642 if (iword == 0x83880000) {
643 mnem = "restored";
644 no_rs1 = no_rs2 = no_rd = 1;
645 }
646 break;
647 case 50:/* wrpr */
648 rd_name = sparc_pregnames[rd];
649 if (rs1 == SPARC_ZEROREG)
650 no_rs1 = 1;
651 break;
652 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 debug("%%%s", rs_name);
679 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 else if (siconst < 0 && (op2 == 0 ||
690 op2 == 4 || op2 == 20 || op2 == 60))
691 debug("-0x%x", -siconst);
692 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 debug("%%%s", rd_name);
702 break;
703
704 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 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 if ((op2 & 0x30) == 0x10)
726 debug("(%i)", asi);
727 if (!(op2 & 4))
728 debug(",%%%s", sparc_regnames[rd]);
729 break;
730 }
731
732 debug("\n");
733 return sizeof(iword);
734 }
735
736
737 /*
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 #include "tmp_sparc_tail.c"
753

  ViewVC Help
Powered by ViewVC 1.1.26