|
|
1.1 root 1: /* Copyright (c) 1980 Regents of the University of California */
2: static char sccsid[] = "@(#)ascode.c 4.7 11/5/80";
3: #include <stdio.h>
4: #include "as.h"
5: #include "assyms.h"
6:
7: /*
8: * Loader reference types (plust PCREL) to bytes and lg bytes
9: */
10: /* LEN1 LEN1+PC LEN2 LEN2+PC LEN4 LEN4+PC LEN8 LEN8+PC*/
11: int reflen[] = /* {LEN*+PCREL} ==> number of bytes */
12: {0, 0, 1, 1, 2, 2, 4, 4, 8, 8};
13: int lgreflen[] = /* {LEN*+PCREL} ==> lg number of bytes */
14: {-1, -1, 0, 0, 1, 1, 2, 2, 3, 3};
15:
16: /*
17: * Sizes to Loader reference types and type flags
18: */
19: /*0 1 2 3 4 5 6 7 8*/
20: int len124[] = /* {1,2,4,8} ==> {LEN1, LEN2, LEN4, LEN8} */
21: {0, LEN1, LEN2, 0, LEN4, 0, 0, 0, LEN8};
22: char mod124[] = /* {1,2,4,8} ==> {bits to construct operands */
23: {0, 0x00, 0x20, 0, 0x40, 0, 0, 0, 0};
24: int type_124[] = /* {1,2,4,8} ==> {TYPB, TYPW, TYPL, TYPQ} */
25: {0, TYPB, TYPW, 0, TYPL, 0, 0, 0, TYPQ};
26:
27: /*
28: * type flags to Loader reference and byte lengths
29: */
30: /*TYPB TYPW TYPL TYPQ TYPF TYPD*/
31: int ty_NORELOC[] = /* {TYPB..TYPD} ==> {1 if relocation not OK */
32: {0, 0, 0, 1, 1, 1};
33: int ty_LEN[] = /* {TYPB..TYPD} ==> {LEN1..LEN8} */
34: {LEN1, LEN2, LEN4, LEN8, LEN4, LEN8};
35: int ty_nbyte[] = /* {TYPB..TYPD} ==> {1,2,4,8} */
36: {1, 2, 4, 8, 4, 8};
37: int ty_nlg[] = /* {TYPB..TYPD} ==> lg{1,2,4,8} */
38: {0, 1, 2, 3, 2, 3};
39:
40: insout(op, ap, nact)
41: struct arg *ap;
42: {
43: int jxxflg;
44: register struct instab *ip; /* the instruction */
45: register struct arg *ap_walk; /* actual param walk */
46: register int i;
47: register int ap_type; /* actual param type */
48: register int ap_type_mask; /* masked actual param */
49: op &= 0xFF;
50: jxxflg = nact;
51: if (nact < 0)
52: nact = -nact;
53: if (passno == 1) {
54: ip = itab[op];
55: if (nact < ip->i_nargs)
56: yyerror("Too few arguments");
57: if (nact > ip->i_nargs) {
58: yyerror("Too many arguments");
59: nact = ip->i_nargs;
60: }
61: /*
62: * Check argument compatability with instruction template
63: */
64: for (ap_walk = ap, i = 1; i <= nact; ap_walk++, i++){
65: ap_type = ap_walk->a_atype;
66: ap_type_mask = ap_type & AMASK;
67: /*
68: * The switch value is >> by 3 so that the switch
69: * code is dense, not implemented as a sequence
70: * of branches but implemented as a casel.
71: * In addition, cases ACCI and ACCR are added to force
72: * dense switch code.
73: */
74: switch( ((fetcharg(ip, i-1)) & ACCESSMASK)>>3){ /* type of fp */
75: case ACCI >> 3:
76: case ACCR >> 3:
77: break;
78: case ACCB >> 3:
79: if ( !((ap_type_mask == AEXP) || (ap_type_mask == AIMM)) ){
80: yyerror("arg %d, branch displacement must be an expression",i);
81: return;
82: }
83: break;
84: case ACCA >> 3:
85: switch(ap_type_mask){
86: case AREG: yyerror("arg %d, addressing a register",i);
87: return;
88: case AIMM: if ( !(ap_type & ASTAR) ){
89: yyerror("arg %d, addressing an immediate operand",i);
90: return;
91: }
92: }
93: break;
94: case ACCM >> 3:
95: case ACCW >> 3:
96: switch(ap_type_mask){
97: case AIMM: if (!(ap_type&ASTAR)) {
98: yyerror("arg %d, modifying a constant",i);
99: return;
100: }
101: }
102: break;
103: } /* end of the switch on fp_type */
104: if (ap_type & AINDX) {
105: if (ap_walk->a_areg2==0xF) {
106: yyerror("arg %d, PC used as index",i);
107: return;
108: }
109: switch(ap_type_mask){
110: case AREG: yyerror("arg %d, indexing the register file",i);
111: return;
112: case AIMM: yyerror("arg %d, indexing a constant",i);
113: return;
114: case ADECR:
115: case AINCR: if (ap_walk->a_areg1==ap_walk->a_areg2) {
116: yyerror("arg %d, indexing with modified register",i);
117: return;
118: }
119: break;
120: } /* end of switch on ap_type_mask */
121: } /* end of AINDX */
122: }
123: } /* both passes here */
124: if (jxxflg < 0)
125: ijxout(op, ap, nact);
126: else putins(op, ap, nact);
127: }
128:
129: extern int d124;
130:
131: putins(op, ap, n)
132: /*
133: * n had better be positive
134: */
135: register struct arg *ap;
136: {
137: register struct exp *xp;
138: register int argtype;
139: int i;
140: int reloc_how;
141:
142: #ifdef DEBUG
143: fflush(stdout);
144: #endif
145: if (passno == 2)
146: goto PASS2;
147:
148: dotp->e_xvalue += n+1; /* 1 for the opcode, at least 1 per arg */
149: for (i=0; i<n; i++,ap++) { /* some args take more than 1 byte */
150: argtype = ap->a_atype;
151: if (argtype & AINDX)
152: dotp->e_xvalue++;
153: /*
154: * This switch has been fixed by enumerating the no action
155: * alternatives (those that have 1 one byte of code)
156: * so that a casel instruction is emitted.
157: */
158: switch (argtype&~(AINDX|ASTAR)) {
159: case AREG:
160: case ABASE:
161: case ADECR:
162: case AINCR:
163: break;
164: case AEXP:
165: argtype = fetcharg(itab[op], i);
166: if (argtype == ACCB+TYPB)
167: break;
168: if (argtype==ACCB+TYPW){
169: dotp->e_xvalue++;
170: break;
171: }
172: /*
173: * Reduces to PC relative
174: */
175: dotp->e_xvalue += ap->a_dispsize;
176: break;
177:
178: case ADISP:
179: xp=ap->a_xp;
180: if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){
181: dotp->e_xvalue += ap->a_dispsize;
182: break;
183: }
184: if (xp->e_xvalue==0 && !(argtype&ASTAR))
185: break;
186: dotp->e_xvalue++;
187: if ((xp->e_xvalue<MINBYTE) || (xp->e_xvalue>MAXBYTE))
188: dotp->e_xvalue++;
189: if ((xp->e_xvalue<MINWORD) || (xp->e_xvalue>MAXWORD))
190: dotp->e_xvalue += 2;
191: break;
192:
193: case AIMM:
194: if (ap->a_atype&ASTAR) argtype=TYPL;
195: else {
196: argtype = fetcharg(itab[op], i);
197: if (argtype&ACCA)
198: argtype = TYPL;
199: else
200: argtype &= TYPMASK;
201: xp = ap->a_xp;
202: if ( ((xp->e_xtype&XTYPE)==XABS)
203: && (!(xp->e_xtype&XFORW))
204: && (xp->e_xvalue>=0)
205: && (xp->e_xvalue<=63)
206: && (xp->e_yvalue == 0)
207: && (argtype != TYPD)
208: && (argtype != TYPF)
209: )
210: break;
211: }
212: switch (argtype) {
213: case TYPD:
214: case TYPF:
215: if ( !(((xp->e_xtype&XTYPE)==XABS)
216: && (!(xp->e_xtype&XFORW))
217: && (slitflt(xp)))
218: ){
219: /* it is NOT short */
220: dotp->e_xvalue += ((argtype==TYPF)?
221: 4 : 8);
222: }
223: break;
224: case TYPQ:
225: dotp->e_xvalue += 8;break;
226: case TYPL:
227: dotp->e_xvalue += 4;break;
228: case TYPW:
229: dotp->e_xvalue += 2;break;
230: case TYPB:
231: dotp->e_xvalue += 1;break;
232: } /*end of the switch on argtype*/
233: } /*end of the switch on the type*/
234: } /*end of looping for all arguments*/
235: return;
236:
237: PASS2:
238:
239: #ifdef UNIX
240: outb(op); /* the opcode */
241: #endif UNIX
242: #ifdef VMS
243: *vms_obj_ptr++ = -1; *vms_obj_ptr++ = (char)op;
244: dotp->e_xvalue += 1;
245: #endif VMS
246:
247: for (i=0; i<n; i++,ap++) {/* now for the arguments */
248: argtype=ap->a_atype;
249: xp=ap->a_xp;
250: reloc_how = TYPNONE;
251: if (argtype&AINDX) {
252: #ifdef UNIX
253: { outb(0x40 | ap->a_areg2); }
254: #endif UNIX
255: #ifdef VMS
256: { *vms_obj_ptr++ = -1;
257: *vms_obj_ptr++ = (0x40 | ap->a_areg2);
258: dotp->e_xvalue += 1; }
259: #endif VMS
260: argtype &= ~AINDX;
261: }
262: if (argtype&ASTAR) {
263: ap->a_areg1 |= 0x10;
264: argtype &= ~ASTAR;
265: }
266: switch (argtype) {
267: case AREG: /* %r */
268: ap->a_areg1 |= 0x50;
269: break;
270: case ABASE: /* (%r) */
271: ap->a_areg1 |= 0x60;
272: break;
273: case ADECR: /* -(%r) */
274: ap->a_areg1 |= 0x70;
275: break;
276: case AINCR: /* (%r)+ */
277: ap->a_areg1 |= 0x80;
278: break;
279: case AEXP: /* expr */
280: argtype = fetcharg(itab[op], i);
281: if (argtype == ACCB+TYPB) {
282: ap->a_areg1 = argtype =
283: xp->e_xvalue - (dotp->e_xvalue + 1);
284: if (argtype<MINBYTE || argtype>MAXBYTE)
285: yyerror("Branch too far"); break;
286: }
287: if (argtype == ACCB+TYPW) {
288: ap->a_areg1 = argtype = xp->e_xvalue
289: -= dotp->e_xvalue + 2;
290: xp->e_xtype = XABS;
291: if (argtype<MINWORD || argtype>MAXWORD)
292: yyerror("Branch too far");
293: xp->e_xvalue = argtype>>8;
294: reloc_how = TYPB;
295: break;
296: }
297: /* reduces to expr(pc) mode */
298: ap->a_areg1 |= (0xAF + mod124[ap->a_dispsize]);
299: reloc_how = type_124[ap->a_dispsize] + RELOC_PCREL;
300: break;
301:
302: case ADISP: /* expr(%r) */
303: ap->a_areg1 |= 0xA0;
304: if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){
305: ap->a_areg1 += mod124[ap->a_dispsize];
306: reloc_how = type_124[ap->a_dispsize];
307: break;
308: }
309: if (xp->e_xvalue==0 && !(ap->a_areg1&0x10)) {
310: ap->a_areg1 ^= 0xC0;
311: break;
312: }
313: reloc_how = TYPB;
314: if ((xp->e_xvalue<MINBYTE) || (xp->e_xvalue>MAXBYTE)){
315: ap->a_areg1 += 0x20;
316: reloc_how = TYPW;
317: }
318: if ((xp->e_xvalue<MINWORD) || (xp->e_xvalue>MAXWORD)){
319: ap->a_areg1 += 0x20;
320: reloc_how = TYPL;
321: }
322: break;
323:
324: case AIMM: /* $expr */
325: if (ap->a_atype&ASTAR)
326: argtype=TYPL;
327: else {
328: argtype = fetcharg(itab[op], i);
329: if (argtype&ACCA)
330: argtype=TYPL;
331: else
332: argtype &= TYPMASK;
333: if ( ( (xp->e_xtype&XTYPE) == XABS)
334: && !(xp->e_xtype&XFORW)
335: && (xp->e_xvalue >= 0)
336: && (xp->e_xvalue <= 63)
337: && (xp->e_yvalue == 0)
338: && (argtype != TYPF)
339: && (argtype != TYPD) ) {
340: ap->a_areg1 = xp->e_xvalue;
341: break;
342: }
343: }
344: ap->a_areg1 |= 0x8F;
345: reloc_how = argtype;
346: if (reloc_how == TYPD || reloc_how == TYPF){
347: if ( ((xp->e_xtype&XTYPE)==XABS)
348: && (!(xp->e_xtype&XFORW))
349: && (slitflt(xp))
350: ){
351: reloc_how = TYPNONE;
352: ap->a_areg1=extlitflt(xp);
353: }
354: }
355: break;
356:
357: } /*end of the switch on argtype*/
358: /*
359: * use the first byte to describe the argument
360: */
361: #ifdef UNIX
362: outb(ap->a_areg1);
363: #endif UNIX
364: #ifdef VMS
365: *vms_obj_ptr++ = -1; *vms_obj_ptr++ = (char)(ap->a_areg1);
366: dotp->e_xvalue += 1;
367: if ((vms_obj_ptr-sobuf) > 400) {
368: write(objfil,sobuf,vms_obj_ptr-sobuf);
369: vms_obj_ptr=sobuf+1;
370: }
371: #endif VMS
372: if (reloc_how != TYPNONE)
373: outrel(xp, reloc_how);
374: } /*end of the for to pick up all arguments*/
375: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.