1 /* 2 * Copyright (c) 1982 Regents of the University of California 3 */ 4 #ifndef lint 5 static char sccsid[] = "@(#)ascode.c 4.11 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 if (reloc_how != TYPNONE) 330 outrel(xp, reloc_how); 331 } /*end of the for to pick up all arguments*/ 332 } 333 /* 334 * Is xp an immediate constant? 335 * argtype: how the instruction will interpret the bytes 336 * xp->e_number.num_tag ("numtype"): the kind of number given 337 * 338 * Use the following table: 339 * float: TYPF, TYPD, TYPG, TYPH 340 * quad: TYPQ, TYPO 341 * int: TYPG, TYPW, TYPL 342 * 343 * numtype 344 * argtype float quad int 345 * 346 * float slitflt slitflt slitflt 347 * quad 0 0 0 348 * int 0..63 0 0..63 349 * 350 * Where the table entry implies the predicate to return. 351 */ 352 #define IMMFLT 1 /* these flags are not used by anybody (yet) */ 353 #define IMMINT 2 354 355 int immconstant(xp, argtype, valuep) 356 reg struct exp *xp; 357 int argtype; 358 int *valuep; 359 { 360 reg int back = 0; 361 int numtype; 362 reg int fits; 363 364 if ((xp->e_xtype & XTYPE) != XABS) 365 return(0); 366 if ((xp->e_xtype & XFORW) != 0) 367 return(0); 368 numtype = xp->e_number.num_tag; 369 370 fits = 1; 371 if (passno == 2) switch(argtype){ 372 case TYPB: 373 switch(numtype){ 374 default: fits = 0; break; 375 case TYPB: fits = 1; break; 376 case TYPW: 377 case TYPL: 378 fits = ISBYTE(xp->e_xvalue) || ISUBYTE(xp->e_xvalue); 379 break; 380 } 381 break; 382 case TYPW: 383 switch(numtype){ 384 default: fits = 0; break; 385 case TYPB: 386 case TYPW: fits = 1; break; 387 case TYPL: 388 fits = ISWORD(xp->e_xvalue) || ISUWORD(xp->e_xvalue); 389 break; 390 } 391 break; 392 case TYPF: 393 if (numtype == TYPD){ /* same format for first 32 bits */ 394 fits = 1; 395 break; 396 } 397 /*FALLTHROUGH*/ 398 default: 399 fits = ty_nbyte[argtype] >= ty_nbyte[numtype]; 400 } 401 if (!fits){ 402 yywarning("Immediate constant type %s mismatches instruction type %s", 403 ty_string[numtype], 404 ty_string[argtype]); 405 } 406 407 switch(argtype){ 408 case TYPF: 409 case TYPG: 410 case TYPD: 411 case TYPH: 412 back = slitflt(xp->e_number, argtype, valuep); 413 break; 414 case TYPO: 415 case TYPQ: 416 back = 0; 417 break; 418 case TYPB: 419 case TYPW: 420 case TYPL: 421 switch(numtype){ 422 case TYPO: 423 case TYPQ: 424 back = 0; 425 break; 426 default: 427 *valuep = xp->e_xvalue; 428 back = ISLIT(xp->e_xvalue); 429 break; 430 } 431 break; 432 } 433 return(back); 434 } 435