|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)eaddr.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: /* eaddr - put in stuff for an effective address */ ! 10: ! 11: #include "as.h" ! 12: ! 13: #define forward_ref(o) ((o)->sym_o && !((o)->sym_o->attr_s&S_DEF)) ! 14: ! 15: operand_t displacement(); ! 16: ! 17: eaddr(opptr, size ,wrtflag) ! 18: register struct oper *opptr; ! 19: subop_t size; ! 20: { ! 21: int reg = (int)opptr->value_o; ! 22: int was_displ; ! 23: if (opptr->flags_o & O_BFLD) ! 24: PROG_ERROR(E_OPERAND); /* unexpected bit field */ ! 25: switch(opptr->type_o) { ! 26: case T_REG: ! 27: if (areg(reg) || dreg(reg)) ! 28: wcode[0] |= (int)opptr->value_o; ! 29: else ! 30: PROG_ERROR(E_REG) ; ! 31: break; ! 32: case T_DEFER: ! 33: wcode[0] |= (((int)opptr->value_o) & 07) | 020; ! 34: break; ! 35: case T_POSTINC: ! 36: wcode[0] |= (((int)opptr->value_o) & 07) | 030; ! 37: break; ! 38: case T_PREDEC: ! 39: wcode[0] |= (reg & 07) | 040; ! 40: break; ! 41: case T_DISPL: ! 42: if (reg<-32768 || reg>32767 || opptr->sym_o && ! 43: !(opptr->sym_o->attr_s&S_DEF) ){ ! 44: if (ext_instruction_set) ! 45: { ! 46: /* looks like a potential index mode */ ! 47: opptr->disp_o = reg; ! 48: opptr->value_o = 0; ! 49: was_displ = 1; ! 50: goto indexmode; ! 51: }else{ ! 52: if ( !pcreg(opptr->reg_o) || (opptr->flags_o) ) ! 53: PROG_ERROR(E_OPERAND); ! 54: } ! 55: } ! 56: if (areg(opptr->reg_o)) { ! 57: wcode[0] |= (opptr->reg_o & 07) | 050; ! 58: rel_val(opptr, SUBOP_W, 0); /* install displacement */ ! 59: } else { ! 60: wcode[0] |= 072; ! 61: if (opptr->sym_o) ! 62: { /* relocatable or external */ ! 63: if (opptr->sym_o && opptr->sym_o->attr_s & S_DEF) ! 64: { /* symbol is defined in this assembly */ ! 65: opptr->sym_o = 0; ! 66: } ! 67: opptr->value_o -= dot + code_length ; /* bias offset */ ! 68: rel_val(opptr, SUBOP_W, 1); /* install displacement */ ! 69: } ! 70: else ! 71: { /* absolute */ ! 72: rel_val(opptr, SUBOP_W, 0); /* install displacement */ ! 73: } ! 74: } ! 75: break; ! 76: case T_PCPLUS: ! 77: /* especially called from ctrl_op to do external PC@() addressing */ ! 78: /* looks a lot like the above */ ! 79: wcode[0] |= 072; ! 80: opptr->value_o -= dot + code_length ; /* bias offset */ ! 81: rel_val(opptr, SUBOP_W, 1); /* <== PC-relative relocation */ ! 82: break; ! 83: case T_INDEX: ! 84: was_displ = 0; ! 85: indexmode: ! 86: if (pcreg(opptr->reg_o)) ! 87: { ! 88: wcode[0] |= 073; ! 89: if (opptr->sym_o) opptr->disp_o -= dot+code_length ; ! 90: index(opptr, was_displ); /* compute index word */ ! 91: if (opptr->sym_o) opptr->disp_o += dot+code_length ; ! 92: } ! 93: else ! 94: { ! 95: wcode[0] |= (opptr->reg_o & 07) | 060; ! 96: index(opptr, was_displ); /* compute index word */ ! 97: } ! 98: break; ! 99: case T_ABSS: ! 100: short_absolute: ! 101: wcode[0] |= 070; ! 102: rel_val(opptr, SUBOP_W, 0); /* install short address */ ! 103: break; ! 104: case T_NORMAL: ! 105: /* ! 106: * Heretofore, this has been handled as long absolute, making ! 107: * the most expensive addressing mode the default one, and the ! 108: * only one used by c programs. Because of the rules of C, this ! 109: * is probably a quite reasonable assumption. But assembly- ! 110: * language programmers might be more tricky in their placement ! 111: * of code and data, and might be able to use short absolute. ! 112: * They might even be able to use PC-relative in an intellegent ! 113: * manner. ! 114: */ ! 115: /* we have three choices of addressing modes to ! 116: * use: absolute long, absolute short, and PC ! 117: * relative. The latter two are the same size, ! 118: * but for entirely different applications. One ! 119: * is for reaching low memory, and the other is ! 120: * for reaching nearby data in the text segment. ! 121: */ ! 122: if (cansdi){ ! 123: switch (displacement( opptr, !wrtflag, 0, 0, 0 )){ ! 124: case T_ABSS: ! 125: wcode[0] |= 070; ! 126: break; ! 127: case T_PCPLUS: ! 128: wcode[0] |= 072; ! 129: break; ! 130: case T_ABSL: ! 131: wcode[0] |= 071; ! 132: break; ! 133: default: ! 134: sys_error("Unfamiliar sdi address mode in ea:\n %s\n", iline); ! 135: } ! 136: break; ! 137: } ! 138: /* else FALL THROUGH */ ! 139: case T_ABSL: ! 140: wcode[0] |= 071; ! 141: rel_val(opptr, SUBOP_L, 0); ! 142: break; ! 143: case T_IMMED: ! 144: wcode[0] |= 074; ! 145: rel_val(opptr, (size == SUBOP_B)? SUBOP_W:size, 0); /* change bytes to words */ ! 146: break; ! 147: default: ! 148: sys_error("Unrecognized address mode in:\n %s\n", iline); ! 149: } ! 150: } ! 151: ! 152: static ! 153: vshort_absolute(opptr) ! 154: register struct oper *opptr; ! 155: { ! 156: if (opptr->sym_o==0 && -128 <= opptr->value_o && opptr->value_o <= 127){ ! 157: return 1; ! 158: } ! 159: return 0; ! 160: } ! 161: ! 162: static ! 163: short_absolute(opptr) ! 164: register struct oper *opptr; ! 165: { ! 166: if (d2flag ! 167: || (opptr->sym_o==0 && -32768 <= opptr->value_o && opptr->value_o <= 32767 )){ ! 168: rel_val(opptr, SUBOP_W, 0); ! 169: return 1; ! 170: } ! 171: return 0; ! 172: } ! 173: ! 174: static ! 175: long_absolute(opptr, pc_ok, null_ok, indexing, was_displ) ! 176: struct oper *opptr; ! 177: { ! 178: /* the form of last resort. Must always succeed */ ! 179: int sdiflavor; ! 180: if (pass==1 && cansdi && opptr->sym_o && !(opptr->sym_o->attr_s&S_DEF) ){ ! 181: if (indexing || was_displ) sdiflavor = SDIX; ! 182: else if (null_ok) sdiflavor = SDI6; ! 183: else sdiflavor = SDIP; ! 184: (void)makeddi( opptr, dot+code_length, sdiflavor, !pc_ok); ! 185: } ! 186: rel_val( opptr, SUBOP_L, 0); ! 187: return 1; ! 188: } ! 189: ! 190: pc_relative(opptr) ! 191: struct oper *opptr; ! 192: { ! 193: register struct sym_bkt *sym = opptr->sym_o; ! 194: if (sym && (sym->attr_s & S_DEF) && ! 195: (sym->csect_s == cur_csect_name ! 196: ||(rflag && sym->csect_s != C_BSS))){ ! 197: /* looks like pc-relative is a real possibility */ ! 198: if (pass==1){ ! 199: (void)makesdi( opptr, dot+code_length, SDIP); ! 200: rel_val( opptr, SUBOP_W, 0); ! 201: return 1; ! 202: } else { ! 203: register int offset = opptr->value_o - (dot + code_length); ! 204: ! 205: if ( offset >= -32768L && offset <= 32767L){ ! 206: opptr->value_o -= dot + code_length; ! 207: opptr->sym_o = 0; /* no relocation */ ! 208: rel_val(opptr, SUBOP_W, 0); /* install displacement */ ! 209: return 1; ! 210: } ! 211: } ! 212: } ! 213: return 0; ! 214: } ! 215: ! 216: static operand_t ! 217: displacement( opptr, pc_ok, null_ok, indexing, was_displ ) ! 218: register struct oper *opptr; ! 219: int pc_ok, null_ok, indexing, was_displ; ! 220: { ! 221: /* we have three choices of addressing modes to ! 222: * use: absolute long, absolute short, and PC ! 223: * relative. The latter two are the same size, ! 224: * but for entirely different applications. One ! 225: * is for reaching low memory, and the other is ! 226: * for reaching nearby data in the text segment. ! 227: */ ! 228: if (null_ok && opptr->sym_o == 0 && opptr->value_o == 0 ){ ! 229: return T_NULL; ! 230: } else if (indexing && vshort_absolute(opptr)){ ! 231: return T_INDEX; ! 232: } else if (short_absolute(opptr)){ ! 233: return T_ABSS; ! 234: } else if ( pc_ok && cansdi && pc_relative(opptr) ){ ! 235: return T_PCPLUS; ! 236: } else { ! 237: long_absolute( opptr, pc_ok, null_ok, indexing, was_displ ); ! 238: return T_ABSL; ! 239: } ! 240: } ! 241: ! 242: /* ! 243: * index - Use data in operand structure to compute an index word. ! 244: */ ! 245: ! 246: static ! 247: index(opptr, was_displ) ! 248: register struct oper *opptr; ! 249: int was_displ; ! 250: { ! 251: register int indexval = 0; ! 252: int displ1=0, displ2=0, shortform; ! 253: int c, f, reg; ! 254: ! 255: reg = opptr->value_o; ! 256: if (areg(reg) || dreg(reg)) ! 257: indexval = reg << 12; ! 258: else PROG_ERROR(E_REG); ! 259: if (opptr->flags_o&O_LINDEX) indexval |= 0x0800; ! 260: switch (opptr->scale_o){ ! 261: case 1 : break; ! 262: case 2 : indexval |= 1<<9; break; ! 263: case 4 : indexval |= 2<<9; break; ! 264: case 8 : indexval |= 3<<9; break; ! 265: } ! 266: opptr->value_o = opptr->disp_o; ! 267: f = opptr->flags_o; ! 268: c = code_length >>1; ! 269: code_length += 2; ! 270: if (f&O_WDISP){ ! 271: /* force word displacement */ ! 272: if ( opptr->disp_o < -32768 || opptr->disp_o > 32767 ! 273: || opptr->sym_o && opptr->sym_o->csect_s == 0 ) ! 274: PROG_ERROR(E_OFFSET) ; ! 275: shortform = 0; ! 276: displ1 = 2<<4; ! 277: rel_val(opptr,SUBOP_W , 0); ! 278: }else if (f&O_LDISP || (ext_instruction_set && !cansdi)){ ! 279: /* force long displacement */ ! 280: shortform = 0; ! 281: displ1 = 3<<4; ! 282: rel_val(opptr,SUBOP_L , 0); ! 283: }else{ ! 284: shortform = (!(f & (O_BSUPRESS|O_POSTINDEX|O_INDIRECT)) ! 285: && (f&O_PREINDEX) ); ! 286: if (ext_instruction_set && cansdi && !(f&O_BDISP)){ ! 287: if (pass == 1 && forward_ref(opptr)) { ! 288: prog_error(E_FORWARD); ! 289: } ! 290: switch (displacement(opptr, 0 , 1, shortform, was_displ)){ ! 291: case T_NULL: /* displacement is 0 */ ! 292: displ1 = 1<<4; ! 293: break; ! 294: case T_INDEX: /* displacement is small */ ! 295: break; ! 296: case T_ABSS: /* displacement is moderate */ ! 297: displ1 = 2<<4; ! 298: shortform = 0; ! 299: break; ! 300: case T_ABSL: /* displacement is huge*/ ! 301: displ1 = 3<<4; ! 302: shortform = 0; ! 303: break; ! 304: } ! 305: } ! 306: /* else !ext_instruction_set: use short form */ ! 307: if (shortform || (f&O_BDISP)){ ! 308: if (opptr->disp_o < -128 || opptr->disp_o > 127 ! 309: || opptr->sym_o && opptr->sym_o->csect_s == 0) ! 310: PROG_ERROR(E_OFFSET) ; ! 311: indexval |= opptr->disp_o & 0377; ! 312: wcode[c] = indexval; /* install index word */ ! 313: return; ! 314: } ! 315: } ! 316: /* long form indexing */ ! 317: /* first displacement */ ! 318: if (f&O_BSUPRESS) ! 319: indexval |= 1<<7; /* base supress */ ! 320: if (!(f&(O_PREINDEX|O_POSTINDEX))) ! 321: indexval |= 1<<6; /* index supress */ ! 322: indexval |= displ1 | (1<<8); ! 323: if (!(f&O_INDIRECT)) ! 324: displ2 = 0; /* no indirection */ ! 325: else { ! 326: opptr->value_o = opptr->disp2_o; ! 327: opptr->sym_o = opptr->sym2_o; ! 328: if (f&O_LDISP2 || !cansdi){ ! 329: /* long displacement */ ! 330: displ2 = 3; ! 331: rel_val(opptr,SUBOP_L , 0); ! 332: }else if (f&O_WDISP2){ ! 333: /* word displacement */ ! 334: if (opptr->disp2_o < -32768 || opptr->disp2_o > 32767 ! 335: || opptr->sym2_o && opptr->sym2_o->csect_s == 0) ! 336: PROG_ERROR(E_OFFSET) ; ! 337: displ2 = 2; ! 338: rel_val(opptr,SUBOP_W , 0); ! 339: } else { ! 340: if (pass == 1 && forward_ref(opptr)) { ! 341: prog_error(E_FORWARD); ! 342: } ! 343: switch (displacement( opptr, 0, 1, 0, 0 )){ ! 344: case T_NULL: ! 345: displ2 = 1; break; ! 346: case T_ABSS: ! 347: displ2 = 2; break; ! 348: case T_ABSL: ! 349: displ2 = 3; break; ! 350: } ! 351: } ! 352: indexval |= displ2 | ((f&O_POSTINDEX)?(1<<2):0); ! 353: ! 354: } ! 355: wcode[c] = indexval; /* install index word */ ! 356: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.