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