1 #include <lib9.h>
2
3 /* Sparc disassembler and related functions */
4
5 typedef struct instr Instr;
6
7 struct opcode
8 {
9 char *mnemonic;
10 void (*f)(Instr*, char*);
11 int flag;
12 };
13
14 static char FRAMENAME[] = ".frame";
15
16
17 struct instr
18 {
19 uchar op; /* bits 31-30 */
20 uchar rd; /* bits 29-25 */
21 uchar op2; /* bits 24-22 */
22 uchar a; /* bit 29 */
23 uchar cond; /* bits 28-25 */
24 uchar op3; /* bits 24-19 */
25 uchar rs1; /* bits 18-14 */
26 uchar i; /* bit 13 */
27 uchar asi; /* bits 12-05 */
28 uchar rs2; /* bits 04-00 */
29 short simm13; /* bits 12-00, signed */
30 ushort opf; /* bits 13-05 */
31 ulong immdisp22; /* bits 21-00 */
32 ulong simmdisp22; /* bits 21-00, signed */
33 ulong disp30; /* bits 30-00 */
34 ulong imm32; /* SETHI+ADD constant */
35 int target; /* SETHI+ADD dest reg */
36 long w0;
37 long w1;
38 ulong addr; /* pc of instruction */
39 char* curr; /* current fill level in output buffer */
40 char* end; /* end of buffer */
41 int size; /* number of longs in instr */
42 char* err; /* errmsg */
43 };
44
45 static int dascase;
46
47 static int mkinstr(ulong*, Instr*);
48 static void bra1(Instr*, char*, char*[]);
49 static void bra(Instr*, char*);
50 static void fbra(Instr*, char*);
51 static void cbra(Instr*, char*);
52 static void unimp(Instr*, char*);
53 static void fpop(Instr*, char*);
54 static void shift(Instr*, char*);
55 static void sethi(Instr*, char*);
56 static void load(Instr*, char*);
57 static void loada(Instr*, char*);
58 static void store(Instr*, char*);
59 static void storea(Instr*, char*);
60 static void add(Instr*, char*);
61 static void cmp(Instr*, char*);
62 static void wr(Instr*, char*);
63 static void jmpl(Instr*, char*);
64 static void rd(Instr*, char*);
65 static void loadf(Instr*, char*);
66 static void storef(Instr*, char*);
67 static void loadc(Instr*, char*);
68 static void loadcsr(Instr*, char*);
69 static void trap(Instr*, char*);
70
71 static struct opcode sparcop0[8] = {
72 /* [0] */ "UNIMP", unimp, 0, /* page 137 */
73 0, 0, 0,
74 /* [2] */ "B", bra, 0, /* page 119 */
75 0, 0, 0,
76 /* [4] */ "SETHI", sethi, 0, /* page 104 */
77 0, 0, 0,
78 /* [6] */ "FB", fbra, 0, /* page 121 */
79 /* [7] */ "CB", cbra, 0, /* page 123 */
80 };
81
82 static struct opcode sparcop2[64] = {
83 /* [0x00] */ "ADD", add, 0, /* page 108 */
84 /* [0x01] */ "AND", add, 0, /* page 106 */
85 /* [0x02] */ "OR", add, 0,
86 /* [0x03] */ "XOR", add, 0,
87 /* [0x04] */ "SUB", add, 0, /* page 110 */
88 /* [0x05] */ "ANDN", add, 0,
89 /* [0x06] */ "ORN", add, 0,
90 /* [0x07] */ "XORN", add, 0,
91 /* [0x08] */ "ADDX", add, 0,
92 0, 0, 0,
93 /* [0x0A] */ "UMUL", add, 0, /* page 113 */
94 /* [0x0B] */ "SMUL", add, 0,
95 /* [0x0C] */ "SUBX", add, 0,
96 0, 0, 0,
97 /* [0x0E] */ "UDIV", add, 0, /* page 115 */
98 /* [0x0F] */ "SDIV", add, 0,
99 /* [0x10] */ "ADDCC", add, 0,
100 /* [0x11] */ "ANDCC", add, 0,
101 /* [0x12] */ "ORCC", add, 0,
102 /* [0x13] */ "XORCC", add, 0,
103 /* [0x14] */ "SUBCC", cmp, 0,
104 /* [0x15] */ "ANDNCC", add, 0,
105 /* [0x16] */ "ORNCC", add, 0,
106 /* [0x17] */ "XORNCC", add, 0,
107 /* [0x18] */ "ADDXCC", add, 0,
108 0, 0, 0,
109 /* [0x1A] */ "UMULCC", add, 0,
110 /* [0x1B] */ "SMULCC", add, 0,
111 /* [0x1C] */ "SUBXCC", add, 0,
112 0, 0, 0,
113 /* [0x1E] */ "UDIVCC", add, 0,
114 /* [0x1F] */ "SDIVCC", add, 0,
115 /* [0x20] */ "TADD", add, 0, /* page 109 */
116 /* [0x21] */ "TSUB", add, 0, /* page 111 */
117 /* [0x22] */ "TADDCCTV", add, 0,
118 /* [0x23] */ "TSUBCCTV", add, 0,
119 /* [0x24] */ "MULSCC", add, 0, /* page 112 */
120 /* [0x25] */ "SLL", shift, 0, /* page 107 */
121 /* [0x26] */ "SRL", shift, 0,
122 /* [0x27] */ "SRA", shift, 0,
123 /* [0x28] */ "rdy", rd, 0, /* page 131 */
124 /* [0x29] */ "rdpsr", rd, 0,
125 /* [0x2A] */ "rdwim", rd, 0,
126 /* [0x2B] */ "rdtbr", rd, 0,
127 0, 0, 0,
128 0, 0, 0,
129 0, 0, 0,
130 0, 0, 0,
131 /* [0x30] */ "wry", wr, 0, /* page 133 */
132 /* [0x31] */ "wrpsr", wr, 0,
133 /* [0x32] */ "wrwim", wr, 0,
134 /* [0x33] */ "wrtbr", wr, 0,
135 /* [0x34] */ "FPOP", fpop, 0, /* page 140 */
136 /* [0x35] */ "FPOP", fpop, 0,
137 0, 0, 0,
138 0, 0, 0,
139 /* [0x38] */ "JMPL", jmpl, 0, /* page 126 */
140 /* [0x39] */ "RETT", add, 0, /* page 127 */
141 /* [0x3A] */ "T", trap, 0, /* page 129 */
142 /* [0x3B] */ "flush", add, 0, /* page 138 */
143 /* [0x3C] */ "SAVE", add, 0, /* page 117 */
144 /* [0x3D] */ "RESTORE", add, 0,
145 };
146
147 static struct opcode sparcop3[64]={
148 /* [0x00] */ "ld", load, 0,
149 /* [0x01] */ "ldub", load, 0,
150 /* [0x02] */ "lduh", load, 0,
151 /* [0x03] */ "ldd", load, 0,
152 /* [0x04] */ "st", store, 0,
153 /* [0x05] */ "stb", store, 0, /* page 95 */
154 /* [0x06] */ "sth", store, 0,
155 /* [0x07] */ "std", store, 0,
156 0, 0, 0,
157 /* [0x09] */ "ldsb", load, 0, /* page 90 */
158 /* [0x0A] */ "ldsh", load, 0,
159 0, 0, 0,
160 0, 0, 0,
161 /* [0x0D] */ "ldstub", store, 0, /* page 101 */
162 0, 0, 0,
163 /* [0x0F] */ "swap", load, 0, /* page 102 */
164 /* [0x10] */ "lda", loada, 0,
165 /* [0x11] */ "lduba", loada, 0,
166 /* [0x12] */ "lduha", loada, 0,
167 /* [0x13] */ "ldda", loada, 0,
168 /* [0x14] */ "sta", storea, 0,
169 /* [0x15] */ "stba", storea, 0,
170 /* [0x16] */ "stha", storea, 0,
171 /* [0x17] */ "stda", storea, 0,
172 0, 0, 0,
173 /* [0x19] */ "ldsba", loada, 0,
174 /* [0x1A] */ "ldsha", loada, 0,
175 0, 0, 0,
176 0, 0, 0,
177 /* [0x1D] */ "ldstuba", storea, 0,
178 0, 0, 0,
179 /* [0x1F] */ "swapa", loada, 0,
180 /* [0x20] */ "ldf", loadf, 0, /* page 92 */
181 /* [0x21] */ "ldfsr", loadf, 0,
182 0, 0, 0,
183 /* [0x23] */ "lddf", loadf, 0,
184 /* [0x24] */ "stf", storef, 0, /* page 97 */
185 /* [0x25] */ "stfsr", storef, 0,
186 /* [0x26] */ "stdfq", storef, 0,
187 /* [0x27] */ "stdf", storef, 0,
188 0, 0, 0,
189 0, 0, 0,
190 0, 0, 0,
191 0, 0, 0,
192 0, 0, 0,
193 0, 0, 0,
194 0, 0, 0,
195 0, 0, 0,
196 /* [0x30] */ "ldc", loadc, 0, /* page 94 */
197 /* [0x31] */ "ldcsr", loadcsr,0,
198 0, 0, 0,
199 /* [0x33] */ "lddc", loadc, 0,
200 /* [0x34] */ "stc", loadc, 0, /* page 99 */
201 /* [0x35] */ "stcsr", loadcsr,0,
202 /* [0x36] */ "stdcq", loadcsr,0,
203 /* [0x37] */ "stdc", loadc, 0,
204 };
205
206 static void
bprint(Instr * i,char * fmt,...)207 bprint(Instr *i, char *fmt, ...)
208 {
209 va_list arg;
210
211 va_start(arg, fmt);
212 i->curr = vseprint(i->curr, i->end, fmt, arg);
213 va_end(arg);
214 }
215
216 static int
decode(ulong * pc,Instr * i)217 decode(ulong *pc, Instr *i)
218 {
219 ulong w;
220
221 w = *pc;
222
223 i->op = (w >> 30) & 0x03;
224 i->rd = (w >> 25) & 0x1F;
225 i->op2 = (w >> 22) & 0x07;
226 i->a = (w >> 29) & 0x01;
227 i->cond = (w >> 25) & 0x0F;
228 i->op3 = (w >> 19) & 0x3F;
229 i->rs1 = (w >> 14) & 0x1F;
230 i->i = (w >> 13) & 0x01;
231 i->asi = (w >> 5) & 0xFF;
232 i->rs2 = (w >> 0) & 0x1F;
233 i->simm13 = (w >> 0) & 0x1FFF;
234 if(i->simm13 & (1<<12))
235 i->simm13 |= ~((1<<13)-1);
236 i->opf = (w >> 5) & 0x1FF;
237 i->immdisp22 = (w >> 0) & 0x3FFFFF;
238 i->simmdisp22 = i->immdisp22;
239 if(i->simmdisp22 & (1<<21))
240 i->simmdisp22 |= ~((1<<22)-1);
241 i->disp30 = (w >> 0) & 0x3FFFFFFF;
242 i->w0 = w;
243 i->target = -1;
244 i->addr = (ulong)pc;
245 i->size = 1;
246 return 1;
247 }
248
249 static int
mkinstr(ulong * pc,Instr * i)250 mkinstr(ulong *pc, Instr *i)
251 {
252 Instr xi;
253
254 if (decode(pc, i) < 0)
255 return -1;
256 if(i->op==0 && i->op2==4 && !dascase){ /* SETHI */
257 if(decode(pc+1, &xi) < 0)
258 return -1;
259 if(xi.op == 2 && xi.op3 == 0) /* ADD */
260 if(xi.i == 1 && xi.rs1 == i->rd){ /* immediate to same reg */
261 i->imm32 = xi.simm13 + (i->immdisp22<<10);
262 i->target = xi.rd;
263 i->w1 = xi.w0;
264 i->size++;
265 return 1;
266 }
267 }
268 if(i->op==2 && i->opf==1 && !dascase){ /* FMOVS */
269 if (decode(pc+1, &xi) < 0)
270 return -1;
271 if(i->op==2 && i->opf==1) /* FMOVS */
272 if(xi.rd==i->rd+1 && xi.rs2==i->rs2+1){ /* next pair */
273 i->w1 = xi.w0;
274 i->size++;
275 }
276 }
277 return 1;
278 }
279
280 static int
inst(ulong * pc)281 inst(ulong *pc)
282 {
283 long disp;
284 Instr instr;
285 static char buf[128];
286 void (*f)(Instr*, char*);
287
288 memset(&instr, 0, sizeof(instr));
289 instr.curr = buf;
290 instr.end = buf+sizeof(buf)-1;
291 if(mkinstr(pc, &instr) < 0)
292 return 4;
293 switch(instr.op){
294 case 0:
295 f = sparcop0[instr.op2].f;
296 if(f)
297 (*f)(&instr, sparcop0[instr.op2].mnemonic);
298 else
299 bprint(&instr, "unknown 0x%lux", instr.w0);
300 break;
301
302 case 1:
303 disp = instr.disp30;
304 disp = (disp<<2)>>2;
305 bprint(&instr, "CALL\t0x%lux", pc+disp);
306 if (!dascase)
307 bprint(&instr, "(SB)");
308 break;
309
310 case 2:
311 f = sparcop2[instr.op3].f;
312 if(f)
313 (*f)(&instr, sparcop2[instr.op3].mnemonic);
314 else
315 bprint(&instr, "unknown 0x%lux", instr.w0);
316 break;
317
318 case 3:
319 f = sparcop3[instr.op3].f;
320 if(f)
321 (*f)(&instr, sparcop3[instr.op3].mnemonic);
322 else
323 bprint(&instr, "unknown 0x%lux", instr.w0);
324 break;
325 }
326 if (instr.err) {
327 if (instr.curr != buf)
328 bprint(&instr, "\t\t;");
329 bprint(&instr, instr.err);
330 }
331 print("\t%.8lux %s\n", (ulong)pc, buf);
332
333 return instr.size;
334 }
335
336 void
das(ulong * pc,int n)337 das(ulong *pc, int n)
338 {
339 ulong *e;
340
341 e = pc + n;
342 while(pc < e)
343 pc += inst(pc);
344 }
345
346 static void
address(Instr * i)347 address(Instr *i)
348 {
349 bprint(i, "0x%lux(R%d)", i->simm13, i->rs1);
350 }
351
352 static void
unimp(Instr * i,char * m)353 unimp(Instr *i, char *m)
354 {
355 bprint(i, "%s", m);
356 }
357
358 static char *bratab[16] = { /* page 91 */
359 /* [0x0] */ "N",
360 /* [0x1] */ "E",
361 /* [0x2] */ "LE",
362 /* [0x3] */ "L",
363 /* [0x4] */ "LEU",
364 /* [0x5] */ "CS",
365 /* [0x6] */ "NEG",
366 /* [0x7] */ "VS",
367 /* [0x8] */ "A",
368 /* [0x9] */ "NE",
369 /* [0xA] */ "G",
370 /* [0xB] */ "GE",
371 /* [0xC] */ "GU",
372 /* [0xD] */ "CC",
373 /* [0xE] */ "POS",
374 /* [0xF] */ "VC",
375 };
376
377 static char *fbratab[16] = { /* page 91 */
378 /* [0x0] */ "N",
379 /* [0x1] */ "NE",
380 /* [0x2] */ "LG",
381 /* [0x3] */ "UL",
382 /* [0x4] */ "L",
383 /* [0x5] */ "UG",
384 /* [0x6] */ "G",
385 /* [0x7] */ "U",
386 /* [0x8] */ "A",
387 /* [0x9] */ "E",
388 /* [0xA] */ "UE",
389 /* [0xB] */ "GE",
390 /* [0xC] */ "UGE",
391 /* [0xD] */ "LE",
392 /* [0xE] */ "ULE",
393 /* [0xF] */ "O",
394 };
395
396 static char *cbratab[16] = { /* page 91 */
397 /* [0x0] */ "N",
398 /* [0x1] */ "123",
399 /* [0x2] */ "12",
400 /* [0x3] */ "13",
401 /* [0x4] */ "1",
402 /* [0x5] */ "23",
403 /* [0x6] */ "2",
404 /* [0x7] */ "3",
405 /* [0x8] */ "A",
406 /* [0x9] */ "0",
407 /* [0xA] */ "03",
408 /* [0xB] */ "02",
409 /* [0xC] */ "023",
410 /* [0xD] */ "01",
411 /* [0xE] */ "013",
412 /* [0xF] */ "012",
413 };
414
415 static void
bra1(Instr * i,char * m,char * tab[])416 bra1(Instr *i, char *m, char *tab[])
417 {
418 long imm;
419
420 imm = i->simmdisp22;
421 if(i->a)
422 bprint(i, "%s%s.%c\t", m, tab[i->cond], 'A'+dascase);
423 else
424 bprint(i, "%s%s\t", m, tab[i->cond]);
425 bprint(i, "0x%lux", i->addr+4*imm);
426 if (!dascase)
427 bprint(i, "(SB)");
428 }
429
430 static void
bra(Instr * i,char * m)431 bra(Instr *i, char *m) /* page 91 */
432 {
433 bra1(i, m, bratab);
434 }
435
436 static void
fbra(Instr * i,char * m)437 fbra(Instr *i, char *m) /* page 93 */
438 {
439 bra1(i, m, fbratab);
440 }
441
442 static void
cbra(Instr * i,char * m)443 cbra(Instr *i, char *m) /* page 95 */
444 {
445 bra1(i, m, cbratab);
446 }
447
448 static void
trap(Instr * i,char * m)449 trap(Instr *i, char *m) /* page 101 */
450 {
451 if(i->i == 0)
452 bprint(i, "%s%s\tR%d+R%d", m, bratab[i->cond], i->rs2, i->rs1);
453 else
454 bprint(i, "%s%s\t$0x%lux+R%d", m, bratab[i->cond], i->simm13, i->rs1);
455 }
456
457 static void
sethi(Instr * i,char * m)458 sethi(Instr *i, char *m) /* page 89 */
459 {
460 ulong imm;
461
462 imm = i->immdisp22<<10;
463 if(dascase){
464 bprint(i, "%s\t0x%lux, R%d", m, imm, i->rd);
465 return;
466 }
467 if(imm==0 && i->rd==0){
468 bprint(i, "NOP");
469 return;
470 }
471 if(i->target < 0){
472 bprint(i, "MOVW\t$0x%lux, R%d", imm, i->rd);
473 return;
474 }
475 bprint(i, "MOVW\t$0x%lux, R%d", i->imm32, i->target);
476 }
477
478 static char ldtab[] = {
479 'W',
480 'B',
481 'H',
482 'D',
483 };
484
485 static char*
moveinstr(int op3,char * m)486 moveinstr(int op3, char *m)
487 {
488 char *s;
489 int c;
490 static char buf[8];
491
492 if(!dascase){
493 /* batshit cases */
494 if(op3 == 0xF || op3 == 0x1F)
495 return "SWAP";
496 if(op3 == 0xD || op3 == 0x1D)
497 return "TAS"; /* really LDSTUB */
498 c = ldtab[op3&3];
499 s = "";
500 if((op3&11)==1 || (op3&11)==2)
501 s="U";
502 sprint(buf, "MOV%c%s", c, s);
503 return buf;
504 }
505 return m;
506 }
507
508 static void
load(Instr * i,char * m)509 load(Instr *i, char *m) /* page 68 */
510 {
511 m = moveinstr(i->op3, m);
512 if(i->i == 0)
513 bprint(i, "%s\t(R%d+R%d), R%d", m, i->rs1, i->rs2, i->rd);
514 else{
515 bprint(i, "%s\t", m);
516 address(i);
517 bprint(i, ", R%d", i->rd);
518 }
519 }
520
521 static void
loada(Instr * i,char * m)522 loada(Instr *i, char *m) /* page 68 */
523 {
524 m = moveinstr(i->op3, m);
525 if(i->i == 0)
526 bprint(i, "%s\t(R%d+R%d, %d), R%d", m, i->rs1, i->rs2, i->asi, i->rd);
527 else
528 bprint(i, "unknown ld asi 0x%lux", i->w0);
529 }
530
531 static void
store(Instr * i,char * m)532 store(Instr *i, char *m) /* page 74 */
533 {
534 m = moveinstr(i->op3, m);
535 if(i->i == 0)
536 bprint(i, "%s\tR%d, (R%d+R%d)",
537 m, i->rd, i->rs1, i->rs2);
538 else{
539 bprint(i, "%s\tR%d, ", m, i->rd);
540 address(i);
541 }
542 }
543
544 static void
storea(Instr * i,char * m)545 storea(Instr *i, char *m) /* page 74 */
546 {
547 m = moveinstr(i->op3, m);
548 if(i->i == 0)
549 bprint(i, "%s\tR%d, (R%d+R%d, %d)", m, i->rd, i->rs1, i->rs2, i->asi);
550 else
551 bprint(i, "%s\tR%d, %d(R%d, %d), ???", m, i->rd, i->simm13, i->rs1, i->asi);
552 }
553
554 static void
shift(Instr * i,char * m)555 shift(Instr *i, char *m) /* page 88 */
556 {
557 if(i->i == 0){
558 if(i->rs1 == i->rd)
559 if(dascase)
560 bprint(i, "%s\tR%d, R%d", m, i->rs1, i->rs2);
561 else
562 bprint(i, "%s\tR%d, R%d", m, i->rs2, i->rs1);
563 else
564 if(dascase)
565 bprint(i, "%s\tR%d, R%d, R%d", m, i->rs1, i->rs2, i->rd);
566 else
567 bprint(i, "%s\tR%d, R%d, R%d", m, i->rs2, i->rs1, i->rd);
568 }else{
569 if(i->rs1 == i->rd)
570 if(dascase)
571 bprint(i, "%s\t$%d,R%d", m, i->simm13&0x1F, i->rs1);
572 else
573 bprint(i, "%s\tR%d, $%d", m, i->rs1, i->simm13&0x1F);
574 else
575 if(dascase)
576 bprint(i, "%s\tR%d, $%d, R%d",m,i->rs1,i->simm13&0x1F,i->rd);
577 else
578 bprint(i, "%s\t$%d, R%d, R%d",m,i->simm13&0x1F,i->rs1,i->rd);
579 }
580 }
581
582 static void
add(Instr * i,char * m)583 add(Instr *i, char *m) /* page 82 */
584 {
585 if(i->i == 0){
586 if(dascase)
587 bprint(i, "%s\tR%d, R%d", m, i->rs1, i->rs2);
588 else
589 if(i->op3==2 && i->rs1==0 && i->rd) /* OR R2, R0, R1 */
590 bprint(i, "MOVW\tR%d", i->rs2);
591 else
592 bprint(i, "%s\tR%d, R%d", m, i->rs2, i->rs1);
593 }else{
594 if(dascase)
595 bprint(i, "%s\tR%d, $0x%lux", m, i->rs1, i->simm13);
596 else
597 if(i->op3==0 && i->rd && i->rs1==0) /* ADD $x, R0, R1 */
598 bprint(i, "MOVW\t$0x%lux", i->simm13);
599 else if(i->op3==0 && i->rd && i->rs1==2){
600 /* ADD $x, R2, R1 -> MOVW $x(SB), R1 */
601 bprint(i, "MOVW\t$");
602 address(i);
603 } else
604 bprint(i, "%s\t$0x%lux, R%d", m, i->simm13, i->rs1);
605 }
606 if(i->rs1 != i->rd)
607 bprint(i, ", R%d", i->rd);
608 }
609
610 static void
cmp(Instr * i,char * m)611 cmp(Instr *i, char *m)
612 {
613 if(dascase || i->rd){
614 add(i, m);
615 return;
616 }
617 if(i->i == 0)
618 bprint(i, "CMP\tR%d, R%d", i->rs1, i->rs2);
619 else
620 bprint(i, "CMP\tR%d, $0x%lux", i->rs1, i->simm13);
621 }
622
623 static char *regtab[4] =
624 {
625 "Y",
626 "PSR",
627 "WIM",
628 "TBR",
629 };
630
631 static void
wr(Instr * i,char * m)632 wr(Instr *i, char *m) /* page 82 */
633 {
634 if(dascase){
635 if(i->i == 0)
636 bprint(i, "%s\tR%d, R%d", m, i->rs1, i->rs2);
637 else
638 bprint(i, "%s\tR%d, $0x%lux", m, i->rs1, i->simm13);
639 }else{
640 if(i->i && i->simm13==0)
641 bprint(i, "MOVW\tR%d", i->rs1);
642 else if(i->i == 0)
643 bprint(i, "wr\tR%d, R%d", i->rs2, i->rs1);
644 else
645 bprint(i, "wr\t$0x%lux, R%d", i->simm13, i->rs1);
646 }
647 bprint(i, ", %s", regtab[i->op3&3]);
648 }
649
650 static void
rd(Instr * i,char * m)651 rd(Instr *i, char *m) /* page 103 */
652 {
653 if(i->rs1==15 && i->rd==0){
654 m = "stbar";
655 if(!dascase)
656 m = "STBAR";
657 bprint(i, "%s", m);
658 }else{
659 if(!dascase)
660 m = "MOVW";
661 bprint(i, "%s\t%s, R%d", m, regtab[i->op3&3], i->rd);
662 }
663 }
664
665 static void
jmpl(Instr * i,char * m)666 jmpl(Instr *i, char *m) /* page 82 */
667 {
668 if(i->i == 0){
669 if(i->rd == 15)
670 bprint(i, "CALL\t(R%d+R%d)", i->rs2, i->rs1);
671 else
672 bprint(i, "%s\t(R%d+R%d), R%d", m, i->rs2, i->rs1, i->rd);
673 }else{
674 if(!dascase && i->simm13==8 && i->rs1==15 && i->rd==0)
675 bprint(i, "RETURN");
676 else{
677 bprint(i, "%s\t", m);
678 address(i);
679 bprint(i, ", R%d", i->rd);
680 }
681 }
682 }
683
684 static void
loadf(Instr * i,char * m)685 loadf(Instr *i, char *m) /* page 70 */
686 {
687 if(!dascase){
688 m = "FMOVD";
689 if(i->op3 == 0x20)
690 m = "FMOVF";
691 else if(i->op3 == 0x21)
692 m = "MOVW";
693 }
694 if(i->i == 0)
695 bprint(i, "%s\t(R%d+R%d)", m, i->rs1, i->rs2);
696 else{
697 bprint(i, "%s\t", m);
698 address(i);
699 }
700 if(i->op3 == 0x21)
701 bprint(i, ", FSR");
702 else
703 bprint(i, ", R%d", i->rd);
704 }
705
706 static
storef(Instr * i,char * m)707 void storef(Instr *i, char *m) /* page 70 */
708 {
709 if(!dascase){
710 m = "FMOVD";
711 if(i->op3 == 0x25 || i->op3 == 0x26)
712 m = "MOVW";
713 else if(i->op3 == 0x24)
714 m = "FMOVF";
715 }
716 bprint(i, "%s\t", m);
717 if(i->op3 == 0x25)
718 bprint(i, "FSR, ");
719 else if(i->op3 == 0x26)
720 bprint(i, "FQ, ");
721 else
722 bprint(i, "R%d, ", i->rd);
723 if(i->i == 0)
724 bprint(i, "(R%d+R%d)", i->rs1, i->rs2);
725 else
726 address(i);
727 }
728
729 static
loadc(Instr * i,char * m)730 void loadc(Instr *i, char *m) /* page 72 */
731 {
732 if(i->i == 0)
733 bprint(i, "%s\t(R%d+R%d), C%d", m, i->rs1, i->rs2, i->rd);
734 else{
735 bprint(i, "%s\t", m);
736 address(i);
737 bprint(i, ", C%d", i->rd);
738 }
739 }
740
741 static
loadcsr(Instr * i,char * m)742 void loadcsr(Instr *i, char *m) /* page 72 */
743 {
744 if(i->i == 0)
745 bprint(i, "%s\t(R%d+R%d), CSR", m, i->rs1, i->rs2);
746 else{
747 bprint(i, "%s\t", m);
748 address(i);
749 bprint(i, ", CSR");
750 }
751 }
752
753 static struct
754 {
755 int opf;
756 char *name;
757 } fptab1[] = { /* ignores rs1 */
758 0xC4, "FITOS", /* page 109 */
759 0xC8, "FITOD",
760 0xCC, "FITOX",
761
762 0xD1, "FSTOI", /* page 110 */
763 0xD2, "FDTOI",
764 0xD3, "FXTOI",
765
766 0xC9, "FSTOD", /* page 111 */
767 0xCD, "FSTOX",
768 0xC6, "FDTOS",
769 0xCE, "FDTOX",
770 0xC7, "FXTOS",
771 0xCB, "FXTOD",
772
773 0x01, "FMOVS", /* page 112 */
774 0x05, "FNEGS",
775 0x09, "FABSS",
776
777 0x29, "FSQRTS", /* page 113 */
778 0x2A, "FSQRTD",
779 0x2B, "FSQRTX",
780
781 0, 0,
782 };
783
784 static struct{
785 int opf;
786 char *name;
787 } fptab2[] = { /* uses rs1 */
788
789 0x41, "FADDS", /* page 114 */
790 0x42, "FADDD",
791 0x43, "FADDX",
792 0x45, "FSUBS",
793 0x46, "FSUBD",
794 0x47, "FSUBX",
795
796 0x49, "FMULS", /* page 115 */
797 0x4A, "FMULD",
798 0x4B, "FMULX",
799 0x4D, "FDIVS",
800 0x4E, "FDIVD",
801 0x4F, "FDIVX",
802
803 0x51, "FCMPS", /* page 116 */
804 0x52, "FCMPD",
805 0x53, "FCMPX",
806 0x55, "FCMPES",
807 0x56, "FCMPED",
808 0x57, "FCMPEX",
809
810 0, 0
811 };
812
813 static void
fpop(Instr * i,char * m)814 fpop(Instr *i, char *m) /* page 108-116 */
815 {
816 int j;
817
818 if(dascase==0 && i->size==2){
819 bprint(i, "FMOVD\tF%d, F%d", i->rs2, i->rd);
820 return;
821 }
822 for(j=0; fptab1[j].name; j++)
823 if(fptab1[j].opf == i->opf){
824 bprint(i, "%s\tF%d, F%d", fptab1[j].name, i->rs2, i->rd);
825 return;
826 }
827 for(j=0; fptab2[j].name; j++)
828 if(fptab2[j].opf == i->opf){
829 bprint(i, "%s\tF%d, F%d, F%d", fptab2[j].name, i->rs1, i->rs2, i->rd);
830 return;
831 }
832 bprint(i, "%s%ux\tF%d, F%d, F%d", m, i->opf, i->rs1, i->rs2, i->rd);
833 }
834