1592Sbill /* Copyright (c) 1980 Regents of the University of California */ 2*629Shenry static char sccsid[] = "@(#)ascode.c 4.2 08/15/80"; 3592Sbill #include <stdio.h> 4592Sbill #include "as.h" 5592Sbill #include "assyms.h" 6592Sbill 7592Sbill insout(op, ap, nact) 8592Sbill struct arg *ap; 9592Sbill { 10592Sbill int jxxflg; 11592Sbill 12592Sbill op &= 0xFF; 13592Sbill jxxflg = nact; 14592Sbill if (nact < 0) 15592Sbill nact = -nact; 16592Sbill if (passno == 1) { 17592Sbill register struct arg *ap2; 18592Sbill register struct instab *ip; 19592Sbill int i,nexp; 20592Sbill ip = itab[op]; 21*629Shenry nexp = ip->i_nargs; 22592Sbill if (nact < nexp) 23592Sbill yyerror("Too few arguments"); 24592Sbill if (nact > nexp) { 25592Sbill yyerror("Too many arguments"); 26592Sbill nact = nexp; 27592Sbill } 28592Sbill /* 29592Sbill * Check argument compatability with instruction template 30592Sbill */ 31592Sbill for (ap2 = ap+nact, i = nact; --i >= 0;) 32*629Shenry argcompat(--ap2, fetcharg(ip, i), i+1); 33592Sbill } 34592Sbill if (jxxflg < 0) 35592Sbill ijxout(op, ap, nact); 36592Sbill else putins(op, ap, nact); 37592Sbill } 38592Sbill 39592Sbill argcompat(act, exp, i) 40592Sbill struct arg *act; 41592Sbill int exp,i; 42592Sbill { 43592Sbill register at,atm; 44592Sbill 45*629Shenry at = act->a_atype; 46592Sbill atm = at & AMASK; 47592Sbill 48592Sbill if ( (exp & ACCB) && (!((atm == AEXP) || (atm == AIMM))) ){ 49592Sbill yyerror("arg %d, branch displacement must be an expression",i); 50592Sbill return; 51592Sbill } 52592Sbill if ((exp & ACCA) && (atm == AREG)) { 53592Sbill yyerror("arg %d, addressing a register",i); 54592Sbill return; 55592Sbill } 56592Sbill if ((exp&ACCW) && (atm==AIMM) && !(at&ASTAR)) { 57592Sbill yyerror("arg %d, modifying a constant",i); 58592Sbill return; 59592Sbill } 60592Sbill if (at & AINDX) { 61*629Shenry if (act->a_areg2==017) { 62592Sbill yyerror("arg %d, PC used as index",i); 63592Sbill return; 64592Sbill } 65592Sbill if (atm==AREG) { 66592Sbill yyerror("arg %d, indexing the register file",i); 67592Sbill return; 68592Sbill } 69592Sbill if (atm==AIMM) { 70592Sbill yyerror("arg %d, indexing a constant",i); 71592Sbill return; 72592Sbill } 73*629Shenry if (((atm==ADECR) || (atm==AINCR)) && (act->a_areg1==act->a_areg2)) { 74592Sbill yyerror("arg %d, indexing with modified register",i); 75592Sbill return; 76592Sbill } 77592Sbill } 78592Sbill } 79592Sbill 80592Sbill extern int d124; 81592Sbill int len124[] = {0,LEN1,LEN2,0,LEN4}; 82592Sbill char mod124[] = {0,0x00,0x20,0,0x40}; 83592Sbill 84592Sbill putins(op, ap, n) 85592Sbill /* 86592Sbill * n had better be positive 87592Sbill */ 88592Sbill register struct arg *ap; 89592Sbill { 90592Sbill register struct exp *xp; 91592Sbill register int a; 92592Sbill int i,xtrab; 93592Sbill 94592Sbill #ifdef DEBUG 95592Sbill fflush(stdout); 96592Sbill #endif 97592Sbill if (passno == 2) 98592Sbill goto PASS2; 99592Sbill 100*629Shenry dotp->e_xvalue += n+1; /* 1 for the opcode, at least 1 per arg */ 101*629Shenry for (i=0; i<n; i++,ap++) { /* some args take more than 1 byte */ 102*629Shenry a = ap->a_atype; 103592Sbill if (a & AINDX) 104*629Shenry dotp->e_xvalue++; 105592Sbill switch (a&~(AINDX|ASTAR)) { 106592Sbill case AEXP: 107*629Shenry a = fetcharg(itab[op], i); 108592Sbill if (a == ACCB+TYPB) 109592Sbill break; 110592Sbill if (a==ACCB+TYPW){ 111*629Shenry dotp->e_xvalue++; 112592Sbill break; 113592Sbill } 114592Sbill /* 115592Sbill * Reduces to PC relative 116592Sbill */ 117*629Shenry dotp->e_xvalue += ap->a_dispsize; 118592Sbill break; 119592Sbill 120592Sbill case ADISP: 121*629Shenry xp=ap->a_xp; 122*629Shenry if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){ 123*629Shenry dotp->e_xvalue += ap->a_dispsize; 124592Sbill break; 125592Sbill } 126*629Shenry if (xp->e_xvalue==0 && !(a&ASTAR)) 127592Sbill break; 128*629Shenry dotp->e_xvalue++; 129*629Shenry if ((xp->e_xvalue<MINBYTE) || (xp->e_xvalue>MAXBYTE)) 130*629Shenry dotp->e_xvalue++; 131*629Shenry if ((xp->e_xvalue<MINWORD) || (xp->e_xvalue>MAXWORD)) 132*629Shenry dotp->e_xvalue += 2; 133592Sbill break; 134592Sbill 135592Sbill case AIMM: 136*629Shenry if (ap->a_atype&ASTAR) a=TYPL; 137592Sbill else { 138*629Shenry a = fetcharg(itab[op], i); 139592Sbill if (a&ACCA) 140592Sbill a = TYPL; 141592Sbill else 142592Sbill a &= TYPMASK; 143*629Shenry xp = ap->a_xp; 144*629Shenry if ( ((xp->e_xtype&XTYPE)==XABS) 145*629Shenry && (!(xp->e_xtype&XFORW)) 146*629Shenry && (xp->e_xvalue>=0) 147*629Shenry && (xp->e_xvalue<=63) 148*629Shenry && (xp->e_yvalue == 0) 149592Sbill && (a != TYPD) 150592Sbill && (a != TYPF) 151592Sbill ) 152592Sbill break; 153592Sbill } 154592Sbill switch (a) { 155592Sbill case TYPD: 156592Sbill case TYPF: 157*629Shenry if ( !(((xp->e_xtype&XTYPE)==XABS) 158*629Shenry && (!(xp->e_xtype&XFORW)) 159592Sbill && (slitflt(xp))) 160592Sbill ){ 161592Sbill /* it is NOT short */ 162*629Shenry dotp->e_xvalue += ((a==TYPF)? 163592Sbill 4 : 8); 164592Sbill } 165592Sbill break; 166592Sbill case TYPQ: 167*629Shenry dotp->e_xvalue += 8;break; 168592Sbill case TYPL: 169*629Shenry dotp->e_xvalue += 4;break; 170592Sbill case TYPW: 171*629Shenry dotp->e_xvalue += 2;break; 172592Sbill case TYPB: 173*629Shenry dotp->e_xvalue += 1;break; 174592Sbill } /*end of the switch on a*/ 175592Sbill } /*end of the switch on the type*/ 176592Sbill } /*end of looping for all arguments*/ 177592Sbill return; 178592Sbill 179592Sbill PASS2: 180592Sbill 181592Sbill #ifdef UNIX 182592Sbill outb(op); /* the opcode */ 183592Sbill #endif UNIX 184592Sbill #ifdef VMS 185592Sbill *vms_obj_ptr++ = -1; *vms_obj_ptr++ = (char)op; 186*629Shenry dotp->e_xvalue += 1; 187592Sbill #endif VMS 188592Sbill 189592Sbill for (i=0; i<n; i++,ap++) {/* now for the arguments */ 190*629Shenry a=ap->a_atype; 191*629Shenry xp=ap->a_xp; 192592Sbill xtrab=0; 193592Sbill if (a&AINDX) { 194592Sbill #ifdef UNIX 195*629Shenry { outb(0x40 | ap->a_areg2); } 196592Sbill #endif UNIX 197592Sbill #ifdef VMS 198592Sbill { *vms_obj_ptr++ = -1; 199*629Shenry *vms_obj_ptr++ = (0x40 | ap->a_areg2); 200*629Shenry dotp->e_xvalue += 1; } 201592Sbill #endif VMS 202592Sbill a &= ~AINDX; 203592Sbill } 204592Sbill if (a&ASTAR) { 205*629Shenry ap->a_areg1 |= 0x10; 206592Sbill a &= ~ASTAR; 207592Sbill } 208592Sbill switch (a) { 209592Sbill case AREG: /* %r */ 210*629Shenry ap->a_areg1 |= 0x50; 211592Sbill break; 212592Sbill case ABASE: /* (%r) */ 213*629Shenry ap->a_areg1 |= 0x60; 214592Sbill break; 215592Sbill case ADECR: /* -(%r) */ 216*629Shenry ap->a_areg1 |= 0x70; 217592Sbill break; 218592Sbill case AINCR: /* (%r) */ 219*629Shenry ap->a_areg1 |= 0x80; 220592Sbill break; 221592Sbill case AEXP: /* expr */ 222*629Shenry a = fetcharg(itab[op], i); 223592Sbill if (a == ACCB+TYPB) { 224*629Shenry ap->a_areg1 = a = 225*629Shenry xp->e_xvalue - (dotp->e_xvalue + 1); 226592Sbill if (a<MINBYTE || a>MAXBYTE) 227592Sbill yyerror("Branch too far"); break; 228592Sbill } 229592Sbill if (a == ACCB+TYPW) { 230*629Shenry ap->a_areg1 = a = xp->e_xvalue 231*629Shenry -= dotp->e_xvalue + 2; 232*629Shenry xp->e_xtype = XABS; 233592Sbill if (a<MINWORD || a>MAXWORD) 234592Sbill yyerror("Branch too far"); 235*629Shenry xp->e_xvalue = a>>8; 236592Sbill xtrab = LEN1; 237592Sbill break; 238592Sbill } 239592Sbill /* reduces to expr(pc) mode */ 240*629Shenry ap->a_areg1 |= (0xAF + mod124[ap->a_dispsize]); 241*629Shenry xtrab = len124[ap->a_dispsize]+PCREL; 242592Sbill break; 243592Sbill 244592Sbill case ADISP: /* expr(%r) */ 245*629Shenry ap->a_areg1 |= 0xA0; 246*629Shenry if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){ 247*629Shenry ap->a_areg1 += mod124[ap->a_dispsize]; 248*629Shenry xtrab=len124[ap->a_dispsize]; 249592Sbill break; 250592Sbill } 251*629Shenry if (xp->e_xvalue==0 && !(ap->a_areg1&0x10)) { 252*629Shenry ap->a_areg1 ^= 0xC0; 253592Sbill break; 254592Sbill } 255592Sbill xtrab=LEN1; 256*629Shenry if ((xp->e_xvalue<MINBYTE) || (xp->e_xvalue>MAXBYTE)){ 257*629Shenry ap->a_areg1 += 0x20; 258592Sbill xtrab=LEN2; 259592Sbill } 260*629Shenry if ((xp->e_xvalue<MINWORD) || (xp->e_xvalue>MAXWORD)){ 261*629Shenry ap->a_areg1 += 0x20; 262592Sbill xtrab=LEN4; 263592Sbill } 264592Sbill break; 265592Sbill 266592Sbill case AIMM: /* $expr */ 267*629Shenry if (ap->a_atype&ASTAR) 268592Sbill a=TYPL; 269592Sbill else { 270*629Shenry a = fetcharg(itab[op], i); 271592Sbill if (a&ACCA) 272592Sbill a=TYPL; 273592Sbill else 274592Sbill a &= TYPMASK; 275*629Shenry if ( ( (xp->e_xtype&XTYPE) == XABS) 276*629Shenry && !(xp->e_xtype&XFORW) 277*629Shenry && (xp->e_xvalue >= 0) 278*629Shenry && (xp->e_xvalue <= 63) 279*629Shenry && (xp->e_yvalue == 0) 280592Sbill && (a != TYPF) 281592Sbill && (a != TYPD) ) { 282*629Shenry ap->a_areg1 = xp->e_xvalue; 283592Sbill break; 284592Sbill } 285592Sbill } 286*629Shenry ap->a_areg1 |= 0x8F; 287592Sbill switch (a) { 288592Sbill case TYPD: 289592Sbill case TYPF: 290*629Shenry if ( ((xp->e_xtype&XTYPE)==XABS) 291*629Shenry && (!(xp->e_xtype&XFORW)) 292592Sbill && (slitflt(xp)) 293592Sbill ){ 294*629Shenry ap->a_areg1=extlitflt(xp); 295592Sbill } else { 296592Sbill xtrab = (a==TYPF) ? LEN4: LEN8; 297592Sbill } 298592Sbill break; 299592Sbill case TYPQ: xtrab = LEN8; break; 300592Sbill case TYPL: xtrab = LEN4; break; 301592Sbill case TYPW: xtrab = LEN2; break; 302592Sbill case TYPB: xtrab = LEN1; break; 303592Sbill } 304592Sbill break; 305592Sbill 306592Sbill } /*end of the switch on a*/ 307592Sbill /* 308592Sbill * use the first byte to describe the argument 309592Sbill */ 310592Sbill #ifdef UNIX 311*629Shenry outb(ap->a_areg1); 312592Sbill #endif UNIX 313592Sbill #ifdef VMS 314*629Shenry *vms_obj_ptr++ = -1; *vms_obj_ptr++ = (char)(ap->a_areg1); 315*629Shenry dotp->e_xvalue += 1; 316592Sbill if ((vms_obj_ptr-sobuf) > 400) { 317592Sbill write(objfil,sobuf,vms_obj_ptr-sobuf); 318592Sbill vms_obj_ptr=sobuf+1; 319592Sbill } 320592Sbill #endif VMS 321592Sbill if (xtrab) 322592Sbill /* 323592Sbill * Floating point numbers are written to a.out 324592Sbill * by outrel; they require that the least significant 325592Sbill * 4 bytes of an 8 byte double precision number 326592Sbill * immediately follow the field xvalue, which 327592Sbill * they do. 328592Sbill */ 329*629Shenry outrel(&xp->e_xvalue, xtrab, xp->e_xtype, xp->e_xname); 330592Sbill } /*end of the for to pick up all arguments*/ 331592Sbill } 332