|
|
1.1 root 1: /*
2: * Copyright (c) 1982 Regents of the University of California
3: */
4: #ifndef lint
5: static char sccsid[] = "@(#)ascode.c 4.11 6/30/83";
6: #endif not lint
7:
8: #include <stdio.h>
9: #include "as.h"
10: #include "assyms.h"
11:
12: insout(opcode, ap, nact)
13: struct Opcode opcode;
14: struct arg *ap;
15: int nact;
16: {
17: int jxxflg;
18: reg struct instab *ip; /* the instruction */
19: reg struct arg *ap_walk; /* actual param walk */
20: reg int i;
21: reg int ap_type; /* actual param type */
22: reg int ap_type_mask; /* masked actual param */
23:
24: jxxflg = nact;
25: if (nact < 0)
26: nact = -nact;
27: if (passno == 1) {
28: if (!(ITABCHECK(opcode)))
29: panic("Botched reference into itab");
30: ip = ITABFETCH(opcode);
31: if (nact < ip->i_nargs)
32: yyerror("Too few arguments");
33: if (nact > ip->i_nargs) {
34: yyerror("Too many arguments");
35: nact = ip->i_nargs;
36: }
37: /*
38: * Check argument compatability with instruction template
39: */
40: for (ap_walk = ap, i = 1; i <= nact; ap_walk++, i++){
41: ap_type = ap_walk->a_atype;
42: ap_type_mask = ap_type & AMASK;
43: /*
44: * The switch value is >> by TYPLG so that the switch
45: * code is dense, not implemented as a sequence
46: * of branches but implemented as a casel.
47: * In addition, cases ACCI and ACCR are added to force
48: * dense switch code.
49: * switch on the type of fp
50: */
51: switch( ((fetcharg(ip, i-1)) & ACCESSMASK) >> TYPLG){
52: case ACCI >> TYPLG:
53: case ACCR >> TYPLG:
54: break;
55: case ACCB >> TYPLG:
56: if ( !((ap_type_mask == AEXP) || (ap_type_mask == AIMM)) ){
57: yyerror("arg %d, branch displacement must be an expression",i);
58: return;
59: }
60: break;
61: case ACCA >> TYPLG:
62: switch(ap_type_mask){
63: case AREG: yyerror("arg %d, addressing a register",i);
64: return;
65: case AIMM: if ( !(ap_type & ASTAR) ){
66: yyerror("arg %d, addressing an immediate operand",i);
67: return;
68: }
69: }
70: break;
71: case ACCM >> TYPLG:
72: case ACCW >> TYPLG:
73: switch(ap_type_mask){
74: case AIMM: if (!(ap_type&ASTAR)) {
75: yyerror("arg %d, modifying a constant",i);
76: return;
77: }
78: }
79: break;
80: } /* end of the switch on fp_type */
81: if (ap_type & AINDX) {
82: if (ap_walk->a_areg2==0xF) {
83: yyerror("arg %d, PC used as index",i);
84: return;
85: }
86: switch(ap_type_mask){
87: case AREG: yyerror("arg %d, indexing the register file",i);
88: return;
89: case AIMM: yyerror("arg %d, indexing a constant",i);
90: return;
91: case ADECR:
92: case AINCR: if (ap_walk->a_areg1==ap_walk->a_areg2) {
93: yyerror("arg %d, indexing with modified register",i);
94: return;
95: }
96: break;
97: } /* end of switch on ap_type_mask */
98: } /* end of AINDX */
99: }
100: } /* both passes here */
101: if (jxxflg < 0)
102: ijxout(opcode, ap, nact);
103: else
104: putins(opcode, ap, nact);
105: }
106:
107: extern int d124;
108:
109: putins(opcode, ap, n)
110: struct Opcode opcode;
111: register struct arg *ap;
112: int n; /* Must be positive */
113: {
114: reg struct exp *xp;
115: reg int argtype;
116: int i;
117: int reloc_how;
118: int value;
119:
120: #ifdef DEBUG
121: fflush(stdout);
122: #endif
123: if (passno == 2)
124: goto PASS2;
125:
126: dotp->e_xvalue += n; /* at least one byte per arg */
127: switch(opcode.Op_eopcode){
128: case NEW:
129: case CORE:
130: dotp->e_xvalue += 1; /* 1 byte opcode */
131: break;
132: case ESCD:
133: case ESCF:
134: dotp->e_xvalue += 2; /* 2 byte opcode */
135: break;
136: default:
137: panic("Bad escape opcode");
138: }
139:
140: for (i=0; i<n; i++,ap++) { /* some args take more than 1 byte */
141: argtype = ap->a_atype;
142: if (argtype & AINDX)
143: dotp->e_xvalue++;
144: /*
145: * This switch has been fixed by enumerating the no action
146: * alternatives (those that have 1 one byte of code)
147: * so that a casel instruction is emitted.
148: */
149: switch (argtype&~(AINDX|ASTAR)) {
150: case AREG:
151: case ABASE:
152: case ADECR:
153: case AINCR:
154: break;
155: case AEXP:
156: argtype = fetcharg(ITABFETCH(opcode), i);
157: if (argtype == A_BB)
158: break;
159: if (argtype == A_BW){
160: dotp->e_xvalue++;
161: break;
162: }
163: /*
164: * Reduces to PC relative
165: */
166: dotp->e_xvalue += ap->a_dispsize;
167: break;
168:
169: case ADISP:
170: xp=ap->a_xp;
171: if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){
172: dotp->e_xvalue += ap->a_dispsize;
173: break;
174: }
175: if (xp->e_xvalue==0 && !(argtype&ASTAR))
176: break;
177: dotp->e_xvalue += 1;
178: if (ISBYTE(xp->e_xvalue))
179: break;
180: dotp->e_xvalue += 1;
181: if (ISWORD(xp->e_xvalue))
182: break;
183: dotp->e_xvalue += 2;
184: break;
185:
186: case AIMM:
187: if (ap->a_atype&ASTAR) {
188: argtype=TYPL;
189: } else {
190: argtype = fetcharg(ITABFETCH(opcode), i);
191: if (argtype&ACCA)
192: argtype = TYPL;
193: else
194: argtype &= TYPMASK;
195: xp = ap->a_xp;
196: if (immconstant(ap->a_xp, argtype, &value))
197: break;
198: }
199: dotp->e_xvalue += ty_nbyte[argtype];
200: } /*end of the switch on the type*/
201: } /*end of looping for all arguments*/
202: return;
203:
204: PASS2:
205: /*
206: * Output the opcode
207: */
208: switch(opcode.Op_eopcode){
209: case NEW:
210: nnewopcodes++;
211: break;
212: case ESCD:
213: case ESCF:
214: nGHopcodes++;
215: Outb(opcode.Op_eopcode);
216: break;
217: case CORE:
218: break;
219: default:
220: panic("Bad escape opcode");
221: }
222: Outb(opcode.Op_popcode);
223:
224: for (i=0; i<n; i++,ap++) {/* now for the arguments */
225: argtype=ap->a_atype;
226: xp=ap->a_xp;
227: reloc_how = TYPNONE;
228: if (argtype&AINDX) {
229: { Outb(0x40 | ap->a_areg2); }
230: argtype &= ~AINDX;
231: }
232: if (argtype&ASTAR) {
233: ap->a_areg1 |= 0x10;
234: argtype &= ~ASTAR;
235: }
236: switch (argtype) {
237: case AREG: /* %r */
238: ap->a_areg1 |= 0x50;
239: break;
240: case ABASE: /* (%r) */
241: ap->a_areg1 |= 0x60;
242: break;
243: case ADECR: /* -(%r) */
244: ap->a_areg1 |= 0x70;
245: break;
246: case AINCR: /* (%r)+ */
247: ap->a_areg1 |= 0x80;
248: break;
249: case AEXP: /* expr */
250: argtype = fetcharg(ITABFETCH(opcode), i);
251: if (argtype == A_BB) {
252: ap->a_areg1 = argtype =
253: xp->e_xvalue - (dotp->e_xvalue + 1);
254: if (xp->e_xtype & XXTRN)
255: yywarning("%s: destination label is external",
256: FETCHNAME(ITABFETCH(opcode)));
257: if (!ISBYTE(argtype))
258: yyerror("%s: Branch too far(%db): try -J flag",
259: FETCHNAME(ITABFETCH(opcode)),
260: argtype);
261: break;
262: }
263: if (argtype == A_BW) {
264: ap->a_areg1 = argtype = xp->e_xvalue
265: -= dotp->e_xvalue + 2;
266: if (xp->e_xtype & XXTRN)
267: yywarning("%s: destination label is external",
268: FETCHNAME(ITABFETCH(opcode)));
269: xp->e_xtype = XABS;
270: if (!ISWORD(argtype))
271: yyerror("%s: Branch too far(%db): try -J flag",
272: FETCHNAME(ITABFETCH(opcode)),
273: argtype);
274: xp->e_xvalue = argtype>>8;
275: reloc_how = TYPB;
276: break;
277: }
278: /* reduces to expr(pc) mode */
279: ap->a_areg1 |= (0xAF + mod124[ap->a_dispsize]);
280: reloc_how = type_124[ap->a_dispsize] + RELOC_PCREL;
281: break;
282:
283: case ADISP: /* expr(%r) */
284: ap->a_areg1 |= 0xA0;
285: if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){
286: ap->a_areg1 += mod124[ap->a_dispsize];
287: reloc_how = type_124[ap->a_dispsize];
288: break;
289: }
290: if (xp->e_xvalue==0 && !(ap->a_areg1&0x10)) {
291: ap->a_areg1 ^= 0xC0;
292: break;
293: }
294: reloc_how = TYPB;
295: if (ISBYTE(xp->e_xvalue))
296: break;
297: ap->a_areg1 += 0x20;
298: reloc_how = TYPW;
299: if (ISWORD(xp->e_xvalue))
300: break;
301: ap->a_areg1 += 0x20;
302: reloc_how = TYPL;
303: break;
304:
305: case AIMM: /* $expr */
306: if (ap->a_atype&ASTAR) {
307: argtype=TYPL;
308: } else {
309: argtype = fetcharg(ITABFETCH(opcode), i);
310: if (argtype&ACCA)
311: argtype = TYPL;
312: else
313: argtype &= TYPMASK;
314: if (immconstant(xp, argtype, &value)){
315: reloc_how = TYPNONE;
316: ap->a_areg1 = value;
317: break;
318: }
319: }
320: ap->a_areg1 |= 0x8F;
321: reloc_how = argtype;
322: break;
323:
324: } /*end of the switch on argtype*/
325: /*
326: * use the first byte to describe the argument
327: */
328: Outb(ap->a_areg1);
329: if (reloc_how != TYPNONE)
330: outrel(xp, reloc_how);
331: } /*end of the for to pick up all arguments*/
332: }
333: /*
334: * Is xp an immediate constant?
335: * argtype: how the instruction will interpret the bytes
336: * xp->e_number.num_tag ("numtype"): the kind of number given
337: *
338: * Use the following table:
339: * float: TYPF, TYPD, TYPG, TYPH
340: * quad: TYPQ, TYPO
341: * int: TYPG, TYPW, TYPL
342: *
343: * numtype
344: * argtype float quad int
345: *
346: * float slitflt slitflt slitflt
347: * quad 0 0 0
348: * int 0..63 0 0..63
349: *
350: * Where the table entry implies the predicate to return.
351: */
352: #define IMMFLT 1 /* these flags are not used by anybody (yet) */
353: #define IMMINT 2
354:
355: int immconstant(xp, argtype, valuep)
356: reg struct exp *xp;
357: int argtype;
358: int *valuep;
359: {
360: reg int back = 0;
361: int numtype;
362: reg int fits;
363:
364: if ((xp->e_xtype & XTYPE) != XABS)
365: return(0);
366: if ((xp->e_xtype & XFORW) != 0)
367: return(0);
368: numtype = xp->e_number.num_tag;
369:
370: fits = 1;
371: if (passno == 2) switch(argtype){
372: case TYPB:
373: switch(numtype){
374: default: fits = 0; break;
375: case TYPB: fits = 1; break;
376: case TYPW:
377: case TYPL:
378: fits = ISBYTE(xp->e_xvalue) || ISUBYTE(xp->e_xvalue);
379: break;
380: }
381: break;
382: case TYPW:
383: switch(numtype){
384: default: fits = 0; break;
385: case TYPB:
386: case TYPW: fits = 1; break;
387: case TYPL:
388: fits = ISWORD(xp->e_xvalue) || ISUWORD(xp->e_xvalue);
389: break;
390: }
391: break;
392: case TYPF:
393: if (numtype == TYPD){ /* same format for first 32 bits */
394: fits = 1;
395: break;
396: }
397: /*FALLTHROUGH*/
398: default:
399: fits = ty_nbyte[argtype] >= ty_nbyte[numtype];
400: }
401: if (!fits){
402: yywarning("Immediate constant type %s mismatches instruction type %s",
403: ty_string[numtype],
404: ty_string[argtype]);
405: }
406:
407: switch(argtype){
408: case TYPF:
409: case TYPG:
410: case TYPD:
411: case TYPH:
412: back = slitflt(xp->e_number, argtype, valuep);
413: break;
414: case TYPO:
415: case TYPQ:
416: back = 0;
417: break;
418: case TYPB:
419: case TYPW:
420: case TYPL:
421: switch(numtype){
422: case TYPO:
423: case TYPQ:
424: back = 0;
425: break;
426: default:
427: *valuep = xp->e_xvalue;
428: back = ISLIT(xp->e_xvalue);
429: break;
430: }
431: break;
432: }
433: return(back);
434: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.