Annotation of researchv9/cmd/sun/as/op.c, revision 1.1

1.1     ! root        1: #ifndef lint
        !             2: static char sccsid[] = "@(#)op.c 1.1 86/02/03 Copyr 1985 Sun Micro";
        !             3: #endif
        !             4: 
        !             5: /*
        !             6:  * Copyright (c) 1985 by Sun Microsystems, Inc.
        !             7:  */
        !             8: 
        !             9: #include "as.h"
        !            10: 
        !            11: /* move_op - uses two effective addresses */
        !            12: 
        !            13: move_op( ip )
        !            14:     struct ins_bkt *ip;
        !            15: {
        !            16:        register struct oper *op1, *op2;
        !            17:        int r1, r2;
        !            18:        /*
        !            19:         * opval_i[0] -- movX   eaddr,eaddr
        !            20:         * opval_i[1] -- movl   Areg,USP
        !            21:         * opval_i[2] -- movw   eaddr,cc
        !            22:         * opval_i[3] -- movw   cc,eaddr
        !            23:         */
        !            24: 
        !            25:        op1 = operands;
        !            26:        op2 = &operands[1];
        !            27:        r1 = (int)op1->value_o;
        !            28:        r2 = (int)op2->value_o;
        !            29: 
        !            30:        if (sr_addr(op1)){
        !            31:                wcode[0] = ip->opval_i[3];
        !            32:                if (r1 != CCREG) wcode[0] ^= 1<<9;
        !            33:                eaddr(op2, SUBOP_W, 0);
        !            34:        } else if (sr_addr(op2)){
        !            35:                wcode[0] = ip->opval_i[2];
        !            36:                if (r2 != CCREG) wcode[0] ^= 1<<9;
        !            37:                eaddr(op1, SUBOP_W, 1);
        !            38:        } else if (usp_addr(op1)) {
        !            39:                wcode[0] = ip->opval_i[1] | 0x8 | (r2 & 07);
        !            40:        } else if (usp_addr(op2)) {
        !            41:                wcode[0] = ip->opval_i[1] | (r1 & 07);
        !            42:        } else {
        !            43:                unsigned reg, mode, source;
        !            44:                wcode[0] = 0;
        !            45:                /* get source address */
        !            46:                eaddr(op1, ip->subop_i, 0);
        !            47:                source = wcode[0];              /* save it */
        !            48:                wcode[0] = 0;
        !            49:                /* get destination address */
        !            50:                eaddr(op2, ip->subop_i, 1);
        !            51:                /* flip around destination address */
        !            52:                reg = wcode[0] & 07;
        !            53:                mode = (wcode[0] >> 3) & 07;
        !            54:                /* assemble instruction */
        !            55:                wcode[0] = ip->opval_i[0] | (reg << 9) | (mode << 6) | source;
        !            56:        }
        !            57: }
        !            58: /* two_ops - these are of the forms:
        !            59:        xxx Dn,<eaddr>
        !            60:        xxx <eaddr>,Dn
        !            61:        xxx #yyy,<eaddr>
        !            62:        xxx <eaddr>,An
        !            63:  */
        !            64: 
        !            65: two_op( ip )
        !            66:        register struct ins_bkt *ip;
        !            67: {
        !            68:        register struct oper *op1, *op2;
        !            69:        int r1, r2;
        !            70:        int wrtflg = ip->touchop_i&TOUCH2((BW|WW|LW)); /* 2nd operand write-to unless compare */
        !            71:        subop_t size = ip->subop_i;
        !            72:        op1 = &operands[0];
        !            73:        op2 = &operands[1];
        !            74:        r1 = (int)op1->value_o & 07;
        !            75:        r2 = (int)op2->value_o & 07;
        !            76: 
        !            77:        /*
        !            78:         * opval_i[0] -- op  eaddr,dreg
        !            79:         * opval_i[1] -- op  eaddr,areg
        !            80:         * opval_i[2] -- op  #imm,eaddr   OR  0xffff
        !            81:         * opval_i[3] -- op  #imm,cc
        !            82:         */
        !            83: 
        !            84:        if (areg_addr(op2)){
        !            85:            /* addl  xxx,a0 */
        !            86:            wcode[0] = ip->opval_i[1] |(r2<<9);
        !            87:            eaddr(op1, size, 0);
        !            88:        } else if (op1->type_o == T_IMMED && ip->opval_i[2] != 0xffff ) {
        !            89:            if (sr_addr(op2)){
        !            90:                /* andb #imm,cc */
        !            91:                wcode[0] = ip->opval_i[3];
        !            92:                /* byte-size to cc only, word-size to sr only */
        !            93:                if (!((op2->value_o == SRREG) ^ (size == SUBOP_B)))
        !            94:                    PROG_ERROR( E_OPERAND );
        !            95:                rel_val(op1, (size==SUBOP_L)?SUBOP_L:SUBOP_W, 0);
        !            96:            } else {
        !            97:                /* andw #imm,eaddr */
        !            98:                wcode[0] = ip->opval_i[2];
        !            99:                rel_val(op1, (size==SUBOP_L)?SUBOP_L:SUBOP_W, 0);
        !           100:                eaddr(op2, size, wrtflg);
        !           101:            }
        !           102:        } else {
        !           103:            wcode[0] = ip->opval_i[0];
        !           104:            /* notice closely:
        !           105:             *   op     d0,d1
        !           106:             * appears ambiguous. Actually, it is not.
        !           107:             * eor takes register only as source. other ops only 
        !           108:             * as destination.
        !           109:             */
        !           110:            if (!dreg_addr(op2) || ip->op_i == OP_EOR) {
        !           111:                /* op   dreg,eaddr & eorl dreg,dreg */
        !           112:                wcode[0] |= 0400|(r1<<9);
        !           113:                eaddr(op2, size, wrtflg);
        !           114:            } else {
        !           115:                /* op   eaddr,dreg  and op dreg,dreg */
        !           116:                /* note that mulu #imm,dreg ends up here, too */
        !           117:                wcode[0] |= (r2 << 9);
        !           118:                eaddr(op1, size, 0);
        !           119:            }
        !           120:        }
        !           121: }
        !           122: /* one_ops - install opr, check for exactly one operand and compute eaddr */
        !           123: 
        !           124: one_op( ip )
        !           125:     struct ins_bkt *ip;
        !           126: {
        !           127:        register struct oper *op = operands;
        !           128:        wcode[0] = ip->opval_i[0];
        !           129:        switch (ip->op_i){
        !           130:        case OP_CALL:
        !           131:        case OP_BRANCH:
        !           132:            if (jsrflag && op->type_o == T_NORMAL && op->sym_o != 0){
        !           133:                /* make this a pc-relative */
        !           134:                /*
        !           135:                op->value_o -= dot+2;
        !           136:                */
        !           137:                op->type_o = T_PCPLUS; /* MAGIC!! */
        !           138:                op->reg_o  = PCREG;
        !           139:            }
        !           140:        }
        !           141:        eaddr(op, ip->subop_i, ip->touchop_i&TOUCH1(LW|WW|BW));
        !           142: }
        !           143: 
        !           144: 
        !           145: /* no_op(opr) -- places opr in wcode[0]. */
        !           146: 
        !           147: no_op(ip)
        !           148:     struct ins_bkt *ip;
        !           149: {
        !           150:     wcode[0] = ip->opval_i[0];
        !           151: };
        !           152: 
        !           153: /* branch_op - process branch offsets */
        !           154: /* also handle DBcc instructions */
        !           155: branch_op(ip)
        !           156:     struct ins_bkt *ip;
        !           157: {
        !           158:        long offs = 0;
        !           159:        register struct oper *opp = operands;
        !           160: 
        !           161:        wcode[0] = ip->opval_i[0];
        !           162:        if (ip->noper_i == 2){
        !           163:            wcode[0] |= opp->value_o;
        !           164:            opp  += 1;
        !           165:        }
        !           166:        if ( opp->sym_o && (opp->sym_o->attr_s & S_DEF) == 0){
        !           167:                /* external branch -- good luck */
        !           168:                ;
        !           169:        } else if (opp->sym_o == 0 || opp->sym_o->csect_s != cur_csect_name){
        !           170:                PROG_ERROR(E_RELOCATE);
        !           171:        } else {
        !           172:                opp->sym_o = 0; /* mark as non relocateable expression */
        !           173:        }
        !           174:        offs = opp->value_o - (dot + 2);
        !           175:        if (offs > 32767L || offs < -32768L)
        !           176:                PROG_ERROR(E_OFFSET);
        !           177:        opp->value_o = (int)offs;
        !           178:        rel_val(opp, SUBOP_W, opp->sym_o != 0);
        !           179: }
        !           180: 
        !           181: 
        !           182: brnchs_op(ip)
        !           183:     struct ins_bkt *ip;
        !           184: {
        !           185:        long offs = 0;
        !           186:        register struct oper *opp = operands;
        !           187: 
        !           188:        wcode[0] = ip->opval_i[0];
        !           189:        if ( opp->sym_o && (opp->sym_o->attr_s & S_DEF) == 0){
        !           190:                /* external branch -- out of luck */
        !           191:                PROG_ERROR(E_RELOCATE);
        !           192:        } else if (opp->sym_o == 0 || opp->sym_o->csect_s != cur_csect_name){
        !           193:                PROG_ERROR(E_RELOCATE);
        !           194:        } 
        !           195:        offs = opp->value_o - (dot + 2);
        !           196:        if (offs > 127 || offs < -128)
        !           197:                PROG_ERROR(E_OFFSET);
        !           198:        if (offs != 0){
        !           199:            wcode[0] |= offs & 0377;
        !           200:        } else if ( ip->op_i != OP_CALL ){
        !           201:            /*
        !           202:             * this is not a bsr, and we have a PC-relative address of zero
        !           203:             * if we just spit this out as usual, it would look just like
        !           204:             * the beginning of a longer form of jump. So instead,
        !           205:             * we emit a "nop" instruction right here.
        !           206:             */
        !           207:            wcode[0] = 0x4e71;
        !           208:        } else {
        !           209:            PROG_ERROR(E_OFFSET);
        !           210:        }
        !           211: }
        !           212: 
        !           213: /* it is not clear that we can get there from here.
        !           214:  * If this is a 68020 instruction generation, then we can use
        !           215:  * the long form of the branch. Otherwise, if this is an
        !           216:  * unconditional, then we can use a long jump. Otherwise,
        !           217:  * we must generate a branch-around-a-jump.
        !           218:  */
        !           219: brnchl_op(ip)
        !           220:     struct ins_bkt *ip;
        !           221: {
        !           222:     register struct oper *opp = &operands[0];
        !           223:     int offs;
        !           224:     if (ext_instruction_set){
        !           225:        wcode[0] = ip->opval_i[0] | 0377;
        !           226:        if (opp->sym_o && ((opp->sym_o->attr_s & S_DEF) == 0)){
        !           227:                /* external branch -- good luck */
        !           228:                ;
        !           229:        } else if ((opp->sym_o==0) || (opp->sym_o->csect_s!=cur_csect_name)){
        !           230:                /* PROG_ERROR(E_RELOCATE); */
        !           231:        } else {
        !           232:                opp->sym_o = 0; /* mark as non relocateable expression */
        !           233:        }
        !           234:        offs = opp->value_o - (dot + 2);
        !           235:        opp->value_o = (int)offs;
        !           236:        rel_val(opp, SUBOP_L, opp->sym_o != 0);
        !           237:     } else {
        !           238:        /* this is not an extended-instruction set assembly */
        !           239:        hard_branch( ip, opp );
        !           240:     }
        !           241: }
        !           242: 
        !           243: static
        !           244: hard_branch( ip, opp )
        !           245:     register struct ins_bkt *ip;
        !           246:     register struct oper *opp;
        !           247: {
        !           248:     /* choose alternate opcode -- either long form or complement */
        !           249:     wcode[0] = ip->opval_i[1];
        !           250:     /*
        !           251:      * if we are unconditional, just use the long mode.
        !           252:      * otherwise, do the jump-around-jump
        !           253:      */
        !           254:     if (ip->subop_i == JALL){
        !           255:        if (jsrflag && opp->type_o == T_NORMAL && opp->sym_o != 0){
        !           256:            /* make this a pc-relative */
        !           257:            /*
        !           258:                opp->value_o -= dot+2;
        !           259:            */
        !           260:            opp->type_o = T_PCPLUS; /* MAGIC!! */
        !           261:            opp->reg_o  = PCREG;
        !           262:        }
        !           263:        eaddr(opp, SUBOP_L, 0);
        !           264:        return;
        !           265:     } else if (d2flag && (opp->type_o == T_NORMAL) ){
        !           266:        /* we're really doing short displacements, anyway */
        !           267:        branch_op( ip );
        !           268:        return;
        !           269:     } else {
        !           270:        /* use complementary branch over jump */
        !           271:        /* we'll fool eaddr() by building the jump instruction in wcode[0], then moving it */
        !           272:        /* its address word, though, must be built in the right place */
        !           273:        wcode[0] = 0x4EC0;              /* jmp xxxxxx */
        !           274:        code_length = 4;                /* so far */
        !           275:        eaddr(opp, SUBOP_L, 0);         /* the address */
        !           276:        wcode[1] = wcode[0];
        !           277:        wcode[0] = ip->opval_i[1] + code_length - 2;
        !           278:     }
        !           279: }
        !           280: /*
        !           281:  * generate a short or a long branch instruction as appropriate
        !           282:  * note that:
        !           283:  *             jra     foo
        !           284:  *     foo:
        !           285:  * is translated (by brnchs_op) to a nop.  If we attempt to
        !           286:  * optimize this to generate no code, then after resolving
        !           287:  * the span-dependent instructions, the value of
        !           288:  * foo is the same as the address of the jra instruction.
        !           289:  * Therefore, on pass 2, the jra looks like a jra .
        !           290:  * Presumably, this could be fixed by keeping more information
        !           291:  * after the sdi's are resolved
        !           292:  */
        !           293: jbrnch_op( ip )
        !           294:        struct ins_bkt *ip;
        !           295: {
        !           296:        long offs = 0;
        !           297:        register struct oper *opp = operands;
        !           298:        int longsize, longsdi, useshort;
        !           299: 
        !           300:        if (opp->type_o != T_NORMAL || opp->sym_o == NULL) {
        !           301:                /* not a relocatable operand */
        !           302:                hard_branch( ip, opp );
        !           303:        } else {
        !           304:                offs = opp->value_o - (dot + 2);
        !           305:                if (hflag && ip->op_i != OP_CALL)
        !           306:                    useshort = 1;
        !           307:                else
        !           308:                    useshort = d2flag||jsrflag;
        !           309:                if ((ip->subop_i == JALL) || ext_instruction_set){
        !           310:                    longsize = 6;
        !           311:                    longsdi = SDI6;
        !           312:                } else {
        !           313:                    longsize = 8;
        !           314:                    longsdi = SDI8;
        !           315:                }
        !           316:                if (opp->flags_o & O_COMPLEX)   /* not a simple address */
        !           317:                        hard_branch( ip, opp );
        !           318:                else if (pass == 1){
        !           319:                        if (cansdi) {
        !           320:                            if (ip->op_i == OP_CALL && !Oflag &&
        !           321:                                operands->sym_o->value_s == 0 )
        !           322:                            /* jbsr w/ forward reference */
        !           323:                                goto no_sdi;
        !           324:                            code_length = makesdi(opp, dot + 2, 
        !           325:                                useshort ? SDI4 : longsdi);
        !           326:                        }
        !           327:                        else
        !           328:                no_sdi:
        !           329:                            code_length = useshort? 4 : longsize;
        !           330:                        put_rel( opp, SUBOP_L, dot+2, 0); /* may be to external */
        !           331:                } else {
        !           332:                        /* pass 2 */
        !           333:                        if (opp->sym_o == 0
        !           334:                         || opp->sym_o->csect_s != cur_csect_name
        !           335:                         || offs < -32768L || offs > 32767L
        !           336:                         || !cansdi ){
        !           337: #ifdef EBUG
        !           338:                                if (debflag>1)
        !           339:                                    printf("jbrnch(2): external branch line %d offset 0x%X\n",
        !           340:                                        line_no, dot);
        !           341: #endif
        !           342:                                if (useshort) branch_op(ip);
        !           343:                                else          brnchl_op( ip );
        !           344:                        }else if (ip->op_i == OP_CALL && !Oflag &&
        !           345:                                  (operands->sym_o->value_s == 0 ||
        !           346:                                   operands->sym_o->value_s > dot ) ){
        !           347:                                cansdi = 0;    /* fake temperarily */
        !           348:                                hard_branch(ip, opp);
        !           349:                                cansdi = 1;
        !           350:                        }else if (offs > 127 || offs < -128){
        !           351: #ifdef EBUG
        !           352:                                if (debflag>1)
        !           353:                                    printf("jbrnch(2): 4 byte branch line %d offset 0x%X\n",
        !           354:                                        line_no, dot);
        !           355: #endif
        !           356:                                branch_op(ip);
        !           357:                        }else{
        !           358: #ifdef EBUG
        !           359:                                if (debflag>1)
        !           360:                                    printf("jbrnch(2): 2 byte branch line %d offset 0x%X\n",
        !           361:                                        line_no, dot);
        !           362: #endif
        !           363:                                brnchs_op(ip);
        !           364:                        }
        !           365:                }
        !           366:        }
        !           367:        return;
        !           368: }
        !           369: 
        !           370:  /* 
        !           371:  * instructions of the form xxx Ax@+,Ay@+
        !           372:  * and those of the forms   xxx Dx,Dy
        !           373:  *                     or   xxx Ax@-,Ay@-
        !           374:  */
        !           375: 
        !           376: regmem_op(ip)
        !           377:     struct ins_bkt *ip;
        !           378: {
        !           379:        wcode[0] = ip->opval_i[0] 
        !           380:                | (operands[0].value_o&07) | ((operands[1].value_o&07)<<9);
        !           381:        if (operands[0].type_o == T_PREDEC ) {
        !           382:                wcode[0] |= 010;
        !           383:        }
        !           384: }
        !           385: 
        !           386: /*
        !           387:  * quick_op -- instructions such as "addqw     #7,d0"
        !           388:  */
        !           389: 
        !           390: quick_op( ip )
        !           391:     struct ins_bkt *ip;
        !           392: {
        !           393:     register int val = operands[0].value_o;
        !           394:     if ( val <= 0 || val > 8 )
        !           395:        PROG_ERROR( E_CONSTANT);
        !           396:     if (val == 8 ) 
        !           397:        val = 8;
        !           398:     wcode[0] = ip->opval_i[0] | (val<<9);
        !           399:     eaddr( &operands[1], ip->subop_i, 0);
        !           400: }
        !           401: 
        !           402: /* shift op -  shift either a register or an effective address */
        !           403: 
        !           404: shift_op( ip )
        !           405:     struct ins_bkt *ip;
        !           406: {
        !           407:        register struct oper *op1, *op2;
        !           408:        op1 = &operands[0];
        !           409:        op2 = &operands[1];
        !           410:        /*
        !           411:         * opval_i[0] -- register-shift opcode
        !           412:         * opval_i[1] -- memory-shift opcode
        !           413:         */
        !           414: 
        !           415:        if (numops == 1) {
        !           416:            wcode[0] = ip->opval_i[1];
        !           417:            eaddr(op1, SUBOP_W, 1);
        !           418:        } else {
        !           419:            int val1, val2;
        !           420:            wcode[0] = ip->opval_i[0];
        !           421:            val1 = (int)op1->value_o;
        !           422:            val2 = (int)op2->value_o;
        !           423:            if (op1->type_o==T_IMMED) {
        !           424:                if (val1 == 8) val1 = 0;
        !           425:            } else {
        !           426:                wcode[0] |=  040;
        !           427:            }
        !           428:            wcode[0] |= ((val1 & 07) << 9) | (val2 & 07);
        !           429:        }
        !           430: }
        !           431: /* bit_op - of the form xxx Dn,<eaddr> or xxx #nnn,<eaddr> */
        !           432: 
        !           433: bit_op( ip )
        !           434:        struct ins_bkt *ip;
        !           435: {
        !           436:        register struct oper *op1 ;
        !           437:        /*
        !           438:         * opval_i[0] -- bit number dynamic
        !           439:         * opval_i[1] -- bit number static
        !           440:         */
        !           441:        op1 = operands;
        !           442: 
        !           443:        wcode[0] = ip->opval_i[0];
        !           444:        if (op1->type_o == T_REG ) {
        !           445:            /* <eaddr> is destination */
        !           446:            wcode[0] = ip->opval_i[0] | ((int)op1->value_o << 9);
        !           447:            eaddr(&operands[1], SUBOP_W, 1);
        !           448:        } else {
        !           449:            wcode[0] = ip->opval_i[1];
        !           450:            rel_val(op1, SUBOP_W, 0);
        !           451:            eaddr(&operands[1], SUBOP_W, 1);
        !           452:        }
        !           453: }
        !           454: 
        !           455: /*
        !           456:  * bitf_op -- single-operand bit-field instructions 
        !           457:  */
        !           458: bitf_op( ip )
        !           459:     struct ins_bkt *ip;
        !           460: {
        !           461:     register struct oper *o = &operands[0];
        !           462:     register flags = o->flags_o;
        !           463:     wcode[0] = ip->opval_i[0];
        !           464:     if (!(flags&O_BFLD))
        !           465:        PROG_ERROR(E_OPERAND);
        !           466:     wcode[1] = 0;
        !           467:     if (flags&O_BFOREG)
        !           468:        wcode[1] |= 1<<11;
        !           469:     wcode[1] |= o->bfoffset_o << 6;
        !           470:     if (flags&O_BFWREG)
        !           471:        wcode[1] |= 1<<5;
        !           472:     wcode[1] |= o->bfwidth_o;
        !           473:     code_length += 2;
        !           474:     o->flags_o &= ~O_BFLD;
        !           475:     eaddr( o, SUBOP_W, 1);
        !           476: }
        !           477: 
        !           478: /*
        !           479:  * bitfr_op -- bit-field + register instructions.
        !           480:  */
        !           481: bitfr_op( ip )
        !           482:     struct ins_bkt *ip;
        !           483: {
        !           484:     struct oper * r ;
        !           485:     int reg;
        !           486:     r = &operands[0];
        !           487:     if (!(r->flags_o&O_BFLD)){
        !           488:        /* first operand register */
        !           489:        /* extract value, slide on down */
        !           490:        reg = r->value_o;
        !           491:        *r = operands[1];
        !           492:     } else {
        !           493:        /* second operand register */
        !           494:        /* just extract value */
        !           495:        reg = operands[1].value_o;
        !           496:     }
        !           497:     bitf_op( ip ); /* do most of the work; */
        !           498:     wcode[1] |= reg << 12; /* finish off */
        !           499: }
        !           500: 
        !           501: /* exg_op - instructions like exg rx,ry */
        !           502: 
        !           503: exg_op( ip )
        !           504:        struct ins_bkt *ip;
        !           505: {
        !           506:        int r1, r2;
        !           507:        register struct oper *op1, *op2;
        !           508:        op1 = operands;
        !           509:        op2 = &operands[1];
        !           510:        r1 = (int)op1->value_o;
        !           511:        r2 = (int)op2->value_o;
        !           512: 
        !           513:        wcode[0] = ip->opval_i[0];
        !           514:        if (dreg(r1) && dreg(r2))
        !           515:                wcode[0] |= 0100 | (r1 << 9) | r2;
        !           516:        else if (areg(r1) && areg(r2))
        !           517:                wcode[0] |= 0110 | ((r1 & 07) << 9) | (r2 & 07);
        !           518:        else if (areg(r1) && dreg(r2))
        !           519:                wcode[0] |= 0210 | (r2 << 9) | (r1 & 07);
        !           520:        else if (dreg(r1) && areg(r2))
        !           521:                wcode[0] |= 0210 | (r1 << 9) | (r2 & 07);
        !           522:        else
        !           523:                PROG_ERROR( E_OPERAND );
        !           524: }              
        !           525: /* reg_op - instructions that take one register operand */
        !           526: 
        !           527: reg_op( ip )
        !           528:     struct ins_bkt *ip;
        !           529: {
        !           530:     wcode[0] = ip->opval_i[0] | (operands[0].value_o & 07);
        !           531: }
        !           532: 
        !           533: 
        !           534: /* link_op - form: link An,#<disp> */
        !           535: 
        !           536: link_op( ip )
        !           537:     struct ins_bkt *ip;
        !           538: {
        !           539:     register int v = operands[1].value_o;
        !           540:     /* 
        !           541:      * opval_i[0] -- normal short form
        !           542:      * opval_i[1] -- extended long form
        !           543:      */
        !           544:     if ( (ip->opval_i[0] == 0) ||              /* If linkl requested specifically, */
        !           545:        v < -32768 || v > 32767 ||      /* or displacement too big for linkw, */ 
        !           546:        !( operands[1].sym_o == NULL || operands[1].sym_o->attr_s & S_DEF))
        !           547:                                        /* or displacement is relocatable !!, */
        !           548:                                        { /* try long form. */
        !           549:        if (ext_instruction_set         /* If generating 68020 code, */
        !           550:            && (ip->opval_i[1] != 0))   /* and linkw not requested specifically, */
        !           551:                                        { /* try long form. */
        !           552:             if (!(operands[1].sym_o==NULL || operands[1].sym_o->attr_s&S_DEF)
        !           553:                 && pass==1 && cansdi){
        !           554:                 (void)makeddi( &operands[1], dot+code_length, SDIL, 0);
        !           555:             }
        !           556:            wcode[0] = ip->opval_i[1] | (operands[0].value_o & 07);
        !           557:            rel_val(&operands[1], SUBOP_L, 0);
        !           558:            return;
        !           559:        } else if ( v < -32768 || v > 32767)
        !           560:            PROG_ERROR(E_CONSTANT);
        !           561:        /* else is external -- take pot luck */
        !           562:     }
        !           563:     wcode[0] = ip->opval_i[0] | (operands[0].value_o & 07);
        !           564:     rel_val(&operands[1], SUBOP_W, 0);
        !           565: }
        !           566: 
        !           567: 
        !           568: /* movec_op - for the very weird movc instruction: movec rn,rc   */
        !           569: /*             where rc is in { usp, sfc, dfc, vbr }            */
        !           570: 
        !           571: movec_op( ip )
        !           572:     struct ins_bkt *ip;
        !           573: {
        !           574:     register struct oper *op1, *op2;
        !           575:     register reg;
        !           576:     register creg;
        !           577:     static ctrl_reg_values[] = 
        !           578:     /*  USP   SFC   DFC   VBR  CACR  CAAR   MSP   ISP */
        !           579:     { 0x800,   0,    1, 0x801,   2, 0x802, 0x803, 0x804 };
        !           580:     op1 = operands;
        !           581:     op2 = &operands[1];
        !           582:     wcode[0] = ip->opval_i[0];
        !           583:     code_length = 4;
        !           584:     if (ctrl_reg(op1->value_o)){
        !           585:            /* from control reg to user reg */
        !           586:            creg = op1->value_o;
        !           587:            reg  = op2->value_o;
        !           588:     }else {
        !           589:            /* from user reg to control reg */
        !           590:            wcode[0] |= 1;
        !           591:            creg = op2->value_o;
        !           592:            reg  = op1->value_o;
        !           593:     }
        !           594:     creg = ctrl_reg_values[ creg - USPREG ];
        !           595:     wcode[1] = ((reg&07)<<12) | creg;
        !           596:     if(areg(reg)){
        !           597:        wcode[1] |= 0x8000;
        !           598:     }
        !           599: }
        !           600: 
        !           601: /* moves_op - for the very weird movs instruction:              */
        !           602: /*             moves rn,eaddr or moves eaddr,rn                 */
        !           603: 
        !           604: moves_op( ip )
        !           605:     struct ins_bkt *ip;
        !           606: {
        !           607:        register struct oper *op1, *op2;
        !           608:        register reg;
        !           609:        op1 = operands;
        !           610:        op2 = &operands[1];
        !           611:        wcode[0] = ip->opval_i[0];
        !           612:        code_length = 4;
        !           613:        if ( op1->type_o == T_REG ){
        !           614:            /* from register to other space */
        !           615:            reg = op1->value_o;
        !           616:            wcode[1] = 1<<11;
        !           617:            eaddr( op2, ip->subop_i, 1);
        !           618:        } else {
        !           619:            /* from outer space to register */
        !           620:            reg = op2->value_o;
        !           621:            wcode[1] = 0;
        !           622:            eaddr( op1, ip->subop_i, 0);
        !           623:        } 
        !           624:        wcode[1] |= (reg&07)<<12;
        !           625:        if(areg(reg)){
        !           626:            wcode[1] |= 0x8000;
        !           627:        }
        !           628: }
        !           629: 
        !           630: 
        !           631: int reverse_bits( forward )
        !           632:        int forward ;
        !           633: 
        !           634: /*
        !           635:        result = forward with with 16 low order bits in reverse order.
        !           636: */
        !           637: 
        !           638: {
        !           639: int bit, new ;
        !           640: long i ;
        !           641: 
        !           642: new = 0 ;
        !           643: bit = 0x8000 ;
        !           644: 
        !           645: for (i=0 ; i<16 ; i++ ) 
        !           646:        {
        !           647:        if (forward & 1) new |= bit ;
        !           648:        forward = forward >> 1 ;
        !           649:        bit = bit >> 1 ;
        !           650:        }
        !           651: return(new) ;
        !           652: }
        !           653: 
        !           654: /* movem_op -  of the form: movem #xxx,<eaddr> or movem <eaddr>,#xxx */
        !           655: 
        !           656: movem_op( ip )
        !           657:        struct ins_bkt *ip;
        !           658: {
        !           659:        register struct oper *op1, *op2;
        !           660:        op1 = operands;
        !           661:        op2 = &operands[1];
        !           662:        switch (op1->type_o) 
        !           663:                {
        !           664:                case T_REGLIST: /*      movem   <reglist>,<ea> */
        !           665:                        if (op2->type_o == T_PREDEC) /* reverse mask for an@- */
        !           666:                                op1->value_o = reverse_bits(op1->value_o) ;
        !           667:                case T_IMMED:   /*      movem   #xxx,<ea> */
        !           668:                        {
        !           669:                        wcode[0] = ip->opval_i[0];
        !           670:                        rel_val(op1, SUBOP_W, 0);
        !           671:                        eaddr(op2, SUBOP_W, 1);
        !           672:                        break ;
        !           673:                        }
        !           674:                default: 
        !           675:                        {
        !           676:                                /*      movem   <ea>,#xxx       */
        !           677:                                /*      movem   <ea>,<reglist>  */
        !           678:                        wcode[0] = ip->opval_i[1];
        !           679:                        rel_val(op2, SUBOP_W, 0);
        !           680:                        eaddr(op1, SUBOP_W, 0);
        !           681:                        }
        !           682:                }
        !           683: }
        !           684: 
        !           685: /* movep_op - of the form:  movep Dx,Ay@(d) or movep Ay@(d),Dx */
        !           686: 
        !           687: movep_op(ip)
        !           688:        struct ins_bkt *ip;
        !           689: {
        !           690:        register struct oper *op1, *op2;
        !           691:        int r1, r2;
        !           692:        /*
        !           693:         * opval_i[0] -- memory-to-register
        !           694:         * opval_i[1] -- register-to-memory
        !           695:         */
        !           696:        op1 = operands;
        !           697:        op2 = &operands[1];
        !           698:        r1 = (int)op1->value_o;
        !           699:        r2 = (int)op2->value_o;
        !           700:        if (op1->type_o == T_REG ) {
        !           701:            /* register-to-memory */
        !           702:            wcode[0] = ip->opval_i[1] | (r1 << 9) | (op2->reg_o & 07);
        !           703:            rel_val(op2, SUBOP_W, 0);           
        !           704:        } else {
        !           705:            /* memory-to-register */
        !           706:            wcode[0] = ip->opval_i[0] | (r2 << 9) | (op1->reg_o & 07);
        !           707:            rel_val(op1, SUBOP_W, 0);
        !           708:        }
        !           709: }      
        !           710: 
        !           711: 
        !           712: /* moveq -  form: moveq #<data>,Dn */
        !           713: 
        !           714: moveq_op( ip )
        !           715:        struct ins_bkt *ip;
        !           716: {
        !           717:        register struct oper *op1, *op2;
        !           718:        int r2;
        !           719:        op1 = operands;
        !           720:        op2 = &operands[1];
        !           721:        r2 = (int)op2->value_o;
        !           722:        if (op1->value_o > 0177 || op1->value_o < -0200)
        !           723:                PROG_ERROR(E_CONSTANT);
        !           724:        wcode[0] = ip->opval_i[0] | (r2 << 9) | ((short)op1->value_o & 0377);
        !           725: }
        !           726: 
        !           727: 
        !           728: /* trap - form: trap #xxx */
        !           729: 
        !           730: trap( ip )
        !           731:        struct ins_bkt *ip;
        !           732: {
        !           733:         wcode[0] = ip->opval_i[0] | (((char)operands[0].value_o) & 017);
        !           734: }
        !           735: 
        !           736: /* stop instruction -- form is stop #xxxx */
        !           737: stop( ip )
        !           738:        struct ins_bkt *ip;
        !           739: {
        !           740:         wcode[0] = ip->opval_i[0];
        !           741:        rel_val( &operands[0], ip->subop_i, 0 );
        !           742: }
        !           743: 
        !           744: /* rts instruction -- may or may not take an operand */
        !           745: rts_op( ip )
        !           746:        struct ins_bkt *ip;
        !           747: {
        !           748:        register struct oper *opp = operands;
        !           749:        /*
        !           750:         * opval_i[0] -- no  operand
        !           751:         * opval_i[1] -- one operand
        !           752:         */
        !           753:        if (numops == 1){
        !           754:                /* new form -- with operand */
        !           755:                wcode[0] = ip->opval_i[1];
        !           756:                wcode[1] = 0xffff & opp->value_o;
        !           757:                code_length = 4;
        !           758:        } else {
        !           759:                wcode[0] = ip->opval_i[0];
        !           760:        }
        !           761: }
        !           762: 
        !           763: /*
        !           764:  *  chk2_op -- instructions of chk2X and cmp2X families: 
        !           765:  *  take register number (plus one bit) in an extension word
        !           766:  */
        !           767: chk2_op( ip )
        !           768:     struct ins_bkt *ip;
        !           769: {
        !           770:     /* 
        !           771:      * opval_i[0] -- opcode 
        !           772:      * opval_i[1] -- extension word
        !           773:      */
        !           774:     wcode[0] = ip->opval_i[0];
        !           775:     wcode[1] = ip->opval_i[1] | ( operands[1].value_o<<12 );
        !           776:     code_length += 2;
        !           777:     eaddr( &operands[0], ip->subop_i, 0 );
        !           778: }
        !           779: 
        !           780: /*
        !           781:  * div_op -- long-form divide and multiply instructions that take
        !           782:  * a register or register pair as operands
        !           783:  */
        !           784: div_op( ip )
        !           785:     struct ins_bkt *ip;
        !           786: {
        !           787:     /* 
        !           788:      * opval_i[0] -- opcode 
        !           789:      * opval_i[1] -- extension word
        !           790:      * opval_i[2] -- alternate extension word to be used if regpair 2nd operand
        !           791:      */
        !           792:     wcode[0] = ip->opval_i[0];
        !           793:     if (operands[1].type_o == T_REGPAIR){
        !           794:        wcode[1] = ip->opval_i[2] | (operands[1].reg_o<<12) | operands[1].value_o;
        !           795:     } else {
        !           796:        wcode[1] = ip->opval_i[1] | (operands[1].value_o<<12) | operands[1].value_o;
        !           797:     }
        !           798:     code_length += 2;
        !           799:     eaddr( &operands[0], SUBOP_L, 0 );
        !           800: }
        !           801: 
        !           802: /* callm_op -- process the callm instruction */
        !           803: callm_op( ip )
        !           804:     struct ins_bkt *ip;
        !           805: {
        !           806:     wcode[0] = ip->opval_i[0];
        !           807:     wcode[1] = operands[0].value_o;
        !           808:     code_length += 2;
        !           809:     eaddr( &operands[1], SUBOP_L, 0 );
        !           810: }
        !           811: 
        !           812: /*
        !           813:  * cas1_op -- stupid comapare & set.
        !           814:  */
        !           815: cas1_op( ip )
        !           816:     struct ins_bkt *ip;
        !           817: {
        !           818:     wcode[0] = ip->opval_i[0];
        !           819:     wcode[1] = (operands[1].value_o<<6) + (operands[0].value_o);
        !           820:     code_length += 2;
        !           821:     eaddr( &operands[2], ip->subop_i, 1);
        !           822: }
        !           823: 
        !           824: /*
        !           825:  * cas2_op -- stupid comapare & set.
        !           826:  */
        !           827: cas2_op( ip )
        !           828:     struct ins_bkt *ip;
        !           829: {
        !           830:     register struct oper * op = &operands[0];
        !           831:     wcode[0] = ip->opval_i[0];
        !           832:     wcode[1] = (op[2].value_o<<12) + (op[1].value_o<<6) + (op[0].value_o);
        !           833:     wcode[2] = (op[2].reg_o<<12) + (op[1].reg_o<<6) + (op[0].reg_o);
        !           834:     code_length += 4;
        !           835: }
        !           836: 
        !           837: /*
        !           838:  * pack_op -- the ridiculous bcd pack instruction.
        !           839:  */
        !           840: pack_op( ip )
        !           841:     struct ins_bkt *ip;
        !           842: {
        !           843:     wcode[0] = ip->opval_i[0] | ((operands[0].type_o==T_REG)?0 : (1<<3));
        !           844:     wcode[0] |= operands[0].value_o&07 | ((operands[1].value_o&07)<<9);
        !           845:     rel_val( &operands[2], SUBOP_W, 0);
        !           846: }

unix.superglobalmegacorp.com

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