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