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