source: mainline/uspace/app/pcc/arch/amd64/local2.c@ a7de7182

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a7de7182 was a7de7182, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 14 years ago

Added pcc source tree (contents of pcc-1.0.0.tgz)

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