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