174a4d8c2SCharles.Forsyth #include <lib9.h>
274a4d8c2SCharles.Forsyth #include <bio.h>
374a4d8c2SCharles.Forsyth #include "mach.h"
474a4d8c2SCharles.Forsyth
574a4d8c2SCharles.Forsyth /*
674a4d8c2SCharles.Forsyth * Sparc-specific debugger interface
774a4d8c2SCharles.Forsyth */
874a4d8c2SCharles.Forsyth
974a4d8c2SCharles.Forsyth static char *sparcexcep(Map*, Rgetter);
10d67b7dadSforsyth static int sparcfoll(Map*, uvlong, Rgetter, uvlong*);
11d67b7dadSforsyth static int sparcinst(Map*, uvlong, char, char*, int);
12d67b7dadSforsyth static int sparcdas(Map*, uvlong, char*, int);
13d67b7dadSforsyth static int sparcinstlen(Map*, uvlong);
1474a4d8c2SCharles.Forsyth
1574a4d8c2SCharles.Forsyth Machdata sparcmach =
1674a4d8c2SCharles.Forsyth {
1774a4d8c2SCharles.Forsyth {0x91, 0xd0, 0x20, 0x01}, /* breakpoint: TA $1 */
1874a4d8c2SCharles.Forsyth 4, /* break point size */
1974a4d8c2SCharles.Forsyth
2074a4d8c2SCharles.Forsyth beswab, /* convert short to local byte order */
2174a4d8c2SCharles.Forsyth beswal, /* convert long to local byte order */
2274a4d8c2SCharles.Forsyth beswav, /* convert vlong to local byte order */
2374a4d8c2SCharles.Forsyth risctrace, /* C traceback */
2474a4d8c2SCharles.Forsyth riscframe, /* frame finder */
2574a4d8c2SCharles.Forsyth sparcexcep, /* print exception */
2674a4d8c2SCharles.Forsyth 0, /* breakpoint fixup */
2774a4d8c2SCharles.Forsyth beieeesftos, /* single precision float printer */
2874a4d8c2SCharles.Forsyth beieeedftos, /* double precision float printer */
2974a4d8c2SCharles.Forsyth sparcfoll, /* following addresses */
3074a4d8c2SCharles.Forsyth sparcinst, /* print instruction */
3174a4d8c2SCharles.Forsyth sparcdas, /* dissembler */
3274a4d8c2SCharles.Forsyth sparcinstlen, /* instruction size */
3374a4d8c2SCharles.Forsyth };
3474a4d8c2SCharles.Forsyth
3574a4d8c2SCharles.Forsyth static char *trapname[] =
3674a4d8c2SCharles.Forsyth {
3774a4d8c2SCharles.Forsyth "reset",
3874a4d8c2SCharles.Forsyth "instruction access exception",
3974a4d8c2SCharles.Forsyth "illegal instruction",
4074a4d8c2SCharles.Forsyth "privileged instruction",
4174a4d8c2SCharles.Forsyth "fp disabled",
4274a4d8c2SCharles.Forsyth "window overflow",
4374a4d8c2SCharles.Forsyth "window underflow",
4474a4d8c2SCharles.Forsyth "unaligned address",
4574a4d8c2SCharles.Forsyth "fp exception",
4674a4d8c2SCharles.Forsyth "data access exception",
4774a4d8c2SCharles.Forsyth "tag overflow",
4874a4d8c2SCharles.Forsyth };
4974a4d8c2SCharles.Forsyth
5074a4d8c2SCharles.Forsyth static char*
excname(ulong tbr)5174a4d8c2SCharles.Forsyth excname(ulong tbr)
5274a4d8c2SCharles.Forsyth {
5374a4d8c2SCharles.Forsyth static char buf[32];
5474a4d8c2SCharles.Forsyth
5574a4d8c2SCharles.Forsyth if(tbr < sizeof trapname/sizeof(char*))
5674a4d8c2SCharles.Forsyth return trapname[tbr];
5774a4d8c2SCharles.Forsyth if(tbr >= 130)
5874a4d8c2SCharles.Forsyth sprint(buf, "trap instruction %ld", tbr-128);
5974a4d8c2SCharles.Forsyth else if(17<=tbr && tbr<=31)
6074a4d8c2SCharles.Forsyth sprint(buf, "interrupt level %ld", tbr-16);
6174a4d8c2SCharles.Forsyth else switch(tbr){
6274a4d8c2SCharles.Forsyth case 36:
6374a4d8c2SCharles.Forsyth return "cp disabled";
6474a4d8c2SCharles.Forsyth case 40:
6574a4d8c2SCharles.Forsyth return "cp exception";
6674a4d8c2SCharles.Forsyth case 128:
6774a4d8c2SCharles.Forsyth return "syscall";
6874a4d8c2SCharles.Forsyth case 129:
6974a4d8c2SCharles.Forsyth return "breakpoint";
7074a4d8c2SCharles.Forsyth default:
7174a4d8c2SCharles.Forsyth sprint(buf, "unknown trap %ld", tbr);
7274a4d8c2SCharles.Forsyth }
7374a4d8c2SCharles.Forsyth return buf;
7474a4d8c2SCharles.Forsyth }
7574a4d8c2SCharles.Forsyth
7674a4d8c2SCharles.Forsyth static char*
sparcexcep(Map * map,Rgetter rget)7774a4d8c2SCharles.Forsyth sparcexcep(Map *map, Rgetter rget)
7874a4d8c2SCharles.Forsyth {
7974a4d8c2SCharles.Forsyth long tbr;
8074a4d8c2SCharles.Forsyth
8174a4d8c2SCharles.Forsyth tbr = (*rget)(map, "TBR");
8274a4d8c2SCharles.Forsyth tbr = (tbr&0xFFF)>>4;
8374a4d8c2SCharles.Forsyth return excname(tbr);
8474a4d8c2SCharles.Forsyth }
8574a4d8c2SCharles.Forsyth
8674a4d8c2SCharles.Forsyth /* Sparc disassembler and related functions */
87fb27fba1Sforsyth typedef struct instr Instr;
8874a4d8c2SCharles.Forsyth
8974a4d8c2SCharles.Forsyth struct opcode {
9074a4d8c2SCharles.Forsyth char *mnemonic;
91fb27fba1Sforsyth void (*f)(Instr*, char*);
9274a4d8c2SCharles.Forsyth int flag;
9374a4d8c2SCharles.Forsyth };
9474a4d8c2SCharles.Forsyth
9574a4d8c2SCharles.Forsyth static char FRAMENAME[] = ".frame";
9674a4d8c2SCharles.Forsyth
97d67b7dadSforsyth
9874a4d8c2SCharles.Forsyth struct instr {
9974a4d8c2SCharles.Forsyth uchar op; /* bits 31-30 */
10074a4d8c2SCharles.Forsyth uchar rd; /* bits 29-25 */
10174a4d8c2SCharles.Forsyth uchar op2; /* bits 24-22 */
10274a4d8c2SCharles.Forsyth uchar a; /* bit 29 */
10374a4d8c2SCharles.Forsyth uchar cond; /* bits 28-25 */
10474a4d8c2SCharles.Forsyth uchar op3; /* bits 24-19 */
10574a4d8c2SCharles.Forsyth uchar rs1; /* bits 18-14 */
10674a4d8c2SCharles.Forsyth uchar i; /* bit 13 */
10774a4d8c2SCharles.Forsyth uchar asi; /* bits 12-05 */
10874a4d8c2SCharles.Forsyth uchar rs2; /* bits 04-00 */
10974a4d8c2SCharles.Forsyth short simm13; /* bits 12-00, signed */
11074a4d8c2SCharles.Forsyth ushort opf; /* bits 13-05 */
11174a4d8c2SCharles.Forsyth ulong immdisp22; /* bits 21-00 */
11274a4d8c2SCharles.Forsyth ulong simmdisp22; /* bits 21-00, signed */
11374a4d8c2SCharles.Forsyth ulong disp30; /* bits 30-00 */
11474a4d8c2SCharles.Forsyth ulong imm32; /* SETHI+ADD constant */
11574a4d8c2SCharles.Forsyth int target; /* SETHI+ADD dest reg */
11674a4d8c2SCharles.Forsyth long w0;
11774a4d8c2SCharles.Forsyth long w1;
118d67b7dadSforsyth uvlong addr; /* pc of instruction */
11974a4d8c2SCharles.Forsyth char *curr; /* current fill level in output buffer */
12074a4d8c2SCharles.Forsyth char *end; /* end of buffer */
12174a4d8c2SCharles.Forsyth int size; /* number of longs in instr */
12274a4d8c2SCharles.Forsyth char *err; /* errmsg */
12374a4d8c2SCharles.Forsyth };
12474a4d8c2SCharles.Forsyth
12574a4d8c2SCharles.Forsyth static Map *mymap; /* disassembler context */
12674a4d8c2SCharles.Forsyth static int dascase;
12774a4d8c2SCharles.Forsyth
128d67b7dadSforsyth static int mkinstr(uvlong, Instr*);
12974a4d8c2SCharles.Forsyth static void bra1(Instr*, char*, char*[]);
13074a4d8c2SCharles.Forsyth static void bra(Instr*, char*);
13174a4d8c2SCharles.Forsyth static void fbra(Instr*, char*);
13274a4d8c2SCharles.Forsyth static void cbra(Instr*, char*);
13374a4d8c2SCharles.Forsyth static void unimp(Instr*, char*);
13474a4d8c2SCharles.Forsyth static void fpop(Instr*, char*);
13574a4d8c2SCharles.Forsyth static void shift(Instr*, char*);
13674a4d8c2SCharles.Forsyth static void sethi(Instr*, char*);
13774a4d8c2SCharles.Forsyth static void load(Instr*, char*);
13874a4d8c2SCharles.Forsyth static void loada(Instr*, char*);
13974a4d8c2SCharles.Forsyth static void store(Instr*, char*);
14074a4d8c2SCharles.Forsyth static void storea(Instr*, char*);
14174a4d8c2SCharles.Forsyth static void add(Instr*, char*);
14274a4d8c2SCharles.Forsyth static void cmp(Instr*, char*);
14374a4d8c2SCharles.Forsyth static void wr(Instr*, char*);
14474a4d8c2SCharles.Forsyth static void jmpl(Instr*, char*);
14574a4d8c2SCharles.Forsyth static void rd(Instr*, char*);
14674a4d8c2SCharles.Forsyth static void loadf(Instr*, char*);
14774a4d8c2SCharles.Forsyth static void storef(Instr*, char*);
14874a4d8c2SCharles.Forsyth static void loadc(Instr*, char*);
14974a4d8c2SCharles.Forsyth static void loadcsr(Instr*, char*);
15074a4d8c2SCharles.Forsyth static void trap(Instr*, char*);
15174a4d8c2SCharles.Forsyth
15274a4d8c2SCharles.Forsyth static struct opcode sparcop0[8] = {
153773d7fd2Sforsyth "UNIMP", unimp, 0, /* page 137 */ /* 0 */
154773d7fd2Sforsyth "", 0, 0, /* 1 */
155773d7fd2Sforsyth "B", bra, 0, /* page 119 */ /* 2 */
156773d7fd2Sforsyth "", 0, 0, /* 3 */
157773d7fd2Sforsyth "SETHI", sethi, 0, /* page 104 */ /* 4 */
158773d7fd2Sforsyth "", 0, 0, /* 5 */
159773d7fd2Sforsyth "FB", fbra, 0, /* page 121 */ /* 6 */
160773d7fd2Sforsyth "CB", cbra, 0, /* page 123 */ /* 7 */
16174a4d8c2SCharles.Forsyth };
16274a4d8c2SCharles.Forsyth
16374a4d8c2SCharles.Forsyth static struct opcode sparcop2[64] = {
164773d7fd2Sforsyth "ADD", add, 0, /* page 108 */ /* 0x00 */
165773d7fd2Sforsyth "AND", add, 0, /* page 106 */ /* 0x01 */
166773d7fd2Sforsyth "OR", add, 0, /* 0x02 */
167773d7fd2Sforsyth "XOR", add, 0, /* 0x03 */
168773d7fd2Sforsyth "SUB", add, 0, /* page 110 */ /* 0x04 */
169773d7fd2Sforsyth "ANDN", add, 0, /* 0x05 */
170773d7fd2Sforsyth "ORN", add, 0, /* 0x06 */
171773d7fd2Sforsyth "XORN", add, 0, /* 0x07 */
172773d7fd2Sforsyth "ADDX", add, 0, /* 0x08 */
173773d7fd2Sforsyth "", 0, 0, /* 0x09 */
174773d7fd2Sforsyth "UMUL", add, 0, /* page 113 */ /* 0x0a */
175773d7fd2Sforsyth "SMUL", add, 0, /* 0x0b */
176773d7fd2Sforsyth "SUBX", add, 0, /* 0x0c */
177773d7fd2Sforsyth "", 0, 0, /* 0x0d */
178773d7fd2Sforsyth "UDIV", add, 0, /* page 115 */ /* 0x0e */
179773d7fd2Sforsyth "SDIV", add, 0, /* 0x0f */
180773d7fd2Sforsyth "ADDCC", add, 0, /* 0x10 */
181773d7fd2Sforsyth "ANDCC", add, 0, /* 0x11 */
182773d7fd2Sforsyth "ORCC", add, 0, /* 0x12 */
183773d7fd2Sforsyth "XORCC", add, 0, /* 0x13 */
184773d7fd2Sforsyth "SUBCC", cmp, 0, /* 0x14 */
185773d7fd2Sforsyth "ANDNCC", add, 0, /* 0x15 */
186773d7fd2Sforsyth "ORNCC", add, 0, /* 0x16 */
187773d7fd2Sforsyth "XORNCC", add, 0, /* 0x17 */
188773d7fd2Sforsyth "ADDXCC", add, 0, /* 0x18 */
189773d7fd2Sforsyth "", 0, 0, /* 0x19 */
190773d7fd2Sforsyth "UMULCC", add, 0, /* 0x1a */
191773d7fd2Sforsyth "SMULCC", add, 0, /* 0x1b */
192773d7fd2Sforsyth "SUBXCC", add, 0, /* 0x1c */
193773d7fd2Sforsyth "", 0, 0, /* 0x1d */
194773d7fd2Sforsyth "UDIVCC", add, 0, /* 0x1e */
195773d7fd2Sforsyth "SDIVCC", add, 0, /* 0x1f */
196773d7fd2Sforsyth "TADD", add, 0, /* page 109 */ /* 0x20 */
197773d7fd2Sforsyth "TSUB", add, 0, /* page 111 */ /* 0x21 */
198773d7fd2Sforsyth "TADDCCTV", add, 0, /* 0x22 */
199773d7fd2Sforsyth "TSUBCCTV", add, 0, /* 0x23 */
200773d7fd2Sforsyth "MULSCC", add, 0, /* page 112 */ /* 0x24 */
201773d7fd2Sforsyth "SLL", shift, 0, /* page 107 */ /* 0x25 */
202773d7fd2Sforsyth "SRL", shift, 0, /* 0x26 */
203773d7fd2Sforsyth "SRA", shift, 0, /* 0x27 */
204773d7fd2Sforsyth "rdy", rd, 0, /* page 131 */ /* 0x28 */
205773d7fd2Sforsyth "rdpsr", rd, 0, /* 0x29 */
206773d7fd2Sforsyth "rdwim", rd, 0, /* 0x2a */
207773d7fd2Sforsyth "rdtbr", rd, 0, /* 0x2b */
208773d7fd2Sforsyth "", 0, 0, /* 0x2c */
209773d7fd2Sforsyth "", 0, 0, /* 0x2d */
210773d7fd2Sforsyth "", 0, 0, /* 0x2e */
211773d7fd2Sforsyth "", 0, 0, /* 0x2f */
212773d7fd2Sforsyth "wry", wr, 0, /* page 133 */ /* 0x30 */
213773d7fd2Sforsyth "wrpsr", wr, 0, /* 0x31 */
214773d7fd2Sforsyth "wrwim", wr, 0, /* 0x32 */
215773d7fd2Sforsyth "wrtbr", wr, 0, /* 0x33 */
216773d7fd2Sforsyth "FPOP", fpop, 0, /* page 140 */ /* 0x34 */
217773d7fd2Sforsyth "FPOP", fpop, 0, /* 0x35 */
218773d7fd2Sforsyth "", 0, 0, /* 0x36 */
219773d7fd2Sforsyth "", 0, 0, /* 0x37 */
220773d7fd2Sforsyth "JMPL", jmpl, 0, /* page 126 */ /* 0x38 */
221773d7fd2Sforsyth "RETT", add, 0, /* page 127 */ /* 0x39 */
222773d7fd2Sforsyth "T", trap, 0, /* page 129 */ /* 0x3a */
223773d7fd2Sforsyth "flush", add, 0, /* page 138 */ /* 0x3b */
224773d7fd2Sforsyth "SAVE", add, 0, /* page 117 */ /* 0x3c */
225773d7fd2Sforsyth "RESTORE", add, 0, /* 0x3d */
22674a4d8c2SCharles.Forsyth };
22774a4d8c2SCharles.Forsyth
22874a4d8c2SCharles.Forsyth static struct opcode sparcop3[64]={
229773d7fd2Sforsyth "ld", load, 0, /* 0x00 */
230773d7fd2Sforsyth "ldub", load, 0, /* 0x01 */
231773d7fd2Sforsyth "lduh", load, 0, /* 0x02 */
232773d7fd2Sforsyth "ldd", load, 0, /* 0x03 */
233773d7fd2Sforsyth "st", store, 0, /* 0x04 */
234773d7fd2Sforsyth "stb", store, 0, /* page 95 */ /* 0x05 */
235773d7fd2Sforsyth "sth", store, 0, /* 0x06 */
236773d7fd2Sforsyth "std", store, 0, /* 0x07 */
237773d7fd2Sforsyth "", 0, 0, /* 0x08 */
238773d7fd2Sforsyth "ldsb", load, 0, /* page 90 */ /* 0x09 */
239773d7fd2Sforsyth "ldsh", load, 0, /* 0x0a */
240773d7fd2Sforsyth "", 0, 0, /* 0x0b */
241773d7fd2Sforsyth "", 0, 0, /* 0x0c */
242773d7fd2Sforsyth "ldstub", store, 0, /* page 101 */ /* 0x0d */
243773d7fd2Sforsyth "", 0, 0, /* 0x0e */
244773d7fd2Sforsyth "swap", load, 0, /* page 102 */ /* 0x0f */
245773d7fd2Sforsyth "lda", loada, 0, /* 0x10 */
246773d7fd2Sforsyth "lduba", loada, 0, /* 0x11 */
247773d7fd2Sforsyth "lduha", loada, 0, /* 0x12 */
248773d7fd2Sforsyth "ldda", loada, 0, /* 0x13 */
249773d7fd2Sforsyth "sta", storea, 0, /* 0x14 */
250773d7fd2Sforsyth "stba", storea, 0, /* 0x15 */
251773d7fd2Sforsyth "stha", storea, 0, /* 0x16 */
252773d7fd2Sforsyth "stda", storea, 0, /* 0x17 */
253773d7fd2Sforsyth "", 0, 0, /* 0x18 */
254773d7fd2Sforsyth "ldsba", loada, 0, /* 0x19 */
255773d7fd2Sforsyth "ldsha", loada, 0, /* 0x1a */
256773d7fd2Sforsyth "", 0, 0, /* 0x1b */
257773d7fd2Sforsyth "", 0, 0, /* 0x1c */
258773d7fd2Sforsyth "ldstuba", storea, 0, /* 0x1d */
259773d7fd2Sforsyth "", 0, 0, /* 0x1e */
260773d7fd2Sforsyth "swapa", loada, 0, /* 0x1f */
261773d7fd2Sforsyth "ldf", loadf, 0, /* page 92 */ /* 0x20 */
262773d7fd2Sforsyth "ldfsr", loadf,0, /* 0x21 */
263773d7fd2Sforsyth "", 0, 0, /* 0x22 */
264773d7fd2Sforsyth "lddf", loadf, 0, /* 0x23 */
265773d7fd2Sforsyth "stf", storef, 0, /* page 97 */ /* 0x24 */
266773d7fd2Sforsyth "stfsr", storef,0, /* 0x25 */
267773d7fd2Sforsyth "stdfq", storef,0, /* 0x26 */
268773d7fd2Sforsyth "stdf", storef, 0, /* 0x27 */
269773d7fd2Sforsyth "", 0, 0, /* 0x28 */
270773d7fd2Sforsyth "", 0, 0, /* 0x29 */
271773d7fd2Sforsyth "", 0, 0, /* 0x2a */
272773d7fd2Sforsyth "", 0, 0, /* 0x2b */
273773d7fd2Sforsyth "", 0, 0, /* 0x2c */
274773d7fd2Sforsyth "", 0, 0, /* 0x2d */
275773d7fd2Sforsyth "", 0, 0, /* 0x2e */
276773d7fd2Sforsyth "", 0, 0, /* 0x2f */
277773d7fd2Sforsyth "ldc", loadc, 0, /* page 94 */ /* 0x30 */
278773d7fd2Sforsyth "ldcsr", loadcsr,0, /* 0x31 */
279773d7fd2Sforsyth "", 0, 0, /* 0x32 */
280773d7fd2Sforsyth "lddc", loadc, 0, /* 0x33 */
281773d7fd2Sforsyth "stc", loadc, 0, /* page 99 */ /* 0x34 */
282773d7fd2Sforsyth "stcsr", loadcsr,0, /* 0x35 */
283773d7fd2Sforsyth "stdcq", loadcsr,0, /* 0x36 */
284773d7fd2Sforsyth "stdc", loadc, 0, /* 0x37 */
28574a4d8c2SCharles.Forsyth };
28674a4d8c2SCharles.Forsyth
287d67b7dadSforsyth #pragma varargck argpos bprint 2
288d67b7dadSforsyth #pragma varargck type "T" char*
289d67b7dadSforsyth
290d67b7dadSforsyth /* convert to lower case from upper, according to dascase */
291d67b7dadSforsyth static int
Tfmt(Fmt * f)292d67b7dadSforsyth Tfmt(Fmt *f)
293d67b7dadSforsyth {
294d67b7dadSforsyth char buf[128];
295d67b7dadSforsyth char *s, *t, *oa;
296d67b7dadSforsyth
297d67b7dadSforsyth oa = va_arg(f->args, char*);
298d67b7dadSforsyth if(dascase){
299d67b7dadSforsyth for(s=oa,t=buf; *t = *s; s++,t++)
300d67b7dadSforsyth if('A'<=*t && *t<='Z')
301d67b7dadSforsyth *t += 'a'-'A';
302d67b7dadSforsyth return fmtstrcpy(f, buf);
303d67b7dadSforsyth }
304d67b7dadSforsyth return fmtstrcpy(f, oa);
305d67b7dadSforsyth }
306d67b7dadSforsyth
30774a4d8c2SCharles.Forsyth static void
bprint(Instr * i,char * fmt,...)30874a4d8c2SCharles.Forsyth bprint(Instr *i, char *fmt, ...)
30974a4d8c2SCharles.Forsyth {
31074a4d8c2SCharles.Forsyth va_list arg;
31174a4d8c2SCharles.Forsyth
31274a4d8c2SCharles.Forsyth va_start(arg, fmt);
31374a4d8c2SCharles.Forsyth i->curr = vseprint(i->curr, i->end, fmt, arg);
31474a4d8c2SCharles.Forsyth va_end(arg);
31574a4d8c2SCharles.Forsyth }
31674a4d8c2SCharles.Forsyth
31774a4d8c2SCharles.Forsyth static int
decode(uvlong pc,Instr * i)318d67b7dadSforsyth decode(uvlong pc, Instr *i)
31974a4d8c2SCharles.Forsyth {
320d67b7dadSforsyth ulong w;
32174a4d8c2SCharles.Forsyth
32274a4d8c2SCharles.Forsyth if (get4(mymap, pc, &w) < 0) {
32374a4d8c2SCharles.Forsyth werrstr("can't read instruction: %r");
32474a4d8c2SCharles.Forsyth return -1;
32574a4d8c2SCharles.Forsyth }
32674a4d8c2SCharles.Forsyth i->op = (w >> 30) & 0x03;
32774a4d8c2SCharles.Forsyth i->rd = (w >> 25) & 0x1F;
32874a4d8c2SCharles.Forsyth i->op2 = (w >> 22) & 0x07;
32974a4d8c2SCharles.Forsyth i->a = (w >> 29) & 0x01;
33074a4d8c2SCharles.Forsyth i->cond = (w >> 25) & 0x0F;
33174a4d8c2SCharles.Forsyth i->op3 = (w >> 19) & 0x3F;
33274a4d8c2SCharles.Forsyth i->rs1 = (w >> 14) & 0x1F;
33374a4d8c2SCharles.Forsyth i->i = (w >> 13) & 0x01;
33474a4d8c2SCharles.Forsyth i->asi = (w >> 5) & 0xFF;
33574a4d8c2SCharles.Forsyth i->rs2 = (w >> 0) & 0x1F;
33674a4d8c2SCharles.Forsyth i->simm13 = (w >> 0) & 0x1FFF;
33774a4d8c2SCharles.Forsyth if(i->simm13 & (1<<12))
33874a4d8c2SCharles.Forsyth i->simm13 |= ~((1<<13)-1);
33974a4d8c2SCharles.Forsyth i->opf = (w >> 5) & 0x1FF;
34074a4d8c2SCharles.Forsyth i->immdisp22 = (w >> 0) & 0x3FFFFF;
34174a4d8c2SCharles.Forsyth i->simmdisp22 = i->immdisp22;
34274a4d8c2SCharles.Forsyth if(i->simmdisp22 & (1<<21))
34374a4d8c2SCharles.Forsyth i->simmdisp22 |= ~((1<<22)-1);
34474a4d8c2SCharles.Forsyth i->disp30 = (w >> 0) & 0x3FFFFFFF;
34574a4d8c2SCharles.Forsyth i->w0 = w;
34674a4d8c2SCharles.Forsyth i->target = -1;
34774a4d8c2SCharles.Forsyth i->addr = pc;
34874a4d8c2SCharles.Forsyth i->size = 1;
34974a4d8c2SCharles.Forsyth return 1;
35074a4d8c2SCharles.Forsyth }
35174a4d8c2SCharles.Forsyth
35274a4d8c2SCharles.Forsyth static int
mkinstr(uvlong pc,Instr * i)353d67b7dadSforsyth mkinstr(uvlong pc, Instr *i)
35474a4d8c2SCharles.Forsyth {
35574a4d8c2SCharles.Forsyth Instr xi;
35674a4d8c2SCharles.Forsyth
35774a4d8c2SCharles.Forsyth if (decode(pc, i) < 0)
35874a4d8c2SCharles.Forsyth return -1;
35974a4d8c2SCharles.Forsyth if(i->op==0 && i->op2==4 && !dascase){ /* SETHI */
36074a4d8c2SCharles.Forsyth if (decode(pc+4, &xi) < 0)
36174a4d8c2SCharles.Forsyth return -1;
36274a4d8c2SCharles.Forsyth if(xi.op==2 && xi.op3==0) /* ADD */
36374a4d8c2SCharles.Forsyth if(xi.i == 1 && xi.rs1 == i->rd){ /* immediate to same reg */
36474a4d8c2SCharles.Forsyth i->imm32 = xi.simm13 + (i->immdisp22<<10);
36574a4d8c2SCharles.Forsyth i->target = xi.rd;
36674a4d8c2SCharles.Forsyth i->w1 = xi.w0;
36774a4d8c2SCharles.Forsyth i->size++;
36874a4d8c2SCharles.Forsyth return 1;
36974a4d8c2SCharles.Forsyth }
37074a4d8c2SCharles.Forsyth }
37174a4d8c2SCharles.Forsyth if(i->op==2 && i->opf==1 && !dascase){ /* FMOVS */
37274a4d8c2SCharles.Forsyth if (decode(pc+4, &xi) < 0)
37374a4d8c2SCharles.Forsyth return -1;
37474a4d8c2SCharles.Forsyth if(i->op==2 && i->opf==1) /* FMOVS */
37574a4d8c2SCharles.Forsyth if(xi.rd==i->rd+1 && xi.rs2==i->rs2+1){ /* next pair */
37674a4d8c2SCharles.Forsyth i->w1 = xi.w0;
37774a4d8c2SCharles.Forsyth i->size++;
37874a4d8c2SCharles.Forsyth }
37974a4d8c2SCharles.Forsyth }
38074a4d8c2SCharles.Forsyth return 1;
38174a4d8c2SCharles.Forsyth }
38274a4d8c2SCharles.Forsyth
38374a4d8c2SCharles.Forsyth static int
printins(Map * map,uvlong pc,char * buf,int n)384d67b7dadSforsyth printins(Map *map, uvlong pc, char *buf, int n)
38574a4d8c2SCharles.Forsyth {
38674a4d8c2SCharles.Forsyth Instr instr;
38774a4d8c2SCharles.Forsyth void (*f)(Instr*, char*);
38874a4d8c2SCharles.Forsyth
38974a4d8c2SCharles.Forsyth mymap = map;
39074a4d8c2SCharles.Forsyth memset(&instr, 0, sizeof(instr));
39174a4d8c2SCharles.Forsyth instr.curr = buf;
39274a4d8c2SCharles.Forsyth instr.end = buf+n-1;
39374a4d8c2SCharles.Forsyth if (mkinstr(pc, &instr) < 0)
39474a4d8c2SCharles.Forsyth return -1;
39574a4d8c2SCharles.Forsyth switch(instr.op){
39674a4d8c2SCharles.Forsyth case 0:
39774a4d8c2SCharles.Forsyth f = sparcop0[instr.op2].f;
39874a4d8c2SCharles.Forsyth if(f)
39974a4d8c2SCharles.Forsyth (*f)(&instr, sparcop0[instr.op2].mnemonic);
40074a4d8c2SCharles.Forsyth else
40174a4d8c2SCharles.Forsyth bprint(&instr, "unknown %lux", instr.w0);
40274a4d8c2SCharles.Forsyth break;
40374a4d8c2SCharles.Forsyth
40474a4d8c2SCharles.Forsyth case 1:
405d67b7dadSforsyth bprint(&instr, "%T", "CALL\t");
40674a4d8c2SCharles.Forsyth instr.curr += symoff(instr.curr, instr.end-instr.curr,
40774a4d8c2SCharles.Forsyth pc+instr.disp30*4, CTEXT);
40874a4d8c2SCharles.Forsyth if (!dascase)
40974a4d8c2SCharles.Forsyth bprint(&instr, "(SB)");
41074a4d8c2SCharles.Forsyth break;
41174a4d8c2SCharles.Forsyth
41274a4d8c2SCharles.Forsyth case 2:
41374a4d8c2SCharles.Forsyth f = sparcop2[instr.op3].f;
41474a4d8c2SCharles.Forsyth if(f)
41574a4d8c2SCharles.Forsyth (*f)(&instr, sparcop2[instr.op3].mnemonic);
41674a4d8c2SCharles.Forsyth else
41774a4d8c2SCharles.Forsyth bprint(&instr, "unknown %lux", instr.w0);
41874a4d8c2SCharles.Forsyth break;
41974a4d8c2SCharles.Forsyth
42074a4d8c2SCharles.Forsyth case 3:
42174a4d8c2SCharles.Forsyth f = sparcop3[instr.op3].f;
42274a4d8c2SCharles.Forsyth if(f)
42374a4d8c2SCharles.Forsyth (*f)(&instr, sparcop3[instr.op3].mnemonic);
42474a4d8c2SCharles.Forsyth else
42574a4d8c2SCharles.Forsyth bprint(&instr, "unknown %lux", instr.w0);
42674a4d8c2SCharles.Forsyth break;
42774a4d8c2SCharles.Forsyth }
42874a4d8c2SCharles.Forsyth if (instr.err) {
42974a4d8c2SCharles.Forsyth if (instr.curr != buf)
43074a4d8c2SCharles.Forsyth bprint(&instr, "\t\t;");
43174a4d8c2SCharles.Forsyth bprint(&instr, instr.err);
43274a4d8c2SCharles.Forsyth }
43374a4d8c2SCharles.Forsyth return instr.size*4;
43474a4d8c2SCharles.Forsyth }
43574a4d8c2SCharles.Forsyth
43674a4d8c2SCharles.Forsyth static int
sparcinst(Map * map,uvlong pc,char modifier,char * buf,int n)437d67b7dadSforsyth sparcinst(Map *map, uvlong pc, char modifier, char *buf, int n)
43874a4d8c2SCharles.Forsyth {
43974a4d8c2SCharles.Forsyth static int fmtinstalled = 0;
44074a4d8c2SCharles.Forsyth
44174a4d8c2SCharles.Forsyth /* a modifier of 'I' toggles the dissassembler type */
44274a4d8c2SCharles.Forsyth if (!fmtinstalled) {
44374a4d8c2SCharles.Forsyth fmtinstalled = 1;
444d67b7dadSforsyth fmtinstall('T', Tfmt);
44574a4d8c2SCharles.Forsyth }
44674a4d8c2SCharles.Forsyth if ((asstype == ASUNSPARC && modifier == 'i')
44774a4d8c2SCharles.Forsyth || (asstype == ASPARC && modifier == 'I'))
44874a4d8c2SCharles.Forsyth dascase = 'a'-'A';
44974a4d8c2SCharles.Forsyth else
45074a4d8c2SCharles.Forsyth dascase = 0;
45174a4d8c2SCharles.Forsyth return printins(map, pc, buf, n);
45274a4d8c2SCharles.Forsyth }
45374a4d8c2SCharles.Forsyth
45474a4d8c2SCharles.Forsyth static int
sparcdas(Map * map,uvlong pc,char * buf,int n)455d67b7dadSforsyth sparcdas(Map *map, uvlong pc, char *buf, int n)
45674a4d8c2SCharles.Forsyth {
45774a4d8c2SCharles.Forsyth Instr instr;
45874a4d8c2SCharles.Forsyth
45974a4d8c2SCharles.Forsyth mymap = map;
46074a4d8c2SCharles.Forsyth memset(&instr, 0, sizeof(instr));
46174a4d8c2SCharles.Forsyth instr.curr = buf;
46274a4d8c2SCharles.Forsyth instr.end = buf+n-1;
46374a4d8c2SCharles.Forsyth if (mkinstr(pc, &instr) < 0)
46474a4d8c2SCharles.Forsyth return -1;
46574a4d8c2SCharles.Forsyth if (instr.end-instr.curr > 8)
46674a4d8c2SCharles.Forsyth instr.curr = _hexify(instr.curr, instr.w0, 7);
46774a4d8c2SCharles.Forsyth if (instr.end-instr.curr > 9 && instr.size == 2) {
46874a4d8c2SCharles.Forsyth *instr.curr++ = ' ';
46974a4d8c2SCharles.Forsyth instr.curr = _hexify(instr.curr, instr.w1, 7);
47074a4d8c2SCharles.Forsyth }
47174a4d8c2SCharles.Forsyth *instr.curr = 0;
47274a4d8c2SCharles.Forsyth return instr.size*4;
47374a4d8c2SCharles.Forsyth }
47474a4d8c2SCharles.Forsyth
47574a4d8c2SCharles.Forsyth static int
sparcinstlen(Map * map,uvlong pc)476d67b7dadSforsyth sparcinstlen(Map *map, uvlong pc)
47774a4d8c2SCharles.Forsyth {
47874a4d8c2SCharles.Forsyth Instr i;
47974a4d8c2SCharles.Forsyth
48074a4d8c2SCharles.Forsyth mymap = map;
48174a4d8c2SCharles.Forsyth if (mkinstr(pc, &i) < 0)
48274a4d8c2SCharles.Forsyth return -1;
48374a4d8c2SCharles.Forsyth return i.size*4;
48474a4d8c2SCharles.Forsyth }
48574a4d8c2SCharles.Forsyth
48674a4d8c2SCharles.Forsyth static int
plocal(Instr * i)48774a4d8c2SCharles.Forsyth plocal(Instr *i)
48874a4d8c2SCharles.Forsyth {
48974a4d8c2SCharles.Forsyth int offset;
49074a4d8c2SCharles.Forsyth Symbol s;
49174a4d8c2SCharles.Forsyth
49274a4d8c2SCharles.Forsyth if (!findsym(i->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s))
49374a4d8c2SCharles.Forsyth return -1;
49474a4d8c2SCharles.Forsyth if (s.value > i->simm13) {
49574a4d8c2SCharles.Forsyth if(getauto(&s, s.value-i->simm13, CAUTO, &s)) {
496d67b7dadSforsyth bprint(i, "%s+%lld(SP)", s.name, s.value);
49774a4d8c2SCharles.Forsyth return 1;
49874a4d8c2SCharles.Forsyth }
49974a4d8c2SCharles.Forsyth } else {
50074a4d8c2SCharles.Forsyth offset = i->simm13-s.value;
50174a4d8c2SCharles.Forsyth if (getauto(&s, offset-4, CPARAM, &s)) {
50274a4d8c2SCharles.Forsyth bprint(i, "%s+%d(FP)", s.name, offset);
50374a4d8c2SCharles.Forsyth return 1;
50474a4d8c2SCharles.Forsyth }
50574a4d8c2SCharles.Forsyth }
50674a4d8c2SCharles.Forsyth return -1;
50774a4d8c2SCharles.Forsyth }
50874a4d8c2SCharles.Forsyth
50974a4d8c2SCharles.Forsyth static void
address(Instr * i)51074a4d8c2SCharles.Forsyth address(Instr *i)
51174a4d8c2SCharles.Forsyth {
51274a4d8c2SCharles.Forsyth Symbol s, s2;
513d67b7dadSforsyth uvlong off, off1;
51474a4d8c2SCharles.Forsyth
51574a4d8c2SCharles.Forsyth if (i->rs1 == 1 && plocal(i) >= 0)
51674a4d8c2SCharles.Forsyth return;
51774a4d8c2SCharles.Forsyth off = mach->sb+i->simm13;
51874a4d8c2SCharles.Forsyth if(i->rs1 == 2 && findsym(off, CANY, &s)
51974a4d8c2SCharles.Forsyth && s.value-off < 4096
52074a4d8c2SCharles.Forsyth && (s.class == CDATA || s.class == CTEXT)) {
52174a4d8c2SCharles.Forsyth if(off==s.value && s.name[0]=='$'){
52274a4d8c2SCharles.Forsyth off1 = 0;
523d67b7dadSforsyth geta(mymap, s.value, &off1);
52474a4d8c2SCharles.Forsyth if(off1 && findsym(off1, CANY, &s2) && s2.value == off1){
52574a4d8c2SCharles.Forsyth bprint(i, "$%s(SB)", s2.name);
52674a4d8c2SCharles.Forsyth return;
52774a4d8c2SCharles.Forsyth }
52874a4d8c2SCharles.Forsyth }
52974a4d8c2SCharles.Forsyth bprint(i, "%s", s.name);
53074a4d8c2SCharles.Forsyth if (s.value != off)
531d67b7dadSforsyth bprint(i, "+%llux", s.value-off);
53274a4d8c2SCharles.Forsyth bprint(i, "(SB)");
53374a4d8c2SCharles.Forsyth return;
53474a4d8c2SCharles.Forsyth }
535d67b7dadSforsyth bprint(i, "%ux(R%d)", i->simm13, i->rs1);
53674a4d8c2SCharles.Forsyth }
53774a4d8c2SCharles.Forsyth
53874a4d8c2SCharles.Forsyth static void
unimp(Instr * i,char * m)53974a4d8c2SCharles.Forsyth unimp(Instr *i, char *m)
54074a4d8c2SCharles.Forsyth {
541d67b7dadSforsyth bprint(i, "%T", m);
54274a4d8c2SCharles.Forsyth }
54374a4d8c2SCharles.Forsyth
54474a4d8c2SCharles.Forsyth static char *bratab[16] = { /* page 91 */
545773d7fd2Sforsyth "N", /* 0x0 */
546773d7fd2Sforsyth "E", /* 0x1 */
547773d7fd2Sforsyth "LE", /* 0x2 */
548773d7fd2Sforsyth "L", /* 0x3 */
549773d7fd2Sforsyth "LEU", /* 0x4 */
550773d7fd2Sforsyth "CS", /* 0x5 */
551773d7fd2Sforsyth "NEG", /* 0x6 */
552773d7fd2Sforsyth "VS", /* 0x7 */
553773d7fd2Sforsyth "A", /* 0x8 */
554773d7fd2Sforsyth "NE", /* 0x9 */
555773d7fd2Sforsyth "G", /* 0xa */
556773d7fd2Sforsyth "GE", /* 0xb */
557773d7fd2Sforsyth "GU", /* 0xc */
558773d7fd2Sforsyth "CC", /* 0xd */
559773d7fd2Sforsyth "POS", /* 0xe */
560773d7fd2Sforsyth "VC", /* 0xf */
56174a4d8c2SCharles.Forsyth };
56274a4d8c2SCharles.Forsyth
56374a4d8c2SCharles.Forsyth static char *fbratab[16] = { /* page 91 */
564773d7fd2Sforsyth "N", /* 0x0 */
565773d7fd2Sforsyth "NE", /* 0x1 */
566773d7fd2Sforsyth "LG", /* 0x2 */
567773d7fd2Sforsyth "UL", /* 0x3 */
568773d7fd2Sforsyth "L", /* 0x4 */
569773d7fd2Sforsyth "UG", /* 0x5 */
570773d7fd2Sforsyth "G", /* 0x6 */
571773d7fd2Sforsyth "U", /* 0x7 */
572773d7fd2Sforsyth "A", /* 0x8 */
573773d7fd2Sforsyth "E", /* 0x9 */
574773d7fd2Sforsyth "UE", /* 0xa */
575773d7fd2Sforsyth "GE", /* 0xb */
576773d7fd2Sforsyth "UGE", /* 0xc */
577773d7fd2Sforsyth "LE", /* 0xd */
578773d7fd2Sforsyth "ULE", /* 0xe */
579773d7fd2Sforsyth "O", /* 0xf */
58074a4d8c2SCharles.Forsyth };
58174a4d8c2SCharles.Forsyth
58274a4d8c2SCharles.Forsyth static char *cbratab[16] = { /* page 91 */
583773d7fd2Sforsyth "N", /* 0x0 */
584773d7fd2Sforsyth "123", /* 0x1 */
585773d7fd2Sforsyth "12", /* 0x2 */
586773d7fd2Sforsyth "13", /* 0x3 */
587773d7fd2Sforsyth "1", /* 0x4 */
588773d7fd2Sforsyth "23", /* 0x5 */
589773d7fd2Sforsyth "2", /* 0x6 */
590773d7fd2Sforsyth "3", /* 0x7 */
591773d7fd2Sforsyth "A", /* 0x8 */
592773d7fd2Sforsyth "0", /* 0x9 */
593773d7fd2Sforsyth "03", /* 0xa */
594773d7fd2Sforsyth "02", /* 0xb */
595773d7fd2Sforsyth "023", /* 0xc */
596773d7fd2Sforsyth "01", /* 0xd */
597773d7fd2Sforsyth "013", /* 0xe */
598773d7fd2Sforsyth "012", /* 0xf */
59974a4d8c2SCharles.Forsyth };
60074a4d8c2SCharles.Forsyth
60174a4d8c2SCharles.Forsyth static void
bra1(Instr * i,char * m,char * tab[])60274a4d8c2SCharles.Forsyth bra1(Instr *i, char *m, char *tab[])
60374a4d8c2SCharles.Forsyth {
60474a4d8c2SCharles.Forsyth long imm;
60574a4d8c2SCharles.Forsyth
60674a4d8c2SCharles.Forsyth imm = i->simmdisp22;
60774a4d8c2SCharles.Forsyth if(i->a)
608d67b7dadSforsyth bprint(i, "%T%T.%c\t", m, tab[i->cond], 'A'+dascase);
60974a4d8c2SCharles.Forsyth else
610d67b7dadSforsyth bprint(i, "%T%T\t", m, tab[i->cond]);
61174a4d8c2SCharles.Forsyth i->curr += symoff(i->curr, i->end-i->curr, i->addr+4*imm, CTEXT);
61274a4d8c2SCharles.Forsyth if (!dascase)
61374a4d8c2SCharles.Forsyth bprint(i, "(SB)");
61474a4d8c2SCharles.Forsyth }
61574a4d8c2SCharles.Forsyth
61674a4d8c2SCharles.Forsyth static void
bra(Instr * i,char * m)61774a4d8c2SCharles.Forsyth bra(Instr *i, char *m) /* page 91 */
61874a4d8c2SCharles.Forsyth {
61974a4d8c2SCharles.Forsyth bra1(i, m, bratab);
62074a4d8c2SCharles.Forsyth }
62174a4d8c2SCharles.Forsyth
62274a4d8c2SCharles.Forsyth static void
fbra(Instr * i,char * m)62374a4d8c2SCharles.Forsyth fbra(Instr *i, char *m) /* page 93 */
62474a4d8c2SCharles.Forsyth {
62574a4d8c2SCharles.Forsyth bra1(i, m, fbratab);
62674a4d8c2SCharles.Forsyth }
62774a4d8c2SCharles.Forsyth
62874a4d8c2SCharles.Forsyth static void
cbra(Instr * i,char * m)62974a4d8c2SCharles.Forsyth cbra(Instr *i, char *m) /* page 95 */
63074a4d8c2SCharles.Forsyth {
63174a4d8c2SCharles.Forsyth bra1(i, m, cbratab);
63274a4d8c2SCharles.Forsyth }
63374a4d8c2SCharles.Forsyth
63474a4d8c2SCharles.Forsyth static void
trap(Instr * i,char * m)63574a4d8c2SCharles.Forsyth trap(Instr *i, char *m) /* page 101 */
63674a4d8c2SCharles.Forsyth {
63774a4d8c2SCharles.Forsyth if(i->i == 0)
638d67b7dadSforsyth bprint(i, "%T%T\tR%d+R%d", m, bratab[i->cond], i->rs2, i->rs1);
63974a4d8c2SCharles.Forsyth else
640d67b7dadSforsyth bprint(i, "%T%T\t$%ux+R%d", m, bratab[i->cond], i->simm13, i->rs1);
64174a4d8c2SCharles.Forsyth }
64274a4d8c2SCharles.Forsyth
64374a4d8c2SCharles.Forsyth static void
sethi(Instr * i,char * m)64474a4d8c2SCharles.Forsyth sethi(Instr *i, char *m) /* page 89 */
64574a4d8c2SCharles.Forsyth {
64674a4d8c2SCharles.Forsyth ulong imm;
64774a4d8c2SCharles.Forsyth
64874a4d8c2SCharles.Forsyth imm = i->immdisp22<<10;
64974a4d8c2SCharles.Forsyth if(dascase){
650d67b7dadSforsyth bprint(i, "%T\t%lux, R%d", m, imm, i->rd);
65174a4d8c2SCharles.Forsyth return;
65274a4d8c2SCharles.Forsyth }
65374a4d8c2SCharles.Forsyth if(imm==0 && i->rd==0){
65474a4d8c2SCharles.Forsyth bprint(i, "NOP");
65574a4d8c2SCharles.Forsyth return;
65674a4d8c2SCharles.Forsyth }
65774a4d8c2SCharles.Forsyth if(i->target < 0){
65874a4d8c2SCharles.Forsyth bprint(i, "MOVW\t$%lux, R%d", imm, i->rd);
65974a4d8c2SCharles.Forsyth return;
66074a4d8c2SCharles.Forsyth }
66174a4d8c2SCharles.Forsyth bprint(i, "MOVW\t$%lux, R%d", i->imm32, i->target);
66274a4d8c2SCharles.Forsyth }
66374a4d8c2SCharles.Forsyth
66474a4d8c2SCharles.Forsyth static char ldtab[] = {
66574a4d8c2SCharles.Forsyth 'W',
66674a4d8c2SCharles.Forsyth 'B',
66774a4d8c2SCharles.Forsyth 'H',
66874a4d8c2SCharles.Forsyth 'D',
66974a4d8c2SCharles.Forsyth };
67074a4d8c2SCharles.Forsyth
67174a4d8c2SCharles.Forsyth static char*
moveinstr(int op3,char * m)67274a4d8c2SCharles.Forsyth moveinstr(int op3, char *m)
67374a4d8c2SCharles.Forsyth {
67474a4d8c2SCharles.Forsyth char *s;
67574a4d8c2SCharles.Forsyth int c;
67674a4d8c2SCharles.Forsyth static char buf[8];
67774a4d8c2SCharles.Forsyth
67874a4d8c2SCharles.Forsyth if(!dascase){
67974a4d8c2SCharles.Forsyth /* batshit cases */
68074a4d8c2SCharles.Forsyth if(op3 == 0xF || op3 == 0x1F)
68174a4d8c2SCharles.Forsyth return "SWAP";
68274a4d8c2SCharles.Forsyth if(op3 == 0xD || op3 == 0x1D)
68374a4d8c2SCharles.Forsyth return "TAS"; /* really LDSTUB */
68474a4d8c2SCharles.Forsyth c = ldtab[op3&3];
68574a4d8c2SCharles.Forsyth s = "";
68674a4d8c2SCharles.Forsyth if((op3&11)==1 || (op3&11)==2)
68774a4d8c2SCharles.Forsyth s="U";
68874a4d8c2SCharles.Forsyth sprint(buf, "MOV%c%s", c, s);
68974a4d8c2SCharles.Forsyth return buf;
69074a4d8c2SCharles.Forsyth }
69174a4d8c2SCharles.Forsyth return m;
69274a4d8c2SCharles.Forsyth }
69374a4d8c2SCharles.Forsyth
69474a4d8c2SCharles.Forsyth static void
load(Instr * i,char * m)69574a4d8c2SCharles.Forsyth load(Instr *i, char *m) /* page 68 */
69674a4d8c2SCharles.Forsyth {
69774a4d8c2SCharles.Forsyth m = moveinstr(i->op3, m);
69874a4d8c2SCharles.Forsyth if(i->i == 0)
69974a4d8c2SCharles.Forsyth bprint(i, "%s\t(R%d+R%d), R%d", m, i->rs1, i->rs2, i->rd);
70074a4d8c2SCharles.Forsyth else{
70174a4d8c2SCharles.Forsyth bprint(i, "%s\t", m);
70274a4d8c2SCharles.Forsyth address(i);
70374a4d8c2SCharles.Forsyth bprint(i, ", R%d", i->rd);
70474a4d8c2SCharles.Forsyth }
70574a4d8c2SCharles.Forsyth }
70674a4d8c2SCharles.Forsyth
70774a4d8c2SCharles.Forsyth static void
loada(Instr * i,char * m)70874a4d8c2SCharles.Forsyth loada(Instr *i, char *m) /* page 68 */
70974a4d8c2SCharles.Forsyth {
71074a4d8c2SCharles.Forsyth m = moveinstr(i->op3, m);
71174a4d8c2SCharles.Forsyth if(i->i == 0)
71274a4d8c2SCharles.Forsyth bprint(i, "%s\t(R%d+R%d, %d), R%d", m, i->rs1, i->rs2, i->asi, i->rd);
71374a4d8c2SCharles.Forsyth else
71474a4d8c2SCharles.Forsyth bprint(i, "unknown ld asi %lux", i->w0);
71574a4d8c2SCharles.Forsyth }
71674a4d8c2SCharles.Forsyth
71774a4d8c2SCharles.Forsyth static void
store(Instr * i,char * m)71874a4d8c2SCharles.Forsyth store(Instr *i, char *m) /* page 74 */
71974a4d8c2SCharles.Forsyth {
72074a4d8c2SCharles.Forsyth m = moveinstr(i->op3, m);
72174a4d8c2SCharles.Forsyth if(i->i == 0)
72274a4d8c2SCharles.Forsyth bprint(i, "%s\tR%d, (R%d+R%d)",
72374a4d8c2SCharles.Forsyth m, i->rd, i->rs1, i->rs2);
72474a4d8c2SCharles.Forsyth else{
72574a4d8c2SCharles.Forsyth bprint(i, "%s\tR%d, ", m, i->rd);
72674a4d8c2SCharles.Forsyth address(i);
72774a4d8c2SCharles.Forsyth }
72874a4d8c2SCharles.Forsyth }
72974a4d8c2SCharles.Forsyth
73074a4d8c2SCharles.Forsyth static void
storea(Instr * i,char * m)73174a4d8c2SCharles.Forsyth storea(Instr *i, char *m) /* page 74 */
73274a4d8c2SCharles.Forsyth {
73374a4d8c2SCharles.Forsyth m = moveinstr(i->op3, m);
73474a4d8c2SCharles.Forsyth if(i->i == 0)
73574a4d8c2SCharles.Forsyth bprint(i, "%s\tR%d, (R%d+R%d, %d)", m, i->rd, i->rs1, i->rs2, i->asi);
73674a4d8c2SCharles.Forsyth else
737*45a20ab7Sforsyth bprint(i, "%s\tR%d, %d(R%d, %d), ?", m, i->rd, i->simm13, i->rs1, i->asi);
73874a4d8c2SCharles.Forsyth }
73974a4d8c2SCharles.Forsyth
74074a4d8c2SCharles.Forsyth static void
shift(Instr * i,char * m)74174a4d8c2SCharles.Forsyth shift(Instr *i, char *m) /* page 88 */
74274a4d8c2SCharles.Forsyth {
74374a4d8c2SCharles.Forsyth if(i->i == 0){
74474a4d8c2SCharles.Forsyth if(i->rs1 == i->rd)
74574a4d8c2SCharles.Forsyth if(dascase)
746d67b7dadSforsyth bprint(i, "%T\tR%d, R%d", m, i->rs1, i->rs2);
74774a4d8c2SCharles.Forsyth else
748d67b7dadSforsyth bprint(i, "%T\tR%d, R%d", m, i->rs2, i->rs1);
74974a4d8c2SCharles.Forsyth else
75074a4d8c2SCharles.Forsyth if(dascase)
751d67b7dadSforsyth bprint(i, "%T\tR%d, R%d, R%d", m, i->rs1, i->rs2, i->rd);
75274a4d8c2SCharles.Forsyth else
753d67b7dadSforsyth bprint(i, "%T\tR%d, R%d, R%d", m, i->rs2, i->rs1, i->rd);
75474a4d8c2SCharles.Forsyth }else{
75574a4d8c2SCharles.Forsyth if(i->rs1 == i->rd)
75674a4d8c2SCharles.Forsyth if(dascase)
757d67b7dadSforsyth bprint(i, "%T\t$%d,R%d", m, i->simm13&0x1F, i->rs1);
75874a4d8c2SCharles.Forsyth else
759d67b7dadSforsyth bprint(i, "%T\tR%d, $%d", m, i->rs1, i->simm13&0x1F);
76074a4d8c2SCharles.Forsyth else
76174a4d8c2SCharles.Forsyth if(dascase)
762d67b7dadSforsyth bprint(i, "%T\tR%d, $%d, R%d",m,i->rs1,i->simm13&0x1F,i->rd);
76374a4d8c2SCharles.Forsyth else
764d67b7dadSforsyth bprint(i, "%T\t$%d, R%d, R%d",m,i->simm13&0x1F,i->rs1,i->rd);
76574a4d8c2SCharles.Forsyth }
76674a4d8c2SCharles.Forsyth }
76774a4d8c2SCharles.Forsyth
76874a4d8c2SCharles.Forsyth static void
add(Instr * i,char * m)76974a4d8c2SCharles.Forsyth add(Instr *i, char *m) /* page 82 */
77074a4d8c2SCharles.Forsyth {
77174a4d8c2SCharles.Forsyth if(i->i == 0){
77274a4d8c2SCharles.Forsyth if(dascase)
773d67b7dadSforsyth bprint(i, "%T\tR%d, R%d", m, i->rs1, i->rs2);
77474a4d8c2SCharles.Forsyth else
77574a4d8c2SCharles.Forsyth if(i->op3==2 && i->rs1==0 && i->rd) /* OR R2, R0, R1 */
77674a4d8c2SCharles.Forsyth bprint(i, "MOVW\tR%d", i->rs2);
77774a4d8c2SCharles.Forsyth else
778d67b7dadSforsyth bprint(i, "%T\tR%d, R%d", m, i->rs2, i->rs1);
77974a4d8c2SCharles.Forsyth }else{
78074a4d8c2SCharles.Forsyth if(dascase)
781d67b7dadSforsyth bprint(i, "%T\tR%d, $%ux", m, i->rs1, i->simm13);
78274a4d8c2SCharles.Forsyth else
78374a4d8c2SCharles.Forsyth if(i->op3==0 && i->rd && i->rs1==0) /* ADD $x, R0, R1 */
784d67b7dadSforsyth bprint(i, "MOVW\t$%ux", i->simm13);
78574a4d8c2SCharles.Forsyth else if(i->op3==0 && i->rd && i->rs1==2){
78674a4d8c2SCharles.Forsyth /* ADD $x, R2, R1 -> MOVW $x(SB), R1 */
78774a4d8c2SCharles.Forsyth bprint(i, "MOVW\t$");
78874a4d8c2SCharles.Forsyth address(i);
78974a4d8c2SCharles.Forsyth } else
790d67b7dadSforsyth bprint(i, "%T\t$%ux, R%d", m, i->simm13, i->rs1);
79174a4d8c2SCharles.Forsyth }
79274a4d8c2SCharles.Forsyth if(i->rs1 != i->rd)
79374a4d8c2SCharles.Forsyth bprint(i, ", R%d", i->rd);
79474a4d8c2SCharles.Forsyth }
79574a4d8c2SCharles.Forsyth
79674a4d8c2SCharles.Forsyth static void
cmp(Instr * i,char * m)79774a4d8c2SCharles.Forsyth cmp(Instr *i, char *m)
79874a4d8c2SCharles.Forsyth {
79974a4d8c2SCharles.Forsyth if(dascase || i->rd){
80074a4d8c2SCharles.Forsyth add(i, m);
80174a4d8c2SCharles.Forsyth return;
80274a4d8c2SCharles.Forsyth }
80374a4d8c2SCharles.Forsyth if(i->i == 0)
80474a4d8c2SCharles.Forsyth bprint(i, "CMP\tR%d, R%d", i->rs1, i->rs2);
80574a4d8c2SCharles.Forsyth else
806d67b7dadSforsyth bprint(i, "CMP\tR%d, $%ux", i->rs1, i->simm13);
80774a4d8c2SCharles.Forsyth }
80874a4d8c2SCharles.Forsyth
80974a4d8c2SCharles.Forsyth static char *regtab[4] = {
81074a4d8c2SCharles.Forsyth "Y",
81174a4d8c2SCharles.Forsyth "PSR",
81274a4d8c2SCharles.Forsyth "WIM",
81374a4d8c2SCharles.Forsyth "TBR",
81474a4d8c2SCharles.Forsyth };
81574a4d8c2SCharles.Forsyth
81674a4d8c2SCharles.Forsyth static void
wr(Instr * i,char * m)81774a4d8c2SCharles.Forsyth wr(Instr *i, char *m) /* page 82 */
81874a4d8c2SCharles.Forsyth {
81974a4d8c2SCharles.Forsyth if(dascase){
82074a4d8c2SCharles.Forsyth if(i->i == 0)
82174a4d8c2SCharles.Forsyth bprint(i, "%s\tR%d, R%d", m, i->rs1, i->rs2);
82274a4d8c2SCharles.Forsyth else
823d67b7dadSforsyth bprint(i, "%s\tR%d, $%ux", m, i->rs1, i->simm13);
82474a4d8c2SCharles.Forsyth }else{
82574a4d8c2SCharles.Forsyth if(i->i && i->simm13==0)
82674a4d8c2SCharles.Forsyth bprint(i, "MOVW\tR%d", i->rs1);
82774a4d8c2SCharles.Forsyth else if(i->i == 0)
82874a4d8c2SCharles.Forsyth bprint(i, "wr\tR%d, R%d", i->rs2, i->rs1);
82974a4d8c2SCharles.Forsyth else
830d67b7dadSforsyth bprint(i, "wr\t$%ux, R%d", i->simm13, i->rs1);
83174a4d8c2SCharles.Forsyth }
83274a4d8c2SCharles.Forsyth bprint(i, ", %s", regtab[i->op3&3]);
83374a4d8c2SCharles.Forsyth }
83474a4d8c2SCharles.Forsyth
83574a4d8c2SCharles.Forsyth static void
rd(Instr * i,char * m)83674a4d8c2SCharles.Forsyth rd(Instr *i, char *m) /* page 103 */
83774a4d8c2SCharles.Forsyth {
83874a4d8c2SCharles.Forsyth if(i->rs1==15 && i->rd==0){
83974a4d8c2SCharles.Forsyth m = "stbar";
84074a4d8c2SCharles.Forsyth if(!dascase)
84174a4d8c2SCharles.Forsyth m = "STBAR";
84274a4d8c2SCharles.Forsyth bprint(i, "%s", m);
84374a4d8c2SCharles.Forsyth }else{
84474a4d8c2SCharles.Forsyth if(!dascase)
84574a4d8c2SCharles.Forsyth m = "MOVW";
84674a4d8c2SCharles.Forsyth bprint(i, "%s\t%s, R%d", m, regtab[i->op3&3], i->rd);
84774a4d8c2SCharles.Forsyth }
84874a4d8c2SCharles.Forsyth }
84974a4d8c2SCharles.Forsyth
85074a4d8c2SCharles.Forsyth static void
jmpl(Instr * i,char * m)85174a4d8c2SCharles.Forsyth jmpl(Instr *i, char *m) /* page 82 */
85274a4d8c2SCharles.Forsyth {
85374a4d8c2SCharles.Forsyth if(i->i == 0){
85474a4d8c2SCharles.Forsyth if(i->rd == 15)
855d67b7dadSforsyth bprint(i, "%T\t(R%d+R%d)", "CALL", i->rs2, i->rs1);
85674a4d8c2SCharles.Forsyth else
857d67b7dadSforsyth bprint(i, "%T\t(R%d+R%d), R%d", m, i->rs2, i->rs1, i->rd);
85874a4d8c2SCharles.Forsyth }else{
85974a4d8c2SCharles.Forsyth if(!dascase && i->simm13==8 && i->rs1==15 && i->rd==0)
86074a4d8c2SCharles.Forsyth bprint(i, "RETURN");
86174a4d8c2SCharles.Forsyth else{
862d67b7dadSforsyth bprint(i, "%T\t", m);
86374a4d8c2SCharles.Forsyth address(i);
86474a4d8c2SCharles.Forsyth bprint(i, ", R%d", i->rd);
86574a4d8c2SCharles.Forsyth }
86674a4d8c2SCharles.Forsyth }
86774a4d8c2SCharles.Forsyth }
86874a4d8c2SCharles.Forsyth
86974a4d8c2SCharles.Forsyth static void
loadf(Instr * i,char * m)87074a4d8c2SCharles.Forsyth loadf(Instr *i, char *m) /* page 70 */
87174a4d8c2SCharles.Forsyth {
87274a4d8c2SCharles.Forsyth if(!dascase){
87374a4d8c2SCharles.Forsyth m = "FMOVD";
87474a4d8c2SCharles.Forsyth if(i->op3 == 0x20)
87574a4d8c2SCharles.Forsyth m = "FMOVF";
87674a4d8c2SCharles.Forsyth else if(i->op3 == 0x21)
87774a4d8c2SCharles.Forsyth m = "MOVW";
87874a4d8c2SCharles.Forsyth }
87974a4d8c2SCharles.Forsyth if(i->i == 0)
88074a4d8c2SCharles.Forsyth bprint(i, "%s\t(R%d+R%d)", m, i->rs1, i->rs2);
88174a4d8c2SCharles.Forsyth else{
88274a4d8c2SCharles.Forsyth bprint(i, "%s\t", m);
88374a4d8c2SCharles.Forsyth address(i);
88474a4d8c2SCharles.Forsyth }
88574a4d8c2SCharles.Forsyth if(i->op3 == 0x21)
88674a4d8c2SCharles.Forsyth bprint(i, ", FSR");
88774a4d8c2SCharles.Forsyth else
88874a4d8c2SCharles.Forsyth bprint(i, ", R%d", i->rd);
88974a4d8c2SCharles.Forsyth }
89074a4d8c2SCharles.Forsyth
891d67b7dadSforsyth static void
storef(Instr * i,char * m)892d67b7dadSforsyth storef(Instr *i, char *m) /* page 70 */
89374a4d8c2SCharles.Forsyth {
89474a4d8c2SCharles.Forsyth if(!dascase){
89574a4d8c2SCharles.Forsyth m = "FMOVD";
89674a4d8c2SCharles.Forsyth if(i->op3 == 0x25 || i->op3 == 0x26)
89774a4d8c2SCharles.Forsyth m = "MOVW";
89874a4d8c2SCharles.Forsyth else if(i->op3 == 0x20)
89974a4d8c2SCharles.Forsyth m = "FMOVF";
90074a4d8c2SCharles.Forsyth }
90174a4d8c2SCharles.Forsyth bprint(i, "%s\t", m);
90274a4d8c2SCharles.Forsyth if(i->op3 == 0x25)
90374a4d8c2SCharles.Forsyth bprint(i, "FSR, ");
90474a4d8c2SCharles.Forsyth else if(i->op3 == 0x26)
90574a4d8c2SCharles.Forsyth bprint(i, "FQ, ");
90674a4d8c2SCharles.Forsyth else
90774a4d8c2SCharles.Forsyth bprint(i, "R%d, ", i->rd);
90874a4d8c2SCharles.Forsyth if(i->i == 0)
90974a4d8c2SCharles.Forsyth bprint(i, "(R%d+R%d)", i->rs1, i->rs2);
91074a4d8c2SCharles.Forsyth else
91174a4d8c2SCharles.Forsyth address(i);
91274a4d8c2SCharles.Forsyth }
91374a4d8c2SCharles.Forsyth
914d67b7dadSforsyth static void
loadc(Instr * i,char * m)915d67b7dadSforsyth loadc(Instr *i, char *m) /* page 72 */
91674a4d8c2SCharles.Forsyth {
91774a4d8c2SCharles.Forsyth if(i->i == 0)
91874a4d8c2SCharles.Forsyth bprint(i, "%s\t(R%d+R%d), C%d", m, i->rs1, i->rs2, i->rd);
91974a4d8c2SCharles.Forsyth else{
92074a4d8c2SCharles.Forsyth bprint(i, "%s\t", m);
92174a4d8c2SCharles.Forsyth address(i);
92274a4d8c2SCharles.Forsyth bprint(i, ", C%d", i->rd);
92374a4d8c2SCharles.Forsyth }
92474a4d8c2SCharles.Forsyth }
92574a4d8c2SCharles.Forsyth
926d67b7dadSforsyth static void
loadcsr(Instr * i,char * m)927d67b7dadSforsyth loadcsr(Instr *i, char *m) /* page 72 */
92874a4d8c2SCharles.Forsyth {
92974a4d8c2SCharles.Forsyth if(i->i == 0)
93074a4d8c2SCharles.Forsyth bprint(i, "%s\t(R%d+R%d), CSR", m, i->rs1, i->rs2);
93174a4d8c2SCharles.Forsyth else{
93274a4d8c2SCharles.Forsyth bprint(i, "%s\t", m);
93374a4d8c2SCharles.Forsyth address(i);
93474a4d8c2SCharles.Forsyth bprint(i, ", CSR");
93574a4d8c2SCharles.Forsyth }
93674a4d8c2SCharles.Forsyth }
93774a4d8c2SCharles.Forsyth
93874a4d8c2SCharles.Forsyth static struct{
93974a4d8c2SCharles.Forsyth int opf;
94074a4d8c2SCharles.Forsyth char *name;
94174a4d8c2SCharles.Forsyth } fptab1[] = { /* ignores rs1 */
94274a4d8c2SCharles.Forsyth 0xC4, "FITOS", /* page 109 */
94374a4d8c2SCharles.Forsyth 0xC8, "FITOD",
94474a4d8c2SCharles.Forsyth 0xCC, "FITOX",
94574a4d8c2SCharles.Forsyth
94674a4d8c2SCharles.Forsyth 0xD1, "FSTOI", /* page 110 */
94774a4d8c2SCharles.Forsyth 0xD2, "FDTOI",
94874a4d8c2SCharles.Forsyth 0xD3, "FXTOI",
94974a4d8c2SCharles.Forsyth
95074a4d8c2SCharles.Forsyth 0xC9, "FSTOD", /* page 111 */
95174a4d8c2SCharles.Forsyth 0xCD, "FSTOX",
95274a4d8c2SCharles.Forsyth 0xC6, "FDTOS",
95374a4d8c2SCharles.Forsyth 0xCE, "FDTOX",
95474a4d8c2SCharles.Forsyth 0xC7, "FXTOS",
95574a4d8c2SCharles.Forsyth 0xCB, "FXTOD",
95674a4d8c2SCharles.Forsyth
95774a4d8c2SCharles.Forsyth 0x01, "FMOVS", /* page 112 */
95874a4d8c2SCharles.Forsyth 0x05, "FNEGS",
95974a4d8c2SCharles.Forsyth 0x09, "FABSS",
96074a4d8c2SCharles.Forsyth
96174a4d8c2SCharles.Forsyth 0x29, "FSQRTS", /* page 113 */
96274a4d8c2SCharles.Forsyth 0x2A, "FSQRTD",
96374a4d8c2SCharles.Forsyth 0x2B, "FSQRTX",
96474a4d8c2SCharles.Forsyth
96574a4d8c2SCharles.Forsyth 0, 0,
96674a4d8c2SCharles.Forsyth };
96774a4d8c2SCharles.Forsyth
96874a4d8c2SCharles.Forsyth static struct{
96974a4d8c2SCharles.Forsyth int opf;
97074a4d8c2SCharles.Forsyth char *name;
97174a4d8c2SCharles.Forsyth } fptab2[] = { /* uses rs1 */
97274a4d8c2SCharles.Forsyth
97374a4d8c2SCharles.Forsyth 0x41, "FADDS", /* page 114 */
97474a4d8c2SCharles.Forsyth 0x42, "FADDD",
97574a4d8c2SCharles.Forsyth 0x43, "FADDX",
97674a4d8c2SCharles.Forsyth 0x45, "FSUBS",
97774a4d8c2SCharles.Forsyth 0x46, "FSUBD",
97874a4d8c2SCharles.Forsyth 0x47, "FSUBX",
97974a4d8c2SCharles.Forsyth
98074a4d8c2SCharles.Forsyth 0x49, "FMULS", /* page 115 */
98174a4d8c2SCharles.Forsyth 0x4A, "FMULD",
98274a4d8c2SCharles.Forsyth 0x4B, "FMULX",
98374a4d8c2SCharles.Forsyth 0x4D, "FDIVS",
98474a4d8c2SCharles.Forsyth 0x4E, "FDIVD",
98574a4d8c2SCharles.Forsyth 0x4F, "FDIVX",
98674a4d8c2SCharles.Forsyth
98774a4d8c2SCharles.Forsyth 0x51, "FCMPS", /* page 116 */
98874a4d8c2SCharles.Forsyth 0x52, "FCMPD",
98974a4d8c2SCharles.Forsyth 0x53, "FCMPX",
99074a4d8c2SCharles.Forsyth 0x55, "FCMPES",
99174a4d8c2SCharles.Forsyth 0x56, "FCMPED",
99274a4d8c2SCharles.Forsyth 0x57, "FCMPEX",
99374a4d8c2SCharles.Forsyth
99474a4d8c2SCharles.Forsyth 0, 0
99574a4d8c2SCharles.Forsyth };
99674a4d8c2SCharles.Forsyth
99774a4d8c2SCharles.Forsyth static void
fpop(Instr * i,char * m)99874a4d8c2SCharles.Forsyth fpop(Instr *i, char *m) /* page 108-116 */
99974a4d8c2SCharles.Forsyth {
100074a4d8c2SCharles.Forsyth int j;
100174a4d8c2SCharles.Forsyth
100274a4d8c2SCharles.Forsyth if(dascase==0 && i->size==2){
100374a4d8c2SCharles.Forsyth bprint(i, "FMOVD\tF%d, F%d", i->rs2, i->rd);
100474a4d8c2SCharles.Forsyth return;
100574a4d8c2SCharles.Forsyth }
100674a4d8c2SCharles.Forsyth for(j=0; fptab1[j].name; j++)
100774a4d8c2SCharles.Forsyth if(fptab1[j].opf == i->opf){
1008d67b7dadSforsyth bprint(i, "%T\tF%d, F%d", fptab1[j].name, i->rs2, i->rd);
100974a4d8c2SCharles.Forsyth return;
101074a4d8c2SCharles.Forsyth }
101174a4d8c2SCharles.Forsyth for(j=0; fptab2[j].name; j++)
101274a4d8c2SCharles.Forsyth if(fptab2[j].opf == i->opf){
1013d67b7dadSforsyth bprint(i, "%T\tF%d, F%d, F%d", fptab2[j].name, i->rs1, i->rs2, i->rd);
101474a4d8c2SCharles.Forsyth return;
101574a4d8c2SCharles.Forsyth }
1016d67b7dadSforsyth bprint(i, "%T%ux\tF%d, F%d, F%d", m, i->opf, i->rs1, i->rs2, i->rd);
101774a4d8c2SCharles.Forsyth }
101874a4d8c2SCharles.Forsyth
101974a4d8c2SCharles.Forsyth static int
sparcfoll(Map * map,uvlong pc,Rgetter rget,uvlong * foll)1020d67b7dadSforsyth sparcfoll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
102174a4d8c2SCharles.Forsyth {
102274a4d8c2SCharles.Forsyth ulong w, r1, r2;
102374a4d8c2SCharles.Forsyth char buf[8];
102474a4d8c2SCharles.Forsyth Instr i;
102574a4d8c2SCharles.Forsyth
102674a4d8c2SCharles.Forsyth mymap = map;
102774a4d8c2SCharles.Forsyth if (mkinstr(pc, &i) < 0)
102874a4d8c2SCharles.Forsyth return -1;
102974a4d8c2SCharles.Forsyth w = i.w0;
103074a4d8c2SCharles.Forsyth switch(w & 0xC1C00000){
103174a4d8c2SCharles.Forsyth case 0x00800000: /* branch on int cond */
103274a4d8c2SCharles.Forsyth case 0x01800000: /* branch on fp cond */
103374a4d8c2SCharles.Forsyth case 0x01C00000: /* branch on copr cond */
103474a4d8c2SCharles.Forsyth foll[0] = pc+8;
103574a4d8c2SCharles.Forsyth foll[1] = pc + (i.simmdisp22<<2);
103674a4d8c2SCharles.Forsyth return 2;
103774a4d8c2SCharles.Forsyth }
103874a4d8c2SCharles.Forsyth
103974a4d8c2SCharles.Forsyth if((w&0xC0000000) == 0x40000000){ /* CALL */
104074a4d8c2SCharles.Forsyth foll[0] = pc + (i.disp30<<2);
104174a4d8c2SCharles.Forsyth return 1;
104274a4d8c2SCharles.Forsyth }
104374a4d8c2SCharles.Forsyth
104474a4d8c2SCharles.Forsyth if((w&0xC1F80000) == 0x81C00000){ /* JMPL */
104574a4d8c2SCharles.Forsyth sprint(buf, "R%ld", (w>>14)&0xF);
104674a4d8c2SCharles.Forsyth r1 = (*rget)(map, buf);
104774a4d8c2SCharles.Forsyth if(w & 0x2000) /* JMPL R1+simm13 */
104874a4d8c2SCharles.Forsyth r2 = i.simm13;
104974a4d8c2SCharles.Forsyth else{ /* JMPL R1+R2 */
105074a4d8c2SCharles.Forsyth sprint(buf, "R%ld", w&0xF);
105174a4d8c2SCharles.Forsyth r2 = (*rget)(map, buf);
105274a4d8c2SCharles.Forsyth }
105374a4d8c2SCharles.Forsyth foll[0] = r1 + r2;
105474a4d8c2SCharles.Forsyth return 1;
105574a4d8c2SCharles.Forsyth }
105674a4d8c2SCharles.Forsyth foll[0] = pc+i.size*4;
105774a4d8c2SCharles.Forsyth return 1;
105874a4d8c2SCharles.Forsyth }
1059