Annotation of researchv9/jerq/sgs/as/gencode.c, revision 1.1.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.