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

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

unix.superglobalmegacorp.com

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