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