xref: /inferno-os/appl/lib/dis.b (revision 6e425a9de8c003b5a733621a6b6730ec3cc902b8)
1implement Dis;
2
3#
4# Derived by Vita Nuova Limited 1998 from /appl/wm/rt.b, which is
5# Copyright © 1996-1999 Lucent Technologies Inc.  All rights reserved.
6#
7
8include "sys.m";
9	sys: Sys;
10	sprint: import sys;
11
12include "math.m";
13	math: Math;
14
15include "dis.m";
16
17disptr: int;
18disobj: array of byte;
19
20optab := array[] of {
21	"nop",
22	"alt",
23	"nbalt",
24	"goto",
25	"call",
26	"frame",
27	"spawn",
28	"runt",
29	"load",
30	"mcall",
31	"mspawn",
32	"mframe",
33	"ret",
34	"jmp",
35	"case",
36	"exit",
37	"new",
38	"newa",
39	"newcb",
40	"newcw",
41	"newcf",
42	"newcp",
43	"newcm",
44	"newcmp",
45	"send",
46	"recv",
47	"consb",
48	"consw",
49	"consp",
50	"consf",
51	"consm",
52	"consmp",
53	"headb",
54	"headw",
55	"headp",
56	"headf",
57	"headm",
58	"headmp",
59	"tail",
60	"lea",
61	"indx",
62	"movp",
63	"movm",
64	"movmp",
65	"movb",
66	"movw",
67	"movf",
68	"cvtbw",
69	"cvtwb",
70	"cvtfw",
71	"cvtwf",
72	"cvtca",
73	"cvtac",
74	"cvtwc",
75	"cvtcw",
76	"cvtfc",
77	"cvtcf",
78	"addb",
79	"addw",
80	"addf",
81	"subb",
82	"subw",
83	"subf",
84	"mulb",
85	"mulw",
86	"mulf",
87	"divb",
88	"divw",
89	"divf",
90	"modw",
91	"modb",
92	"andb",
93	"andw",
94	"orb",
95	"orw",
96	"xorb",
97	"xorw",
98	"shlb",
99	"shlw",
100	"shrb",
101	"shrw",
102	"insc",
103	"indc",
104	"addc",
105	"lenc",
106	"lena",
107	"lenl",
108	"beqb",
109	"bneb",
110	"bltb",
111	"bleb",
112	"bgtb",
113	"bgeb",
114	"beqw",
115	"bnew",
116	"bltw",
117	"blew",
118	"bgtw",
119	"bgew",
120	"beqf",
121	"bnef",
122	"bltf",
123	"blef",
124	"bgtf",
125	"bgef",
126	"beqc",
127	"bnec",
128	"bltc",
129	"blec",
130	"bgtc",
131	"bgec",
132	"slicea",
133	"slicela",
134	"slicec",
135	"indw",
136	"indf",
137	"indb",
138	"negf",
139	"movl",
140	"addl",
141	"subl",
142	"divl",
143	"modl",
144	"mull",
145	"andl",
146	"orl",
147	"xorl",
148	"shll",
149	"shrl",
150	"bnel",
151	"bltl",
152	"blel",
153	"bgtl",
154	"bgel",
155	"beql",
156	"cvtlf",
157	"cvtfl",
158	"cvtlw",
159	"cvtwl",
160	"cvtlc",
161	"cvtcl",
162	"headl",
163	"consl",
164	"newcl",
165	"casec",
166	"indl",
167	"movpc",
168	"tcmp",
169	"mnewz",
170	"cvtrf",
171	"cvtfr",
172	"cvtws",
173	"cvtsw",
174	"lsrw",
175	"lsrl",
176	"eclr",
177	"newz",
178	"newaz",
179	"raise",
180	"casel",
181	"mulx",
182	"divx",
183	"cvtxx",
184	"mulx0",
185	"divx0",
186	"cvtxx0",
187	"mulx1",
188	"divx1",
189	"cvtxx1",
190	"cvtfx",
191	"cvtxf",
192	"expw",
193	"expl",
194	"expf",
195	"self",
196};
197
198init()
199{
200	sys = load Sys  Sys->PATH;
201	math = load Math Math->PATH;	# optional
202}
203
204loadobj(disfile: string): (ref Mod, string)
205{
206	fd := sys->open(disfile, sys->OREAD);
207	if(fd == nil)
208		return (nil, "open failed: "+sprint("%r"));
209
210	(ok, d) := sys->fstat(fd);
211	if(ok < 0)
212		return (nil, "stat failed: "+sprint("%r"));
213
214	objlen := int d.length;
215	disobj = array[objlen] of byte;
216
217	if(sys->read(fd, disobj, objlen) != objlen){
218		disobj = nil;
219		return (nil, "read failed: "+sprint("%r"));
220	}
221
222	disptr = 0;
223	m := ref Mod;
224	m.magic = operand();
225	if(m.magic == SMAGIC) {
226		n := operand();
227		m.sign = disobj[disptr:disptr+n];
228		disptr += n;
229		m.magic = operand();
230	}
231	if(m.magic != XMAGIC){
232		disobj = nil;
233		return (nil, "bad magic number");
234	}
235
236	m.rt = operand();
237	m.ssize = operand();
238	m.isize = operand();
239	m.dsize = operand();
240	m.tsize = operand();
241	m.lsize = operand();
242	m.entry = operand();
243	m.entryt = operand();
244
245	m.inst = array[m.isize] of ref Inst;
246	for(i := 0; i < m.isize; i++) {
247		o := ref Inst;
248		o.op = int disobj[disptr++];
249		o.addr = int disobj[disptr++];
250		case o.addr & ARM {
251		AXIMM or
252		AXINF or
253		AXINM =>
254			o.mid = operand();
255		}
256
257		case (o.addr>>3) & 7 {
258		AFP or
259		AMP or
260		AIMM =>
261			o.src = operand();
262		AIND|AFP or
263		AIND|AMP =>
264			o.src = operand()<<16;
265			o.src |= operand();
266		}
267
268		case o.addr & 7	 {
269		AFP or
270		AMP or
271		AIMM =>
272			o.dst = operand();
273		AIND|AFP or
274		AIND|AMP =>
275			o.dst = operand()<<16;
276			o.dst |= operand();
277		}
278		m.inst[i] = o;
279	}
280
281	m.types = array[m.tsize] of ref Type;
282	for(i = 0; i < m.tsize; i++) {
283		h := ref Type;
284		id := operand();
285		h.size = operand();
286		h.np = operand();
287		h.map = disobj[disptr:disptr+h.np];
288		disptr += h.np;
289		m.types[i] = h;
290	}
291
292	for(;;) {
293		op := int disobj[disptr++];
294		if(op == 0)
295			break;
296
297		n := op & (DMAX-1);
298		if(n == 0)
299			n = operand();
300
301		offset := operand();
302
303		dat: ref Data;
304		case op>>4 {
305		DEFB =>
306			dat = ref Data.Bytes(op, n, offset, disobj[disptr:disptr+n]);
307			disptr += n;
308		DEFW =>
309			words := array[n] of int;
310			for(i = 0; i < n; i++)
311				words[i] = getw();
312			dat = ref Data.Words(op, n, offset, words);
313		DEFS =>
314			dat = ref Data.String(op, n, offset, string disobj[disptr:disptr+n]);
315			disptr += n;
316		DEFF =>
317			if(math != nil){
318				reals := array[n] of real;
319				for(i = 0; i < n; i++)
320					reals[i] = math->bits64real(getl());
321				dat = ref Data.Reals(op, n, offset, reals);
322			} else {
323				disptr += 8*n;	# skip it
324				dat = ref Data.Reals(op, n, offset, nil);
325			}
326			break;
327		DEFA =>
328			typex := getw();
329			length := getw();
330			dat = ref Data.Array(op, n, offset, typex, length);
331		DIND =>
332			dat = ref Data.Aindex(op, n, offset, getw());
333		DAPOP =>
334			dat = ref Data.Arestore(op, n, offset);
335		DEFL =>
336			bigs := array[n] of big;
337			for(i = 0; i < n; i++)
338				bigs[i] = getl();
339			dat = ref Data.Bigs(op, n, offset, bigs);
340		* =>
341			dat = ref Data.Zero(op, n, offset);
342		}
343		m.data = dat :: m.data;
344	}
345
346	m.data = revdat(m.data);
347
348	m.name = gets();
349
350	m.links = array[m.lsize] of ref Link;
351	for(i = 0; i < m.lsize; i++) {
352		l := ref Link;
353		l.pc = operand();
354		l.desc = operand();
355		l.sig = getw();
356		l.name = gets();
357
358		m.links[i] = l;
359	}
360
361	if(m.rt & Dis->HASLDT0)
362		raise "obsolete dis";
363
364	if(m.rt & Dis->HASLDT){
365		nl := operand();
366		imps := array[nl] of array of ref Import;
367		for(i = 0; i < nl; i++){
368			n := operand();
369			imps[i] = array[n] of ref Import;
370			for(j := 0; j < n; j++){
371				imps[i][j] = im := ref Import;
372				im.sig = getw();
373				im.name = gets();
374			}
375		}
376		disptr++;
377		m.imports = imps;
378	}
379
380	if(m.rt & Dis->HASEXCEPT){
381		nh := operand();	# number of handlers
382		hs := array[nh] of ref Handler;
383		for(i = 0; i < nh; i++){
384			h := hs[i] = ref Handler;
385			h.eoff = operand();
386			h.pc1 = operand();
387			h.pc2 = operand();
388			t := operand();
389			if(t >= 0)
390				h.t = m.types[t];
391			n := operand();
392			h.ne = n>>16;
393			n &= 16rffff;	# number of cases
394			h.etab = array[n+1] of ref Except;
395			for(j := 0; j < n; j++){
396				e := h.etab[j] = ref Except;
397				k := disptr;
398				while(int disobj[disptr++])	# pattern
399					;
400				e.s = string disobj[k: disptr-1];
401				e.pc = operand();
402			}
403			e := h.etab[j] = ref Except;
404			e.pc = operand();	# * pc
405		}
406		disptr++;	# 0 byte
407		m.handlers = hs;
408	}
409
410	m.srcpath = gets();
411
412	disobj = nil;
413	return (m, nil);
414}
415
416operand(): int
417{
418	if(disptr >= len disobj)
419		return -1;
420
421	b := int disobj[disptr++];
422
423	case b & 16rC0 {
424	16r00 =>
425		return b;
426	16r40 =>
427		return b | ~16r7F;
428	16r80 =>
429		if(disptr >= len disobj)
430			return -1;
431		if(b & 16r20)
432			b |= ~16r3F;
433		else
434			b &= 16r3F;
435		return (b<<8) | int disobj[disptr++];
436	16rC0 =>
437		if(disptr+2 >= len disobj)
438			return -1;
439		if(b & 16r20)
440			b |= ~16r3F;
441		else
442			b &= 16r3F;
443		b = b<<24 |
444			(int disobj[disptr]<<16) |
445		    	(int disobj[disptr+1]<<8)|
446		    	int disobj[disptr+2];
447		disptr += 3;
448		return b;
449	}
450	return 0;
451}
452
453get4(a: array of byte, i: int): int
454{
455	return (int a[i+0] << 24) | (int a[i+1] << 16) | (int a[i+2] << 8) | int a[i+3];
456}
457
458getw(): int
459{
460	if(disptr+3 >= len disobj)
461		return -1;
462	i := (int disobj[disptr+0]<<24) |
463	     (int disobj[disptr+1]<<16) |
464	     (int disobj[disptr+2]<<8) |
465	      int disobj[disptr+3];
466
467	disptr += 4;
468	return i;
469}
470
471getl(): big
472{
473	if(disptr+7 >= len disobj)
474		return big -1;
475	i := (big disobj[disptr+0]<<56) |
476	     (big disobj[disptr+1]<<48) |
477	     (big disobj[disptr+2]<<40) |
478	     (big disobj[disptr+3]<<32) |
479	     (big disobj[disptr+4]<<24) |
480	     (big disobj[disptr+5]<<16) |
481	     (big disobj[disptr+6]<<8) |
482	      big disobj[disptr+7];
483
484	disptr += 8;
485	return i;
486}
487
488gets(): string
489{
490	s := disptr;
491	while(disptr < len disobj && disobj[disptr] != byte 0)
492		disptr++;
493
494	v := string disobj[s:disptr];
495	disptr++;
496	return v;
497}
498
499revdat(d: list of ref Data): list of ref Data
500{
501	t: list of ref Data;
502
503	while(d != nil) {
504		t = hd d :: t;
505		d = tl d;
506	}
507	return t;
508}
509
510op2s(op: int): string
511{
512	if(op < 0 || op >= len optab)
513		return sys->sprint("OP%d", op);
514	return optab[op];
515}
516
517inst2s(o: ref Inst): string
518{
519	fi := 0;
520	si := 0;
521	s := sprint("%-10s", optab[o.op]);
522	src := "";
523	dst := "";
524	mid := "";
525	case (o.addr>>3) & 7 {
526	AFP =>
527		src = sprint("%d(fp)", o.src);
528	AMP =>
529		src = sprint("%d(mp)", o.src);
530	AIMM =>
531		src = sprint("$%d", o.src);
532	AIND|AFP =>
533		fi = (o.src>>16) & 16rFFFF;
534		si = o.src & 16rFFFF;
535		src = sprint("%d(%d(fp))", si, fi);
536	AIND|AMP =>
537		fi = (o.src>>16) & 16rFFFF;
538		si = o.src & 16rFFFF;
539		src = sprint("%d(%d(mp))", si, fi);
540	}
541
542	case o.addr & ARM {
543	AXIMM =>
544		mid = sprint("$%d", o.mid);
545	AXINF =>
546		mid = sprint("%d(fp)", o.mid);
547	AXINM =>
548		mid = sprint("%d(mp)", o.mid);
549	}
550
551	case o.addr & 7 {
552	AFP =>
553		dst = sprint("%d(fp)", o.dst);
554	AMP =>
555		dst = sprint("%d(mp)", o.dst);
556	AIMM =>
557		dst = sprint("$%d", o.dst);
558	AIND|AFP =>
559		fi = (o.dst>>16) & 16rFFFF;
560		si = o.dst & 16rFFFF;
561		dst = sprint("%d(%d(fp))", si, fi);
562	AIND|AMP =>
563		fi = (o.dst>>16) & 16rFFFF;
564		si = o.dst & 16rFFFF;
565		dst = sprint("%d(%d(mp))", si, fi);
566	}
567	if(mid == "") {
568		if(src == "")
569			s += sprint("%s", dst);
570		else if(dst == "")
571			s += sprint("%s", src);
572		else
573			s += sprint("%s, %s", src, dst);
574	}
575	else
576		s += sprint("%s, %s, %s", src, mid, dst);
577
578	return s;
579}
580
581getsb(fd: ref Sys->FD, o: int): (string, int)
582{
583	b := array[1] of byte;
584	buf := array[8192] of byte;
585	p := len buf;
586	for( ; ; o++){
587		sys->seek(fd, big -o, Sys->SEEKEND);
588		if(sys->read(fd, b, 1) != 1)
589			return (nil, 0);
590		if(b[0] == byte 0){
591			if(p < len buf)
592				break;
593		}
594		else if(p > 0)
595			buf[--p] = b[0];
596	}
597	return (string buf[p: ], o);
598}
599
600src(disf: string): string
601{
602	fd := sys->open(disf, sys->OREAD);
603	if(fd == nil)
604		return nil;
605	(s, nil) := getsb(fd, 1);
606	if(s != nil && s[0] == '/')
607		return s;
608	return nil;
609}
610