Annotation of researchv10no/cmd/lcc/gen2/mips/pseudos.c, revision 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.