Annotation of researchv9/jerq/sgs/as/gencode.c, revision 1.1

1.1     ! root        1: static char *ID_gencode="@(#) gencode.c: 1.22 5/8/84";
        !             2: #include <stdio.h>
        !             3: #include "systems.h"
        !             4: #include "symbols.h"
        !             5: #include "instab.h"
        !             6: #include "parse.h"
        !             7: #include "gendefs.h"
        !             8: #include "expand.h"
        !             9: #include "expand2.h"
        !            10: 
        !            11: long
        !            12:        swap_b2(),
        !            13:        swap_b4();
        !            14: extern upsymins
        !            15:        *lookup();
        !            16: extern short
        !            17:        opt;    /* no optimize flag */
        !            18: extern unsigned short
        !            19:        line;   /* current line number */
        !            20: 
        !            21: addrgen(insptr,addr,expand,opnum)
        !            22: register instr
        !            23:        *insptr;
        !            24: register addrmode
        !            25:        *addr;
        !            26: short  expand, opnum;
        !            27: {
        !            28:        long    val;
        !            29:        register short reg;
        !            30: 
        !            31:                /* check if USER specified an expand byte */
        !            32:                /* check if USER specified an operand specifier */
        !            33:        if (insptr->tag & IS25) {
        !            34:                if (addr->newtype != NOTYPE)
        !            35:                        yyerror("Expand byte invalid in IS25 instruction");
        !            36:                if (addr->expspec != NULLSPEC)
        !            37:                        yyerror("Operand specifier invalid in IS25 instruction");
        !            38:        } else
        !            39:                expand = addr->newtype;
        !            40:        if (expand != NOTYPE)
        !            41:                generate(8,NOACTION,(long)((CEXPAND<<4)|expand),NULLSYM);
        !            42: 
        !            43:        switch(addr->admode) {
        !            44: 
        !            45:        case REGDFMD: /* register deferred mode */
        !            46:                reg = addr->adreg;
        !            47:                if (reg != PCREG) {
        !            48:                        generate(8,NOACTION,(long)((CREGDFMD<<4)|reg),NULLSYM);
        !            49:                } else {
        !            50:                        yyerror("Register deferred mode illegal with register 15 (%pc).");
        !            51:                }
        !            52:                return;
        !            53: 
        !            54:        case DSPMD: /* displacement mode */
        !            55:                val = addr->adexpr.expval;
        !            56:                reg = addr->adreg;
        !            57:                if ((addr->adexpr.symptr ==  NULLSYM)
        !            58:                    && (addr->expspec == NULLSPEC)
        !            59:                    && opt) {
        !            60:                     /* No operand specifier, and optimization allowed, and
        !            61:                        symbol ptr is null */
        !            62:                        if ((val == 0) && (reg != PCREG)) {
        !            63:                                /* register deferred mode */
        !            64:                                /* not legal for register 15 or PC */
        !            65:                                generate(8,NOACTION,(long)((CREGDFMD<<4)|reg),
        !            66:                                        NULLSYM);
        !            67:                                return;
        !            68:                        } /* register deferred mode */
        !            69:  
        !            70:                        if ((reg == APREG) && (0 <= val && val <= 14)) {
        !            71:                                 /* AP displacement mode */
        !            72:                                generate(8,NOACTION,(CAPDSPMD<<4)|val,NULLSYM);
        !            73:                                return;
        !            74:                        } /* AP displacement mode */
        !            75: 
        !            76:                        if ((reg == FPREG) && (0 <= val && val <= 14)) {
        !            77:                                 /* FP displacement mode */
        !            78:                                generate(8,NOACTION,(CFPDSPMD<<4)|val,NULLSYM);
        !            79:                                return;
        !            80:                        } /* FP displacement mode */
        !            81:  
        !            82:                        if (-(1<<7) <= val && val < 1<<7) {
        !            83:                                /* byte displacement mode */
        !            84:                                generate(8,NOACTION,(long)((CBDSPMD<<4)|reg),
        !            85:                                        NULLSYM);
        !            86:                                generate(8,NOACTION,val,NULLSYM);
        !            87:                                return;
        !            88:                        } /* byte displacement mode */
        !            89:                        if (-(1L<<15) <= val && val < 1L<<15) {
        !            90:                                /* halfword displacement mode */
        !            91:                                generate(8,NOACTION,(long)((CHDSPMD<<4)|reg),
        !            92:                                        NULLSYM);
        !            93:                                generate(16,NOACTION,swap_b2(val),NULLSYM);
        !            94:                                return;
        !            95:                        } /* halfword displacement mode */
        !            96:                        /* Otherwise use word displacement mode */
        !            97:                        generate(8,NOACTION,(long)((CDSPMD<<4)|reg),NULLSYM);
        !            98:                        generate(32,NOACTION,swap_b4(val),NULLSYM);
        !            99:                        return;
        !           100:                } /* addr->adexpr.symptr == NULLSYM */
        !           101: 
        !           102:                if ( (addr->adexpr.symptr != NULLSYM) 
        !           103:                     || ((!opt) && (addr->expspec == NULLSPEC))) {
        !           104:                        /* don't know displacement;
        !           105:                                 must use word displacement mode */
        !           106:                        generate(8,NOACTION,(long)((CDSPMD<<4)|reg),NULLSYM);
        !           107:                        generate(32,RELDIR32,val,addr->adexpr.symptr);
        !           108:                        return;
        !           109:                } 
        !           110: 
        !           111:                /* At this point the user must be specifying the operand 
        !           112:                   expression size through the use of an operand specifier.
        !           113:                   Generate the correct operand. */
        !           114: 
        !           115:                switch ( addr->expspec ) {
        !           116: 
        !           117:                case BYTESPEC:
        !           118:                        if ( (unsigned) val >= (1<<8)) {
        !           119:                                yyerror("Expression larger than byte.");
        !           120:                        } else {
        !           121:                                /* byte displacement mode */
        !           122:                                generate(8,NOACTION,(long)((CBDSPMD<<4)|reg),
        !           123:                                         NULLSYM);
        !           124:                                generate(8,NOACTION,val,NULLSYM);
        !           125:                        }
        !           126:                        return;
        !           127: 
        !           128:                case HALFSPEC:
        !           129:                        if ( (unsigned) val >= (1<<16)) {
        !           130:                                yyerror("Expression larger than halfword.");
        !           131:                        } else {
        !           132:                                /* halfword displacement mode */
        !           133:                                generate(8,NOACTION,(long)((CHDSPMD<<4)|reg),
        !           134:                                         NULLSYM);
        !           135:                                generate(16,NOACTION,swap_b2(val),NULLSYM);
        !           136:                        }
        !           137:                        return;
        !           138: 
        !           139:                case WORDSPEC:
        !           140:                        generate(8,NOACTION,(long)((CDSPMD<<4)|reg),NULLSYM);
        !           141:                        generate(32,NOACTION,swap_b4(val),NULLSYM);
        !           142:                        return;
        !           143: 
        !           144:                case SHORTSPEC:
        !           145:                        if (0 > val || val > 14) {
        !           146:                                yyerror("Expression outside short offset range.");
        !           147:                                return;
        !           148:                        }
        !           149:                        if (reg == APREG) {
        !           150:                                 /* AP displacement mode */
        !           151:                                generate(8,NOACTION,(CAPDSPMD<<4)|val,NULLSYM);
        !           152:                                return;
        !           153:                        } /* AP short offset */
        !           154: 
        !           155:                        if (reg == FPREG) {
        !           156:                                 /* FP displacement mode */
        !           157:                                generate(8,NOACTION,(CFPDSPMD<<4)|val,NULLSYM);
        !           158:                                return;
        !           159:                        } /* FP displacement mode */
        !           160: 
        !           161:                        yyerror("Illegal register for short offset address mode.");
        !           162:                        return;
        !           163: 
        !           164:                default:
        !           165:                        yyerror("Illegal operand specifier for displacement address mode.");
        !           166:                        return;
        !           167: 
        !           168:                } /* switch */
        !           169: 
        !           170:        case DSPDFMD: /* displacement deferred mode */
        !           171:                val = addr->adexpr.expval;
        !           172:                reg = addr->adreg;
        !           173:                if ( (addr->adexpr.symptr ==  NULLSYM)
        !           174:                     && (addr->expspec == NULLSPEC)
        !           175:                     &&  opt) {
        !           176:                        if (-(1<<7) <= val && val < 1<<7) {
        !           177:                                /* byte displacement deferred mode */
        !           178:                                generate(8,NOACTION,(long)((CBDSPDFMD<<4)|reg),
        !           179:                                        NULLSYM);
        !           180:                                generate(8,NOACTION,val,NULLSYM);
        !           181:                                return;
        !           182:                        } /* byte displacement deferred mode */
        !           183:                        if (-(1L<<15) <= val && val < 1L<<15) {
        !           184:                                /* halfword displacement deferred mode */
        !           185:                                generate(8,NOACTION,(long)((CHDSPDFMD<<4)|reg),
        !           186:                                        NULLSYM);
        !           187:                                generate(16,NOACTION,swap_b2(val),NULLSYM);
        !           188:                                return;
        !           189:                        } /* halfword displacement deferred mode */
        !           190:                        /* Otherwise use word displacement deferred mode */
        !           191:                        generate(8,NOACTION,(long)((CDSPDFMD<<4)|reg),NULLSYM);
        !           192:                        generate(32,NOACTION,swap_b4(val),NULLSYM);
        !           193:                        return;
        !           194:                } /* addr->adexpr.symptr == NULLSYM */
        !           195: 
        !           196:                if ( (addr->adexpr.symptr != NULLSYM)
        !           197:                     || ((!opt) && (addr->expspec == NULLSPEC))) {
        !           198: 
        !           199:                        /* don't know displacement;
        !           200:                                must use word displacement deferred mode */
        !           201:                        generate(8,NOACTION,(long)((CDSPDFMD<<4)|reg),NULLSYM);
        !           202:                        generate(32,RELDIR32,val,addr->adexpr.symptr);
        !           203:                        return;
        !           204:                }
        !           205: 
        !           206:                /* At this point the user must be specifying the operand
        !           207:                   expression size through the use of an operand specifier.
        !           208:                   Generate the correct operand. */
        !           209: 
        !           210:                switch ( addr->expspec ) {
        !           211: 
        !           212:                case BYTESPEC:
        !           213:                        if ( (unsigned) val >= (1<<8)) {
        !           214:                                yyerror("Expression larger than byte.");
        !           215:                        } else {
        !           216:                                /* byte displacement deferred mode */
        !           217:                                generate(8,NOACTION,(long)((CBDSPDFMD<<4)|reg),
        !           218:                                        NULLSYM);
        !           219:                                generate(8,NOACTION,val,NULLSYM);
        !           220:                        }
        !           221:                        return;
        !           222: 
        !           223:                case HALFSPEC:
        !           224:                        if ( (unsigned) val >= (1<<16)) {
        !           225:                                yyerror("Expression larger than halfword.");
        !           226:                        } else {
        !           227:                                /* halfword displacement deferred mode */
        !           228:                                generate(8,NOACTION,(long)((CHDSPDFMD<<4)|reg),
        !           229:                                        NULLSYM);
        !           230:                                generate(16,NOACTION,swap_b2(val),NULLSYM);
        !           231:                        }
        !           232:                        return;
        !           233: 
        !           234:                case WORDSPEC:
        !           235:                        generate(8,NOACTION,(long)((CDSPDFMD<<4)|reg),NULLSYM);
        !           236:                        generate(32,NOACTION,swap_b4(val),NULLSYM);
        !           237:                        return;
        !           238: 
        !           239:                default:
        !           240:                        yyerror("Illegal operand specifier for displacement deferred address mode.");
        !           241:                        return;
        !           242: 
        !           243:                } /* switch */
        !           244: 
        !           245:        case EXADMD: /* external address mode */
        !           246:        case ABSMD: /* absolute address mode */
        !           247:                generate(8,NOACTION,(long)(CABSMD),NULLSYM);
        !           248:                generate(32,RELDIR32,addr->adexpr.expval,addr->adexpr.symptr);
        !           249:                return;
        !           250: 
        !           251:        case EXADDFMD: /* external address deferred mode (PC relative deferred) */
        !           252:        case ABSDFMD: /* absolute address deferred mode */
        !           253:                generate(8,NOACTION,(long)(CABSDFMD),NULLSYM);
        !           254:                generate(32,RELDIR32,addr->adexpr.expval,addr->adexpr.symptr);
        !           255:                return;
        !           256: 
        !           257:        case IMMD: /* immediate mode */
        !           258:                val = addr->adexpr.expval;
        !           259:                if ( (addr->adexpr.symptr ==  NULLSYM)
        !           260:                     && (addr->expspec == NULLSPEC)
        !           261:                     &&  opt) {
        !           262:                        if ( val < 0 ) {
        !           263:                                if ( (insptr->tag & IS25) &&
        !           264:                                     (insptr->name[0] == 'u') )
        !           265:                                {
        !           266:                                   generate(8,NOACTION,(long)CIMMD,NULLSYM);
        !           267:                                   generate(32,NOACTION,swap_b4(val),NULLSYM);
        !           268:                                   return;
        !           269:                                }
        !           270:                        }
        !           271:  
        !           272:                        if (-(1<<4) <= val && val < 1<<6) {
        !           273:                                generate(8,NOACTION,val,NULLSYM);
        !           274:                                return;
        !           275:                        }
        !           276:  
        !           277:                        if (-(1<<7) <= val && val < 1<<7) {
        !           278:                                /* byte immediate mode */
        !           279:                                generate(8,NOACTION,(long)CBIMMD,NULLSYM);
        !           280:                                generate(8,NOACTION,val,NULLSYM);
        !           281:                                return;
        !           282:                        } /* byte immediate mode */
        !           283:                        if (-(1L<<15) <= val && val < 1L<<15) {
        !           284:                                /* halfword immediate mode */
        !           285:                                generate(8,NOACTION,(long)CHIMMD,NULLSYM);
        !           286:                                generate(16,NOACTION,swap_b2(val),NULLSYM);
        !           287:                                return;
        !           288:                        } /* halfword immediate mode */
        !           289:                        /* Otherwise use fullword immediate mode */
        !           290:                        generate(8,NOACTION,(long)CIMMD,NULLSYM);
        !           291:                        generate(32,NOACTION,swap_b4(val),NULLSYM);
        !           292:                        return;
        !           293:                } /* addr->adexpr.symptr == NULLSYM */
        !           294: 
        !           295:                if ( (addr->adexpr.symptr != NULLSYM)
        !           296:                     || ((!opt) && (addr->expspec == NULLSPEC))) {
        !           297: 
        !           298:                        /* don't know value; 
        !           299:                                must use fullword immediate mode */
        !           300:                        generate(8,NOACTION,(long)CIMMD,NULLSYM);
        !           301:                        generate(32,RELDIR32,val,addr->adexpr.symptr);
        !           302:                        return;
        !           303:                }
        !           304: 
        !           305:                /* At this point the user must be specifying the operand
        !           306:                   expression size through the use of an operand specifier.
        !           307:                   Generate the correct operand. */
        !           308: 
        !           309:                switch ( addr->expspec ) {
        !           310: 
        !           311:                case BYTESPEC:
        !           312:                        if ( (unsigned) val >= (1<<8)) {
        !           313:                                yyerror("Expression larger than byte.");
        !           314:                        } else {
        !           315:                                /* byte immediate mode */
        !           316:                                generate(8,NOACTION,(long)CBIMMD,NULLSYM);
        !           317:                                generate(8,NOACTION,val,NULLSYM);
        !           318:                        }
        !           319:                        return;
        !           320: 
        !           321:                case HALFSPEC:
        !           322:                        if ( (unsigned) val >= (1<<16)) {
        !           323:                                yyerror("Expression larger than halfword.");
        !           324:                        } else {
        !           325:                                /* halfword immediate mode */
        !           326:                                generate(8,NOACTION,(long)CHIMMD,NULLSYM);
        !           327:                                generate(16,NOACTION,swap_b2(val),NULLSYM);
        !           328:                        }
        !           329:                        return;
        !           330: 
        !           331:                case WORDSPEC:
        !           332:                        /* fullword immediate mode */
        !           333:                        generate(8,NOACTION,(long)CIMMD,NULLSYM);
        !           334:                        generate(32,NOACTION,swap_b4(val),NULLSYM);
        !           335:                        return;
        !           336: 
        !           337:                case LITERALSPEC:
        !           338:                        if (-(1<<4) <= val && val < 1<<6) {
        !           339:                                generate(8,NOACTION,val,NULLSYM);
        !           340:                        } else {
        !           341:                                yyerror("Expression larger than literal.");
        !           342:                        }
        !           343:                        return;
        !           344: 
        !           345:                default:
        !           346:                        yyerror("Illegal operand specifier for immediate address mode.");
        !           347:                        return;
        !           348: 
        !           349:                } /* switch */
        !           350: 
        !           351: #if    FLOAT
        !           352:        case FPIMMD: /* fp immediate, same as IMMD but w/o optimization */
        !           353:                if ((val=optype(insptr->tag,opnum)) == 3)  /* 64 bit (double) */
        !           354:                        generate(8,NOACTION,(long)CDIMMD,NULLSYM);
        !           355:                else            /* 32 bit (single) */
        !           356:                        generate(8,NOACTION,(long)CIMMD,NULLSYM);
        !           357:                generate(32,NOACTION,swap_b4(addr->adexpr.expval),addr->adexpr.symptr);
        !           358:                if (val == 3)           /* generate second 32 bits */
        !           359:                        generate(32,NOACTION,swap_b4(addr->adexpr.fdexpval2),addr->adexpr.symptr);
        !           360:                break;
        !           361: #endif
        !           362: 
        !           363:        case REGMD: /* register mode */
        !           364:                reg = addr->adreg;
        !           365:                if ( reg == PCREG ) {
        !           366:                        yyerror("Register mode illegal with register 15 (%pc).");
        !           367:                } else {
        !           368:                        generate(8,NOACTION,(long)((CREGMD<<4)|reg),NULLSYM);
        !           369:                }
        !           370:                return;
        !           371: 
        !           372:        default:
        !           373:                yyerror("Assembler error: invalid addressing mode");
        !           374:                return;
        !           375:        } /* switch */
        !           376: } /* addrgen */
        !           377: 
        !           378: long
        !           379: swap_b2(val)
        !           380: long val;
        !           381: {
        !           382:        long b1, b2;
        !           383: 
        !           384:        b1 = (val >> 8) & 0x00FFL;      /* 2nd low goes to low */
        !           385:        b2 = (val << 8) & 0xFF00L;      /* low goes to high */
        !           386:        return (b2|b1);
        !           387: } /* swap_b2 */
        !           388: 
        !           389: long
        !           390: swap_b4(val)
        !           391: long val;
        !           392: {
        !           393:        long b1, b2, b3, b4;
        !           394: 
        !           395:        b1 = (val >> 24) & 0x000000FFL; /* high goes to low */
        !           396:        b2 = (val >>  8) & 0x0000FF00L; /* 2nd high goes to 2nd low */
        !           397:        b3 = (val <<  8) & 0x00FF0000L; /* 2nd low goes to 2nd high */
        !           398:        b4 = (val << 24) & 0xFF000000L; /* low goes to high */
        !           399:        return (b1|b2|b3|b4);
        !           400: } /* swap_b4 */
        !           401: 
        !           402: optype(instype,opnum)
        !           403: BYTE instype;
        !           404: short opnum;
        !           405: {
        !           406: /*
        !           407:  * figure out operand type according to instruction type and operand number
        !           408:  * return:     0=byte  1=half  2=word  3=double
        !           409:  */
        !           410: 
        !           411:        switch (instype & (~IS25)) {
        !           412: 
        !           413:        case INSTRB:
        !           414:                return 0;
        !           415: 
        !           416:        case INSTRH:
        !           417:                return 1;
        !           418: 
        !           419:        case INSTRW:
        !           420:                return 2;
        !           421: 
        !           422: #if    FLOAT
        !           423:        case INSTRD:
        !           424:                return 3;
        !           425: #endif
        !           426: 
        !           427:        case INSTRBH:
        !           428:                return (opnum==1) ? 0 : 1;
        !           429: 
        !           430:        case INSTRBW:
        !           431:                return (opnum==1) ? 0 : 2;
        !           432: 
        !           433:        case INSTRHW:
        !           434:                return (opnum==1) ? 1 : 2;
        !           435: 
        !           436:        case INSTRWH:
        !           437:                return (opnum==1) ? 2 : 1;
        !           438: 
        !           439:        case INSTRWB:
        !           440:                return (opnum==1) ? 2 : 0;
        !           441: 
        !           442:        case INSTRHB:
        !           443:                return (opnum==1) ? 1 : 0;
        !           444: 
        !           445:        default:                /* should not happen, but just in case */
        !           446:                return 2;       /* treat as word operand */
        !           447:        }
        !           448: } /* optype */
        !           449: 
        !           450: convgen(insptr,addr1,addr2)
        !           451: instr  *insptr;
        !           452: register addrmode
        !           453:        *addr1,
        !           454:        *addr2;
        !           455: {
        !           456:        /*
        !           457:         *
        !           458:         * movb[bh|bw|hw] and movt[wb|hb|wh] instructions;
        !           459:         *
        !           460:         * All are encoded as expand mode mappings except
        !           461:         * for movtXY with a register destination.
        !           462:         * These are encoded as follows:
        !           463:         *
        !           464:         *      movthb  X,%ry   -> andh3 &0xFF,X,%ry
        !           465:         *      movtwb  X,%ry   -> andw3 &0xFF,X,%ry
        !           466:         *      movtwh  X,%ry   -> movw  X,%ry ; movh %ry,%ry
        !           467:         *
        !           468:         */
        !           469: 
        !           470:        static addrmode maskop = {NOTYPE,IMMD,0x01,{ABS,NULLSYM,0xFFL}};
        !           471:        register short  expand;
        !           472:        instr   *newins;                /* set up dummy operands for movtwb */
        !           473:        char    *maskinst = "andw3";
        !           474: 
        !           475:        /* check for movtXY with a register dest. */
        !           476:        if (addr2->admode == REGMD)
        !           477:                switch (insptr->tag & (~IS25)) {
        !           478:                case INSTRHB:
        !           479:                        /* change instruction for movthb */
        !           480:                        maskinst = "andh3";
        !           481:                        /* fall through to ... */
        !           482:                case INSTRWB:
        !           483:                        newins = (*lookup(maskinst,N_INSTALL,MNEMON)).itp;
        !           484:                        generate(8,NOACTION,newins->opcode,NULLSYM);
        !           485:                        addrgen(newins,&maskop,NOTYPE,1); /* mask operand */
        !           486:                        addrgen(insptr,addr1,NOTYPE,2);
        !           487:                        addrgen(insptr,addr2,UBYTE,3);
        !           488:                        return;
        !           489:                case INSTRWH:
        !           490:                        generate(8,NOACTION,insptr->opcode,NULLSYM);  /* movw */
        !           491:                        addrgen(insptr,addr1,NOTYPE,1);
        !           492:                        addrgen(insptr,addr2,NOTYPE,2);
        !           493:                        generate(0,NEWSTMT,(long)line,NULLSYM);
        !           494:                        newins = (*lookup("movh",N_INSTALL,MNEMON)).itp;
        !           495:                        generate(8,NOACTION,newins->opcode,NULLSYM);
        !           496:                        addrgen(insptr,addr2,NOTYPE,1);
        !           497:                        addrgen(insptr,addr2,NOTYPE,2);
        !           498:                        return;
        !           499:                } /* switch */
        !           500: 
        !           501:        generate(insptr->nbits,NOACTION,insptr->opcode,NULLSYM);
        !           502:        addrgen(insptr,addr1,NOTYPE,1);
        !           503:        switch (optype(insptr->tag,2)) {
        !           504:                case 0: /* byte */
        !           505:                        expand = SBYTE;
        !           506:                        break;
        !           507:                case 1: /* half */
        !           508:                        expand = SHALF;
        !           509:                        break;
        !           510:                case 2: /* word */
        !           511:                        expand = SWORD;
        !           512:                        break;
        !           513:        } /* switch */
        !           514: 
        !           515:        addrgen(insptr,addr2,expand,2);
        !           516: } /* convgen */
        !           517: 
        !           518: testgen(insptr, addr1)
        !           519: register       instr           *insptr;
        !           520: register       addrmode        *addr1;
        !           521: {
        !           522:        /*
        !           523:         *      NOP2 NOP3
        !           524:         *
        !           525:         *              This routine will generate the filler bytes
        !           526:         *      for the above two nops.
        !           527:         */
        !           528:        
        !           529:        int     val;
        !           530: 
        !           531:        if ( addr1->newtype != NOTYPE ) {
        !           532:                yyerror("Expand byte illegal with NOP2 or NOP3 instructions.");
        !           533:                return;
        !           534:        }
        !           535: 
        !           536:        if ( addr1->expspec != NULLSPEC ) {
        !           537:                yyerror("Operand specifier illegal with NOP2 or NOP3 instructions.");
        !           538:                return;
        !           539:        }
        !           540: 
        !           541:        generate( insptr->nbits, NOACTION, insptr->opcode, NULLSYM);
        !           542:        val = addr1->adexpr.expval;
        !           543: 
        !           544:        if ( insptr->tag ==  INSTRB ) {
        !           545:                if ((unsigned) val >= (1L << 8)) {
        !           546:                      yyerror("Optional immediate for NOP2 larger than byte.");
        !           547:                } else {
        !           548:                        generate( 8, NOACTION, val, NULLSYM);
        !           549:                }
        !           550:        } else {
        !           551:                if ((unsigned) val >= (1L << 16)) {
        !           552:                      yyerror("Optional immediate for NOP3 larger than halfword.");
        !           553:                } else {
        !           554:                        generate(16, NOACTION, val, NULLSYM);
        !           555:                }
        !           556:        }
        !           557: } /* testgen */
        !           558: 
        !           559: opt21gen(insptr,addr1,addr2,constant)
        !           560: instr  *insptr;
        !           561: register addrmode
        !           562:        *addr1,
        !           563:        *addr2;
        !           564: short  constant;
        !           565: {
        !           566:        /*
        !           567:         * This function attempts to optimize certain dyadic instructions
        !           568:         * into monadics when the first operand is a particular
        !           569:         * immediate constant.
        !           570:         *
        !           571:         * The possible optimizations are:
        !           572:         *
        !           573:         * Dyadic       Constant        Monadic
        !           574:         *
        !           575:         * mov[bhw]     0               CLR[BHW]
        !           576:         * add[bhw]2    1               INC[BHW]
        !           577:         * sub[bhw]2    1               DEC[BHW]
        !           578:         * cmp[bhw]     0               TST[BHW]
        !           579:         *
        !           580:         *
        !           581:         * In all cases the dyadic opcode is stored in the low byte
        !           582:         * of the opcode field of the instruction table (pointed to by insptr)
        !           583:         * and the monadic opcode is stored in the 2nd low byte
        !           584:         *
        !           585:         */
        !           586: 
        !           587:        if (addr1->admode==IMMD && addr1->adexpr.exptype==ABS &&
        !           588:                addr1->adexpr.expval==(long)constant &&
        !           589:                (insptr->tag & IS25) && opt)
        !           590:        {
        !           591:                /* generate monadic opcode */
        !           592:                generate(8,NOACTION,(insptr->opcode >> 8),NULLSYM);
        !           593:                addrgen(insptr,addr2,NOTYPE,2);
        !           594:        }
        !           595:        else {
        !           596:                /* just do normal dyadic instruction */
        !           597:                /* mask off 2nd low byte, but don't really have to */
        !           598:                generate(8,NOACTION,insptr->opcode & 0xFFL,NULLSYM);
        !           599:                addrgen(insptr,addr1,NOTYPE,1);
        !           600:                addrgen(insptr,addr2,NOTYPE,2);
        !           601:        } /* else */
        !           602: } /* opt21gen */
        !           603: 
        !           604: jmpopgen(insptr,opnd1)
        !           605: instr  *insptr;
        !           606: addrmode       *opnd1;
        !           607: {
        !           608:        instr   *newins;
        !           609:        long    opcd, newopcd;
        !           610:        BYTE    nbits;
        !           611:        unsigned short  action;
        !           612:        short   jmptype;
        !           613: 
        !           614:        opcd = insptr->opcode;
        !           615: 
        !           616:        switch (insptr->tag) {
        !           617:        case INSTRB: /* byte displacement */
        !           618:                nbits = 8;
        !           619:                if (opnd1->admode != EXADMD)
        !           620:                        yyerror("Invalid operand");
        !           621:                action = RELPC8;
        !           622:                break;
        !           623:        case INSTRH: /* halfword displacement */
        !           624:                if (opnd1->admode != EXADMD)
        !           625:                        yyerror("Invalid operand");
        !           626:                nbits = 16;
        !           627:                action = RELPC16;
        !           628:                break;
        !           629:        case IS25|INSTRW: /* IS25, word displacement */
        !           630:                if (opnd1->admode != EXADMD) {
        !           631:                        /* can't generate PC relative */
        !           632:                        if ((newopcd = opcd >> 8) != 0) {
        !           633:                                /* generate complementary branch */
        !           634:                                generate(8,NOACTION,newopcd,NULLSYM);
        !           635:                                generate(8,FNDBRLEN,0L,NULLSYM);
        !           636:                        } /* (newopcd = opcd >> 8) != 0 */
        !           637:                        newins = (*lookup("JMP",N_INSTALL,MNEMON)).itp;
        !           638:                        generate(8,NOACTION,newins->opcode,NULLSYM);
        !           639:                        addrgen(insptr,opnd1,NOTYPE,1);
        !           640:                        return;
        !           641:                } /* opnd1->admode != EXADMD */
        !           642:                jmptype = (opcd >> 8) != 0;
        !           643:                /* 1 means conditional; 0 unconditional */
        !           644:                if (opt) switch(shortsdi(opnd1->adexpr.symptr,
        !           645:                                opnd1->adexpr.expval,
        !           646:                                jmptype ? CBRB : UBRB))
        !           647:                {
        !           648:                case S_SDI: /* definitely 8-bit short */
        !           649:                        generate(8,NOACTION,opcd & 0xFFL,NULLSYM);
        !           650:                        generate(8,RELPC8,opnd1->adexpr.expval,
        !           651:                                opnd1->adexpr.symptr);
        !           652:                        return;
        !           653:                case U_SDI: /* don't know; generate short and flag */
        !           654:                        generate(8,BRNOPT,opcd,NULLSYM);
        !           655:                        generate(8,RELPC8,opnd1->adexpr.expval,
        !           656:                                opnd1->adexpr.symptr);
        !           657:                        return;
        !           658:                /* case L_SDI: fall through */
        !           659:                } /* if (opt) switch (...) */
        !           660: 
        !           661:                /* try 16-bit branch offset */
        !           662:                switch(shortsdi(opnd1->adexpr.symptr,
        !           663:                                opnd1->adexpr.expval,
        !           664:                                jmptype ? CBRH : UBRH))
        !           665:                {
        !           666:                case S_SDI: /* definitely 16-bit short */
        !           667:                        generate(8,NOACTION,(opcd & 0xFFL) - 1L,
        !           668:                                NULLSYM);
        !           669:                        generate(16,RELPC16,opnd1->adexpr.expval,
        !           670:                                opnd1->adexpr.symptr);
        !           671:                        return;
        !           672:                case U_SDI: /* unknown; generate 16-bit short (interm.) and flag */
        !           673:                        /* convert opcode(s) from short to intermed. */
        !           674:                        if ((opcd >> 8) != 0)
        !           675:                                /* subtract 1 from both opcodes */
        !           676:                                opcd -= 0x0101L;
        !           677:                        else
        !           678:                                /* subtract 1 from opcode */
        !           679:                                --opcd;
        !           680:                        generate(8,BRNOPT,opcd,NULLSYM);
        !           681:                        generate(16,RELPC16,opnd1->adexpr.expval,
        !           682:                                opnd1->adexpr.symptr);
        !           683:                        return;
        !           684:                case L_SDI:
        !           685:                        /* test for unconditional jump */
        !           686:                        if ((newopcd = opcd >> 8) != 0) {
        !           687:                                /* generate complementary branch */
        !           688:                                generate(8,NOACTION,newopcd,NULLSYM);
        !           689:                                generate(8,FNDBRLEN,0L,NULLSYM);
        !           690:                                generate(0,NEWSTMT,(long)line,NULLSYM);
        !           691:                        }
        !           692:                        newins = (*lookup("JMP",N_INSTALL,MNEMON)).itp;
        !           693:                        generate(8,NOACTION,newins->opcode,NULLSYM);
        !           694:                        addrgen(insptr,opnd1,NOTYPE,1);
        !           695:                        return;
        !           696:                } /* switch */
        !           697:        case INSTRW: /* word displacement */
        !           698:                        generate(8,NOACTION,opcd,NULLSYM);
        !           699:                        addrgen(insptr,opnd1,NOTYPE,1);
        !           700:                        return;
        !           701:        default:
        !           702:                aerror("assembler error; invalid operator type");
        !           703:        } /* switch */
        !           704: 
        !           705:        generate(8,NOACTION,opcd & 0xFFL,NULLSYM); /* not necessary to mask */
        !           706:        generate(nbits,action,opnd1->adexpr.expval,opnd1->adexpr.symptr);
        !           707: } /* jmpopgen */
        !           708: 
        !           709: jsbopgen(insptr,opnd1)
        !           710: instr  *insptr;
        !           711: addrmode       *opnd1;
        !           712: {
        !           713:        long    opcd;
        !           714: 
        !           715:        opcd = insptr->opcode;
        !           716: 
        !           717:        if (opnd1->admode != EXADMD) {
        !           718:                /* can't generate PC relative */
        !           719:                generate(8,NOACTION,opcd >> 8,NULLSYM);
        !           720:                addrgen(insptr,opnd1,NOTYPE,1);
        !           721:        }
        !           722:        else {
        !           723:                if (opt) switch(shortsdi(opnd1->adexpr.symptr,
        !           724:                                opnd1->adexpr.expval,BSBB))
        !           725:                {
        !           726:                case S_SDI: /* definitely 8-bit short */
        !           727:                        generate(8,NOACTION,opcd & 0xFFL,NULLSYM);
        !           728:                        generate(8,RELPC8,opnd1->adexpr.expval,
        !           729:                                opnd1->adexpr.symptr);
        !           730:                        return;
        !           731:                case U_SDI: /* don't know; generate short and flag */
        !           732:                        generate(8,BSBNOPT,opcd,NULLSYM);
        !           733:                        generate(8,RELPC8,opnd1->adexpr.expval,
        !           734:                                opnd1->adexpr.symptr);
        !           735:                        return;
        !           736:                /* case L_SDI: fall through */
        !           737:                } /* if (opt) switch (...) */
        !           738: 
        !           739:                /* try 16-bit branch offset */
        !           740:                switch(shortsdi(opnd1->adexpr.symptr,
        !           741:                                opnd1->adexpr.expval,BSBH))
        !           742:                {
        !           743:                case S_SDI: /* definitely 16-bit short */
        !           744:                        generate(8,NOACTION,(opcd & 0xFFL) - 1L,NULLSYM);
        !           745:                        generate(16,RELPC16,opnd1->adexpr.expval,
        !           746:                                opnd1->adexpr.symptr);
        !           747:                        return;
        !           748:                case U_SDI: /* don't know; generate 16-bit short and flag */
        !           749:                        /* convert opcode from short to intermed. */
        !           750:                        --opcd;
        !           751:                        generate(8,BSBNOPT,opcd,NULLSYM);
        !           752:                        generate(16,RELPC16,opnd1->adexpr.expval,
        !           753:                                opnd1->adexpr.symptr);
        !           754:                        generate(8,NOACTION,opcd >> 8,NULLSYM);
        !           755:                        addrgen(insptr,opnd1,NOTYPE,1);
        !           756:                        return;
        !           757:                case L_SDI:
        !           758:                        generate(8,NOACTION,opcd,NULLSYM);
        !           759:                        addrgen(insptr,opnd1,NOTYPE,2);
        !           760:                        return;
        !           761:                } /* switch */
        !           762:        } /* else */
        !           763: } /* jsbopgen */
        !           764: 
        !           765: callgen(insptr,imm,dest)
        !           766: instr  *insptr;
        !           767: addrmode       *imm, *dest;
        !           768: {
        !           769:        /*
        !           770:         *
        !           771:         * call   imm,dest
        !           772:         *
        !           773:         *      is encoded as
        !           774:         *
        !           775:         * CALL -(4*imm)(%sp),dest
        !           776:         *
        !           777:         */
        !           778: 
        !           779:        static addrmode dispsp = {NOTYPE,DSPMD,SPREG,{ABS,NULLSYM,1L}};
        !           780:        int     span;
        !           781: 
        !           782:        dispsp.adexpr.expval = - (4L * imm->adexpr.expval );
        !           783:        generate(8,NOACTION,insptr->opcode,NULLSYM); /* CALL opcode */
        !           784:        addrgen(insptr,&dispsp,NOTYPE,1);
        !           785: 
        !           786: #ifndef CALLPCREL
        !           787:        addrgen(insptr,dest,NOTYPE,2);
        !           788: #else
        !           789:        if (dest->admode != EXADMD) {
        !           790:                /* can't generate PC relative */
        !           791:                addrgen(insptr,dest,NOTYPE,2);
        !           792:        } else {
        !           793:                if (opt) {
        !           794:                        if (sdi(dest->adexpr.symptr, dest->adexpr.expval,
        !           795:                                PCBRELCALL) == S_SDI) {
        !           796:                                span = shortsdi(dest->adexpr.symptr,
        !           797:                                        dest->adexpr.expval,PCBRELCALL);
        !           798:                                if ( span == S_SDI) {
        !           799:                                        /* byte displacement from PC */
        !           800:                                        generate(8,NOACTION,0xCFL,NULLSYM);
        !           801:                                        generate(8,RELPC8,dest->adexpr.expval,
        !           802:                                                dest->adexpr.symptr);
        !           803:                                } else {
        !           804:                                        yyerror("Assembler error with short span dependent procedure call.");
        !           805:                                }
        !           806:                                return;
        !           807:                        }
        !           808:                }
        !           809: 
        !           810: /*             if (opt) switch(shortsdi(dest->adexpr.symptr,
        !           811: /*                             dest->adexpr.expval,PCBRELCALL))
        !           812: /*             {
        !           813: /*             case S_SDI: /* definitely 8-bit short */
        !           814: /*                     /* byte displacement from PC */
        !           815: /*                     generate(8,NOACTION,0xCFL,NULLSYM);
        !           816: /*                     generate(8,RELPC8,dest->adexpr.expval,
        !           817: /*                             dest->adexpr.symptr);
        !           818: /*                     return;
        !           819: /*             case U_SDI: /* don't know; generate short and flag */
        !           820: /*                     /* byte displacement from PC */
        !           821: /*                     generate(8,CALLNOPT,0xCFL,NULLSYM);
        !           822: /*                     generate(8,RELPC8,dest->adexpr.expval,
        !           823: /*                             dest->adexpr.symptr);
        !           824: /*                     return;
        !           825: /*             /* case L_SDI: fall through */
        !           826: /*             } /* if (opt) switch (...) */
        !           827: 
        !           828:                /* try 16-bit branch offset */
        !           829:                switch(shortsdi(dest->adexpr.symptr,
        !           830:                                dest->adexpr.expval,PCHRELCALL))
        !           831:                {
        !           832:                case S_SDI: /* definitely 16-bit short */
        !           833:                        /* halfword relative from PC */
        !           834:                        generate(8,NOACTION,0xAFL,NULLSYM);
        !           835:                        generate(16,RELPC16,dest->adexpr.expval,
        !           836:                                dest->adexpr.symptr);
        !           837:                        return;
        !           838:                case U_SDI: /* don't know; generate 16-bit short and flag */
        !           839:                        /* halfword relative from PC */
        !           840:                        generate(8,CALLNOPT,0xAFL,NULLSYM);
        !           841:                        generate(16,RELPC16,dest->adexpr.expval,
        !           842:                                dest->adexpr.symptr);
        !           843:                        return;
        !           844:                case L_SDI:
        !           845:                        /* CALL opcode */
        !           846:                        addrgen(insptr,dest,NOTYPE,2);
        !           847:                        return;
        !           848:                } /* switch */
        !           849:        } /* else */
        !           850: #endif
        !           851: } /* callgen */
        !           852: 
        !           853: loop1gen(insptr,index,incr,limit,dest)
        !           854: instr  *insptr;
        !           855: addrmode       *index, *incr, *limit, *dest;
        !           856: {
        !           857:        /*
        !           858:         *
        !           859:         * acX  index,incr,limit,dest
        !           860:         *      where X can be [jl|jlu|jle|jleu]
        !           861:         *
        !           862:         *      is encoded as
        !           863:         *
        !           864:         * addw2        incr,index
        !           865:         * cmpw         index,limit
        !           866:         * X            dest
        !           867:         *
        !           868:         */
        !           869: 
        !           870:        instr   *newins;
        !           871: 
        !           872:                /* addw2 */
        !           873:        newins = (*lookup("addw2",N_INSTALL,MNEMON)).itp;
        !           874:        opt21gen(newins,incr,index,1);  /* optimized "add" */
        !           875:        pcintcheck(newins,index);
        !           876: 
        !           877:                /* cmpw */
        !           878:        generate(0,NEWSTMT,(long)line,NULLSYM);
        !           879:        newins = (*lookup("cmpw",N_INSTALL,MNEMON)).itp;
        !           880: #if 0
        !           881:        /* generate optimized "cmpw" and interchange operands */
        !           882:        opt21gen(newins,limit,index,0);
        !           883: #endif
        !           884:        /* DONT generate optimized "cmpw" because of Interrupt
        !           885:         * After TSTW Chip Bug.
        !           886:         */
        !           887:        generate(8,NOACTION,newins->opcode & 0xFFL,NULLSYM);
        !           888:        addrgen(newins,limit,NOTYPE,1);
        !           889:        addrgen(newins,index,NOTYPE,2);
        !           890: 
        !           891:                /* jump instr. */
        !           892:        generate(0,NEWSTMT,(long)line,NULLSYM);
        !           893:        newins = (*lookup((insptr->name)+2,N_INSTALL,MNEMON)).itp;
        !           894:        jmpopgen(newins,dest);
        !           895: } /* loop1gen */
        !           896: 
        !           897: loop2gen(insptr,index,incr,dest)
        !           898: instr  *insptr;
        !           899: addrmode       *index, *incr, *dest;
        !           900: {
        !           901:        /*
        !           902:         *
        !           903:         * atjnz[bhw]   index,incr,dest
        !           904:         *
        !           905:         *      is encoded as
        !           906:         *
        !           907:         * addw2        incr,index
        !           908:         * TST[BHW]     *index
        !           909:         * jnz          dest
        !           910:         *
        !           911:         */
        !           912: 
        !           913:        instr   *newins;
        !           914: 
        !           915:                /* addw2 */
        !           916:        newins = (*lookup("addw2",N_INSTALL,MNEMON)).itp;
        !           917:        opt21gen(newins,incr,index,1);  /* optimized "add" */
        !           918: 
        !           919:                /* TST[BHW] */
        !           920:        generate(0,NEWSTMT,(long)line,NULLSYM);
        !           921:        generate(8,NOACTION,insptr->opcode,NULLSYM); /* TST opcode */
        !           922: 
        !           923:        /*
        !           924:         * To generate TST *index,
        !           925:         * must add a level of indirection to "index"
        !           926:         *
        !           927:         */
        !           928: 
        !           929:        switch(index->admode) {
        !           930: 
        !           931:                case DSPMD:
        !           932:                case EXADMD:
        !           933:                case ABSMD:
        !           934:                        ++(index->admode); /* adds a level of indirection */
        !           935:                        break;
        !           936:                case REGMD:
        !           937:                        index->admode = DSPMD;
        !           938:                        index->adexpr.exptype = ABS;
        !           939:                        index->adexpr.expval = 0L;
        !           940:                        index->adexpr.symptr = NULLSYM;
        !           941:                        break;
        !           942:                default:
        !           943:                        yyerror("Invalid `index' operand of `atjnz'");
        !           944:                        break;
        !           945:        } /* switch */
        !           946: 
        !           947:        addrgen(insptr,index,NOTYPE,1);
        !           948: 
        !           949:                /* jnz */
        !           950:        generate(0,NEWSTMT,(long)line,NULLSYM);
        !           951:        newins = (*lookup("jnz",N_INSTALL,MNEMON)).itp;
        !           952:        jmpopgen(newins,dest);
        !           953: } /* loop2gen */
        !           954: 
        !           955: blockgen(insptr)
        !           956: instr  *insptr;
        !           957: {
        !           958:        /*
        !           959:         *
        !           960:         * movbl[bh]
        !           961:         *      is encoded as
        !           962:         *
        !           963:         * TSTW         %r2
        !           964:         * BRB          +12 (for half) or +14 (for byte)
        !           965:         * mov[bh]      (%r0),(%r1)
        !           966:         * NOP 
        !           967:         * addw2        &2,%r0 (for half) or INCW %r0 (for byte)
        !           968:         * addw2        &2,%r1 (for half) or INCW %r1 (for byte)
        !           969:         * DECW         %r2
        !           970:         * BNEB         -12 (for half) or -10 (for byte)
        !           971:         *
        !           972:         */
        !           973: 
        !           974:        instr   *newins;
        !           975:        short   byte;
        !           976: 
        !           977:        if( (insptr->tag & SHFT_MSK) == INSTRB)
        !           978:                byte = YES;
        !           979:        else
        !           980:                byte = NO;
        !           981: 
        !           982:                /* TSTW */
        !           983:        newins = (*lookup("TSTW",N_INSTALL,MNEMON)).itp;
        !           984:        generate(8,NOACTION,newins->opcode,NULLSYM);    /* TSTW opcode */
        !           985:        generate(8,NOACTION,(long)(CREGMD<<4|0x02),NULLSYM); /* %r2 */
        !           986: 
        !           987:                /* BRB */
        !           988:        generate(0,NEWSTMT,(long)line,NULLSYM);
        !           989:        newins = (*lookup("BRB",N_INSTALL,MNEMON)).itp;
        !           990:        generate(8,NOACTION,newins->opcode,NULLSYM);    /* unc. branch */
        !           991:        if (byte == YES)
        !           992:                generate(8,NOACTION,12L,NULLSYM);
        !           993:        else
        !           994:                generate(8,NOACTION,14L,NULLSYM);
        !           995: 
        !           996:                /* mov[bh] */
        !           997:        generate(0,NEWSTMT,(long)line,NULLSYM);
        !           998:        generate(8,NOACTION,insptr->opcode,NULLSYM);    /* mov[bh] */
        !           999:        generate(8,NOACTION,(long)(CREGDFMD<<4|0x00),NULLSYM); /* (%r0) */
        !          1000:        generate(8,NOACTION,(long)(CREGDFMD<<4|0x01),NULLSYM); /* (%r1) */
        !          1001: 
        !          1002:        /*
        !          1003:         *  A NOP must ne inserted here because a write to memory 
        !          1004:         *  was just generated.
        !          1005:         */
        !          1006:        generate(0,NEWSTMT,(long)line,NULLSYM);
        !          1007:        newins = (*lookup("NOP",N_INSTALL,MNEMON)).itp;
        !          1008:        generate(newins->nbits, NOACTION, newins->opcode, NULLSYM);
        !          1009: 
        !          1010:        generate(0,NEWSTMT,(long)line,NULLSYM);
        !          1011:        if (byte == YES) {
        !          1012:                /* INCW - increment register 0 */
        !          1013:                /* INCW - increment register 1 */
        !          1014:        
        !          1015:                newins = (*lookup("INCW",N_INSTALL,MNEMON)).itp;
        !          1016:                generate(8,NOACTION,newins->opcode,NULLSYM);    /* INCW */
        !          1017:                generate(8,NOACTION,(long)(CREGMD<<4|0x00),NULLSYM); /* %r0 */
        !          1018:                generate(0,NEWSTMT,(long)line,NULLSYM);
        !          1019:                generate(8,NOACTION,newins->opcode,NULLSYM);    /* INCW */
        !          1020:                generate(8,NOACTION,(long)(CREGMD<<4|0x01),NULLSYM); /* %r1 */
        !          1021:        }
        !          1022:        else {
        !          1023: 
        !          1024:                /* addw2 - increment register 0 */
        !          1025:                /* addw2 - increment register 1 */
        !          1026:                newins = (*lookup("addw2",N_INSTALL,MNEMON)).itp;
        !          1027:                generate(8,NOACTION,newins->opcode,NULLSYM);    /* addw2 */
        !          1028:                generate(8,NOACTION,2L,NULLSYM);
        !          1029:                generate(8,NOACTION,(long)(CREGMD<<4|0x00),NULLSYM); /* %r0 */
        !          1030:                generate(0,NEWSTMT,(long)line,NULLSYM);
        !          1031:                generate(8,NOACTION,newins->opcode,NULLSYM);    /* addw2 */
        !          1032:                generate(8,NOACTION,2L,NULLSYM);
        !          1033:                generate(8,NOACTION,(long)(CREGMD<<4|0x01),NULLSYM); /* %r1 */
        !          1034:        }
        !          1035: 
        !          1036:                /* DECW */
        !          1037:        generate(0,NEWSTMT,(long)line,NULLSYM);
        !          1038:        newins = (*lookup("DECW",N_INSTALL,MNEMON)).itp;
        !          1039:        generate(8,NOACTION,newins->opcode,NULLSYM);    /* DECW */
        !          1040:        generate(8,NOACTION,(long)(CREGMD<<4|0x02),NULLSYM); /* %r2 */
        !          1041: 
        !          1042:                /* BNEB */
        !          1043:        generate(0,NEWSTMT,(long)line,NULLSYM);
        !          1044:        newins = (*lookup("BNEB",N_INSTALL,MNEMON)).itp;
        !          1045:        generate(8,NOACTION,newins->opcode,NULLSYM);    /* BNEB opcode */
        !          1046:        if (byte == YES)
        !          1047:                generate(8,NOACTION,-10L,NULLSYM);
        !          1048:        else
        !          1049:                generate(8,NOACTION,-12L,NULLSYM);
        !          1050: } /* blockgen */
        !          1051: 
        !          1052: pushopgen(insptr,opnd1)
        !          1053: instr  *insptr;
        !          1054: addrmode       *opnd1;
        !          1055: {
        !          1056:        /*
        !          1057:         *
        !          1058:         * push[zb][bh] opnd1
        !          1059:         *
        !          1060:         *      is encoded as
        !          1061:         *
        !          1062:         * addw2        &4,%sp
        !          1063:         * followed by one of the following:
        !          1064:         *
        !          1065:         *      if opnd1 does not use %sp
        !          1066:         * mov[bh]      {X}opnd1,{sword}-4(%sp)
        !          1067:         *
        !          1068:         *      if opnd1=%sp
        !          1069:         * subw3        &4,{X}%sp,{sword}-4(%sp)
        !          1070:         *
        !          1071:         *      if opnd1=expr(%sp)
        !          1072:         * mov[bh]      {X}expr-4(%sp),{sword}-4(%sp)
        !          1073:         *
        !          1074:         *      if opnd1=*expr(%sp)
        !          1075:         * mov[bh]      {X}*expr-4(%sp),{sword}-4(%sp)
        !          1076:         *
        !          1077:         *      where X = signed for push.b
        !          1078:         *                unsigned for push.h
        !          1079:         */
        !          1080: 
        !          1081:        static addrmode dispsp = {NOTYPE,DSPMD,SPREG,{ABS,NULLSYM,-4L}};
        !          1082:        static addrmode immdop = {NOTYPE,IMMD,0x04,{ABS,NULLSYM,4L}};
        !          1083:        instr   *newins;
        !          1084:        short   expand;
        !          1085: 
        !          1086:                /* addw2 */
        !          1087:        newins = (*lookup("addw2",N_INSTALL,MNEMON)).itp;
        !          1088:        generate(8,NOACTION,newins->opcode,NULLSYM);
        !          1089:        addrgen(insptr,&immdop,NOTYPE,1);
        !          1090:        generate(8,NOACTION,(long)((CREGMD<<4)|SPREG),NULLSYM); /* operand %sp */
        !          1091: 
        !          1092:                /* decide on which second instruction to generate */
        !          1093:        switch (opnd1->admode) {
        !          1094:        case REGMD:
        !          1095:                if (opnd1->adreg == SPREG) {    /* if opnd1 is %sp then */
        !          1096:                                                /* generate subw3 instr */
        !          1097:                        newins = (*lookup("subw3",N_INSTALL,MNEMON)).itp;
        !          1098:                        generate(8,NOACTION,newins->opcode,NULLSYM);
        !          1099:                        addrgen(insptr,&immdop,NOTYPE,1);
        !          1100:                        generate(8,NOACTION,(long)((CREGMD<<4)|SPREG),NULLSYM); /* oprnd %sp */
        !          1101:                        addrgen(insptr,&dispsp,SWORD,3); /* oprnd {sword}-4(%sp) */
        !          1102:                        pcintcheck(insptr,&dispsp);
        !          1103:                        return;
        !          1104:                } else
        !          1105:                        break;
        !          1106:        case REGDFMD:
        !          1107:        case DSPMD:
        !          1108:        case DSPDFMD:
        !          1109:                /* if register is %sp, subtract 4 from displacement */
        !          1110:                if (opnd1->adreg == SPREG)
        !          1111:                        opnd1->adexpr.expval -= 4;
        !          1112:                break;
        !          1113:        } /* switch */
        !          1114: 
        !          1115:                /* mov[bh] opcode */
        !          1116:        generate(8,NOACTION,insptr->opcode,NULLSYM);
        !          1117:        switch (insptr->tag & (~IS25)) {
        !          1118:                case INSTRBW:
        !          1119:                        expand = SBYTE;
        !          1120:                        break;
        !          1121:                case INSTRHW:
        !          1122:                        expand = UHALF;
        !          1123:                        break;
        !          1124:                default:
        !          1125:                        expand = NOTYPE;
        !          1126:        } /* switch */
        !          1127: 
        !          1128:        addrgen(insptr,opnd1,expand,1);
        !          1129:        addrgen(insptr,&dispsp,SWORD,2);
        !          1130:        pcintcheck(insptr,&dispsp);
        !          1131: } /* pushopgen */
        !          1132: 
        !          1133: shftopgen(insptr,opnd1,opnd2,opnd3)
        !          1134: instr  *insptr;
        !          1135: addrmode       *opnd1, *opnd2, *opnd3;
        !          1136: {
        !          1137:        short   expand1, expand2;
        !          1138:        long    opcd, opcd2;
        !          1139: 
        !          1140:        opcd = insptr->opcode;
        !          1141:        if ((insptr->tag & IS25) &&
        !          1142:                (opnd1->admode != REGMD) && (opnd1->admode != IMMD))
        !          1143:        {
        !          1144:                expand2 = SWORD;
        !          1145:                /*
        !          1146:                 * The opcode field contains 2 8-bit opcodes.
        !          1147:                 * The lower opcode corresponds to the shift
        !          1148:                 * word opcode.  The higher opcode corresponds
        !          1149:                 * either to a shift word or a shift byte opcode.
        !          1150:                 * Since the shift length (opnd1) is a byte operand
        !          1151:                 * in IS25, the shift byte opcode will be used if
        !          1152:                 * there is one on the MAC32.  If there is no shift
        !          1153:                 * byte instruction, then the shift word will be used
        !          1154:                 * with an expand byte of signed-byte specified.
        !          1155:                 * Thus, test to see if the 2 opcodes are the same.
        !          1156:                 * If so, then the expand byte must be used.
        !          1157:                 */
        !          1158:                opcd2 = opcd & 0x000000FFL; /* lower 8 bits */
        !          1159:                if ((opcd >>= 8) == opcd2)
        !          1160:                        expand1 = SBYTE;
        !          1161:                else
        !          1162:                        expand1 = NOTYPE;
        !          1163:        }
        !          1164:        else
        !          1165:                expand1 = expand2 = NOTYPE;
        !          1166: 
        !          1167:        generate(8,NOACTION,opcd,NULLSYM);
        !          1168:        addrgen(insptr,opnd1,expand1,1);
        !          1169:        addrgen(insptr,opnd2,expand2,2);
        !          1170:        addrgen(insptr,opnd3,NOTYPE,3);
        !          1171: } /* shftopgen */

unix.superglobalmegacorp.com

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