Quick Search:

Mode

Context

Displaying the whole file. None | Less | More | Full

Other Diffs

Ignore

Blank Lines Whitespace: Expand:

Diff

1.51
 
1.52
 
MAIN:ragge:20121228160249
 
local2.c
_>11 /*      $Id$    */
 22 /*
 33  * Copyright (c) 2008 Michael Shalayeff
 44  * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
 55  * All rights reserved.
 66  *
 77  * Redistribution and use in source and binary forms, with or without
 88  * modification, are permitted provided that the following conditions
 99  * are met:
 1010  * 1. Redistributions of source code must retain the above copyright
 1111  *    notice, this list of conditions and the following disclaimer.
 1212  * 2. Redistributions in binary form must reproduce the above copyright
 1313  *    notice, this list of conditions and the following disclaimer in the
 1414  *    documentation and/or other materials provided with the distribution.
 1515  * 3. The name of the author may not be used to endorse or promote products
 1616  *    derived from this software without specific prior written permission
 1717  *
 1818  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 1919  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 2020  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 2121  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 2222  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 2323  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 2424  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 2525  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 2626  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 2727  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 2828  */
 2929 
 3030 # include "pass2.h"
 3131 # include <ctype.h>
 3232 # include <string.h>
 3333 
 3434 static int stkpos;
 3535 
 3636 void
 3737 deflab(int label)
 3838 {
 3939         printf(LABFMT ":\n", label);
 4040 }
 4141 
 4242 static int regoff[MAXREGS];
 4343 static TWORD ftype;
 4444 char *rbyte[], *rshort[], *rlong[];
 4545 static int needframe;
 4646 
 4747 /*
 4848  * Print out the prolog assembler.
 4949  * addto and regoff are already calculated.
 5050  */
 5151 static void
 5252 prtprolog(struct interpass_prolog *ipp, int addto)
 5353 {
 5454         int i;
 5555 
 5656         printf("\tpushq %%rbp\n");
 5757         printf("\tmovq %%rsp,%%rbp\n");
 5858         addto = (addto+15) & ~15; /* 16-byte aligned */
 5959         if (addto)
 6060                 printf("\tsubq $%d,%%rsp\n", addto);
 6161 
 6262         /* save permanent registers */
 6363         for (i = 0; i < MAXREGS; i++)
 6464                 if (TESTBIT(ipp->ipp_regs, i))
 6565                         printf("\tmovq %s,-%d(%s)\n",
 6666                             rnames[i], regoff[i], rnames[FPREG]);
 6767 }
 6868 
 6969 /*
 7070  * calculate stack size and offsets
 7171  */
 7272 static int
 7373 offcalc(struct interpass_prolog *ipp)
 7474 {
 7575         int i, addto;
 7676 
 7777         addto = p2maxautooff;
 7878         if (addto >= AUTOINIT/SZCHAR)
 7979                 addto -= AUTOINIT/SZCHAR;
 8080         for (i = 0; i < MAXREGS; i++)
 8181                 if (TESTBIT(ipp->ipp_regs, i)) {
 8282                         addto += SZLONG/SZCHAR;
 8383                         regoff[i] = addto;
 8484                 }
 8585         return addto;
 8686 }
 8787 
 8888 /*
 8989  * Traverse a tree to check if we need to emit a frame at all.
 9090  * We emit it if:
 9191  * - any function call
 9292  * - rsp or rbp referenced
 9393  * Return 1 if frame is needed, 0 otherwise.
 9494  */
 9595 static int
 9696 chkf(NODE *p)
 9797 {
 9898         int o = p->n_op;
 9999 
 100100         if ((o == REG || o == OREG) && (regno(p) == RBP || regno(p) == RSP))
 101101                 return 1;
 102102         if (callop(o))
 103103                 return 1;
 104104         if (optype(o) == UTYPE)
 105105                 return chkf(p->n_left);
 106106         else if (optype(o) == BITYPE)
 107107                 return chkf(p->n_left) || chkf(p->n_right);
 108108         return 0;
 109109 }
 110110 
 111111 static int
 112112 chkframe(struct interpass_prolog *ipp)
 113113 {
 114114         struct interpass *ip;
 115115 
 116116         DLIST_FOREACH(ip, &ipp->ipp_ip, qelem) {
 117117                 if (ip->type == IP_EPILOG)
 118118                         break;
 119119                 if (ip->type == IP_NODE) {
 120120                         if (chkf(ip->ip_node))
 121121                                 return 1;
 122122                 }
 123123         }
 124124         return 0;
 125125 }
 126126 
 127127 void
 128128 prologue(struct interpass_prolog *ipp)
 129129 {
 130130         int addto;
 131131 
 132132         ftype = ipp->ipp_type;
 133133 
 134134         if (xdeljumps)
 135135                 needframe = chkframe(ipp);
 136136         else
 137137                 needframe = 1;
 138138 
 139139 #ifdef LANG_F77
 140140         if (ipp->ipp_vis)
 141141                 printf("        .globl %s\n", ipp->ipp_name);
 142142         printf("        .align 16\n");
 143143         printf("%s:\n", ipp->ipp_name);
 144144 #endif
 145145         /*
 146146          * We here know what register to save and how much to
 147147          * add to the stack.
 148148          */
 149149         addto = offcalc(ipp);
 150150         if (addto)
 151151                 needframe = 1;
 152152         if (needframe)
 153153                 prtprolog(ipp, addto);
 154154 }
 155155 
 156156 void
 157157 eoftn(struct interpass_prolog *ipp)
 158158 {
 159159         int i;
 160160 
 161161         if (ipp->ipp_ip.ip_lbl == 0)
 162162                 return; /* no code needs to be generated */
 163163 
 164164         if (needframe) {
 165165                 /* return from function code */
 166166                 for (i = 0; i < MAXREGS; i++)
 167167                         if (TESTBIT(ipp->ipp_regs, i))
 168168                                 printf("        movq -%d(%s),%s\n",
 169169                                     regoff[i], rnames[FPREG], rnames[i]);
 170170 
 171171                 /* struct return needs special treatment */
 172172                 if (ftype == STRTY || ftype == UNIONTY) {
 173173                         printf("        movl 8(%%ebp),%%eax\n");
 174174                         printf("        leave\n");
 175175                         printf("        ret $%d\n", 4);
 176176                 } else {
 177177                         printf("        leave\n");
 178178                         printf("        ret\n");
 179179                 }
 180180         } else
 181181                 printf("\tret\n");
 182182 
 183183 #ifndef MACHOABI
 184184         printf("\t.size %s,.-%s\n", ipp->ipp_name, ipp->ipp_name);
 185185 #endif
 186186 }
 187187 
 188188 /*
 189189  * add/sub/...
 190190  *
 191191  * Param given:
 192192  */
 193193 void
 194194 hopcode(int f, int o)
 195195 {
 196196         char *str;
 197197 
 198198         switch (o) {
 199199         case PLUS:
 200200                 str = "add";
 201201                 break;
 202202         case MINUS:
 203203                 str = "sub";
 204204                 break;
 205205         case AND:
 206206                 str = "and";
 207207                 break;
 208208         case OR:
 209209                 str = "or";
 210210                 break;
 211211         case ER:
 212212                 str = "xor";
 213213                 break;
 214214         default:
 215215                 comperr("hopcode2: %d", o);
 216216                 str = 0; /* XXX gcc */
 217217         }
 218218         printf("%s%c", str, f);
 219219 }
 220220 
 221221 /*
 222222  * Return type size in bytes.  Used by R2REGS, arg 2 to offset().
 223223  */
 224224 int
 225225 tlen(NODE *p)
 226226 {
 227227         switch(p->n_type) {
 228228                 case CHAR:
 229229                 case UCHAR:
 230230                         return(1);
 231231 
 232232                 case SHORT:
 233233                 case USHORT:
 234234                         return(SZSHORT/SZCHAR);
 235235 
 236236                 case DOUBLE:
 237237                         return(SZDOUBLE/SZCHAR);
 238238 
 239239                 case INT:
 240240                 case UNSIGNED:
 241241                         return(SZINT/SZCHAR);
 242242 
 243243                 case LONG:
 244244                 case ULONG:
 245245                 case LONGLONG:
 246246                 case ULONGLONG:
 247247                         return SZLONGLONG/SZCHAR;
 248248 
 249249                 default:
 250250                         if (!ISPTR(p->n_type))
 251251                                 comperr("tlen type %d not pointer");
 252252                         return SZPOINT(p->n_type)/SZCHAR;
 253253                 }
 254254 }
 255255 
 256256 /*
 257257  * Compare two floating point numbers.
 258258  */
 259259 static void
 260260 fcomp(NODE *p)  
 261261 {
 262262 
 263263         if (p->n_left->n_op != REG)
 264264                 comperr("bad compare %p\n", p);
 265265         if ((p->n_su & DORIGHT) == 0)
 266266                 expand(p, 0, "\tfxch\n");
 267267         expand(p, 0, "\tfucomip %st(1),%st\n"); /* emit compare insn  */
 268268         expand(p, 0, "\tfstp %st(0)\n");        /* pop fromstack */
 269269         zzzcode(p, 'U');
 270270 }
 271271 
 272272 int
 273273 fldexpand(NODE *p, int cookie, char **cp)
 274274 {
 275275         comperr("fldexpand");
 276276         return 0;
 277277 }
 278278 
 279279 static void
 280280 stasg(NODE *p)
 281281 {
 282282         expand(p, INAREG, "     leaq AL,%rdi\n");
 283283         if (p->n_stsize >= 8)
 284284                 printf("\tmovl $%d,%%ecx\n\trep movsq\n", p->n_stsize >> 3);
 285285         if (p->n_stsize & 4)
 286286                 printf("\tmovsl\n");
 287287         if (p->n_stsize & 2)
 288288                 printf("\tmovsw\n");
 289289         if (p->n_stsize & 1)
 290290                 printf("\tmovsb\n");
 291291 }
 292292 
 293293 #define E(x)    expand(p, 0, x)
 294294 /*
 295295  * Generate code to convert an unsigned long to xmm float/double.
 296296  */
 297297 static void
 298298 ultofd(NODE *p)
 299299 {
 300300 
 301301         E("     movq AL,A1\n");
 302302         E("     testq A1,A1\n");
 303303         E("     js 2f\n");
 304304         E("     cvtsi2sZfq A1,A3\n");
 305305         E("     jmp 3f\n");
 306306         E("2:\n");
 307307         E("     movq A1,A2\n");
 308308         E("     shrq A2\n");
 309309         E("     andq $1,A1\n");
 310310         E("     orq A1,A2\n");
 311311         E("     cvtsi2sZfq A2,A3\n");
 312312         E("     addsZf A3,A3\n");
 313313         E("3:\n");
 314314 }
 315315 
 316316 /*
 317317  * Generate code to convert an x87 long double to an unsigned long.
 318318  * This is ugly :-/
 319319  */
 320320 static void
 321321 ldtoul(NODE *p)
 322322 {
 323323         int r;
 324324 
 325325         r = getlr(p, '1')->n_rval;
 326326 
 327327         E("     subq $16,%rsp\n");
 328328         E("     movl $0x5f000000,(%rsp)\n"); /* More than long can have */
 329329         E("     flds (%rsp)\n");
 330330         if (p->n_left->n_op == REG) {
 331331                 E("     fxch\n");
 332332         } else
 333333                 E("     fldt AL\n");
 334334         E("     fucomi %st(1), %st\n");
 335335         E("     jae 2f\n");
 336336 
 337337         E("     fstp %st(1)\n");         /* Pop huge val from stack */
 338338         E("     fnstcw (%rsp)\n");       /* store cw */
 339339         E("     movw $0x0f3f,4(%rsp)\n");/* round towards 0 */
 340340         E("     fldcw 4(%rsp)\n");       /* new cw */
 341341         E("     fistpll 8(%rsp)\n");     /* save val */
 342342         E("     fldcw (%rsp)\n");        /* fetch old cw */
 343343         E("     movq 8(%rsp),A1\n");
 344344 
 345345         E("     jmp 3f\n");
 346346 
 347347         E("2:\n");
 348348 
 349349         E("     fsubp %st, %st(1)\n");
 350350         E("     fnstcw (%rsp)\n");      
 351351         E("     movw $0x0f3f,4(%rsp)\n");
 352352         E("     fldcw 4(%rsp)\n");
 353353         E("     fistpll 8(%rsp)\n");
 354354         E("     fldcw (%rsp)\n");
 355355         E("     movabsq $0x8000000000000000,A1\n");
 356356         E("     xorq 8(%rsp),A1\n");
 357357 
 358358         E("3:   addq $16,%rsp\n");
 359359 }
 360360 
 361361 /*
 362362  * Generate code to convert an SSE float/double to an unsigned long.
 363363  */    
 364364 static void    
 365365 fdtoul(NODE *p)
 366366 {
 367367         if (p->n_left->n_type == FLOAT)
 368368                 E("     movabsq $0x5f000000,A1\n");
 369369         else
 370370                 E("     movabsq $0x43e0000000000000,A1\n");
 371371         E("     movd A1,A3\n");
 372372         E("     ucomisZg A3,AL\n");
 373373         E("     jae 2f\n");
 374374         E("     cvttsZg2siq AL,A1\n");
 375375         E("     jmp 3f\n");
 376376         E("2:\n");
 377377         E("     subsZg A3,AL\n");
 378378         E("     cvttsZg2siq AL,A1\n");
 379379         E("     movabsq $0x8000000000000000,A2\n");
 380380         E("     xorq A2,A1\n");
 381381         E("3:\n");
 382382 }
 383383 #undef E
 384384 
 385385 void
 386386 zzzcode(NODE *p, int c)
 387387 {
 388388         NODE *l;
 389389         int pr, lr, s;
 390390         char **rt;
 391391 
 392392         switch (c) {
 393393         case 'A': /* swap st0 and st1 if right is evaluated second */
 394394                 if ((p->n_su & DORIGHT) == 0) {
 395395                         if (logop(p->n_op))
 396396                                 printf("        fxch\n");
 397397                         else
 398398                                 printf("r");
 399399                 }
 400400                 break;
 401401 
 402402         case 'B': /* ldouble to unsigned long cast */
 403403                 ldtoul(p);
 404404                 break;
 405405 
 406406         case 'b': /* float/double to unsigned long cast */
 407407                 fdtoul(p);
 408408                 break;
 409409 
 410410         case 'C'/* remove from stack after subroutine call */
 411411                 pr = p->n_qual;
 412412                 if (p->n_op == UCALL)
 413413                         return; /* XXX remove ZC from UCALL */
 414414                 if (pr)
 415415                         printf("        addq $%d, %s\n", pr, rnames[RSP]);
 416416                 if ((p->n_op == STCALL || p->n_op == USTCALL) &&
 417417                     p->n_stsize <= 16) {
 418418                         /* store reg-passed structs on stack */
 419419                         printf("\tmovq %%rax,-%d(%%rbp)\n", stkpos);
 420420                         printf("\tmovq %%rdx,-%d(%%rbp)\n", stkpos-8);
 421421                         printf("\tleaq -%d(%%rbp),%%rax\n", stkpos);
 422422                 }
 423423                 break;
 424424 
 425425         case 'F': /* Structure argument */
 426426                 printf("        subq $%d,%%rsp\n", p->n_stsize);
 427427                 printf("        movq %%rsp,%%rsi\n");
 428428                 stasg(p);
 429429                 break;
 430430 
 431431         case 'G': /* Floating point compare */
 432432                 fcomp(p);
 433433                 break;
 434434 
 435435         case 'j': /* convert unsigned long to f/d */
 436436                 ultofd(p);
 437437                 break;
 438438 
 439439         case 'M': /* Output sconv move, if needed */
 440440                 l = getlr(p, 'L');
 441441                 /* XXX fixneed: regnum */
 442442                 pr = DECRA(p->n_reg, 0);
 443443                 lr = DECRA(l->n_reg, 0);
 444444                 if (pr == lr)
 445445                         break;
 446446                 printf("        movb %s,%s\n", rbyte[lr], rbyte[pr]);
 447447                 l->n_rval = l->n_reg = p->n_reg; /* XXX - not pretty */
 448448                 break;
 449449 
 450450         case 'N': /* output long reg name */
 451451                 printf("%s", rlong[getlr(p, '1')->n_rval]);
 452452                 break;
 453453 
 454454         case 'P': /* Put hidden argument in rdi */
 455455                 if (p->n_stsize > 16)
 456456                         printf("\tleaq -%d(%%rbp),%%rdi\n", stkpos);
 457457                 break;
 458458 
 459459         case 'Q': /* emit struct assign */
 460460                 stasg(p);
 461461                 break;
 462462 
 463463         case 'R': /* print opname based on right type */
 464464         case 'L': /* print opname based on left type */
 465465                 switch (getlr(p, c)->n_type) {
 466466                 case CHAR: case UCHAR: s = 'b'; break;
 467467                 case SHORT: case USHORT: s = 'w'; break;
 468468                 case INT: case UNSIGNED: s = 'l'; break;
 469469                 default: s = 'q'; break;
 470470                 printf("%c", s);
 471471                 }
 472472                 break;
 473473 
 474474         case 'U': { /* output branch insn for ucomi */
 475475                 static char *fpcb[] = { "jz", "jnz", "jbe", "jc", "jnc", "ja" };
 476476                 if (p->n_op < EQ || p->n_op > GT)
 477477                         comperr("bad fp branch");
 478478                 if (p->n_op == NE || p->n_op == GT || p->n_op == GE)
 479479                         expand(p, 0, "  jp LC\n");
 480480                 else if (p->n_op == EQ)
 481481                         printf("\tjp 1f\n");
 482482                 printf("        %s ", fpcb[p->n_op - EQ]);
 483483                 expand(p, 0, "LC\n");
 484484                 if (p->n_op == EQ)
 485485                         printf("1:\n");
 486486                 break;
 487487                 }
 488488 
 489489         case '8': /* special reg name printout (64-bit) */
 490490         case '1': /* special reg name printout (32-bit) */
 491491                 l = getlr(p, '1');
 492492                 rt = c == '8' ? rnames : rlong;
 493493                 printf("%s", rt[l->n_rval]);
 494494                 break;
 495495 
 496496         case 'g':
 497497                 p = p->n_left;
 498498                 /* FALLTHROUGH */
 499499         case 'f': /* float or double */
 500500                 printf("%c", p->n_type == FLOAT ? 's' : 'd');
 501501                 break;
 502502 
 503503         case 'q': /* int or long */
 504504                 printf("%c", p->n_left->n_type == LONG ? 'q' : ' ');
 505505                 break;
 506506 
 507507         default:
 508508                 comperr("zzzcode %c", c);
 509509         }
 510510 }
 511511 
 512512 int canaddr(NODE *);
 513513 int
 514514 canaddr(NODE *p)
 515515 {
 516516         int o = p->n_op;
 517517 
 518518         if (o==NAME || o==REG || o==ICON || o==OREG ||
 519519             (o==UMUL && shumul(p->n_left, SOREG)))
 520520                 return(1);
 521521         return(0);
 522522 }
 523523 
 524524 /*
 525525  * Does the bitfield shape match?
 526526  */
 527527 int
 528528 flshape(NODE *p)
 529529 {
 530530         comperr("flshape");
 531531         return(0);
 532532 }
 533533 
 534534 /* INTEMP shapes must not contain any temporary registers */
 535535 /* XXX should this go away now? */
 536536 int
 537537 shtemp(NODE *p)
 538538 {
 539539         return 0;
 540540 #if 0
 541541         int r;
 542542 
 543543         if (p->n_op == STARG )
 544544                 p = p->n_left;
 545545 
 546546         switch (p->n_op) {
 547547         case REG:
 548548                 return (!istreg(p->n_rval));
 549549 
 550550         case OREG:
 551551                 r = p->n_rval;
 552552                 if (R2TEST(r)) {
 553553                         if (istreg(R2UPK1(r)))
 554554                                 return(0);
 555555                         r = R2UPK2(r);
 556556                 }
 557557                 return (!istreg(r));
 558558 
 559559         case UMUL:
 560560                 p = p->n_left;
 561561                 return (p->n_op != UMUL && shtemp(p));
 562562         }
 563563 
 564564         if (optype(p->n_op) != LTYPE)
 565565                 return(0);
 566566         return(1);
 567567 #endif
 568568 }
 569569 
 570570 void
 571571 adrcon(CONSZ val)
 572572 {
 573573         printf("$" CONFMT, val);
 574574 }
 575575 
 576576 void
 577577 conput(FILE *fp, NODE *p)
 578578 {
 579579         long val = p->n_lval;
 580580 
 581581         switch (p->n_op) {
 582582         case ICON:
 583583                 if (p->n_name[0] != '\0') {
 584584                         fprintf(fp, "%s", p->n_name);
 585585                         if (val)
 586586                                 fprintf(fp, "+%ld", val);
 587587                 } else
 588588                         fprintf(fp, "%ld", val);
 589589                 return;
 590590 
 591591         default:
 592592                 comperr("illegal conput, p %p", p);
 593593         }
 594594 }
 595595 
 596596 /*ARGSUSED*/
 597597 void
 598598 insput(NODE *p)
 599599 {
 600600         comperr("insput");
 601601 }
 602602 
 603603 /*
 604604  * Write out the upper address, like the upper register of a 2-register
 605605  * reference, or the next memory location.
 606606  * XXX - not needed on amd64
 607607  */
 608608 void
 609609 upput(NODE *p, int size)
 610610 {
 611611 
 612612         size /= SZCHAR;
 613613         switch (p->n_op) {
 614614         case REG:
 615615                 printf("%%%s", &rnames[p->n_rval][3]);
 616616                 break;
 617617 
 618618         case NAME:
 619619         case OREG:
 620620                 p->n_lval += size;
 621621                 adrput(stdout, p);
 622622                 p->n_lval -= size;
 623623                 break;
 624624         case ICON:
 625625                 printf("$" CONFMT, p->n_lval >> 32);
 626626                 break;
 627627         default:
 628628                 comperr("upput bad op %d size %d", p->n_op, size);
 629629         }
 630630 }
 631631 
 632632 void
 633633 adrput(FILE *io, NODE *p)
 634634 {
 635635         int r;
 636636         char **rc;
 637637         /* output an address, with offsets, from p */
 638638 
 639639         switch (p->n_op) {
 640640 
 641641         case NAME:
 642642                 if (p->n_name[0] != '\0') {
 643643                         if (p->n_lval != 0)
 644644                                 fprintf(io, CONFMT "+", p->n_lval);
 645645                         fprintf(io, "%s(%%rip)", p->n_name);
 646646                 } else
 647647                         fprintf(io, CONFMT, p->n_lval);
 648648                 return;
 649649 
 650650         case OREG:
 651651                 r = p->n_rval;
 652652                 if (p->n_name[0])
 653653                         printf("%s%s", p->n_name, p->n_lval ? "+" : "");
 654654                 if (p->n_lval)
 655655                         fprintf(io, "%lld", p->n_lval);
 656656                 if (R2TEST(r)) {
 657657                         int r1 = R2UPK1(r);
 658658                         int r2 = R2UPK2(r);
 659659                         int sh = R2UPK3(r);
 660660 
 661661                         fprintf(io, "(%s,%s,%d)",
 662662                             r1 == MAXREGS ? "" : rnames[r1],
 663663                             r2 == MAXREGS ? "" : rnames[r2], sh);
 664664                 } else
 665665                         fprintf(io, "(%s)", rnames[p->n_rval]);
 666666                 return;
 667667         case ICON:
 668668                 /* addressable value of the constant */
 669669                 fputc('$', io);
 670670                 conput(io, p);
 671671                 return;
 672672 
 673673         case REG:
 674674                 switch (p->n_type) {
 675675                 case CHAR:
 676676                 case UCHAR:
 677677                         rc = rbyte;
 678678                         break;
 679679                 case SHORT:
 680680                 case USHORT:
 681681                         rc = rshort;
 682682                         break;
 683683                 case INT:
 684684                 case UNSIGNED:
 685685                         rc = rlong;
 686686                         break;
 687687                 default:
 688688                         rc = rnames;
 689689                         break;
 690690                 }
 691691                 fprintf(io, "%s", rc[p->n_rval]);
 692692                 return;
 693693 
 694694         default:
 695695                 comperr("illegal address, op %d, node %p", p->n_op, p);
 696696                 return;
 697697 
 698698         }
 699699 }
 700700 
 701701 static char *
 702702 ccbranches[] = {
 703703         "je",           /* jumpe */
 704704         "jne",          /* jumpn */
 705705         "jle",          /* jumple */
 706706         "jl",           /* jumpl */
 707707         "jge",          /* jumpge */
 708708         "jg",           /* jumpg */
 709709         "jbe",          /* jumple (jlequ) */
 710710         "jb",           /* jumpl (jlssu) */
 711711         "jae",          /* jumpge (jgequ) */
 712712         "ja",           /* jumpg (jgtru) */
 713713 };
 714714 
 715715 
 716716 /*   printf conditional and unconditional branches */
 717717 void
 718718 cbgen(int o, int lab)
 719719 {
 720720         if (o < EQ || o > UGT)
 721721                 comperr("bad conditional branch: %s", opst[o]);
 722722         printf("        %s " LABFMT "\n", ccbranches[o-EQ], lab);
 723723 }
 724724 
 725725 /*
 726726  * gcc xasm has the ability to generate different asm types
 727727  * via some magic.
 728728  *
 729729  * Only support AT&T asm for now.
 730730  */
 731731 static char *
 732732 adjustname(char *s)
 733733 {
 734734         int len = strlen(s);
 735735         char *d = tmpalloc(len+1);
 736736         int i, j, flvl, tlvl;
 737737 
 738738         flvl = tlvl = 0;
 739739         for (i = j = 0; i < len; i++) {
 740740                 switch (s[i]) {
 741741                 case '{': tlvl++; break;
 742742                 case '}': if (tlvl)tlvl--; else flvl--; break;
 743743                 case '|': tlvl--; flvl++; break;
 744744                 default:
 745745                         if (flvl == 0)
 746746                                 d[j++] = s[i];
 747747                         break;
 748748                 }
 749749         }
 750750         d[j] = 0;
 751751         return d;
 752752 }
 753753 
 754754 static void
 755755 fixcalls(NODE *p, void *arg)
 756756 {
 757757         /* Prepare for struct return by allocating bounce space on stack */
 758758         switch (p->n_op) {
 759759         case STCALL:
 760760         case USTCALL:
 761761                 if (p->n_stsize+p2autooff > stkpos)
 762762                         stkpos = p->n_stsize+p2autooff;
 763763                 break;
 764764         case XASM:
 765765                 p->n_name = adjustname(p->n_name);
 766766                 break;
 767767         }
 768768 }
 769769 
 770770 void
 771771 myreader(struct interpass *ipole)
 772772 {
 773773         struct interpass *ip;
 774774 
 775775         stkpos = p2autooff;
 776776         DLIST_FOREACH(ip, ipole, qelem) {
 777777                 if (ip->type != IP_NODE)
 778778                         continue;
 779779                 walkf(ip->ip_node, fixcalls, 0);
 780780         }
 781781         if (stkpos > p2autooff)
 782782                 p2autooff = stkpos;
 783783         if (stkpos > p2maxautooff)
 784784                 p2maxautooff = stkpos;
 785785         if (x2debug)
 786786                 printip(ipole);
 787787 }
 788788 
 789789 /*
 790790  * Remove some PCONVs after OREGs are created.
 791791  */
 792792 static void
 793793 pconv2(NODE *p, void *arg)
 794794 {
 795795         NODE *q;
 796796 
 797797         if (p->n_op == PLUS) {
 798798                 if (p->n_type == (PTR|SHORT) || p->n_type == (PTR|USHORT)) {
 799799                         if (p->n_right->n_op != ICON)
 800800                                 return;
 801801                         if (p->n_left->n_op != PCONV)
 802802                                 return;
 803803                         if (p->n_left->n_left->n_op != OREG)
 804804                                 return;
 805805                         q = p->n_left->n_left;
 806806                         nfree(p->n_left);
 807807                         p->n_left = q;
 808808                         /*
 809809                          * This will be converted to another OREG later.
 810810                          */
 811811                 }
 812812         }
 813813 }
 814814 
 815815 void
 816816 mycanon(NODE *p)
 817817 {
 818818         walkf(p, pconv2, 0);
 819819 }
 820820 
 821821 void
 822822 myoptim(struct interpass *ip)
 823823 {
 824824 }
 825825 
 826826 void
 827827 rmove(int s, int d, TWORD t)
 828828 {
 829829 
 830830         switch (t) {
 831831         case INT:
 832832         case UNSIGNED:
 833833                 printf("        movl %s,%s\n", rlong[s], rlong[d]);
 834834                 break;
 835835         case CHAR:
 836836         case UCHAR:
 837837                 printf("        movb %s,%s\n", rbyte[s], rbyte[d]);
 838838                 break;
 839839         case SHORT:
 840840         case USHORT:
 841841                 printf("        movw %s,%s\n", rshort[s], rshort[d]);
 842842                 break;
 843843         case FLOAT:
 844844                 printf("        movss %s,%s\n", rnames[s], rnames[d]);
 845845                 break;
 846846         case DOUBLE:
 847847                 printf("        movsd %s,%s\n", rnames[s], rnames[d]);
 848848                 break;
 849849         case LDOUBLE:
 850850 #ifdef notdef
 851851                 /* a=b()*c(); will generate this */
 852852                 /* XXX can it fail anyway? */
 853853                 comperr("bad float rmove: %d %d", s, d);
 854854 #endif
 855855                 break;
 856856         default:
 857857                 printf("        movq %s,%s\n", rnames[s], rnames[d]);
 858858                 break;
 859859         }
 860860 }
 861861 
 862862 /*
 863863  * For class c, find worst-case displacement of the number of
 864864  * registers in the array r[] indexed by class.
 865865  */
 866866 int
 867867 COLORMAP(int c, int *r)
 868868 {
 869869 
 870870         switch (c) {
 871871         case CLASSA:
 872872                 return r[CLASSA] < 14;
 873873         case CLASSB:
 874874                 return r[CLASSB] < 16;
 875875         case CLASSC:
 876876                 return r[CLASSC] < CREGCNT;
 877877         }
 878878         return 0; /* XXX gcc */
 879879 }
 880880 
 881881 char *rnames[] = {
 882882         "%rax", "%rdx", "%rcx", "%rbx", "%rsi", "%rdi", "%rbp", "%rsp",
 883883         "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
 884884         "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7",
 885885         "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14",
 886886         "%xmm15",
 887887 };
 888888 
 889889 /* register names for shorter sizes */
 890890 char *rbyte[] = {
 891891         "%al", "%dl", "%cl", "%bl", "%sil", "%dil", "%bpl", "%spl",
 892892         "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b",
 893893 };
 894894 char *rshort[] = {
 895895         "%ax", "%dx", "%cx", "%bx", "%si", "%di", "%bp", "%sp",
 896896         "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w",
 897897 };
 898898 char *rlong[] = {
 899899         "%eax", "%edx", "%ecx", "%ebx", "%esi", "%edi", "%ebp", "%esp",
 900900         "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d",
 901901 };
 902902 
 903903 
 904904 /*
 905905  * Return a class suitable for a specific type.
 906906  */
 907907 int
 908908 gclass(TWORD t)
 909909 {
 910910         if (t == LDOUBLE)
 911911                 return CLASSC;
 912912         if (t == FLOAT || t == DOUBLE)
 913913                 return CLASSB;
 914914         return CLASSA;
 915915 }
 916916 
 917917 static int
 918918 argsiz(NODE *p)
 919919 {
 920920         TWORD t = p->n_type;
 921921 
 922922         if (p->n_left->n_op == REG)
 923923                 return 0; /* not on stack */
 924924         if (t == LDOUBLE)
 925925                 return 16;
 926926         if (p->n_op == STASG)
 927927                 return p->n_stsize;
 928928         return 8;
 929929 }
 930930 
 931931 /*
 932932  * Calculate argument sizes.
 933933  */
 934934 void
 935935 lastcall(NODE *p)
 936936 {
 937937         NODE *op = p;
 938938         int size = 0;
 939939 
 940940         p->n_qual = 0;
 941941         if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL)
 942942                 return;
 943943         for (p = p->n_right; p->n_op == CM; p = p->n_left)
 944944                 size += argsiz(p->n_right);
 945945         size += argsiz(p);
 946946         size = (size+15) & ~15;
 947947         if (size)
 948948                 printf("        subq $%d,%s\n", size, rnames[RSP]);
 949949         op->n_qual = size; /* XXX */
 950950 }
 951951 
 952952 /*
 953953  * Special shapes.
 954954  */
 955955 int
 956956 special(NODE *p, int shape)
 957957 {
 958958         int o = p->n_op;
 959959 
 960960         switch (shape) {
 961961         case SFUNCALL:
 962962                 if (o == STCALL || o == USTCALL)
 963963                         return SRREG;
 964964                 break;
 965965         case SPCON:
 966966                 if (o != ICON || p->n_name[0] ||
 967967                     p->n_lval < 0 || p->n_lval > 0x7fffffff)
 968968                         break;
 969969                 return SRDIR;
 970970         case SMIXOR:
 971971                 return tshape(p, SZERO);
 972972         case SMILWXOR:
 973973                 if (o != ICON || p->n_name[0] ||
 974974                     p->n_lval == 0 || p->n_lval & 0xffffffff)
 975975                         break;
 976976                 return SRDIR;
 977977         case SMIHWXOR:
 978978                 if (o != ICON || p->n_name[0] ||
 979979                      p->n_lval == 0 || (p->n_lval >> 32) != 0)
 980980                         break;
 981981                 return SRDIR;
 982982         case SCON32:
 983983                 if (o != ICON || p->n_name[0])
 984984                         break;
 985985                 if (p->n_lval < MIN_INT || p->n_lval > MAX_INT)
 986986                         break;
 987987                 return SRDIR;
 988988         default:
 989989                 cerror("special: %x\n", shape);
 990990         }
 991991         return SRNOPE;
 992992 }
 993993 
 994994 /*
 995995  * Target-dependent command-line options.
 996996  */
 997997 void
 998998 mflags(char *str)
 999999 {
 10001000 }
 10011001 
 10021002 /*
 10031003  * Do something target-dependent for xasm arguments.
 10041004  */
 10051005 int
 10061006 myxasm(struct interpass *ip, NODE *p)
 10071007 {
 10081008         struct interpass *ip2;
 10091009         int Cmax[] = { 31, 63, 127, 0xffff, 3, 255 };
 10101010         NODE *in = 0, *ut = 0;
 10111011         TWORD t;
 10121012         char *w;
 10131013         int reg;
 10141014         int c, cw, v;
 10151015 
 10161016         cw = xasmcode(p->n_name);
 10171017         if (cw & (XASMASG|XASMINOUT))
 10181018                 ut = p->n_left;
 10191019         if ((cw & XASMASG) == 0)
 10201020                 in = p->n_left;
 10211021 
 10221022         c = XASMVAL(cw);
 10231023 retry:  switch (c) {
 10241024         case 'D': reg = RDI; break;
 10251025         case 'S': reg = RSI; break;
 10261026         case 'A':
 10271027         case 'a': reg = RAX; break;
 10281028         case 'b': reg = RBX; break;
 10291029         case 'c': reg = RCX; break;
 10301030         case 'd': reg = RDX; break;
 10311031 
 10321032         case 'Q': reg = RDX; break; /* Always dx for now */
 10331033 
 10341034         case 'x':
 10351035         case 'q':
 10361036         case 't':
 10371037         case 'u':
 10381038                 p->n_name = tmpstrdup(p->n_name);
 10391039                 w = strchr(p->n_name, c);
 10401040                 *w = 'r'; /* now reg */
 10411041                 return c == 'q' || c == 'x' ? 0 : 1;
 10421042 
 10431043         case 'I':
 10441044         case 'J':
 10451045         case 'K':
 10461046         case 'L':
 10471047         case 'M':
 10481048         case 'N':
 10491049                 if (p->n_left->n_op != ICON) {
 10501050                         if ((c = XASMVAL1(cw))) {
 10511051                                 if (c == 'r') {
 10521052                                         p->n_name++;
 10531053                                         return 0;
 10541054                                 }
 10551055                                 goto retry;
 10561056                         }
 10571057                         uerror("xasm arg not constant");
 10581058                 }
 10591059                 v = p->n_left->n_lval;
 10601060                 if ((c == 'K' && v < -128) ||
 10611061                     (c == 'L' && v != 0xff && v != 0xffff) ||
 10621062                     (c != 'K' && v < 0) ||
 10631063                     (v > Cmax[c-'I']))
 10641064                         uerror("xasm val out of range");
 10651065                 p->n_name = "i";
 10661066                 return 1;
 10671067 
 10681068         default:
 10691069                 return 0;
 10701070         }
 10711071         /* If there are requested either memory or register, delete memory */
 10721072         w = p->n_name = tmpstrdup(p->n_name);
 10731073         if (*w == '=')
 10741074                 w++;
 10751075         *w++ = 'r';
 10761076         *w = 0;
 10771077 
 10781078         t = p->n_left->n_type;
 10791079 
 10801080         if (t == FLOAT || t == DOUBLE) {
 10811081                 p->n_label = CLASSB;
 10821082                 reg += 16;
 10831083         } else if (t == LDOUBLE) {
 10841084                 p->n_label = CLASSC;
 10851085                 reg += 32;
 10861086         } else
 10871087                 p->n_label = CLASSA;
 10881088 
 10891089         if (in && ut)
 10901090                 in = tcopy(in);
 10911091         p->n_left = mklnode(REG, 0, reg, t);
 10921092         if (ut) {
 10931093                 ip2 = ipnode(mkbinode(ASSIGN, ut, tcopy(p->n_left), t));
 10941094                 DLIST_INSERT_AFTER(ip, ip2, qelem);
 10951095         }
 10961096         if (in) {
 10971097                 ip2 = ipnode(mkbinode(ASSIGN, tcopy(p->n_left), in, t));
 10981098                 DLIST_INSERT_BEFORE(ip, ip2, qelem);
 10991099         }
 11001100 
 11011101         return 1;
 11021102 }
 11031103 
 11041104 void
 11051105 targarg(char *w, void *arg, int n)
 11061106 {
 11071107         NODE **ary = arg;
 11081108         NODE *p, *q;
 11091109 
 11101110         if (w[1] < '0' || w[1] > (n + '0'))
 11111111                 uerror("bad xasm arg number %c", w[1]);
 11121112         if (w[1] == (n + '0'))
 11131113                 p = ary[(int)w[1]-'0' - 1]; /* XXX */
 11141114         else
 11151115                 p = ary[(int)w[1]-'0'];
 11161116         p = p->n_left;
 11171117 
 11181118         if (optype(p->n_op) != LTYPE)
 11191119                 comperr("bad xarg op %d", p->n_op);
 11201120         q = tcopy(p);
 11211121         if (q->n_op == REG) {
 11221122                 if (*w == 'k') {
 11231123                         q->n_type = INT;
<> 1124+                } else if (*w == 'q') {
  1125+                        q->n_type = LONG;
<_11241126                 } else if (*w == 'h' || *w == 'b') {
 11251127                         /* Can do this only because we know dx is used */
 11261128                         printf("%%d%c", *w == 'h' ? 'h' : 'l');
 11271129                         tfree(q);
 11281130                         return;
 11291131                 } else if (*w != 'w') {
 11301132                         cerror("targarg"); /* XXX ??? */
 11311133                         if (q->n_type > UCHAR) {
 11321134                                 regno(q) = regno(q)*2+8;
 11331135                                 if (*w == 'h')
 11341136                                         regno(q)++;
 11351137                         }
 11361138                         q->n_type = INT;
 11371139                 } else
 11381140                         q->n_type = SHORT;
 11391141         }
 11401142         adrput(stdout, q);
 11411143         tfree(q);
 11421144 }
 11431145 
 11441146 /*
 11451147  * target-specific conversion of numeric arguments.
 11461148  */
 11471149 int
 11481150 numconv(void *ip, void *p1, void *q1)
 11491151 {
 11501152         NODE *p = p1, *q = q1;
 11511153         int cw = xasmcode(q->n_name);
 11521154 
 11531155         switch (XASMVAL(cw)) {
 11541156         case 'a':
 11551157         case 'b':
 11561158         case 'c':
 11571159         case 'd':
 11581160                 p->n_name = tmpcalloc(2);
 11591161                 p->n_name[0] = XASMVAL(cw);
 11601162                 return 1;
 11611163         default:
 11621164                 return 0;
 11631165         }
 11641166 }
 11651167 
 11661168 static struct {
 11671169         char *name; int num;
 11681170 } xcr[] = {
 11691171         { "rax", RAX },
 11701172         { "rbx", RBX },
 11711173         { "rcx", RCX },
 11721174         { "rdx", RDX },
 11731175         { "rsi", RSI },
 11741176         { "rdi", RDI },
 11751177         { "st", 040 },
 11761178         { "st(0)", 040 },
 11771179         { "st(1)", 041 },
 11781180         { "st(2)", 042 },
 11791181         { "st(3)", 043 },
 11801182         { "st(4)", 044 },
 11811183         { "st(5)", 045 },
 11821184         { "st(6)", 046 },
 11831185         { "st(7)", 047 },
 11841186         { NULL, 0 },
 11851187 };
 11861188 
 11871189 /*
 11881190  * Check for other names of the xasm constraints registers.
 11891191  */
 11901192 int xasmconstregs(char *s)
 11911193 {
 11921194         int i;
 11931195 
 11941196         for (i = 0; xcr[i].name; i++)
 11951197                 if (strcmp(xcr[i].name, s) == 0)
 11961198                         return xcr[i].num;
 11971199         return -1;
 11981200 }
 11991201 
FishEye: Open Source License registered to PCC.
Atlassian FishEye, CVS analysis. (Version:1.6.3 Build:build-336 2008-11-04) - Administration - Page generated 2014-12-27 22:26 +0100