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