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 } 432