Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature-vt/sys/src/libmach/alphadb.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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 *
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
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
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
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
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
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
239
load(Opcode *o, Instr *i)
240
{
241
	_load(o, i, 'R');
242
}
243
 
244
static void
245
loadf(Opcode *o, Instr *i)
246
{
247
	_load(o, i, 'F');
248
}
249
 
250
static void
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
268
store(Opcode *o, Instr *i)
269
{
270
	_store(o, i, 'R');
271
}
272
 
273
static void
274
storef(Opcode *o, Instr *i)
275
{
276
	_store(o, i, 'F');
277
}
278
 
279
static void
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
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
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
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
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
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
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
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
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
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
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
}