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_fixcpp/sys/src/libmach/vcodas.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
	/* mips native disassembler */
7
 
8
typedef struct {
9
	uvlong addr;			/* pc of instr */
10
	uchar op;			/* bits 31-26 */
11
	uchar rs;			/* bits 25-21 */
12
	uchar rt;			/* bits 20-16 */
13
	uchar rd;			/* bits 15-11 */
14
	uchar sa;			/* bits 10-6 */
15
	uchar function;			/* bits 5-0 */
16
	long immediate;			/* bits 15-0 */
17
	ulong cofun;			/* bits 24-0 */
18
	ulong target;			/* bits 25-0 */
19
	long w0;
20
	char *curr;			/* current fill point */
21
	char *end;			/* end of buffer */
22
	char *err;
23
} Instr;
24
 
25
typedef struct {
26
	char *mnemonic;
27
	char *mipsco;
28
} Opcode;
29
 
30
static char mipscoload[] = "r%t,%l";
31
static char mipscoalui[] = "r%t,r%s,%i";
32
static char mipscoalu3op[] = "r%d,r%s,r%t";
33
static char mipscoboc[] = "r%s,r%t,%b";
34
static char mipscoboc0[] = "r%s,%b";
35
static char mipscorsrt[] = "r%s,r%t";
36
static char mipscorsi[] = "r%s,%i";
37
static char mipscoxxx[] = "%w";
38
static char mipscofp3[] = "f%a,f%d,f%t";	/* fd,fs,ft */
39
static char mipscofp2[] = "f%a,f%d";		/* fd,fs */
40
static char mipscofpc[] = "f%d,f%t";		/* fs,ft */
41
 
42
static Opcode opcodes[64] = {
43
	0,		0,
44
	0,		0,
45
	"j",		"%j",
46
	"jal",		"%j",
47
	"beq",		mipscoboc,
48
	"bne",		mipscoboc,
49
	"blez",		mipscoboc0,
50
	"bgtz",		mipscoboc0,
51
	"addi",		mipscoalui,
52
	"addiu",	mipscoalui,
53
	"slti",		mipscoalui,
54
	"sltiu",	mipscoalui,
55
	"andi",		mipscoalui,
56
	"ori",		mipscoalui,
57
	"xori",		mipscoalui,
58
	"lui",		"r%t,%u",
59
	"cop0",		0,
60
	"cop1",		0,
61
	"cop2",		0,
62
	"cop3",		0,
63
	"beql",		mipscoboc,
64
	"bnel",		mipscoboc,
65
	"blezl",	mipscoboc0,
66
	"bgtzl",	mipscoboc0,
67
	"instr18",	mipscoxxx,
68
	"instr19",	mipscoxxx,
69
	"instr1A",	mipscoxxx,
70
	"instr1B",	mipscoxxx,
71
	"instr1C",	mipscoxxx,
72
	"instr1D",	mipscoxxx,
73
	"instr1E",	mipscoxxx,
74
	"instr1F",	mipscoxxx,
75
	"lb",		mipscoload,
76
	"lh",		mipscoload,
77
	"lwl",		mipscoload,
78
	"lw",		mipscoload,
79
	"lbu",		mipscoload,
80
	"lhu",		mipscoload,
81
	"lwr",		mipscoload,
82
	"instr27",	mipscoxxx,
83
	"sb",		mipscoload,
84
	"sh",		mipscoload,
85
	"swl",		mipscoload,
86
	"sw",		mipscoload,
87
	"instr2C",	mipscoxxx,
88
	"instr2D",	mipscoxxx,
89
	"swr",		mipscoload,
90
	"cache",	"",
91
	"ll",		mipscoload,
92
	"lwc1",		mipscoload,
93
	"lwc2",		mipscoload,
94
	"lwc3",		mipscoload,
95
	"instr34",	mipscoxxx,
96
	"ld",		mipscoload,
97
	"ld",		mipscoload,
98
	"ld",		mipscoload,
99
	"sc",		mipscoload,
100
	"swc1",		mipscoload,
101
	"swc2",		mipscoload,
102
	"swc3",		mipscoload,
103
	"instr3C",	mipscoxxx,
104
	"sd",		mipscoload,
105
	"sd",		mipscoload,
106
	"sd",		mipscoload,
107
};
108
 
109
static Opcode sopcodes[64] = {
110
	"sll",		"r%d,r%t,$%a",
111
	"special01",	mipscoxxx,
112
	"srl",		"r%d,r%t,$%a",
113
	"sra",		"r%d,r%t,$%a",
114
	"sllv",		"r%d,r%t,R%s",
115
	"special05",	mipscoxxx,
116
	"srlv",		"r%d,r%t,r%s",
117
	"srav",		"r%d,r%t,r%s",
118
	"jr",		"r%s",
119
	"jalr",		"r%d,r%s",
120
	"special0A",	mipscoxxx,
121
	"special0B",	mipscoxxx,
122
	"syscall",	"",
123
	"break",	"",
124
	"special0E",	mipscoxxx,
125
	"sync",		"",
126
	"mfhi",		"r%d",
127
	"mthi",		"r%s",
128
	"mflo",		"r%d",
129
	"mtlo",		"r%s",
130
	"special14",	mipscoxxx,
131
	"special15",	mipscoxxx,
132
	"special16",	mipscoxxx,
133
	"special17",	mipscoxxx,
134
	"mult",		mipscorsrt,
135
	"multu",	mipscorsrt,
136
	"div",		mipscorsrt,
137
	"divu",		mipscorsrt,
138
	"special1C",	mipscoxxx,
139
	"special1D",	mipscoxxx,
140
	"special1E",	mipscoxxx,
141
	"special1F",	mipscoxxx,
142
	"add",		mipscoalu3op,
143
	"addu",		mipscoalu3op,
144
	"sub",		mipscoalu3op,
145
	"subu",		mipscoalu3op,
146
	"and",		mipscoalu3op,
147
	"or",		mipscoalu3op,
148
	"xor",		mipscoalu3op,
149
	"nor",		mipscoalu3op,
150
	"special28",	mipscoxxx,
151
	"special29",	mipscoxxx,
152
	"slt",		mipscoalu3op,
153
	"sltu",		mipscoalu3op,
154
	"special2C",	mipscoxxx,
155
	"special2D",	mipscoxxx,
156
	"special2E",	mipscoxxx,
157
	"special2F",	mipscoxxx,
158
	"tge",		mipscorsrt,
159
	"tgeu",		mipscorsrt,
160
	"tlt",		mipscorsrt,
161
	"tltu",		mipscorsrt,
162
	"teq",		mipscorsrt,
163
	"special35",	mipscoxxx,
164
	"tne",		mipscorsrt,
165
	"special37",	mipscoxxx,
166
	"special38",	mipscoxxx,
167
	"special39",	mipscoxxx,
168
	"special3A",	mipscoxxx,
169
	"special3B",	mipscoxxx,
170
	"special3C",	mipscoxxx,
171
	"special3D",	mipscoxxx,
172
	"special3E",	mipscoxxx,
173
	"special3F",	mipscoxxx,
174
};
175
 
176
static Opcode ropcodes[32] = {
177
	"bltz",		mipscoboc0,
178
	"bgez",		mipscoboc0,
179
	"bltzl",	mipscoboc0,
180
	"bgezl",	mipscoboc0,
181
	"regimm04",	mipscoxxx,
182
	"regimm05",	mipscoxxx,
183
	"regimm06",	mipscoxxx,
184
	"regimm07",	mipscoxxx,
185
	"tgei",		mipscorsi,
186
	"tgeiu",	mipscorsi,
187
	"tlti",		mipscorsi,
188
	"tltiu",	mipscorsi,
189
	"teqi",		mipscorsi,
190
	"regimm0D",	mipscoxxx,
191
	"tnei",		mipscorsi,
192
	"regimm0F",	mipscoxxx,
193
	"bltzal",	mipscoboc0,
194
	"bgezal",	mipscoboc0,
195
	"bltzall",	mipscoboc0,
196
	"bgezall",	mipscoboc0,
197
	"regimm14",	mipscoxxx,
198
	"regimm15",	mipscoxxx,
199
	"regimm16",	mipscoxxx,
200
	"regimm17",	mipscoxxx,
201
	"regimm18",	mipscoxxx,
202
	"regimm19",	mipscoxxx,
203
	"regimm1A",	mipscoxxx,
204
	"regimm1B",	mipscoxxx,
205
	"regimm1C",	mipscoxxx,
206
	"regimm1D",	mipscoxxx,
207
	"regimm1E",	mipscoxxx,
208
	"regimm1F",	mipscoxxx,
209
};
210
 
211
static Opcode fopcodes[64] = {
212
	"add.%f",	mipscofp3,
213
	"sub.%f",	mipscofp3,
214
	"mul.%f",	mipscofp3,
215
	"div.%f",	mipscofp3,
216
	"sqrt.%f",	mipscofp2,
217
	"abs.%f",	mipscofp2,
218
	"mov.%f",	mipscofp2,
219
	"neg.%f",	mipscofp2,
220
	"finstr08",	mipscoxxx,
221
	"finstr09",	mipscoxxx,
222
	"finstr0A",	mipscoxxx,
223
	"finstr0B",	mipscoxxx,
224
	"round.w.%f",	mipscofp2,
225
	"trunc.w%f",	mipscofp2,
226
	"ceil.w%f",	mipscofp2,
227
	"floor.w%f",	mipscofp2,
228
	"finstr10",	mipscoxxx,
229
	"finstr11",	mipscoxxx,
230
	"finstr12",	mipscoxxx,
231
	"finstr13",	mipscoxxx,
232
	"finstr14",	mipscoxxx,
233
	"finstr15",	mipscoxxx,
234
	"finstr16",	mipscoxxx,
235
	"finstr17",	mipscoxxx,
236
	"finstr18",	mipscoxxx,
237
	"finstr19",	mipscoxxx,
238
	"finstr1A",	mipscoxxx,
239
	"finstr1B",	mipscoxxx,
240
	"finstr1C",	mipscoxxx,
241
	"finstr1D",	mipscoxxx,
242
	"finstr1E",	mipscoxxx,
243
	"finstr1F",	mipscoxxx,
244
	"cvt.s.%f",	mipscofp2,
245
	"cvt.d.%f",	mipscofp2,
246
	"cvt.e.%f",	mipscofp2,
247
	"cvt.q.%f",	mipscofp2,
248
	"cvt.w.%f",	mipscofp2,
249
	"finstr25",	mipscoxxx,
250
	"finstr26",	mipscoxxx,
251
	"finstr27",	mipscoxxx,
252
	"finstr28",	mipscoxxx,
253
	"finstr29",	mipscoxxx,
254
	"finstr2A",	mipscoxxx,
255
	"finstr2B",	mipscoxxx,
256
	"finstr2C",	mipscoxxx,
257
	"finstr2D",	mipscoxxx,
258
	"finstr2E",	mipscoxxx,
259
	"finstr2F",	mipscoxxx,
260
	"c.f.%f",	mipscofpc,
261
	"c.un.%f",	mipscofpc,
262
	"c.eq.%f",	mipscofpc,
263
	"c.ueq.%f",	mipscofpc,
264
	"c.olt.%f",	mipscofpc,
265
	"c.ult.%f",	mipscofpc,
266
	"c.ole.%f",	mipscofpc,
267
	"c.ule.%f",	mipscofpc,
268
	"c.sf.%f",	mipscofpc,
269
	"c.ngle.%f",	mipscofpc,
270
	"c.seq.%f",	mipscofpc,
271
	"c.ngl.%f",	mipscofpc,
272
	"c.lt.%f",	mipscofpc,
273
	"c.nge.%f",	mipscofpc,
274
	"c.le.%f",	mipscofpc,
275
	"c.ngt.%f",	mipscofpc,
276
};
277
 
278
static char fsub[16] = {
279
	's', 'd', 'e', 'q', 'w', '?', '?', '?',
280
	'?', '?', '?', '?', '?', '?', '?', '?'
281
};
282
 
283
 
284
static int
285
mkinstr(Instr *i, Map *map, uvlong pc)
286
{
287
	ulong w;
288
 
289
	if (get4(map, pc, &w) < 0) {
290
		werrstr("can't read instruction: %r");
291
		return -1;
292
	}
293
	i->addr = pc;
294
	i->op = (w >> 26) & 0x3F;
295
	i->rs = (w >> 21) & 0x1F;
296
	i->rt = (w >> 16) & 0x1F;
297
	i->rd = (w >> 11) & 0x1F;
298
	i->sa = (w >> 6) & 0x1F;
299
	i->function = w & 0x3F;
300
	i->immediate = w & 0x0000FFFF;
301
	if (i->immediate & 0x8000)
302
		i->immediate |= ~0x0000FFFF;
303
	i->cofun = w & 0x01FFFFFF;
304
	i->target = w & 0x03FFFFFF;
305
	i->w0 = w;
306
	return 1;
307
}
308
 
309
#pragma	varargck	argpos	bprint		2
310
 
311
static void
312
bprint(Instr *i, char *fmt, ...)
313
{
314
	va_list arg;
315
 
316
	va_start(arg, fmt);
317
	i->curr = vseprint(i->curr, i->end, fmt, arg);
318
	va_end(arg);
319
}
320
 
321
static void
322
format(char *mnemonic, Instr *i, char *f)
323
{
324
	if (mnemonic)
325
		format(0, i, mnemonic);
326
	if (f == 0)
327
		return;
328
	if (i->curr < i->end)
329
		*i->curr++ = '\t';
330
	for ( ; *f && i->curr < i->end; f++) {
331
		if (*f != '%') {
332
			*i->curr++ = *f;
333
			continue;
334
		}
335
		switch (*++f) {
336
 
337
		case 's':
338
			bprint(i, "%d", i->rs);
339
			break;
340
 
341
		case 't':
342
			bprint(i, "%d", i->rt);
343
			break;
344
 
345
		case 'd':
346
			bprint(i, "%d", i->rd);
347
			break;
348
 
349
		case 'a':
350
			bprint(i, "%d", i->sa);
351
			break;
352
 
353
		case 'l':
354
			if (i->rs == 30) {
355
				i->curr += symoff(i->curr, i->end-i->curr, i->immediate+mach->sb, CANY);
356
				bprint(i, "(SB)");
357
			} else 
358
				bprint(i, "%lx(r%d)", i->immediate, i->rs);
359
			break;
360
 
361
		case 'i':
362
			bprint(i, "$%lx", i->immediate);
363
			break;
364
 
365
		case 'u':
366
			*i->curr++ = '$';
367
			i->curr += symoff(i->curr, i->end-i->curr, i->immediate, CANY);
368
			bprint(i, "(SB)");
369
			break;
370
 
371
		case 'j':
372
			i->curr += symoff(i->curr, i->end-i->curr,
373
				(i->target<<2)|(i->addr & 0xF0000000), CANY);
374
			bprint(i, "(SB)");
375
			break;
376
 
377
		case 'b':
378
			i->curr += symoff(i->curr, i->end-i->curr,
379
				(i->immediate<<2)+i->addr+4, CANY);
380
			break;
381
 
382
		case 'c':
383
			bprint(i, "%lux", i->cofun);
384
			break;
385
 
386
		case 'w':
387
			bprint(i, "[%lux]", i->w0);
388
			break;
389
 
390
		case 'f':
391
			*i->curr++ = fsub[i->rs & 0x0F];
392
			break;
393
 
394
		case '\0':
395
			*i->curr++ = '%';
396
			return;
397
 
398
		default:
399
			bprint(i, "%%%c", *f);
400
			break;
401
		}
402
	}
403
}
404
 
405
static void
406
copz(int cop, Instr *i)
407
{
408
	char *f, *m, buf[16];
409
 
410
	m = buf;
411
	f = "%t,%d";
412
	switch (i->rs) {
413
 
414
	case 0:
415
		sprint(buf, "mfc%d", cop);
416
		break;
417
 
418
	case 2:
419
		sprint(buf, "cfc%d", cop);
420
		break;
421
 
422
	case 4:
423
		sprint(buf, "mtc%d", cop);
424
		break;
425
 
426
	case 6:
427
		sprint(buf, "ctc%d", cop);
428
		break;
429
 
430
	case 8:
431
		f = "%b";
432
		switch (i->rt) {
433
 
434
		case 0:
435
			sprint(buf, "bc%df", cop);
436
			break;
437
 
438
		case 1:
439
			sprint(buf, "bc%dt", cop);
440
			break;
441
 
442
		case 2:
443
			sprint(buf, "bc%dfl", cop);
444
			break;
445
 
446
		case 3:
447
			sprint(buf, "bc%dtl", cop);
448
			break;
449
 
450
		default:
451
			sprint(buf, "cop%d", cop);
452
			f = mipscoxxx;
453
			break;
454
		}
455
		break;
456
 
457
	default:
458
		sprint(buf, "cop%d", cop);
459
		if (i->rs & 0x10)
460
			f = "function %c";
461
		else
462
			f = mipscoxxx;
463
		break;
464
	}
465
	format(m, i, f);
466
}
467
 
468
static void
469
cop0(Instr *i)
470
{
471
	char *m = 0;
472
 
473
	if (i->rs >= 0x10) {
474
		switch (i->cofun) {
475
 
476
		case 1:
477
			m = "tlbr";
478
			break;
479
 
480
		case 2:
481
			m = "tlbwi";
482
			break;
483
 
484
		case 6:
485
			m = "tlbwr";
486
			break;
487
 
488
		case 8:
489
			m = "tlbp";
490
			break;
491
 
492
		case 16:
493
			m = "rfe";
494
			break;
495
 
496
		case 24:
497
			m = "eret";
498
			break;
499
 
500
		case 32:
501
			m = "wait";
502
			break;
503
		}
504
		if (m) {
505
			format(m, i, 0);
506
			if (i->curr < i->end)
507
				*i->curr++ = 0;
508
			return;
509
		}
510
	}
511
	copz(0, i);
512
}
513
 
514
int
515
_mipscoinst(Map *map, uvlong pc, char *buf, int n)
516
{
517
	Instr i;
518
	Opcode *o;
519
	uchar op;
520
 
521
	i.curr = buf;
522
	i.end = buf+n-1;
523
	if (mkinstr(&i, map, pc) < 0)
524
		return -1;
525
	switch (i.op) {
526
 
527
	case 0x00:					/* SPECIAL */
528
		o = sopcodes;
529
		op = i.function;
530
		break;
531
 
532
	case 0x01:					/* REGIMM */
533
		o = ropcodes;
534
		op = i.rt;
535
		break;
536
 
537
	case 0x10:					/* COP0 */
538
		cop0(&i);
539
		return 4;
540
 
541
	case 0x11:					/* COP1 */
542
		if (i.rs & 0x10) {
543
			o = fopcodes;
544
			op = i.function;
545
			break;
546
		}
547
		/*FALLTHROUGH*/
548
	case 0x12:					/* COP2 */
549
	case 0x13:					/* COP3 */
550
		copz(i.op-0x10, &i);
551
		return 4;
552
 
553
	default:
554
		o = opcodes;
555
		op = i.op;
556
		break;
557
	}
558
	format(o[op].mnemonic, &i, o[op].mipsco);
559
	return 4;
560
}