Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | 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
/*
7
 * PowerPC-specific debugger interface,
8
 * including 64-bit modes
9
 *	forsyth@terzarima.net
10
 */
11
 
12
static	char	*powerexcep(Map*, Rgetter);
13
static	int	powerfoll(Map*, uvlong, Rgetter, uvlong*);
14
static	int	powerinst(Map*, uvlong, char, char*, int);
15
static	int	powerinstlen(Map*, uvlong);
16
static	int	powerdas(Map*, uvlong, char*, int);
17
 
18
/*
19
 *	Machine description
20
 */
21
Machdata powermach =
22
{
23
	{0x02, 0x8f, 0xff, 0xff},		/* break point */	/* BUG */
24
	4,			/* break point size */
25
 
26
	beswab,			/* short to local byte order */
27
	beswal,			/* long to local byte order */
28
	beswav,			/* vlong to local byte order */
29
	risctrace,		/* print C traceback */
30
	riscframe,		/* frame finder */
31
	powerexcep,		/* print exception */
32
	0,			/* breakpoint fixup */
33
	beieeesftos,		/* single precision float printer */
34
	beieeedftos,		/* double precisioin float printer */
35
	powerfoll,		/* following addresses */
36
	powerinst,		/* print instruction */
37
	powerdas,		/* dissembler */
38
	powerinstlen,		/* instruction size */
39
};
40
 
41
static char *excname[] =
42
{
43
	"reserved 0",
44
	"system reset",
45
	"machine check",
46
	"data access",
47
	"instruction access",
48
	"external interrupt",
49
	"alignment",
50
	"program exception",
51
	"floating-point unavailable",
52
	"decrementer",
53
	"i/o controller interface error",
54
	"reserved B",
55
	"system call",
56
	"trace trap",
57
	"floating point assist",
58
	"reserved",
59
	"ITLB miss",
60
	"DTLB load miss",
61
	"DTLB store miss",
62
	"instruction address breakpoint"
63
	"SMI interrupt"
64
	"reserved 15",
65
	"reserved 16",
66
	"reserved 17",
67
	"reserved 18",
68
	"reserved 19",
69
	"reserved 1A",
70
	/* the following are made up on a program exception */
71
	"floating point exception",		/* FPEXC */
72
	"illegal instruction",
73
	"privileged instruction",
74
	"trap",
75
	"illegal operation",
76
};
77
 
78
static char*
79
powerexcep(Map *map, Rgetter rget)
80
{
81
	long c;
82
	static char buf[32];
83
 
84
	c = (*rget)(map, "CAUSE") >> 8;
85
	if(c < nelem(excname))
86
		return excname[c];
87
	sprint(buf, "unknown trap #%lx", c);
88
	return buf;
89
}
90
 
91
/*
92
 * disassemble PowerPC opcodes
93
 */
94
 
95
#define	REGSP	1	/* should come from q.out.h, but there's a clash */
96
#define	REGSB	2
97
 
98
static	char FRAMENAME[] = ".frame";
99
 
100
static Map *mymap;
101
 
102
/*
103
 * ibm conventions for these: bit 0 is top bit
104
 *	from table 10-1
105
 */
106
typedef struct {
107
	uchar	aa;		/* bit 30 */
108
	uchar	crba;		/* bits 11-15 */
109
	uchar	crbb;		/* bits 16-20 */
110
	long	bd;		/* bits 16-29 */
111
	uchar	crfd;		/* bits 6-8 */
112
	uchar	crfs;		/* bits 11-13 */
113
	uchar	bi;		/* bits 11-15 */
114
	uchar	bo;		/* bits 6-10 */
115
	uchar	crbd;		/* bits 6-10 */
116
	union {
117
		short	d;	/* bits 16-31 */
118
		short	simm;
119
		ushort	uimm;
120
	};
121
	uchar	fm;		/* bits 7-14 */
122
	uchar	fra;		/* bits 11-15 */
123
	uchar	frb;		/* bits 16-20 */
124
	uchar	frc;		/* bits 21-25 */
125
	uchar	frs;		/* bits 6-10 */
126
	uchar	frd;		/* bits 6-10 */
127
	uchar	crm;		/* bits 12-19 */
128
	long	li;		/* bits 6-29 || b'00' */
129
	uchar	lk;		/* bit 31 */
130
	uchar	mb;		/* bits 21-25 */
131
	uchar	me;		/* bits 26-30 */
132
	uchar	xmbe;		/* bits 26,21-25: mb[5] || mb[0:4], also xme */
133
	uchar	xsh;		/* bits 30,16-20: sh[5] || sh[0:4] */
134
	uchar	nb;		/* bits 16-20 */
135
	uchar	op;		/* bits 0-5 */
136
	uchar	oe;		/* bit 21 */
137
	uchar	ra;		/* bits 11-15 */
138
	uchar	rb;		/* bits 16-20 */
139
	uchar	rc;		/* bit 31 */
140
	union {
141
		uchar	rs;	/* bits 6-10 */
142
		uchar	rd;
143
	};
144
	uchar	sh;		/* bits 16-20 */
145
	ushort	spr;		/* bits 11-20 */
146
	uchar	to;		/* bits 6-10 */
147
	uchar	imm;		/* bits 16-19 */
148
	ushort	xo;		/* bits 21-30, 22-30, 26-30, or 30 (beware) */
149
	uvlong	imm64;
150
	long w0;
151
	long w1;
152
	uvlong	addr;		/* pc of instruction */
153
	short	target;
154
	short	m64;		/* 64-bit mode */
155
	char	*curr;		/* current fill level in output buffer */
156
	char	*end;		/* end of buffer */
157
	int 	size;		/* number of longs in instr */
158
	char	*err;		/* errmsg */
159
} Instr;
160
 
161
#define	IBF(v,a,b) (((ulong)(v)>>(32-(b)-1)) & ~(~0L<<(((b)-(a)+1))))
162
#define	IB(v,b) IBF((v),(b),(b))
163
 
164
#pragma	varargck	argpos	bprint		2
165
 
166
static void
167
bprint(Instr *i, char *fmt, ...)
168
{
169
	va_list arg;
170
 
171
	va_start(arg, fmt);
172
	i->curr = vseprint(i->curr, i->end, fmt, arg);
173
	va_end(arg);
174
}
175
 
176
static int
177
decode(uvlong pc, Instr *i)
178
{
179
	ulong w;
180
 
181
	if (get4(mymap, pc, &w) < 0) {
182
		werrstr("can't read instruction: %r");
183
		return -1;
184
	}
185
	i->m64 = asstype == APOWER64;
186
	i->aa = IB(w, 30);
187
	i->crba = IBF(w, 11, 15);
188
	i->crbb = IBF(w, 16, 20);
189
	i->bd = IBF(w, 16, 29)<<2;
190
	if(i->bd & 0x8000)
191
		i->bd |= ~0L<<16;
192
	i->crfd = IBF(w, 6, 8);
193
	i->crfs = IBF(w, 11, 13);
194
	i->bi = IBF(w, 11, 15);
195
	i->bo = IBF(w, 6, 10);
196
	i->crbd = IBF(w, 6, 10);
197
	i->uimm = IBF(w, 16, 31);	/* also d, simm */
198
	i->fm = IBF(w, 7, 14);
199
	i->fra = IBF(w, 11, 15);
200
	i->frb = IBF(w, 16, 20);
201
	i->frc = IBF(w, 21, 25);
202
	i->frs = IBF(w, 6, 10);
203
	i->frd = IBF(w, 6, 10);
204
	i->crm = IBF(w, 12, 19);
205
	i->li = IBF(w, 6, 29)<<2;
206
	if(IB(w, 6))
207
		i->li |= ~0<<25;
208
	i->lk = IB(w, 31);
209
	i->mb = IBF(w, 21, 25);
210
	i->me = IBF(w, 26, 30);
211
	i->xmbe = (IB(w,26)<<5) | i->mb;
212
	i->nb = IBF(w, 16, 20);
213
	i->op = IBF(w, 0, 5);
214
	i->oe = IB(w, 21);
215
	i->ra = IBF(w, 11, 15);
216
	i->rb = IBF(w, 16, 20);
217
	i->rc = IB(w, 31);
218
	i->rs = IBF(w, 6, 10);	/* also rd */
219
	i->sh = IBF(w, 16, 20);
220
	i->xsh = (IB(w, 30)<<5) | i->sh;
221
	i->spr = IBF(w, 11, 20);
222
	i->to = IBF(w, 6, 10);
223
	i->imm = IBF(w, 16, 19);
224
	i->xo = IBF(w, 21, 30);		/* bits 21-30, 22-30, 26-30, or 30 (beware) */
225
	if(i->op == 58){	/* class of 64-bit loads */
226
		i->xo = i->simm & 3;
227
		i->simm &= ~3;
228
	}
229
	i->imm64 = i->simm;
230
	if(i->op == 15)
231
		i->imm64 <<= 16;
232
	else if(i->op == 25 || i->op == 27 || i->op == 29)
233
		i->imm64 = (uvlong)(i->uimm<<16);
234
	i->w0 = w;
235
	i->target = -1;
236
	i->addr = pc;
237
	i->size = 1;
238
	return 1;
239
}
240
 
241
static int
242
mkinstr(uvlong pc, Instr *i)
243
{
244
	Instr x;
245
 
246
	if(decode(pc, i) < 0)
247
		return -1;
248
	/*
249
	 * combine ADDIS/ORI (CAU/ORIL) into MOVW
250
	 * also ORIS/ORIL for unsigned in 64-bit mode
251
	 */
252
	if ((i->op == 15 || i->op == 25) && i->ra==0) {
253
		if(decode(pc+4, &x) < 0)
254
			return -1;
255
		if (x.op == 24 && x.rs == x.ra && x.ra == i->rd) {
256
			i->imm64 |= (x.imm64 & 0xFFFF);
257
			if(i->op != 15)
258
				i->imm64 &= 0xFFFFFFFFUL;
259
			i->w1 = x.w0;
260
			i->target = x.rd;
261
			i->size++;
262
			return 1;
263
		}
264
	}
265
	return 1;
266
}
267
 
268
static int
269
plocal(Instr *i)
270
{
271
	long offset;
272
	Symbol s;
273
 
274
	if (!findsym(i->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s))
275
		return -1;
276
	offset = s.value - i->imm64;
277
	if (offset > 0) {
278
		if(getauto(&s, offset, CAUTO, &s)) {
279
			bprint(i, "%s+%lld(SP)", s.name, s.value);
280
			return 1;
281
		}
282
	} else {
283
		if (getauto(&s, -offset-4, CPARAM, &s)) {
284
			bprint(i, "%s+%ld(FP)", s.name, -offset);
285
			return 1;
286
		}
287
	}
288
	return -1;
289
}
290
 
291
static int
292
pglobal(Instr *i, uvlong off, int anyoff, char *reg)
293
{
294
	Symbol s, s2;
295
	uvlong off1;
296
 
297
	if(findsym(off, CANY, &s) &&
298
	   off-s.value < 4096 &&
299
	   (s.class == CDATA || s.class == CTEXT)) {
300
		if(off==s.value && s.name[0]=='$'){
301
			off1 = 0;
302
			geta(mymap, s.value, &off1);
303
			if(off1 && findsym(off1, CANY, &s2) && s2.value == off1){
304
				bprint(i, "$%s%s", s2.name, reg);
305
				return 1;
306
			}
307
		}
308
		bprint(i, "%s", s.name);
309
		if (s.value != off)
310
			bprint(i, "+%llux", off-s.value);
311
		bprint(i, reg);
312
		return 1;
313
	}
314
	if(!anyoff)
315
		return 0;
316
	bprint(i, "%llux%s", off, reg);
317
	return 1;
318
}
319
 
320
static void
321
address(Instr *i)
322
{
323
	if (i->ra == REGSP && plocal(i) >= 0)
324
		return;
325
	if (i->ra == REGSB && mach->sb && pglobal(i, mach->sb+i->imm64, 0, "(SB)"))
326
		return;
327
	if(i->simm < 0)
328
		bprint(i, "-%x(R%d)", -i->simm, i->ra);
329
	else
330
		bprint(i, "%llux(R%d)", i->imm64, i->ra);
331
}
332
 
333
static	char	*tcrbits[] = {"LT", "GT", "EQ", "VS"};
334
static	char	*fcrbits[] = {"GE", "LE", "NE", "VC"};
335
 
336
typedef struct Opcode Opcode;
337
 
338
struct Opcode {
339
	uchar	op;
340
	ushort	xo;
341
	ushort	xomask;
342
	char	*mnemonic;
343
	void	(*f)(Opcode *, Instr *);
344
	char	*ken;
345
	int	flags;
346
};
347
 
348
static void format(char *, Instr *, char *);
349
 
350
static void
351
branch(Opcode *o, Instr *i)
352
{
353
	char buf[8];
354
	int bo, bi;
355
 
356
	bo = i->bo & ~1;	/* ignore prediction bit */
357
	if(bo==4 || bo==12 || bo==20) {	/* simple forms */
358
		if(bo != 20) {
359
			bi = i->bi&3;
360
			sprint(buf, "B%s%%L", bo==12? tcrbits[bi]: fcrbits[bi]);
361
			format(buf, i, nil);
362
			bprint(i, "\t");
363
			if(i->bi > 4)
364
				bprint(i, "CR(%d),", i->bi/4);
365
		} else
366
			format("BR%L\t", i, nil);
367
		if(i->op == 16)
368
			format(0, i, "%J");
369
		else if(i->op == 19 && i->xo == 528)
370
			format(0, i, "(CTR)");
371
		else if(i->op == 19 && i->xo == 16)
372
			format(0, i, "(LR)");
373
	} else
374
		format(o->mnemonic, i, o->ken);
375
}
376
 
377
static void
378
addi(Opcode *o, Instr *i)
379
{
380
	if (i->op==14 && i->ra == 0)
381
		format("MOVW", i, "%i,R%d");
382
	else if (i->ra == REGSB) {
383
		bprint(i, "MOVW\t$");
384
		address(i);
385
		bprint(i, ",R%d", i->rd);
386
	} else if(i->op==14 && i->simm < 0) {
387
		bprint(i, "SUB\t$%d,R%d", -i->simm, i->ra);
388
		if(i->rd != i->ra)
389
			bprint(i, ",R%d", i->rd);
390
	} else if(i->ra == i->rd) {
391
		format(o->mnemonic, i, "%i");
392
		bprint(i, ",R%d", i->rd);
393
	} else
394
		format(o->mnemonic, i, o->ken);
395
}
396
 
397
static void
398
addis(Opcode *o, Instr *i)
399
{
400
	long v;
401
 
402
	v = i->imm64;
403
	if (i->op==15 && i->ra == 0)
404
		bprint(i, "MOVW\t$%lux,R%d", v, i->rd);
405
	else if (i->op==15 && i->ra == REGSB) {
406
		bprint(i, "MOVW\t$");
407
		address(i);
408
		bprint(i, ",R%d", i->rd);
409
	} else if(i->op==15 && v < 0) {
410
		bprint(i, "SUB\t$%ld,R%d", -v, i->ra);
411
		if(i->rd != i->ra)
412
			bprint(i, ",R%d", i->rd);
413
	} else {
414
		format(o->mnemonic, i, nil);
415
		bprint(i, "\t$%ld,R%d", v, i->ra);
416
		if(i->rd != i->ra)
417
			bprint(i, ",R%d", i->rd);
418
	}
419
}
420
 
421
static void
422
andi(Opcode *o, Instr *i)
423
{
424
	if (i->ra == i->rs)
425
		format(o->mnemonic, i, "%I,R%d");
426
	else
427
		format(o->mnemonic, i, o->ken);
428
}
429
 
430
static void
431
gencc(Opcode *o, Instr *i)
432
{
433
	format(o->mnemonic, i, o->ken);
434
}
435
 
436
static void
437
gen(Opcode *o, Instr *i)
438
{
439
	format(o->mnemonic, i, o->ken);
440
	if (i->rc)
441
		bprint(i, " [illegal Rc]");
442
}
443
 
444
static void
445
ldx(Opcode *o, Instr *i)
446
{
447
	if(i->ra == 0)
448
		format(o->mnemonic, i, "(R%b),R%d");
449
	else
450
		format(o->mnemonic, i, "(R%b+R%a),R%d");
451
	if(i->rc)
452
		bprint(i, " [illegal Rc]");
453
}
454
 
455
static void
456
stx(Opcode *o, Instr *i)
457
{
458
	if(i->ra == 0)
459
		format(o->mnemonic, i, "R%d,(R%b)");
460
	else
461
		format(o->mnemonic, i, "R%d,(R%b+R%a)");
462
	if(i->rc && i->xo != 150)
463
		bprint(i, " [illegal Rc]");
464
}
465
 
466
static void
467
fldx(Opcode *o, Instr *i)
468
{
469
	if(i->ra == 0)
470
		format(o->mnemonic, i, "(R%b),F%d");
471
	else
472
		format(o->mnemonic, i, "(R%b+R%a),F%d");
473
	if(i->rc)
474
		bprint(i, " [illegal Rc]");
475
}
476
 
477
static void
478
fstx(Opcode *o, Instr *i)
479
{
480
	if(i->ra == 0)
481
		format(o->mnemonic, i, "F%d,(R%b)");
482
	else
483
		format(o->mnemonic, i, "F%d,(R%b+R%a)");
484
	if(i->rc)
485
		bprint(i, " [illegal Rc]");
486
}
487
 
488
static void
489
dcb(Opcode *o, Instr *i)
490
{
491
	if(i->ra == 0)
492
		format(o->mnemonic, i, "(R%b)");
493
	else
494
		format(o->mnemonic, i, "(R%b+R%a)");
495
	if(i->rd)
496
		bprint(i, " [illegal Rd]");
497
	if(i->rc)
498
		bprint(i, " [illegal Rc]");
499
}
500
 
501
static void
502
lw(Opcode *o, Instr *i, char r)
503
{
504
	format(o->mnemonic, i, nil);
505
	bprint(i, "\t");
506
	address(i);
507
	bprint(i, ",%c%d", r, i->rd);
508
}
509
 
510
static void
511
load(Opcode *o, Instr *i)
512
{
513
	lw(o, i, 'R');
514
}
515
 
516
static void
517
fload(Opcode *o, Instr *i)
518
{
519
	lw(o, i, 'F');
520
}
521
 
522
static void
523
sw(Opcode *o, Instr *i, char r)
524
{
525
	int offset;
526
	Symbol s;
527
 
528
	if (i->rs == REGSP) {
529
		if (findsym(i->addr, CTEXT, &s) && findlocal(&s, FRAMENAME, &s)) {
530
			offset = s.value-i->imm64;
531
			if (offset > 0 && getauto(&s, offset, CAUTO, &s)) {
532
				format(o->mnemonic, i, nil);
533
				bprint(i, "\t%c%d,%s-%d(SP)", r, i->rd, s.name, offset);
534
				return;
535
			}
536
		}
537
	}
538
	if (i->rs == REGSB && mach->sb) {
539
		format(o->mnemonic, i, nil);
540
		bprint(i, "\t%c%d,", r, i->rd);
541
		address(i);
542
		return;
543
	}
544
	if (r == 'F')
545
		format(o->mnemonic, i, "F%d,%l");
546
	else
547
		format(o->mnemonic, i, o->ken);
548
}
549
 
550
static void
551
store(Opcode *o, Instr *i)
552
{
553
	sw(o, i, 'R');
554
}
555
 
556
static void
557
fstore(Opcode *o, Instr *i)
558
{
559
	sw(o, i, 'F');
560
}
561
 
562
static void
563
shifti(Opcode *o, Instr *i)
564
{
565
	if (i->ra == i->rs)
566
		format(o->mnemonic, i, "$%k,R%a");
567
	else
568
		format(o->mnemonic, i, o->ken);
569
}
570
 
571
static void
572
shift(Opcode *o, Instr *i)
573
{
574
	if (i->ra == i->rs)
575
		format(o->mnemonic, i, "R%b,R%a");
576
	else
577
		format(o->mnemonic, i, o->ken);
578
}
579
 
580
static void
581
add(Opcode *o, Instr *i)
582
{
583
	if (i->rd == i->ra)
584
		format(o->mnemonic, i, "R%b,R%d");
585
	else if (i->rd == i->rb)
586
		format(o->mnemonic, i, "R%a,R%d");
587
	else
588
		format(o->mnemonic, i, o->ken);
589
}
590
 
591
static void
592
sub(Opcode *o, Instr *i)
593
{
594
	format(o->mnemonic, i, nil);
595
	bprint(i, "\t");
596
	if(i->op == 31) {
597
		bprint(i, "\tR%d,R%d", i->ra, i->rb);	/* subtract Ra from Rb */
598
		if(i->rd != i->rb)
599
			bprint(i, ",R%d", i->rd);
600
	} else
601
		bprint(i, "\tR%d,$%d,R%d", i->ra, i->simm, i->rd);
602
}
603
 
604
static void
605
qdiv(Opcode *o, Instr *i)
606
{
607
	format(o->mnemonic, i, nil);
608
	if(i->op == 31)
609
		bprint(i, "\tR%d,R%d", i->rb, i->ra);
610
	else
611
		bprint(i, "\t$%d,R%d", i->simm, i->ra);
612
	if(i->ra != i->rd)
613
		bprint(i, ",R%d", i->rd);
614
}
615
 
616
static void
617
and(Opcode *o, Instr *i)
618
{
619
	if (i->op == 31) {
620
		/* Rb,Rs,Ra */
621
		if (i->ra == i->rs)
622
			format(o->mnemonic, i, "R%b,R%a");
623
		else if (i->ra == i->rb)
624
			format(o->mnemonic, i, "R%s,R%a");
625
		else
626
			format(o->mnemonic, i, o->ken);
627
	} else {
628
		/* imm,Rs,Ra */
629
		if (i->ra == i->rs)
630
			format(o->mnemonic, i, "%I,R%a");
631
		else
632
			format(o->mnemonic, i, o->ken);
633
	}
634
}
635
 
636
static void
637
or(Opcode *o, Instr *i)
638
{
639
	if (i->op == 31) {
640
		/* Rb,Rs,Ra */
641
		if (i->rs == 0 && i->ra == 0 && i->rb == 0)
642
			format("NOP", i, nil);
643
		else if (i->rs == i->rb)
644
			format("MOVW", i, "R%b,R%a");
645
		else
646
			and(o, i);
647
	} else
648
		and(o, i);
649
}
650
 
651
static void
652
shifted(Opcode *o, Instr *i)
653
{
654
	format(o->mnemonic, i, nil);
655
	bprint(i, "\t$%lux,", (ulong)i->uimm<<16);
656
	if (i->rs == i->ra)
657
		bprint(i, "R%d", i->ra);
658
	else
659
		bprint(i, "R%d,R%d", i->rs, i->ra);
660
}
661
 
662
static void
663
neg(Opcode *o, Instr *i)
664
{
665
	if (i->rd == i->ra)
666
		format(o->mnemonic, i, "R%d");
667
	else
668
		format(o->mnemonic, i, o->ken);
669
}
670
 
671
static	char	ir2[] = "R%a,R%d";		/* reverse of IBM order */
672
static	char	ir3[] = "R%b,R%a,R%d";
673
static	char	ir3r[] = "R%a,R%b,R%d";
674
static	char	il3[] = "R%b,R%s,R%a";
675
static	char	il2u[] = "%I,R%d,R%a";
676
static	char	il3s[] = "$%k,R%s,R%a";
677
static	char	il2[] = "R%s,R%a";
678
static	char	icmp3[] = "R%a,R%b,%D";
679
static	char	cr3op[] = "%b,%a,%d";
680
static	char	ir2i[] = "%i,R%a,R%d";
681
static	char	fp2[] = "F%b,F%d";
682
static	char	fp3[] = "F%b,F%a,F%d";
683
static	char	fp3c[] = "F%c,F%a,F%d";
684
static	char	fp4[] = "F%a,F%c,F%b,F%d";
685
static	char	fpcmp[] = "F%a,F%b,%D";
686
static	char	ldop[] = "%l,R%d";
687
static	char	stop[] = "R%d,%l";
688
static	char	fldop[] = "%l,F%d";
689
static	char	fstop[] = "F%d,%l";
690
static	char	rldc[] = "R%b,R%s,$%E,R%a";
691
static	char	rlim[] = "R%b,R%s,$%z,R%a";
692
static	char	rlimi[] = "$%k,R%s,$%z,R%a";
693
static	char	rldi[] = "$%e,R%s,$%E,R%a";
694
 
695
#define	OEM	IBF(~0,22,30)
696
#define	FP4	IBF(~0,26,30)
697
#define	ALL	(~0)
698
#define	RLDC	0xF
699
#define	RLDI	0xE
700
/*
701
notes:
702
	10-26: crfD = rD>>2; rD&3 mbz
703
		also, L bit (bit 10) mbz or selects 64-bit operands
704
*/
705
 
706
static Opcode opcodes[] = {
707
	{31,	266,	OEM,	"ADD%V%C",	add,	ir3},
708
	{31,	 10,	OEM,	"ADDC%V%C",	add,	ir3},
709
	{31,	138,	OEM,	"ADDE%V%C",	add,	ir3},
710
	{14,	0,	0,	"ADD",		addi,	ir2i},
711
	{12,	0,	0,	"ADDC",		addi,	ir2i},
712
	{13,	0,	0,	"ADDCCC",	addi,	ir2i},
713
	{15,	0,	0,	"ADD",		addis,	0},
714
	{31,	234,	OEM,	"ADDME%V%C",	gencc,	ir2},
715
	{31,	202,	OEM,	"ADDZE%V%C",	gencc,	ir2},
716
 
717
	{31,	28,	ALL,	"AND%C",	and,	il3},
718
	{31,	60,	ALL,	"ANDN%C",	and,	il3},
719
	{28,	0,	0,	"ANDCC",	andi,	il2u},
720
	{29,	0,	0,	"ANDCC",	shifted, 0},
721
 
722
	{18,	0,	0,	"B%L",		gencc,	"%j"},
723
	{16,	0,	0,	"BC%L",		branch,	"%d,%a,%J"},
724
	{19,	528,	ALL,	"BC%L",		branch,	"%d,%a,(CTR)"},
725
	{19,	16,	ALL,	"BC%L",		branch,	"%d,%a,(LR)"},
726
 
727
	{31,	0,	ALL,	"CMP",		0,	icmp3},
728
	{11,	0,	0,	"CMP",		0,	"R%a,%i,%D"},
729
	{31,	32,	ALL,	"CMPU",		0,	icmp3},
730
	{10,	0,	0,	"CMPU",		0,	"R%a,%I,%D"},
731
 
732
	{31,	58,	ALL,	"CNTLZD%C",	gencc,	ir2},	/* 64 */
733
	{31,	26,	ALL,	"CNTLZ%W%C",	gencc,	ir2},
734
 
735
	{19,	257,	ALL,	"CRAND",	gen,	cr3op},
736
	{19,	129,	ALL,	"CRANDN",	gen,	cr3op},
737
	{19,	289,	ALL,	"CREQV",	gen,	cr3op},
738
	{19,	225,	ALL,	"CRNAND",	gen,	cr3op},
739
	{19,	33,	ALL,	"CRNOR",	gen,	cr3op},
740
	{19,	449,	ALL,	"CROR",		gen,	cr3op},
741
	{19,	417,	ALL,	"CRORN",	gen,	cr3op},
742
	{19,	193,	ALL,	"CRXOR",	gen,	cr3op},
743
 
744
	{31,	86,	ALL,	"DCBF",		dcb,	0},
745
	{31,	470,	ALL,	"DCBI",		dcb,	0},
746
	{31,	54,	ALL,	"DCBST",	dcb,	0},
747
	{31,	278,	ALL,	"DCBT",		dcb,	0},
748
	{31,	246,	ALL,	"DCBTST",	dcb,	0},
749
	{31,	1014,	ALL,	"DCBZ",		dcb,	0},
750
	{31,	454,	ALL,	"DCCCI",	dcb,	0},
751
	{31,	966,	ALL,	"ICCCI",	dcb,	0},
752
 
753
	{31,	489,	OEM,	"DIVD%V%C",	qdiv,	ir3},	/* 64 */
754
	{31,	457,	OEM,	"DIVDU%V%C",	qdiv,	ir3},	/* 64 */
755
	{31,	491,	OEM,	"DIVW%V%C",	qdiv,	ir3},
756
	{31,	459,	OEM,	"DIVWU%V%C",	qdiv,	ir3},
757
 
758
	{31,	310,	ALL,	"ECIWX",	ldx,	0},
759
	{31,	438,	ALL,	"ECOWX",	stx,	0},
760
	{31,	854,	ALL,	"EIEIO",	gen,	0},
761
 
762
	{31,	284,	ALL,	"EQV%C",	gencc,	il3},
763
 
764
	{31,	954,	ALL,	"EXTSB%C",	gencc,	il2},
765
	{31,	922,	ALL,	"EXTSH%C",	gencc,	il2},
766
	{31,	986,	ALL,	"EXTSW%C",	gencc,	il2},	/* 64 */
767
 
768
	{63,	264,	ALL,	"FABS%C",	gencc,	fp2},
769
	{63,	21,	ALL,	"FADD%C",	gencc,	fp3},
770
	{59,	21,	ALL,	"FADDS%C",	gencc,	fp3},
771
	{63,	32,	ALL,	"FCMPO",	gen,	fpcmp},
772
	{63,	0,	ALL,	"FCMPU",	gen,	fpcmp},
773
	{63,	846,	ALL,	"FCFID%C",	gencc,	fp2},	/* 64 */
774
	{63,	814,	ALL,	"FCTID%C",	gencc,	fp2},	/* 64 */
775
	{63,	815,	ALL,	"FCTIDZ%C",	gencc,	fp2},	/* 64 */
776
	{63,	14,	ALL,	"FCTIW%C",	gencc,	fp2},
777
	{63,	15,	ALL,	"FCTIWZ%C",	gencc,	fp2},
778
	{63,	18,	ALL,	"FDIV%C",	gencc,	fp3},
779
	{59,	18,	ALL,	"FDIVS%C",	gencc,	fp3},
780
	{63,	29,	FP4,	"FMADD%C",	gencc,	fp4},
781
	{59,	29,	FP4,	"FMADDS%C",	gencc,	fp4},
782
	{63,	72,	ALL,	"FMOVD%C",	gencc,	fp2},
783
	{63,	28,	FP4,	"FMSUB%C",	gencc,	fp4},
784
	{59,	28,	FP4,	"FMSUBS%C",	gencc,	fp4},
785
	{63,	25,	FP4,	"FMUL%C",	gencc,	fp3c},
786
	{59,	25,	FP4,	"FMULS%C",	gencc,	fp3c},
787
	{63,	136,	ALL,	"FNABS%C",	gencc,	fp2},
788
	{63,	40,	ALL,	"FNEG%C",	gencc,	fp2},
789
	{63,	31,	FP4,	"FNMADD%C",	gencc,	fp4},
790
	{59,	31,	FP4,	"FNMADDS%C",	gencc,	fp4},
791
	{63,	30,	FP4,	"FNMSUB%C",	gencc,	fp4},
792
	{59,	30,	FP4,	"FNMSUBS%C",	gencc,	fp4},
793
	{59,	24,	ALL,	"FRES%C",	gencc,	fp2},	/* optional */
794
	{63,	12,	ALL,	"FRSP%C",	gencc,	fp2},
795
	{63,	26,	ALL,	"FRSQRTE%C",	gencc,	fp2},	/* optional */
796
	{63,	23,	FP4,	"FSEL%CC",	gencc,	fp4},	/* optional */
797
	{63,	22,	ALL,	"FSQRT%C",	gencc,	fp2},	/* optional */
798
	{59,	22,	ALL,	"FSQRTS%C",	gencc,	fp2},	/* optional */
799
	{63,	20,	FP4,	"FSUB%C",	gencc,	fp3},
800
	{59,	20,	FP4,	"FSUBS%C",	gencc,	fp3},
801
 
802
	{31,	982,	ALL,	"ICBI",		dcb,	0},	/* optional */
803
	{19,	150,	ALL,	"ISYNC",	gen,	0},
804
 
805
	{34,	0,	0,	"MOVBZ",	load,	ldop},
806
	{35,	0,	0,	"MOVBZU",	load,	ldop},
807
	{31,	119,	ALL,	"MOVBZU",	ldx,	0},
808
	{31,	87,	ALL,	"MOVBZ",	ldx,	0},
809
	{50,	0,	0,	"FMOVD",	fload,	fldop},
810
	{51,	0,	0,	"FMOVDU",	fload,	fldop},
811
	{31,	631,	ALL,	"FMOVDU",	fldx,	0},
812
	{31,	599,	ALL,	"FMOVD",	fldx,	0},
813
	{48,	0,	0,	"FMOVS",	load,	fldop},
814
	{49,	0,	0,	"FMOVSU",	load,	fldop},
815
	{31,	567,	ALL,	"FMOVSU",	fldx,	0},
816
	{31,	535,	ALL,	"FMOVS",	fldx,	0},
817
	{42,	0,	0,	"MOVH",		load,	ldop},
818
	{43,	0,	0,	"MOVHU",	load,	ldop},
819
	{31,	375,	ALL,	"MOVHU",	ldx,	0},
820
	{31,	343,	ALL,	"MOVH",		ldx,	0},
821
	{31,	790,	ALL,	"MOVHBR",	ldx,	0},
822
	{40,	0,	0,	"MOVHZ",	load,	ldop},
823
	{41,	0,	0,	"MOVHZU",	load,	ldop},
824
	{31,	311,	ALL,	"MOVHZU",	ldx,	0},
825
	{31,	279,	ALL,	"MOVHZ",	ldx,	0},
826
	{46,	0,	0,	"MOVMW",	load,	ldop},
827
	{31,	597,	ALL,	"LSW",		gen,	"(R%a),$%n,R%d"},
828
	{31,	533,	ALL,	"LSW",		ldx,	0},
829
	{31,	20,	ALL,	"LWAR",		ldx,	0},
830
	{31,	84,	ALL,	"LWARD",	ldx,	0},	/* 64 */
831
 
832
	{58,	0,	ALL,	"MOVD",		load,	ldop},	/* 64 */
833
	{58,	1,	ALL,	"MOVDU",	load,	ldop},	/* 64 */
834
	{31,	53,	ALL,	"MOVDU",	ldx,	0},	/* 64 */
835
	{31,	21,	ALL,	"MOVD",		ldx,	0},	/* 64 */
836
 
837
	{31,	534,	ALL,	"MOVWBR",	ldx,	0},
838
 
839
	{58,	2,	ALL,	"MOVW",		load,	ldop},	/* 64 (lwa) */
840
	{31,	373,	ALL,	"MOVWU",	ldx,	0},	/* 64 */
841
	{31,	341,	ALL,	"MOVW",		ldx,	0},	/* 64 */
842
 
843
	{32,	0,	0,	"MOVW%Z",	load,	ldop},
844
	{33,	0,	0,	"MOVW%ZU",	load,	ldop},
845
	{31,	55,	ALL,	"MOVW%ZU",	ldx,	0},
846
	{31,	23,	ALL,	"MOVW%Z",	ldx,	0},
847
 
848
	{19,	0,	ALL,	"MOVFL",	gen,	"%S,%D"},
849
	{63,	64,	ALL,	"MOVCRFS",	gen,	"%S,%D"},
850
	{31,	512,	ALL,	"MOVW",		gen,	"XER,%D"},
851
	{31,	19,	ALL,	"MOVW",		gen,	"CR,R%d"},
852
 
853
	{63,	583,	ALL,	"MOVW%C",	gen,	"FPSCR, F%d"},	/* mffs */
854
	{31,	83,	ALL,	"MOVW",		gen,	"MSR,R%d"},
855
	{31,	339,	ALL,	"MOVW",		gen,	"%P,R%d"},
856
	{31,	595,	ALL,	"MOVW",		gen,	"SEG(%a),R%d"},
857
	{31,	659,	ALL,	"MOVW",		gen,	"SEG(R%b),R%d"},
858
	{31,	323,	ALL,	"MOVW",		gen,	"DCR(%Q),R%d"},
859
	{31,	451,	ALL,	"MOVW",		gen,	"R%s,DCR(%Q)"},
860
	{31,	259,	ALL,	"MOVW",		gen,	"DCR(R%a),R%d"},
861
	{31,	387,	ALL,	"MOVW",		gen,	"R%s,DCR(R%a)"},
862
	{31,	144,	ALL,	"MOVFL",	gen,	"R%s,%m,CR"},
863
	{63,	70,	ALL,	"MTFSB0%C",	gencc,	"%D"},
864
	{63,	38,	ALL,	"MTFSB1%C",	gencc,	"%D"},
865
	{63,	711,	ALL,	"MOVFL%C",	gencc,	"F%b,%M,FPSCR"},	/* mtfsf */
866
	{63,	134,	ALL,	"MOVFL%C",	gencc,	"%K,%D"},
867
	{31,	146,	ALL,	"MOVW",		gen,	"R%s,MSR"},
868
	{31,	178,	ALL,	"MOVD",		gen,	"R%s,MSR"},
869
	{31,	467,	ALL,	"MOVW",		gen,	"R%s,%P"},
870
	{31,	210,	ALL,	"MOVW",		gen,	"R%s,SEG(%a)"},
871
	{31,	242,	ALL,	"MOVW",		gen,	"R%s,SEG(R%b)"},
872
 
873
	{31,	73,	ALL,	"MULHD%C",	gencc,	ir3},
874
	{31,	9,	ALL,	"MULHDU%C",	gencc,	ir3},
875
	{31,	233,	OEM,	"MULLD%V%C",	gencc,	ir3},
876
 
877
	{31,	75,	ALL,	"MULHW%C",	gencc,	ir3},
878
	{31,	11,	ALL,	"MULHWU%C",	gencc,	ir3},
879
	{31,	235,	OEM,	"MULLW%V%C",	gencc,	ir3},
880
 
881
	{7,	0,	0,	"MULLW",	qdiv,	"%i,R%a,R%d"},
882
 
883
	{31,	476,	ALL,	"NAND%C",	gencc,	il3},
884
	{31,	104,	OEM,	"NEG%V%C",	neg,	ir2},
885
	{31,	124,	ALL,	"NOR%C",	gencc,	il3},
886
	{31,	444,	ALL,	"OR%C",		or,	il3},
887
	{31,	412,	ALL,	"ORN%C",	or,	il3},
888
	{24,	0,	0,	"OR",		and,	"%I,R%d,R%a"},
889
	{25,	0,	0,	"OR",		shifted, 0},
890
 
891
	{19,	50,	ALL,	"RFI",		gen,	0},
892
	{19,	51,	ALL,	"RFCI",		gen,	0},
893
 
894
	{30,	8,	RLDC,	"RLDCL%C",	gencc,	rldc},	/* 64 */
895
	{30,	9,	RLDC,	"RLDCR%C",	gencc,	rldc},	/* 64 */
896
	{30,	0,	RLDI,	"RLDCL%C",	gencc,	rldi},	/* 64 */
897
	{30,	1<<1, RLDI,	"RLDCR%C",	gencc,	rldi},	/* 64 */
898
	{30,	2<<1, RLDI,	"RLDC%C",	gencc,	rldi},	/* 64 */
899
	{30,	3<<1, RLDI,	"RLDMI%C",	gencc,	rldi},	/* 64 */
900
 
901
	{20,	0,	0,	"RLWMI%C",	gencc,	rlimi},
902
	{21,	0,	0,	"RLWNM%C",	gencc,	rlimi},
903
	{23,	0,	0,	"RLWNM%C",	gencc,	rlim},
904
 
905
	{17,	1,	ALL,	"SYSCALL",	gen,	0},
906
 
907
	{31,	27,	ALL,	"SLD%C",	shift,	il3},	/* 64 */
908
	{31,	24,	ALL,	"SLW%C",	shift,	il3},
909
 
910
	{31,	794,	ALL,	"SRAD%C",	shift,	il3},	/* 64 */
911
	{31,	(413<<1)|0,	ALL,	"SRAD%C",	shifti,	il3s},	/* 64 */
912
	{31,	(413<<1)|1,	ALL,	"SRAD%C",	shifti,	il3s},	/* 64 */
913
	{31,	792,	ALL,	"SRAW%C",	shift,	il3},
914
	{31,	824,	ALL,	"SRAW%C",	shifti,	il3s},
915
 
916
	{31,	539,	ALL,	"SRD%C",	shift,	il3},	/* 64 */
917
	{31,	536,	ALL,	"SRW%C",	shift,	il3},
918
 
919
	{38,	0,	0,	"MOVB",		store,	stop},
920
	{39,	0,	0,	"MOVBU",	store,	stop},
921
	{31,	247,	ALL,	"MOVBU",	stx,	0},
922
	{31,	215,	ALL,	"MOVB",		stx,	0},
923
	{54,	0,	0,	"FMOVD",	fstore,	fstop},
924
	{55,	0,	0,	"FMOVDU",	fstore,	fstop},
925
	{31,	759,	ALL,	"FMOVDU",	fstx,	0},
926
	{31,	727,	ALL,	"FMOVD",	fstx,	0},
927
	{52,	0,	0,	"FMOVS",	fstore,	fstop},
928
	{53,	0,	0,	"FMOVSU",	fstore,	fstop},
929
	{31,	695,	ALL,	"FMOVSU",	fstx,	0},
930
	{31,	663,	ALL,	"FMOVS",	fstx,	0},
931
	{44,	0,	0,	"MOVH",		store,	stop},
932
	{31,	918,	ALL,	"MOVHBR",	stx,	0},
933
	{45,	0,	0,	"MOVHU",	store,	stop},
934
	{31,	439,	ALL,	"MOVHU",	stx,	0},
935
	{31,	407,	ALL,	"MOVH",		stx,	0},
936
	{47,	0,	0,	"MOVMW",	store,	stop},
937
	{31,	725,	ALL,	"STSW",		gen,	"R%d,$%n,(R%a)"},
938
	{31,	661,	ALL,	"STSW",		stx,	0},
939
	{36,	0,	0,	"MOVW",		store,	stop},
940
	{31,	662,	ALL,	"MOVWBR",	stx,	0},
941
	{31,	150,	ALL,	"STWCCC",	stx,	0},
942
	{31,	214,	ALL,	"STDCCC",	stx,	0},	/* 64 */
943
	{37,	0,	0,	"MOVWU",	store,	stop},
944
	{31,	183,	ALL,	"MOVWU",	stx,	0},
945
	{31,	151,	ALL,	"MOVW",		stx,	0},
946
 
947
	{62,	0,	0,	"MOVD%U",	store,	stop},	/* 64 */
948
	{31,	149,	ALL,	"MOVD",		stx,	0,},	/* 64 */
949
	{31,	181,	ALL,	"MOVDU",	stx,	0},	/* 64 */
950
 
951
	{31,	498,	ALL,	"SLBIA",	gen,	0},	/* 64 */
952
	{31,	434,	ALL,	"SLBIE",	gen,	"R%b"},	/* 64 */
953
	{31,	466,	ALL,	"SLBIEX",	gen,	"R%b"},	/* 64 */
954
	{31,	915,	ALL,	"SLBMFEE",	gen,	"R%b,R%d"},	/* 64 */
955
	{31,	851,	ALL,	"SLBMFEV",	gen,	"R%b,R%d"},	/* 64 */
956
	{31,	402,	ALL,	"SLBMTE",	gen,	"R%s,R%b"},	/* 64 */
957
 
958
	{31,	40,	OEM,	"SUB%V%C",	sub,	ir3},
959
	{31,	8,	OEM,	"SUBC%V%C",	sub,	ir3},
960
	{31,	136,	OEM,	"SUBE%V%C",	sub,	ir3},
961
	{8,	0,	0,	"SUBC",		gen,	"R%a,%i,R%d"},
962
	{31,	232,	OEM,	"SUBME%V%C",	sub,	ir2},
963
	{31,	200,	OEM,	"SUBZE%V%C",	sub,	ir2},
964
 
965
	{31,	598,	ALL,	"SYNC",		gen,	0},	/* TO DO: there's a parameter buried in there */
966
	{2,	0,	0,	"TD",		gen,	"%d,R%a,%i"},	/* 64 */
967
	{31,	370,	ALL,	"TLBIA",	gen,	0},	/* optional */
968
	{31,	306,	ALL,	"TLBIE",	gen,	"R%b"},	/* optional */
969
	{31,	274,	ALL,	"TLBIEL",	gen,	"R%b"},	/* optional */
970
	{31,	1010,	ALL,	"TLBLI",	gen,	"R%b"},	/* optional */
971
	{31,	978,	ALL,	"TLBLD",	gen,	"R%b"},	/* optional */
972
	{31,	566,	ALL,	"TLBSYNC",	gen,	0},	/* optional */
973
	{31,	68,	ALL,	"TD",		gen,	"%d,R%a,R%b"},	/* 64 */
974
	{31,	4,	ALL,	"TW",		gen,	"%d,R%a,R%b"},
975
	{3,	0,	0,	"TW",		gen,	"%d,R%a,%i"},
976
 
977
	{31,	316,	ALL,	"XOR",		and,	il3},
978
	{26,	0,	0,	"XOR",		and,	il2u},
979
	{27,	0,	0,	"XOR",		shifted, 0},
980
 
981
	{0},
982
};
983
 
984
typedef struct Spr Spr;
985
struct Spr {
986
	int	n;
987
	char	*name;
988
};
989
 
990
static	Spr	sprname[] = {
991
	{0, "MQ"},
992
	{1, "XER"},
993
	{268, "TBL"},
994
	{269, "TBU"},
995
	{8, "LR"},
996
	{9, "CTR"},
997
	{528, "IBAT0U"},
998
	{529, "IBAT0L"},
999
	{530, "IBAT1U"},
1000
	{531, "IBAT1L"},
1001
	{532, "IBAT2U"},
1002
	{533, "IBAT2L"},
1003
	{534, "IBAT3U"},
1004
	{535, "IBAT3L"},
1005
	{536, "DBAT0U"},
1006
	{537, "DBAT0L"},
1007
	{538, "DBAT1U"},
1008
	{539, "DBAT1L"},
1009
	{540, "DBAT2U"},
1010
	{541, "DBAT2L"},
1011
	{542, "DBAT3U"},
1012
	{543, "DBAT3L"},
1013
	{25, "SDR1"},
1014
	{19, "DAR"},
1015
	{272, "SPRG0"},
1016
	{273, "SPRG1"},
1017
	{274, "SPRG2"},
1018
	{275, "SPRG3"},
1019
	{18, "DSISR"},
1020
	{26, "SRR0"},
1021
	{27, "SRR1"},
1022
	{284, "TBLW"},
1023
	{285, "TBUW"},	
1024
	{22, "DEC"},
1025
	{282, "EAR"},
1026
	{1008, "HID0"},
1027
	{1009, "HID1"},
1028
	{976, "DMISS"},
1029
	{977, "DCMP"},
1030
	{978, "HASH1"},
1031
	{979, "HASH2"},
1032
	{980, "IMISS"},
1033
	{981, "ICMP"},
1034
	{982, "RPA"},
1035
	{1010, "IABR"},
1036
	{1013, "DABR"},
1037
	{0,0},
1038
};
1039
 
1040
static int
1041
shmask(uvlong *m)
1042
{
1043
	int i;
1044
 
1045
	for(i=0; i<63; i++)
1046
		if(*m & ((uvlong)1<<i))
1047
			break;
1048
	if(i > 63)
1049
		return 0;
1050
	if(*m & ~((uvlong)1<<i)){	/* more than one bit: do multiples of bytes */
1051
		i = (i/8)*8;
1052
		if(i == 0)
1053
			return 0;
1054
	}
1055
	*m >>= i;
1056
	return i;
1057
}
1058
 
1059
static void
1060
format(char *mnemonic, Instr *i, char *f)
1061
{
1062
	int n, s;
1063
	ulong mask;
1064
	uvlong vmask;
1065
 
1066
	if (mnemonic)
1067
		format(0, i, mnemonic);
1068
	if (f == 0)
1069
		return;
1070
	if (mnemonic)
1071
		bprint(i, "\t");
1072
	for ( ; *f; f++) {
1073
		if (*f != '%') {
1074
			bprint(i, "%c", *f);
1075
			continue;
1076
		}
1077
		switch (*++f) {
1078
 
1079
		case 'a':
1080
			bprint(i, "%d", i->ra);
1081
			break;
1082
 
1083
		case 'b':
1084
			bprint(i, "%d", i->rb);
1085
			break;
1086
 
1087
		case 'c':
1088
			bprint(i, "%d", i->frc);
1089
			break;
1090
 
1091
		case 'd':
1092
		case 's':
1093
			bprint(i, "%d", i->rd);
1094
			break;
1095
 
1096
		case 'C':
1097
			if(i->rc)
1098
				bprint(i, "CC");
1099
			break;
1100
 
1101
		case 'D':
1102
			if(i->rd & 3)
1103
				bprint(i, "CR(INVAL:%d)", i->rd);
1104
			else if(i->op == 63)
1105
				bprint(i, "FPSCR(%d)", i->crfd);
1106
			else
1107
				bprint(i, "CR(%d)", i->crfd);
1108
			break;
1109
 
1110
		case 'e':
1111
			bprint(i, "%d", i->xsh);
1112
			break;
1113
 
1114
		case 'E':
1115
			switch(IBF(i->w0,27,30)){	/* low bit is top bit of shift in rldiX cases */
1116
			case 8:	i->mb = i->xmbe; i->me = 63; break;	/* rldcl */
1117
			case 9:	i->mb = 0; i->me = i->xmbe; break;	/* rldcr */
1118
			case 4: case 5:
1119
					i->mb = i->xmbe; i->me = 63-i->xsh; break;	/* rldic */
1120
			case 0: case 1:
1121
					i->mb = i->xmbe; i->me = 63; break;	/* rldicl */
1122
			case 2: case 3:
1123
					i->mb = 0; i->me = i->xmbe; break;	/* rldicr */
1124
			case 6: case 7:
1125
					i->mb = i->xmbe; i->me = 63-i->xsh; break;	/* rldimi */
1126
			}
1127
			vmask = (~(uvlong)0>>i->mb) & (~(uvlong)0<<(63-i->me));
1128
			s = shmask(&vmask);
1129
			if(s)
1130
				bprint(i, "(%llux<<%d)", vmask, s);
1131
			else
1132
				bprint(i, "%llux", vmask);
1133
			break;
1134
 
1135
		case 'i':
1136
			bprint(i, "$%d", i->simm);
1137
			break;
1138
 
1139
		case 'I':
1140
			bprint(i, "$%ux", i->uimm);
1141
			break;
1142
 
1143
		case 'j':
1144
			if(i->aa)
1145
				pglobal(i, i->li, 1, "(SB)");
1146
			else
1147
				pglobal(i, i->addr+i->li, 1, "");
1148
			break;
1149
 
1150
		case 'J':
1151
			if(i->aa)
1152
				pglobal(i, i->bd, 1, "(SB)");
1153
			else
1154
				pglobal(i, i->addr+i->bd, 1, "");
1155
			break;
1156
 
1157
		case 'k':
1158
			bprint(i, "%d", i->sh);
1159
			break;
1160
 
1161
		case 'K':
1162
			bprint(i, "$%x", i->imm);
1163
			break;
1164
 
1165
		case 'L':
1166
			if(i->lk)
1167
				bprint(i, "L");
1168
			break;
1169
 
1170
		case 'l':
1171
			if(i->simm < 0)
1172
				bprint(i, "-%x(R%d)", -i->simm, i->ra);
1173
			else
1174
				bprint(i, "%x(R%d)", i->simm, i->ra);
1175
			break;
1176
 
1177
		case 'm':
1178
			bprint(i, "%ux", i->crm);
1179
			break;
1180
 
1181
		case 'M':
1182
			bprint(i, "%ux", i->fm);
1183
			break;
1184
 
1185
		case 'n':
1186
			bprint(i, "%d", i->nb==0? 32: i->nb);	/* eg, pg 10-103 */
1187
			break;
1188
 
1189
		case 'P':
1190
			n = ((i->spr&0x1f)<<5)|((i->spr>>5)&0x1f);
1191
			for(s=0; sprname[s].name; s++)
1192
				if(sprname[s].n == n)
1193
					break;
1194
			if(sprname[s].name) {
1195
				if(s < 10)
1196
					bprint(i, sprname[s].name);
1197
				else
1198
					bprint(i, "SPR(%s)", sprname[s].name);
1199
			} else
1200
				bprint(i, "SPR(%d)", n);
1201
			break;
1202
 
1203
		case 'Q':
1204
			n = ((i->spr&0x1f)<<5)|((i->spr>>5)&0x1f);
1205
			bprint(i, "%d", n);
1206
			break;
1207
 
1208
		case 'S':
1209
			if(i->ra & 3)
1210
				bprint(i, "CR(INVAL:%d)", i->ra);
1211
			else if(i->op == 63)
1212
				bprint(i, "FPSCR(%d)", i->crfs);
1213
			else
1214
				bprint(i, "CR(%d)", i->crfs);
1215
			break;
1216
 
1217
		case 'U':
1218
			if(i->rc)
1219
				bprint(i, "U");
1220
			break;
1221
 
1222
		case 'V':
1223
			if(i->oe)
1224
				bprint(i, "V");
1225
			break;
1226
 
1227
		case 'w':
1228
			bprint(i, "[%lux]", i->w0);
1229
			break;
1230
 
1231
		case 'W':
1232
			if(i->m64)
1233
				bprint(i, "W");
1234
			break;
1235
 
1236
		case 'Z':
1237
			if(i->m64)
1238
				bprint(i, "Z");
1239
			break;
1240
 
1241
		case 'z':
1242
			if(i->mb <= i->me)
1243
				mask = ((ulong)~0L>>i->mb) & (~0L<<(31-i->me));
1244
			else
1245
				mask = ~(((ulong)~0L>>(i->me+1)) & (~0L<<(31-(i->mb-1))));
1246
			bprint(i, "%lux", mask);
1247
			break;
1248
 
1249
		case '\0':
1250
			bprint(i, "%%");
1251
			return;
1252
 
1253
		default:
1254
			bprint(i, "%%%c", *f);
1255
			break;
1256
		}
1257
	}
1258
}
1259
 
1260
static int
1261
printins(Map *map, uvlong pc, char *buf, int n)
1262
{
1263
	Instr i;
1264
	Opcode *o;
1265
 
1266
	mymap = map;
1267
	memset(&i, 0, sizeof(i));
1268
	i.curr = buf;
1269
	i.end = buf+n-1;
1270
	if(mkinstr(pc, &i) < 0)
1271
		return -1;
1272
	for(o = opcodes; o->mnemonic != 0; o++)
1273
		if(i.op == o->op && (i.xo & o->xomask) == o->xo) {
1274
			if (o->f)
1275
				(*o->f)(o, &i);
1276
			else
1277
				format(o->mnemonic, &i, o->ken);
1278
			return i.size*4;
1279
		}
1280
	bprint(&i, "unknown %lux", i.w0);
1281
	return i.size*4;
1282
}
1283
 
1284
static int
1285
powerinst(Map *map, uvlong pc, char modifier, char *buf, int n)
1286
{
1287
	USED(modifier);
1288
	return printins(map, pc, buf, n);
1289
}
1290
 
1291
static int
1292
powerdas(Map *map, uvlong pc, char *buf, int n)
1293
{
1294
	Instr instr;
1295
 
1296
	mymap = map;
1297
	memset(&instr, 0, sizeof(instr));
1298
	instr.curr = buf;
1299
	instr.end = buf+n-1;
1300
	if (mkinstr(pc, &instr) < 0)
1301
		return -1;
1302
	if (instr.end-instr.curr > 8)
1303
		instr.curr = _hexify(instr.curr, instr.w0, 7);
1304
	if (instr.end-instr.curr > 9 && instr.size == 2) {
1305
		*instr.curr++ = ' ';
1306
		instr.curr = _hexify(instr.curr, instr.w1, 7);
1307
	}
1308
	*instr.curr = 0;
1309
	return instr.size*4;
1310
}
1311
 
1312
static int
1313
powerinstlen(Map *map, uvlong pc)
1314
{
1315
	Instr i;
1316
 
1317
	mymap = map;
1318
	if (mkinstr(pc, &i) < 0)
1319
		return -1;
1320
	return i.size*4;
1321
}
1322
 
1323
static int
1324
powerfoll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
1325
{
1326
	char *reg;
1327
	Instr i;
1328
 
1329
	mymap = map;
1330
	if (mkinstr(pc, &i) < 0)
1331
		return -1;
1332
	foll[0] = pc+4;
1333
	foll[1] = pc+4;
1334
	switch(i.op) {
1335
	default:
1336
		return 1;
1337
 
1338
	case 18:	/* branch */
1339
		foll[0] = i.li;
1340
		if(!i.aa)
1341
			foll[0] += pc;
1342
		break;
1343
 
1344
	case 16:	/* conditional branch */
1345
		foll[0] = i.bd;
1346
		if(!i.aa)
1347
			foll[0] += pc;
1348
		break;
1349
 
1350
	case 19:	/* conditional branch to register */
1351
		if(i.xo == 528)
1352
			reg = "CTR";
1353
		else if(i.xo == 16)
1354
			reg = "LR";
1355
		else
1356
			return 1;	/* not a branch */
1357
		foll[0] = (*rget)(map, reg);
1358
		break;
1359
	}
1360
	if(i.lk)
1361
		return 2;
1362
	return 1;
1363
}