Annotation of researchv10no/cmd/lcc/gen2/mips/pseudos.c, revision 1.1.1.1

1.1       root        1: /* C compiler: MIPS code generator */
                      2: 
                      3: #include "c.h"
                      4: 
                      5: static Symbol f0, ireg[32], d4, d6, f12, f14;
                      6: 
                      7: static int flabel;
                      8: int gnum = 8;
                      9: char *nrflag = "";
                     10: int framesize;
                     11: 
                     12: dclproto(static void addr,(Symbol, Symbol, int));
                     13: dclproto(static void funcsave,(int, int, int, int, unsigned, unsigned, int));
                     14: dclproto(static void storearg,(Symbol, Symbol, Symbol));
                     15: dclproto(static unsigned a_def,(Symbol));
                     16: dclproto(static void a_defaddress,(Symbol));
                     17: dclproto(static unsigned a_emit,(unsigned, int, int, int, int));
                     18: dclproto(static void a_end,(Symbol));
                     19: dclproto(static void a_entry,(Symbol, int, int));
                     20: dclproto(static int a_offset,(int));
                     21: dclproto(static void a_symbol,(int, Symbol));
                     22: dclproto(static void a_word,(unsigned, int));
                     23: 
                     24: dclproto(static void address,(Symbol, Symbol, int));
                     25: dclproto(static void blkfetch,(int, int, int, int));
                     26: dclproto(static void blkloop,(int, int, int, int, int, int[]));
                     27: dclproto(static void blkstore,(int, int, int, int));
                     28: dclproto(static void defaddress,(Symbol));
                     29: dclproto(static void defconst,(int, Value));
                     30: dclproto(static void defstring,(int, char *));
                     31: dclproto(static void defsymbol,(Symbol));
                     32: dclproto(static void doarg,(Node));
                     33: dclproto(static void emitspecial,(Node));
                     34: dclproto(static void function,(Symbol, Symbol [], Symbol [], int));
                     35: dclproto(static void global,(Symbol));
                     36: dclproto(static void import,(Symbol));
                     37: dclproto(static void local,(Symbol));
                     38: dclproto(static void progbeg,(int, char **));
                     39: dclproto(static void segment,(int));
                     40: dclproto(static void space,(int));
                     41: 
                     42: dclproto(static void stabinit,(char *, int, char *[]));
                     43: dclproto(static void stabline,(Coordinate *));
                     44: dclproto(static void stabsym,(Symbol));
                     45: 
                     46: dclproto(static void initgen,(void));
                     47: dclproto(static void final,(Node));
                     48: 
                     49: #ifdef GEN4
                     50: dclproto(static unsigned emit2,(Node,Node[],short[]));
                     51: dclproto(static void target,(Node));
                     52: #endif
                     53: 
                     54: struct emit put = {
                     55:        setseg,
                     56:        spacen,
                     57:        genascii,
                     58:        a_emit,
                     59:        addr,
                     60:        a_def,
                     61:        a_defaddress,
                     62:        a_end,
                     63:        a_entry,
                     64:        a_offset,
                     65:        a_symbol,
                     66:        a_word
                     67: };
                     68: 
                     69: Interface mipsInterface = {
                     70:        "mips",
                     71:        1, 1, 0,        /* char */
                     72:        2, 2, 0,        /* short */
                     73:        4, 4, 0,        /* int */
                     74:        4, 4, 1,        /* float */
                     75:        8, 8, 1,        /* double */
                     76:        4, 4, 0,        /* T * */
                     77:        0, 1, 0,        /* struct */
                     78:        1,              /* left_to_right */
                     79:        0,              /* little_endian */
                     80:        1,              /* jump_on_return */
                     81:        0,              /* mulops_are_calls */
                     82:        0,              /* compl_band */
                     83:        0,              /* no_argb */
                     84:        NODAG,          /* no_dag */
                     85:        address,
                     86:        blockbeg,
                     87:        blockend,
                     88:        defaddress,
                     89:        defconst,
                     90:        defstring,
                     91:        defsymbol,
                     92:        0,
                     93:        export,
                     94:        function,
                     95:        gen,
                     96:        global,
                     97:        import,
                     98:        local,
                     99:        progbeg,
                    100:        progend,
                    101:        segment,
                    102:        space,
                    103:        0,
                    104:        0,
                    105:        0,
                    106:        stabinit,
                    107:        stabline,
                    108:        stabsym,
                    109:        0,
                    110:        {".globl %s\n", 0, 4, {".text", 0, 0, ".rdata", ".rdata" },
                    111:        doarg, docall, blkfetch, blkloop, blkstore,
                    112:        final, 0, emitspecial,
                    113: #ifdef GEN4
                    114:        mips_kids, mips_ntname, mips_nts, mips_rule, mips_state, mips_string, mips_cost,
                    115:        rules, emit2, target
                    116: #endif
                    117:        }
                    118: }, mipselInterface = {
                    119:        "mipsel",
                    120:        1, 1, 0,        /* char */
                    121:        2, 2, 0,        /* short */
                    122:        4, 4, 0,        /* int */
                    123:        4, 4, 1,        /* float */
                    124:        8, 8, 1,        /* double */
                    125:        4, 4, 0,        /* T * */
                    126:        0, 1, 0,        /* struct */
                    127:        1,              /* left_to_right */
                    128:        1,              /* little_endian */
                    129:        1,              /* jump_on_return */
                    130:        0,              /* mulops_are_calls */
                    131:        0,              /* compl_band */
                    132:        0,              /* no_argb */
                    133:        NODAG,          /* no_dag */
                    134:        address,
                    135:        blockbeg,
                    136:        blockend,
                    137:        defaddress,
                    138:        defconst,
                    139:        defstring,
                    140:        defsymbol,
                    141:        0,
                    142:        export,
                    143:        function,
                    144:        gen,
                    145:        global,
                    146:        import,
                    147:        local,
                    148:        progbeg,
                    149:        progend,
                    150:        segment,
                    151:        space,
                    152:        0,
                    153:        0,
                    154:        0,
                    155:        stabinit,
                    156:        stabline,
                    157:        stabsym,
                    158:        0,
                    159:        {".globl %s\n", 0, 4, {".text", 0, 0, ".rdata", ".rdata" },
                    160:        doarg, docall, blkfetch, blkloop, blkstore,
                    161:        final, 0, emitspecial,
                    162: #ifdef GEN4
                    163:        mips_kids, mips_ntname, mips_nts, mips_rule, mips_state, mips_string, mips_cost,
                    164:        rules, emit2, target
                    165: #endif
                    166:        }
                    167: };
                    168: 
                    169: #define nop    0,0,0,0,0
                    170: 
                    171: static unsigned a_def(s1) Symbol s1; {
                    172:        print("%s:\n", s1->x.name);
                    173:        return 0;
                    174: }
                    175: 
                    176: static void a_defaddress(p) Symbol p; {
                    177:        if (p->scope == LABELS)
                    178:                print(".align 2; ");    /* for switch tables */
                    179:        print(".word %s\n", (p)->x.name);
                    180: }
                    181: 
                    182: static unsigned a_emit(op, rs, rt, rd, immed) unsigned op; {
                    183:        int off = immed;
                    184: 
                    185:        switch (op) {
                    186:        case 0:
                    187:                if (immed)
                    188:                        print("sll $%s,$%s,%d\n", ireg[rd]->x.name, ireg[rt]->x.name, immed>>6);
                    189:                else
                    190:                        print("%s", nrflag);
                    191:                break;
                    192:        case o_bgt:     print("bgtz $%d,L.%d\n",    rs, rd);     break;
                    193:        case o_or:      print("or $%d,$%d,$%d\n",   rd, rs, rt); break;
                    194:        case o_sltu:    print("sltu $%d,$%d,$%d\n", rd, rs, rt); break;
                    195:        case o_addu:
                    196:                if (rs == 0)
                    197:                        print("move $%d,$%d\n", rd, rt);
                    198:                else if (rt == 0)
                    199:                        print("move $%d,$%d\n", rd, rs);
                    200:                else
                    201:                        print("addu $%d,$%d,$%d\n", rd, rs, rt);
                    202:                break;
                    203:        case o_addui:   print("addu $%s,$%s,%d\n", ireg[rt]->x.name, ireg[rs]->x.name, immed); break;
                    204:        case o_srli:    print("srl $%s,$%s,%d\n",  ireg[rd]->x.name, ireg[rt]->x.name, immed>>6); break;
                    205:        case o_lbu:     print("lbu $%d,%d($%s)\n",  rt, off, ireg[rs]->x.name); break;
                    206:        case o_lhu:     print("lhu $%d,%d($%s)\n",  rt, off, ireg[rs]->x.name); break;
                    207:        case o_lw:      print("lw $%d,%d($%s)\n",   rt, off, ireg[rs]->x.name); break;
                    208:        case o_lwl:     print("lwl $%d,%d($%s)\n",  rt, off, ireg[rs]->x.name); break;
                    209:        case o_lwr:     print("lwr $%d,%d($%s)\n",  rt, off, ireg[rs]->x.name); break;
                    210:        case o_sb:      print("sb $%d,%d($%s)\n",   rt, off, ireg[rs]->x.name); break;
                    211:        case o_sh:      print("sh $%d,%d($%s)\n",   rt, off, ireg[rs]->x.name); break;
                    212:        case o_sw:      print("sw $%d,%d($%s)\n",   rt, off, ireg[rs]->x.name); break;
                    213:        case o_swl:     print("swl $%d,%d($%s)\n",  rt, off, ireg[rs]->x.name); break;
                    214:        case o_swr:     print("swr $%d,%d($%s)\n",  rt, off, ireg[rs]->x.name); break;
                    215:        case o_l_s:     print("l.s $f%d,%d($%s)\n", rt, off, ireg[rs]->x.name); break;
                    216:        case o_l_d:     print("l.d $f%d,%d($%s)\n", rt, off, ireg[rs]->x.name); break;
                    217:        case o_s_s:     print("s.s $f%d,%d($%s)\n", rt, off, ireg[rs]->x.name); break;
                    218:        case o_s_d:     print("s.d $f%d,%d($%s)\n", rt, off, ireg[rs]->x.name); break;
                    219:        case o_mtc1_s:  print("mtc1 $%d,$f%d\n",    rt, rd); break;
                    220:        case o_mfc1_s:  print("mfc1 $%d,$f%d\n",    rt, rd); break;
                    221:        case o_mtc1_d:  print("mtc1.d $%d,$f%d\n",  rt, rd); break;
                    222:        case o_mfc1_d:  print("mfc1.d $%d,$f%d\n",  rt, rd); break;
                    223:        case o_mov_s:   print("mov.s $f%d,$f%d\n",  immed>>6, rd); break;
                    224:        case o_mov_d:   print("mov.d $f%d,$f%d\n",  immed>>6, rd); break;
                    225:        default:        assert(0);
                    226:        }
                    227:        return rt;
                    228: }
                    229: 
                    230: static void a_end(s1) Symbol s1; {
                    231:        print("j $31\n%s.end %s\n", nrflag, s1->x.name);
                    232: }
                    233: 
                    234: static void a_entry(s1, flabel, framesize) Symbol s1; {
                    235:        segment(CODE);
                    236:        print(".align 2; .ent %s\n", s1->x.name);
                    237:        put.def(s1);
                    238:        print("$fp%d=%d\n.frame $sp,%d,$31\n", flabel, framesize, framesize);
                    239: }
                    240: 
                    241: static int a_offset(i) {
                    242:        return i;
                    243: }
                    244: 
                    245: static void a_symbol(seg, p) Symbol p; {
                    246:        if (seg == DATA)
                    247:                print(".%s; ", p->type->size > gnum || isarray(p->type) ? "data" : "sdata");
                    248:        if (seg == BSS && (p->sclass == STATIC || Aflag >= 2))
                    249:                print(".lcomm %s,", p->x.name);
                    250:        else if (seg == BSS)
                    251:                print(".comm %s,", p->x.name);
                    252:        else {
                    253:                if (p->type->align > 1)
                    254:                        print(".align %c; ", "..1.2...3"[p->type->align]);
                    255:                print("%s:", p->x.name);
                    256:        }
                    257: }
                    258: 
                    259: static void a_word(w, sz) unsigned w; {
                    260:        static char *fmt[] = { 0, ".byte %d\n", ".half %d\n", 0, ".word 0x%x\n" };
                    261: 
                    262:        assert(sz >= 1 && sz < sizeof fmt/sizeof fmt[0] && fmt[sz]);
                    263:        print(fmt[sz], w);
                    264: }
                    265: 
                    266: /* addr - initialize q for addressing expression p+n */
                    267: static void addr(q, p, n) Symbol q, p; {
                    268:        q->x.offset = p->x.offset + n;
                    269:        if (p->scope == GLOBAL || p->sclass == STATIC || p->sclass == EXTERN)
                    270:                q->x.name = stringf("%s%s%d", p->x.name, n >= 0 ? "+" : "", n);
                    271:        else
                    272:                q->x.name = stringf("$fp%d%s%d", flabel,
                    273:                        q->x.offset >= 0 ? "+" : "", q->x.offset);
                    274: }
                    275: 
                    276: static void address(p, q, n) Symbol p, q; {
                    277:        put.addr(p, q, n);
                    278: }
                    279: 
                    280: /* argreg - which register, if any, holds arg at given offset and of given type? */
                    281: Symbol argreg(offset, ty, ty0, varargs) {
                    282:        assert((offset&3) == 0);
                    283:        if (offset > 12)
                    284:                return 0;
                    285:        else if (!varargs && offset == 0 && (ty == F || ty == D))
                    286:                return f12;
                    287:        else if (!varargs && offset == 4 && ty0 == F && ty == F)
                    288:                return f14;
                    289:        else if (!varargs && offset == 8 && ty0 == D && (ty == F || ty == D))
                    290:                return f14;
                    291:        else if (varargs && offset == 0 && ty == D)
                    292:                return d4;
                    293:        else if (offset == 8 && ty == D)
                    294:                return d6;
                    295:        else
                    296:                return ireg[(offset/4) + 4];
                    297: }
                    298: 
                    299: #define BIG (!IR->little_endian)
                    300: 
                    301: /* blkfetch - emit code to load k bytes from reg+off into tmp */
                    302: static void blkfetch(k, off, reg, tmp) {
                    303:        static unsigned ops[] = {0, o_lbu, o_lhu, 0, o_lw};
                    304: 
                    305:        assert(k == 1 || k == 2 || k == 4);
                    306:        if (salign >= k) {
                    307:                put.emit(ops[k], reg, tmp, 0, put.offset(off));
                    308:                put.emit(nop);
                    309:        } else if (k == 2) {
                    310:                put.emit(o_lbu, reg, tmp, 0, put.offset(off+!BIG));
                    311:                if (!bflag)
                    312:                        print(".set noat\n");
                    313:                put.emit(o_lbu, reg, 1,   0, put.offset(off+ BIG));
                    314:                put.emit(o_slli, 0, tmp, tmp, 8<<6);
                    315:                put.emit(o_or, 1, tmp, tmp, 0);
                    316:                if (!bflag)
                    317:                        print(".set at\n");
                    318:        } else {
                    319:                put.emit(o_lwl, reg, tmp, 0, put.offset(off+(BIG?0:3)));
                    320:                put.emit(o_lwr, reg, tmp, 0, put.offset(off+(BIG?3:0)));
                    321:                put.emit(nop);
                    322:        }
                    323: }
                    324: 
                    325: /* blkloop - emit loop to copy size bytes from sreg+soff to dreg+doff using tmp regs */
                    326: static void blkloop(dreg, doff, sreg, soff, size, tmp) int tmp[]; {
                    327:        struct symbol lab;
                    328:        unsigned pc1;
                    329: 
                    330:        BZERO(&lab, struct symbol);
                    331:        lab.u.l.label = genlabel(1);
                    332:        lab.name = stringd(lab.u.l.label);
                    333:        lab.scope = LABELS;
                    334:        lab.generated = 1;
                    335:        defsymbol(&lab);
                    336:        put.emit(o_addui, sreg, sreg,   0, size&~7);
                    337:        put.emit(o_addui, dreg, tmp[2], 0, size&~7);
                    338:        blkcopy(tmp[2], doff, sreg, soff, size&7, tmp);
                    339:        put.def(&lab);
                    340:        pc1 = symeaddr(&lab);
                    341:        put.emit(o_addui, sreg,   sreg,   0, put.offset(-8));
                    342:        put.emit(o_addui, tmp[2], tmp[2], 0, put.offset(-8));
                    343:        blkcopy(tmp[2], doff, sreg, soff, 8, tmp);
                    344:        if (!bflag)
                    345:                print(".set noat\n");
                    346:        put.emit(o_sltu, dreg, tmp[2], 1, 0);
                    347:        if (bflag) {
                    348:                symeaddr(&lab) = 0;
                    349:                put.def(&lab);
                    350:        }
                    351:        put.emit(o_bgt, 1, 0, bflag ? 0 : lab.u.l.label,
                    352:                put.offset((int)(pc1 - (symeaddr(&lab) + 4))>>2));
                    353:        put.emit(nop);
                    354:        if (!bflag)
                    355:                print(".set at\n");
                    356: }
                    357: 
                    358: /* blkstore - emit code to store k bytes from tmp to reg+off */
                    359: static void blkstore(k, off, reg, tmp) {
                    360:        static unsigned ops[] = {0, o_sb, o_sh, 0, o_sw};
                    361: 
                    362:        assert(k == 1 || k == 2 || k == 4);
                    363:        if (dalign >= k)
                    364:                put.emit(ops[k], reg, tmp, 0, put.offset(off));
                    365:        else if (k == 2) {
                    366:                if (!bflag)
                    367:                        print(".set noat\n");
                    368:                put.emit(o_srli, 0, tmp, 1, 8<<6);
                    369:                put.emit(o_sb, reg, 1,   0, put.offset(off+!BIG));
                    370:                if (!bflag)
                    371:                        print(".set at\n");
                    372:                put.emit(o_sb, reg, tmp, 0, put.offset(off+ BIG));
                    373:        } else {
                    374:                put.emit(o_swl, reg, tmp, 0, put.offset(off+(BIG?0:3)));
                    375:                put.emit(o_swr, reg, tmp, 0, put.offset(off+(BIG?3:0)));
                    376:        }
                    377: }
                    378: 
                    379: static void defaddress(p) Symbol p; {
                    380:        put.defaddr(p);
                    381: }
                    382: 
                    383: /* defconst - define a constant */
                    384: static void defconst(ty, v) Value v; {
                    385:        struct real r;
                    386: 
                    387:        switch (ty) {
                    388:        case C: put.word(v.uc, 1); break;
                    389:        case S: put.word(v.ss, 2); break;
                    390:        case I: put.word(v.i,  4); break;
                    391:        case U: put.word(v.u,  4); break;
                    392:        case P: put.word((unsigned int)v.p, 4); break;
                    393:        case F:
                    394:                r = decode(F, v.f);
                    395:                if (v.f)
                    396:                        r.exp = (r.exp + 127)&0xff;
                    397:                put.word((r.sign<<31) | (r.exp<<23) | (r.msb>>9), 4);
                    398:                break;
                    399:        case D:
                    400:                r = decode(D, v.d);
                    401:                if (v.d)
                    402:                        r.exp = (r.exp + 1023)&0x7ff;
                    403:                if (IR->little_endian) {
                    404:                        put.word(( r.msb<<20) | (r.lsb>>12), 4);
                    405:                        put.word((r.sign<<31) | (r.exp<<20) | (r.msb>>12), 4);
                    406:                } else {
                    407:                        put.word((r.sign<<31) | (r.exp<<20) | (r.msb>>12), 4);
                    408:                        put.word(( r.msb<<20) | (r.lsb>>12), 4);
                    409:                }
                    410:                break;
                    411:        default:
                    412:                assert(0);
                    413:        }
                    414: }
                    415: 
                    416: static void defstring(n, s) char *s; {
                    417:        put.string(".ascii", ".byte", n, s);
                    418: }
                    419: 
                    420: /* defsymbol - compute and store p's back-end name */
                    421: static void defsymbol(p) Symbol p; {
                    422:        if (p->scope >= LOCAL && p->sclass == STATIC)
                    423:                p->x.name = stringf("L.%d", genlabel(1));
                    424:        else if (p->generated)
                    425:                p->x.name = stringf("L.%s", p->name);
                    426:        else
                    427:                p->x.name = p->name;
                    428: }
                    429: 
                    430: dclproto(static Node iscall,(Node));
                    431: 
                    432: static Node iscall(q) Node q; {
                    433:        if (generic(q->op) == CALL)
                    434:                return q;
                    435:        else if (IR->no_dag && generic(q->op) == ASGN && generic(q->kids[1]->op) == CALL)
                    436:                return q->kids[1];
                    437:        else
                    438:                return 0;
                    439: }
                    440: 
                    441: /* doarg - assign offset for next ARG node */
                    442: static void doarg(p) Node p; {
                    443:        Symbol tmp;
                    444: 
                    445:        if (argoffset == 0) {
                    446:                Node call, q = p->link;
                    447:                while ((call = iscall(q)) == 0)
                    448:                        q = q->link;
                    449:                assert(generic(call->op) == CALL && call->syms[0]);
                    450:                if (variadic(call->syms[0]->type))
                    451:                        for (q = p; !iscall(q); q = q->link)
                    452:                                if (generic(q->op) == ARG)
                    453:                                        q->x.isvararg = 1;
                    454:                if (optype(call->op) == B)
                    455:                        argoffset = 4;
                    456:        }
                    457:        tmp = p->syms[0];
                    458:        p->syms[0] = intconst(mkactual(p->syms[1]->u.c.v.i, p->syms[0]->u.c.v.i, 4));
                    459:        p->syms[2] = p->syms[1];
                    460:        p->syms[1] = tmp;       /* xc=S0 */
                    461: }
                    462: 
                    463: #ifdef GEN4
                    464: char **opcodes;        /* dreg to get what's below to compile */
                    465: #endif
                    466: 
                    467: static void emitspecial(p) Node p; {
                    468: 
                    469:        if (genx == 4 ? (p->op == ARGB) : !strcmp(opcodes[p->op], "# argb"))
                    470:                emitargb(p);
                    471:        else if (genx == 4 ? (p->op == ASGNB) : !strcmp(opcodes[p->op], "# asgnb"))
                    472:                emitasgnb(p);
                    473: }
                    474: 
                    475: void emitargb(p) Node p; {
                    476:        static int tmp[] = { 2, 3, 8 };
                    477: 
                    478:        int dst, n = p->syms[0]->u.c.v.i + p->syms[1]->u.c.v.i;
                    479:        dalign = 4;
                    480:        salign = p->syms[2]->u.c.v.i;
                    481:        blkcopy(29, p->syms[0]->u.c.v.i,
                    482:                getregnode(p->kids[0]->syms[RX])->regnum, 0, p->syms[1]->u.c.v.i, tmp);
                    483:        for (dst = p->syms[0]->u.c.v.i; dst <= 12 && dst < n; dst += 4)
                    484:                put.emit(o_lw, r_sp, dst/4+4, 0, put.offset(dst));
                    485:        if (p->syms[0]->u.c.v.i <= 12)
                    486:                put.emit(nop);
                    487: }
                    488: 
                    489: void emitasgnb(p) Node p; {
                    490:        static int tmp[] = { 2, 3, 8 };
                    491: 
                    492:        dalign = salign = p->syms[1]->u.c.v.i;
                    493:        blkcopy(getregnode(p->kids[0]->syms[RX])->regnum, 0,
                    494:                getregnode(p->kids[1]->syms[RX])->regnum, 0, p->syms[0]->u.c.v.i, tmp);
                    495: }
                    496: 
                    497: /* function - generate code for a function */
                    498: static void function(f, caller, callee, n) Symbol f, callee[], caller[]; {
                    499:        int i, lbase, varargs;
                    500:        Symbol p, q, r, argireg[4];
                    501:        int ty0 = caller[0] ? ttob(caller[0]->type) : I;
                    502: 
                    503:        initfunc(n, 0, 0);
                    504:        for (i = 0; callee[i]; i++)
                    505:                ;
                    506:        varargs = variadic(f->type) || i > 0 && strcmp(callee[i-1]->name, "va_alist") == 0;
                    507:        flabel++;
                    508:        if (isstruct(freturn(f->type))) {
                    509:                offset = 4;
                    510:                ty0 = I;
                    511:        }
                    512:        for (i = 0; p = callee[i]; i++) {
                    513:                q = caller[i];
                    514:                assert(q);
                    515:                offset = roundup(offset, q->type->align);
                    516:                p->x.offset = q->x.offset = offset;
                    517:                p->x.name = q->x.name = stringf("$fp%d+%d", flabel, offset);
                    518:                r = argreg(offset, ttob(q->type), ty0, varargs);
                    519:                if (i < 4)
                    520:                        argireg[i] = r;
                    521:                offset = roundup(offset + q->type->size, 4);
                    522:                if (varargs)
                    523:                        p->sclass = AUTO;
                    524:                else if (
                    525:                        r &&
                    526:                        ncalls == 0 &&
                    527:                        !isstruct(q->type) &&
                    528:                        !p->addressed &&
                    529:                        (!isfloat(q->type) || r->x.regnode->regset == FREG)
                    530:                ) {
                    531:                        p->x.regvar = q->x.regvar = r;
                    532:                        p->x.name = q->x.name = r->x.name;
                    533:                        p->sclass = q->sclass = REGISTER;
                    534:                        if (!isfloat(p->type))
                    535:                                q->type = p->type;
                    536:                } else if (
                    537:                        getregvar(p, rmap[ttob(p->type)]) &&
                    538:                        r &&
                    539:                        (isint(p->type) || p->type == q->type)
                    540:                ) {
                    541:                        assert(p->x.regvar != r);
                    542:                        q->sclass = REGISTER;
                    543:                        q->type = p->type;
                    544:                }
                    545:        }
                    546:        assert(caller[i] == 0);
                    547:        offset = 0;
                    548:        gencode(caller, callee);
                    549:        mvregvars();
                    550:        if (ncalls)
                    551:                usedmask[IREG] |= 1<<31;
                    552:        usedmask[IREG] &= eemask[IREG];
                    553:        usedmask[FREG] &= eemask[FREG];
                    554:        if (argbuildsize && argbuildsize < 16)
                    555:                argbuildsize = 16;
                    556:        savemask[FREG] = usedmask[FREG]; savemask[IREG] = usedmask[IREG];
                    557:        savebase[FREG] = argbuildsize; savebase[IREG] = savebase[FREG] + 4*bitcount(usedmask[FREG]);
                    558:        lbase = savebase[IREG] + 4*bitcount(usedmask[IREG]);
                    559:        framesize = roundup(lbase + maxoffset, 8);
                    560:        put.entry(f, flabel, framesize);
                    561:        for (i = 0; p = callee[i]; i++) {
                    562:                if (p->sclass == REGISTER) {
                    563:                        assert(p->x.regvar && p->x.regvar->x.regnode);
                    564:                        symeaddr(p) = p->x.regvar->x.regnode->regnum;
                    565:                        }
                    566:                }
                    567:        if (framesize > 0)
                    568:                put.emit(o_addui, r_sp, r_sp, 0, put.offset(-framesize));
                    569:        if (usedmask[FREG]) {
                    570:                if (!bflag)
                    571:                        print(".fmask 0x%x,%d\n", usedmask[FREG], savebase[IREG] - framesize - 8);
                    572:                funcsave(o_s_d, 20, 30, 2, usedmask[FREG], 3, savebase[FREG]);
                    573:        }
                    574:        if (usedmask[IREG]) {
                    575:                if (!bflag)
                    576:                        print(".mask 0x%x,%d\n", usedmask[IREG], lbase - framesize - 4);
                    577:                funcsave(o_sw, 16, 31, 1, usedmask[IREG], 1, savebase[IREG]);
                    578:        }
                    579:        if (isstruct(freturn(f->type)))
                    580:                put.emit(o_sw, r_sp, 4, 0, put.offset(framesize - 4));
                    581:        for (i = 0; i < 4 && callee[i]; i++)
                    582:                if ((r = argireg[i]) && (varargs || r != callee[i]->x.regvar))
                    583:                        storearg(callee[i], caller[i], r);
                    584:        if (varargs && r)
                    585:                for (i = r->x.regnode->regnum + (r == d4 || r == d6); i <= 6; i++)
                    586:                        put.emit(o_sw, r_sp, i + 1, 0, put.offset(framesize + 4*(i - 3)));
                    587:        emitcode();
                    588:        if (usedmask[FREG]) {
                    589:                funcsave(o_l_d, 20, 30, 2, usedmask[FREG], 3, savebase[FREG]);
                    590:                put.emit(nop);
                    591:        }
                    592:        if (usedmask[IREG]) {
                    593:                funcsave(o_lw, 16, 31, 1, usedmask[IREG], 1, savebase[IREG]);
                    594:                put.emit(nop);
                    595:        }
                    596:        if (framesize > 0)
                    597:                put.emit(o_addui, r_sp, r_sp, 0, put.offset(framesize));
                    598:        put.end(f);
                    599: }
                    600: 
                    601: /* funcsave - generate register save/restore sequences */
                    602: static void funcsave(op, lo, hi, inc, used, mask, base) unsigned used, mask; {
                    603:        for (; lo <= hi; lo += inc)
                    604:                if ((used>>lo)&mask) {
                    605:                        put.emit(op, r_sp, lo, 0, put.offset(base));
                    606:                        base += 4*inc;
                    607:                }
                    608: }
                    609: 
                    610: static void global(p) Symbol p; {
                    611:        assert(p->u.seg);
                    612:        put.symbol(p->u.seg, p);
                    613: }
                    614: 
                    615: /* import - import a symbol */
                    616: static void import(p) Symbol p; {
                    617:        if (!isfunc(p->type) && !bflag)
                    618:                print(".extern %s %d\n", p->name,
                    619:                        isarray(p->type) ? 0 : p->type->size);
                    620: }
                    621: 
                    622: /* local - local */
                    623: static void local(p) Symbol p; {
                    624:        if (getregvar(p, rmap[ttob(p->type)]) == 0) {
                    625:                int offset = mkauto(p, p->type->align);
                    626:                p->x.name = stringf("$fp%d%d", flabel, offset);
                    627:        }
                    628: }
                    629: 
                    630: /* progbeg - beginning of program */
                    631: static void progbeg(argc, argv) char *argv[]; {
                    632:        int i;
                    633: 
                    634:        nregsets = 2;
                    635:        eemask[IREG] = 0xc0ff0000; eemask[FREG] = 0xfff00000;
                    636:        tmask[IREG]  = 0x0300ffff; tmask[FREG]  = 0x000f0fff;
                    637:        vmask[IREG]  = 0x40ff0000; vmask[FREG]  = 0xfff00000;
                    638:        parseflags(argc, argv);
                    639:        for (i = 0; i < argc; i++)
                    640:                if (strncmp(argv[i], "-G", 2) == 0)
                    641:                        gnum = atoi(argv[i] + 2);
                    642: #if BINARY
                    643:                else if (strcmp(argv[i], "-binary") == 0) {
                    644:                        dclproto(extern unsigned (*emitter),(Node, int));
                    645:                        dclproto(extern unsigned emitbin,(Node, int));
                    646:                        extern struct emit bput;
                    647:                        bflag = 1;
                    648:                        put = bput;
                    649:                        emitter = emitbin;
                    650:                }
                    651: #endif
                    652:                else if (strcmp(argv[i], "-noreorder") == 0) {
                    653:                        nrflag = "nop\n";
                    654: #ifdef GEN4
                    655:                        addnops();
                    656: #endif
                    657:                }
                    658:        initgen();
                    659:        for (i = 0; i < 32; i++)
                    660:                ireg[i] = mkregs("%d",  i,  i, 1, 1, IREG, I, 0);
                    661:        ireg[29]->x.name = "sp";
                    662:        d4      = mkregs("%d",  4,  4, 1, 3, IREG, V, 0);
                    663:        d6      = mkregs("%d",  6,  6, 1, 3, IREG, V, 0);
                    664:        f0      = mkregs("%d",  0,  0, 1, 3, FREG, D, 0);
                    665:        f12     = mkregs("%d", 12, 12, 1, 3, FREG, D, 0);
                    666:        f14     = mkregs("%d", 14, 14, 1, 3, FREG, D, 0);
                    667:        rmap[I] = mkregs("%d",  2,  2, 1, 1, IREG, I, rmap[I]);
                    668:        rmap[I] = mkregs("%d",  8, 25, 1, 1, IREG, I, rmap[I]);
                    669:        rmap[I] = mkregs("%d", 30, 30, 1, 1, IREG, I, rmap[I]);
                    670:        rmap[D] = mkregs("%d",  4, 10, 2, 3, FREG, D, rmap[D]);
                    671:        rmap[D] = mkregs("%d", 16, 30, 2, 3, FREG, D, rmap[D]);
                    672:        rmap[F] = rmap[D]; rmap[C] = rmap[S] = rmap[P] = rmap[U] = rmap[I];
                    673:        rmap[F] = rmap[D]; rmap[C] = rmap[S] = rmap[P] = rmap[U] = rmap[I];
                    674:        if (!bflag)
                    675:                print(".set %sreorder\n", *nrflag ? "no" : "");
                    676: }
                    677: 
                    678: static void segment(n) {
                    679:        put.seg(n);
                    680: }
                    681: 
                    682: static void space(n) {
                    683:        put.spacen(n, ".space");
                    684: }
                    685: 
                    686: /* storearg - emit a store for an argument in register r. p is callee, q caller */
                    687: static void storearg(p, q, r) Symbol p, q, r; {
                    688:        int pn, rn;
                    689: 
                    690:        assert(r && r->x.regnode);
                    691:        rn = r->x.regnode->regnum;
                    692:        if (p->sclass == REGISTER && (isint(p->type) || p->type == q->type)) {
                    693:                assert(p && p->x.regvar && p->x.regvar->x.regnode);
                    694:                pn = p->x.regvar->x.regnode->regnum;
                    695:                if (!isfloat(q->type))
                    696:                        put.emit(o_move, rn, 0, pn, 0);
                    697:                else if (r->x.regnode->regset == FREG) {
                    698:                        put.emit(ttob(q->type) == D ? o_mov_d : o_mov_s, 0, 0, rn, pn<<6);
                    699:                        put.emit(nop);
                    700:                } else
                    701:                        put.emit(ttob(q->type) == D ? o_mtc1_d : o_mtc1_s, 0, rn, pn, 0);
                    702:        } else {
                    703:                if (!isfloat(q->type)) {
                    704:                        int n = (q->type->size - 1)/4;
                    705:                        if (n > '7' - *r->x.name)
                    706:                                n = '7' - *r->x.name;
                    707:                        for ( ; n >= 0; n--)
                    708:                                put.emit(o_sw, r_sp, rn+n, 0, put.offset(q->x.offset + framesize + n*4));
                    709:                        put.emit(nop);
                    710:                } else if (r->x.regnode->regset == FREG) {
                    711:                        put.emit(ttob(q->type) == D ? o_s_d : o_s_s, r_sp, rn, 0,
                    712:                                put.offset(q->x.offset + framesize));
                    713:                        put.emit(nop);
                    714:                } else {
                    715:                        put.emit(o_sw, r_sp, rn, 0, put.offset(q->x.offset + framesize));
                    716:                        if (ttob(q->type) == D)
                    717:                                put.emit(o_sw, r_sp, rn + 1, 0, put.offset(q->x.offset + framesize + 4));
                    718:                        put.emit(nop);
                    719:                }
                    720:        }
                    721: }
                    722: 
                    723: static char *currentfile;
                    724: 
                    725: /* stabinit - initialize stab output */
                    726: static void stabinit(file, argc, argv) char *file, *argv[]; {
                    727:        if (file) {
                    728:                print(".file 2,\"%s\"\n", file);
                    729:                currentfile = file;
                    730:        }
                    731: }
                    732: 
                    733: /* stabline - emit stab entry for source coordinate *cp */
                    734: static void stabline(cp) Coordinate *cp; {
                    735:        if (cp->file && cp->file != currentfile) {
                    736:                print(".file 2,\"%s\"\n", cp->file);
                    737:                currentfile = cp->file;
                    738:        }
                    739:        print(".loc 2,%d\n", cp->y);
                    740: }
                    741: 
                    742: /* stabsym - output a stab entry for symbol p */
                    743: static void stabsym(p) Symbol p; {
                    744:        if (p == cfunc && IR->stabline)
                    745:                (*IR->stabline)(&p->src);
                    746: }

unix.superglobalmegacorp.com

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