BSD 3 development
[unix-history] / usr / src / cmd / as / ascode.c
CommitLineData
629188b5
JR
1/* Copyright (c) 1979 Regents of the University of California */
2#include <stdio.h>
3#include "as.h"
4#include "assyms.h"
5
6insout(op, ap, nact)
7 struct arg *ap;
8{
9 int jxxflg;
10
11 op &= 0xFF;
12 jxxflg = nact;
13 if (nact < 0)
14 nact = -nact;
15 if (passno!=2) {
16 register struct arg *ap2;
17 register struct instab *ip;
18 int i,nexp;
19 ip = itab[op];
20 nexp = ip->nargs;
21 if (nact < nexp)
22 yyerror("Too few arguments");
23 if (nact > nexp) {
24 yyerror("Too many arguments");
25 nact = nexp;
26 }
27 /*
28 * Check argument compatability with instruction template
29 */
30 for (ap2 = ap+nact, i = nact; --i >= 0;)
31 argcompat(--ap2, ip->argtype[i], i);
32 }
33 if (jxxflg < 0)
34 ijxout(op, ap, nact);
35 else putins(op, ap, nact);
36}
37
38argcompat(act, exp, i)
39 struct arg *act;
40 int exp,i;
41{
42 register at,atm;
43
44 at = act->atype;
45 atm = at & AMASK;
46
47 if ((exp & ACCA) && (atm == AREG)) {
48 yyerror("arg %d, addressing a register",i);
49 return;
50 }
51 if ((exp&ACCW) && (atm==AIMM) && !(at&ASTAR)) {
52 yyerror("arg %d, modifying a constant",i);
53 return;
54 }
55 if (at & AINDX) {
56 if (act->areg2==017) {
57 yyerror("arg %d, PC used as index",i);
58 return;
59 }
60 if (atm==AREG) {
61 yyerror("arg %d, indexing the register file",i);
62 return;
63 }
64 if (atm==AIMM) {
65 yyerror("arg %d, indexing a constant",i);
66 return;
67 }
68 if (((atm==ADECR) || (atm==AINCR)) && (act->areg1==act->areg2)) {
69 yyerror("arg %d, indexing with modified register",i);
70 return;
71 }
72 }
73}
74
75int d124 = {4};
76int len124[] = {0,LEN1,LEN2,0,LEN4};
77char mod124[] = {0,0x00,0x20,0,0x40};
78
79putins(op, ap, n)
80 /*
81 * n had better be positive
82 */
83 register struct arg *ap;
84{
85 register struct exp *xp;
86 register int a;
87 int i,xtrab;
88
89 if (passno!=2) {
90 dotp->xvalue += n+1; /* 1 for the opcode, at least 1 per arg */
91 for (i=0; i<n; i++,ap++) {/* some args take more than 1 byte */
92 a=ap->atype;
93 if (a & AINDX)
94 dotp->xvalue++;
95 switch (a&~(AINDX|ASTAR)) {
96 case AEXP: {
97 a = itab[op]->argtype[i];
98 if (a == ACCB+TYPB)
99 break;
100 if (a==ACCB+TYPW){
101 dotp->xvalue++;
102 break;
103 }
104 dotp->xvalue += ap->dispsize;
105 break;
106 }
107 case ADISP: {
108 xp=ap->xp;
109 if ((xp->xtype&XTYPE)!=XABS || xp->xtype&XFORW){
110 dotp->xvalue += ap->dispsize;
111 break;
112 }
113 if (xp->xvalue==0 && !(a&ASTAR))
114 break;
115 dotp->xvalue++;
116 if ((xp->xvalue<MINBYTE) || (xp->xvalue>MAXBYTE))
117 dotp->xvalue++;
118 if ((xp->xvalue<MINWORD) || (xp->xvalue>MAXWORD))
119 dotp->xvalue += 2;
120 break;
121 }
122 case AIMM: {
123 if (ap->atype&ASTAR) a=TYPL;
124 else {
125 xp = ap->xp;
126 if ((xp->xtype&XTYPE)==XABS && !(xp->xtype&XFORW)
127 && xp->xvalue>=0 && xp->xvalue<=63)
128 break;
129 a = itab[op]->argtype[i];
130 if (a&ACCA)
131 a = TYPL;
132 else
133 a &= TYPMASK;
134 }
135 switch (a) {
136 case TYPD:
137 case TYPF:
138 if (slitflt(xp))
139 break;
140 if (a==TYPF)
141 dotp->xvalue -= 4;
142 case TYPQ:
143 dotp->xvalue += 4;
144 case TYPL:
145 dotp->xvalue += 2;
146 case TYPW:
147 dotp->xvalue++;
148 case TYPB:
149 dotp->xvalue++;
150 } /*end of the switch on a*/
151 } /*end of case AIMM*/
152 } /*end of the switch on the type*/
153 } /*end of looping for all arguments*/
154 return;
155 } /*end of it being time for pass 1*/
156 /*
157 * PASS2 HERE
158 */
159
160 outb(op); /* the opcode */
161 for (i=0; i<n; i++,ap++) {/* now for the arguments */
162 a=ap->atype;
163 xp=ap->xp;
164 xtrab=0;
165 if (a&AINDX) {
166 { outb(0x40 | ap->areg2); }
167 a &= ~AINDX;
168 }
169 if (a&ASTAR) {
170 ap->areg1 |= 0x10;
171 a &= ~ASTAR;
172 }
173 switch (a) {
174 case AREG: /* %r */
175 ap->areg1 |= 0x50;
176 break;
177 case ABASE: /* (%r) */
178 ap->areg1 |= 0x60;
179 break;
180 case ADECR: /* -(%r) */
181 ap->areg1 |= 0x70;
182 break;
183 case AINCR: /* (%r) */
184 ap->areg1 |= 0x80;
185 break;
186 case AEXP: {/* expr */
187 a = itab[op]->argtype[i];
188 if (a == ACCB+TYPB) {
189 ap->areg1 = a =
190 xp->xvalue - (dotp->xvalue + 1);
191 if (a<MINBYTE || a>MAXBYTE)
192 yyerror("Branch too far"); break;
193 }
194 if (a == ACCB+TYPW) {
195 ap->areg1 = a = xp->xvalue
196 -= dotp->xvalue + 2;
197 xp->xtype = XABS;
198 if (a<MINWORD || a>MAXWORD)
199 yyerror("Branch too far");
200 xp->xvalue = a>>8;
201 xtrab = LEN1;
202 break;
203 }
204 /* reduces to expr(pc) mode */
205 ap->areg1 |= (0xAF + mod124[ap->dispsize]);
206 xtrab = len124[ap->dispsize]+PCREL;
207 break;
208 }
209 case ADISP: {/* expr(%r) */
210 ap->areg1 |= 0xA0;
211 if ((xp->xtype&XTYPE)!=XABS || xp->xtype&XFORW){
212 ap->areg1 += mod124[ap->dispsize];
213 xtrab=len124[ap->dispsize];
214 break;
215 }
216 if (xp->xvalue==0 && !(ap->areg1&0x10)) {
217 ap->areg1 ^= 0xC0;
218 break;
219 }
220 xtrab=LEN1;
221 if ((xp->xvalue<MINBYTE) || (xp->xvalue>MAXBYTE)){
222 ap->areg1 += 0x20;
223 xtrab=LEN2;
224 }
225 if ((xp->xvalue<MINWORD) || (xp->xvalue>MAXWORD)){
226 ap->areg1 += 0x20;
227 xtrab=LEN4;
228 }
229 break;
230 }
231 case AIMM: { /* $expr */
232 if (ap->atype&ASTAR)
233 a=TYPL;
234 else {
235 if ( ( (xp->xtype&XTYPE) == XABS)
236 && !(xp->xtype&XFORW)
237 && (xp->xvalue >= 0)
238 && (xp->xvalue <= 63) ) {
239 ap->areg1 = xp->xvalue;
240 break;
241 }
242 a = itab[op]->argtype[i];
243 if (a&ACCA)
244 a=TYPL;
245 else
246 a &= TYPMASK;
247 }
248 ap->areg1 |= 0x8F;
249 switch (a) {
250 case TYPD:
251 case TYPF:
252 if (slitflt(xp)){
253 ap->areg1=extlitflt(xp);
254 break;
255 }
256 if (a==TYPF) {
257 xtrab = LEN4;
258 break;
259 }
260 case TYPQ: xtrab = LEN8; break;
261 case TYPL: xtrab = LEN4; break;
262 case TYPW: xtrab = LEN2; break;
263 case TYPB: xtrab = LEN1; break;
264 }
265 } /*end of the switch on AIMM*/
266 } /*end of the switch on a*/
267 /*
268 * use the first byte to describe the argument
269 */
270 outb(ap->areg1);
271 if (xtrab)
272 outrel(&xp->xvalue, xtrab, xp->xtype, xp->xname);
273 } /*end of the for to pick up all arguments*/
274}