|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)coprocessor.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: cp_general( ip ) ! 12: struct ins_bkt *ip ; ! 13: ! 14: { ! 15: struct oper *op1, *op2 ; ! 16: unsigned r1, r2 ; ! 17: ! 18: /* ! 19: opval_i[0] -- fop ea,fpn ! 20: opval_i[1] -- fop fpm,fpn ! 21: */ ! 22: ! 23: op1 = &operands[0] ; ! 24: op2 = &operands[1] ; ! 25: r2 = (int) op2 -> value_o - FP0REG ; ! 26: code_length = 4 ; ! 27: wcode[0] = 0xf000 + current_cpid * 01000 ; ! 28: ! 29: if (freg_addr(op1)) ! 30: { ! 31: r1 = (int) op1 -> value_o - FP0REG ; ! 32: wcode[1] = ip->opval_i[1] + r2 * 0200 + r1 * 02000 ; ! 33: } ! 34: else ! 35: { ! 36: wcode[1] = ip->opval_i[0] + r2 * 0200 ; ! 37: eaddr( op1, ip->subop_i, 0) ; ! 38: } ! 39: } ! 40: ! 41: cp_oneop( ip ) ! 42: struct ins_bkt *ip ; ! 43: ! 44: { ! 45: struct oper *op1; ! 46: unsigned r1; ! 47: ! 48: /* ! 49: opval_i[0] -- fop ea ! 50: opval_i[1] -- fop fpm ! 51: */ ! 52: ! 53: op1 = &operands[0] ; ! 54: code_length = 4 ; ! 55: wcode[0] = 0xf000 + current_cpid * 01000 ; ! 56: ! 57: if (freg_addr(op1)) ! 58: { ! 59: r1 = (int) op1 -> value_o - FP0REG ; ! 60: wcode[1] = ip->opval_i[1] + r1 * 02000 ; ! 61: } ! 62: else ! 63: { ! 64: wcode[1] = ip->opval_i[0] ; ! 65: eaddr( op1, ip->subop_i, 0) ; ! 66: } ! 67: } ! 68: ! 69: cp_move( ip ) ! 70: struct ins_bkt *ip ; ! 71: ! 72: { ! 73: struct oper *op1, *op2 ; ! 74: unsigned r1, r2 ; ! 75: ! 76: /* ! 77: opval_i[0] -- fmov? ea,fpn ! 78: opval_i[1] -- fmov? fpm,ea ! 79: opval_i[2] -- fmovx fpm,fpn ! 80: -- fmovl ea,fpctrl ! 81: opval_i[3] -- fmovl fpctrl,ea ! 82: ! 83: */ ! 84: ! 85: op1 = &operands[0] ; ! 86: op2 = &operands[1] ; ! 87: r1 = (int) op1 -> value_o - FP0REG ; ! 88: r2 = (int) op2 -> value_o - FP0REG ; ! 89: code_length = 4 ; ! 90: wcode[0] = 0xf000 + current_cpid * 01000 ; ! 91: ! 92: if (freg_addr(op1)) ! 93: { ! 94: if (freg_addr(op2)) ! 95: { /* fmovx fpm,fpn */ ! 96: wcode[1] = ip->opval_i[2] + r1 * 02000 + r2 * 0200 ; ! 97: } ! 98: else ! 99: { /* fmov? fpm,ea */ ! 100: wcode[1] = ip->opval_i[1] + r1 * 0200 ; ! 101: eaddr( op2, ip->subop_i, 1) ; ! 102: } ! 103: } ! 104: else ! 105: if (freg_addr(op2)) ! 106: { /* fmov? ea,fpn */ ! 107: wcode[1] = ip->opval_i[0] + r2 * 0200 ; ! 108: eaddr( op1, ip->subop_i, 0) ; ! 109: } ! 110: else ! 111: { ! 112: if (fctrlreg_addr(op2)) ! 113: { /* fmovl ea,fpctrl */ ! 114: switch((int) op2->value_o) ! 115: { ! 116: case FPCREG: { r2 = 4 ; break ; } ! 117: case FPSREG: { r2 = 2 ; break ; } ! 118: case FPIREG: { r2 = 1 ; break ; } ! 119: } ! 120: wcode[1] = ip->opval_i[2] + r2 * 02000 ; ! 121: eaddr( op1, ip->subop_i, 0) ; ! 122: } ! 123: else ! 124: { /* fmovl fpctrl,ea */ ! 125: switch((int) op1->value_o) ! 126: { ! 127: case FPCREG: { r2 = 4 ; break ; } ! 128: case FPSREG: { r2 = 2 ; break ; } ! 129: case FPIREG: { r2 = 1 ; break ; } ! 130: } ! 131: wcode[1] = ip->opval_i[3] + r2 * 02000 ; ! 132: eaddr( op2, ip->subop_i, 0) ; ! 133: } ! 134: } ! 135: } ! 136: ! 137: cp_regpair( ip ) ! 138: struct ins_bkt *ip ; ! 139: ! 140: /* Works like cp_general except the result is put in a PAIR ! 141: * of fp registers. ! 142: */ ! 143: ! 144: { ! 145: struct oper *op1, *op2 ; ! 146: unsigned r1, r2, r3 ; ! 147: ! 148: /* ! 149: opval_i[0] -- fop ea,fpn:fpq ! 150: opval_i[1] -- fop fpm,fpn:fpq ! 151: */ ! 152: ! 153: op1 = &operands[0] ; ! 154: op2 = &operands[1] ; ! 155: r2 = (int) op2 -> reg_o - FP0REG ; ! 156: r3 = (int) op2 -> value_o - FP0REG ; ! 157: code_length = 4 ; ! 158: wcode[0] = 0xf000 + current_cpid * 01000 ; ! 159: ! 160: if (freg_addr(op1)) ! 161: { ! 162: r1 = (int) op1 -> value_o - FP0REG ; ! 163: wcode[1] = ip->opval_i[1] + r2 * 0200 + r1 * 02000 + r3 ; ! 164: } ! 165: else ! 166: { ! 167: wcode[1] = ip->opval_i[0] + r2 * 0200 + r3 ; ! 168: eaddr( op1, ip->subop_i, 0) ; ! 169: } ! 170: } ! 171: ! 172: cp_movecr( ip ) ! 173: struct ins_bkt *ip ; ! 174: ! 175: /* ! 176: ! 177: For general format coprocessor instructions that put an immediate ! 178: operand in the op code extension field. ! 179: ! 180: */ ! 181: ! 182: { ! 183: struct oper *op1, *op2 ; ! 184: unsigned r1, r2 ; ! 185: ! 186: /* ! 187: opval_i[0] -- fop #ccc,fpn ! 188: */ ! 189: ! 190: op1 = &operands[0] ; ! 191: op2 = &operands[1] ; ! 192: r2 = (int) op2 -> value_o - FP0REG ; ! 193: code_length = 4 ; ! 194: wcode[0] = 0xf000 + current_cpid * 01000 ; ! 195: wcode[1] = ip->opval_i[0] + r2 * 0200 + op1->value_o ; ! 196: } ! 197: ! 198: ! 199: int reverse_8bits( forward ) ! 200: int forward ; ! 201: ! 202: /* ! 203: result = forward with with 8 low order bits in reverse order. ! 204: */ ! 205: ! 206: { ! 207: int bit, new ; ! 208: long i ; ! 209: ! 210: new = 0 ; ! 211: bit = 0x80 ; ! 212: ! 213: for (i=0 ; i<8 ; i++ ) ! 214: { ! 215: if (forward & 1) new |= bit ; ! 216: forward = forward >> 1 ; ! 217: bit = bit >> 1 ; ! 218: } ! 219: return(new) ; ! 220: } ! 221: ! 222: cp_movem( ip ) ! 223: struct ins_bkt *ip ; ! 224: ! 225: /* ! 226: ! 227: Floating move multiples come in too many varieties: ! 228: ! 229: fmovem ea,#imm ! 230: fmovem ea,freglist ! 231: fmovem ea,dn ! 232: fmovem ea,fcreglist ! 233: fmovem #imm,ea ! 234: fmovem #imm,sp@- ! 235: fmovem freglist,ea ! 236: fmovem freglist,sp@- ! 237: fmovem dn,ea ! 238: fmovem dn,sp@- ! 239: fmovem fcreglist,ea ! 240: ! 241: */ ! 242: ! 243: { ! 244: struct oper *op1, *op2 ; ! 245: ! 246: /* ! 247: opval_i[0] -- fmovem ea,#imm or freglist or dn ! 248: opval_i[1] -- fmovem ...,ea ! 249: opval-i[2] -- fmovem ea,fcreglist ! 250: opval-i[3] -- fop fcreglist,ea ! 251: */ ! 252: ! 253: op1 = &operands[0] ; ! 254: op2 = &operands[1] ; ! 255: code_length = 4 ; ! 256: wcode[0] = 0xf000 + current_cpid * 01000 ; ! 257: switch (op2->type_o) ! 258: { ! 259: case T_FCREGLIST:/* fmovem ea,fcreglist */ ! 260: { ! 261: wcode[1] = ip->opval_i[2] + op2->value_o * 0x400 ; ! 262: eaddr( op1, ip->subop_i, 0) ; ! 263: break ; ! 264: } ! 265: case T_IMMED: /* fmovem ea,#imm */ ! 266: { ! 267: wcode[1] = ip->opval_i[0] + op2->value_o ; ! 268: eaddr( op1, ip->subop_i, 0) ; ! 269: break ; ! 270: } ! 271: case T_FREGLIST:/* fmovem ea,freglist */ ! 272: { ! 273: wcode[1] = ip->opval_i[0] + reverse_8bits(op2->value_o) ; ! 274: eaddr( op1, ip->subop_i, 0) ; ! 275: break ; ! 276: } ! 277: case T_REG: /* fmovem ea,dn */ ! 278: { ! 279: wcode[1] = ip->opval_i[0] + 0x800 + (op2->value_o-D0REG)*0x10; ! 280: eaddr( op1, ip->subop_i, 0) ; ! 281: break ; ! 282: } ! 283: default: ! 284: { ! 285: switch(op1->type_o) ! 286: { ! 287: case T_FCREGLIST:/* fmovem fcreglist,ea */ ! 288: { ! 289: wcode[1] = ip->opval_i[3] + op1->value_o * 0x400 ; ! 290: break ; ! 291: } ! 292: case T_IMMED: /* fmovem #imm,ea */ ! 293: { ! 294: wcode[1] = ip->opval_i[1] + op1->value_o ; ! 295: if (op2->type_o != T_PREDEC) wcode[1] |= 0x1000 ; ! 296: break ; ! 297: } ! 298: case T_FREGLIST:/* fmovem freglist,ea */ ! 299: { ! 300: wcode[1] = ip->opval_i[1] ; ! 301: if (op2->type_o == T_PREDEC) ! 302: wcode[1] |= op1->value_o ; ! 303: else ! 304: wcode[1] |= 0x1000 | reverse_8bits(op1->value_o); ! 305: break ; ! 306: } ! 307: case T_REG: /* fmovem dn,ea */ ! 308: { ! 309: wcode[1] = ip->opval_i[1] + 0x800 + (op1->value_o-D0REG)*0x10; ! 310: if (op2->type_o != T_PREDEC) wcode[1] |= 0x1000 ; ! 311: break ; ! 312: } ! 313: } ! 314: eaddr( op2, ip->subop_i, 1) ; ! 315: } ! 316: } ! 317: } ! 318: ! 319: cp_oneword( ip ) ! 320: struct ins_bkt *ip ; ! 321: ! 322: /* For one word coprocessor instructions like FSAVE and FRESTORE. */ ! 323: ! 324: { ! 325: struct oper *op1 ; ! 326: ! 327: /* ! 328: opval_i[0] -- fop ea ! 329: */ ! 330: ! 331: op1 = &operands[0] ; ! 332: wcode[0] = ip->opval_i[0] + current_cpid * 01000 ; ! 333: eaddr( op1, ip->subop_i, 0) ; ! 334: ! 335: } ! 336: ! 337: cp_branch( ip ) ! 338: struct ins_bkt *ip ; ! 339: ! 340: /* For coprocessor 16, 32, and indeterminate branches. */ ! 341: ! 342: { ! 343: long offs = 0; ! 344: register struct oper *opp = operands; ! 345: int offlong, instlong ; ! 346: int useshort; ! 347: ! 348: wcode[0] = ip->opval_i[0] + current_cpid * 01000 ; ! 349: if (ip->noper_i == 0) ! 350: { /* fnop */ ! 351: code_length = 4 ; ! 352: wcode[1] = 0 ; ! 353: return ; ! 354: } ! 355: offs = opp->value_o - (dot + 2); ! 356: if (hflag ) ! 357: useshort = 1; ! 358: else ! 359: useshort = d2flag||jsrflag; ! 360: if (opp->flags_o & O_COMPLEX) { ! 361: /* not a simple address */ ! 362: opp->value_o = (int) offs; ! 363: rel_val(opp, SUBOP_W, opp->sym_o != 0); ! 364: return; ! 365: } ! 366: if (pass == 1 ) { ! 367: if (cansdi) ! 368: code_length += useshort? 2 : makesdi(opp, dot+2, SDIP); ! 369: else ! 370: code_length += (useshort)?2:4; ! 371: put_rel(opp, SUBOP_L, dot+2, 0); ! 372: } ! 373: else { ! 374: /* pass 2 */ ! 375: if ( opp->sym_o && (opp->sym_o->attr_s & S_DEF) == 0){ ! 376: /* external branch -- good luck */ ! 377: ; ! 378: } else if (opp->sym_o == 0 || opp->sym_o->csect_s != cur_csect_name){ ! 379: PROG_ERROR(E_RELOCATE); ! 380: } else { ! 381: opp->sym_o = 0; /* mark as non relocateable expression */ ! 382: } ! 383: offlong = (offs > 32767L || offs < -32768L) ; ! 384: if (ip->opval_i[0] & 0100) instlong = 1 ; /* fbccl*/ ! 385: else if (ip->opval_i[0] & 0200) instlong = 0 ; /* fbcc */ ! 386: else ! 387: { /* fjcc */ ! 388: instlong = offlong ; ! 389: if (instlong && !useshort ) ! 390: wcode[0] |= 0300 ; /* Op code for fbccl. */ ! 391: else ! 392: wcode[0] |= 0200 ; /* Op code for fbcc . */ ! 393: } ! 394: if (offlong &~ instlong) PROG_ERROR(E_OFFSET); ! 395: opp->value_o = (int)offs; ! 396: if (instlong && !useshort) ! 397: rel_val(opp, SUBOP_L, opp->sym_o != 0); ! 398: else ! 399: rel_val(opp, SUBOP_W, opp->sym_o != 0); ! 400: } ! 401: } ! 402: ! 403: cp_conditional ( ip ) ! 404: struct ins_bkt *ip ; ! 405: /* ! 406: ! 407: Coprocessor conditional instructions: ! 408: fscc ea ! 409: fdbcc dn,label ! 410: ftcc ! 411: ftccw #imm ! 412: ftccl #imm ! 413: ! 414: */ ! 415: ! 416: { ! 417: struct oper *op1, *op2 ; ! 418: long offs = 0; ! 419: ! 420: /* ! 421: opval_i[0] -- fop ea,fpn ! 422: opval_i[1] -- fop fpm,fpn ! 423: */ ! 424: ! 425: code_length = 4 ; ! 426: wcode[0] = ip->opval_i[0] + current_cpid * 01000 ; ! 427: wcode[1] = ip->opval_i[1] ; /* condition code */ ! 428: switch(ip->noper_i) ! 429: { ! 430: /* case 0: ftcc - nothing more to do */ ! 431: case 1: { ! 432: op1 = &operands[0] ; ! 433: if (op1->type_o == T_IMMED) ! 434: { /* ftccw or ftccl */ ! 435: rel_val(op1, ip->subop_i, 0) ; ! 436: } ! 437: else ! 438: { /* fscc */ ! 439: eaddr( op1, ip->subop_i, 0) ; ! 440: } ! 441: break ; ! 442: } ! 443: case 2: { /* fdbcc */ ! 444: op1 = &operands[0] ; ! 445: op2 = &operands[1] ; ! 446: wcode[0] |= op1->value_o; ! 447: if ( op2->sym_o && (op2->sym_o->attr_s & S_DEF) == 0){ ! 448: /* external branch -- good luck */ ! 449: ; ! 450: } else if (op2->sym_o == 0 || op2->sym_o->csect_s != cur_csect_name){ ! 451: PROG_ERROR(E_RELOCATE); ! 452: } else { ! 453: op2->sym_o = 0; /* mark as non relocateable expression */ ! 454: } ! 455: offs = op2->value_o - (dot + 4); ! 456: if (offs > 32767L || offs < -32768L) ! 457: PROG_ERROR(E_OFFSET); ! 458: op2->value_o = (int)offs; ! 459: rel_val(op2, SUBOP_W, op2->sym_o != 0); ! 460: break ; ! 461: } ! 462: } ! 463: } ! 464:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.