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