1 /* Copyright (c) 1980 Regents of the University of California */ 2 static char sccsid[] = "@(#)ascode.c 4.3 08/19/80"; 3 #include <stdio.h> 4 #include "as.h" 5 #include "assyms.h" 6 7 insout(op, ap, nact) 8 struct arg *ap; 9 { 10 int jxxflg; 11 12 op &= 0xFF; 13 jxxflg = nact; 14 if (nact < 0) 15 nact = -nact; 16 if (passno == 1) { 17 register struct arg *ap2; 18 register struct instab *ip; 19 int i,nexp; 20 ip = itab[op]; 21 nexp = ip->i_nargs; 22 if (nact < nexp) 23 yyerror("Too few arguments"); 24 if (nact > nexp) { 25 yyerror("Too many arguments"); 26 nact = nexp; 27 } 28 /* 29 * Check argument compatability with instruction template 30 */ 31 for (ap2 = ap+nact, i = nact; --i >= 0;) 32 argcompat(--ap2, fetcharg(ip, i), i+1); 33 } 34 if (jxxflg < 0) 35 ijxout(op, ap, nact); 36 else putins(op, ap, nact); 37 } 38 39 argcompat(act, exp, i) 40 struct arg *act; 41 int exp,i; 42 { 43 register at,atm; 44 45 at = act->a_atype; 46 atm = at & AMASK; 47 48 if ( (exp & ACCB) && (!((atm == AEXP) || (atm == AIMM))) ){ 49 yyerror("arg %d, branch displacement must be an expression",i); 50 return; 51 } 52 if (exp & ACCA){ 53 if (atm == AREG) { 54 yyerror("arg %d, addressing a register",i); 55 return; 56 } 57 if ( (atm == AIMM) && !(at & ASTAR) ){ 58 yyerror("arg %d, addressing an immediate operand",i); 59 return; 60 } 61 } 62 if ((exp&ACCW) && (atm==AIMM) && !(at&ASTAR)) { 63 yyerror("arg %d, modifying a constant",i); 64 return; 65 } 66 if (at & AINDX) { 67 if (act->a_areg2==017) { 68 yyerror("arg %d, PC used as index",i); 69 return; 70 } 71 if (atm==AREG) { 72 yyerror("arg %d, indexing the register file",i); 73 return; 74 } 75 if (atm==AIMM) { 76 yyerror("arg %d, indexing a constant",i); 77 return; 78 } 79 if (((atm==ADECR) || (atm==AINCR)) && (act->a_areg1==act->a_areg2)) { 80 yyerror("arg %d, indexing with modified register",i); 81 return; 82 } 83 } 84 } 85 86 extern int d124; 87 int len124[] = {0,LEN1,LEN2,0,LEN4}; 88 char mod124[] = {0,0x00,0x20,0,0x40}; 89 90 putins(op, ap, n) 91 /* 92 * n had better be positive 93 */ 94 register struct arg *ap; 95 { 96 register struct exp *xp; 97 register int a; 98 int i,xtrab; 99 100 #ifdef DEBUG 101 fflush(stdout); 102 #endif 103 if (passno == 2) 104 goto PASS2; 105 106 dotp->e_xvalue += n+1; /* 1 for the opcode, at least 1 per arg */ 107 for (i=0; i<n; i++,ap++) { /* some args take more than 1 byte */ 108 a = ap->a_atype; 109 if (a & AINDX) 110 dotp->e_xvalue++; 111 switch (a&~(AINDX|ASTAR)) { 112 case AEXP: 113 a = fetcharg(itab[op], i); 114 if (a == ACCB+TYPB) 115 break; 116 if (a==ACCB+TYPW){ 117 dotp->e_xvalue++; 118 break; 119 } 120 /* 121 * Reduces to PC relative 122 */ 123 dotp->e_xvalue += ap->a_dispsize; 124 break; 125 126 case ADISP: 127 xp=ap->a_xp; 128 if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){ 129 dotp->e_xvalue += ap->a_dispsize; 130 break; 131 } 132 if (xp->e_xvalue==0 && !(a&ASTAR)) 133 break; 134 dotp->e_xvalue++; 135 if ((xp->e_xvalue<MINBYTE) || (xp->e_xvalue>MAXBYTE)) 136 dotp->e_xvalue++; 137 if ((xp->e_xvalue<MINWORD) || (xp->e_xvalue>MAXWORD)) 138 dotp->e_xvalue += 2; 139 break; 140 141 case AIMM: 142 if (ap->a_atype&ASTAR) a=TYPL; 143 else { 144 a = fetcharg(itab[op], i); 145 if (a&ACCA) 146 a = TYPL; 147 else 148 a &= TYPMASK; 149 xp = ap->a_xp; 150 if ( ((xp->e_xtype&XTYPE)==XABS) 151 && (!(xp->e_xtype&XFORW)) 152 && (xp->e_xvalue>=0) 153 && (xp->e_xvalue<=63) 154 && (xp->e_yvalue == 0) 155 && (a != TYPD) 156 && (a != TYPF) 157 ) 158 break; 159 } 160 switch (a) { 161 case TYPD: 162 case TYPF: 163 if ( !(((xp->e_xtype&XTYPE)==XABS) 164 && (!(xp->e_xtype&XFORW)) 165 && (slitflt(xp))) 166 ){ 167 /* it is NOT short */ 168 dotp->e_xvalue += ((a==TYPF)? 169 4 : 8); 170 } 171 break; 172 case TYPQ: 173 dotp->e_xvalue += 8;break; 174 case TYPL: 175 dotp->e_xvalue += 4;break; 176 case TYPW: 177 dotp->e_xvalue += 2;break; 178 case TYPB: 179 dotp->e_xvalue += 1;break; 180 } /*end of the switch on a*/ 181 } /*end of the switch on the type*/ 182 } /*end of looping for all arguments*/ 183 return; 184 185 PASS2: 186 187 #ifdef UNIX 188 outb(op); /* the opcode */ 189 #endif UNIX 190 #ifdef VMS 191 *vms_obj_ptr++ = -1; *vms_obj_ptr++ = (char)op; 192 dotp->e_xvalue += 1; 193 #endif VMS 194 195 for (i=0; i<n; i++,ap++) {/* now for the arguments */ 196 a=ap->a_atype; 197 xp=ap->a_xp; 198 xtrab=0; 199 if (a&AINDX) { 200 #ifdef UNIX 201 { outb(0x40 | ap->a_areg2); } 202 #endif UNIX 203 #ifdef VMS 204 { *vms_obj_ptr++ = -1; 205 *vms_obj_ptr++ = (0x40 | ap->a_areg2); 206 dotp->e_xvalue += 1; } 207 #endif VMS 208 a &= ~AINDX; 209 } 210 if (a&ASTAR) { 211 ap->a_areg1 |= 0x10; 212 a &= ~ASTAR; 213 } 214 switch (a) { 215 case AREG: /* %r */ 216 ap->a_areg1 |= 0x50; 217 break; 218 case ABASE: /* (%r) */ 219 ap->a_areg1 |= 0x60; 220 break; 221 case ADECR: /* -(%r) */ 222 ap->a_areg1 |= 0x70; 223 break; 224 case AINCR: /* (%r)+ */ 225 ap->a_areg1 |= 0x80; 226 break; 227 case AEXP: /* expr */ 228 a = fetcharg(itab[op], i); 229 if (a == ACCB+TYPB) { 230 ap->a_areg1 = a = 231 xp->e_xvalue - (dotp->e_xvalue + 1); 232 if (a<MINBYTE || a>MAXBYTE) 233 yyerror("Branch too far"); break; 234 } 235 if (a == ACCB+TYPW) { 236 ap->a_areg1 = a = xp->e_xvalue 237 -= dotp->e_xvalue + 2; 238 xp->e_xtype = XABS; 239 if (a<MINWORD || a>MAXWORD) 240 yyerror("Branch too far"); 241 xp->e_xvalue = a>>8; 242 xtrab = LEN1; 243 break; 244 } 245 /* reduces to expr(pc) mode */ 246 ap->a_areg1 |= (0xAF + mod124[ap->a_dispsize]); 247 xtrab = len124[ap->a_dispsize]+PCREL; 248 break; 249 250 case ADISP: /* expr(%r) */ 251 ap->a_areg1 |= 0xA0; 252 if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){ 253 ap->a_areg1 += mod124[ap->a_dispsize]; 254 xtrab=len124[ap->a_dispsize]; 255 break; 256 } 257 if (xp->e_xvalue==0 && !(ap->a_areg1&0x10)) { 258 ap->a_areg1 ^= 0xC0; 259 break; 260 } 261 xtrab=LEN1; 262 if ((xp->e_xvalue<MINBYTE) || (xp->e_xvalue>MAXBYTE)){ 263 ap->a_areg1 += 0x20; 264 xtrab=LEN2; 265 } 266 if ((xp->e_xvalue<MINWORD) || (xp->e_xvalue>MAXWORD)){ 267 ap->a_areg1 += 0x20; 268 xtrab=LEN4; 269 } 270 break; 271 272 case AIMM: /* $expr */ 273 if (ap->a_atype&ASTAR) 274 a=TYPL; 275 else { 276 a = fetcharg(itab[op], i); 277 if (a&ACCA) 278 a=TYPL; 279 else 280 a &= TYPMASK; 281 if ( ( (xp->e_xtype&XTYPE) == XABS) 282 && !(xp->e_xtype&XFORW) 283 && (xp->e_xvalue >= 0) 284 && (xp->e_xvalue <= 63) 285 && (xp->e_yvalue == 0) 286 && (a != TYPF) 287 && (a != TYPD) ) { 288 ap->a_areg1 = xp->e_xvalue; 289 break; 290 } 291 } 292 ap->a_areg1 |= 0x8F; 293 switch (a) { 294 case TYPD: 295 case TYPF: 296 if ( ((xp->e_xtype&XTYPE)==XABS) 297 && (!(xp->e_xtype&XFORW)) 298 && (slitflt(xp)) 299 ){ 300 ap->a_areg1=extlitflt(xp); 301 } else { 302 xtrab = (a==TYPF) ? LEN4: LEN8; 303 } 304 break; 305 case TYPQ: xtrab = LEN8; break; 306 case TYPL: xtrab = LEN4; break; 307 case TYPW: xtrab = LEN2; break; 308 case TYPB: xtrab = LEN1; break; 309 } 310 break; 311 312 } /*end of the switch on a*/ 313 /* 314 * use the first byte to describe the argument 315 */ 316 #ifdef UNIX 317 outb(ap->a_areg1); 318 #endif UNIX 319 #ifdef VMS 320 *vms_obj_ptr++ = -1; *vms_obj_ptr++ = (char)(ap->a_areg1); 321 dotp->e_xvalue += 1; 322 if ((vms_obj_ptr-sobuf) > 400) { 323 write(objfil,sobuf,vms_obj_ptr-sobuf); 324 vms_obj_ptr=sobuf+1; 325 } 326 #endif VMS 327 if (xtrab) 328 /* 329 * Floating point numbers are written to a.out 330 * by outrel; they require that the least significant 331 * 4 bytes of an 8 byte double precision number 332 * immediately follow the field xvalue, which 333 * they do. 334 */ 335 outrel(&xp->e_xvalue, xtrab, xp->e_xtype, xp->e_xname); 336 } /*end of the for to pick up all arguments*/ 337 } 338