|
|
1.1 root 1: #include <u.h>
2: #include <libc.h>
3: #include <bio.h>
4: #include <mach.h>
5:
6: /*
7: * Sparc-specific debugger interface
8: */
9:
10: static char *sparcexcep(Map*, Rgetter);
11: static int sparcfoll(Map*, ulong, Rgetter, ulong*);
12: static int sparcinst(Map*, ulong, char, char*, int);
13: static int sparcdas(Map*, ulong, char*, int);
14: static int sparcinstlen(Map*, ulong);
15:
16: Machdata sparcmach =
17: {
18: {0x91, 0xd0, 0x20, 0x01}, /* breakpoint: TA $1 */
19: 4, /* break point size */
20:
21: beswab, /* convert short to local byte order */
22: beswal, /* convert long to local byte order */
23: risctrace, /* C traceback */
24: riscframe, /* frame finder */
25: 0, /* ublock fixup */
26: sparcexcep, /* print exception */
27: 0, /* breakpoint fixup */
28: beieeesftos, /* single precision float printer */
29: beieeedftos, /* double precision float printer */
30: sparcfoll, /* following addresses */
31: sparcinst, /* print instruction */
32: sparcdas, /* dissembler */
33: sparcinstlen, /* instruction size */
34: };
35:
36: static char *trapname[] =
37: {
38: "reset",
39: "instruction access exception",
40: "illegal instruction",
41: "privileged instruction",
42: "fp disabled",
43: "window overflow",
44: "window underflow",
45: "unaligned address",
46: "fp exception",
47: "data access exception",
48: "tag overflow",
49: };
50:
51: static char*
52: excname(ulong tbr)
53: {
54: static char buf[32];
55:
56: if(tbr < sizeof trapname/sizeof(char*))
57: return trapname[tbr];
58: if(tbr >= 130)
59: sprint(buf, "trap instruction %d", tbr-128);
60: else if(17<=tbr && tbr<=31)
61: sprint(buf, "interrupt level %d", tbr-16);
62: else switch(tbr){
63: case 36:
64: return "cp disabled";
65: case 40:
66: return "cp exception";
67: case 128:
68: return "syscall";
69: case 129:
70: return "breakpoint";
71: default:
72: sprint(buf, "unknown trap %d", tbr);
73: }
74: Return:
75: return buf;
76: }
77:
78: static char*
79: sparcexcep(Map *map, Rgetter rget)
80: {
81: long tbr;
82:
83: tbr = (*rget)(map, "TBR");
84: tbr = (tbr&0xFFF)>>4;
85: return excname(tbr);
86: }
87:
88: /* Sparc disassembler and related functions */
89:
90: struct opcode {
91: char *mnemonic;
92: void (*f)(struct instr*, char*);
93: int flag;
94: };
95:
96: static char FRAMENAME[] = ".frame";
97:
98: typedef struct instr Instr;
99:
100: struct instr {
101: uchar op; /* bits 31-30 */
102: uchar rd; /* bits 29-25 */
103: uchar op2; /* bits 24-22 */
104: uchar a; /* bit 29 */
105: uchar cond; /* bits 28-25 */
106: uchar op3; /* bits 24-19 */
107: uchar rs1; /* bits 18-14 */
108: uchar i; /* bit 13 */
109: uchar asi; /* bits 12-05 */
110: uchar rs2; /* bits 04-00 */
111: short simm13; /* bits 12-00, signed */
112: ushort opf; /* bits 13-05 */
113: ulong immdisp22; /* bits 21-00 */
114: ulong simmdisp22; /* bits 21-00, signed */
115: ulong disp30; /* bits 30-00 */
116: ulong imm32; /* SETHI+ADD constant */
117: int target; /* SETHI+ADD dest reg */
118: long w0;
119: long w1;
120: ulong addr; /* pc of instruction */
121: char *curr; /* current fill level in output buffer */
122: char *end; /* end of buffer */
123: int size; /* number of longs in instr */
124: char *err; /* errmsg */
125: };
126:
127: static Map *mymap; /* disassembler context */
128: static int dascase;
129:
130: static int mkinstr(ulong, Instr*);
131: static void bra1(Instr*, char*, char*[]);
132: static void bra(Instr*, char*);
133: static void fbra(Instr*, char*);
134: static void cbra(Instr*, char*);
135: static void unimp(Instr*, char*);
136: static void fpop(Instr*, char*);
137: static void shift(Instr*, char*);
138: static void sethi(Instr*, char*);
139: static void load(Instr*, char*);
140: static void loada(Instr*, char*);
141: static void store(Instr*, char*);
142: static void storea(Instr*, char*);
143: static void add(Instr*, char*);
144: static void cmp(Instr*, char*);
145: static void wr(Instr*, char*);
146: static void jmpl(Instr*, char*);
147: static void rd(Instr*, char*);
148: static void loadf(Instr*, char*);
149: static void storef(Instr*, char*);
150: static void loadc(Instr*, char*);
151: static void loadcsr(Instr*, char*);
152: static void trap(Instr*, char*);
153:
154: static struct opcode sparcop0[8] = {
155: [0] "UNIMP", unimp, 0, /* page 137 */
156: [2] "B", bra, 0, /* page 119 */
157: [4] "SETHI", sethi, 0, /* page 104 */
158: [6] "FB", fbra, 0, /* page 121 */
159: [7] "CB", cbra, 0, /* page 123 */
160: };
161:
162: static struct opcode sparcop2[64] = {
163: [0x00] "ADD", add, 0, /* page 108 */
164: [0x10] "ADDCC", add, 0,
165: [0x08] "ADDX", add, 0,
166: [0x18] "ADDXCC", add, 0,
167:
168: [0x20] "TADD", add, 0, /* page 109 */
169: [0x22] "TADDCCTV", add, 0,
170:
171: [0x04] "SUB", add, 0, /* page 110 */
172: [0x14] "SUBCC", cmp, 0,
173: [0x0C] "SUBX", add, 0,
174: [0x1C] "SUBXCC", add, 0,
175:
176: [0x21] "TSUB", add, 0, /* page 111 */
177: [0x23] "TSUBCCTV", add, 0,
178:
179: [0x24] "MULSCC", add, 0, /* page 112 */
180:
181: [0x0A] "UMUL", add, 0, /* page 113 */
182: [0x0B] "SMUL", add, 0,
183: [0x1A] "UMULCC", add, 0,
184: [0x1B] "SMULCC", add, 0,
185:
186: [0x0E] "UDIV", add, 0, /* page 115 */
187: [0x0F] "SDIV", add, 0,
188: [0x1E] "UDIVCC", add, 0,
189: [0x1F] "SDIVCC", add, 0,
190:
191: [0x01] "AND", add, 0, /* page 106 */
192: [0x11] "ANDCC", add, 0,
193: [0x05] "ANDN", add, 0,
194: [0x15] "ANDNCC", add, 0,
195: [0x02] "OR", add, 0,
196: [0x12] "ORCC", add, 0,
197: [0x06] "ORN", add, 0,
198: [0x16] "ORNCC", add, 0,
199: [0x03] "XOR", add, 0,
200: [0x13] "XORCC", add, 0,
201: [0x07] "XORN", add, 0,
202: [0x17] "XORNCC", add, 0,
203:
204: [0x25] "SLL", shift, 0, /* page 107 */
205: [0x26] "SRL", shift, 0,
206: [0x27] "SRA", shift, 0,
207:
208: [0x3C] "SAVE", add, 0, /* page 117 */
209: [0x3D] "RESTORE", add, 0,
210:
211: [0x38] "JMPL", jmpl, 0, /* page 126 */
212:
213: [0x39] "RETT", add, 0, /* page 127 */
214:
215: [0x3A] "T", trap, 0, /* page 129 */
216:
217: [0x28] "rdy", rd, 0, /* page 131 */
218: [0x29] "rdpsr", rd, 0,
219: [0x2A] "rdwim", rd, 0,
220: [0x2B] "rdtbr", rd, 0,
221:
222: [0x30] "wry", wr, 0, /* page 133 */
223: [0x31] "wrpsr", wr, 0,
224: [0x32] "wrwim", wr, 0,
225: [0x33] "wrtbr", wr, 0,
226:
227: [0x3B] "flush", add, 0, /* page 138 */
228:
229: [0x34] "FPOP", fpop, 0, /* page 140 */
230: [0x35] "FPOP", fpop, 0,
231: };
232:
233: static struct opcode sparcop3[64]={
234: [0x09] "ldsb", load, 0, /* page 90 */
235: [0x19] "ldsba", loada, 0,
236: [0x0A] "ldsh", load, 0,
237: [0x1A] "ldsha", loada, 0,
238: [0x01] "ldub", load, 0,
239: [0x11] "lduba", loada, 0,
240: [0x02] "lduh", load, 0,
241: [0x12] "lduha", loada, 0,
242: [0x00] "ld", load, 0,
243: [0x10] "lda", loada, 0,
244: [0x03] "ldd", load, 0,
245: [0x13] "ldda", loada, 0,
246:
247: [0x20] "ldf", loadf, 0, /* page 92 */
248: [0x23] "lddf", loadf, 0,
249: [0x21] "ldfsr", loadf,0,
250:
251: [0x30] "ldc", loadc, 0, /* page 94 */
252: [0x33] "lddc", loadc, 0,
253: [0x31] "ldcsr", loadcsr,0,
254:
255: [0x05] "stb", store, 0, /* page 95 */
256: [0x15] "stba", storea, 0,
257: [0x06] "sth", store, 0,
258: [0x16] "stha", storea, 0,
259: [0x04] "st", store, 0,
260: [0x14] "sta", storea, 0,
261: [0x07] "std", store, 0,
262: [0x17] "stda", storea, 0,
263:
264: [0x24] "stf", storef, 0, /* page 97 */
265: [0x27] "stdf", storef, 0,
266: [0x25] "stfsr", storef,0,
267: [0x26] "stdfq", storef,0,
268:
269: [0x34] "stc", loadc, 0, /* page 99 */
270: [0x37] "stdc", loadc, 0,
271: [0x35] "stcsr", loadcsr,0,
272: [0x36] "stdcq", loadcsr,0,
273:
274: [0x0D] "ldstub", store, 0, /* page 101 */
275: [0x1D] "ldstuba", storea, 0,
276:
277: [0x0F] "swap", load, 0, /* page 102 */
278: [0x1F] "swapa", loada, 0,
279: };
280:
281: static void
282: bprint(Instr *i, char *fmt, ...)
283: {
284: i->curr = doprint(i->curr, i->end, fmt, (&fmt+1));
285: }
286:
287: static int
288: decode(ulong pc, Instr *i)
289: {
290: long w;
291:
292: if (get4(mymap, pc, &w) < 0) {
293: werrstr("can't read instruction: %r");
294: return -1;
295: }
296: i->op = (w >> 30) & 0x03;
297: i->rd = (w >> 25) & 0x1F;
298: i->op2 = (w >> 22) & 0x07;
299: i->a = (w >> 29) & 0x01;
300: i->cond = (w >> 25) & 0x0F;
301: i->op3 = (w >> 19) & 0x3F;
302: i->rs1 = (w >> 14) & 0x1F;
303: i->i = (w >> 13) & 0x01;
304: i->asi = (w >> 5) & 0xFF;
305: i->rs2 = (w >> 0) & 0x1F;
306: i->simm13 = (w >> 0) & 0x1FFF;
307: if(i->simm13 & (1<<12))
308: i->simm13 |= ~((1<<13)-1);
309: i->opf = (w >> 5) & 0x1FF;
310: i->immdisp22 = (w >> 0) & 0x3FFFFF;
311: i->simmdisp22 = i->immdisp22;
312: if(i->simmdisp22 & (1<<21))
313: i->simmdisp22 |= ~((1<<22)-1);
314: i->disp30 = (w >> 0) & 0x3FFFFFFF;
315: i->w0 = w;
316: i->target = -1;
317: i->addr = pc;
318: i->size = 1;
319: return 1;
320: }
321:
322: static int
323: mkinstr(ulong pc, Instr *i)
324: {
325: Instr xi;
326:
327: if (decode(pc, i) < 0)
328: return -1;
329: if(i->op==0 && i->op2==4 && !dascase){ /* SETHI */
330: if (decode(pc+4, &xi) < 0)
331: return -1;
332: if(xi.op==2 && xi.op3==0) /* ADD */
333: if(xi.i == 1 && xi.rs1 == i->rd){ /* immediate to same reg */
334: i->imm32 = xi.simm13 + (i->immdisp22<<10);
335: i->target = xi.rd;
336: i->w1 = xi.w0;
337: i->size++;
338: return 1;
339: }
340: }
341: if(i->op==2 && i->opf==1 && !dascase){ /* FMOVS */
342: if (decode(pc+4, &xi) < 0)
343: return -1;
344: if(i->op==2 && i->opf==1) /* FMOVS */
345: if(xi.rd==i->rd+1 && xi.rs2==i->rs2+1){ /* next pair */
346: i->w1 = xi.w0;
347: i->size++;
348: }
349: }
350: return 1;
351: }
352:
353: static int
354: printins(Map *map, ulong pc, char *buf, int n)
355: {
356: Instr instr;
357: void (*f)(Instr*, char*);
358:
359: mymap = map;
360: memset(&instr, 0, sizeof(instr));
361: instr.curr = buf;
362: instr.end = buf+n-1;
363: if (mkinstr(pc, &instr) < 0)
364: return -1;
365: switch(instr.op){
366: case 0:
367: f = sparcop0[instr.op2].f;
368: if(f)
369: (*f)(&instr, sparcop0[instr.op2].mnemonic);
370: else
371: bprint(&instr, "unknown %lux", instr.w0);
372: break;
373:
374: case 1:
375: bprint(&instr, "%X", "CALL\t");
376: instr.curr += symoff(instr.curr, instr.end-instr.curr,
377: pc+instr.disp30*4, CTEXT);
378: if (!dascase)
379: bprint(&instr, "(SB)");
380: break;
381:
382: case 2:
383: f = sparcop2[instr.op3].f;
384: if(f)
385: (*f)(&instr, sparcop2[instr.op3].mnemonic);
386: else
387: bprint(&instr, "unknown %lux", instr.w0);
388: break;
389:
390: case 3:
391: f = sparcop3[instr.op3].f;
392: if(f)
393: (*f)(&instr, sparcop3[instr.op3].mnemonic);
394: else
395: bprint(&instr, "unknown %lux", instr.w0);
396: break;
397: }
398: if (instr.err) {
399: if (instr.curr != buf)
400: bprint(&instr, "\t\t;");
401: bprint(&instr, instr.err);
402: }
403: return instr.size*4;
404: }
405:
406: /* convert to lower case from upper, according to dascase */
407: static int
408: Xconv(void *oa, Fconv *f)
409: {
410: char buf[128];
411: char *s, *t;
412:
413: if(dascase){
414: for(s=*(char**)oa,t=buf; *t = *s; s++,t++)
415: if('A'<=*t && *t<='Z')
416: *t += 'a'-'A';
417: strconv(buf, f);
418: }else
419: strconv(*(char**)oa, f);
420: return sizeof(char*);
421: }
422:
423: static int
424: sparcinst(Map *map, ulong pc, char modifier, char *buf, int n)
425: {
426: static int fmtinstalled = 0;
427:
428: /* a modifier of 'I' toggles the dissassembler type */
429: if (!fmtinstalled) {
430: fmtinstalled = 1;
431: fmtinstall('X', Xconv);
432: }
433: if ((asstype == ASUNSPARC && modifier == 'i')
434: || (asstype == ASPARC && modifier == 'I'))
435: dascase = 'a'-'A';
436: else
437: dascase = 0;
438: return printins(map, pc, buf, n);
439: }
440:
441: static int
442: sparcdas(Map *map, ulong pc, char *buf, int n)
443: {
444: Instr instr;
445:
446: mymap = map;
447: memset(&instr, 0, sizeof(instr));
448: instr.curr = buf;
449: instr.end = buf+n-1;
450: if (mkinstr(pc, &instr) < 0)
451: return -1;
452: if (instr.end-instr.curr > 8)
453: instr.curr = _hexify(instr.curr, instr.w0, 7);
454: if (instr.end-instr.curr > 9 && instr.size == 2) {
455: *instr.curr++ = ' ';
456: instr.curr = _hexify(instr.curr, instr.w1, 7);
457: }
458: *instr.curr = 0;
459: return instr.size*4;
460: }
461:
462: static int
463: sparcinstlen(Map *map, ulong pc)
464: {
465: Instr i;
466:
467: mymap = map;
468: if (mkinstr(pc, &i) < 0)
469: return -1;
470: return i.size*4;
471: }
472:
473: static int
474: plocal(Instr *i)
475: {
476: int offset;
477: Symbol s;
478:
479: if (!findsym(i->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s))
480: return -1;
481: if (s.value > i->simm13) {
482: if(getauto(&s, s.value-i->simm13, CAUTO, &s)) {
483: bprint(i, "%s+%d(SP)", s.name, s.value);
484: return 1;
485: }
486: } else {
487: offset = i->simm13-s.value;
488: if (getauto(&s, offset-4, CPARAM, &s)) {
489: bprint(i, "%s+%d(FP)", s.name, offset);
490: return 1;
491: }
492: }
493: return -1;
494: }
495:
496: static void
497: address(Instr *i)
498: {
499: Symbol s, s2;
500: long off, off1;
501:
502: if (i->rs1 == 1 && plocal(i) >= 0)
503: return;
504: off = mach->sb+i->simm13;
505: if(i->rs1 == 2 && findsym(off, CANY, &s)
506: && s.value-off < 4096
507: && (s.class == CDATA || s.class == CTEXT)) {
508: if(off==s.value && s.name[0]=='$'){
509: off1 = 0;
510: get4(mymap, s.value, &off1);
511: if(off1 && findsym(off1, CANY, &s2) && s2.value == off1){
512: bprint(i, "$%s(SB)", s2.name);
513: return;
514: }
515: }
516: bprint(i, "%s", s.name);
517: if (s.value != off)
518: bprint(i, "+%lux", s.value-off);
519: bprint(i, "(SB)");
520: return;
521: }
522: bprint(i, "%lux(R%d)", i->simm13, i->rs1);
523: }
524:
525: static void
526: unimp(Instr *i, char *m)
527: {
528: bprint(i, "%X", m);
529: }
530:
531: static char *bratab[16] = { /* page 91 */
532: [0X8] "A",
533: [0X0] "N",
534: [0X9] "NE",
535: [0X1] "E",
536: [0XA] "G",
537: [0X2] "LE",
538: [0XB] "GE",
539: [0X3] "L",
540: [0XC] "GU",
541: [0X4] "LEU",
542: [0XD] "CC",
543: [0X5] "CS",
544: [0XE] "POS",
545: [0X6] "NEG",
546: [0XF] "VC",
547: [0X7] "VS",
548: };
549:
550: static char *fbratab[16] = { /* page 91 */
551: [0X8] "A",
552: [0X0] "N",
553: [0X7] "U",
554: [0X6] "G",
555: [0X5] "UG",
556: [0X4] "L",
557: [0X3] "UL",
558: [0X2] "LG",
559: [0X1] "NE",
560: [0X9] "E",
561: [0XA] "UE",
562: [0XB] "GE",
563: [0XC] "UGE",
564: [0XD] "LE",
565: [0XE] "ULE",
566: [0XF] "O",
567: };
568:
569: static char *cbratab[16] = { /* page 91 */
570: [0X8] "A",
571: [0X0] "N",
572: [0X7] "3",
573: [0X6] "2",
574: [0X5] "23",
575: [0X4] "1",
576: [0X3] "13",
577: [0X2] "12",
578: [0X1] "123",
579: [0X9] "0",
580: [0XA] "03",
581: [0XB] "02",
582: [0XC] "023",
583: [0XD] "01",
584: [0XE] "013",
585: [0XF] "012",
586: };
587:
588: static void
589: bra1(Instr *i, char *m, char *tab[])
590: {
591: long imm;
592:
593: imm = i->simmdisp22;
594: if(i->a)
595: bprint(i, "%X%X.%c\t", m, tab[i->cond], 'A'+dascase);
596: else
597: bprint(i, "%X%X\t", m, tab[i->cond]);
598: i->curr += symoff(i->curr, i->end-i->curr, i->addr+4*imm, CTEXT);
599: if (!dascase)
600: bprint(i, "(SB)");
601: }
602:
603: static void
604: bra(Instr *i, char *m) /* page 91 */
605: {
606: bra1(i, m, bratab);
607: }
608:
609: static void
610: fbra(Instr *i, char *m) /* page 93 */
611: {
612: bra1(i, m, fbratab);
613: }
614:
615: static void
616: cbra(Instr *i, char *m) /* page 95 */
617: {
618: bra1(i, m, cbratab);
619: }
620:
621: static void
622: trap(Instr *i, char *m) /* page 101 */
623: {
624: if(i->i == 0)
625: bprint(i, "%X%X\tR%d+R%d", m, bratab[i->cond], i->rs2, i->rs1);
626: else
627: bprint(i, "%X%X\t$%lux+R%d", m, bratab[i->cond], i->simm13, i->rs1);
628: }
629:
630: static void
631: sethi(Instr *i, char *m) /* page 89 */
632: {
633: ulong imm;
634:
635: imm = i->immdisp22<<10;
636: if(dascase){
637: bprint(i, "%X\t%lux, R%d", m, imm, i->rd);
638: return;
639: }
640: if(imm==0 && i->rd==0){
641: bprint(i, "NOP");
642: return;
643: }
644: if(i->target < 0){
645: bprint(i, "MOVW\t$%lux, R%d", imm, i->rd);
646: return;
647: }
648: bprint(i, "MOVW\t$%lux, R%d", i->imm32, i->target);
649: }
650:
651: static char ldtab[] = {
652: 'W',
653: 'B',
654: 'H',
655: 'D',
656: };
657:
658: static char*
659: moveinstr(int op3, char *m)
660: {
661: char *s;
662: int c;
663: static char buf[8];
664:
665: if(!dascase){
666: /* batshit cases */
667: if(op3 == 0xF || op3 == 0x1F)
668: return "SWAP";
669: if(op3 == 0xD || op3 == 0x1D)
670: return "TAS"; /* really LDSTUB */
671: c = ldtab[op3&3];
672: s = "";
673: if((op3&11)==1 || (op3&11)==2)
674: s="U";
675: sprint(buf, "MOV%c%s", c, s);
676: return buf;
677: }
678: return m;
679: }
680:
681: static void
682: load(Instr *i, char *m) /* page 68 */
683: {
684: m = moveinstr(i->op3, m);
685: if(i->i == 0)
686: bprint(i, "%s\t(R%d+R%d), R%d", m, i->rs1, i->rs2, i->rd);
687: else{
688: bprint(i, "%s\t", m);
689: address(i);
690: bprint(i, ", R%d", i->rd);
691: }
692: }
693:
694: static void
695: loada(Instr *i, char *m) /* page 68 */
696: {
697: m = moveinstr(i->op3, m);
698: if(i->i == 0)
699: bprint(i, "%s\t(R%d+R%d, %d), R%d", m, i->rs1, i->rs2, i->asi, i->rd);
700: else
701: bprint(i, "unknown ld asi %lux", i->w0);
702: }
703:
704: static void
705: store(Instr *i, char *m) /* page 74 */
706: {
707: m = moveinstr(i->op3, m);
708: if(i->i == 0)
709: bprint(i, "%s\tR%d, (R%d+R%d)",
710: m, i->rd, i->rs1, i->rs2);
711: else{
712: bprint(i, "%s\tR%d, ", m, i->rd);
713: address(i);
714: }
715: }
716:
717: static void
718: storea(Instr *i, char *m) /* page 74 */
719: {
720: m = moveinstr(i->op3, m);
721: if(i->i == 0)
722: bprint(i, "%s\tR%d, (R%d+R%d, %d)", m, i->rd, i->rs1, i->rs2, i->asi);
723: else
724: bprint(i, "%s\tR%d, %d(R%d, %d), ???", m, i->rd, i->simm13, i->rs1, i->asi);
725: }
726:
727: void
728: shift(Instr *i, char *m) /* page 88 */
729: {
730: if(i->i == 0){
731: if(i->rs1 == i->rd)
732: if(dascase)
733: bprint(i, "%X\tR%d, R%d", m, i->rs1, i->rs2);
734: else
735: bprint(i, "%X\tR%d, R%d", m, i->rs2, i->rs1);
736: else
737: if(dascase)
738: bprint(i, "%X\tR%d, R%d, R%d", m, i->rs1, i->rs2, i->rd);
739: else
740: bprint(i, "%X\tR%d, R%d, R%d", m, i->rs2, i->rs1, i->rd);
741: }else{
742: if(i->rs1 == i->rd)
743: if(dascase)
744: bprint(i, "%X\t$%d,R%d", m, i->simm13&0x1F, i->rs1);
745: else
746: bprint(i, "%X\tR%d, $%d", m, i->rs1, i->simm13&0x1F);
747: else
748: if(dascase)
749: bprint(i, "%X\tR%d, $%d, R%d",m,i->rs1,i->simm13&0x1F,i->rd);
750: else
751: bprint(i, "%X\t$%d, R%d, R%d",m,i->simm13&0x1F,i->rs1,i->rd);
752: }
753: }
754:
755: static void
756: add(Instr *i, char *m) /* page 82 */
757: {
758: if(i->i == 0){
759: if(dascase)
760: bprint(i, "%X\tR%d, R%d", m, i->rs1, i->rs2);
761: else
762: if(i->op3==2 && i->rs1==0 && i->rd) /* OR R2, R0, R1 */
763: bprint(i, "MOVW\tR%d", i->rs2);
764: else
765: bprint(i, "%X\tR%d, R%d", m, i->rs2, i->rs1);
766: }else{
767: if(dascase)
768: bprint(i, "%X\tR%d, $%lux", m, i->rs1, i->simm13);
769: else
770: if(i->op3==0 && i->rd && i->rs1==0) /* ADD $x, R0, R1 */
771: bprint(i, "MOVW\t$%lux", i->simm13);
772: else if(i->op3==0 && i->rd && i->rs1==2){
773: /* ADD $x, R2, R1 -> MOVW $x(SB), R1 */
774: bprint(i, "MOVW\t$");
775: address(i);
776: } else
777: bprint(i, "%X\t$%lux, R%d", m, i->simm13, i->rs1);
778: }
779: if(i->rs1 != i->rd)
780: bprint(i, ", R%d", i->rd);
781: }
782:
783: static void
784: cmp(Instr *i, char *m)
785: {
786: if(dascase || i->rd){
787: add(i, m);
788: return;
789: }
790: if(i->i == 0)
791: bprint(i, "CMP\tR%d, R%d", i->rs1, i->rs2);
792: else
793: bprint(i, "CMP\tR%d, $%lux", i->rs1, i->simm13);
794: }
795:
796: static char *regtab[4] = {
797: "Y",
798: "PSR",
799: "WIM",
800: "TBR",
801: };
802:
803: static void
804: wr(Instr *i, char *m) /* page 82 */
805: {
806: if(dascase){
807: if(i->i == 0)
808: bprint(i, "%s\tR%d, R%d", m, i->rs1, i->rs2);
809: else
810: bprint(i, "%s\tR%d, $%lux", m, i->rs1, i->simm13);
811: }else{
812: if(i->i && i->simm13==0)
813: bprint(i, "MOVW\tR%d", i->rs1);
814: else if(i->i == 0)
815: bprint(i, "wr\tR%d, R%d", i->rs2, i->rs1);
816: else
817: bprint(i, "wr\t$%lux, R%d", i->simm13, i->rs1);
818: }
819: bprint(i, ", %s", regtab[i->op3&3]);
820: }
821:
822: static void
823: rd(Instr *i, char *m) /* page 103 */
824: {
825: if(i->rs1==15 && i->rd==0){
826: m = "stbar";
827: if(!dascase)
828: m = "STBAR";
829: bprint(i, "%s", m);
830: }else{
831: if(!dascase)
832: m = "MOVW";
833: bprint(i, "%s\t%s, R%d", m, regtab[i->op3&3], i->rd);
834: }
835: }
836:
837: static void
838: jmpl(Instr *i, char *m) /* page 82 */
839: {
840: if(i->i == 0){
841: if(i->rd == 15)
842: bprint(i, "%X\t(R%d+R%d)", "CALL", i->rs2, i->rs1);
843: else
844: bprint(i, "%X\t(R%d+R%d), R%d", m, i->rs2, i->rs1, i->rd);
845: }else{
846: if(!dascase && i->simm13==8 && i->rs1==15 && i->rd==0)
847: bprint(i, "RETURN");
848: else{
849: bprint(i, "%X\t", m);
850: address(i);
851: bprint(i, ", R%d", i->rd);
852: }
853: }
854: }
855:
856: static void
857: loadf(Instr *i, char *m) /* page 70 */
858: {
859: if(!dascase){
860: m = "FMOVD";
861: if(i->op3 == 0x20)
862: m = "FMOVF";
863: else if(i->op3 == 0x21)
864: m = "MOVW";
865: }
866: if(i->i == 0)
867: bprint(i, "%s\t(R%d+R%d)", m, i->rs1, i->rs2);
868: else{
869: bprint(i, "%s\t", m);
870: address(i);
871: }
872: if(i->op3 == 0x21)
873: bprint(i, ", FSR");
874: else
875: bprint(i, ", R%d", i->rd);
876: }
877:
878: static
879: void storef(Instr *i, char *m) /* page 70 */
880: {
881: if(!dascase){
882: m = "FMOVD";
883: if(i->op3 == 0x25 || i->op3 == 0x26)
884: m = "MOVW";
885: else if(i->op3 == 0x20)
886: m = "FMOVF";
887: }
888: bprint(i, "%s\t", m);
889: if(i->op3 == 0x25)
890: bprint(i, "FSR, ");
891: else if(i->op3 == 0x26)
892: bprint(i, "FQ, ");
893: else
894: bprint(i, "R%d, ", i->rd);
895: if(i->i == 0)
896: bprint(i, "(R%d+R%d)", i->rs1, i->rs2);
897: else
898: address(i);
899: }
900:
901: static
902: void loadc(Instr *i, char *m) /* page 72 */
903: {
904: if(i->i == 0)
905: bprint(i, "%s\t(R%d+R%d), C%d", m, i->rs1, i->rs2, i->rd);
906: else{
907: bprint(i, "%s\t", m);
908: address(i);
909: bprint(i, ", C%d", i->rd);
910: }
911: }
912:
913: static
914: void loadcsr(Instr *i, char *m) /* page 72 */
915: {
916: if(i->i == 0)
917: bprint(i, "%s\t(R%d+R%d), CSR", m, i->rs1, i->rs2);
918: else{
919: bprint(i, "%s\t", m);
920: address(i);
921: bprint(i, ", CSR");
922: }
923: }
924:
925: static struct{
926: int opf;
927: char *name;
928: } fptab1[] = { /* ignores rs1 */
929: 0xC4, "FITOS", /* page 109 */
930: 0xC8, "FITOD",
931: 0xCC, "FITOX",
932:
933: 0xD1, "FSTOI", /* page 110 */
934: 0xD2, "FDTOI",
935: 0xD3, "FXTOI",
936:
937: 0xC9, "FSTOD", /* page 111 */
938: 0xCD, "FSTOX",
939: 0xC6, "FDTOS",
940: 0xCE, "FDTOX",
941: 0xC7, "FXTOS",
942: 0xCB, "FXTOD",
943:
944: 0x01, "FMOVS", /* page 112 */
945: 0x05, "FNEGS",
946: 0x09, "FABSS",
947:
948: 0x29, "FSQRTS", /* page 113 */
949: 0x2A, "FSQRTD",
950: 0x2B, "FSQRTX",
951:
952: 0, 0,
953: };
954:
955: static struct{
956: int opf;
957: char *name;
958: } fptab2[] = { /* uses rs1 */
959:
960: 0x41, "FADDS", /* page 114 */
961: 0x42, "FADDD",
962: 0x43, "FADDX",
963: 0x45, "FSUBS",
964: 0x46, "FSUBD",
965: 0x47, "FSUBX",
966:
967: 0x49, "FMULS", /* page 115 */
968: 0x4A, "FMULD",
969: 0x4B, "FMULX",
970: 0x4D, "FDIVS",
971: 0x4E, "FDIVD",
972: 0x4F, "FDIVX",
973:
974: 0x51, "FCMPS", /* page 116 */
975: 0x52, "FCMPD",
976: 0x53, "FCMPX",
977: 0x55, "FCMPES",
978: 0x56, "FCMPED",
979: 0x57, "FCMPEX",
980:
981: 0, 0
982: };
983:
984: static void
985: fpop(Instr *i, char *m) /* page 108-116 */
986: {
987: int j;
988:
989: if(dascase==0 && i->size==2){
990: bprint(i, "FMOVD\tF%d, F%d", i->rs2, i->rd);
991: return;
992: }
993: for(j=0; fptab1[j].name; j++)
994: if(fptab1[j].opf == i->opf){
995: bprint(i, "%X\tF%d, F%d", fptab1[j].name, i->rs2, i->rd);
996: return;
997: }
998: for(j=0; fptab2[j].name; j++)
999: if(fptab2[j].opf == i->opf){
1000: bprint(i, "%X\tF%d, F%d, F%d", fptab2[j].name, i->rs1, i->rs2, i->rd);
1001: return;
1002: }
1003: bprint(i, "%X%ux\tF%d, F%d, F%d", m, i->opf, i->rs1, i->rs2, i->rd);
1004: }
1005:
1006: static int
1007: sparcfoll(Map *map, ulong pc, Rgetter rget, ulong *foll)
1008: {
1009: ulong w, r1, r2;
1010: char buf[8];
1011: Instr i;
1012:
1013: mymap = map;
1014: if (mkinstr(pc, &i) < 0)
1015: return -1;
1016: w = i.w0;
1017: switch(w & 0xC1C00000){
1018: case 0x00800000: /* branch on int cond */
1019: case 0x01800000: /* branch on fp cond */
1020: case 0x01C00000: /* branch on copr cond */
1021: foll[0] = pc+8;
1022: foll[1] = pc + (i.simmdisp22<<2);
1023: return 2;
1024: }
1025:
1026: if((w&0xC0000000) == 0x40000000){ /* CALL */
1027: foll[0] = pc + (i.disp30<<2);
1028: return 1;
1029: }
1030:
1031: if((w&0xC1F80000) == 0x81C00000){ /* JMPL */
1032: sprint(buf, "R%d", (w>>14)&0xF);
1033: r1 = (*rget)(map, buf);
1034: if(w & 0x2000) /* JMPL R1+simm13 */
1035: r2 = i.simm13;
1036: else{ /* JMPL R1+R2 */
1037: sprint(buf, "R%d", w&0xF);
1038: r2 = (*rget)(map, buf);
1039: }
1040: foll[0] = r1 + r2;
1041: return 1;
1042: }
1043: foll[0] = pc+i.size*4;
1044: return 1;
1045: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.