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