Annotation of researchv9/jerq/sgs/as/swagen.c, revision 1.1.1.1

1.1       root        1: static char *ID_swagen="@(#) swagen.c: 1.3 5/4/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: #define MULOP 0
                     12: #define DIVOP 1
                     13: #define MODOP 2
                     14: 
                     15: #define SIGNED 0
                     16: #define UNSIGNED 1
                     17: 
                     18: extern upsymins
                     19:        *lookup();
                     20: extern short
                     21:        workaround, /* no software workaround flag */
                     22:        opt;    /* no optimize flag */
                     23: extern unsigned short
                     24:        line;   /* current line number */
                     25: 
                     26: /*
                     27:  * chip fix routines:
                     28:  * The following three routines (mtoregcheck, intaft1check, and intaft2check)
                     29:  * are chip fix routines for the Interrupt After TSTW bug.
                     30:  *
                     31:  * If an interupt is responded to after a certain sequence of instructions,
                     32:  * (described below) the last instruction in the sequence may not set flags
                     33:  * at all.
                     34:  *
                     35:  * Instruction Sequences which can cause problems:
                     36:  * First Instruction:
                     37:  *     Type 1) Instruction which does a store to a register and whose
                     38:  *             last source operand comes from memory. This does not
                     39:  *             include any discontinuities, SWAPs, RESTORE, or instructions
                     40:  *             without destinations (ie. BIT, TST, CMP).
                     41:  *     Type 2) Instruction which does a store to a register and is a
                     42:  *             multiple cycle ALU operation (ie. multiply, divide, modulo,
                     43:  *             insert field, move negate).
                     44:  * Second Instruction:
                     45:  *     Any instruction which is executed in 3 cycles. These are:
                     46:  *     TSTW %reg       MOVW %reg,%reg  MCOMW %reg %reg
                     47:  *     INCW %reg       DECW %reg       CLRW %reg
                     48:  * The fix for thisproblem is to insert a NOP before the second instruction
                     49:  * in the sequence.
                     50:  *
                     51:  */
                     52: 
                     53: /* This routine will return a 1 so that an indicator may be set if
                     54:  * the first instruction in the dangerous sequence is assembled.
                     55:  */
                     56: mtoregcheck(src, dest)
                     57: register addrmode *src, *dest;
                     58: {
                     59: #ifdef CHIPFIX
                     60:        if ((dest->admode == REGMD) && (src->admode == REGDFMD ||
                     61:             src->admode == DSPMD || src->admode == DSPDFMD ||
                     62:             src->admode == EXADMD || src->admode == ABSMD ||
                     63:             src->admode == EXADDFMD || src->admode == ABSDFMD)
                     64:             && workaround )
                     65:                return(1);
                     66:        else
                     67:                return(0);
                     68: #else
                     69:                return(0);
                     70: #endif
                     71: } /* mtoregcheck */
                     72: 
                     73: 
                     74: /* This routine will generate a NOP if the indicator is set, and
                     75:  * the operand is a register operand.
                     76:  */
                     77: intaft1check(opnd, mtoreg)
                     78: register addrmode *opnd;
                     79: short  mtoreg;
                     80: {
                     81: #ifdef CHIPFIX
                     82:        instr   *newins;
                     83:        if (mtoreg != 1)
                     84:                return;
                     85:        if ( (opnd->admode == REGMD) && workaround ) {
                     86:                newins = (*lookup("NOP",N_INSTALL,MNEMON)).itp;
                     87:                generate(newins->nbits, NOACTION, newins->opcode, NULLSYM);
                     88:        }
                     89: #endif
                     90: } /* intaft1check */
                     91: 
                     92: 
                     93: /* This routine will generate a NOP if the indicator is set, and
                     94:  * both of the operands are register operands.
                     95:  */
                     96: intaft2check(opnd1, opnd2, mtoreg)
                     97: register addrmode *opnd1, *opnd2;
                     98: short  mtoreg;
                     99: {
                    100: #ifdef CHIPFIX
                    101:        instr   *newins;
                    102:        if (mtoreg != 1)
                    103:                return;
                    104:        if ((opnd1->admode == REGMD) && (opnd2->admode == REGMD &&
                    105:                workaround)) {
                    106:                newins = (*lookup("NOP",N_INSTALL,MNEMON)).itp;
                    107:                generate(newins->nbits, NOACTION, newins->opcode, NULLSYM);
                    108:        }
                    109: #endif
                    110: } /* intaft2check */
                    111: 
                    112: 
                    113: /*
                    114:  *     chip fix routine: Due to pipelining on the cpu chip
                    115:  *     it is possible for the chip to have the "next" instruction
                    116:  *     almost completely executed while it is waiting for the memory
                    117:  *     write of the "current" instr. to be completed, even executed
                    118:  *     to the point where the PC is incremented past the "next" instr.
                    119:  *     If an interrupt occurs in a situation like this then the PC
                    120:  *     will be restored to one past the "next" instr, thereby, in effect,
                    121:  *     skipping one instr. The fix for this is to place a NOP after
                    122:  *     every instr. that does a memory write, except for:
                    123:  *             CALL, call, SAVE, save, PUSHW, pushw, PUSHAW, pushaw
                    124:  *     These don't need the NOP padding.
                    125:  */
                    126: pcintcheck(insptr, dest)
                    127: register instr *insptr;
                    128: register addrmode *dest;
                    129: {
                    130: #ifdef CHIPFIX
                    131:        instr *newins;
                    132: 
                    133:        if ( (dest->admode == DSPMD || dest->admode == DSPDFMD ||
                    134:                dest->admode == EXADMD || dest->admode == ABSMD ||
                    135:                dest->admode == EXADDFMD || dest->admode == ABSDFMD ||
                    136:                dest->admode == REGDFMD) && (workaround) ) {
                    137: 
                    138:                        newins = (*lookup("NOP",N_INSTALL,MNEMON)).itp;
                    139:                        generate(newins->nbits,NOACTION,newins->opcode,NULLSYM);
                    140:        }
                    141: #endif
                    142: } /* pcintcheck */
                    143: 
                    144: #if    0
                    145: /*     The following routine is ifdef'ed out because it is not
                    146:  *     needed in DBO Mask 2 chips.
                    147:  */
                    148: /*
                    149:  *     chip fix routine:       if one of the following instructions:
                    150:  *             MUL[BHW]3, DIV[BHW]3, MOD[BHW]3
                    151:  *     occurs and, during execution, the result from the first two
                    152:  *     operands is computed before the third (destination) operand
                    153:  *     has been latched and decoded then the CPU will hang.
                    154:  *     This problem is fixed with the following mapping:
                    155:  *
                    156:  *             MULX3, DIVX3, MODX3     is mapped into
                    157:  *
                    158:  *                     pushYX          arg1
                    159:  *                     if arg2 is %sp
                    160:  *                             subw3   &4, %sp, marg3
                    161:  *                     else
                    162:  *                             movX    marg2, marg3
                    163:  *                     "offending instr"2      {Z}spoff(%sp), marg3
                    164:  *                     SUBW2           &4, %sp
                    165:  *                     TSTX            {Z}arg3
                    166:  *
                    167:  *                     where:  X = B, H, or W
                    168:  *                             Y = z (zero extend) for bytes
                    169:  *                                 b (bit extend) for halfs
                    170:  *                             Z = user specified expand byte
                    171:  *                             marg[2|3] indicates arg[2|3] has been
                    172:  *                                modified if it references the stack
                    173:  *                                pointer. (The first instruction in
                    174:  *                                the mapping is a push which changes
                    175:  *                                the stack pointer.)
                    176:  *                             spoff is -4L  if  X = W
                    177:  *                                   is -2L  if  X = H
                    178:  *                                   is -1L  if  X = B
                    179:  */
                    180: trimulcheck(insptr, arg1, arg2, arg3)
                    181: register instr *insptr;
                    182: register addrmode      *arg1, *arg2, *arg3;
                    183: {
                    184: #ifdef CHIPFIX
                    185:        instr   *newins, *movins, *tstins;
                    186:        short   usrexp1, usrexp2, usrexp3, adjarg3, otype;
                    187:        long    spoffset;
                    188: 
                    189:        /* Save user specified expand bytes (if there are any)
                    190:         * so that we can push arg1 on the stack using our own
                    191:         * expand byte
                    192:         */
                    193:        usrexp1 = arg1->newtype;
                    194:        usrexp2 = arg2->newtype;
                    195:        usrexp3 = arg3->newtype;
                    196:        /* check if USER specified an expand byte in an IS25 instruction */
                    197:        if (insptr->tag & IS25) {
                    198:                if (( usrexp1 != NOTYPE) || (usrexp2 != NOTYPE) || (usrexp3 != NOTYPE))
                    199:                        yyerror("Expand byte invalid in IS25 instruction");
                    200:        }
                    201:        arg1->newtype = NOTYPE;
                    202: 
                    203:        /* PUSHYX  arg1 
                    204:         *
                    205:         * Generate push instruction. Also look up the correct forms
                    206:         * of the MOV and TST instructions.
                    207:         */
                    208:        otype = optype(insptr->tag,1);
                    209:        switch (otype) {
                    210:                case 0: newins = (*lookup("pushzb",N_INSTALL,MNEMON)).itp; /* BYTE */
                    211:                        pushopgen(newins, arg1);
                    212:                        movins = (*lookup("MOVB",N_INSTALL,MNEMON)).itp;
                    213:                        tstins = (*lookup("TSTB",N_INSTALL,MNEMON)).itp;
                    214:                        spoffset = -1L;
                    215:                        break;
                    216:                case 1: newins = (*lookup("pushbh",N_INSTALL,MNEMON)).itp; /* HALF */
                    217:                        pushopgen(newins, arg1);
                    218:                        movins = (*lookup("MOVH",N_INSTALL,MNEMON)).itp;
                    219:                        tstins = (*lookup("TSTH",N_INSTALL,MNEMON)).itp;
                    220:                        spoffset = -2L;
                    221:                        break;
                    222:                case 2: newins = (*lookup("pushw",N_INSTALL,MNEMON)).itp; /* WORD */
                    223:                        generate (newins->nbits, NOACTION, newins->opcode, NULLSYM);
                    224:                        addrgen (newins, arg1, NOTYPE, 1);
                    225:                        movins = (*lookup("MOVW",N_INSTALL,MNEMON)).itp;
                    226:                        tstins = (*lookup("TSTW",N_INSTALL,MNEMON)).itp;
                    227:                        spoffset = -4L;
                    228:                        break;
                    229:        }
                    230: 
                    231:        /* adjust arg3 if it references the stack pointer */
                    232:        adjarg3 = 0;
                    233:        if (((arg3->admode == DSPMD) || (arg3->admode == DSPDFMD)
                    234:           || (arg3->admode == REGDFMD)) && (arg3->adreg == SPREG)) {
                    235:                adjarg3 = 1;
                    236:                arg3->adexpr.expval -= 4L;
                    237:        }
                    238:        if ((arg2->admode == REGMD) && (arg2->adreg == SPREG)) {
                    239:                /* SUBW3  &4,%sp,marg3  */
                    240:                movins = (*lookup("SUBW3",N_INSTALL,MNEMON)).itp;
                    241:                generate(movins->nbits, NOACTION, movins->opcode, NULLSYM);
                    242:                generate(8, NOACTION, 0x4L, NULLSYM);
                    243:                generate(8, NOACTION, (long)((CREGMD<<4)|SPREG), NULLSYM);
                    244:                addrgen(movins, arg3, NOTYPE, 3);
                    245:        }
                    246:        else {
                    247:                /* adjust arg2 if it references the stack pointer */
                    248:                if (((arg2->admode == DSPMD) || (arg2->admode == DSPDFMD)
                    249:                   || (arg3->admode == REGDFMD)) && (arg2->adreg == SPREG))
                    250:                        arg2->adexpr.expval -= 4L;
                    251: 
                    252:                /* MOVX  marg2,marg3    */
                    253:                generate(movins->nbits, NOACTION, movins->opcode, NULLSYM);
                    254:                if (insptr->name[0] == 'u')
                    255:                        generate(8, NOACTION, (long)((CEXPAND<<4)|UWORD), NULLSYM);
                    256:                else if (usrexp2 == NOTYPE)
                    257:                        arg2->newtype = usrexp1;
                    258:                addrgen(movins, arg2, NOTYPE, 1);
                    259:                addrgen(movins, arg3, NOTYPE, 2);
                    260:        }
                    261:        pcintcheck(movins, arg3);
                    262: 
                    263:        /* <instr>X2  {expand}spoff(%sp),marg3  */
                    264:        switch ((int)insptr->opcode) {
                    265:                case 0xe4:      newins = (*lookup("MODW2",N_INSTALL,MNEMON)).itp;
                    266:                                break;
                    267:                case 0xe6:      newins = (*lookup("MODH2",N_INSTALL,MNEMON)).itp;
                    268:                                break;
                    269:                case 0xe7:      newins = (*lookup("MODB2",N_INSTALL,MNEMON)).itp;
                    270:                                break;
                    271:                case 0xe8:      newins = (*lookup("MULW2",N_INSTALL,MNEMON)).itp;
                    272:                                break;
                    273:                case 0xea:      newins = (*lookup("MULH2",N_INSTALL,MNEMON)).itp;
                    274:                                break;
                    275:                case 0xeb:      newins = (*lookup("MULB2",N_INSTALL,MNEMON)).itp;
                    276:                                break;
                    277:                case 0xec:      newins = (*lookup("DIVW2",N_INSTALL,MNEMON)).itp;
                    278:                                break;
                    279:                case 0xee:      newins = (*lookup("DIVH2",N_INSTALL,MNEMON)).itp;
                    280:                                break;
                    281:                case 0xef:      newins = (*lookup("DIVB2",N_INSTALL,MNEMON)).itp;
                    282:                                break;
                    283:        }
                    284:        generate(newins->nbits, NOACTION, newins->opcode, NULLSYM);
                    285:        if (insptr->name[0] == 'u')
                    286:                generate(8,NOACTION,(long)((CEXPAND<<4)|UWORD),NULLSYM);
                    287:        else
                    288:                if (usrexp1 != NOTYPE)
                    289:                        generate(8,NOACTION,(long)((CEXPAND<<4)|usrexp1),NULLSYM);
                    290: 
                    291:        generate(8, NOACTION, (long)((CBDSPMD<<4)|SPREG), NULLSYM);
                    292:        generate(8, NOACTION, spoffset, NULLSYM);
                    293:        arg3->newtype = usrexp2;
                    294:        addrgen(newins, arg3, NOTYPE, 2);
                    295:        pcintcheck(newins, arg3);
                    296: 
                    297:        /* SUBW2  &4,%sp        */
                    298:        newins = (*lookup("SUBW2",N_INSTALL,MNEMON)).itp;
                    299:        generate(newins->nbits, NOACTION, newins->opcode, NULLSYM);
                    300:        generate(8, NOACTION, 0x4L, NULLSYM);
                    301:        generate(8, NOACTION, (long)((CREGMD<<4)|SPREG), NULLSYM);
                    302: 
                    303:        /* TSTX arg3    
                    304:         * This instruction is generated in order to restore the flag settings
                    305:         * of the mul, div, or mod instruction.
                    306:         *
                    307:         * If arg3 was adjusted because of a stack reference it must now
                    308:         * be readjusted.
                    309:         */
                    310:        if (adjarg3 != 0)
                    311:                arg3->adexpr.expval += 4L;
                    312:        generate(tstins->nbits, NOACTION, tstins->opcode, NULLSYM);
                    313:        if (insptr->name[0] == 'u')
                    314:                arg3->newtype = UWORD;
                    315:        else if (usrexp3 != NOTYPE)
                    316:                arg3->newtype = usrexp3;
                    317:        else if (usrexp2 != NOTYPE)
                    318:                arg3->newtype = usrexp2;
                    319:        else
                    320:                arg3->newtype = usrexp1;
                    321:        addrgen(tstins, arg3, NOTYPE, 1);
                    322: #endif
                    323: } /* trimulcheck */
                    324: #endif
                    325: 
                    326: /*
                    327:  *     chip fix routine: if the psw register is used as the source of
                    328:  *     an instruction, the flag values may not be set yet from the 
                    329:  *     previous instruction due to a timing problem.  If the instruction
                    330:  *     is preceded by a NOP then the bits have time to settle and all
                    331:  *     is well.
                    332:  *     This chip fix routine will only fix IS25 instructions, BELLMAC-32B
                    333:  *     instructions are left untouched.
                    334:  */
                    335: pswcheck( insptr, addr)
                    336: register       instr   *insptr;
                    337: register       addrmode        *addr;
                    338: {
                    339:        instr   *newins;
                    340:        
                    341:        if ( (addr->admode == REGMD) && (addr->adreg == PSWREG) ) {
                    342:                newins = (*lookup("NOP",N_INSTALL,MNEMON)).itp;
                    343:                generate(newins->nbits,NOACTION,newins->opcode,NULLSYM);
                    344:                return(0);      /* indicate that NOP was generated */
                    345:        } else {
                    346:                return(1);      /* NOP not needed */
                    347:        }
                    348: }
                    349: 
                    350: #if    M32RSTFIX
                    351: /*
                    352:  *  The following routine is a workaround for the
                    353:  *  RESTORE chip bug.
                    354:  *
                    355:  *  The RESTORE instruction will be mapped into the
                    356:  *  following sequence of instructions.
                    357:  *
                    358:  *     RESTORE %rX  ===>       MOVAW  -Y(%fp), %sp
                    359:  *                             POPW    %r8
                    360:  *                             POPW    %rZ
                    361:  *                               .
                    362:  *                               .
                    363:  *                             POPW    %rX
                    364:  *                             POPW    %fp
                    365:  *
                    366:  *     where:
                    367:  *             Y is  4 * (3 - X)  (ie. 12-4X )
                    368:  *             Z is  Y - 1
                    369:  *
                    370:  *     and if %rW is %fp then the sequence is the following:
                    371:  *     RESTORE %fp ===>        MOVAW   -24(%fp),%sp
                    372:  *                             POPW    %fp
                    373:  */
                    374: restorefix(num)
                    375: register addrmode *num;
                    376: {
                    377:        register int numregs, rnum;
                    378:        instr *newins;
                    379:        static addrmode dispfp = {NOTYPE, DSPMD,FPREG,{ABS,NULLSYM,1L}};
                    380: 
                    381:        if (num->admode == REGMD) 
                    382:                        numregs = 9 - num->adreg;
                    383:        if (num->admode == IMMD) 
                    384:                        numregs = num->adexpr.expval;
                    385:        newins = (*lookup("MOVAW",N_INSTALL,MNEMON)).itp;
                    386:        generate(newins->nbits,NOACTION,newins->opcode,NULLSYM);
                    387:        dispfp.adexpr.expval = -24 + (4 * numregs);
                    388:        addrgen(newins,&dispfp,NOTYPE,1);
                    389:        generate(8,NOACTION,(long)(CREGMD<<4|SPREG),NULLSYM);
                    390:        /* generate MOVAW (12-4X)(%fp),%sp */
                    391:        newins = (*lookup("POPW",N_INSTALL,MNEMON)).itp;
                    392:        for (rnum=8; numregs > 0; numregs--,rnum--) {
                    393:                /* generate POPW with the register being 9-numreg */
                    394:                generate(newins->nbits,NOACTION,newins->opcode,NULLSYM);
                    395:                generate(8,NOACTION,(long)(CREGMD<<4|rnum),NULLSYM);
                    396:        }
                    397:        generate(newins->nbits,NOACTION,newins->opcode,NULLSYM);
                    398:        generate(8,NOACTION,(long)(CREGMD<<4|FPREG),NULLSYM);
                    399: }
                    400: #endif /* M32RSTFIX */
                    401: 
                    402: flags(flag)
                    403: char flag;
                    404: {
                    405:        char errmsg[28];
                    406: 
                    407:        switch(flag) {
                    408: 
                    409:        default:
                    410:                sprintf(errmsg,"Illegal flag (%c) - ignored",flag);
                    411:                werror(errmsg);
                    412:                break;
                    413:        } /* switch */
                    414: } /* flags */
                    415: 
                    416: #if MLDVFIX
                    417: /* 
                    418:  * Number:      er 1
                    419:  * 
                    420:  * Name: Flag Setting for Multiply/Divide
                    421:  * 
                    422:  * Description: There are two situations where the CPU sets the N & V
                    423:  *          flags but not the Z flag, even though the result is zero.
                    424:  *          The source operands must be of opposite signs, with
                    425:  *          an unsigned destination.  For multiply one source must be 0.
                    426:  *          For divide the absolute value of the numerator must be 
                    427:  *          non-zero and greater than the absolute value of the denominator.
                    428:  * 
                    429:  * Resolution: generate a warning diagnostic
                    430:  * 
                    431:  */
                    432: 
                    433: mulchk3(insptr,addr1,addr2,addr3)
                    434:            instr *
                    435: insptr;
                    436:            addrmode *
                    437: addr1;
                    438:            addrmode *
                    439: addr2;
                    440:            addrmode *
                    441: addr3;
                    442: {
                    443:    if (compare(insptr->name, "MULB3") == EQUAL ||
                    444:        compare(insptr->name, "MULH3") == EQUAL ||
                    445:        compare(insptr->name, "MULW3") == EQUAL ||
                    446:        compare(insptr->name, "DIVB3") == EQUAL ||
                    447:        compare(insptr->name, "DIVH3") == EQUAL ||
                    448:        compare(insptr->name, "DIVW3") == EQUAL ||
                    449:        compare(insptr->name, "MULB2") == EQUAL ||
                    450:        compare(insptr->name, "MULH2") == EQUAL ||
                    451:        compare(insptr->name, "MULW2") == EQUAL ||
                    452:        compare(insptr->name, "DIVB2") == EQUAL ||
                    453:        compare(insptr->name, "DIVH2") == EQUAL ||
                    454:        compare(insptr->name, "DIVW2") == EQUAL)
                    455:    {
                    456:               int 
                    457:       type1, type2, type3;
                    458: 
                    459:       switch (addr1->newtype)
                    460:       {
                    461:       case SBYTE:
                    462:       case SHALF:
                    463:       case SWORD:
                    464:         type1 = SIGNED;
                    465:         break;
                    466:       case UBYTE:
                    467:       case UHALF:
                    468:       case UWORD:
                    469:         type1 = UNSIGNED;
                    470:         break;
                    471:       case NOTYPE:
                    472:          switch(optype(insptr->tag,1))
                    473:          {
                    474:          case 0:       /* byte */
                    475:            type1 = UNSIGNED;
                    476:            break;
                    477:          case 1:       /* half */
                    478:            type1 = SIGNED;
                    479:            break;
                    480:          case 2:       /* word */
                    481:            type1 = SIGNED;
                    482:            break;
                    483:          }
                    484:       }
                    485:       switch (addr2->newtype)
                    486:       {
                    487:       case SBYTE:
                    488:       case SHALF:
                    489:       case SWORD:
                    490:         type2 = SIGNED;
                    491:         break;
                    492:       case UBYTE:
                    493:       case UHALF:
                    494:       case UWORD:
                    495:         type2 = UNSIGNED;
                    496:         break;
                    497:       case NOTYPE:
                    498:          type2 = type1;
                    499:       }
                    500:       switch (addr3->newtype)
                    501:       {
                    502:       case SBYTE:
                    503:       case SHALF:
                    504:       case SWORD:
                    505:         type3 = SIGNED;
                    506:         break;
                    507:       case UBYTE:
                    508:       case UHALF:
                    509:       case UWORD:
                    510:         type3 = UNSIGNED;
                    511:         break;
                    512:       case NOTYPE:
                    513:          type3 = type2;
                    514:       }
                    515:       if ( (addr1->admode == IMMD) && (addr1->adexpr.expval < 0 ) )
                    516:         type1 = SIGNED;
                    517:       if ( (addr2->admode == IMMD) && (addr2->adexpr.expval < 0 ) )
                    518:         type2 = SIGNED;
                    519: 
                    520:       if ( ( ( type1 == SIGNED ) || ( type2 == SIGNED ) ) &&
                    521:             ( type3 == UNSIGNED ) )
                    522: 
                    523:       {
                    524:         werror("Mixed signs with unsignd destination can cause erroneous flags");
                    525:       }
                    526:    }
                    527: } /* mulchk3 */
                    528: 
                    529: #endif
                    530: 
                    531: #if    ER21FIX
                    532: 
                    533: er21(insptr,addr1,addr2,addr3)
                    534:            instr *
                    535: insptr;
                    536:            addrmode *
                    537: addr1;
                    538:            addrmode *
                    539: addr2;
                    540:            addrmode *
                    541: addr3;
                    542: {
                    543:    if (compare(insptr->name, "MODB3") == EQUAL ||
                    544:        compare(insptr->name, "MODH3") == EQUAL ||
                    545:        compare(insptr->name, "MODW3") == EQUAL )
                    546:    {
                    547:               int 
                    548:       type1, type2, type3;
                    549: 
                    550:       switch (addr1->newtype)
                    551:       {
                    552:       case SBYTE:
                    553:       case SHALF:
                    554:       case SWORD:
                    555:         type1 = SIGNED;
                    556:         break;
                    557:       case UBYTE:
                    558:       case UHALF:
                    559:       case UWORD:
                    560:         type1 = UNSIGNED;
                    561:         break;
                    562:       case NOTYPE:
                    563:          switch(optype(insptr->tag,1))
                    564:          {
                    565:          case 0:       /* byte */
                    566:            type1 = UNSIGNED;
                    567:            break;
                    568:          case 1:       /* half */
                    569:            type1 = SIGNED;
                    570:            break;
                    571:          case 2:       /* word */
                    572:            type1 = SIGNED;
                    573:            break;
                    574:          }
                    575:       }
                    576:       switch (addr2->newtype)
                    577:       {
                    578:       case SBYTE:
                    579:       case SHALF:
                    580:       case SWORD:
                    581:         type2 = SIGNED;
                    582:         break;
                    583:       case UBYTE:
                    584:       case UHALF:
                    585:       case UWORD:
                    586:         type2 = UNSIGNED;
                    587:         break;
                    588:       case NOTYPE:
                    589:          type2 = type1;
                    590:       }
                    591:       switch (addr3->newtype)
                    592:       {
                    593:       case SBYTE:
                    594:       case SHALF:
                    595:       case SWORD:
                    596:         type3 = SIGNED;
                    597:         break;
                    598:       case UBYTE:
                    599:       case UHALF:
                    600:       case UWORD:
                    601:         type3 = UNSIGNED;
                    602:         break;
                    603:       case NOTYPE:
                    604:          type3 = type2;
                    605:       }
                    606:       if ( (addr1->admode == IMMD) && (addr1->adexpr.expval < 0 ) )
                    607:         type1 = SIGNED;
                    608:       if ( (addr2->admode == IMMD) && (addr2->adexpr.expval < 0 ) )
                    609:         type2 = SIGNED;
                    610: 
                    611:       if ( ( type2 == SIGNED ) && ( type3 == UNSIGNED ) )
                    612:       {
                    613:         werror
                    614:         ("Mixed signs with unsignd destination can cause erroneous flags");
                    615:       }
                    616:    }
                    617: } /* er21 */
                    618: 
                    619: #endif
                    620: 
                    621: #if ER16FIX
                    622: 
                    623: decrstk(i)
                    624:            int
                    625: i;
                    626: { /* decrstk */
                    627:            instr *
                    628:    tmpins;
                    629: 
                    630:    tmpins = (*lookup("SUBW2",N_INSTALL,MNEMON)).itp;
                    631:    generate(8, NOACTION, tmpins->opcode, NULLSYM);
                    632:    generate(8, NOACTION, i, NULLSYM);
                    633:    generate(8, NOACTION, (long)((CREGMD<<4)|SPREG), NULLSYM);
                    634: } /* decrstk */
                    635: 
                    636: incrstk(i)
                    637:            int
                    638: i;
                    639: { /* incrstk */
                    640:            instr *
                    641:    tmpins;
                    642: 
                    643:    tmpins = (*lookup("ADDW2",N_INSTALL,MNEMON)).itp;
                    644:    generate(8, NOACTION, tmpins->opcode, NULLSYM);
                    645:    generate(8, NOACTION, i, NULLSYM);
                    646:    generate(8, NOACTION, (long)((CREGMD<<4)|SPREG), NULLSYM);
                    647: } /* incrstk */
                    648: 
                    649: copyadd(addr1,addr2)
                    650:            addrmode *
                    651: addr1;
                    652:            addrmode *
                    653: addr2;
                    654: { /* copyadd */
                    655:    addr2->newtype = addr1->newtype;
                    656:    addr2->admode = addr1->admode;
                    657:    addr2->adreg = addr1->adreg;
                    658:    addr2->adexpr.exptype = addr1->adexpr.exptype;
                    659:    addr2->adexpr.symptr = addr1->adexpr.symptr;
                    660:    addr2->adexpr.expval = addr1->adexpr.expval;
                    661:    addr2->adexpr.fdexpval2 = addr1->adexpr.fdexpval2;
                    662:    addr2->expspec = addr1->expspec;
                    663: } /* copyadd */
                    664: 
                    665: gen2(op,addr1,addr2)
                    666:            char *
                    667: op;
                    668:            addrmode *
                    669: addr1;
                    670:            addrmode *
                    671: addr2;
                    672: { /* gen2 */
                    673:            instr *
                    674:    tmpins;
                    675: 
                    676:    tmpins = (*lookup(op,N_INSTALL,MNEMON)).itp;
                    677:    generate (tmpins->nbits, NOACTION, tmpins->opcode, NULLSYM);
                    678:    addrgen(tmpins,addr1,NOTYPE,1);
                    679:    addrgen(tmpins,addr2,NOTYPE,2);
                    680: } /* gen2 */
                    681: 
                    682: er16fix(insptr, arg1, arg2, arg3)
                    683:         instr *
                    684: insptr;
                    685:         addrmode *
                    686: arg1;
                    687:         addrmode *
                    688: arg2;
                    689:         addrmode *
                    690: arg3;
                    691: { /* er16fix */
                    692:            addrmode
                    693:    c_tmp1;
                    694:         addrmode *
                    695:    c_arg1 = &c_tmp1;
                    696:            addrmode
                    697:    c_tmp2;
                    698:         addrmode *
                    699:    c_arg2 = &c_tmp2;
                    700:            addrmode
                    701:    c_tmp3;
                    702:         addrmode *
                    703:    c_arg3 = &c_tmp3;
                    704:            instr *
                    705:    tmpins;
                    706: 
                    707:    if ( ! ( (compare(insptr->name, "MULH3") == EQUAL ) ||
                    708:            (compare(insptr->name, "MULB3") == EQUAL ) ||
                    709:            (compare(insptr->name, "MULW3") == EQUAL ) ||
                    710:            (compare(insptr->name, "DIVH3") == EQUAL ) ||
                    711:            (compare(insptr->name, "DIVB3") == EQUAL ) ||
                    712:            (compare(insptr->name, "DIVW3") == EQUAL ) ||
                    713:            (compare(insptr->name, "MODH3") == EQUAL ) ||
                    714:            (compare(insptr->name, "MODB3") == EQUAL ) ||
                    715:            (compare(insptr->name, "MODW3") == EQUAL ) ||
                    716:            (compare(insptr->name, "mulw3") == EQUAL ) ||
                    717:            (compare(insptr->name, "umulw3") == EQUAL ) ||
                    718:            (compare(insptr->name, "divw3") == EQUAL ) ||
                    719:            (compare(insptr->name, "udivw3") == EQUAL ) ||
                    720:            (compare(insptr->name, "modw3") == EQUAL ) ||
                    721:            (compare(insptr->name, "umodw3") == EQUAL ) ) )
                    722:       return(0); 
                    723: 
                    724:    if( ! ( (er16chk(arg1,arg3)) || (er16chk(arg2,arg3)) ) )
                    725:       return(0); 
                    726:    if( ! workaround )
                    727:       return(0); 
                    728: 
                    729:    if ( compare(insptr->name, "mulw3") == EQUAL)
                    730:       insptr = (*lookup("MULW3",N_INSTALL,MNEMON)).itp;
                    731:    if (compare(insptr->name, "umulw3") == EQUAL )
                    732:    {
                    733:       insptr = (*lookup("MULW3",N_INSTALL,MNEMON)).itp;
                    734:       arg1->newtype = UWORD;
                    735:    }
                    736: 
                    737:    if ( compare(insptr->name, "divw3") == EQUAL)
                    738:       insptr = (*lookup("DIVW3",N_INSTALL,MNEMON)).itp;
                    739:    if (compare(insptr->name, "udivw3") == EQUAL )
                    740:    {
                    741:       insptr = (*lookup("DIVW3",N_INSTALL,MNEMON)).itp;
                    742:       arg1->newtype = UWORD;
                    743:    }
                    744: 
                    745:    if ( compare(insptr->name, "modw3") == EQUAL)
                    746:       insptr = (*lookup("MODW3",N_INSTALL,MNEMON)).itp;
                    747:    if (compare(insptr->name, "umodw3") == EQUAL )
                    748:    {
                    749:       insptr = (*lookup("MODW3",N_INSTALL,MNEMON)).itp;
                    750:       arg1->newtype = UWORD;
                    751:    }
                    752: 
                    753:    incrstk(12);
                    754: 
                    755:    if (arg1->newtype == NOTYPE)
                    756:       switch(optype(insptr->tag,1))
                    757:       {
                    758:       case 0:  /* byte */
                    759:          arg1->newtype = UBYTE;
                    760:         break;
                    761:       case 1:  /* half */
                    762:         arg1->newtype = SHALF;
                    763:         break;
                    764:       case 2:  /* word */
                    765:         arg1->newtype = SWORD;
                    766:         break;
                    767:       }
                    768:    if (arg2->newtype == NOTYPE)
                    769:       arg2->newtype = arg1->newtype;
                    770:    if (arg3->newtype == NOTYPE)
                    771:       arg3->newtype = arg2->newtype;
                    772: 
                    773:    copyadd(arg1,c_arg1);
                    774:    copyadd(arg2,c_arg2);
                    775:    copyadd(arg3,c_arg3);
                    776: 
                    777:    if ( ( (c_arg1->admode == DSPMD  ) ||
                    778:           (c_arg1->admode == DSPDFMD) ||
                    779:          (c_arg1->admode == REGDFMD) ) &&
                    780:        ( c_arg1->adreg == SPREG      ) )
                    781:       c_arg1->adexpr.expval -= 12;
                    782:    if ( (c_arg1->admode == REGMD) && (c_arg1->adreg == SPREG) )
                    783:    {
                    784:       /* SUBW3  &12,%sp,c_arg1 */
                    785:       c_arg1->admode = DSPMD;
                    786:       c_arg1->adexpr.exptype = ABS;
                    787:       c_arg1->adexpr.symptr = NULLSYM;
                    788:       c_arg1->adexpr.expval = -12;
                    789: 
                    790:       tmpins = (*lookup("SUBW3",N_INSTALL,MNEMON)).itp;
                    791:       generate(tmpins->nbits, NOACTION, tmpins->opcode, NULLSYM);
                    792:       generate(8, NOACTION, 0x12L, NULLSYM);
                    793:       generate(8, NOACTION, (long)((CREGMD<<4)|SPREG), NULLSYM);
                    794:       addrgen(tmpins, c_arg1, NOTYPE, 3);
                    795:    }
                    796: 
                    797:    if ( ( (c_arg2->admode == DSPMD  ) ||
                    798:           (c_arg2->admode == DSPDFMD) ||
                    799:          (c_arg2->admode == REGDFMD) ) &&
                    800:        ( c_arg2->adreg == SPREG      ) )
                    801:       c_arg2->adexpr.expval -= 12;
                    802:    if ( (c_arg2->admode == REGMD) && (c_arg2->adreg == SPREG) )
                    803:    {
                    804:       /* SUBW3  &12,%sp,c_arg2 */
                    805:       c_arg2->admode = DSPMD;
                    806:       c_arg2->adexpr.exptype = ABS;
                    807:       c_arg2->adexpr.symptr = NULLSYM;
                    808:       c_arg2->adexpr.expval = -8;
                    809: 
                    810: 
                    811:       tmpins = (*lookup("SUBW3",N_INSTALL,MNEMON)).itp;
                    812:       generate(tmpins->nbits, NOACTION, tmpins->opcode, NULLSYM);
                    813:       generate(8, NOACTION, 0x12L, NULLSYM);
                    814:       generate(8, NOACTION, (long)((CREGMD<<4)|SPREG), NULLSYM);
                    815:       addrgen(tmpins, c_arg2, NOTYPE, 3);
                    816:    }
                    817: 
                    818:    c_arg3->admode = DSPMD;
                    819:    c_arg3->adreg = SPREG;
                    820:    c_arg3->adexpr.exptype = ABS;
                    821:    c_arg3->adexpr.symptr = NULLSYM;
                    822:    c_arg3->adexpr.expval = -4;
                    823: 
                    824:    generate(8,NOACTION,insptr->opcode,NULLSYM);
                    825:    addrgen(insptr,c_arg1,NOTYPE,1);
                    826:    addrgen(insptr,c_arg2,NOTYPE,2);
                    827:    addrgen(insptr,c_arg3,NOTYPE,3);
                    828: 
                    829:    if ( ( (arg3->admode == DSPMD  ) ||
                    830:           (arg3->admode == DSPDFMD) ||
                    831:          (arg3->admode == REGDFMD) ) &&
                    832:        ( arg3->adreg == SPREG      ) )
                    833:       arg3->adexpr.expval -= 12;
                    834: 
                    835:    gen2("MOVW",c_arg3,arg3);
                    836: 
                    837:    decrstk(12);
                    838: 
                    839:    c_arg3->adexpr.expval = 0;
                    840:    generate(8,NOACTION,insptr->opcode,NULLSYM);
                    841:    addrgen(insptr,arg1,NOTYPE,1);
                    842:    addrgen(insptr,arg2,NOTYPE,2);
                    843:    addrgen(insptr,c_arg3,NOTYPE,3);
                    844: 
                    845:    return(1);
                    846: 
                    847: } /* er16fix */
                    848: 
                    849: 
                    850: er16chk(addr1,addr2)
                    851: addrmode
                    852:        *addr1;
                    853: addrmode
                    854:        *addr2;
                    855: { /* er16chk */
                    856:    switch(addr2->admode)
                    857:    { /* switch(addr2->admode) */
                    858:    case REGDFMD: /* register deferred mode */
                    859:       switch(addr1->admode)
                    860:       {
                    861:       case DSPMD: /* displacement mode */
                    862:         if ( ( addr1->adreg == addr2->adreg ) &&
                    863:              ( abs(addr1->adexpr.expval - 0) >= 4 ) )
                    864:               return(NO);
                    865:          break;
                    866:       case REGMD: /* register mode */
                    867:         return(NO);
                    868:       }
                    869:       break;
                    870:    case DSPMD: /* displacement mode */
                    871:       switch(addr1->admode)
                    872:       {
                    873:       case DSPMD: /* displacement mode */
                    874:         if ( ( addr1->adreg == addr2->adreg ) &&
                    875:              ( abs(addr1->adexpr.expval - addr2->adexpr.expval) >=4 ) )
                    876:               return(NO);
                    877:          break;
                    878:       case REGMD: /* register mode */
                    879:         return(NO);
                    880:       }
                    881:       break;
                    882:    case DSPDFMD: /* displacement deferred mode */
                    883:       switch(addr1->admode)
                    884:       {
                    885:       case REGMD: /* register mode */
                    886:         return(NO);
                    887:       }
                    888:       break;
                    889:    case EXADMD: /* external address mode */
                    890:       switch(addr1->admode)
                    891:       {
                    892:       case REGMD: /* register mode */
                    893:         return(NO);
                    894:       }
                    895:       break;
                    896:    case ABSMD: /* absolute address mode */
                    897:       switch(addr1->admode)
                    898:       {
                    899:       case ABSMD: /* absolute address mode */
                    900:         if ( abs(addr1->adexpr.expval - addr2->adexpr.expval) >= 4 )
                    901:            return(NO);
                    902:          break;
                    903:       case REGMD: /* register mode */
                    904:         return(NO);
                    905:       }
                    906:       break;
                    907:    case EXADDFMD: /* external address deferred mode (PC relative deferred) */
                    908:       switch(addr1->admode)
                    909:       {
                    910:       case REGMD: /* register mode */
                    911:         return(NO);
                    912:       }
                    913:       break;
                    914:    case ABSDFMD: /* absolute address deferred mode */
                    915:       switch(addr1->admode)
                    916:       {
                    917:       case REGMD: /* register mode */
                    918:         return(NO);
                    919:       }
                    920:       break;
                    921:    case IMMD: /* immediate mode */
                    922:       return(NO);
                    923:    case REGMD: /* register mode */
                    924:       return(NO);
                    925:    } /* switch(addr2->admode) */
                    926:    return(YES);
                    927: } /* er16chk */
                    928: 
                    929: #endif

unix.superglobalmegacorp.com

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