/[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 38 - (show annotations)
Mon Oct 8 16:21:53 2007 UTC (16 years, 5 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 /*
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