xref: /inferno-os/utils/6l/asm.c (revision 6cde411a8ffd477459336cedf48034e46f56f913)
1 #include	"l.h"
2 
3 #define	Dbufslop	100
4 
5 #define PADDR(a)	((a) & ~0xfffffffff0000000ull)
6 
7 vlong
8 entryvalue(void)
9 {
10 	char *a;
11 	Sym *s;
12 
13 	a = INITENTRY;
14 	if(*a >= '0' && *a <= '9')
15 		return atolwhex(a);
16 	s = lookup(a, 0);
17 	if(s->type == 0)
18 		return INITTEXT;
19 	switch(s->type) {
20 	case STEXT:
21 		break;
22 	case SDATA:
23 		if(dlm)
24 			return s->value+INITDAT;
25 	default:
26 		diag("entry not text: %s", s->name);
27 	}
28 	return s->value;
29 }
30 
31 /* these need to take long arguments to be compatible with elf.c */void
32 wputl(long w)
33 {
34 	cput(w);
35 	cput(w>>8);
36 }
37 
38 void
39 wput(long w)
40 {
41 	cput(w>>8);
42 	cput(w);
43 }
44 
45 void
46 lput(long l)
47 {
48 	cput(l>>24);
49 	cput(l>>16);
50 	cput(l>>8);
51 	cput(l);
52 }
53 
54 void
55 llput(vlong v)
56 {
57 	lput(v>>32);
58 	lput(v);
59 }
60 
61 void
62 lputl(long l)
63 {
64 	cput(l);
65 	cput(l>>8);
66 	cput(l>>16);
67 	cput(l>>24);
68 }
69 
70 void
71 llputl(vlong v)
72 {
73 	lputl(v);
74 	lputl(v>>32);
75 }
76 
77 void
78 strnput(char *s, int n)
79 {
80 	for(; *s && n > 0; s++){
81 		cput(*s);
82 		n--;
83 	}
84 	while(n > 0){
85 		cput(0);
86 		n--;
87 	}
88 }
89 
90 void
91 asmb(void)
92 {
93 	Prog *p;
94 	long v, magic;
95 	int a;
96 	uchar *op1;
97 	vlong vl;
98 
99 	if(debug['v'])
100 		Bprint(&bso, "%5.2f asmb\n", cputime());
101 	Bflush(&bso);
102 
103 	seek(cout, HEADR, 0);
104 	pc = INITTEXT;
105 	curp = firstp;
106 	for(p = firstp; p != P; p = p->link) {
107 		if(p->as == ATEXT)
108 			curtext = p;
109 		if(p->pc != pc) {
110 			if(!debug['a'])
111 				print("%P\n", curp);
112 			diag("phase error %llux sb %llux in %s", p->pc, pc, TNAME);
113 			pc = p->pc;
114 		}
115 		curp = p;
116 		asmins(p);
117 		a = (andptr - and);
118 		if(cbc < a)
119 			cflush();
120 		if(debug['a']) {
121 			Bprint(&bso, pcstr, pc);
122 			for(op1 = and; op1 < andptr; op1++)
123 				Bprint(&bso, "%.2ux", *op1 & 0xff);
124 			Bprint(&bso, "\t%P\n", curp);
125 		}
126 		if(dlm) {
127 			if(p->as == ATEXT)
128 				reloca = nil;
129 			else if(reloca != nil)
130 				diag("reloc failure: %P", curp);
131 		}
132 		memmove(cbp, and, a);
133 		cbp += a;
134 		pc += a;
135 		cbc -= a;
136 	}
137 	cflush();
138 	switch(HEADTYPE) {
139 	default:
140 		diag("unknown header type %ld", HEADTYPE);
141 	case 2:
142 	case 5:
143 	case 6:
144 		seek(cout, HEADR+textsize, 0);
145 		break;
146 	}
147 
148 	if(debug['v'])
149 		Bprint(&bso, "%5.2f datblk\n", cputime());
150 	Bflush(&bso);
151 
152 	if(dlm){
153 		char buf[8];
154 
155 		write(cout, buf, INITDAT-textsize);
156 		textsize = INITDAT;
157 	}
158 
159 	for(v = 0; v < datsize; v += sizeof(buf)-Dbufslop) {
160 		if(datsize-v > sizeof(buf)-Dbufslop)
161 			datblk(v, sizeof(buf)-Dbufslop);
162 		else
163 			datblk(v, datsize-v);
164 	}
165 
166 	symsize = 0;
167 	spsize = 0;
168 	lcsize = 0;
169 	if(!debug['s']) {
170 		if(debug['v'])
171 			Bprint(&bso, "%5.2f sym\n", cputime());
172 		Bflush(&bso);
173 		switch(HEADTYPE) {
174 		default:
175 		case 2:
176 		case 5:
177 		case 6:
178 			seek(cout, HEADR+textsize+datsize, 0);
179 			break;
180 		}
181 		if(!debug['s'])
182 			asmsym();
183 		if(debug['v'])
184 			Bprint(&bso, "%5.2f sp\n", cputime());
185 		Bflush(&bso);
186 		if(debug['v'])
187 			Bprint(&bso, "%5.2f pc\n", cputime());
188 		Bflush(&bso);
189 		if(!debug['s'])
190 			asmlc();
191 		if(dlm)
192 			asmdyn();
193 		cflush();
194 	}
195 	else if(dlm){
196 		seek(cout, HEADR+textsize+datsize, 0);
197 		asmdyn();
198 		cflush();
199 	}
200 	if(debug['v'])
201 		Bprint(&bso, "%5.2f headr\n", cputime());
202 	Bflush(&bso);
203 	seek(cout, 0L, 0);
204 	switch(HEADTYPE) {
205 	default:
206 	case 2:	/* plan9 */
207 		magic = 4*26*26+7;
208 		magic |= 0x00008000;		/* fat header */
209 		if(dlm)
210 			magic |= 0x80000000;	/* dlm */
211 		lput(magic);			/* magic */
212 		lput(textsize);			/* sizes */
213 		lput(datsize);
214 		lput(bsssize);
215 		lput(symsize);			/* nsyms */
216 		vl = entryvalue();
217 		lput(PADDR(vl));		/* va of entry */
218 		lput(spsize);			/* sp offsets */
219 		lput(lcsize);			/* line offsets */
220 		llput(vl);			/* va of entry */
221 		break;
222 	case 5:
223 		elf32(debug['8']? I386: AMD64, ELFDATA2LSB, 0, nil);
224 		break;
225 	case 6:
226 		elf64(AMD64, ELFDATA2LSB, 0, nil);
227 		break;
228 	}
229 	cflush();
230 }
231 
232 void
233 cflush(void)
234 {
235 	int n;
236 
237 	n = sizeof(buf.cbuf) - cbc;
238 	if(n)
239 		write(cout, buf.cbuf, n);
240 	cbp = buf.cbuf;
241 	cbc = sizeof(buf.cbuf);
242 }
243 
244 void
245 datblk(long s, long n)
246 {
247 	Prog *p;
248 	uchar *cast;
249 	long l, fl, j;
250 	vlong o;
251 	int i, c;
252 
253 	memset(buf.dbuf, 0, n+Dbufslop);
254 	for(p = datap; p != P; p = p->link) {
255 		curp = p;
256 		l = p->from.sym->value + p->from.offset - s;
257 		c = p->from.scale;
258 		i = 0;
259 		if(l < 0) {
260 			if(l+c <= 0)
261 				continue;
262 			while(l < 0) {
263 				l++;
264 				i++;
265 			}
266 		}
267 		if(l >= n)
268 			continue;
269 		if(p->as != AINIT && p->as != ADYNT) {
270 			for(j=l+(c-i)-1; j>=l; j--)
271 				if(buf.dbuf[j]) {
272 					print("%P\n", p);
273 					diag("multiple initialization");
274 					break;
275 				}
276 		}
277 		switch(p->to.type) {
278 		case D_FCONST:
279 			switch(c) {
280 			default:
281 			case 4:
282 				fl = ieeedtof(&p->to.ieee);
283 				cast = (uchar*)&fl;
284 				if(debug['a'] && i == 0) {
285 					Bprint(&bso, pcstr, l+s+INITDAT);
286 					for(j=0; j<c; j++)
287 						Bprint(&bso, "%.2ux", cast[fnuxi4[j]]);
288 					Bprint(&bso, "\t%P\n", curp);
289 				}
290 				for(; i<c; i++) {
291 					buf.dbuf[l] = cast[fnuxi4[i]];
292 					l++;
293 				}
294 				break;
295 			case 8:
296 				cast = (uchar*)&p->to.ieee;
297 				if(debug['a'] && i == 0) {
298 					Bprint(&bso, pcstr, l+s+INITDAT);
299 					for(j=0; j<c; j++)
300 						Bprint(&bso, "%.2ux", cast[fnuxi8[j]]);
301 					Bprint(&bso, "\t%P\n", curp);
302 				}
303 				for(; i<c; i++) {
304 					buf.dbuf[l] = cast[fnuxi8[i]];
305 					l++;
306 				}
307 				break;
308 			}
309 			break;
310 
311 		case D_SCONST:
312 			if(debug['a'] && i == 0) {
313 				Bprint(&bso, pcstr, l+s+INITDAT);
314 				for(j=0; j<c; j++)
315 					Bprint(&bso, "%.2ux", p->to.scon[j] & 0xff);
316 				Bprint(&bso, "\t%P\n", curp);
317 			}
318 			for(; i<c; i++) {
319 				buf.dbuf[l] = p->to.scon[i];
320 				l++;
321 			}
322 			break;
323 		default:
324 			o = p->to.offset;
325 			if(p->to.type == D_ADDR) {
326 				if(p->to.index != D_STATIC && p->to.index != D_EXTERN)
327 					diag("DADDR type%P", p);
328 				if(p->to.sym) {
329 					if(p->to.sym->type == SUNDEF)
330 						ckoff(p->to.sym, o);
331 					o += p->to.sym->value;
332 					if(p->to.sym->type != STEXT && p->to.sym->type != SUNDEF)
333 						o += INITDAT;
334 					if(dlm)
335 						dynreloc(p->to.sym, l+s+INITDAT, 1);
336 				}
337 			}
338 			fl = o;
339 			cast = (uchar*)&fl;
340 			switch(c) {
341 			default:
342 				diag("bad nuxi %d %d\n%P", c, i, curp);
343 				break;
344 			case 1:
345 				if(debug['a'] && i == 0) {
346 					Bprint(&bso, pcstr, l+s+INITDAT);
347 					for(j=0; j<c; j++)
348 						Bprint(&bso, "%.2ux", cast[inuxi1[j]]);
349 					Bprint(&bso, "\t%P\n", curp);
350 				}
351 				for(; i<c; i++) {
352 					buf.dbuf[l] = cast[inuxi1[i]];
353 					l++;
354 				}
355 				break;
356 			case 2:
357 				if(debug['a'] && i == 0) {
358 					Bprint(&bso, pcstr, l+s+INITDAT);
359 					for(j=0; j<c; j++)
360 						Bprint(&bso, "%.2ux", cast[inuxi2[j]]);
361 					Bprint(&bso, "\t%P\n", curp);
362 				}
363 				for(; i<c; i++) {
364 					buf.dbuf[l] = cast[inuxi2[i]];
365 					l++;
366 				}
367 				break;
368 			case 4:
369 				if(debug['a'] && i == 0) {
370 					Bprint(&bso, pcstr, l+s+INITDAT);
371 					for(j=0; j<c; j++)
372 						Bprint(&bso, "%.2ux", cast[inuxi4[j]]);
373 					Bprint(&bso, "\t%P\n", curp);
374 				}
375 				for(; i<c; i++) {
376 					buf.dbuf[l] = cast[inuxi4[i]];
377 					l++;
378 				}
379 				break;
380 			case 8:
381 				cast = (uchar*)&o;
382 				if(debug['a'] && i == 0) {
383 					Bprint(&bso, pcstr, l+s+INITDAT);
384 					for(j=0; j<c; j++)
385 						Bprint(&bso, "%.2ux", cast[inuxi8[j]]);
386 					Bprint(&bso, "\t%P\n", curp);
387 				}
388 				for(; i<c; i++) {
389 					buf.dbuf[l] = cast[inuxi8[i]];
390 					l++;
391 				}
392 				break;
393 			}
394 			break;
395 		}
396 	}
397 	write(cout, buf.dbuf, n);
398 }
399 
400 vlong
401 rnd(vlong v, vlong r)
402 {
403 	vlong c;
404 
405 	if(r <= 0)
406 		return v;
407 	v += r - 1;
408 	c = v % r;
409 	if(c < 0)
410 		c += r;
411 	v -= c;
412 	return v;
413 }
414