1 /* Id: local2.c,v 1.62 2015/12/13 09:00:04 ragge Exp */
2 /* $NetBSD: local2.c,v 1.4 2016/02/09 20:37:32 plunky Exp $ */
3 /*
4 * Copyright (c) 2008 Michael Shalayeff
5 * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 # include "pass2.h"
32 # include <ctype.h>
33 # include <string.h>
34
35 static int stkpos;
36
37 void
deflab(int label)38 deflab(int label)
39 {
40 printf(LABFMT ":\n", label);
41 }
42
43 static int regoff[MAXREGS];
44 static TWORD ftype;
45 char *rbyte[], *rshort[], *rlong[];
46 static int needframe;
47
48 /*
49 * Print out the prolog assembler.
50 * addto and regoff are already calculated.
51 */
52 static void
prtprolog(struct interpass_prolog * ipp,int addto)53 prtprolog(struct interpass_prolog *ipp, int addto)
54 {
55 int i;
56
57 printf("\tpushq %%rbp\n");
58 printf("\tmovq %%rsp,%%rbp\n");
59 addto = (addto+15) & ~15; /* 16-byte aligned */
60 if (addto)
61 printf("\tsubq $%d,%%rsp\n", addto);
62
63 /* save permanent registers */
64 for (i = 0; i < MAXREGS; i++)
65 if (TESTBIT(ipp->ipp_regs, i))
66 printf("\tmovq %s,-%d(%s)\n",
67 rnames[i], regoff[i], rnames[FPREG]);
68 }
69
70 /*
71 * calculate stack size and offsets
72 */
73 static int
offcalc(struct interpass_prolog * ipp)74 offcalc(struct interpass_prolog *ipp)
75 {
76 int i, addto;
77
78 addto = p2maxautooff;
79 if (addto >= AUTOINIT/SZCHAR)
80 addto -= AUTOINIT/SZCHAR;
81 for (i = 0; i < MAXREGS; i++)
82 if (TESTBIT(ipp->ipp_regs, i)) {
83 addto += SZLONG/SZCHAR;
84 regoff[i] = addto;
85 }
86 return addto;
87 }
88
89 /*
90 * Traverse a tree to check if we need to emit a frame at all.
91 * We emit it if:
92 * - any function call
93 * - rsp or rbp referenced
94 * Return 1 if frame is needed, 0 otherwise.
95 */
96 static int
chkf(NODE * p)97 chkf(NODE *p)
98 {
99 int o = p->n_op;
100
101 if ((o == REG || o == OREG) && (regno(p) == RBP || regno(p) == RSP))
102 return 1;
103 if (callop(o))
104 return 1;
105 if (optype(o) == UTYPE)
106 return chkf(p->n_left);
107 else if (optype(o) == BITYPE)
108 return chkf(p->n_left) || chkf(p->n_right);
109 return 0;
110 }
111
112 static int
chkframe(struct interpass_prolog * ipp)113 chkframe(struct interpass_prolog *ipp)
114 {
115 struct interpass *ip;
116
117 DLIST_FOREACH(ip, &ipp->ipp_ip, qelem) {
118 if (ip->type == IP_EPILOG)
119 break;
120 if (ip->type == IP_NODE) {
121 if (chkf(ip->ip_node))
122 return 1;
123 }
124 }
125 return 0;
126 }
127
128 void
prologue(struct interpass_prolog * ipp)129 prologue(struct interpass_prolog *ipp)
130 {
131 int addto;
132
133 ftype = ipp->ipp_type;
134
135 if (xdeljumps)
136 needframe = chkframe(ipp);
137 else
138 needframe = 1;
139
140 #ifdef LANG_F77
141 if (ipp->ipp_vis)
142 printf(" .globl %s\n", ipp->ipp_name);
143 printf(" .align 16\n");
144 printf("%s:\n", ipp->ipp_name);
145 #endif
146 /*
147 * We here know what register to save and how much to
148 * add to the stack.
149 */
150 addto = offcalc(ipp);
151 if (addto)
152 needframe = 1;
153 if (needframe)
154 prtprolog(ipp, addto);
155 }
156
157 void
eoftn(struct interpass_prolog * ipp)158 eoftn(struct interpass_prolog *ipp)
159 {
160 int i;
161
162 if (ipp->ipp_ip.ip_lbl == 0)
163 return; /* no code needs to be generated */
164
165 if (needframe) {
166 /* return from function code */
167 for (i = 0; i < MAXREGS; i++)
168 if (TESTBIT(ipp->ipp_regs, i))
169 printf(" movq -%d(%s),%s\n",
170 regoff[i], rnames[FPREG], rnames[i]);
171
172 /* struct return needs special treatment */
173 if (ftype == STRTY || ftype == UNIONTY) {
174 printf(" movl 8(%%ebp),%%eax\n");
175 printf(" leave\n");
176 printf(" ret $%d\n", 4);
177 } else {
178 printf(" leave\n");
179 printf(" ret\n");
180 }
181 } else
182 printf("\tret\n");
183
184 #ifndef MACHOABI
185 printf("\t.size %s,.-%s\n", ipp->ipp_name, ipp->ipp_name);
186 #endif
187 }
188
189 /*
190 * add/sub/...
191 *
192 * Param given:
193 */
194 void
hopcode(int f,int o)195 hopcode(int f, int o)
196 {
197 char *str;
198
199 switch (o) {
200 case PLUS:
201 str = "add";
202 break;
203 case MINUS:
204 str = "sub";
205 break;
206 case AND:
207 str = "and";
208 break;
209 case OR:
210 str = "or";
211 break;
212 case ER:
213 str = "xor";
214 break;
215 default:
216 comperr("hopcode2: %d", o);
217 str = 0; /* XXX gcc */
218 }
219 printf("%s%c", str, f);
220 }
221
222 /*
223 * Return type size in bytes. Used by R2REGS, arg 2 to offset().
224 */
225 int
tlen(NODE * p)226 tlen(NODE *p)
227 {
228 switch(p->n_type) {
229 case CHAR:
230 case UCHAR:
231 return(1);
232
233 case SHORT:
234 case USHORT:
235 return(SZSHORT/SZCHAR);
236
237 case DOUBLE:
238 return(SZDOUBLE/SZCHAR);
239
240 case INT:
241 case UNSIGNED:
242 return(SZINT/SZCHAR);
243
244 case LONG:
245 case ULONG:
246 case LONGLONG:
247 case ULONGLONG:
248 return SZLONGLONG/SZCHAR;
249
250 default:
251 if (!ISPTR(p->n_type))
252 comperr("tlen type %d not pointer");
253 return SZPOINT(p->n_type)/SZCHAR;
254 }
255 }
256
257 /*
258 * Compare two floating point numbers.
259 */
260 static void
fcomp(NODE * p)261 fcomp(NODE *p)
262 {
263
264 if (p->n_left->n_op != REG)
265 comperr("bad compare %p\n", p);
266 if ((p->n_su & DORIGHT) == 0)
267 expand(p, 0, "\tfxch\n");
268 expand(p, 0, "\tfucomip %st(1),%st\n"); /* emit compare insn */
269 expand(p, 0, "\tfstp %st(0)\n"); /* pop fromstack */
270 zzzcode(p, 'U');
271 }
272
273 int
fldexpand(NODE * p,int cookie,char ** cp)274 fldexpand(NODE *p, int cookie, char **cp)
275 {
276 comperr("fldexpand");
277 return 0;
278 }
279
280 static void
stasg(NODE * p)281 stasg(NODE *p)
282 {
283 struct attr *ap = attr_find(p->n_ap, ATTR_P2STRUCT);
284 expand(p, INAREG, " leaq AL,%rdi\n");
285 if (ap->iarg(0) >= 8)
286 printf("\tmovl $%d,%%ecx\n\trep movsq\n", ap->iarg(0) >> 3);
287 if (ap->iarg(0) & 4)
288 printf("\tmovsl\n");
289 if (ap->iarg(0) & 2)
290 printf("\tmovsw\n");
291 if (ap->iarg(0) & 1)
292 printf("\tmovsb\n");
293 }
294
295 #define E(x) expand(p, 0, x)
296 /*
297 * Generate code to convert an unsigned long to xmm float/double.
298 */
299 static void
ultofd(NODE * p)300 ultofd(NODE *p)
301 {
302
303 E(" movq AL,A1\n");
304 E(" testq A1,A1\n");
305 E(" js 2f\n");
306 E(" cvtsi2sZfq A1,A3\n");
307 E(" jmp 3f\n");
308 E("2:\n");
309 E(" movq A1,A2\n");
310 E(" shrq A2\n");
311 E(" andq $1,A1\n");
312 E(" orq A1,A2\n");
313 E(" cvtsi2sZfq A2,A3\n");
314 E(" addsZf A3,A3\n");
315 E("3:\n");
316 }
317
318 /*
319 * Generate code to convert an x87 long double to an unsigned long.
320 * This is ugly :-/
321 */
322 static void
ldtoul(NODE * p)323 ldtoul(NODE *p)
324 {
325
326 E(" subq $16,%rsp\n");
327 E(" movl $0x5f000000,(%rsp)\n"); /* More than long can have */
328 E(" flds (%rsp)\n");
329 if (p->n_left->n_op == REG) {
330 E(" fxch\n");
331 } else
332 E(" fldt AL\n");
333 E(" fucomi %st(1), %st\n");
334 E(" jae 2f\n");
335
336 E(" fstp %st(1)\n"); /* Pop huge val from stack */
337 E(" fnstcw (%rsp)\n"); /* store cw */
338 E(" movw $0x0f3f,4(%rsp)\n");/* round towards 0 */
339 E(" fldcw 4(%rsp)\n"); /* new cw */
340 E(" fistpll 8(%rsp)\n"); /* save val */
341 E(" fldcw (%rsp)\n"); /* fetch old cw */
342 E(" movq 8(%rsp),A1\n");
343
344 E(" jmp 3f\n");
345
346 E("2:\n");
347
348 E(" fsubp %st, %st(1)\n");
349 E(" fnstcw (%rsp)\n");
350 E(" movw $0x0f3f,4(%rsp)\n");
351 E(" fldcw 4(%rsp)\n");
352 E(" fistpll 8(%rsp)\n");
353 E(" fldcw (%rsp)\n");
354 E(" movabsq $0x8000000000000000,A1\n");
355 E(" xorq 8(%rsp),A1\n");
356
357 E("3: addq $16,%rsp\n");
358 }
359
360 /*
361 * Generate code to convert an SSE float/double to an unsigned long.
362 */
363 static void
fdtoul(NODE * p)364 fdtoul(NODE *p)
365 {
366 if (p->n_left->n_type == FLOAT)
367 E(" movabsq $0x5f000000,A1\n");
368 else
369 E(" movabsq $0x43e0000000000000,A1\n");
370 E(" movd A1,A3\n");
371 E(" ucomisZg A3,AL\n");
372 E(" jae 2f\n");
373 E(" cvttsZg2siq AL,A1\n");
374 E(" jmp 3f\n");
375 E("2:\n");
376 E(" subsZg A3,AL\n");
377 E(" cvttsZg2siq AL,A1\n");
378 E(" movabsq $0x8000000000000000,A2\n");
379 E(" xorq A2,A1\n");
380 E("3:\n");
381 }
382 #undef E
383
384 void
zzzcode(NODE * p,int c)385 zzzcode(NODE *p, int c)
386 {
387 struct attr *ap, *ap2;
388 NODE *l;
389 int pr, lr, s;
390 char **rt;
391
392 switch (c) {
393 case 'A': /* swap st0 and st1 if right is evaluated second */
394 if ((p->n_su & DORIGHT) == 0) {
395 if (logop(p->n_op))
396 printf(" fxch\n");
397 else
398 printf("r");
399 }
400 break;
401
402 case 'B': /* ldouble to unsigned long cast */
403 ldtoul(p);
404 break;
405
406 case 'b': /* float/double to unsigned long cast */
407 fdtoul(p);
408 break;
409
410 case 'C': /* remove from stack after subroutine call */
411 pr = p->n_qual;
412 if (p->n_op == UCALL)
413 return; /* XXX remove ZC from UCALL */
414 if (pr)
415 printf(" addq $%d, %s\n", pr, rnames[RSP]);
416 #define STRREG 6
417 #define STRSSE 8
418 #define STRIF 9
419 #define STRFI 10
420 #define STRX87 11
421 ap = attr_find(p->n_ap, ATTR_P2STRUCT);
422 ap2 = attr_find(p->n_ap, ATTR_AMD64_CMPLRET);
423 if ((p->n_op == STCALL || p->n_op == USTCALL) &&
424 ap->iarg(0) == 32 && ap2->iarg(0) == STRX87) {
425 printf("\tfstpt -%d(%%rbp)\n", stkpos);
426 printf("\tfstpt -%d(%%rbp)\n", stkpos-16);
427 printf("\tleaq -%d(%%rbp),%%rax\n", stkpos);
428 }
429 if ((p->n_op == STCALL || p->n_op == USTCALL) &&
430 ap->iarg(0) <= 16) {
431 /* store reg-passed structs on stack */
432 if (ap2->iarg(0) == STRREG || ap2->iarg(0) == STRIF)
433 printf("\tmovq %%rax,-%d(%%rbp)\n", stkpos);
434 else
435 printf("\tmovsd %%xmm0,-%d(%%rbp)\n", stkpos);
436 if (ap->iarg(0) > 8) {
437 if (ap2->iarg(0) == STRREG)
438 printf("\tmovq %%rdx");
439 else if (ap2->iarg(0) == STRFI)
440 printf("\tmovq %%rax");
441 else if (ap2->iarg(0) == STRIF)
442 printf("\tmovsd %%xmm0");
443 else
444 printf("\tmovsd %%xmm1");
445 printf(",-%d(%%rbp)\n", stkpos-8);
446 }
447 printf("\tleaq -%d(%%rbp),%%rax\n", stkpos);
448 }
449 break;
450
451 case 'c': /* xor label */
452 if ((ap = attr_find(p->n_ap, ATTR_AMD64_XORLBL)) == NULL)
453 comperr("missing xor label");
454 printf(LABFMT, ap->iarg(0));
455 break;
456
457 case 'F': /* Structure argument */
458 ap = attr_find(p->n_ap, ATTR_P2STRUCT);
459 printf(" subq $%d,%%rsp\n", ap->iarg(0));
460 printf(" movq %%rsp,%%rsi\n");
461 stasg(p);
462 break;
463
464 case 'G': /* Floating point compare */
465 fcomp(p);
466 break;
467
468 case 'j': /* convert unsigned long to f/d */
469 ultofd(p);
470 break;
471
472 case 'M': /* Output sconv move, if needed */
473 l = getlr(p, 'L');
474 /* XXX fixneed: regnum */
475 pr = DECRA(p->n_reg, 0);
476 lr = DECRA(l->n_reg, 0);
477 if (pr == lr)
478 break;
479 printf(" movb %s,%s\n", rbyte[lr], rbyte[pr]);
480 l->n_rval = l->n_reg = p->n_reg; /* XXX - not pretty */
481 break;
482
483 case 'N': /* output long reg name */
484 printf("%s", rlong[getlr(p, '1')->n_rval]);
485 break;
486
487 case 'P': /* Put hidden argument in rdi */
488 ap = attr_find(p->n_ap, ATTR_P2STRUCT);
489 ap2 = attr_find(p->n_ap, ATTR_AMD64_CMPLRET);
490 if (ap->iarg(0) > 16 && ap2->iarg(0) != STRX87)
491 printf("\tleaq -%d(%%rbp),%%rdi\n", stkpos);
492 break;
493
494 case 'Q': /* emit struct assign */
495 stasg(p);
496 break;
497
498 case 'R': /* print opname based on right type */
499 case 'L': /* print opname based on left type */
500 switch (getlr(p, c)->n_type) {
501 case CHAR: case UCHAR: s = 'b'; break;
502 case SHORT: case USHORT: s = 'w'; break;
503 case INT: case UNSIGNED: s = 'l'; break;
504 default: s = 'q'; break;
505 printf("%c", s);
506 }
507 break;
508
509 case 'U': { /* output branch insn for ucomi */
510 static char *fpcb[] = { "jz", "jnz", "jbe", "jc", "jnc", "ja" };
511 if (p->n_op < EQ || p->n_op > GT)
512 comperr("bad fp branch");
513 if (p->n_op == NE || p->n_op == GT || p->n_op == GE)
514 expand(p, 0, " jp LC\n");
515 else if (p->n_op == EQ)
516 printf("\tjp 1f\n");
517 printf(" %s ", fpcb[p->n_op - EQ]);
518 expand(p, 0, "LC\n");
519 if (p->n_op == EQ)
520 printf("1:\n");
521 break;
522 }
523
524 case '8': /* special reg name printout (64-bit) */
525 case '1': /* special reg name printout (32-bit) */
526 l = getlr(p, '1');
527 rt = c == '8' ? rnames : rlong;
528 printf("%s", rt[l->n_rval]);
529 break;
530
531 case 'g':
532 p = p->n_left;
533 /* FALLTHROUGH */
534 case 'f': /* float or double */
535 printf("%c", p->n_type == FLOAT ? 's' : 'd');
536 break;
537
538 case 'q': /* int or long */
539 printf("%c", p->n_left->n_type == LONG ? 'q' : ' ');
540 break;
541
542 default:
543 comperr("zzzcode %c", c);
544 }
545 }
546
547 int canaddr(NODE *);
548 int
canaddr(NODE * p)549 canaddr(NODE *p)
550 {
551 int o = p->n_op;
552
553 if (o==NAME || o==REG || o==ICON || o==OREG ||
554 (o==UMUL && shumul(p->n_left, SOREG)))
555 return(1);
556 return(0);
557 }
558
559 /*
560 * Does the bitfield shape match?
561 */
562 int
flshape(NODE * p)563 flshape(NODE *p)
564 {
565 comperr("flshape");
566 return(0);
567 }
568
569 /* INTEMP shapes must not contain any temporary registers */
570 /* XXX should this go away now? */
571 int
shtemp(NODE * p)572 shtemp(NODE *p)
573 {
574 return 0;
575 #if 0
576 int r;
577
578 if (p->n_op == STARG )
579 p = p->n_left;
580
581 switch (p->n_op) {
582 case REG:
583 return (!istreg(p->n_rval));
584
585 case OREG:
586 r = p->n_rval;
587 if (R2TEST(r)) {
588 if (istreg(R2UPK1(r)))
589 return(0);
590 r = R2UPK2(r);
591 }
592 return (!istreg(r));
593
594 case UMUL:
595 p = p->n_left;
596 return (p->n_op != UMUL && shtemp(p));
597 }
598
599 if (optype(p->n_op) != LTYPE)
600 return(0);
601 return(1);
602 #endif
603 }
604
605 void
adrcon(CONSZ val)606 adrcon(CONSZ val)
607 {
608 printf("$" CONFMT, val);
609 }
610
611 void
conput(FILE * fp,NODE * p)612 conput(FILE *fp, NODE *p)
613 {
614 long val = getlval(p);
615
616 switch (p->n_op) {
617 case ICON:
618 if (p->n_name[0] != '\0') {
619 fprintf(fp, "%s", p->n_name);
620 if (val)
621 fprintf(fp, "+%ld", val);
622 } else
623 fprintf(fp, "%ld", val);
624 return;
625
626 default:
627 comperr("illegal conput, p %p", p);
628 }
629 }
630
631 /*ARGSUSED*/
632 void
insput(NODE * p)633 insput(NODE *p)
634 {
635 comperr("insput");
636 }
637
638 /*
639 * Write out the upper address, like the upper register of a 2-register
640 * reference, or the next memory location.
641 * XXX - not needed on amd64
642 */
643 void
upput(NODE * p,int size)644 upput(NODE *p, int size)
645 {
646
647 size /= SZCHAR;
648 switch (p->n_op) {
649 case REG:
650 printf("%%%s", &rnames[p->n_rval][3]);
651 break;
652
653 case NAME:
654 case OREG:
655 setlval(p, getlval(p) + size);
656 adrput(stdout, p);
657 setlval(p, getlval(p) - size);
658 break;
659 case ICON:
660 printf("$" CONFMT, getlval(p) >> 32);
661 break;
662 default:
663 comperr("upput bad op %d size %d", p->n_op, size);
664 }
665 }
666
667 void
adrput(FILE * io,NODE * p)668 adrput(FILE *io, NODE *p)
669 {
670 int r;
671 char **rc;
672 /* output an address, with offsets, from p */
673
674 switch (p->n_op) {
675
676 case NAME:
677 if (p->n_name[0] != '\0') {
678 if (getlval(p) != 0)
679 fprintf(io, CONFMT "+", getlval(p));
680 fprintf(io, "%s(%%rip)", p->n_name);
681 } else
682 fprintf(io, CONFMT, getlval(p));
683 return;
684
685 case OREG:
686 r = p->n_rval;
687 if (p->n_name[0])
688 printf("%s%s", p->n_name, getlval(p) ? "+" : "");
689 if (getlval(p))
690 fprintf(io, "%lld", getlval(p));
691 if (R2TEST(r)) {
692 int r1 = R2UPK1(r);
693 int r2 = R2UPK2(r);
694 int sh = R2UPK3(r);
695
696 fprintf(io, "(%s,%s,%d)",
697 r1 == MAXREGS ? "" : rnames[r1],
698 r2 == MAXREGS ? "" : rnames[r2], sh);
699 } else
700 fprintf(io, "(%s)", rnames[p->n_rval]);
701 return;
702 case ICON:
703 /* addressable value of the constant */
704 fputc('$', io);
705 conput(io, p);
706 return;
707
708 case REG:
709 switch (p->n_type) {
710 case CHAR:
711 case UCHAR:
712 rc = rbyte;
713 break;
714 case SHORT:
715 case USHORT:
716 rc = rshort;
717 break;
718 case INT:
719 case UNSIGNED:
720 rc = rlong;
721 break;
722 default:
723 rc = rnames;
724 break;
725 }
726 fprintf(io, "%s", rc[p->n_rval]);
727 return;
728
729 default:
730 comperr("illegal address, op %d, node %p", p->n_op, p);
731 return;
732
733 }
734 }
735
736 static char *
737 ccbranches[] = {
738 "je", /* jumpe */
739 "jne", /* jumpn */
740 "jle", /* jumple */
741 "jl", /* jumpl */
742 "jge", /* jumpge */
743 "jg", /* jumpg */
744 "jbe", /* jumple (jlequ) */
745 "jb", /* jumpl (jlssu) */
746 "jae", /* jumpge (jgequ) */
747 "ja", /* jumpg (jgtru) */
748 };
749
750
751 /* printf conditional and unconditional branches */
752 void
cbgen(int o,int lab)753 cbgen(int o, int lab)
754 {
755 if (o < EQ || o > UGT)
756 comperr("bad conditional branch: %s", opst[o]);
757 printf(" %s " LABFMT "\n", ccbranches[o-EQ], lab);
758 }
759
760 /*
761 * gcc xasm has the ability to generate different asm types
762 * via some magic.
763 *
764 * Only support AT&T asm for now.
765 */
766 static char *
adjustname(char * s)767 adjustname(char *s)
768 {
769 int len = strlen(s);
770 char *d = tmpalloc(len+1);
771 int i, j, flvl, tlvl;
772
773 flvl = tlvl = 0;
774 for (i = j = 0; i < len; i++) {
775 switch (s[i]) {
776 case '{': tlvl++; break;
777 case '}': if (tlvl)tlvl--; else flvl--; break;
778 case '|': tlvl--; flvl++; break;
779 default:
780 if (flvl == 0)
781 d[j++] = s[i];
782 break;
783 }
784 }
785 d[j] = 0;
786 return d;
787 }
788
789 static void
fixcalls(NODE * p,void * arg)790 fixcalls(NODE *p, void *arg)
791 {
792 int ps;
793
794 /* Prepare for struct return by allocating bounce space on stack */
795 switch (p->n_op) {
796 case STCALL:
797 case USTCALL:
798 ps = attr_find(p->n_ap, ATTR_P2STRUCT)->iarg(0);
799 if (ps < 16)
800 ps = 16;
801 if (ps+p2autooff > stkpos)
802 stkpos = ps+p2autooff;
803 break;
804 case XASM:
805 p->n_name = adjustname(p->n_name);
806 break;
807 }
808 }
809
810 void
myreader(struct interpass * ipole)811 myreader(struct interpass *ipole)
812 {
813 struct interpass *ip;
814
815 stkpos = p2autooff;
816 DLIST_FOREACH(ip, ipole, qelem) {
817 if (ip->type != IP_NODE)
818 continue;
819 walkf(ip->ip_node, fixcalls, 0);
820 }
821 if (stkpos > p2autooff)
822 p2autooff = stkpos;
823 if (stkpos > p2maxautooff)
824 p2maxautooff = stkpos;
825 if (x2debug)
826 printip(ipole);
827 }
828
829 /*
830 * Remove some PCONVs after OREGs are created.
831 */
832 static void
pconv2(NODE * p,void * arg)833 pconv2(NODE *p, void *arg)
834 {
835 NODE *q;
836
837 if (p->n_op == PLUS) {
838 if (p->n_type == (PTR|SHORT) || p->n_type == (PTR|USHORT)) {
839 if (p->n_right->n_op != ICON)
840 return;
841 if (p->n_left->n_op != PCONV)
842 return;
843 if (p->n_left->n_left->n_op != OREG)
844 return;
845 q = p->n_left->n_left;
846 nfree(p->n_left);
847 p->n_left = q;
848 /*
849 * This will be converted to another OREG later.
850 */
851 }
852 }
853 }
854
855 void
mycanon(NODE * p)856 mycanon(NODE *p)
857 {
858 walkf(p, pconv2, 0);
859 }
860
861 void
myoptim(struct interpass * ip)862 myoptim(struct interpass *ip)
863 {
864 }
865
866 void
rmove(int s,int d,TWORD t)867 rmove(int s, int d, TWORD t)
868 {
869
870 switch (t) {
871 case INT:
872 case UNSIGNED:
873 printf(" movl %s,%s\n", rlong[s], rlong[d]);
874 break;
875 case CHAR:
876 case UCHAR:
877 printf(" movb %s,%s\n", rbyte[s], rbyte[d]);
878 break;
879 case SHORT:
880 case USHORT:
881 printf(" movw %s,%s\n", rshort[s], rshort[d]);
882 break;
883 case FLOAT:
884 printf(" movss %s,%s\n", rnames[s], rnames[d]);
885 break;
886 case DOUBLE:
887 printf(" movsd %s,%s\n", rnames[s], rnames[d]);
888 break;
889 case LDOUBLE:
890 #ifdef notdef
891 /* a=b()*c(); will generate this */
892 /* XXX can it fail anyway? */
893 comperr("bad float rmove: %d %d", s, d);
894 #endif
895 break;
896 default:
897 printf(" movq %s,%s\n", rnames[s], rnames[d]);
898 break;
899 }
900 }
901
902 /*
903 * For class c, find worst-case displacement of the number of
904 * registers in the array r[] indexed by class.
905 */
906 int
COLORMAP(int c,int * r)907 COLORMAP(int c, int *r)
908 {
909
910 switch (c) {
911 case CLASSA:
912 return r[CLASSA] < 14;
913 case CLASSB:
914 return r[CLASSB] < 16;
915 case CLASSC:
916 return r[CLASSC] < CREGCNT;
917 }
918 return 0; /* XXX gcc */
919 }
920
921 char *rnames[] = {
922 "%rax", "%rdx", "%rcx", "%rbx", "%rsi", "%rdi", "%rbp", "%rsp",
923 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
924 "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7",
925 "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14",
926 "%xmm15",
927 };
928
929 /* register names for shorter sizes */
930 char *rbyte[] = {
931 "%al", "%dl", "%cl", "%bl", "%sil", "%dil", "%bpl", "%spl",
932 "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b",
933 };
934 char *rshort[] = {
935 "%ax", "%dx", "%cx", "%bx", "%si", "%di", "%bp", "%sp",
936 "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w",
937 };
938 char *rlong[] = {
939 "%eax", "%edx", "%ecx", "%ebx", "%esi", "%edi", "%ebp", "%esp",
940 "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d",
941 };
942
943
944 /*
945 * Return a class suitable for a specific type.
946 */
947 int
gclass(TWORD t)948 gclass(TWORD t)
949 {
950 if (t == LDOUBLE)
951 return CLASSC;
952 if (t == FLOAT || t == DOUBLE)
953 return CLASSB;
954 return CLASSA;
955 }
956
957 static int
argsiz(NODE * p)958 argsiz(NODE *p)
959 {
960 TWORD t = p->n_type;
961
962 if (p->n_left->n_op == REG)
963 return 0; /* not on stack */
964 if (t == LDOUBLE)
965 return 16;
966 if (p->n_op == STASG)
967 return attr_find(p->n_ap, ATTR_P2STRUCT)->iarg(0);
968 return 8;
969 }
970
971 /*
972 * Calculate argument sizes.
973 */
974 void
lastcall(NODE * p)975 lastcall(NODE *p)
976 {
977 NODE *op = p;
978 int size = 0;
979
980 p->n_qual = 0;
981 if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL)
982 return;
983 for (p = p->n_right; p->n_op == CM; p = p->n_left)
984 size += argsiz(p->n_right);
985 size += argsiz(p);
986 size = (size+15) & ~15;
987 if (size)
988 printf(" subq $%d,%s\n", size, rnames[RSP]);
989 op->n_qual = size; /* XXX */
990 }
991
992 /*
993 * Special shapes.
994 */
995 int
special(NODE * p,int shape)996 special(NODE *p, int shape)
997 {
998 int o = p->n_op;
999
1000 switch (shape) {
1001 case SFUNCALL:
1002 if (o == STCALL || o == USTCALL)
1003 return SRREG;
1004 break;
1005 case SPCON:
1006 if (o != ICON || p->n_name[0] ||
1007 getlval(p) < 0 || getlval(p) > 0x7fffffff)
1008 break;
1009 return SRDIR;
1010 case SMIXOR:
1011 return tshape(p, SZERO);
1012 case SMILWXOR:
1013 if (o != ICON || p->n_name[0] ||
1014 getlval(p) == 0 || getlval(p) & 0xffffffff)
1015 break;
1016 return SRDIR;
1017 case SMIHWXOR:
1018 if (o != ICON || p->n_name[0] ||
1019 getlval(p) == 0 || (getlval(p) >> 32) != 0)
1020 break;
1021 return SRDIR;
1022 case SCON32:
1023 if (o != ICON || p->n_name[0])
1024 break;
1025 if (getlval(p) < MIN_INT || getlval(p) > MAX_INT)
1026 break;
1027 return SRDIR;
1028 default:
1029 cerror("special: %x\n", shape);
1030 }
1031 return SRNOPE;
1032 }
1033
1034 /*
1035 * Target-dependent command-line options.
1036 */
1037 void
mflags(char * str)1038 mflags(char *str)
1039 {
1040 }
1041
1042 /*
1043 * Do something target-dependent for xasm arguments.
1044 */
1045 int
myxasm(struct interpass * ip,NODE * p)1046 myxasm(struct interpass *ip, NODE *p)
1047 {
1048 struct interpass *ip2;
1049 int Cmax[] = { 31, 63, 127, 0xffff, 3, 255 };
1050 NODE *in = 0, *ut = 0;
1051 TWORD t;
1052 char *w;
1053 int reg;
1054 int c, cw, v;
1055
1056 cw = xasmcode(p->n_name);
1057 if (cw & (XASMASG|XASMINOUT))
1058 ut = p->n_left;
1059 if ((cw & XASMASG) == 0)
1060 in = p->n_left;
1061
1062 c = XASMVAL(cw);
1063 retry: switch (c) {
1064 case 'D': reg = RDI; break;
1065 case 'S': reg = RSI; break;
1066 case 'A':
1067 case 'a': reg = RAX; break;
1068 case 'b': reg = RBX; break;
1069 case 'c': reg = RCX; break;
1070 case 'd': reg = RDX; break;
1071
1072 case 'Q': reg = RDX; break; /* Always dx for now */
1073
1074 case 'x':
1075 case 'q':
1076 case 't':
1077 case 'u':
1078 p->n_name = tmpstrdup(p->n_name);
1079 w = strchr(p->n_name, c);
1080 *w = 'r'; /* now reg */
1081 return c == 'q' || c == 'x' || c == 't' ? 0 : 1;
1082
1083 case 'I':
1084 case 'J':
1085 case 'K':
1086 case 'L':
1087 case 'M':
1088 case 'N':
1089 if (p->n_left->n_op != ICON) {
1090 if ((c = XASMVAL1(cw))) {
1091 if (c == 'r') {
1092 p->n_name++;
1093 return 0;
1094 }
1095 goto retry;
1096 }
1097 uerror("xasm arg not constant");
1098 }
1099 v = getlval(p->n_left);
1100 if ((c == 'K' && v < -128) ||
1101 (c == 'L' && v != 0xff && v != 0xffff) ||
1102 (c != 'K' && v < 0) ||
1103 (v > Cmax[c-'I']))
1104 uerror("xasm val out of range");
1105 p->n_name = "i";
1106 return 1;
1107
1108 default:
1109 return 0;
1110 }
1111 /* If there are requested either memory or register, delete memory */
1112 w = p->n_name = tmpstrdup(p->n_name);
1113 if (*w == '=')
1114 w++;
1115 *w++ = 'r';
1116 *w = 0;
1117
1118 t = p->n_left->n_type;
1119
1120 if (t == FLOAT || t == DOUBLE) {
1121 reg += 16;
1122 } else if (t == LDOUBLE) {
1123 reg += 32;
1124 }
1125
1126 if (in && ut)
1127 in = tcopy(in);
1128 p->n_left = mklnode(REG, 0, reg, t);
1129 if (ut) {
1130 ip2 = ipnode(mkbinode(ASSIGN, ut, tcopy(p->n_left), t));
1131 DLIST_INSERT_AFTER(ip, ip2, qelem);
1132 }
1133 if (in) {
1134 ip2 = ipnode(mkbinode(ASSIGN, tcopy(p->n_left), in, t));
1135 DLIST_INSERT_BEFORE(ip, ip2, qelem);
1136 }
1137
1138 return 1;
1139 }
1140
1141 void
targarg(char * w,void * arg,int n)1142 targarg(char *w, void *arg, int n)
1143 {
1144 NODE **ary = arg;
1145 NODE *p, *q;
1146
1147 if (w[1] < '0' || w[1] > (n + '0'))
1148 uerror("bad xasm arg number %c", w[1]);
1149 if (w[1] == (n + '0'))
1150 p = ary[(int)w[1]-'0' - 1]; /* XXX */
1151 else
1152 p = ary[(int)w[1]-'0'];
1153 p = p->n_left;
1154
1155 if (optype(p->n_op) != LTYPE)
1156 comperr("bad xarg op %d", p->n_op);
1157 q = tcopy(p);
1158 if (q->n_op == REG) {
1159 if (*w == 'k') {
1160 q->n_type = INT;
1161 } else if (*w == 'q') {
1162 q->n_type = LONG;
1163 } else if (*w == 'h' || *w == 'b') {
1164 /* Can do this only because we know dx is used */
1165 printf("%%d%c", *w == 'h' ? 'h' : 'l');
1166 tfree(q);
1167 return;
1168 } else if (*w != 'w') {
1169 cerror("targarg"); /* XXX ??? */
1170 if (q->n_type > UCHAR) {
1171 regno(q) = regno(q)*2+8;
1172 if (*w == 'h')
1173 regno(q)++;
1174 }
1175 q->n_type = INT;
1176 } else
1177 q->n_type = SHORT;
1178 }
1179 adrput(stdout, q);
1180 tfree(q);
1181 }
1182
1183 /*
1184 * target-specific conversion of numeric arguments.
1185 */
1186 int
numconv(void * ip,void * p1,void * q1)1187 numconv(void *ip, void *p1, void *q1)
1188 {
1189 NODE *p = p1, *q = q1;
1190 int cw = xasmcode(q->n_name);
1191
1192 switch (XASMVAL(cw)) {
1193 case 'a':
1194 case 'b':
1195 case 'c':
1196 case 'd':
1197 p->n_name = tmpcalloc(2);
1198 p->n_name[0] = XASMVAL(cw);
1199 return 1;
1200 default:
1201 return 0;
1202 }
1203 }
1204
1205 static struct {
1206 char *name; int num;
1207 } xcr[] = {
1208 { "rax", RAX },
1209 { "rbx", RBX },
1210 { "rcx", RCX },
1211 { "rdx", RDX },
1212 { "rsi", RSI },
1213 { "rdi", RDI },
1214 { "r8", R08 },
1215 { "r9", R09 },
1216 { "r10", R10 },
1217 { "r11", R11 },
1218 { "r12", R12 },
1219 { "r13", R13 },
1220 { "r14", R14 },
1221 { "r15", R15 },
1222 { "st", 040 },
1223 { "st(0)", 040 },
1224 { "st(1)", 041 },
1225 { "st(2)", 042 },
1226 { "st(3)", 043 },
1227 { "st(4)", 044 },
1228 { "st(5)", 045 },
1229 { "st(6)", 046 },
1230 { "st(7)", 047 },
1231 { NULL, 0 },
1232 };
1233
1234 /*
1235 * Check for other names of the xasm constraints registers.
1236 */
xasmconstregs(char * s)1237 int xasmconstregs(char *s)
1238 {
1239 int i;
1240
1241 for (i = 0; xcr[i].name; i++)
1242 if (strcmp(xcr[i].name, s) == 0)
1243 return xcr[i].num;
1244 return -1;
1245 }
1246
1247