|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.