xref: /inferno-os/appl/cmd/limbo/dis.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1
2NAMELEN:	con 28;
3
4cache:		array of byte;
5ncached:	int;
6ndatum:		int;
7startoff:	int;
8lastoff:	int;
9lastkind:	int;
10
11discon(val: int)
12{
13	if(val >= -64 && val <= 63){
14		bout.putb(byte (val & ~16r80));
15		return;
16	}
17	if(val >= -8192 && val <= 8191){
18		bout.putb(byte ((val>>8) & ~16rC0 | 16r80));
19		bout.putb(byte val);
20		return;
21	}
22	if(val < 0 && ((val >> 29) & 7) != 7
23	|| val > 0 && (val >> 29) != 0)
24		fatal("overflow in constant 16r"+hex(val, 0));
25	bout.putb(byte(val>>24 | 16rC0));
26	bout.putb(byte(val>>16));
27	bout.putb(byte(val>>8));
28	bout.putb(byte val);
29}
30
31disword(w: int)
32{
33	bout.putb(byte(w >> 24));
34	bout.putb(byte(w >> 16));
35	bout.putb(byte(w >> 8));
36	bout.putb(byte w);
37}
38
39disdata(kind, n: int)
40{
41	if(n < DMAX && n != 0)
42		bout.putb(byte((kind << DBYTE) | n));
43	else{
44		bout.putb(byte kind << DBYTE);
45		discon(n);
46	}
47}
48
49dismod(m: ref Decl)
50{
51	fileoff := bout.seek(big 0, 1);
52	name := array of byte m.sym.name;
53	n := len name;
54	if(n > NAMELEN-1)
55		n = NAMELEN-1;
56	bout.write(name, n);
57	bout.putb(byte 0);
58	for(m = m.ty.tof.ids; m != nil; m = m.next){
59		case m.store{
60		Dglobal =>
61			discon(-1);
62			discon(-1);
63			disword(sign(m));
64			bout.puts(".mp");
65			bout.putb(byte 0);
66		Dfn =>
67			discon(m.pc.pc);
68			discon(m.desc.id);
69			disword(sign(m));
70			if(m.dot.ty.kind == Tadt){
71				bout.puts(m.dot.sym.name);
72				bout.putb(byte '.');
73			}
74			bout.puts(m.sym.name);
75			bout.putb(byte 0);
76		* =>
77			fatal("unknown kind in dismod: "+declconv(m));
78		}
79	}
80	if(debug['s'])
81		print("%bd linkage bytes start %bd\n", bout.seek(big 0, 1) - fileoff, fileoff);
82}
83
84dispath()
85{
86	sp := array of byte srcpath();
87	bout.write(sp, len sp);
88	bout.putb(byte 0);
89}
90
91disentry(e: ref Decl)
92{
93	if(e == nil){
94		discon(-1);
95		discon(-1);
96		return;
97	}
98	discon(e.pc.pc);
99	discon(e.desc.id);
100}
101
102disdesc(d: ref Desc)
103{
104	fileoff := bout.seek(big 0, 1);
105	for(; d != nil; d = d.next){
106		discon(d.id);
107		discon(d.size);
108		discon(d.nmap);
109		bout.write(d.map, d.nmap);
110	}
111	if(debug['s'])
112		print("%bd type descriptor bytes start %bd\n", bout.seek(big 0, 1) - fileoff, fileoff);
113}
114
115disvar(nil: int, ids: ref Decl)
116{
117	fileoff := bout.seek(big 0, 1);
118	lastkind = -1;
119	ncached = 0;
120	ndatum = 0;
121
122	for(d := ids; d != nil; d = d.next)
123		if(d.store == Dglobal && d.init != nil)
124			disdatum(d.offset, d.init);
125
126	disflush(-1, -1, 0);
127
128	bout.putb(byte 0);
129
130	if(debug['s'])
131		print("%bd data bytes start %bd\n", bout.seek(big 0, 1) - fileoff, fileoff);
132}
133
134disldt(size: int, ds: ref Decl)
135{
136	if(0){
137		discon(size);
138		disvar(size, ds);
139		return;
140	}
141
142	m := 0;
143	for(d := ds; d != nil; d = d.next)
144		if(d.store == Dglobal && d.init != nil)
145			m++;
146	discon(m);
147	n: ref Node;
148	for(d = ds; d != nil; d = d.next){
149		if(d.store == Dglobal && d.init != nil){
150			n = d.init;
151			if(n.ty.kind != Tiface)
152				nerror(n, "disldt: not Tiface");
153			discon(int n.c.val);
154			for(id := n.decl.ty.ids; id != nil; id = id.next){
155				disword(sign(id));
156				if(id.dot.ty.kind == Tadt){
157					s := array of byte id.dot.sym.name;
158					bout.write(s, len s);
159					bout.putb(byte '.');
160				}
161				s := array of byte id.sym.name;
162				bout.write(s, len s);
163				bout.putb(byte 0);
164			}
165		}
166	}
167	discon(0);
168}
169
170disdatum(offset: int, n: ref Node)
171{
172	c: ref Case;
173	lab: Label;
174	id: ref Decl;
175	wild: ref Node;
176	i, e: int;
177
178	case n.ty.kind{
179	Tbyte =>
180		disbyte(offset, byte n.c.val);
181	Tint or
182	Tfix =>
183		disint(offset, int n.c.val);
184	Tbig =>
185		disbig(offset, n.c.val);
186	Tstring =>
187		disstring(offset, n.decl.sym);
188	Treal =>
189		disreal(offset, n.c.rval);
190	Tadt or
191	Tadtpick or
192	Ttuple =>
193		id = n.ty.ids;
194		for(n = n.left; n != nil; n = n.right){
195			disdatum(offset + id.offset, n.left);
196			id = id.next;
197		}
198	Tany =>
199		break;
200	Tcase =>
201		c = n.ty.cse;
202		disint(offset, c.nlab);
203		offset += IBY2WD;
204		for(i = 0; i < c.nlab; i++){
205			lab = c.labs[i];
206			disint(offset, int lab.start.c.val);
207			offset += IBY2WD;
208			disint(offset, int lab.stop.c.val+1);
209			offset += IBY2WD;
210			disint(offset, lab.inst.pc);
211			offset += IBY2WD;
212		}
213		if(c.iwild != nil)
214			disint(offset, c.iwild.pc);
215		else
216			disint(offset, -1);
217	Tcasel =>
218		c = n.ty.cse;
219		disint(offset, c.nlab);
220		offset += 2*IBY2WD;
221		for(i = 0; i < c.nlab; i++){
222			lab = c.labs[i];
223			disbig(offset, lab.start.c.val);
224			offset += IBY2LG;
225			disbig(offset, lab.stop.c.val+big 1);
226			offset += IBY2LG;
227			disint(offset, lab.inst.pc);
228			offset += 2*IBY2WD;
229		}
230		if(c.iwild != nil)
231			disint(offset, c.iwild.pc);
232		else
233			disint(offset, -1);
234	Tcasec =>
235		c = n.ty.cse;
236		disint(offset, c.nlab);
237		offset += IBY2WD;
238		for(i = 0; i < c.nlab; i++){
239			lab = c.labs[i];
240			disstring(offset, lab.start.decl.sym);
241			offset += IBY2WD;
242			if(lab.stop != lab.start)
243				disstring(offset, lab.stop.decl.sym);
244			offset += IBY2WD;
245			disint(offset, lab.inst.pc);
246			offset += IBY2WD;
247		}
248		if(c.iwild != nil)
249			disint(offset, c.iwild.pc);
250		else
251			disint(offset, -1);
252	Tgoto =>
253		c = n.ty.cse;
254		disint(offset, n.ty.size/IBY2WD-1);
255		offset += IBY2WD;
256		for(i = 0; i < c.nlab; i++){
257			disint(offset, c.labs[i].inst.pc);
258			offset += IBY2WD;
259		}
260		if(c.iwild != nil)
261			disint(offset, c.iwild.pc);
262	Tarray =>
263		disflush(-1, -1, 0);
264		disdata(DEFA, 1);		# 1 is ignored
265		discon(offset);
266		disword(n.ty.tof.decl.desc.id);
267		disword(int n.left.c.val);
268
269		if(n.right == nil)
270			break;
271
272		disdata(DIND, 1);		# 1 is ignored
273		discon(offset);
274		disword(0);
275
276		c = n.right.ty.cse;
277		wild = nil;
278		if(c.wild != nil)
279			wild = c.wild.right;
280		last := 0;
281		esz := n.ty.tof.size;
282		for(i = 0; i < c.nlab; i++){
283			e = int c.labs[i].start.c.val;
284			if(wild != nil){
285				for(; last < e; last++)
286					disdatum(esz * last, wild);
287			}
288			last = e;
289			e = int c.labs[i].stop.c.val;
290			elem := c.labs[i].node.right;
291			for(; last <= e; last++)
292				disdatum(esz * last, elem);
293		}
294		if(wild != nil)
295			for(e = int n.left.c.val; last < e; last++)
296				disdatum(esz * last, wild);
297
298		disflush(-1, -1, 0);
299		disdata(DAPOP, 1);		# 1 is ignored
300		discon(0);
301	Tiface =>
302		disint(offset, int n.c.val);
303		offset += IBY2WD;
304		for(id = n.decl.ty.ids; id != nil; id = id.next){
305			offset = align(offset, IBY2WD);
306			disint(offset, sign(id));
307			offset += IBY2WD;
308
309			name: array of byte;
310			if(id.dot.ty.kind == Tadt){
311				name = array of byte id.dot.sym.name;
312				disbytes(offset, name);
313				offset += len name;
314				disbyte(offset, byte '.');
315				offset++;
316			}
317			name = array of byte id.sym.name;
318			disbytes(offset, name);
319			offset += len name;
320			disbyte(offset, byte 0);
321			offset++;
322		}
323	* =>
324		fatal("can't gen global "+nodeconv(n));
325	}
326}
327
328disexc(es: ref Except)
329{
330	e: ref Except;
331
332	n := 0;
333	for(e = es; e != nil; e = e.next)
334		if(int e.p1.reach || int e.p2.reach)
335			n++;
336	discon(n);
337	for(e = es; e != nil; e = e.next){
338		if(!int e.p1.reach && !int e.p2.reach)
339			continue;
340		c := e.c;
341		discon(e.d.offset);
342		discon(getpc(e.p1));
343		discon(getpc(e.p2));
344		if(e.desc != nil)
345			discon(e.desc.id);
346		else
347			discon(-1);
348		discon(c.nlab|(e.ne<<16));
349		for(i := 0; i < c.nlab; i++){
350			lab := c.labs[i];
351			d := lab.start.decl;
352			if(lab.start.ty.kind == Texception)
353				d = d.init.decl;
354			bout.puts(d.sym.name);
355			bout.putb(byte 0);
356			discon(lab.inst.pc);
357		}
358		if(c.iwild == nil)
359			discon(-1);
360		else
361			discon(c.iwild.pc);
362	}
363	discon(0);
364}
365
366disbyte(off: int, v: byte)
367{
368	disflush(DEFB, off, 1);
369	cache[ncached++] = v;
370	ndatum++;
371}
372
373disbytes(off: int, v: array of byte)
374{
375	n := len v;
376	disflush(DEFB, off, n);
377	cache[ncached:] = v;
378	ncached += n;
379	ndatum += n;
380}
381
382disint(off, v: int)
383{
384	disflush(DEFW, off, IBY2WD);
385	cache[ncached++] = byte(v >> 24);
386	cache[ncached++] = byte(v >> 16);
387	cache[ncached++] = byte(v >> 8);
388	cache[ncached++] = byte(v);
389	ndatum++;
390}
391
392disbig(off: int, v: big)
393{
394	disflush(DEFL, off, IBY2LG);
395	iv := int(v >> 32);
396	cache[ncached++] = byte(iv >> 24);
397	cache[ncached++] = byte(iv >> 16);
398	cache[ncached++] = byte(iv >> 8);
399	cache[ncached++] = byte(iv);
400	iv = int v;
401	cache[ncached++] = byte(iv >> 24);
402	cache[ncached++] = byte(iv >> 16);
403	cache[ncached++] = byte(iv >> 8);
404	cache[ncached++] = byte(iv);
405	ndatum++;
406}
407
408disreal(off: int, v: real)
409{
410	disflush(DEFF, off, IBY2LG);
411	export_real(cache[ncached:ncached+8], array[] of {v});
412	ncached += IBY2LG;
413	ndatum++;
414}
415
416disstring(offset: int, sym: ref Sym)
417{
418	disflush(-1, -1, 0);
419	d := array of byte sym.name;
420	disdata(DEFS, len d);
421	discon(offset);
422	bout.write(d, len d);
423}
424
425disflush(kind, off, size: int)
426{
427	if(kind != lastkind || off != lastoff){
428		if(lastkind != -1 && ncached){
429			disdata(lastkind, ndatum);
430			discon(startoff);
431			bout.write(cache, ncached);
432		}
433		startoff = off;
434		lastkind = kind;
435		ncached = 0;
436		ndatum = 0;
437	}
438	lastoff = off + size;
439	while(kind >= 0 && ncached + size >= len cache){
440		c := array[ncached + 1024] of byte;
441		c[0:] = cache;
442		cache = c;
443	}
444}
445
446dismode := array[int Aend] of
447{
448	int Aimm =>	byte AIMM,
449	int Amp =>	byte AMP,
450	int Ampind =>	byte(AMP|AIND),
451	int Afp =>	byte AFP,
452	int Afpind =>	byte(AFP|AIND),
453	int Apc =>	byte AIMM,
454	int Adesc =>	byte AIMM,
455	int Aoff =>	byte AIMM,
456	int Anoff =>	byte AIMM,
457	int Aerr =>	byte AXXX,
458	int Anone =>	byte AXXX,
459	int Aldt =>	byte AIMM,
460};
461
462disregmode := array[int Aend] of
463{
464	int Aimm =>	byte AXIMM,
465	int Amp =>	byte AXINM,
466	int Ampind =>	byte AXNON,
467	int Afp =>	byte AXINF,
468	int Afpind =>	byte AXNON,
469	int Apc =>	byte AXIMM,
470	int Adesc =>	byte AXIMM,
471	int Aoff =>	byte AXIMM,
472	int Anoff =>	byte AXIMM,
473	int Aerr =>	byte AXNON,
474	int Anone =>	byte AXNON,
475	int Aldt =>	byte AXIMM,
476};
477
478MAXCON: con 4;
479MAXADDR: con 2*MAXCON;
480MAXINST: con 3*MAXADDR+2;
481NIBUF: con 1024;
482
483ibuf:	array of byte;
484nibuf:	int;
485
486disinst(in: ref Inst)
487{
488	fileoff := bout.seek(big 0, 1);
489	ibuf = array[NIBUF] of byte;
490	nibuf = 0;
491	for(; in != nil; in = in.next){
492		if(in.op == INOOP)
493			continue;
494		if(nibuf >= NIBUF-MAXINST){
495			bout.write(ibuf, nibuf);
496			nibuf = 0;
497		}
498		ibuf[nibuf++] = byte in.op;
499		o := dismode[int in.sm] << SRC;
500		o |= dismode[int in.dm] << DST;
501		o |= disregmode[int in.mm];
502		ibuf[nibuf++] = o;
503		if(in.mm != Anone)
504			disaddr(in.mm, in.m);
505		if(in.sm != Anone)
506			disaddr(in.sm, in.s);
507		if(in.dm != Anone)
508			disaddr(in.dm, in.d);
509	}
510	if(nibuf > 0)
511		bout.write(ibuf, nibuf);
512	ibuf = nil;
513
514	if(debug['s'])
515		print("%bd instruction bytes start %bd\n", bout.seek(big 0, 1) - fileoff, fileoff);
516}
517
518disaddr(m: byte, a: Addr)
519{
520	val := 0;
521	case int m{
522	int Aimm or
523	int Apc or
524	int Adesc =>
525		val = a.offset;
526	int Aoff =>
527		val = a.decl.iface.offset;
528	int Anoff =>
529		val = -(a.decl.iface.offset+1);
530	int Afp or
531	int Amp or
532	int Aldt =>
533		val = a.reg;
534	int Afpind or
535	int Ampind =>
536		disbcon(a.reg);
537		val = a.offset;
538	}
539	disbcon(val);
540}
541
542disbcon(val: int)
543{
544	if(val >= -64 && val <= 63){
545		ibuf[nibuf++] = byte(val & ~16r80);
546		return;
547	}
548	if(val >= -8192 && val <= 8191){
549		ibuf[nibuf++] = byte(val>>8 & ~16rC0 | 16r80);
550		ibuf[nibuf++] = byte val;
551		return;
552	}
553	if(val < 0 && ((val >> 29) & 7) != 7
554	|| val > 0 && (val >> 29) != 0)
555		fatal("overflow in constant 16r"+hex(val, 0));
556	ibuf[nibuf++] = byte(val>>24 | 16rC0);
557	ibuf[nibuf++] = byte(val>>16);
558	ibuf[nibuf++] = byte(val>>8);
559	ibuf[nibuf++] = byte val;
560}
561