xref: /plan9/sys/src/libmach/alphadb.c (revision 473d4f4b3fed09ca133e03643ec71c9150b33bcc)
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <mach.h>
5 /*
6  * Alpha-specific debugger interface
7  */
8 
9 static 	char	*alphaexcep(Map*, Rgetter);
10 static	int	alphafoll(Map*, uvlong, Rgetter, uvlong*);
11 static	int	alphainst(Map*, uvlong, char, char*, int);
12 static	int	alphadas(Map*, uvlong, char*, int);
13 static	int	alphainstlen(Map*, uvlong);
14 /*
15  *	Debugger interface
16  */
17 Machdata alphamach =
18 {
19 	{0x80, 0, 0, 0},		/* break point */
20 	4,			/* break point size */
21 
22 	leswab,			/* short to local byte order */
23 	leswal,			/* long to local byte order */
24 	leswav,			/* vlong to local byte order */
25 	risctrace,		/* C traceback */
26 	riscframe,		/* Frame finder */
27 	alphaexcep,		/* print exception */
28 	0,			/* breakpoint fixup */
29 	leieeesftos,		/* single precision float printer */
30 	leieeedftos,		/* double precisioin float printer */
31 	alphafoll,		/* following addresses */
32 	alphainst,		/* print instruction */
33 	alphadas,		/* dissembler */
34 	alphainstlen,		/* instruction size */
35 };
36 
37 static char *illegaltype[] = {
38 	"breakpoint",
39 	"bugchk",
40 	"gentrap",
41 	"fen",
42 	"illegal instruction",
43 };
44 
45 static char *
alphaexcep(Map * map,Rgetter rget)46 alphaexcep(Map *map, Rgetter rget)
47 {
48 	ulong type, a0, a1;
49 	static char buf[256];
50 
51 	type = (*rget)(map, "TYPE");
52 	a0 = (*rget)(map, "A0");
53 	a1 = (*rget)(map, "A1");
54 /*	a2 = (*rget)(map, "A2"); */
55 
56 	switch (type) {
57 	case 1:	/* arith */
58 		sprint(buf, "trap: arithmetic trap 0x%lux", a0);
59 		break;
60 	case 2:	/* bad instr or FEN */
61 		if (a0 <= 4)
62 			return illegaltype[a0];
63 		else
64 			sprint(buf, "illegal instr trap, unknown type %lud", a0);
65 		break;
66 	case 3:	/* intr */
67 		sprint(buf, "interrupt type %lud", a0);
68 		break;
69 	case 4:	/* memory fault */
70 		sprint(buf, "fault %s addr=0x%lux", (a1&1)?"write":"read", a0);
71 		break;
72 	case 5:	/* syscall() */
73 		return "system call";
74 	case 6:	/* alignment fault */
75 		sprint(buf, "unaligned op 0x%lux addr 0x%lux", a1, a0);
76 		break;
77 	default:	/* cannot happen */
78 		sprint(buf, "unknown exception type %lud", type);
79 		break;
80 	}
81 	return buf;
82 }
83 
84 	/* alpha disassembler and related functions */
85 
86 static	char FRAMENAME[] = ".frame";
87 
88 typedef struct {
89 	uvlong addr;
90 	uchar op;			/* bits 31-26 */
91 	uchar ra;			/* bits 25-21 */
92 	uchar rb;			/* bits 20-16 */
93 	uchar rc;			/* bits 4-0 */
94 	long mem;			/* bits 15-0 */
95 	long branch;			/* bits 20-0 */
96 	uchar function;			/* bits 11-5 */
97 	uchar literal;			/* bits 20-13 */
98 	uchar islit;			/* bit 12 */
99 	uchar fpfn;			/* bits 10-5 */
100 	uchar fpmode;			/* bits 15-11 */
101 	long w0;
102 	long w1;
103 	int size;			/* instruction size */
104 	char *curr;			/* fill point in buffer */
105 	char *end;			/* end of buffer */
106 	char *err;			/* error message */
107 } Instr;
108 
109 static Map *mymap;
110 
111 static int
decode(uvlong pc,Instr * i)112 decode(uvlong pc, Instr *i)
113 {
114 	ulong w;
115 
116 	if (get4(mymap, pc, &w) < 0) {
117 		werrstr("can't read instruction: %r");
118 		return -1;
119 	}
120 	i->addr = pc;
121 	i->size = 1;
122 	i->op = (w >> 26) & 0x3F;
123 	i->ra = (w >> 21) & 0x1F;
124 	i->rb = (w >> 16) & 0x1F;
125 	i->rc = w & 0x1F;
126 	i->function = (w >> 5) & 0x7F;
127 	i->mem = w & 0xFFFF;
128 	if (i->mem & 0x8000)
129 		i->mem -= 0x10000;
130 	i->branch = w & 0x1FFFFF;
131 	if (i->branch & 0x100000)
132 		i->branch -= 0x200000;
133 	i->function = (w >> 5) & 0x7F;
134 	i->literal = (w >> 13) & 0xFF;
135 	i->islit = (w >> 12) & 0x01;
136 	i->fpfn = (w >> 5) & 0x3F;
137 	i->fpmode = (w >> 11) & 0x1F;
138 	i->w0 = w;
139 	return 1;
140 }
141 
142 static int
mkinstr(uvlong pc,Instr * i)143 mkinstr(uvlong pc, Instr *i)
144 {
145 /*	Instr x; */
146 
147 	if (decode(pc, i) < 0)
148 		return -1;
149 
150 #ifdef	frommips
151 /* we probably want to do something like this for alpha... */
152 	/*
153 	 * if it's a LUI followed by an ORI,
154 	 * it's an immediate load of a large constant.
155 	 * fix the LUI immediate in any case.
156 	 */
157 	if (i->op == 0x0F) {
158 		if (decode(pc+4, &x) < 0)
159 			return 0;
160 		i->immediate <<= 16;
161 		if (x.op == 0x0D && x.rs == x.rt && x.rt == i->rt) {
162 			i->immediate |= (x.immediate & 0xFFFF);
163 			i->w1 = x.w0;
164 			i->size++;
165 			return 1;
166 		}
167 	}
168 #endif
169 	return 1;
170 }
171 
172 #pragma	varargck	argpos	bprint		2
173 
174 static void
bprint(Instr * i,char * fmt,...)175 bprint(Instr *i, char *fmt, ...)
176 {
177 	va_list arg;
178 
179 	va_start(arg, fmt);
180 	i->curr = vseprint(i->curr, i->end, fmt, arg);
181 	va_end(arg);
182 }
183 
184 typedef struct Opcode Opcode;
185 
186 struct Opcode {
187 	char *mnemonic;
188 	void (*f)(Opcode *, Instr *);
189 	char *ken;
190 };
191 
192 static void format(char *, Instr *, char *);
193 
194 static int
plocal(Instr * i,char * m,char r,int store)195 plocal(Instr *i, char *m, char r, int store)
196 {
197 	int offset;
198 	char *reg;
199 	Symbol s;
200 
201 	if (!findsym(i->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s))
202 		return 0;
203 	if (s.value > i->mem) {
204 		if(!getauto(&s, s.value-i->mem, CAUTO, &s))
205 			return 0;
206 		reg = "(SP)";
207 		offset = i->mem;
208 	} else {
209 		offset = i->mem-s.value-8;
210 		if (!getauto(&s, offset, CPARAM, &s))
211 			return 0;
212 		reg = "(FP)";
213 	}
214 	if (store)
215 		bprint(i, "%s\t%c%d,%s+%d%s", m, r, i->ra, s.name, offset, reg);
216 	else
217 		bprint(i, "%s\t%s+%d%s,%c%d", m, s.name, offset, reg, r, i->ra);
218 	return 1;
219 }
220 
221 static void
_load(Opcode * o,Instr * i,char r)222 _load(Opcode *o, Instr *i, char r)
223 {
224 	char *m;
225 
226 	m = o->mnemonic;
227 	if (i->rb == 30 && plocal(i, m, r, 0))
228 		return;
229 	if (i->rb == 29 && mach->sb) {
230 		bprint(i, "%s\t", m);
231 		i->curr += symoff(i->curr, i->end-i->curr, i->mem+mach->sb, CANY);
232 		bprint(i, "(SB),%c%d", r, i->ra);
233 		return;
234 	}
235 	format(m, i, o->ken);
236 }
237 
238 static void
load(Opcode * o,Instr * i)239 load(Opcode *o, Instr *i)
240 {
241 	_load(o, i, 'R');
242 }
243 
244 static void
loadf(Opcode * o,Instr * i)245 loadf(Opcode *o, Instr *i)
246 {
247 	_load(o, i, 'F');
248 }
249 
250 static void
_store(Opcode * o,Instr * i,char r)251 _store(Opcode *o, Instr *i, char r)
252 {
253 	char *m;
254 
255 	m = o->mnemonic;
256 	if (i->rb == 30 && plocal(i, m, r, 1))
257 		return;
258 	if (i->rb == 29 && mach->sb) {
259 		bprint(i, "%s\t%c%d,", m, r, i->ra);
260 		i->curr += symoff(i->curr, i->end-i->curr, i->mem+mach->sb, CANY);
261 		bprint(i, "(SB)");
262 		return;
263 	}
264 	format(o->mnemonic, i, o->ken);
265 }
266 
267 static void
store(Opcode * o,Instr * i)268 store(Opcode *o, Instr *i)
269 {
270 	_store(o, i, 'R');
271 }
272 
273 static void
storef(Opcode * o,Instr * i)274 storef(Opcode *o, Instr *i)
275 {
276 	_store(o, i, 'F');
277 }
278 
279 static void
misc(Opcode * o,Instr * i)280 misc(Opcode *o, Instr *i)
281 {
282 	char *f;
283 
284 	USED(o);
285 	switch (i->mem&0xFFFF) {
286 	case 0x0000:
287 		f = "TRAPB";
288 		break;
289 	case 0x4000:
290 		f = "MB";
291 		break;
292 	case 0x8000:
293 		f = "FETCH\t0(R%b)";
294 		break;
295 	case 0xA000:
296 		f = "FETCH_M\t0(R%b)";
297 		break;
298 	case 0xC000:
299 		f = "RPCC\tR%a";
300 		break;
301 	case 0xE000:
302 		f = "RC\tR%a";
303 		break;
304 	case 0xF000:
305 		f = "RS\tR%a";
306 		break;
307 	default:
308 		f = "%w";
309 	}
310 	format(0, i, f);
311 }
312 
313 static char	*jmpcode[4] = { "JMP", "JSR", "RET", "JSR_COROUTINE" };
314 
315 static void
jmp(Opcode * o,Instr * i)316 jmp(Opcode *o, Instr *i)
317 {
318 	int hint;
319 	char *m;
320 
321 	USED(o);
322 	hint = (i->mem >> 14) & 3;
323 	m = jmpcode[hint];
324 	if (i->ra == 31) {
325 		if (hint == 2 && i->rb == 29)
326 			bprint(i, m);
327 		else
328 			format(m, i, "(R%b)");
329 	}
330 	else
331 		format(m, i, "R%a,(R%b)");
332 }
333 
334 static void
br(Opcode * o,Instr * i)335 br(Opcode *o, Instr *i)
336 {
337 	if (i->ra == 31)
338 		format(o->mnemonic, i, "%B");
339 	else
340 		format(o->mnemonic, i, o->ken);
341 }
342 
343 static void
bsr(Opcode * o,Instr * i)344 bsr(Opcode *o, Instr *i)
345 {
346 	if (i->ra == 26)
347 		format(o->mnemonic, i, "%B");
348 	else
349 		format(o->mnemonic, i, o->ken);
350 }
351 
352 static void
mult(Opcode * o,Instr * i)353 mult(Opcode *o, Instr *i)
354 {
355 	char *m;
356 
357 	switch (i->function) {
358 	case 0x00:
359 		m = "MULL";
360 		break;
361 	case 0x20:
362 		m = "MULQ";
363 		break;
364 	case 0x40:
365 		m = "MULL/V";
366 		break;
367 	case 0x60:
368 		m = "MULQ/V";
369 		break;
370 	case 0x30:
371 		m = "UMULH";
372 		break;
373 	default:
374 		format("???", i, "%w");
375 		return;
376 	}
377 	format(m, i, o->ken);
378 }
379 
380 static char	alphaload[] = "%l,R%a";
381 static char	alphafload[] = "%l,F%a";
382 static char	alphastore[] = "R%a,%l";
383 static char	alphafstore[] = "F%a,%l";
384 static char	alphabranch[] = "R%a,%B";
385 static char	alphafbranch[] = "F%a,%B";
386 static char	alphaint[] = "%v,R%a,R%c";
387 static char	alphafp[] = "F%b,F%a,F%c";
388 static char	alphafp2[] = "F%b,F%c";
389 static char	alphaxxx[] = "%w";
390 
391 static Opcode opcodes[64] = {
392 	"PAL",		0,	alphaxxx,
393 	"OPC01",	0,	alphaxxx,
394 	"OPC02",	0,	alphaxxx,
395 	"OPC03",	0,	alphaxxx,
396 	"OPC04",	0,	alphaxxx,
397 	"OPC05",	0,	alphaxxx,
398 	"OPC06",	0,	alphaxxx,
399 	"OPC07",	0,	alphaxxx,
400 	"MOVQA",	load,	alphaload,
401 	"MOVQAH",	load,	alphaload,
402 	"MOVBU",	load,	alphaload,		/* v 3 */
403 	"MOVQU",	load,	alphaload,
404 	"MOVWU",	load,	alphaload,		/* v 3 */
405 	"MOVWU",	store,	alphastore,		/* v 3 */
406 	"MOVBU",	store,	alphastore,		/* v 3 */
407 	"MOVQU",	store,	alphastore,
408 	0,		0,	0,			/* int arith */
409 	0,		0,	0,			/* logical */
410 	0,		0,	0,			/* shift */
411 	0,		mult,	alphaint,
412 	"OPC14",	0,	alphaxxx,
413 	"vax",		0,	alphafp,		/* vax */
414 	0,		0,	0,			/* ieee */
415 	0,		0,	0,			/* fp */
416 	0,		misc,	alphaxxx,
417 	"PAL19 [HW_MFPR]",0,	alphaxxx,
418 	"JSR",		jmp,	0,
419 	"PAL1B [HW_LD]",0,	alphaxxx,
420 	"OPC1C",	0,	alphaxxx,
421 	"PAL1D [HW_MTPR]",0,	alphaxxx,
422 	"PAL1E [HW_REI]",0,	alphaxxx,
423 	"PAL1F [HW_ST]",0,	alphaxxx,
424 	"MOVF",		loadf,	alphafload,
425 	"MOVG",		loadf,	alphafload,
426 	"MOVS",		loadf,	alphafload,
427 	"MOVT",		loadf,	alphafload,
428 	"MOVF",		storef,	alphafstore,
429 	"MOVG",		storef,	alphafstore,
430 	"MOVS",		storef,	alphafstore,
431 	"MOVT",		storef,	alphafstore,
432 	"MOVL",		load,	alphaload,
433 	"MOVQ",		load,	alphaload,
434 	"MOVLL",	load,	alphaload,
435 	"MOVQL",	load,	alphaload,
436 	"MOVL",		store,	alphastore,
437 	"MOVQ",		store,	alphastore,
438 	"MOVLC",	store,	alphastore,
439 	"MOVQC",	store,	alphastore,
440 	"JMP",		br,	alphabranch,
441 	"FBEQ",		0,	alphafbranch,
442 	"FBLT",		0,	alphafbranch,
443 	"FBLE",		0,	alphafbranch,
444 	"JSR",		bsr,	alphabranch,
445 	"FBNE",		0,	alphafbranch,
446 	"FBGE",		0,	alphafbranch,
447 	"FBGT",		0,	alphafbranch,
448 	"BLBC",		0,	alphafbranch,
449 	"BEQ",		0,	alphabranch,
450 	"BLT",		0,	alphabranch,
451 	"BLE",		0,	alphabranch,
452 	"BLBS",		0,	alphabranch,
453 	"BNE",		0,	alphabranch,
454 	"BGE",		0,	alphabranch,
455 	"BGT",		0,	alphabranch,
456 };
457 
458 static Opcode fpopcodes[64] = {
459 	"???",		0,	alphaxxx,
460 	"???",		0,	alphaxxx,
461 	"???",		0,	alphaxxx,
462 	"???",		0,	alphaxxx,
463 	"???",		0,	alphaxxx,
464 	"???",		0,	alphaxxx,
465 	"???",		0,	alphaxxx,
466 	"???",		0,	alphaxxx,
467 	"???",		0,	alphaxxx,
468 	"???",		0,	alphaxxx,
469 	"???",		0,	alphaxxx,
470 	"???",		0,	alphaxxx,
471 	"???",		0,	alphaxxx,
472 	"???",		0,	alphaxxx,
473 	"???",		0,	alphaxxx,
474 	"???",		0,	alphaxxx,
475 
476 	"CVTLQ",	0,	alphafp2,
477 	"???",		0,	alphaxxx,
478 	"???",		0,	alphaxxx,
479 	"???",		0,	alphaxxx,
480 	"???",		0,	alphaxxx,
481 	"???",		0,	alphaxxx,
482 	"???",		0,	alphaxxx,
483 	"???",		0,	alphaxxx,
484 	"???",		0,	alphaxxx,
485 	"???",		0,	alphaxxx,
486 	"???",		0,	alphaxxx,
487 	"???",		0,	alphaxxx,
488 	"???",		0,	alphaxxx,
489 	"???",		0,	alphaxxx,
490 	"???",		0,	alphaxxx,
491 	"???",		0,	alphaxxx,
492 
493 	"CPYS",		0,	alphafp,
494 	"CPYSN",	0,	alphafp,
495 	"CPYSE",	0,	alphafp,
496 	"???",		0,	alphaxxx,
497 	"MOVT",		0,	"FPCR,F%a",
498 	"MOVT",		0,	"F%a,FPCR",
499 	"???",		0,	alphaxxx,
500 	"???",		0,	alphaxxx,
501 	"???",		0,	alphaxxx,
502 	"???",		0,	alphaxxx,
503 	"FCMOVEQ",	0,	alphafp,
504 	"FCMOVNE",	0,	alphafp,
505 	"FCMOVLT",	0,	alphafp,
506 	"FCMOVGE",	0,	alphafp,
507 	"FCMOVLE",	0,	alphafp,
508 	"FCMOVGT",	0,	alphafp,
509 
510 	"CVTQL",	0,	alphafp2,
511 	"???",		0,	alphaxxx,
512 	"???",		0,	alphaxxx,
513 	"???",		0,	alphaxxx,
514 	"???",		0,	alphaxxx,
515 	"???",		0,	alphaxxx,
516 	"???",		0,	alphaxxx,
517 	"???",		0,	alphaxxx,
518 	"???",		0,	alphaxxx,
519 	"???",		0,	alphaxxx,
520 	"???",		0,	alphaxxx,
521 	"???",		0,	alphaxxx,
522 	"???",		0,	alphaxxx,
523 	"???",		0,	alphaxxx,
524 	"???",		0,	alphaxxx,
525 	"???",		0,	alphaxxx,
526 };
527 
528 static Opcode ieeeopcodes[64] = {
529 	"ADDS",		0,	alphafp,
530 	"SUBS",		0,	alphafp,
531 	"MULS",		0,	alphafp,
532 	"DIVS",		0,	alphafp,
533 	"???",		0,	alphaxxx,
534 	"???",		0,	alphaxxx,
535 	"???",		0,	alphaxxx,
536 	"???",		0,	alphaxxx,
537 	"???",		0,	alphaxxx,
538 	"???",		0,	alphaxxx,
539 	"???",		0,	alphaxxx,
540 	"???",		0,	alphaxxx,
541 	"???",		0,	alphaxxx,
542 	"???",		0,	alphaxxx,
543 	"???",		0,	alphaxxx,
544 	"???",		0,	alphaxxx,
545 
546 	"???",		0,	alphaxxx,
547 	"???",		0,	alphaxxx,
548 	"???",		0,	alphaxxx,
549 	"???",		0,	alphaxxx,
550 	"???",		0,	alphaxxx,
551 	"???",		0,	alphaxxx,
552 	"???",		0,	alphaxxx,
553 	"???",		0,	alphaxxx,
554 	"???",		0,	alphaxxx,
555 	"???",		0,	alphaxxx,
556 	"???",		0,	alphaxxx,
557 	"???",		0,	alphaxxx,
558 	"???",		0,	alphaxxx,
559 	"???",		0,	alphaxxx,
560 	"???",		0,	alphaxxx,
561 	"???",		0,	alphaxxx,
562 
563 	"ADDT",		0,	alphafp,
564 	"SUBT",		0,	alphafp,
565 	"MULT",		0,	alphafp,
566 	"DIVT",		0,	alphafp,
567 	"CMPTUN",	0,	alphafp,
568 	"CMPTEQ",	0,	alphafp,
569 	"CMPTLT",	0,	alphafp,
570 	"CMPTLE",	0,	alphafp,
571 	"???",		0,	alphaxxx,
572 	"???",		0,	alphaxxx,
573 	"???",		0,	alphaxxx,
574 	"???",		0,	alphaxxx,
575 	"CVTTS",	0,	alphafp2,
576 	"???",		0,	alphaxxx,
577 	"???",		0,	alphaxxx,
578 	"CVTTQ",	0,	alphafp2,
579 
580 	"???",		0,	alphaxxx,
581 	"???",		0,	alphaxxx,
582 	"???",		0,	alphaxxx,
583 	"???",		0,	alphaxxx,
584 	"???",		0,	alphaxxx,
585 	"???",		0,	alphaxxx,
586 	"???",		0,	alphaxxx,
587 	"???",		0,	alphaxxx,
588 	"???",		0,	alphaxxx,
589 	"???",		0,	alphaxxx,
590 	"???",		0,	alphaxxx,
591 	"???",		0,	alphaxxx,
592 	"CVTQS",	0,	alphafp2,
593 	"???",		0,	alphaxxx,
594 	"CVTQT",	0,	alphafp2,
595 	"???",		0,	alphaxxx,
596 };
597 
598 static uchar	amap[128] = {
599 	[0x00]	1,
600 	[0x40]	2,
601 	[0x20]	3,
602 	[0x60]	4,
603 	[0x09]	5,
604 	[0x49]	6,
605 	[0x29]	7,
606 	[0x69]	8,
607 	[0x2D]	9,
608 	[0x4D]	10,
609 	[0x6D]	11,
610 	[0x1D]	12,
611 	[0x3D]	13,
612 	[0x0F]	14,
613 	[0x02]	15,
614 	[0x0B]	16,
615 	[0x12]	17,
616 	[0x1B]	18,
617 	[0x22]	19,
618 	[0x2B]	20,
619 	[0x32]	21,
620 	[0x3B]	22,
621 };
622 
623 static Opcode arithopcodes[64] = {
624 	"???",		0,	alphaxxx,
625 	"ADDL",		0,	alphaint,
626 	"ADDL/V",	0,	alphaint,
627 	"ADDQ",		0,	alphaint,
628 	"ADDQ/V",	0,	alphaint,
629 	"SUBL",		0,	alphaint,
630 	"SUBL/V",	0,	alphaint,
631 	"SUBQ",		0,	alphaint,
632 	"SUBQ/V",	0,	alphaint,
633 	"CMPEQ",	0,	alphaint,
634 	"CMPLT",	0,	alphaint,
635 	"CMPLE",	0,	alphaint,
636 	"CMPULT",	0,	alphaint,
637 	"CMPULE",	0,	alphaint,
638 	"CMPBGE",	0,	alphaint,
639 	"S4ADDL",	0,	alphaint,
640 	"S4SUBL",	0,	alphaint,
641 	"S8ADDL",	0,	alphaint,
642 	"S8SUBL",	0,	alphaint,
643 	"S4ADDQ",	0,	alphaint,
644 	"S4SUBQ",	0,	alphaint,
645 	"S8ADDQ",	0,	alphaint,
646 	"S8SUBQ",	0,	alphaint,
647 };
648 
649 static uchar	lmap[128] = {
650 	[0x00]	1,
651 	[0x20]	2,
652 	[0x40]	3,
653 	[0x08]	4,
654 	[0x28]	5,
655 	[0x48]	6,
656 	[0x24]	7,
657 	[0x44]	8,
658 	[0x64]	9,
659 	[0x26]	7,
660 	[0x46]	8,
661 	[0x66]	9,
662 	[0x14]	10,
663 	[0x16]	11,
664 };
665 
666 static Opcode logicalopcodes[64] = {
667 	"???",		0,	alphaxxx,
668 	"AND",		0,	alphaint,
669 	"OR",		0,	alphaint,
670 	"XOR",		0,	alphaint,
671 	"ANDNOT",	0,	alphaint,
672 	"ORNOT",	0,	alphaint,
673 	"XORNOT",	0,	alphaint,
674 	"CMOVEQ",	0,	alphaint,
675 	"CMOVLT",	0,	alphaint,
676 	"CMOVLE",	0,	alphaint,
677 	"CMOVNE",	0,	alphaint,
678 	"CMOVGE",	0,	alphaint,
679 	"CMOVGT",	0,	alphaint,
680 	"CMOVLBS",	0,	alphaint,
681 	"CMOVLBC",	0,	alphaint,
682 };
683 
684 static uchar	smap[128] = {
685 	[0x39]	1,
686 	[0x3C]	2,
687 	[0x34]	3,
688 	[0x06]	4,
689 	[0x16]	5,
690 	[0x26]	6,
691 	[0x36]	7,
692 	[0x5A]	8,
693 	[0x6A]	9,
694 	[0x7A]	10,
695 	[0x0B]	11,
696 	[0x1B]	12,
697 	[0x2B]	13,
698 	[0x3B]	14,
699 	[0x57]	15,
700 	[0x67]	16,
701 	[0x77]	17,
702 	[0x02]	18,
703 	[0x12]	19,
704 	[0x22]	20,
705 	[0x32]	21,
706 	[0x52]	22,
707 	[0x62]	23,
708 	[0x72]	24,
709 	[0x30]	25,
710 	[0x31]	26,
711 };
712 
713 static Opcode shiftopcodes[64] = {
714 	"???",		0,	alphaxxx,
715 	"SLLQ",		0,	alphaint,
716 	"SRAQ",		0,	alphaint,
717 	"SRLQ",		0,	alphaint,
718 	"EXTBL",	0,	alphaint,
719 	"EXTWL",	0,	alphaint,
720 	"EXTLL",	0,	alphaint,
721 	"EXTQL",	0,	alphaint,
722 	"EXTWH",	0,	alphaint,
723 	"EXTLH",	0,	alphaint,
724 	"EXTQH",	0,	alphaint,
725 	"INSBL",	0,	alphaint,
726 	"INSWL",	0,	alphaint,
727 	"INSLL",	0,	alphaint,
728 	"INSQL",	0,	alphaint,
729 	"INSWH",	0,	alphaint,
730 	"INSLH",	0,	alphaint,
731 	"INSQH",	0,	alphaint,
732 	"MSKBL",	0,	alphaint,
733 	"MSKWL",	0,	alphaint,
734 	"MSKLL",	0,	alphaint,
735 	"MSKQL",	0,	alphaint,
736 	"MSKWH",	0,	alphaint,
737 	"MSKLH",	0,	alphaint,
738 	"MSKQH",	0,	alphaint,
739 	"ZAP",		0,	alphaint,
740 	"ZAPNOT",	0,	alphaint,
741 };
742 
743 static void
format(char * mnemonic,Instr * i,char * f)744 format(char *mnemonic, Instr *i, char *f)
745 {
746 	if (mnemonic)
747 		format(0, i, mnemonic);
748 	if (f == 0)
749 		return;
750 	if (mnemonic)
751 		if (i->curr < i->end)
752 			*i->curr++ = '\t';
753 	for ( ; *f && i->curr < i->end; f++) {
754 		if (*f != '%') {
755 			*i->curr++ = *f;
756 			continue;
757 		}
758 		switch (*++f) {
759 
760 		case 'a':
761 			bprint(i, "%d", i->ra);
762 			break;
763 
764 		case 'b':
765 			bprint(i, "%d", i->rb);
766 			break;
767 
768 		case 'c':
769 			bprint(i, "%d", i->rc);
770 			break;
771 
772 		case 'v':
773 			if (i->islit)
774 				bprint(i, "$%ux", i->literal);
775 			else
776 				bprint(i, "R%d", i->rb);
777 			break;
778 
779 		case 'l':
780 			bprint(i, "%lx(R%d)", i->mem, i->rb);
781 			break;
782 
783 		case 'i':
784 			bprint(i, "$%lx", i->mem);
785 			break;
786 
787 		case 'B':
788 			i->curr += symoff(i->curr, i->end-i->curr,
789 				(i->branch<<2)+i->addr+4, CANY);
790 			break;
791 
792 		case 'w':
793 			bprint(i, "[%lux]", i->w0);
794 			break;
795 
796 		case '\0':
797 			*i->curr++ = '%';
798 			return;
799 
800 		default:
801 			bprint(i, "%%%c", *f);
802 			break;
803 		}
804 	}
805 	*i->curr = 0;
806 }
807 
808 static int
printins(Map * map,uvlong pc,char * buf,int n)809 printins(Map *map, uvlong pc, char *buf, int n)
810 {
811 	Instr i;
812 	Opcode *o;
813 	uchar op;
814 
815 	i.curr = buf;
816 	i.end = buf+n-1;
817 	mymap = map;
818 	if (mkinstr(pc, &i) < 0)
819 		return -1;
820 	switch (i.op) {
821 
822 	case 0x10:					/* INTA */
823 		o = arithopcodes;
824 		op = amap[i.function];
825 		break;
826 
827 	case 0x11:					/* INTL */
828 		o = logicalopcodes;
829 		op = lmap[i.function];
830 		break;
831 
832 	case 0x12:					/* INTS */
833 		o = shiftopcodes;
834 		op = smap[i.function];
835 		break;
836 
837 	case 0x16:					/* FLTI */
838 		o = ieeeopcodes;
839 		op = i.fpfn;
840 		break;
841 
842 	case 0x17:					/* FLTL */
843 		o = fpopcodes;
844 		op = i.fpfn;
845 		break;
846 
847 	default:
848 		o = opcodes;
849 		op = i.op;
850 		break;
851 	}
852 	if (o[op].f)
853 		(*o[op].f)(&o[op], &i);
854 	else
855 		format(o[op].mnemonic, &i, o[op].ken);
856 	return i.size*4;
857 }
858 
859 static int
alphainst(Map * map,uvlong pc,char modifier,char * buf,int n)860 alphainst(Map *map, uvlong pc, char modifier, char *buf, int n)
861 {
862 	USED(modifier);
863 	return printins(map, pc, buf, n);
864 }
865 
866 static int
alphadas(Map * map,uvlong pc,char * buf,int n)867 alphadas(Map *map, uvlong pc, char *buf, int n)
868 {
869 	Instr i;
870 
871 	i.curr = buf;
872 	i.end = buf+n;
873 	mymap = map;
874 	if (mkinstr(pc, &i) < 0)
875 		return -1;
876 	if (i.end-i.curr > 8)
877 		i.curr = _hexify(buf, i.w0, 7);
878 	if (i.size == 2 && i.end-i.curr > 9) {
879 		*i.curr++ = ' ';
880 		i.curr = _hexify(i.curr, i.w1, 7);
881 	}
882 	*i.curr = 0;
883 	return i.size*4;
884 }
885 
886 static int
alphainstlen(Map * map,uvlong pc)887 alphainstlen(Map *map, uvlong pc)
888 {
889 	Instr i;
890 
891 	mymap = map;
892 	if (mkinstr(pc, &i) < 0)
893 		return -1;
894 	return i.size*4;
895 }
896 
897 static int
alphafoll(Map * map,uvlong pc,Rgetter rget,uvlong * foll)898 alphafoll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
899 {
900 	char buf[8];
901 	Instr i;
902 
903 	mymap = map;
904 	if (mkinstr(pc, &i) < 0)
905 		return -1;
906 
907 	switch(i.op) {
908 	case 0x1A:				/* JMP/JSR/RET */
909 		sprint(buf, "R%d", i.rb);
910 		foll[0] = (*rget)(map, buf);
911 		return 1;
912 	case 0x30:				/* BR */
913 	case 0x34:				/* BSR */
914 		foll[0] = pc+4 + (i.branch<<2);
915 		return 1;
916 	default:
917 		if (i.op > 0x30) {		/* cond */
918 			foll[0] = pc+4;
919 			foll[1] = pc+4 + (i.branch<<2);
920 			return 2;
921 		}
922 		foll[0] = pc+i.size*4;
923 		return 1;
924 	}
925 }
926