xref: /inferno-os/utils/5l/list.c (revision 50b0dbb170df61467e42c7ea4deb0b5692d15f4c)
1 #include "l.h"
2 
3 void
4 listinit(void)
5 {
6 
7 	fmtinstall('A', Aconv);
8 	fmtinstall('C', Cconv);
9 	fmtinstall('D', Dconv);
10 	fmtinstall('P', Pconv);
11 	fmtinstall('S', Sconv);
12 	fmtinstall('N', Nconv);
13 }
14 
15 void
16 prasm(Prog *p)
17 {
18 	print("%P\n", p);
19 }
20 
21 int
22 Pconv(Fmt *fp)
23 {
24 	char str[STRINGSZ], *s;
25 	Prog *p;
26 	int a;
27 
28 	p = va_arg(fp->args, Prog*);
29 	curp = p;
30 	a = p->as;
31 	switch(a) {
32 	default:
33 		s = str;
34 		s += sprint(s, "(%ld)", p->line);
35 		if(p->reg == NREG)
36 			sprint(s, "	%A%C	%D,%D",
37 				a, p->scond, &p->from, &p->to);
38 		else
39 		if(p->from.type != D_FREG)
40 			sprint(s, "	%A%C	%D,R%d,%D",
41 				a, p->scond, &p->from, p->reg, &p->to);
42 		else
43 			sprint(s, "	%A%C	%D,F%d,%D",
44 				a, p->scond, &p->from, p->reg, &p->to);
45 		break;
46 
47 	case ASWPW:
48 	case ASWPBU:
49 		sprint(str, "(%ld)	%A%C	R%d,%D,%D",
50 			p->line, a, p->scond, p->reg, &p->from, &p->to);
51 		break;
52 
53 	case ADATA:
54 	case AINIT:
55 	case ADYNT:
56 		sprint(str, "(%ld)	%A%C	%D/%d,%D",
57 			p->line, a, p->scond, &p->from, p->reg, &p->to);
58 		break;
59 	}
60 	return fmtstrcpy(fp, str);
61 }
62 
63 int
64 Aconv(Fmt *fp)
65 {
66 	char *s;
67 	int a;
68 
69 	a = va_arg(fp->args, int);
70 	s = "?";
71 	if(a >= AXXX && a < ALAST)
72 		s = anames[a];
73 	return fmtstrcpy(fp, s);
74 }
75 
76 char*	strcond[16] =
77 {
78 	".EQ",
79 	".NE",
80 	".HS",
81 	".LO",
82 	".MI",
83 	".PL",
84 	".VS",
85 	".VC",
86 	".HI",
87 	".LS",
88 	".GE",
89 	".LT",
90 	".GT",
91 	".LE",
92 	"",
93 	".NV"
94 };
95 
96 int
97 Cconv(Fmt *fp)
98 {
99 	char s[20];
100 	int c;
101 
102 	c = va_arg(fp->args, int);
103 	strcpy(s, strcond[c & C_SCOND]);
104 	if(c & C_SBIT)
105 		strcat(s, ".S");
106 	if(c & C_PBIT)
107 		strcat(s, ".P");
108 	if(c & C_WBIT)
109 		strcat(s, ".W");
110 	if(c & C_UBIT)		/* ambiguous with FBIT */
111 		strcat(s, ".U");
112 	return fmtstrcpy(fp, s);
113 }
114 
115 int
116 Dconv(Fmt *fp)
117 {
118 	char str[STRINGSZ];
119 	char *op;
120 	Adr *a;
121 	long v;
122 
123 	a = va_arg(fp->args, Adr*);
124 	switch(a->type) {
125 
126 	default:
127 		sprint(str, "GOK-type(%d)", a->type);
128 		break;
129 
130 	case D_NONE:
131 		str[0] = 0;
132 		if(a->name != D_NONE || a->reg != NREG || a->sym != S)
133 			sprint(str, "%N(R%d)(NONE)", a, a->reg);
134 		break;
135 
136 	case D_CONST:
137 		if(a->reg == NREG)
138 			sprint(str, "$%N", a);
139 		else
140 			sprint(str, "$%N(R%d)", a, a->reg);
141 		break;
142 
143 	case D_SHIFT:
144 		v = a->offset;
145 		op = "<<>>->@>" + (((v>>5) & 3) << 1);
146 		if(v & (1<<4))
147 			sprint(str, "R%ld%c%cR%ld", v&15, op[0], op[1], (v>>8)&15);
148 		else
149 			sprint(str, "R%ld%c%c%ld", v&15, op[0], op[1], (v>>7)&31);
150 		if(a->reg != NREG)
151 			sprint(str+strlen(str), "(R%d)", a->reg);
152 		break;
153 
154 	case D_OCONST:
155 		sprint(str, "$*$%N", a);
156 		if(a->reg != NREG)
157 			sprint(str, "%N(R%d)(CONST)", a, a->reg);
158 		break;
159 
160 	case D_OREG:
161 		if(a->reg != NREG)
162 			sprint(str, "%N(R%d)", a, a->reg);
163 		else
164 			sprint(str, "%N", a);
165 		break;
166 
167 	case D_REG:
168 		sprint(str, "R%d", a->reg);
169 		if(a->name != D_NONE || a->sym != S)
170 			sprint(str, "%N(R%d)(REG)", a, a->reg);
171 		break;
172 
173 	case D_REGREG:
174 		sprint(str, "(R%d,R%d)", a->reg, (int)a->offset);
175 		if(a->name != D_NONE || a->sym != S)
176 			sprint(str, "%N(R%d)(REG)", a, a->reg);
177 		break;
178 
179 	case D_FREG:
180 		sprint(str, "F%d", a->reg);
181 		if(a->name != D_NONE || a->sym != S)
182 			sprint(str, "%N(R%d)(REG)", a, a->reg);
183 		break;
184 
185 	case D_PSR:
186 		switch(a->reg) {
187 		case 0:
188 			sprint(str, "CPSR");
189 			break;
190 		case 1:
191 			sprint(str, "SPSR");
192 			break;
193 		default:
194 			sprint(str, "PSR%d", a->reg);
195 			break;
196 		}
197 		if(a->name != D_NONE || a->sym != S)
198 			sprint(str, "%N(PSR%d)(REG)", a, a->reg);
199 		break;
200 
201 	case D_FPCR:
202 		switch(a->reg){
203 		case 0:
204 			sprint(str, "FPSR");
205 			break;
206 		case 1:
207 			sprint(str, "FPCR");
208 			break;
209 		default:
210 			sprint(str, "FCR%d", a->reg);
211 			break;
212 		}
213 		if(a->name != D_NONE || a->sym != S)
214 			sprint(str, "%N(FCR%d)(REG)", a, a->reg);
215 
216 		break;
217 
218 	case D_BRANCH:	/* botch */
219 		if(curp->cond != P) {
220 			v = curp->cond->pc;
221 			if(a->sym != S)
222 				sprint(str, "%s+%.5lux(BRANCH)", a->sym->name, v);
223 			else
224 				sprint(str, "%.5lux(BRANCH)", v);
225 		} else
226 			if(a->sym != S)
227 				sprint(str, "%s+%ld(APC)", a->sym->name, a->offset);
228 			else
229 				sprint(str, "%ld(APC)", a->offset);
230 		break;
231 
232 	case D_FCONST:
233 		sprint(str, "$%e", ieeedtod(a->ieee));
234 		break;
235 
236 	case D_SCONST:
237 		sprint(str, "$\"%S\"", a->sval);
238 		break;
239 	}
240 	return fmtstrcpy(fp, str);
241 }
242 
243 int
244 Nconv(Fmt *fp)
245 {
246 	char str[STRINGSZ];
247 	Adr *a;
248 	Sym *s;
249 
250 	a = va_arg(fp->args, Adr*);
251 	s = a->sym;
252 	switch(a->name) {
253 	default:
254 		sprint(str, "GOK-name(%d)", a->name);
255 		break;
256 
257 	case D_NONE:
258 		sprint(str, "%ld", a->offset);
259 		break;
260 
261 	case D_EXTERN:
262 		if(s == S)
263 			sprint(str, "%ld(SB)", a->offset);
264 		else
265 			sprint(str, "%s+%ld(SB)", s->name, a->offset);
266 		break;
267 
268 	case D_STATIC:
269 		if(s == S)
270 			sprint(str, "<>+%ld(SB)", a->offset);
271 		else
272 			sprint(str, "%s<>+%ld(SB)", s->name, a->offset);
273 		break;
274 
275 	case D_AUTO:
276 		if(s == S)
277 			sprint(str, "%ld(SP)", a->offset);
278 		else
279 			sprint(str, "%s-%ld(SP)", s->name, -a->offset);
280 		break;
281 
282 	case D_PARAM:
283 		if(s == S)
284 			sprint(str, "%ld(FP)", a->offset);
285 		else
286 			sprint(str, "%s+%ld(FP)", s->name, a->offset);
287 		break;
288 	}
289 	return fmtstrcpy(fp, str);
290 }
291 
292 int
293 Sconv(Fmt *fp)
294 {
295 	int i, c;
296 	char str[STRINGSZ], *p, *a;
297 
298 	a = va_arg(fp->args, char*);
299 	p = str;
300 	for(i=0; i<sizeof(long); i++) {
301 		c = a[i] & 0xff;
302 		if(c >= 'a' && c <= 'z' ||
303 		   c >= 'A' && c <= 'Z' ||
304 		   c >= '0' && c <= '9' ||
305 		   c == ' ' || c == '%') {
306 			*p++ = c;
307 			continue;
308 		}
309 		*p++ = '\\';
310 		switch(c) {
311 		case 0:
312 			*p++ = 'z';
313 			continue;
314 		case '\\':
315 		case '"':
316 			*p++ = c;
317 			continue;
318 		case '\n':
319 			*p++ = 'n';
320 			continue;
321 		case '\t':
322 			*p++ = 't';
323 			continue;
324 		}
325 		*p++ = (c>>6) + '0';
326 		*p++ = ((c>>3) & 7) + '0';
327 		*p++ = (c & 7) + '0';
328 	}
329 	*p = 0;
330 	return fmtstrcpy(fp, str);
331 }
332 
333 void
334 diag(char *fmt, ...)
335 {
336 	char buf[STRINGSZ], *tn;
337 	va_list arg;
338 
339 	tn = "??none??";
340 	if(curtext != P && curtext->from.sym != S)
341 		tn = curtext->from.sym->name;
342 	va_start(arg, fmt);
343 	vseprint(buf, buf+sizeof(buf), fmt, arg);
344 	va_end(arg);
345 	print("%s: %s\n", tn, buf);
346 
347 	nerrors++;
348 	if(nerrors > 10) {
349 		print("too many errors\n");
350 		errorexit();
351 	}
352 }
353