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
 * Sparc-specific debugger interface
8
 */
9
 
10
static	char	*sparcexcep(Map*, Rgetter);
11
static	int	sparcfoll(Map*, uvlong, Rgetter, uvlong*);
12
static	int	sparcinst(Map*, uvlong, char, char*, int);
13
static	int	sparcdas(Map*, uvlong, char*, int);
14
static	int	sparcinstlen(Map*, uvlong);
15
 
16
Machdata sparcmach =
17
{
18
	{0x91, 0xd0, 0x20, 0x01},	/* breakpoint: TA $1 */
19
	4,			/* break point size */
20
 
21
	beswab,			/* convert short to local byte order */
22
	beswal,			/* convert long to local byte order */
23
	beswav,			/* convert vlong to local byte order */
24
	risctrace,		/* C traceback */
25
	riscframe,		/* frame finder */
26
	sparcexcep,		/* print exception */
27
	0,			/* breakpoint fixup */
28
	beieeesftos,		/* single precision float printer */
29
	beieeedftos,		/* double precision float printer */
30
	sparcfoll,		/* following addresses */
31
	sparcinst,		/* print instruction */
32
	sparcdas,		/* dissembler */
33
	sparcinstlen,		/* instruction size */
34
};
35
 
36
static char *trapname[] =
37
{
38
	"reset",
39
	"instruction access exception",
40
	"illegal instruction",
41
	"privileged instruction",
42
	"fp disabled",
43
	"window overflow",
44
	"window underflow",
45
	"unaligned address",
46
	"fp exception",
47
	"data access exception",
48
	"tag overflow",
49
};
50
 
51
static char*
52
excname(ulong tbr)
53
{
54
	static char buf[32];
55
 
56
	if(tbr < sizeof trapname/sizeof(char*))
57
		return trapname[tbr];
58
	if(tbr >= 130)
59
		sprint(buf, "trap instruction %ld", tbr-128);
60
	else if(17<=tbr && tbr<=31)
61
		sprint(buf, "interrupt level %ld", tbr-16);
62
	else switch(tbr){
63
	case 36:
64
		return "cp disabled";
65
	case 40:
66
		return "cp exception";
67
	case 128:
68
		return "syscall";
69
	case 129:
70
		return "breakpoint";
71
	default:
72
		sprint(buf, "unknown trap %ld", tbr);
73
	}
74
	return buf;
75
}
76
 
77
static char*
78
sparcexcep(Map *map, Rgetter rget)
79
{
80
	long tbr;
81
 
82
	tbr = (*rget)(map, "TBR");
83
	tbr = (tbr&0xFFF)>>4;
84
	return excname(tbr);
85
}
86
 
87
	/* Sparc disassembler and related functions */
88
 
89
struct opcode {
90
	char	*mnemonic;
91
	void	(*f)(struct instr*, char*);
92
	int	flag;
93
};
94
 
95
static	char FRAMENAME[] = ".frame";
96
 
97
typedef struct instr Instr;
98
 
99
struct instr {
100
	uchar	op;		/* bits 31-30 */
101
	uchar	rd;		/* bits 29-25 */
102
	uchar	op2;		/* bits 24-22 */
103
	uchar	a;		/* bit  29    */
104
	uchar	cond;		/* bits 28-25 */
105
	uchar	op3;		/* bits 24-19 */
106
	uchar	rs1;		/* bits 18-14 */
107
	uchar	i;		/* bit  13    */
108
	uchar	asi;		/* bits 12-05 */
109
	uchar	rs2;		/* bits 04-00 */
110
	short	simm13;		/* bits 12-00, signed */
111
	ushort	opf;		/* bits 13-05 */
112
	ulong	immdisp22;	/* bits 21-00 */
113
	ulong	simmdisp22;	/* bits 21-00, signed */
114
	ulong	disp30;		/* bits 30-00 */
115
	ulong	imm32;		/* SETHI+ADD constant */
116
	int	target;		/* SETHI+ADD dest reg */
117
	long	w0;
118
	long	w1;
119
	uvlong	addr;		/* pc of instruction */
120
	char	*curr;		/* current fill level in output buffer */
121
	char	*end;		/* end of buffer */
122
	int 	size;		/* number of longs in instr */
123
	char	*err;		/* errmsg */
124
};
125
 
126
static	Map	*mymap;		/* disassembler context */
127
static	int	dascase;
128
 
129
static int	mkinstr(uvlong, Instr*);
130
static void	bra1(Instr*, char*, char*[]);
131
static void	bra(Instr*, char*);
132
static void	fbra(Instr*, char*);
133
static void	cbra(Instr*, char*);
134
static void	unimp(Instr*, char*);
135
static void	fpop(Instr*, char*);
136
static void	shift(Instr*, char*);
137
static void	sethi(Instr*, char*);
138
static void	load(Instr*, char*);
139
static void	loada(Instr*, char*);
140
static void	store(Instr*, char*);
141
static void	storea(Instr*, char*);
142
static void	add(Instr*, char*);
143
static void	cmp(Instr*, char*);
144
static void	wr(Instr*, char*);
145
static void	jmpl(Instr*, char*);
146
static void	rd(Instr*, char*);
147
static void	loadf(Instr*, char*);
148
static void	storef(Instr*, char*);
149
static void	loadc(Instr*, char*);
150
static void	loadcsr(Instr*, char*);
151
static void	trap(Instr*, char*);
152
 
153
static struct opcode sparcop0[8] = {
154
	[0]	"UNIMP",	unimp,	0,	/* page 137 */
155
	[2]	"B",		bra,	0,	/* page 119 */
156
	[4]	"SETHI",	sethi,	0,	/* page 104 */
157
	[6]	"FB",		fbra,	0,	/* page 121 */
158
	[7]	"CB",		cbra,	0,	/* page 123 */
159
};
160
 
161
static struct opcode sparcop2[64] = {
162
	[0x00]	"ADD",		add,	0,	/* page 108 */
163
	[0x10]	"ADDCC",	add,	0,
164
	[0x08]	"ADDX",		add,	0,
165
	[0x18]	"ADDXCC",	add,	0,
166
 
167
	[0x20]	"TADD",		add,	0,	/* page 109 */
168
	[0x22]	"TADDCCTV",	add,	0,
169
 
170
	[0x04]	"SUB",		add,	0,	/* page 110 */
171
	[0x14]	"SUBCC",	cmp,	0,
172
	[0x0C]	"SUBX",		add,	0,
173
	[0x1C]	"SUBXCC",	add,	0,
174
 
175
	[0x21]	"TSUB",		add,	0,	/* page 111 */
176
	[0x23]	"TSUBCCTV",	add,	0,
177
 
178
	[0x24]	"MULSCC",	add,	0,	/* page 112 */
179
 
180
	[0x0A]	"UMUL",		add,	0,	/* page 113 */
181
	[0x0B]	"SMUL",		add,	0,
182
	[0x1A]	"UMULCC",	add,	0,
183
	[0x1B]	"SMULCC",	add,	0,
184
 
185
	[0x0E]	"UDIV",		add,	0,	/* page 115 */
186
	[0x0F]	"SDIV",		add,	0,
187
	[0x1E]	"UDIVCC",	add,	0,
188
	[0x1F]	"SDIVCC",	add,	0,
189
 
190
	[0x01]	"AND",		add,	0,	/* page 106 */
191
	[0x11]	"ANDCC",	add,	0,
192
	[0x05]	"ANDN",		add,	0,
193
	[0x15]	"ANDNCC",	add,	0,
194
	[0x02]	"OR",		add,	0,
195
	[0x12]	"ORCC",		add,	0,
196
	[0x06]	"ORN",		add,	0,
197
	[0x16]	"ORNCC",	add,	0,
198
	[0x03]	"XOR",		add,	0,
199
	[0x13]	"XORCC",	add,	0,
200
	[0x07]	"XORN",		add,	0,
201
	[0x17]	"XORNCC",	add,	0,
202
 
203
	[0x25]	"SLL",		shift,	0,	/* page 107 */
204
	[0x26]	"SRL",		shift,	0,
205
	[0x27]	"SRA",		shift,	0,
206
 
207
	[0x3C]	"SAVE",		add,	0,	/* page 117 */
208
	[0x3D]	"RESTORE",	add,	0,
209
 
210
	[0x38]	"JMPL",		jmpl,	0,	/* page 126 */
211
 
212
	[0x39]	"RETT",		add,	0,	/* page 127 */
213
 
214
	[0x3A]	"T",		trap,	0,	/* page 129 */
215
 
216
	[0x28]	"rdy",		rd,	0,	/* page 131 */
217
	[0x29]	"rdpsr",	rd,	0,
218
	[0x2A]	"rdwim",	rd,	0,
219
	[0x2B]	"rdtbr",	rd,	0,
220
 
221
	[0x30]	"wry",		wr,	0,	/* page 133 */
222
	[0x31]	"wrpsr",	wr,	0,
223
	[0x32]	"wrwim",	wr,	0,
224
	[0x33]	"wrtbr",	wr,	0,
225
 
226
	[0x3B]	"flush",	add,	0,	/* page 138 */
227
 
228
	[0x34]	"FPOP",		fpop,	0,	/* page 140 */
229
	[0x35]	"FPOP",		fpop,	0,
230
};
231
 
232
static struct opcode sparcop3[64]={
233
	[0x09]	"ldsb",		load,	0,	/* page 90 */
234
	[0x19]	"ldsba",	loada,	0,
235
	[0x0A]	"ldsh",		load,	0,
236
	[0x1A]	"ldsha",	loada,	0,
237
	[0x01]	"ldub",		load,	0,
238
	[0x11]	"lduba",	loada,	0,
239
	[0x02]	"lduh",		load,	0,
240
	[0x12]	"lduha",	loada,	0,
241
	[0x00]	"ld",		load,	0,
242
	[0x10]	"lda",		loada,	0,
243
	[0x03]	"ldd",		load,	0,
244
	[0x13]	"ldda",		loada,	0,
245
 
246
	[0x20]	"ldf",		loadf,	0,	/* page 92 */
247
	[0x23]	"lddf",		loadf,	0,
248
	[0x21]	"ldfsr",	loadf,0,
249
 
250
	[0x30]	"ldc",		loadc,	0,	/* page 94 */
251
	[0x33]	"lddc",		loadc,	0,
252
	[0x31]	"ldcsr",	loadcsr,0,
253
 
254
	[0x05]	"stb",		store,	0,	/* page 95 */
255
	[0x15]	"stba",		storea,	0,
256
	[0x06]	"sth",		store,	0,
257
	[0x16]	"stha",		storea,	0,
258
	[0x04]	"st",		store,	0,
259
	[0x14]	"sta",		storea,	0,
260
	[0x07]	"std",		store,	0,
261
	[0x17]	"stda",		storea,	0,
262
 
263
	[0x24]	"stf",		storef,	0,	/* page 97 */
264
	[0x27]	"stdf",		storef,	0,
265
	[0x25]	"stfsr",	storef,0,
266
	[0x26]	"stdfq",	storef,0,
267
 
268
	[0x34]	"stc",		loadc,	0,	/* page 99 */
269
	[0x37]	"stdc",		loadc,	0,
270
	[0x35]	"stcsr",	loadcsr,0,
271
	[0x36]	"stdcq",	loadcsr,0,
272
 
273
	[0x0D]	"ldstub",	store,	0,	/* page 101 */
274
	[0x1D]	"ldstuba",	storea,	0,
275
 
276
	[0x0F]	"swap",		load,	0,	/* page 102 */
277
	[0x1F]	"swapa",	loada,	0,
278
};
279
 
280
#pragma	varargck	argpos	bprint	2
281
#pragma	varargck	type	"T"	char*
282
 
283
/* convert to lower case from upper, according to dascase */
284
static int
285
Tfmt(Fmt *f)
286
{
287
	char buf[128];
288
	char *s, *t, *oa;
289
 
290
	oa = va_arg(f->args, char*);
291
	if(dascase){
292
		for(s=oa,t=buf; *t = *s; s++,t++)
293
			if('A'<=*t && *t<='Z')
294
				*t += 'a'-'A';
295
		return fmtstrcpy(f, buf);
296
	}
297
	return fmtstrcpy(f, oa);
298
}
299
 
300
static void
301
bprint(Instr *i, char *fmt, ...)
302
{
303
	va_list arg;
304
 
305
	va_start(arg, fmt);
306
	i->curr = vseprint(i->curr, i->end, fmt, arg);
307
	va_end(arg);
308
}
309
 
310
static int
311
decode(uvlong pc, Instr *i)
312
{
313
	ulong w;
314
 
315
	if (get4(mymap, pc, &w) < 0) {
316
		werrstr("can't read instruction: %r");
317
		return -1;
318
	}
319
	i->op = (w >> 30) & 0x03;
320
	i->rd = (w >> 25) & 0x1F;
321
	i->op2 = (w >> 22) & 0x07;
322
	i->a = (w >> 29) & 0x01;
323
	i->cond = (w >> 25) & 0x0F;
324
	i->op3 = (w >> 19) & 0x3F;
325
	i->rs1 = (w >> 14) & 0x1F;
326
	i->i = (w >> 13) & 0x01;
327
	i->asi = (w >> 5) & 0xFF;
328
	i->rs2 = (w >> 0) & 0x1F;
329
	i->simm13 = (w >> 0) & 0x1FFF;
330
	if(i->simm13 & (1<<12))
331
		i->simm13 |= ~((1<<13)-1);
332
	i->opf = (w >> 5) & 0x1FF;
333
	i->immdisp22 = (w >> 0) & 0x3FFFFF;
334
	i->simmdisp22 = i->immdisp22;
335
	if(i->simmdisp22 & (1<<21))
336
		i->simmdisp22 |= ~((1<<22)-1);
337
	i->disp30 = (w >> 0) & 0x3FFFFFFF;
338
	i->w0 = w;
339
	i->target = -1;
340
	i->addr = pc;
341
	i->size = 1;
342
	return 1;
343
}
344
 
345
static int
346
mkinstr(uvlong pc, Instr *i)
347
{
348
	Instr xi;
349
 
350
	if (decode(pc, i) < 0)
351
		return -1;
352
	if(i->op==0 && i->op2==4 && !dascase){	/* SETHI */
353
		if (decode(pc+4, &xi) < 0)
354
			return -1;
355
		if(xi.op==2 && xi.op3==0)		/* ADD */
356
		if(xi.i == 1 && xi.rs1 == i->rd){	/* immediate to same reg */
357
			i->imm32 = xi.simm13 + (i->immdisp22<<10);
358
			i->target = xi.rd;
359
			i->w1 = xi.w0;
360
			i->size++;
361
			return 1;
362
		}
363
	}
364
	if(i->op==2 && i->opf==1 && !dascase){	/* FMOVS */
365
		if (decode(pc+4, &xi) < 0)
366
			return -1;
367
		if(i->op==2 && i->opf==1)		/* FMOVS */
368
		if(xi.rd==i->rd+1 && xi.rs2==i->rs2+1){	/* next pair */
369
			i->w1 = xi.w0;
370
			i->size++;
371
		}
372
	}
373
	return 1;
374
}
375
 
376
static int
377
printins(Map *map, uvlong pc, char *buf, int n)
378
{
379
	Instr instr;
380
	void (*f)(Instr*, char*);
381
 
382
	mymap = map;
383
	memset(&instr, 0, sizeof(instr));
384
	instr.curr = buf;
385
	instr.end = buf+n-1;
386
	if (mkinstr(pc, &instr) < 0)
387
		return -1;
388
	switch(instr.op){
389
	case 0:
390
		f = sparcop0[instr.op2].f;
391
		if(f)
392
			(*f)(&instr, sparcop0[instr.op2].mnemonic);
393
		else
394
			bprint(&instr, "unknown %lux", instr.w0);
395
		break;
396
 
397
	case 1:
398
		bprint(&instr, "%T", "CALL\t");
399
		instr.curr += symoff(instr.curr, instr.end-instr.curr,
400
					pc+instr.disp30*4, CTEXT);
401
		if (!dascase)
402
			bprint(&instr, "(SB)");
403
		break;
404
 
405
	case 2:
406
		f = sparcop2[instr.op3].f;
407
		if(f)
408
			(*f)(&instr, sparcop2[instr.op3].mnemonic);
409
		else
410
			bprint(&instr, "unknown %lux", instr.w0);
411
		break;
412
 
413
	case 3:
414
		f = sparcop3[instr.op3].f;
415
		if(f)
416
			(*f)(&instr, sparcop3[instr.op3].mnemonic);
417
		else
418
			bprint(&instr, "unknown %lux", instr.w0);
419
		break;
420
	}
421
	if (instr.err) {
422
		if (instr.curr != buf)
423
			bprint(&instr, "\t\t;");
424
		bprint(&instr, instr.err);
425
	}
426
	return instr.size*4;
427
}
428
 
429
static int
430
sparcinst(Map *map, uvlong pc, char modifier, char *buf, int n)
431
{
432
	static int fmtinstalled = 0;
433
 
434
		/* a modifier of 'I' toggles the dissassembler type */
435
	if (!fmtinstalled) {
436
		fmtinstalled = 1;
437
		fmtinstall('T', Tfmt);
438
	}
439
	if ((asstype == ASUNSPARC && modifier == 'i')
440
		|| (asstype == ASPARC && modifier == 'I'))
441
		dascase = 'a'-'A';
442
	else
443
		dascase = 0;
444
	return printins(map, pc, buf, n);
445
}
446
 
447
static int
448
sparcdas(Map *map, uvlong pc, char *buf, int n)
449
{
450
	Instr instr;
451
 
452
	mymap = map;
453
	memset(&instr, 0, sizeof(instr));
454
	instr.curr = buf;
455
	instr.end = buf+n-1;
456
	if (mkinstr(pc, &instr) < 0)
457
		return -1;
458
	if (instr.end-instr.curr > 8)
459
		instr.curr = _hexify(instr.curr, instr.w0, 7);
460
	if (instr.end-instr.curr > 9 && instr.size == 2) {
461
		*instr.curr++ = ' ';
462
		instr.curr = _hexify(instr.curr, instr.w1, 7);
463
	}
464
	*instr.curr = 0;
465
	return instr.size*4;
466
}
467
 
468
static int
469
sparcinstlen(Map *map, uvlong pc)
470
{
471
	Instr i;
472
 
473
	mymap = map;
474
	if (mkinstr(pc, &i) < 0)
475
		return -1;
476
	return i.size*4;
477
}
478
 
479
static int
480
plocal(Instr *i)
481
{
482
	int offset;
483
	Symbol s;
484
 
485
	if (!findsym(i->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s))
486
		return -1;
487
	if (s.value > i->simm13) {
488
		if(getauto(&s, s.value-i->simm13, CAUTO, &s)) {
489
			bprint(i, "%s+%lld(SP)", s.name, s.value);
490
			return 1;
491
		}
492
	} else {
493
		offset = i->simm13-s.value;
494
		if (getauto(&s, offset-4, CPARAM, &s)) {
495
			bprint(i, "%s+%d(FP)", s.name, offset);
496
			return 1;
497
		}
498
	}
499
	return -1;
500
}
501
 
502
static void
503
address(Instr *i)
504
{
505
	Symbol s, s2;
506
	uvlong off, off1;
507
 
508
	if (i->rs1 == 1 && plocal(i) >= 0)
509
		return;
510
	off = mach->sb+i->simm13;
511
	if(i->rs1 == 2	&& findsym(off, CANY, &s)
512
			&& s.value-off < 4096
513
			&& (s.class == CDATA || s.class == CTEXT)) {
514
		if(off==s.value && s.name[0]=='$'){
515
			off1 = 0;
516
			geta(mymap, s.value, &off1);
517
			if(off1 && findsym(off1, CANY, &s2) && s2.value == off1){
518
				bprint(i, "$%s(SB)", s2.name);
519
				return;
520
			}
521
		}
522
		bprint(i, "%s", s.name);
523
		if (s.value != off)
524
			bprint(i, "+%llux", s.value-off);
525
		bprint(i, "(SB)");
526
		return;
527
	}
528
	bprint(i, "%ux(R%d)", i->simm13, i->rs1);
529
}
530
 
531
static void
532
unimp(Instr *i, char *m)
533
{
534
	bprint(i, "%T", m);
535
}
536
 
537
static char	*bratab[16] = {	/* page 91 */
538
	[0X8]	"A",
539
	[0X0]	"N",
540
	[0X9]	"NE",
541
	[0X1]	"E",
542
	[0XA]	"G",
543
	[0X2]	"LE",
544
	[0XB]	"GE",
545
	[0X3]	"L",
546
	[0XC]	"GU",
547
	[0X4]	"LEU",
548
	[0XD]	"CC",
549
	[0X5]	"CS",
550
	[0XE]	"POS",
551
	[0X6]	"NEG",
552
	[0XF]	"VC",
553
	[0X7]	"VS",
554
};
555
 
556
static char	*fbratab[16] = {	/* page 91 */
557
	[0X8]	"A",
558
	[0X0]	"N",
559
	[0X7]	"U",
560
	[0X6]	"G",
561
	[0X5]	"UG",
562
	[0X4]	"L",
563
	[0X3]	"UL",
564
	[0X2]	"LG",
565
	[0X1]	"NE",
566
	[0X9]	"E",
567
	[0XA]	"UE",
568
	[0XB]	"GE",
569
	[0XC]	"UGE",
570
	[0XD]	"LE",
571
	[0XE]	"ULE",
572
	[0XF]	"O",
573
};
574
 
575
static char	*cbratab[16] = {	/* page 91 */
576
	[0X8]	"A",
577
	[0X0]	"N",
578
	[0X7]	"3",
579
	[0X6]	"2",
580
	[0X5]	"23",
581
	[0X4]	"1",
582
	[0X3]	"13",
583
	[0X2]	"12",
584
	[0X1]	"123",
585
	[0X9]	"0",
586
	[0XA]	"03",
587
	[0XB]	"02",
588
	[0XC]	"023",
589
	[0XD]	"01",
590
	[0XE]	"013",
591
	[0XF]	"012",
592
};
593
 
594
static void
595
bra1(Instr *i, char *m, char *tab[])
596
{
597
	long imm;
598
 
599
	imm = i->simmdisp22;
600
	if(i->a)
601
		bprint(i, "%T%T.%c\t", m, tab[i->cond], 'A'+dascase);
602
	else
603
		bprint(i, "%T%T\t", m, tab[i->cond]);
604
	i->curr += symoff(i->curr, i->end-i->curr, i->addr+4*imm, CTEXT);
605
	if (!dascase)
606
		bprint(i, "(SB)");
607
}
608
 
609
static void
610
bra(Instr *i, char *m)			/* page 91 */
611
{
612
	bra1(i, m, bratab);
613
}
614
 
615
static void
616
fbra(Instr *i, char *m)			/* page 93 */
617
{
618
	bra1(i, m, fbratab);
619
}
620
 
621
static void
622
cbra(Instr *i, char *m)			/* page 95 */
623
{
624
	bra1(i, m, cbratab);
625
}
626
 
627
static void
628
trap(Instr *i, char *m)			/* page 101 */
629
{
630
	if(i->i == 0)
631
		bprint(i, "%T%T\tR%d+R%d", m, bratab[i->cond], i->rs2, i->rs1);
632
	else
633
		bprint(i, "%T%T\t$%ux+R%d", m, bratab[i->cond], i->simm13, i->rs1);
634
}
635
 
636
static void
637
sethi(Instr *i, char *m)		/* page 89 */
638
{
639
	ulong imm;
640
 
641
	imm = i->immdisp22<<10;
642
	if(dascase){
643
		bprint(i, "%T\t%lux, R%d", m, imm, i->rd);
644
		return;
645
	}
646
	if(imm==0 && i->rd==0){
647
		bprint(i, "NOP");
648
		return;
649
	}
650
	if(i->target < 0){
651
		bprint(i, "MOVW\t$%lux, R%d", imm, i->rd);
652
		return;
653
	}
654
	bprint(i, "MOVW\t$%lux, R%d", i->imm32, i->target);
655
}
656
 
657
static char ldtab[] = {
658
	'W',
659
	'B',
660
	'H',
661
	'D',
662
};
663
 
664
static char*
665
moveinstr(int op3, char *m)
666
{
667
	char *s;
668
	int c;
669
	static char buf[8];
670
 
671
	if(!dascase){
672
		/* batshit cases */
673
		if(op3 == 0xF || op3 == 0x1F)
674
			return "SWAP";
675
		if(op3 == 0xD || op3 == 0x1D)
676
			return "TAS";	/* really LDSTUB */
677
		c = ldtab[op3&3];
678
		s = "";
679
		if((op3&11)==1 || (op3&11)==2)
680
			s="U";
681
		sprint(buf, "MOV%c%s", c, s);
682
		return buf;
683
	}
684
	return m;
685
}
686
 
687
static void
688
load(Instr *i, char *m)			/* page 68 */
689
{
690
	m = moveinstr(i->op3, m);
691
	if(i->i == 0)
692
		bprint(i, "%s\t(R%d+R%d), R%d", m, i->rs1, i->rs2, i->rd);
693
	else{
694
		bprint(i, "%s\t", m);
695
		address(i);
696
		bprint(i, ", R%d", i->rd);
697
	}
698
}
699
 
700
static void
701
loada(Instr *i, char *m)		/* page 68 */
702
{
703
	m = moveinstr(i->op3, m);
704
	if(i->i == 0)
705
		bprint(i, "%s\t(R%d+R%d, %d), R%d", m, i->rs1, i->rs2, i->asi, i->rd);
706
	else
707
		bprint(i, "unknown ld asi %lux", i->w0);
708
}
709
 
710
static void
711
store(Instr *i, char *m)		/* page 74 */
712
{
713
	m = moveinstr(i->op3, m);
714
	if(i->i == 0)
715
		bprint(i, "%s\tR%d, (R%d+R%d)",
716
				m, i->rd, i->rs1, i->rs2);
717
	else{
718
		bprint(i, "%s\tR%d, ", m, i->rd);
719
		address(i);
720
	}
721
}
722
 
723
static void
724
storea(Instr *i, char *m)		/* page 74 */
725
{
726
	m = moveinstr(i->op3, m);
727
	if(i->i == 0)
728
		bprint(i, "%s\tR%d, (R%d+R%d, %d)", m, i->rd, i->rs1, i->rs2, i->asi);
729
	else
730
		bprint(i, "%s\tR%d, %d(R%d, %d), ???", m, i->rd, i->simm13, i->rs1, i->asi);
731
}
732
 
733
static void
734
shift(Instr *i, char *m)	/* page 88 */
735
{
736
	if(i->i == 0){
737
		if(i->rs1 == i->rd)
738
			if(dascase)
739
				bprint(i, "%T\tR%d, R%d", m, i->rs1, i->rs2);
740
			else
741
				bprint(i, "%T\tR%d, R%d", m, i->rs2, i->rs1);
742
		else
743
			if(dascase)
744
				bprint(i, "%T\tR%d, R%d, R%d", m, i->rs1, i->rs2, i->rd);
745
			else
746
				bprint(i, "%T\tR%d, R%d, R%d", m, i->rs2, i->rs1, i->rd);
747
	}else{
748
		if(i->rs1 == i->rd)
749
			if(dascase)
750
				bprint(i, "%T\t$%d,R%d", m, i->simm13&0x1F, i->rs1);
751
			else
752
				bprint(i, "%T\tR%d, $%d", m,  i->rs1, i->simm13&0x1F);
753
		else
754
			if(dascase)
755
				bprint(i, "%T\tR%d, $%d, R%d",m,i->rs1,i->simm13&0x1F,i->rd);
756
			else
757
				bprint(i, "%T\t$%d, R%d, R%d",m,i->simm13&0x1F,i->rs1,i->rd);
758
	}
759
}
760
 
761
static void
762
add(Instr *i, char *m)	/* page 82 */
763
{
764
	if(i->i == 0){
765
		if(dascase)
766
			bprint(i, "%T\tR%d, R%d", m, i->rs1, i->rs2);
767
		else
768
			if(i->op3==2 && i->rs1==0 && i->rd)  /* OR R2, R0, R1 */
769
				bprint(i, "MOVW\tR%d", i->rs2);
770
			else
771
				bprint(i, "%T\tR%d, R%d", m, i->rs2, i->rs1);
772
	}else{
773
		if(dascase)
774
			bprint(i, "%T\tR%d, $%ux", m, i->rs1, i->simm13);
775
		else
776
			if(i->op3==0 && i->rd && i->rs1==0)	/* ADD $x, R0, R1 */
777
				bprint(i, "MOVW\t$%ux", i->simm13);
778
			else if(i->op3==0 && i->rd && i->rs1==2){
779
				/* ADD $x, R2, R1 -> MOVW $x(SB), R1 */
780
				bprint(i, "MOVW\t$");
781
				address(i);
782
			} else
783
				bprint(i, "%T\t$%ux, R%d", m, i->simm13, i->rs1);
784
	}
785
	if(i->rs1 != i->rd)
786
		bprint(i, ", R%d", i->rd);
787
}
788
 
789
static void
790
cmp(Instr *i, char *m)
791
{
792
	if(dascase || i->rd){
793
		add(i, m);
794
		return;
795
	}
796
	if(i->i == 0)
797
		bprint(i, "CMP\tR%d, R%d", i->rs1, i->rs2);
798
	else
799
		bprint(i, "CMP\tR%d, $%ux", i->rs1, i->simm13);
800
}
801
 
802
static char *regtab[4] = {
803
	"Y",
804
	"PSR",
805
	"WIM",
806
	"TBR",
807
};
808
 
809
static void
810
wr(Instr *i, char *m)		/* page 82 */
811
{
812
	if(dascase){
813
		if(i->i == 0)
814
			bprint(i, "%s\tR%d, R%d", m, i->rs1, i->rs2);
815
		else
816
			bprint(i, "%s\tR%d, $%ux", m, i->rs1, i->simm13);
817
	}else{
818
		if(i->i && i->simm13==0)
819
			bprint(i, "MOVW\tR%d", i->rs1);
820
		else if(i->i == 0)
821
			bprint(i, "wr\tR%d, R%d", i->rs2, i->rs1);
822
		else
823
			bprint(i, "wr\t$%ux, R%d", i->simm13, i->rs1);
824
	}
825
	bprint(i, ", %s", regtab[i->op3&3]);
826
}
827
 
828
static void
829
rd(Instr *i, char *m)		/* page 103 */
830
{
831
	if(i->rs1==15 && i->rd==0){
832
		m = "stbar";
833
		if(!dascase)
834
			m = "STBAR";
835
		bprint(i, "%s", m);
836
	}else{
837
		if(!dascase)
838
			m = "MOVW";
839
		bprint(i, "%s\t%s, R%d", m, regtab[i->op3&3], i->rd);
840
	}
841
}
842
 
843
static void
844
jmpl(Instr *i, char *m)		/* page 82 */
845
{
846
	if(i->i == 0){
847
		if(i->rd == 15)
848
			bprint(i, "%T\t(R%d+R%d)", "CALL", i->rs2, i->rs1);
849
		else
850
			bprint(i, "%T\t(R%d+R%d), R%d", m, i->rs2, i->rs1, i->rd);
851
	}else{
852
		if(!dascase && i->simm13==8 && i->rs1==15 && i->rd==0)
853
			bprint(i, "RETURN");
854
		else{
855
			bprint(i, "%T\t", m);
856
			address(i);
857
			bprint(i, ", R%d", i->rd);
858
		}
859
	}
860
}
861
 
862
static void
863
loadf(Instr *i, char *m)		/* page 70 */
864
{
865
	if(!dascase){
866
		m = "FMOVD";
867
		if(i->op3 == 0x20)
868
			m = "FMOVF";
869
		else if(i->op3 == 0x21)
870
			m = "MOVW";
871
	}
872
	if(i->i == 0)
873
		bprint(i, "%s\t(R%d+R%d)", m, i->rs1, i->rs2);
874
	else{
875
		bprint(i, "%s\t", m);
876
		address(i);
877
	}
878
	if(i->op3 == 0x21)
879
		bprint(i, ", FSR");
880
	else
881
		bprint(i, ", R%d", i->rd);
882
}
883
 
884
static void
885
storef(Instr *i, char *m)		/* page 70 */
886
{
887
	if(!dascase){
888
		m = "FMOVD";
889
		if(i->op3 == 0x25 || i->op3 == 0x26)
890
			m = "MOVW";
891
		else if(i->op3 == 0x20)
892
			m = "FMOVF";
893
	}
894
	bprint(i, "%s\t", m);
895
	if(i->op3 == 0x25)
896
		bprint(i, "FSR, ");
897
	else if(i->op3 == 0x26)
898
		bprint(i, "FQ, ");
899
	else
900
		bprint(i, "R%d, ", i->rd);
901
	if(i->i == 0)
902
		bprint(i, "(R%d+R%d)", i->rs1, i->rs2);
903
	else
904
		address(i);
905
}
906
 
907
static void
908
loadc(Instr *i, char *m)			/* page 72 */
909
{
910
	if(i->i == 0)
911
		bprint(i, "%s\t(R%d+R%d), C%d", m, i->rs1, i->rs2, i->rd);
912
	else{
913
		bprint(i, "%s\t", m);
914
		address(i);
915
		bprint(i, ", C%d", i->rd);
916
	}
917
}
918
 
919
static void
920
loadcsr(Instr *i, char *m)			/* page 72 */
921
{
922
	if(i->i == 0)
923
		bprint(i, "%s\t(R%d+R%d), CSR", m, i->rs1, i->rs2);
924
	else{
925
		bprint(i, "%s\t", m);
926
		address(i);
927
		bprint(i, ", CSR");
928
	}
929
}
930
 
931
static struct{
932
	int	opf;
933
	char	*name;
934
} fptab1[] = {			/* ignores rs1 */
935
	0xC4,	"FITOS",	/* page 109 */
936
	0xC8,	"FITOD",
937
	0xCC,	"FITOX",
938
 
939
	0xD1,	"FSTOI",	/* page 110 */
940
	0xD2,	"FDTOI",
941
	0xD3,	"FXTOI",
942
 
943
	0xC9,	"FSTOD",	/* page 111 */
944
	0xCD,	"FSTOX",
945
	0xC6,	"FDTOS",
946
	0xCE,	"FDTOX",
947
	0xC7,	"FXTOS",
948
	0xCB,	"FXTOD",
949
 
950
	0x01,	"FMOVS",	/* page 112 */
951
	0x05,	"FNEGS",
952
	0x09,	"FABSS",
953
 
954
	0x29,	"FSQRTS", 	/* page 113 */
955
	0x2A,	"FSQRTD",
956
	0x2B,	"FSQRTX",
957
 
958
	0,	0,
959
};
960
 
961
static struct{
962
	int	opf;
963
	char	*name;
964
} fptab2[] = {			/* uses rs1 */
965
 
966
	0x41,	"FADDS",	/* page 114 */
967
	0x42,	"FADDD",
968
	0x43,	"FADDX",
969
	0x45,	"FSUBS",
970
	0x46,	"FSUBD",
971
	0x47,	"FSUBX",
972
 
973
	0x49,	"FMULS",	/* page 115 */
974
	0x4A,	"FMULD",
975
	0x4B,	"FMULX",
976
	0x4D,	"FDIVS",
977
	0x4E,	"FDIVD",
978
	0x4F,	"FDIVX",
979
 
980
	0x51,	"FCMPS",	/* page 116 */
981
	0x52,	"FCMPD",
982
	0x53,	"FCMPX",
983
	0x55,	"FCMPES",
984
	0x56,	"FCMPED",
985
	0x57,	"FCMPEX",
986
 
987
	0, 0
988
};
989
 
990
static void
991
fpop(Instr *i, char *m)	/* page 108-116 */
992
{
993
	int j;
994
 
995
	if(dascase==0 && i->size==2){
996
		bprint(i, "FMOVD\tF%d, F%d", i->rs2, i->rd);
997
		return;
998
	}
999
	for(j=0; fptab1[j].name; j++)
1000
		if(fptab1[j].opf == i->opf){
1001
			bprint(i, "%T\tF%d, F%d", fptab1[j].name, i->rs2, i->rd);
1002
			return;
1003
		}
1004
	for(j=0; fptab2[j].name; j++)
1005
		if(fptab2[j].opf == i->opf){
1006
			bprint(i, "%T\tF%d, F%d, F%d", fptab2[j].name, i->rs1, i->rs2, i->rd);
1007
			return;
1008
		}
1009
	bprint(i, "%T%ux\tF%d, F%d, F%d", m, i->opf, i->rs1, i->rs2, i->rd);
1010
}
1011
 
1012
static int
1013
sparcfoll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
1014
{
1015
	ulong w, r1, r2;
1016
	char buf[8];
1017
	Instr i;
1018
 
1019
	mymap = map;
1020
	if (mkinstr(pc, &i) < 0)
1021
		return -1;
1022
	w = i.w0;
1023
	switch(w & 0xC1C00000){
1024
	case 0x00800000:		/* branch on int cond */
1025
	case 0x01800000:		/* branch on fp cond */
1026
	case 0x01C00000:		/* branch on copr cond */
1027
		foll[0] = pc+8;
1028
		foll[1] = pc + (i.simmdisp22<<2);
1029
		return 2;
1030
	}
1031
 
1032
	if((w&0xC0000000) == 0x40000000){	/* CALL */
1033
		foll[0] = pc + (i.disp30<<2);
1034
		return 1;
1035
	}
1036
 
1037
	if((w&0xC1F80000) == 0x81C00000){	/* JMPL */
1038
		sprint(buf, "R%ld", (w>>14)&0xF);
1039
		r1 = (*rget)(map, buf);
1040
		if(w & 0x2000)			/* JMPL R1+simm13 */
1041
			r2 = i.simm13;
1042
		else{				/* JMPL R1+R2 */
1043
			sprint(buf, "R%ld", w&0xF);
1044
			r2 = (*rget)(map, buf);
1045
		}
1046
		foll[0] = r1 + r2;
1047
		return 1;
1048
	}
1049
	foll[0] = pc+i.size*4;
1050
	return 1;
1051
}