xref: /plan9-contrib/sys/src/cmd/cc/com64.c (revision 14ea38b6f8adaf7a49ae969a6611c1375d5f4c57)
1 #include "cc.h"
2 
3 /*
4  * this is machine dependent, but it is totally
5  * common on all of the 64-bit symulating machines.
6  */
7 
8 #define	FNX	100	/* botch -- redefinition */
9 
10 Node*	nodaddv;
11 Node*	nodsubv;
12 Node*	nodmulv;
13 Node*	noddivv;
14 Node*	noddivvu;
15 Node*	nodmodv;
16 Node*	nodmodvu;
17 Node*	nodlshv;
18 Node*	nodrshav;
19 Node*	nodrshlv;
20 Node*	nodandv;
21 Node*	nodorv;
22 Node*	nodxorv;
23 Node*	nodnegv;
24 Node*	nodcomv;
25 
26 Node*	nodtestv;
27 Node*	nodeqv;
28 Node*	nodnev;
29 Node*	nodlev;
30 Node*	nodltv;
31 Node*	nodgev;
32 Node*	nodgtv;
33 Node*	nodhiv;
34 Node*	nodhsv;
35 Node*	nodlov;
36 Node*	nodlsv;
37 
38 Node*	nodf2v;
39 Node*	nodd2v;
40 Node*	nodp2v;
41 Node*	nodsi2v;
42 Node*	nodui2v;
43 Node*	nodsl2v;
44 Node*	nodul2v;
45 Node*	nodsh2v;
46 Node*	noduh2v;
47 Node*	nodsc2v;
48 Node*	noduc2v;
49 
50 Node*	nodv2f;
51 Node*	nodv2d;
52 Node*	nodv2ui;
53 Node*	nodv2si;
54 Node*	nodv2ul;
55 Node*	nodv2sl;
56 Node*	nodv2uh;
57 Node*	nodv2sh;
58 Node*	nodv2uc;
59 Node*	nodv2sc;
60 
61 Node*	nodvpp;
62 Node*	nodppv;
63 Node*	nodvmm;
64 Node*	nodmmv;
65 
66 Node*	nodaddd;
67 Node*	nodsubd;
68 Node*	nodmuld;
69 Node*	noddivd;
70 
71 Node*	nodvasop;
72 
73 char	etconv[NTYPE];	/* for _vasop */
74 Init	initetconv[] =
75 {
76 	TCHAR,		1,	0,
77 	TUCHAR,		2,	0,
78 	TSHORT,		3,	0,
79 	TUSHORT,	4,	0,
80 	TLONG,		5,	0,
81 	TULONG,		6,	0,
82 	TVLONG,		7,	0,
83 	TUVLONG,	8,	0,
84 	TINT,		9,	0,
85 	TUINT,		10,	0,
86 	-1,		0,	0,
87 };
88 
89 Node*
fvn(char * name,int type)90 fvn(char *name, int type)
91 {
92 	Node *n;
93 
94 	n = new(ONAME, Z, Z);
95 	n->sym = slookup(name);
96 	n->sym->sig = SIGINTERN;
97 	if(fntypes[type] == 0)
98 		fntypes[type] = typ(TFUNC, types[type]);
99 	n->type = fntypes[type];
100 	n->etype = type;
101 	n->class = CGLOBL;
102 	n->addable = 10;
103 	n->complex = 0;
104 	return n;
105 }
106 
107 void
com64init(void)108 com64init(void)
109 {
110 	Init *p;
111 
112 	nodaddv = fvn("_addv", TVLONG);
113 	nodsubv = fvn("_subv", TVLONG);
114 	nodmulv = fvn("_mulv", TVLONG);
115 	noddivv = fvn("_divv", TVLONG);
116 	noddivvu = fvn("_divvu", TVLONG);
117 	nodmodv = fvn("_modv", TVLONG);
118 	nodmodvu = fvn("_modvu", TVLONG);
119 	nodlshv = fvn("_lshv", TVLONG);
120 	nodrshav = fvn("_rshav", TVLONG);
121 	nodrshlv = fvn("_rshlv", TVLONG);
122 	nodandv = fvn("_andv", TVLONG);
123 	nodorv = fvn("_orv", TVLONG);
124 	nodxorv = fvn("_xorv", TVLONG);
125 	nodnegv = fvn("_negv", TVLONG);
126 	nodcomv = fvn("_comv", TVLONG);
127 
128 	nodtestv = fvn("_testv", TLONG);
129 	nodeqv = fvn("_eqv", TLONG);
130 	nodnev = fvn("_nev", TLONG);
131 	nodlev = fvn("_lev", TLONG);
132 	nodltv = fvn("_ltv", TLONG);
133 	nodgev = fvn("_gev", TLONG);
134 	nodgtv = fvn("_gtv", TLONG);
135 	nodhiv = fvn("_hiv", TLONG);
136 	nodhsv = fvn("_hsv", TLONG);
137 	nodlov = fvn("_lov", TLONG);
138 	nodlsv = fvn("_lsv", TLONG);
139 
140 	nodf2v = fvn("_f2v", TVLONG);
141 	nodd2v = fvn("_d2v", TVLONG);
142 	nodp2v = fvn("_p2v", TVLONG);
143 	nodsi2v = fvn("_si2v", TVLONG);
144 	nodui2v = fvn("_ui2v", TVLONG);
145 	nodsl2v = fvn("_sl2v", TVLONG);
146 	nodul2v = fvn("_ul2v", TVLONG);
147 	nodsh2v = fvn("_sh2v", TVLONG);
148 	noduh2v = fvn("_uh2v", TVLONG);
149 	nodsc2v = fvn("_sc2v", TVLONG);
150 	noduc2v = fvn("_uc2v", TVLONG);
151 
152 	nodv2f = fvn("_v2f", TFLOAT);
153 	nodv2d = fvn("_v2d", TDOUBLE);
154 	nodv2sl = fvn("_v2sl", TLONG);
155 	nodv2ul = fvn("_v2ul", TULONG);
156 	nodv2si = fvn("_v2si", TINT);
157 	nodv2ui = fvn("_v2ui", TUINT);
158 	nodv2sh = fvn("_v2sh", TSHORT);
159 	nodv2uh = fvn("_v2ul", TUSHORT);
160 	nodv2sc = fvn("_v2sc", TCHAR);
161 	nodv2uc = fvn("_v2uc", TUCHAR);
162 
163 	nodvpp = fvn("_vpp", TVLONG);
164 	nodppv = fvn("_ppv", TVLONG);
165 	nodvmm = fvn("_vmm", TVLONG);
166 	nodmmv = fvn("_mmv", TVLONG);
167 
168 	nodaddd = fvn("_vasaddd", TVLONG);
169 	nodsubd = fvn("_vassubd", TVLONG);
170 	nodmuld = fvn("_vasmuld", TVLONG);
171 	noddivd = fvn("_vasdivd", TVLONG);
172 
173 	nodvasop = fvn("_vasop", TVLONG);
174 
175 	for(p = initetconv; p->code >= 0; p++)
176 		etconv[p->code] = p->value;
177 }
178 
179 int
com64(Node * n)180 com64(Node *n)
181 {
182 	Node *l, *r, *a, *t;
183 	int lv, rv;
184 
185 	if(n->type == 0)
186 		return 0;
187 
188 	l = n->left;
189 	r = n->right;
190 
191 	lv = 0;
192 	if(l && l->type && typev[l->type->etype])
193 		lv = 1;
194 	rv = 0;
195 	if(r && r->type && typev[r->type->etype])
196 		rv = 1;
197 
198 	if(lv) {
199 		switch(n->op) {
200 		case OEQ:
201 			a = nodeqv;
202 			goto setbool;
203 		case ONE:
204 			a = nodnev;
205 			goto setbool;
206 		case OLE:
207 			a = nodlev;
208 			goto setbool;
209 		case OLT:
210 			a = nodltv;
211 			goto setbool;
212 		case OGE:
213 			a = nodgev;
214 			goto setbool;
215 		case OGT:
216 			a = nodgtv;
217 			goto setbool;
218 		case OHI:
219 			a = nodhiv;
220 			goto setbool;
221 		case OHS:
222 			a = nodhsv;
223 			goto setbool;
224 		case OLO:
225 			a = nodlov;
226 			goto setbool;
227 		case OLS:
228 			a = nodlsv;
229 			goto setbool;
230 
231 		case OANDAND:
232 		case OOROR:
233 			if(machcap(n))
234 				return 1;
235 
236 			if(rv) {
237 				r = new(OFUNC, nodtestv, r);
238 				n->right = r;
239 				r->complex = FNX;
240 				r->op = OFUNC;
241 				r->type = types[TLONG];
242 			}
243 
244 		case OCOND:
245 		case ONOT:
246 			if(machcap(n))
247 				return 1;
248 
249 			l = new(OFUNC, nodtestv, l);
250 			n->left = l;
251 			l->complex = FNX;
252 			l->op = OFUNC;
253 			l->type = types[TLONG];
254 			n->complex = FNX;
255 			return 1;
256 		}
257 	}
258 
259 	if(rv) {
260 		if(machcap(n))
261 			return 1;
262 		switch(n->op) {
263 		case OANDAND:
264 		case OOROR:
265 			r = new(OFUNC, nodtestv, r);
266 			n->right = r;
267 			r->complex = FNX;
268 			r->op = OFUNC;
269 			r->type = types[TLONG];
270 			return 1;
271 		case OCOND:
272 			return 1;
273 		}
274 	}
275 
276 	if(typev[n->type->etype]) {
277 		if(machcap(n))
278 			return 1;
279 		switch(n->op) {
280 		default:
281 			diag(n, "unknown vlong %O", n->op);
282 		case OFUNC:
283 			n->complex = FNX;
284 		case ORETURN:
285 		case OAS:
286 		case OIND:
287 		case OLIST:
288 		case OCOMMA:
289 			return 1;
290 		case OADD:
291 			a = nodaddv;
292 			goto setbop;
293 		case OSUB:
294 			a = nodsubv;
295 			goto setbop;
296 		case OMUL:
297 		case OLMUL:
298 			a = nodmulv;
299 			goto setbop;
300 		case ODIV:
301 			a = noddivv;
302 			goto setbop;
303 		case OLDIV:
304 			a = noddivvu;
305 			goto setbop;
306 		case OMOD:
307 			a = nodmodv;
308 			goto setbop;
309 		case OLMOD:
310 			a = nodmodvu;
311 			goto setbop;
312 		case OASHL:
313 			a = nodlshv;
314 			goto setbop;
315 		case OASHR:
316 			a = nodrshav;
317 			goto setbop;
318 		case OLSHR:
319 			a = nodrshlv;
320 			goto setbop;
321 		case OAND:
322 			a = nodandv;
323 			goto setbop;
324 		case OOR:
325 			a = nodorv;
326 			goto setbop;
327 		case OXOR:
328 			a = nodxorv;
329 			goto setbop;
330 		case OPOSTINC:
331 			a = nodvpp;
332 			goto setvinc;
333 		case OPOSTDEC:
334 			a = nodvmm;
335 			goto setvinc;
336 		case OPREINC:
337 			a = nodppv;
338 			goto setvinc;
339 		case OPREDEC:
340 			a = nodmmv;
341 			goto setvinc;
342 		case ONEG:
343 			a = nodnegv;
344 			goto setfnx;
345 		case OCOM:
346 			a = nodcomv;
347 			goto setfnx;
348 		case OCAST:
349 			switch(l->type->etype) {
350 			case TCHAR:
351 				a = nodsc2v;
352 				goto setfnxl;
353 			case TUCHAR:
354 				a = noduc2v;
355 				goto setfnxl;
356 			case TSHORT:
357 				a = nodsh2v;
358 				goto setfnxl;
359 			case TUSHORT:
360 				a = noduh2v;
361 				goto setfnxl;
362 			case TINT:
363 				a = nodsi2v;
364 				goto setfnx;
365 			case TUINT:
366 				a = nodui2v;
367 				goto setfnx;
368 			case TLONG:
369 				a = nodsl2v;
370 				goto setfnx;
371 			case TULONG:
372 				a = nodul2v;
373 				goto setfnx;
374 			case TFLOAT:
375 				a = nodf2v;
376 				goto setfnx;
377 			case TDOUBLE:
378 				a = nodd2v;
379 				goto setfnx;
380 			case TIND:
381 				a = nodp2v;
382 				goto setfnx;
383 			}
384 			diag(n, "unknown %T->vlong cast", l->type);
385 			return 1;
386 		case OASADD:
387 			a = nodaddv;
388 			goto setasop;
389 		case OASSUB:
390 			a = nodsubv;
391 			goto setasop;
392 		case OASMUL:
393 		case OASLMUL:
394 			a = nodmulv;
395 			goto setasop;
396 		case OASDIV:
397 			a = noddivv;
398 			goto setasop;
399 		case OASLDIV:
400 			a = noddivvu;
401 			goto setasop;
402 		case OASMOD:
403 			a = nodmodv;
404 			goto setasop;
405 		case OASLMOD:
406 			a = nodmodvu;
407 			goto setasop;
408 		case OASASHL:
409 			a = nodlshv;
410 			goto setasop;
411 		case OASASHR:
412 			a = nodrshav;
413 			goto setasop;
414 		case OASLSHR:
415 			a = nodrshlv;
416 			goto setasop;
417 		case OASAND:
418 			a = nodandv;
419 			goto setasop;
420 		case OASOR:
421 			a = nodorv;
422 			goto setasop;
423 		case OASXOR:
424 			a = nodxorv;
425 			goto setasop;
426 		}
427 	}
428 
429 	if(typefd[n->type->etype] && l && l->op == OFUNC) {
430 		switch(n->op) {
431 		case OASADD:
432 		case OASSUB:
433 		case OASMUL:
434 		case OASLMUL:
435 		case OASDIV:
436 		case OASLDIV:
437 		case OASMOD:
438 		case OASLMOD:
439 		case OASASHL:
440 		case OASASHR:
441 		case OASLSHR:
442 		case OASAND:
443 		case OASOR:
444 		case OASXOR:
445 			if(l->right && typev[l->right->etype]) {
446 				diag(n, "sorry float <asop> vlong not implemented\n");
447 			}
448 		}
449 	}
450 
451 	if(n->op == OCAST) {
452 		if(l->type && typev[l->type->etype]) {
453 			if(machcap(n))
454 				return 1;
455 			switch(n->type->etype) {
456 			case TDOUBLE:
457 				a = nodv2d;
458 				goto setfnx;
459 			case TFLOAT:
460 				a = nodv2f;
461 				goto setfnx;
462 			case TLONG:
463 				a = nodv2sl;
464 				goto setfnx;
465 			case TULONG:
466 				a = nodv2ul;
467 				goto setfnx;
468 			case TINT:
469 				a = nodv2si;
470 				goto setfnx;
471 			case TUINT:
472 				a = nodv2ui;
473 				goto setfnx;
474 			case TSHORT:
475 				a = nodv2sh;
476 				goto setfnx;
477 			case TUSHORT:
478 				a = nodv2uh;
479 				goto setfnx;
480 			case TCHAR:
481 				a = nodv2sc;
482 				goto setfnx;
483 			case TUCHAR:
484 				a = nodv2uc;
485 				goto setfnx;
486 			case TIND:	// small pun here
487 				a = nodv2ul;
488 				goto setfnx;
489 			}
490 			diag(n, "unknown vlong->%T cast", n->type);
491 			return 1;
492 		}
493 	}
494 
495 	return 0;
496 
497 setbop:
498 	n->left = a;
499 	n->right = new(OLIST, l, r);
500 	n->complex = FNX;
501 	n->op = OFUNC;
502 	return 1;
503 
504 setfnxl:
505 	l = new(OCAST, l, 0);
506 	l->type = types[TLONG];
507 	l->complex = l->left->complex;
508 
509 setfnx:
510 	n->left = a;
511 	n->right = l;
512 	n->complex = FNX;
513 	n->op = OFUNC;
514 	return 1;
515 
516 setvinc:
517 	n->left = a;
518 	l = new(OADDR, l, Z);
519 	l->type = typ(TIND, l->left->type);
520 	l->complex = l->left->complex;
521 	n->right = new(OLIST, l, r);
522 	n->complex = FNX;
523 	n->op = OFUNC;
524 	return 1;
525 
526 setbool:
527 	if(machcap(n))
528 		return 1;
529 	n->left = a;
530 	n->right = new(OLIST, l, r);
531 	n->complex = FNX;
532 	n->op = OFUNC;
533 	n->type = types[TLONG];
534 	return 1;
535 
536 setasop:
537 	while(l->op == OFUNC)
538 		l = l->right;
539 
540 	if(mixedasop(n->left->type, n->right->type)) {
541 		if(n->right->type->etype != TDOUBLE) {
542 			r = new(OCAST, r, 0);
543 			r->type = types[TDOUBLE];
544 		}
545 
546 		t = new(OADDR, l, 0);
547 		t->type = typ(TIND, l->type);
548 		t->complex = l->complex;
549 		r = new(OLIST, t, r);
550 
551 		switch(n->op) {
552 		case OASADD:	a = nodaddd; break;
553 		case OASSUB:	a = nodsubd; break;
554 		case OASMUL:	a = nodmuld; break;
555 		case OASDIV:	a = noddivd; break;
556 		default:	diag(n, "bad vasop %O", n->op); a = nodaddd; break;
557 		}
558 
559 		n->left = a;
560 		n->right = r;
561 		n->complex = FNX;
562 		n->op = OFUNC;
563 
564 	} else {
565 		t = new(OCONST, 0, 0);
566 		t->vconst = etconv[l->type->etype];
567 		t->type = types[TLONG];
568 		t->addable = 20;
569 		r = new(OLIST, t, r);
570 
571 		t = new(OADDR, a, 0);
572 		t->type = typ(TIND, a->type);
573 		r = new(OLIST, t, r);
574 
575 		t = new(OADDR, l, 0);
576 		t->type = typ(TIND, l->type);
577 		t->complex = l->complex;
578 		r = new(OLIST, t, r);
579 
580 		n->left = nodvasop;
581 		n->right = r;
582 		n->complex = FNX;
583 		n->op = OFUNC;
584 	}
585 
586 	return 1;
587 }
588 
589 void
bool64(Node * n)590 bool64(Node *n)
591 {
592 	Node *n1;
593 
594 	if(machcap(Z))
595 		return;
596 	if(typev[n->type->etype]) {
597 		n1 = new(OXXX, 0, 0);
598 		*n1 = *n;
599 
600 		n->right = n1;
601 		n->left = nodtestv;
602 		n->complex = FNX;
603 		n->addable = 0;
604 		n->op = OFUNC;
605 		n->type = types[TLONG];
606 	}
607 }
608 
609 /*
610  * more machine depend stuff.
611  * this is common for 8,16,32,64 bit machines.
612  * this is common for ieee machines.
613  */
614 double
convvtof(vlong v)615 convvtof(vlong v)
616 {
617 	double d;
618 
619 	d = v;		/* BOTCH */
620 	return d;
621 }
622 
623 vlong
convftov(double d)624 convftov(double d)
625 {
626 	vlong v;
627 
628 
629 	v = d;		/* BOTCH */
630 	return v;
631 }
632 
633 double
convftox(double d,int et)634 convftox(double d, int et)
635 {
636 
637 	if(!typefd[et])
638 		diag(Z, "bad type in castftox %s", tnames[et]);
639 	return d;
640 }
641 
642 vlong
convvtox(vlong c,int et)643 convvtox(vlong c, int et)
644 {
645 	int n;
646 
647 	n = 8 * ewidth[et];
648 	c &= MASK(n);
649 	if(!typeu[et])
650 		if(c & SIGN(n))
651 			c |= ~MASK(n);
652 	return c;
653 }
654