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