Annotation of researchv10no/cmd/ccom/vax/gencode.c, revision 1.1.1.1

1.1       root        1: #include "gencode.h"
                      2: #define fieldbotch(p) if(p->left->op == Fld) {rewritefld(p); longjmp(back, 1);}
                      3: jmp_buf back;
                      4: int acnt, Pflag, bbcnt;
                      5: NODE *svq;             /* just for printing at FAIL */
                      6: 
                      7: gencode(p)
                      8: NODE *p;
                      9: {      mnod *q;
                     10:        ret s;
                     11:        int svtemp, svregvar, i, svbb;
                     12:        extern int bothdebug;
                     13:        svtemp = tmpoff;
                     14:        svregvar = regvar;
                     15:        svbb = ++bbcnt;
                     16:        svq = p;
                     17:        if(setjmp(back)) {
                     18:                pr("#\treg\t%d\n", ++acnt) /*,prtree(q), putchar('\n')*/;
                     19:                if(acnt > 20) {
                     20:                        prtree(q);
                     21:                        outpr();
                     22:                        tmpoff = svtemp;
                     23:                        bbcnt = svbb;
                     24:                        uerror("expression too complicated");
                     25:                        return;
                     26:                }
                     27:        }
                     28:        else
                     29:                q = copytree(p);
                     30:        buf = bufs[1];
                     31:        prptr = prbuf;
                     32:        if(Pflag && q->op != Init) {
                     33:                pr("#\tincl\tlocprof+%d\n", 4*(svbb+3));
                     34:        }
                     35:        s = doit(q, 0, 0, REGMASK);
                     36:        if(s.flag & FAIL)
                     37:                uerror("codegen failed at top level");
                     38:        acnt = ntree = 0;
                     39:        if(Pflag && q->op != Init)
                     40:                printx("#%d ", svbb), prtree(q), printx("\n");
                     41:        outpr();
                     42:        tmpoff = svtemp;
                     43:        regvar = svregvar;
                     44: }
                     45: 
                     46: ret
                     47: doit(p, flag, dest, regmask)
                     48: mnod *p;
                     49: ret dest;
                     50: {      ret s, t, x, y;
                     51:        char *pp;
                     52:        mnod snode, *q;
                     53:        int i, j, svmask = regmask;
                     54:        switch(p->op) {
                     55:        default:
                     56:                pr("#\tweird??? %d\n", p->op);
                     57:                return(dest);
                     58:        case Andeq:
                     59:                fieldbotch(p)
                     60:                if(dest.ans && p->left->op == Star)
                     61:                        longjmp(back, mediumstar(p));
                     62:                flag |= DESTISLEFT;
                     63:                flag &= ~CC;
                     64:        case And:
                     65:                if((flag & CC)) {       /* short b; reg int *c; if(b & *c++); */
                     66:                        if(p->left->op == Conv && incrsize(p->left->left) < 4)
                     67:                                p->left = p->left->left;
                     68:                        if(p->right->op == Conv
                     69:                                && incrsize(p->right->left) < 4)
                     70:                                p->right = p->right->left;
                     71:                }
                     72:                t = doit(p->left, VALUE|USED, 0, regmask);
                     73:                if(t.flag & FAIL)
                     74:                        return(t);
                     75:                regmask &= ~t.regmask;
                     76:                s = doit(p->right, VALUE|USED, 0, regmask);
                     77:                if(s.flag & FAIL)
                     78:                        goto binfail;
                     79:                if(flag & CC) {
                     80:                        if(incrsize(p->left) == incrsize(p->right))
                     81:                                i = type(p->right);
                     82:                        else if(incrsize(p->left) < incrsize(p->right)) {
                     83:                                if(s.flag & INDEX) {
                     84:                                        totemp(p, RIGHT);
                     85:                                        longjmp(back, 1);
                     86:                                }
                     87:                                i = childtype(p);
                     88:                        }
                     89:                        else {
                     90:                                if(t.flag & INDEX) {
                     91:                                        totemp(p, LEFT);
                     92:                                        longjmp(back, 1);
                     93:                                }
                     94:                                i = type(p->right);
                     95:                        }
                     96:                        pr("#\tbit%c\t%s,%s\n", i, str(s), str(t));
                     97:                        dest.ans = 0;
                     98:                        dest.flag = CC;
                     99:                        dest.regmask = 0;
                    100:                        return(dest);
                    101:                }
                    102:                regmask &= ~s.regmask;
                    103:                /* p->right->op == Compl is a useful special case */
                    104:                if((flag & DESTISLEFT) && dest.ans == 0)
                    105:                        dest = x = t;
                    106:                if(dest.ans == 0)
                    107:                        if(s.flag & SCRATCH)
                    108:                                dest = x = s;
                    109:                        else if(t.flag & SCRATCH) {
                    110:                                dest = t;
                    111:                                x = allocreg(p, regmask);
                    112:                        }
                    113:                        else
                    114:                                dest = x = allocreg(p, regmask);
                    115:                else
                    116:                        x = allocreg(p, regmask);
                    117:                if(p->right->op == Icon) {
                    118:                        x = tostack();  /* to get a buf */
                    119:                        sprintx(str(x), "$%d", -p->right->lval - 1);
                    120:                }
                    121:                else
                    122:                        pr("#\tmcom%c\t%s,%s\n", childtype(p), str(s), str(x));
                    123:                if(strcmp(str(t), str(dest)) == 0)
                    124:                        pr("#\tbic%c2\t%s,%s\n", childtype(p), str(x), str(dest));
                    125:                else if(flag & DESTISLEFT) {
                    126:                        pr("#\tbic%c2\t%s,%s\n", childtype(p), str(x), str(t));
                    127:                        if(strcmp(str(t), str(dest))) {
                    128:                                x = t;
                    129:                                goto movexdest;
                    130:                        }
                    131:                }
                    132:                else
                    133:                        pr("#\tbic%c3\t%s,%s,%s\n", childtype(p), str(x),
                    134:                                str(t), str(dest));
                    135:                if(flag & ASADDR)
                    136:                        goto toaddr;
                    137:                dest.flag |= CC;
                    138:                return(dest);
                    139:        case Call:
                    140: call:
                    141:                s.flag = funargs(p->right, regmask);
                    142:                if(s.flag & FAIL)
                    143:                        return(s);
                    144:                i = p->argsize/32;
                    145:                if(i > 255)
                    146:                        uerror("%d arguments is too many", i);
                    147: called:
                    148:                s = doit(p->left, VALUE|ASADDR|USED, 0, regmask);
                    149:                pp = str(s);
                    150: aftercall:
                    151:                if(svmask != REGMASK) {
                    152:                        debugpr("#FAIL aftercall ");
                    153:                        s.flag = FAIL;
                    154:                        return(s);
                    155:                }
                    156:                x = specialreg(p, regmask);
                    157:                pr("#\tcalls\t$%d,%s\n", i, pp);
                    158:                if(flag & ASADDR) {
                    159:                        strcat(str(x), ")");
                    160:                        strshift(str(x), 1);
                    161:                        str(x)[0] = '(';
                    162:                }
                    163:                if(dest.ans == 0)
                    164:                        if(flag & DESTISLEFT)
                    165:                                dest = doit(p->left->op == Conv?
                    166:                                        p->left->left:
                    167:                                        p->left, 0/* ? */, 0, regmask & ~x.regmask);
                    168:                        else
                    169:                                return(x);
                    170: movexdest:     /* type(p), not childtype, for a = a % b */
                    171:                if(strcmp(str(x), str(dest)) == 0)
                    172:                        return(x);
                    173:                if((flag & TOSTACK) && incrsize(p) == 4)
                    174:                        pr("#\tpush%c\t%s\n", type(p), str(x));
                    175:                else if(x.flag & ICON0)
                    176:                        pr("#\tclr%c\t%s\n", type(p), str(dest));
                    177:                else if(isfloat(p) != isfloat(p->left)
                    178:                        && p->op != Call && p->op != Ucall)
                    179:                        pr("#\tcvt%c%c\t%s,%s\n", childtype(p), type(p), str(x), str(dest));
                    180:                else if((flag & TOSTACK) && (incrsize(p) != 8))
                    181:                        pr("#\tcvt%cl\t%s,-(sp)\n", type(p), str(x));
                    182:                else {
                    183:                        pr("#\tmov%c\t%s,%s\n", type(p), str(x), str(dest));
                    184:                        dest = simpler(x, dest);
                    185:                }
                    186:                dest.flag |= CC;
                    187:                return(dest);
                    188:        case Cmp:
                    189:                if(p->left->op == Conv && p->right->op == Conv
                    190:                        && childtype(p->left) == childtype(p->right)
                    191:                        && !isfloat(p->left->left)) {   /* bogus? */
                    192:                        p->left = p->left->left;
                    193:                        p->right = p->right->left;
                    194:                }
                    195:                else if(p->left->op == Conv && p->right->op == Icon
                    196:                        && p->right->lval >= 0
                    197:                        && ((incrsize(p->left->left) == 1
                    198:                                && p->right->lval < 128)
                    199:                        || (incrsize(p->left->left) == 2
                    200:                                && p->right->lval < 32768)))
                    201:                        p->left = p->left->left;
                    202:                /* the above rewriting depends on childype being of p->left */
                    203:                s = doit(p->left, VALUE|USED, 0, regmask);
                    204:                if(s.flag & FAIL)
                    205:                        return(s);
                    206:                regmask &= ~s.regmask;
                    207:                t = doit(p->right, VALUE|USED, 0, regmask);
                    208:                if(t.flag & FAIL) {
                    209:                        t = doit(p->right, VALUE|USED, 0, REGMASK);
                    210:                        if(!(t.flag & FAIL) && svmask != REGMASK)
                    211:                                return(t.flag = FAIL, t);
                    212:                        totemp(p, LEFT);
                    213:                        longjmp(back, 1);
                    214:                }
                    215:                pr("#\tcmp%c\t%s,%s\n", childtype(p), str(s), str(t));
                    216:                dest.ans = dest.regmask = 0;
                    217:                dest.flag = CC;
                    218:                return(dest);
                    219:        case Comop:     /* qnodes lurking underneath */
                    220:                if(p->left->op == Genlab && hasqnode(p->right)) {
                    221:                        if(dest.ans == 0) {
                    222:                                dest = allocreg(p, regmask);
                    223:                        }
                    224:                        t = doit(p->left, VALUE|(flag & CC), dest, regmask);
                    225:                }
                    226:                else
                    227:                        t = doit(p->left, 0, 0, regmask);
                    228:                if(t.flag & FAIL)
                    229:                        return(t);
                    230:                s = doit(p->right, VALUE|(flag & (USED|CC)), dest, regmask);
                    231:                if(s.flag & FAIL)
                    232:                        return(s);
                    233:                if(flag & ASADDR) {
                    234:                        dest.ans = 0;
                    235:                        i = (s.flag & (ISREG|CANINDIR|SCRATCH));
                    236:                        j = s.regmask;
                    237:                        buf = str(s);
                    238:                        goto convbuf;
                    239:                }
                    240:                return(s);
                    241:        case Compl:
                    242:                s = doit(p->left, VALUE|USED, 0, regmask);
                    243:                if(s.flag & FAIL)
                    244:                        return(s);
                    245:                if(dest.ans == 0)
                    246:                        if(s.flag & SCRATCH)
                    247:                                dest = s;
                    248:                        else
                    249:                                dest = allocreg(p, regmask & ~s.regmask);
                    250:                pr("#\tmcom%c\t%s,%s\n", childtype(p), str(s), str(dest));
                    251:                dest.flag |= CC;
                    252:                return(dest);
                    253:        case Conv:
                    254:                if(p->left->op == Asg && p->left->left->op == Star) {
                    255:                        if(dest.ans == 0) {
                    256:                                dest = allocreg(p, regmask);
                    257:                                s = doit(p->left, VALUE|USED, dest, regmask);
                    258:                        }
                    259:                        else {
                    260:                                x = allocreg(p, regmask);
                    261:                                s = doit(p->left, VALUE|USED, x, regmask & ~x.regmask);
                    262:                        }
                    263:                        if(s.flag & FAIL) {
                    264:                                asgwrite(p->left);
                    265:                                longjmp(back, 1);
                    266:                        }
                    267:                }
                    268:                else
                    269:                        s = doit(p->left, VALUE|USED, 0, regmask);
                    270:                if(childtype(p) == type(p) && dest.ans == 0)
                    271:                        return(s);
                    272:                if(s.flag & FAIL)
                    273:                        return(s);
                    274:                if(dest.ans == 0)
                    275:                        if(s.flag & SCRATCH)
                    276:                                dest = checksize(p, s, regmask);
                    277:                        else
                    278:                                dest = allocreg(p, regmask);
                    279:                if(isunsigned(p->left) && incrsize(p) > incrsize(p->left)) {
                    280:                        if(type(p) != 'f' && type(p) != 'd')
                    281:                                pp = "movz";
                    282:                        else {  /* uns to float or double */
                    283:                                rewriteconv(p);
                    284:                                longjmp(back, 1);
                    285:                        }
                    286:                }
                    287:                else
                    288:                        pp = "cvt";
                    289:                if(isfloat(p) != isfloat(p->left))
                    290:                        goto cvtop;
                    291:                if(incrsize(p) < incrsize(p->left)) {
                    292:                        if(isfloat(p))
                    293:                                goto cvtop;
                    294:                        pr("#\tmov%c\t%s,%s\n", type(p), str(s), str(dest));
                    295:                        dest = simpler(s, dest);
                    296:                }
                    297:                else if(incrsize(p) > incrsize(p->left))
                    298: cvtop:
                    299:                        pr("#\t%s%c%c\t%s,%s\n", pp, childtype(p), type(p), str(s), str(dest));
                    300:                else {  /* types were the same, but dest.ans != 0 */
                    301:                        pr("#\tmov%c\t%s,%s\n", type(p), str(s), str(dest));
                    302:                        dest = simpler(s, dest);
                    303:                }
                    304:                dest.flag |= CC;
                    305:                return(dest);
                    306:        case Decr:
                    307:                i = -1;
                    308:                pp = "sub";
                    309: incrop:
                    310:                if(p->type == Tfloat)
                    311:                        uerror("no float ++/--");
                    312:                fieldbotch(p)
                    313:                /* if the dest uses regs, it may be from a qnode, so that reg
                    314:                 * shouldn't be used (i?*a->b++:x()) where b has offset > 0
                    315:                 */
                    316:                s = doit(p->left, USED, 0, dest.ans? regmask & ~dest.regmask: regmask);
                    317:                if(s.flag & FAIL)
                    318:                        return(s);
                    319:                t = doit(p->right, 0, 0, 0);
                    320:                if(flag & VALUE) {
                    321:                        if(dest.ans == 0)
                    322:                                dest = allocreg(p, regmask & ~s.regmask);
                    323:                        pr("#\tmov%c\t%s,%s\n", childtype(p), str(s), str(dest));
                    324:                        if(t.flag & ICON1) {
                    325:                                if(i == 1)
                    326:                                        pp = "inc";
                    327:                                else
                    328:                                        pp = "dec";
                    329:                                pr("#\t%s%c\t%s\n", pp, childtype(p), str(s));
                    330:                        }
                    331:                        else
                    332:                                pr("#\t%s%c2\t%s,%s\n", pp, childtype(p),
                    333:                                        str(t), str(s));
                    334: toaddr:
                    335:                        if(flag & ASADDR) {
                    336:                                if(dest.flag & ISREG) {
                    337:                                        sprintx(buf, "(%s)", str(dest));
                    338:                                        done(dest, CANINDIR, dest.regmask);
                    339:                                }
                    340:                                if(dest.flag & CANINDIR) {
                    341:                                        sprintx(buf, "*%s", str(dest));
                    342:                                        done(dest, 0, dest.regmask);
                    343:                                }
                    344:                                uerror("weird asaddr in incrop");
                    345:                        }
                    346:                        dest.flag &= ~CC;
                    347:                        return(dest);
                    348:                }
                    349:                if(t.flag & ICON1) {
                    350:                        if(i == 1)
                    351:                                pp = "inc";
                    352:                        else
                    353:                                pp = "dec";
                    354:                        pr("#\t%s%c\t%s\n", pp, childtype(p), str(s));
                    355:                }
                    356:                else
                    357:                        pr("#\t%s%c2\t%s,%s\n", pp, childtype(p), str(t), str(s));
                    358:                if(dest.ans) {
                    359:                        x = s;
                    360:                        goto movexdest;
                    361:                }
                    362:                s.flag &= ~CC;
                    363:                return(s);
                    364:        case Diveq:
                    365:                fieldbotch(p)
                    366:                if(rewriteasgop(p))
                    367:                        goto assign;
                    368:                flag |= DESTISLEFT;
                    369:        case Div:
                    370:                /* trees wrong: uns/=int and int/=uns */
                    371:                if(!isunsigned(p->right) && !isunsigned(p->left)) {
                    372:                        pp = "div";
                    373:                        goto binop;
                    374:                }
                    375:                pp = "udiv";
                    376: unsdiv:
                    377:                /* *p++ /= uns is hard */
                    378:                if(p->left->op == Star && fixuns(p))
                    379:                        longjmp(back, 1);       /* *A op= B => (T=A, *T op= B) */
                    380:                if(incrsize(p->right) != 4) {
                    381:                        snode.op = Conv;
                    382:                        snode.left = p->right;
                    383:                        snode.type = Tulong;
                    384:                        s = doit(&snode, VALUE|TOSTACK, tostack(), regmask);
                    385:                }
                    386:                else
                    387:                        s = doit(p->right, TOSTACK, tostack(), regmask);
                    388:                if(s.flag & FAIL)
                    389:                        return(s);
                    390:                regmask &= ~s.regmask;
                    391:                if(incrsize(p->left) != 4) {            
                    392:                        snode.op = Conv;
                    393:                        snode.left = p->left;
                    394:                        snode.type = Tulong;
                    395:                        t = doit(&snode, VALUE|TOSTACK, tostack(), regmask);
                    396:                }
                    397:                else
                    398:                        t = doit(p->left, VALUE|TOSTACK, tostack(), regmask);
                    399:                if(t.flag & FAIL) {
                    400:                        if(dest.ans || svmask != REGMASK) {
                    401:                                t = doit(p->left, VALUE|TOSTACK, tostack(), svmask);
                    402:                                if(t.flag & FAIL)
                    403:                                        return(t);
                    404:                        }
                    405:                        totemp(p, RIGHT);
                    406:                        longjmp(back, 1);
                    407:                }
                    408:                i = 2;
                    409:                goto aftercall;
                    410:        case Xoreq:
                    411:                fieldbotch(p)
                    412:                flag |= DESTISLEFT;
                    413:        case Xor:
                    414:                pp = "xor";
                    415: binop:
                    416:                if((flag & DESTISLEFT) && dest.ans && p->left->op == Star)
                    417:                        longjmp(back, mediumstar(p));
                    418:                t = doit(p->left, VALUE|USED, 0, regmask);
                    419:                if(t.flag & FAIL) {
                    420:                        return(t);
                    421:                }
                    422:                regmask &= ~t.regmask;
                    423:                s = doit(p->right, VALUE|USED, 0, regmask);
                    424:                if(s.flag & FAIL) {
                    425: binfail:
                    426:                        if(dest.ans || svmask != REGMASK) {
                    427:                                s = doit(p->right, VALUE|USED, 0, svmask);
                    428:                                if(s.flag & FAIL)
                    429:                                        return(s);
                    430:                        }
                    431:                        /* *foo op= expr  requires care */
                    432:                        if((flag & DESTISLEFT) && p->left->op == Star)
                    433:                                totemp(p->left, LEFT);
                    434:                        else
                    435:                                totemp(p, LEFT);
                    436:                        longjmp(back, 1);
                    437:                }
                    438:                if(type(p) != childtype(p)) {
                    439:                        x = allocreg(p, regmask);
                    440:                        pr("#\t%s%c3\t%s,%s,%s\n", pp, childtype(p), str(s),
                    441:                                str(t), str(x));
                    442:                        if(dest.ans == 0)
                    443:                                if(flag & DESTISLEFT)
                    444:                                        dest = t;
                    445:                                else
                    446:                                        dest = x;
                    447:                        if(!isfloat(p) && !isfloat(p->left)
                    448:                                && incrsize(p) < incrsize(p->left)) {
                    449:                                pr("#\tmov%c\t%s,%s\n", type(p), str(x), str(dest));
                    450:                                dest = simpler(x, dest);
                    451:                        }
                    452:                        else
                    453:                                pr("#\tcvt%c%c\t%s,%s\n", childtype(p), type(p),
                    454:                                        str(x), str(dest));
                    455:                        dest.flag |= CC;
                    456:                        return(dest);
                    457:                }       
                    458:                if(dest.ans == 0)
                    459:                        if((t.flag & SCRATCH) || (flag & DESTISLEFT)) {
                    460: twoop:
                    461:                                dest = t;
                    462:                                if(*pp == 'a' && (s.flag & ICON1))
                    463:                                        pr("#\tinc%c\t%s\n", childtype(p), str(t));
                    464:                                else if(*pp == 's' && (s.flag & ICON1))
                    465:                                        pr("#\tdec%c\t%s\n", childtype(p), str(t));
                    466:                                else
                    467:                                        pr("#\t%s%c2\t%s,%s\n", pp, childtype(p),
                    468:                                                str(s), str(t));
                    469:                                if(flag & ASADDR)
                    470:                                        goto binopaddr;
                    471:                                if(flag & TOSTACK)
                    472:                                        pr("#\tpush%c\t%s\n", type(p), str(t));
                    473:                                dest.flag |= CC;
                    474:                                return(dest);
                    475:                        }
                    476:                        else if(s.flag & SCRATCH)
                    477:                                dest = s;
                    478:                        else
                    479:                                dest = allocreg(p, regmask);
                    480:                if(dest.ans && (flag & DESTISLEFT)) {
                    481:                        pr("#\t%s%c2\t%s,%s\n", pp, childtype(p), str(s), str(t));
                    482:                        x = t;
                    483:                        goto movexdest;
                    484:                }
                    485:                if(commutes(p->op) && strcmp(str(s), str(dest)) == 0) {
                    486:                        dest = s;
                    487:                        s = t;
                    488:                        t = dest;
                    489:                        goto twoop;
                    490:                }
                    491:                if(strcmp(str(t), str(dest)) == 0)
                    492:                        goto twoop;
                    493:                        
                    494:                pr("#\t%s%c3\t%s,%s,%s\n", pp, childtype(p), str(s), str(t), str(dest));
                    495: binopaddr:
                    496:                if(flag & ASADDR) {
                    497:                        if(dest.flag & ISREG) {
                    498:                                strcat(str(dest), ")");
                    499:                                strshift(str(dest), 1);
                    500:                                str(dest)[0] = '(';
                    501:                                return(dest);
                    502:                        }
                    503:                        if(dest.flag & CANINDIR) {
                    504:                                strshift(str(dest), 1);
                    505:                                str(dest)[0] = '*';
                    506:                                dest.flag &= ~CANINDIR;
                    507:                                return(dest);
                    508:                        }
                    509:                        debugpr("#FAIL doubtful ");
                    510:                        dest.flag = FAIL;       /* doubtful */
                    511:                        return(dest);
                    512:                }
                    513:                dest.flag |= CC;
                    514:                return(dest);   
                    515:        case Fld:
                    516:                /* this is rvalues */
                    517:                s = doit(p->left, USED, 0, regmask);
                    518:                if(s.flag & FAIL)
                    519:                        return(s);
                    520:                if(dest.ans == 0)
                    521:                        dest = allocreg(p, regmask);
                    522:                if((s.flag & INDEX) && p->left->op == Star
                    523:                        && incrsize(p->left) != 1) {
                    524:                /* over-enthusiastic use of index mode */
                    525:                        if(dest.flag & SCRATCH)
                    526:                                x = dest;
                    527:                        else
                    528:                                x = allocreg(p, regmask);
                    529:                        pr("#\tmov%c\t%s,%s\n", childtype(p), str(s), str(x));
                    530:                        s = x;
                    531:                }
                    532:                pr("#\text%sv\t$%d,$%d,%s,%s\n", isunsigned(p->left)? "z": "",
                    533:                        p->rval/64, p->rval%64, str(s), str(dest));
                    534:                dest.flag |= CC;
                    535:                return(dest);
                    536:        case Genbr:
                    537:                if(p->left->op == Conv)
                    538:                        s = doit(p->left->left, CC|VALUE|USED, 0, regmask);
                    539:                /*else if(p->left->op == And && pow2(p->left->right->lval) > 0) {
                    540:                        s = doit(p->left->left, CC|VALUE, 0, regmask);
                    541:                        pp = genjbc(p->lop);
                    542:                        pr("#\t%s\t$%d,%s,L%d\n", pp, pow2(p->left->right->lval),
                    543:                                str(s), p->label);
                    544:                        goto genbr0;
                    545:                } not a win on 8550 */
                    546:                else
                    547:                        s = doit(p->left, CC|VALUE|USED, 0, regmask);
                    548:                pp = genjmp(p->lop);
                    549:                if(s.flag & CC)
                    550:                        if(p->left->op != Conv || p->left->type >= Tint)
                    551:                                pr("#\t%s\t", pp);
                    552:                        else
                    553:                                pr("#\ttst%c\t%s\n\t%s\t", childtype(p),
                    554:                                        str(s), pp);
                    555:                else if(p->left->op == Conv)
                    556:                        pr("#\ttst%c\t%s\n#\t%s\t", childtype(p->left), str(s), pp);
                    557:                else
                    558:                        pr("#\ttst%c\t%s\n#\t%s\t", childtype(p), str(s), pp);
                    559:                pr("L%d\n", p->label);
                    560: genbr0:
                    561:                s.flag |= CC;   /* ?? */
                    562:                if(Pflag) {
                    563:                        ++bbcnt;
                    564:                        pr("#\tincl\tlocprof+%d\n", 4*(bbcnt+3));
                    565:                }
                    566:                return(s);
                    567:        case Genlab:
                    568:                s = doit(p->left, flag, dest, regmask);
                    569:                pr("#L%d:\n", p->label);
                    570:                if(Pflag) {
                    571:                        ++bbcnt;
                    572:                        pr("#\tincl\tlocprof+%d\n", 4*(bbcnt+3));
                    573:                }
                    574:                return(s);
                    575:        case Genubr:
                    576:                s = doit(p->left, flag & CC, dest, regmask);
                    577:                if((flag & CC) && !(s.flag & CC))
                    578:                        pr("#\ttst%c\t%s\n", childtype(p), str(s));
                    579:                pr("#\tjbr\tL%d\n", p->label);
                    580:                return(s);
                    581:        case Icon:
                    582:                if(p->name)
                    583:                        if(p->lval)
                    584:                                sprintx(buf, "%s+%d", p->name, p->lval);
                    585:                        else
                    586:                                sprintx(buf, "%s", p->name);
                    587:                else
                    588:                        sprintx(buf, "%d", p->lval);
                    589:                if(!(flag & ASADDR)) {
                    590:                        strshift(buf, 1);;
                    591:                        buf[0] = '$';
                    592:                }
                    593:                i = 0;
                    594:                if(p->name == 0)
                    595:                        if(p->lval == 0)
                    596:                                i = ICON0;
                    597:                        else if(p->lval == 1)
                    598:                                i = ICON1;
                    599:                j = 0;
                    600: convbuf:       /* the cookie is in buf */
                    601:                if(dest.ans == 0 && !(flag & TOSTACK)) {
                    602:                        if(p->op == Icon || !(flag & ASADDR)) {
                    603:                                done(s, i, j);
                    604:                        }
                    605:                        if(i & CANINDIR) {
                    606:                                strshift(buf, 1);
                    607:                                buf[0] = '*';
                    608:                                done(s, i & ~CANINDIR, j);
                    609:                        }
                    610:                        if(i & ISREG) {
                    611:                                strcat(buf, ")");
                    612:                                strshift(buf, 1);
                    613:                                buf[0] = '(';
                    614:                                done(s, i, j);
                    615:                        }
                    616:                        pp = buf;
                    617:                        buf += BUF;
                    618:                        s = allocreg(p, regmask);
                    619:                        pr("#\tmov%c\t%s,%s\n", type(p), pp, str(s));
                    620:                        flag &= ~ASADDR;
                    621:                        goto inreg;
                    622:                }
                    623:                if(flag & TOSTACK)
                    624:                        if(incrsize(p) == 4)
                    625:                                pr("#\tpushl\t%s\n", buf);
                    626:                        else if(incrsize(p) == 8)
                    627:                                pr("#\tmovd\t%s,%s\n", buf, str(dest));
                    628:                        else
                    629:                                pr("#\tcvt%cl\t%s,%s\n", type(p), buf, str(dest));
                    630:                else if(i & ICON0)
                    631:                        pr("#\tclr%c\t%s\n", type(p), str(dest));
                    632:                else {  
                    633:                        pr("#\tmov%c\t%s,%s\n", type(p), buf, str(dest));
                    634:                        if(!(dest.flag & INDEX) || !index(str(dest), '+')
                    635:                                && !index(str(dest), '-'))
                    636:                                ;
                    637:                        else if(!(i & INDEX) || !index(buf, '+')
                    638:                                && !index(buf, '-')) {
                    639:                                done(s, (i|CC), j);
                    640:                        }
                    641:                        else
                    642:                                dest.flag |= USED;
                    643:                }
                    644:                dest.flag |= CC;
                    645:                return(dest);
                    646:        case Incr:
                    647:                i = 1;
                    648:                pp = "add";
                    649:                goto incrop;
                    650:        case Init:      /* knows it is ICON */
                    651:                s = doit(p->left, ASADDR, 0, 0);
                    652:                pr("#\t.long\t%s\n", str(s));
                    653:                return(dest);
                    654:        case Lseq:
                    655:                if(incrsize(p) != 4)
                    656:                        lsconv(p);
                    657:                if(rewriteasgop(p))
                    658:                        goto assign;
                    659:                fieldbotch(p)
                    660:                flag |= DESTISLEFT;
                    661:                if(dest.ans && p->left->op == Star)
                    662:                        longjmp(back, mediumstar(p));
                    663:        case Ls:        /* stupid vax */
                    664:                if(incrsize(p) != 4)
                    665:                        lsconv(p);
                    666:                s = doit(p->left, VALUE|USED, 0, regmask);
                    667:                if(s.flag & FAIL)
                    668:                        return(s);
                    669:                regmask &= ~s.regmask;
                    670:                t = doit(p->right, VALUE|USED, 0, regmask);
                    671:                if(t.flag & FAIL)
                    672:                        goto binfail;
                    673:                if((t.flag & INDEX) && p->right->op == Star
                    674:                        && incrsize(p->right) != 1) {
                    675:                /* over-enthusiastic use of index mode */
                    676:                        if(dest.flag & SCRATCH)
                    677:                                x = dest;
                    678:                        else
                    679:                                x = allocreg(p, regmask);
                    680:                        pr("#\tmov%c\t%s,%s\n", childtype(p), str(t), str(x));
                    681:                        t = x;
                    682:                }
                    683:                if(dest.ans == 0)
                    684:                        if((s.flag & SCRATCH) || (flag & DESTISLEFT))
                    685:                                dest = s;
                    686:                        else
                    687:                                dest = allocreg(p, regmask);
                    688:                if(incrsize(p) != 4) {  /* stupid vax */
                    689:                        x = allocreg(p, regmask);
                    690:                        pr("#\tashl\t%s,%s,%s\n", str(t), str(s), str(x));
                    691:                        pr("#\tmov%c\t%s,%s\n", type(p), str(x), str(dest));
                    692:                        if(flag & DESTISLEFT)
                    693:                                pr("#\tmovl\t%s,%s\n", str(x), str(s));
                    694:                        dest.flag |= CC;
                    695:                        return(dest);
                    696:                }
                    697:                if(p->right->op == Icon && (i = p->right->lval) <= 4
                    698:                        && (dest.flag & ISREG) && !(s.flag&AUTO)) {
                    699:                        if(strcmp(str(s), str(dest))) {
                    700:                                i--;
                    701:                                pr("#\taddl3\t%s,%s,%s\n", str(s), str(s), str(dest));
                    702:                        }
                    703:                        while(i-- > 0)
                    704:                                pr("#\taddl2\t%s,%s\n", str(dest), str(dest));
                    705:                }
                    706:                else if(flag & DESTISLEFT)
                    707:                        pr("#\tashl\t%s,%s,%s\n", str(t), str(s), str(s));
                    708:                else
                    709:                        pr("#\tashl\t%s,%s,%s\n", str(t), str(s), str(dest));
                    710:                if((flag & DESTISLEFT) && strcmp(str(dest), str(s)))
                    711:                        pr("#\tmovl\t%s,%s\n", str(s), str(dest));
                    712:                dest.flag |= CC;
                    713:                return(dest);
                    714:        case Minuseq:
                    715:                fieldbotch(p)
                    716:                if(rewriteasgop(p))
                    717:                        goto assign;
                    718:                flag |= DESTISLEFT;
                    719:        case Minus:
                    720:                pp = "sub";
                    721:                /* you won't believe this: type x[], *y where type is shorter than
                    722:                 * int, generates subx $_x,y which the assembler barfs on.
                    723:                 * instead, generate crummy code (stupid assembler)
                    724:                 */
                    725:                if(incrsize(p) < 4) {
                    726:                        if(p->left->op == Icon && p->left->name) {
                    727:                                p->left->type = Tint;
                    728:                                totemp(p, LEFT);
                    729:                        }
                    730:                        if(p->right->op == Icon && p->right->name) {
                    731:                                p->right->type = Tint;
                    732:                                totemp(p, RIGHT);
                    733:                        }
                    734:                }
                    735:                goto binop;
                    736:        case Modeq:
                    737:                fieldbotch(p)
                    738:                if(rewriteasgop(p))
                    739:                        goto assign;
                    740:                if(dest.ans && p->left->op == Star)
                    741:                        longjmp(back, mediumstar(p));
                    742:                flag |= DESTISLEFT;
                    743:        case Mod:
                    744:                if(isunsigned(p->right) || isunsigned(p->left)) {
                    745:                        pp = "urem";
                    746:                        goto unsdiv;
                    747:                }
                    748:                s = doit(p->left, VALUE|USED, 0, regmask);
                    749:                if(s.flag & FAIL)
                    750:                        return(s);
                    751:                regmask &= ~s.regmask;
                    752:                t = doit(p->right, VALUE|USED, 0, regmask);
                    753:                if(t.flag & FAIL)
                    754:                        goto binfail;
                    755:                regmask &= ~t.regmask;
                    756:                x = allocreg(p, regmask);
                    757:                pr("#\tdiv%c3\t%s,%s,%s\n", childtype(p), str(t), str(s), str(x));
                    758:                pr("#\tmul%c2\t%s,%s\n", childtype(p), str(t), str(x));
                    759:                pr("#\tsub%c3\t%s,%s,%s\n", childtype(p), str(x), str(s), str(x));
                    760:                if(dest.ans)
                    761:                        goto movexdest;
                    762:                if(flag & DESTISLEFT) {
                    763:                        dest = s;
                    764:                        goto movexdest;
                    765:                }
                    766:                x.flag |= CC;
                    767:                return(x);
                    768:        case Muleq:
                    769:                fieldbotch(p)
                    770:                if(rewriteasgop(p))
                    771:                        goto assign;
                    772:                flag |= DESTISLEFT;
                    773:        case Mul:
                    774:                pp = "mul";
                    775:                goto binop;
                    776:        case Name:      /* ASADDR? */
                    777:                if(p->lval && p->name)
                    778:                        sprintx(buf, "%s+%d", p->name, p->lval);
                    779:                else if(p->name)
                    780:                        sprintx(buf, "%s", p->name);
                    781:                else if(p->lval)
                    782:                        sprintf(buf, "%d", p->lval);
                    783:                else
                    784:                        sprintx(buf, "0");
                    785:                j = 0;
                    786:                i = CANINDIR;
                    787:                goto convbuf;
                    788:        case Oreq:
                    789:                fieldbotch(p)
                    790:                flag |= DESTISLEFT;
                    791:        case Or:
                    792:                pp = "bis";
                    793:                goto binop;
                    794:        case Pluseq:
                    795:                fieldbotch(p)
                    796:                if(rewriteasgop(p))
                    797:                        goto assign;
                    798:                flag |= DESTISLEFT;
                    799:        case Plus:
                    800:                pp = "add";
                    801:                goto binop;
                    802:        case Reg:
                    803:                sprintx(buf, "%s", regnames[p->rval]);
                    804:                j = 0;
                    805:                i = ISREG;
                    806:                if(p->lval == 1)
                    807:                        i |= SCRATCH;
                    808:                goto convbuf;
                    809:        case Rnode: case Snode:
                    810:                x = specialreg(p, 3);
                    811:                x.regmask = 0;
                    812:                if(dest.ans)
                    813:                        goto movexdest;
                    814:                return(x);
                    815:        case Qnode:
                    816:                return(specialreg(p, regmask));
                    817:        case Rseq:
                    818:                fieldbotch(p)
                    819:                if(incrsize(p) != 4)
                    820:                        lsconv(p);
                    821:                if(rewriteasgop(p))
                    822:                        goto assign;
                    823:                flag |= DESTISLEFT;
                    824:        case Rs:        /* all right shifts are unsigned */
                    825:                if(incrsize(p->left) != 4)      /* shifting funny objects */
                    826:                        lsconv(p);
                    827:                s = doit(p->left, VALUE|USED, 0, regmask);
                    828:                if(s.flag & FAIL)
                    829:                        return(s);
                    830:                if(p->left->op == Icon ||
                    831:                        (s.flag & INDEX) && p->left->op == Star
                    832:                        && incrsize(p->left) != 1 ||
                    833:                        (s.flag & AUTO) && incrsize(p->left) != 1) {
                    834:                /* over-enthusiastic use of index mode */
                    835:                /* 12 >> i generates a byte immediate */
                    836:                        if((s.flag & INDEX) && (flag & DESTISLEFT)) {/* *a++ >>= 1 */
                    837:                                lsconv(p);      /* not best */
                    838:                                longjmp(back, 1);
                    839:                        }
                    840:                        if((flag & DESTISLEFT) && dest.ans == 0) {
                    841:                                dest = s;
                    842:                                regmask &= ~s.regmask;
                    843:                        }
                    844:                        if(dest.flag & SCRATCH)
                    845:                                x = dest;
                    846:                        else
                    847:                                x = allocreg(p, regmask);
                    848:                        pr("#\tmovl\t%s,%s\n", str(s), str(x));
                    849:                        s = x;
                    850:                }
                    851:                regmask &= ~s.regmask;
                    852:                if(dest.ans == 0)
                    853:                        if((flag & DESTISLEFT) || (s.flag & SCRATCH))
                    854:                                dest = s;
                    855:                        else
                    856:                                dest = allocreg(p, regmask);
                    857:                dest.flag |= CC;
                    858:                regmask &= ~dest.regmask;
                    859:                if(incrsize(p) != 4)
                    860:                        x = allocreg(p, regmask);
                    861:                else if(flag & DESTISLEFT)
                    862:                        x = s;
                    863:                else
                    864:                        x = dest;
                    865:                if(p->right->op == Icon && (i = p->right->lval) >= 0) {
                    866:                        pr("#\textzv\t$%d,$%d,%s,%s\n", i, 32 - i, str(s), str(x));
                    867:                        goto movexdest;
                    868:                }
                    869:                t = doit(p->right, VALUE|USED, 0, regmask);
                    870:                if(t.flag & FAIL)
                    871:                        goto binfail;
                    872:                y = allocreg(p, regmask & ~t.regmask);
                    873:                pr("#\tsubl3\t%s,$32,%s\n", str(t), str(y));
                    874:                pr("#\textzv\t%s,%s,%s,%s\n", str(t), str(y), str(s), str(x));
                    875:                goto movexdest;
                    876:        case Star:
                    877:                switch(p->left->op) {
                    878:                case Icon:      /* as in foo((a, a)), where a is a struct */
                    879:                        s = doit(p->left, VALUE, 0, regmask);
                    880:                        sprintx(buf, "%s", str(s)+1);
                    881:                        i = j = 0;
                    882:                        goto convbuf;
                    883:                case Auto:
                    884:                case Param:
                    885:                case Name:
                    886:                        s = doit(p->left, VALUE, 0, regmask);
                    887:                        sprintx(buf, "*%s", str(s));
                    888:                        j = i = 0;
                    889:                        goto convbuf;
                    890:                case Reg:
                    891:                        s = doit(p->left, VALUE, 0, regmask);
                    892: inreg:
                    893:                        if(s.flag & ISREG) {
                    894:                                sprintx(buf, "(%s)", str(s));
                    895:                                j = s.regmask;
                    896:                                i = CANINDIR;
                    897:                                goto convbuf;
                    898:                        }
                    899:                        else if(s.flag & CANINDIR) {
                    900:                                sprintx(buf, "*%s", str(s));
                    901:                                j = s.regmask;
                    902:                                i = 0;
                    903:                                goto convbuf;
                    904:                        }
                    905:                        else {
                    906:                                debugpr("#FAIL STAR REG ");
                    907:                                s.flag = FAIL;
                    908:                                return(s);
                    909:                        }
                    910:                }
                    911:                q = p->left;
                    912:                if(q->op == Incr && !(flag & INDEX)
                    913:                        && q->right->op == Icon && q->left->op == Reg
                    914:                        && incrsize(p) == (int) q->right->lval) {
                    915:                        s = doit(q->left, VALUE, 0, regmask);
                    916:                        sprintx(buf, "(%s)+", str(s));
                    917:                        i = INDEX|AUTO;
                    918:                        j = s.regmask;
                    919:                        goto convbuf;
                    920:                }
                    921:                if(q->op == Plus && q->left->op == Ls
                    922:                        && !(flag & INDEX)
                    923:                        && q->left->right->op == Icon
                    924:                        && shiftsize(p) == (int) q->left->right->lval) {
                    925:                        s = doit(q->left->left, VALUE|USED, 0, regmask);
                    926:                        if(s.flag & FAIL)
                    927:                                return(s);
                    928:                        regmask &= ~s.regmask;
                    929:                        if(!(s.flag & ISREG)) {
                    930:                                x = allocreg(p, regmask);
                    931:                                pr("#\tmov%c\t%s,%s\n", childtype(q), str(s), str(x));
                    932:                                regmask |= s.regmask;
                    933:                                regmask &= ~x.regmask;
                    934:                                s = x;
                    935:                                if(!(s.flag & ISREG)) {
                    936:                                        debugpr("#FAIL a[b] ");
                    937:                                        s.flag = FAIL;
                    938:                                        return(s);
                    939:                                }
                    940:                        }
                    941:                        t = doit(q->right, ASADDR|USED|VALUE, 0, regmask);
                    942:                        if(t.flag & FAIL) {
                    943:                                totemp(q, LEFT);
                    944:                                longjmp(back, 1);
                    945:                        }
                    946:                        sprintx(buf, "%s[%s]", str(t), str(s));
                    947:                        i = INDEX;
                    948:                        j = s.regmask | t.regmask;
                    949:                        goto convbuf;
                    950:                }
                    951:                if(q->op == Plus && q->right->op == Icon) {
                    952:                        s = doit(q->left, VALUE|USED, 0, regmask);
                    953:                        if(s.flag & FAIL)
                    954:                                return(s);
                    955:                        if(!(s.flag & ISREG)) {
                    956:                                x = allocreg(p, regmask);
                    957:                                pr("#\tmov%c\t%s,%s\n", childtype(q), str(s), str(x));
                    958:                                s = x;
                    959:                                if(!(s.flag & ISREG)) {
                    960:                                        debugpr("#FAIL a(b) ");
                    961:                                        s.flag = FAIL;
                    962:                                        return(s);
                    963:                                }
                    964:                        }
                    965:                        regmask &= ~s.regmask;
                    966:                        t = doit(q->right, ASADDR|USED, 0, regmask);
                    967:                        sprintx(buf, "%s(%s)", str(t), str(s));
                    968:                        i = CANINDIR;
                    969:                        j = s.regmask;
                    970:                        goto convbuf;
                    971:                }
                    972:                if(q->op == Minus && q->right->op == Icon) {
                    973:                        s = doit(q->left, VALUE|USED, 0, regmask);
                    974:                        if(s.flag & FAIL)
                    975:                                return(s);
                    976:                        if(!(s.flag & ISREG)) {
                    977:                                x = allocreg(p, regmask);
                    978:                                pr("#\tmov%c\t%s,%s\n", childtype(q), str(s), str(x));
                    979:                                s = x;
                    980:                                if(!(s.flag & ISREG)) {
                    981:                                        debugpr("#FAIL %d(a) ");
                    982:                                        s.flag = FAIL;
                    983:                                        return(s);
                    984:                                }
                    985:                        }
                    986:                        regmask &= ~s.regmask;
                    987:                        sprintx(buf, "%d(%s)", -q->right->lval, str(s));
                    988:                        i = CANINDIR;
                    989:                        j = s.regmask;
                    990:                        goto convbuf;
                    991:                }
                    992:                if(q->op == Minuseq && !(flag & (INDEX|USED))
                    993:                        && q->right->op == Icon && q->left->op == Reg
                    994:                        && incrsize(p) == (int) q->right->lval) {
                    995:                        s = doit(q->left, VALUE, 0, regmask);
                    996:                        sprintx(buf, "-(%s)", str(s));
                    997:                        i = INDEX|AUTO;
                    998:                        j = s.regmask;
                    999:                        goto convbuf;
                   1000:                }
                   1001:                if(q->op == Plus && q->left->op == Reg
                   1002:                        && !(flag & INDEX) && q->right->op == Reg
                   1003:                        && incrsize(p) == 1) {
                   1004:                        sprintx(buf, "(r%d)[r%d]", q->right->rval,
                   1005:                                q->left->rval);
                   1006:                        i = INDEX;
                   1007:                        j = 0;
                   1008:                        goto convbuf;
                   1009:                }
                   1010:                s = doit(p->left, VALUE|USED, 0, regmask);
                   1011:                if(s.flag & FAIL)
                   1012:                        return(s);
                   1013:                regmask &= ~s.regmask;
                   1014:                if(s.flag & CANINDIR) {
                   1015:                        sprintx(buf, "*%s", str(s));
                   1016:                        i = 0;
                   1017:                        j = s.regmask;
                   1018:                        goto convbuf;
                   1019:                }
                   1020:                if(!(s.flag & ISREG)) {
                   1021:                        x = allocreg(p, regmask);
                   1022:                        pr("#\tmov%c\t%s,%s\n", type(q), str(s), str(x));
                   1023:                        regmask |= s.regmask;
                   1024:                        regmask &= ~x.regmask;
                   1025:                        s = x;
                   1026:                }
                   1027:                if(!(s.flag & ISREG)) {
                   1028:                        debugpr("#FAIL STAR ");
                   1029:                        s.flag = FAIL;
                   1030:                        return(s);
                   1031:                }
                   1032:                sprintx(buf, "(%s)", str(s));
                   1033:                i = 0;
                   1034:                j = s.regmask;
                   1035:                goto convbuf;
                   1036:        case Stasg:
                   1037:                if(p->stsize/8 == 4) {
                   1038:                        i = 'l';
                   1039: stasg:
                   1040:                        s = doit(p->left, VALUE|ASADDR|USED|FSTASG, 0, regmask);
                   1041:                        if(s.flag & FAIL)
                   1042:                                return(s);
                   1043:                        regmask &= ~s.regmask;
                   1044:                        t = doit(p->right, VALUE|ASADDR|USED|FSTASG, 0, regmask);
                   1045:                        if(t.flag & FAIL) {
                   1046:                                t = doit(p->right, VALUE|ASADDR|USED|FSTASG, 0, REGMASK);
                   1047:                                if(!(t.flag & FAIL) && svmask != REGMASK)
                   1048:                                        return(t.flag = FAIL, t);
                   1049:                                totemp(p, LEFT);
                   1050:                                longjmp(back, 1);
                   1051:                        }
                   1052:                        pr("#\tmov%c\t%s,%s\n", i, str(t), str(s));
                   1053:                        if(!(flag & FSTASG))
                   1054:                                s = addrsimp(s, t);
                   1055:                        return(s);
                   1056:                }
                   1057:                else if(p->stsize/8 == 8) {
                   1058:                        i = 'q';
                   1059:                        goto stasg;
                   1060:                }
                   1061:                if(regmask != REGMASK) {
                   1062:                        debugpr("#FAIL stasg ");
                   1063:                        s.flag = FAIL;
                   1064:                        return(s);
                   1065:                }
                   1066:                s = doit(p->right, VALUE|USED|FSTASG, 0, regmask);
                   1067:                if(s.flag & INDEX) {
                   1068:                /* over-enthusiastic use of index mode */
                   1069:                        x = allocreg(p, regmask);
                   1070:                        pr("#\tmovl\t%s,%s\n", str(s), str(x));
                   1071:                        s = x;
                   1072:                }
                   1073:                regmask &= ~s.regmask;
                   1074:                t = doit(p->left, VALUE|USED|FSTASG, 0, regmask);
                   1075:                if(t.flag & FAIL) {
                   1076:                        totemp(p, RIGHT);
                   1077:                        longjmp(back, 1);
                   1078:                }
                   1079:                if(t.flag & INDEX) {
                   1080:                /* over-enthusiastic use of index mode */
                   1081:                        x = allocreg(p, regmask);
                   1082:                        pr("#\tmovl\t%s,%s\n", str(t), str(x));
                   1083:                        t = x;
                   1084:                }
                   1085:                t = indirit(t);
                   1086:                if(t.flag & FAIL) {
                   1087:                        if(p->left->op != Star)
                   1088:                                cerror("codegen failure in struct asg");
                   1089:                        totemp(p->left, LEFT);
                   1090:                        longjmp(back, 1);
                   1091:                }
                   1092:                s = indirit(s);
                   1093:                if(s.flag & FAIL) {
                   1094:                        if(p->right->op != Star)
                   1095:                                cerror("codgen fail in stasg");
                   1096:                        totemp(p->right, LEFT);
                   1097:                        longjmp(back, 1);
                   1098:                }
                   1099:                pr("#\tmovc3\t$%d,%s,%s\n", p->stsize/8, str(s), str(t));
                   1100:                if(flag & USED) {
                   1101:                        t = specialreg(p, REGMASK);
                   1102:                        pr("#\tsubl3\t$%d,r3,r0\n", p->stsize/8);
                   1103:                }
                   1104:                else
                   1105:                        t.flag = 0;
                   1106:                return(t);
                   1107:        case Stcall:
                   1108:                goto call;
                   1109:        case Auto:
                   1110:                sprintx(buf, "%d(%s)", p->lval, frameptr);
                   1111:                j = 0;
                   1112:                i = CANINDIR;
                   1113:                goto convbuf;
                   1114:        case Param:
                   1115:                sprintx(buf, "%d(%s)", p->lval, argptr);
                   1116:                j = 0;
                   1117:                i = CANINDIR;
                   1118:                goto convbuf;
                   1119:        case Addr:
                   1120:                s = doit(p->left, USED, 0, regmask);
                   1121:                if(s.flag & FAIL)
                   1122:                        return(s);
                   1123:                regmask &= ~s.regmask;
                   1124:                if(dest.ans == 0) {
                   1125:                        dest = allocreg(p, regmask);
                   1126:                }
                   1127:                if(s.flag & ISREG) {
                   1128:                        x = alloctmp(p);
                   1129:                        pr("#\tmov%c\t%s,%s\n", childtype(p), str(s), str(x));
                   1130:                        s = x;
                   1131:                }
                   1132:                if(flag & TOSTACK)
                   1133:                        pr("#\tpushal\t%s\n", str(s));
                   1134:                else
                   1135:                        pr("#\tmova%c\t%s,%s\n", type(p), str(s), str(dest));
                   1136:                if(flag & ASADDR) {
                   1137:                        if(dest.flag & ISREG) {
                   1138:                                strcat(str(dest), ")");
                   1139:                                strshift(str(dest), 1);
                   1140:                                str(dest)[0] = '(';
                   1141:                        }
                   1142:                        else {
                   1143:                                strshift(str(dest), 1);
                   1144:                                str(dest)[0] = '*';
                   1145:                        }
                   1146:                }
                   1147:                return(dest);
                   1148:        case Ucall:
                   1149:                i = 0;
                   1150:                goto called;
                   1151:        case Uminus:
                   1152:                s = doit(p->left, VALUE|USED, 0, regmask);
                   1153:                if(s.flag & FAIL)
                   1154:                        return(s);
                   1155:                if(dest.ans == 0)
                   1156:                        if(s.flag & SCRATCH)
                   1157:                                dest = s;
                   1158:                        else
                   1159:                                dest = allocreg(p, regmask & ~s.regmask);
                   1160:                pr("#\tmneg%c\t%s,%s\n", childtype(p), str(s), str(dest));
                   1161:                dest.flag |= CC;
                   1162:                return(dest);
                   1163:        case Ustcall:
                   1164:                i = 0;
                   1165:                goto called;
                   1166:        case Asg:
                   1167: assign:
                   1168:                if(p->left->op == Qnode && dest.ans) {
                   1169:                        s = doit(p->right, VALUE|(flag&USED? USED: 0),
                   1170:                                dest, regmask);
                   1171:                        return(s);
                   1172:                }
                   1173:                if(p->left->op == Rnode || p->left->op == Snode) {
                   1174:                        s = doit(p->right, VALUE|(flag&USED? USED: 0),
                   1175:                                dest, regmask);
                   1176:                        if(s.flag & FAIL)
                   1177:                                return(s);
                   1178:                        x = s;
                   1179:                        dest = doit(p->left, USED, 0, 0);
                   1180:                        goto movexdest;
                   1181:                }
                   1182:                if(p->left->op == Fld) {
                   1183:                        s = doit(p->left->left, INDEX, 0, regmask);
                   1184:                        regmask &= ~s.regmask;
                   1185:                        if(p->right->op == Asg) {
                   1186:                                x = allocreg(p->right, regmask);
                   1187:                                t = doit(p->right, VALUE|USED, x, regmask & ~x.regmask);
                   1188:                        }
                   1189:                        else
                   1190:                                t = doit(p->right, VALUE|USED, 0, regmask);
                   1191:                        if(t.flag & FAIL) {     /* was fldstar */
                   1192:                                totemp(p->left->left, LEFT);
                   1193:                                totemp(p, RIGHT);
                   1194:                                longjmp(back, 1);
                   1195:                        }
                   1196:                        i = '$';
                   1197:                        pr("#\tinsv\t%s,%c%d,%c%d,%s\n", str(t), i,
                   1198:                                p->left->rval/64, i,
                   1199:                                p->left->rval % 64, str(s));
                   1200:                        if(dest.ans) {
                   1201:                                pr("#\tmovl\t%s,%s\n", str(t), str(dest));
                   1202:                                t.flag |= CC;
                   1203:                        }
                   1204:                        return(t);
                   1205:                }
                   1206:                if(dest.ans && p->left->op == Star) {
                   1207:                        if(dest.flag & SCRATCH)
                   1208:                                x = dest;
                   1209:                        else
                   1210:                                x = allocreg(p, regmask);
                   1211:                        s = doit(p->right, VALUE|USED, x, regmask);
                   1212:                        if(s.flag & FAIL)
                   1213:                                return(s);
                   1214:                        regmask &= ~s.regmask;
                   1215:                        t = doit(p->left, USED, 0, regmask);
                   1216:                        if(t.flag & FAIL) {
                   1217:                        /* did we fail because of a dest, or was it us? */
                   1218:                                if(dest.ans || svmask != REGMASK) {
                   1219:                                        t = doit(p->left, USED, 0, svmask);
                   1220:                                        if(t.flag & FAIL) {
                   1221:                                                return(t);
                   1222:                                        }
                   1223:                                        starasg(p);
                   1224:                                }
                   1225:                                else
                   1226:                                        asgwrite(p);
                   1227:                                longjmp(back, 1);
                   1228:                        }
                   1229:                        pr("#\tmov%c\t%s,%s\n", type(p), str(x), str(t));
                   1230:                        if(strcmp(str(x), str(dest)) == 0) {
                   1231:                                dest.flag |= CC;
                   1232:                                return(dest);
                   1233:                        }
                   1234:                        goto movexdest;
                   1235:                }
                   1236:                if(p->right->op == Fld && incrsize(p) != 4) {
                   1237:                        /* ext sets whole word */
                   1238:                        asgwrite(p);
                   1239:                        p->left->type = isunsigned(p)? Tuint: Tint;
                   1240:                        longjmp(back, 1);
                   1241:                }
                   1242:                t = doit(p->left, USED, 0, regmask);
                   1243:                regmask &= ~t.regmask;
                   1244:                if(p->right->op == Genlab || p->right->op == Comop)
                   1245:                        extracheck(p);  /* slightly worse code in usual case */
                   1246:                s = doit(p->right, VALUE, t, regmask);  /* VALUE is't right:
                   1247:                        register char *a, *b; return((*a++ = *b++ | 40) != 3); */
                   1248:                if(s.flag & NOGOOD) {
                   1249:                /* did we fail because of a dest, or was it us? */
                   1250:                        if(s.flag & FAIL) {
                   1251:                                if(dest.ans || svmask != REGMASK) {
                   1252:                                        s = doit(p->right, VALUE, t, svmask);
                   1253:                                        if(s.flag & FAIL) {
                   1254:                                                return(s);
                   1255:                                        }
                   1256:                                }
                   1257:                                asgwrite(p);
                   1258:                                longjmp(back, 1);
                   1259:                        }
                   1260:                        else if((flag & USED) && !((flag & CC) && (s.flag & CC))) {
                   1261:                                /* presumably USED as in *p++=*q++ */
                   1262:                                totemp(p, RIGHT);
                   1263:                                longjmp(back, 1);
                   1264:                        }
                   1265:                }
                   1266:                if(dest.ans) {
                   1267:                        x = s;
                   1268:                        goto movexdest;
                   1269:                }
                   1270:                else if(flag & ASADDR) {
                   1271:                        i = (s.flag & (ISREG|CANINDIR|SCRATCH));
                   1272:                        j = s.regmask;
                   1273:                        buf = str(s);
                   1274:                        goto convbuf;
                   1275:                }
                   1276:                return(s);
                   1277:        }
                   1278: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.