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