Annotation of researchv9/cmd/sun/as/op.c, revision 1.1.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.