|
|
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.