1592Sbill /* Copyright (c) 1980 Regents of the University of California */ 2*665Shenry static char sccsid[] = "@(#)ascode.c 4.3 08/19/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]; 21629Shenry 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;) 32629Shenry 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 45629Shenry 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 } 52*665Shenry if (exp & ACCA){ 53*665Shenry if (atm == AREG) { 54*665Shenry yyerror("arg %d, addressing a register",i); 55*665Shenry return; 56*665Shenry } 57*665Shenry if ( (atm == AIMM) && !(at & ASTAR) ){ 58*665Shenry yyerror("arg %d, addressing an immediate operand",i); 59*665Shenry return; 60*665Shenry } 61592Sbill } 62592Sbill if ((exp&ACCW) && (atm==AIMM) && !(at&ASTAR)) { 63592Sbill yyerror("arg %d, modifying a constant",i); 64592Sbill return; 65592Sbill } 66592Sbill if (at & AINDX) { 67629Shenry if (act->a_areg2==017) { 68592Sbill yyerror("arg %d, PC used as index",i); 69592Sbill return; 70592Sbill } 71592Sbill if (atm==AREG) { 72592Sbill yyerror("arg %d, indexing the register file",i); 73592Sbill return; 74592Sbill } 75592Sbill if (atm==AIMM) { 76592Sbill yyerror("arg %d, indexing a constant",i); 77592Sbill return; 78592Sbill } 79629Shenry if (((atm==ADECR) || (atm==AINCR)) && (act->a_areg1==act->a_areg2)) { 80592Sbill yyerror("arg %d, indexing with modified register",i); 81592Sbill return; 82592Sbill } 83592Sbill } 84592Sbill } 85592Sbill 86592Sbill extern int d124; 87592Sbill int len124[] = {0,LEN1,LEN2,0,LEN4}; 88592Sbill char mod124[] = {0,0x00,0x20,0,0x40}; 89592Sbill 90592Sbill putins(op, ap, n) 91592Sbill /* 92592Sbill * n had better be positive 93592Sbill */ 94592Sbill register struct arg *ap; 95592Sbill { 96592Sbill register struct exp *xp; 97592Sbill register int a; 98592Sbill int i,xtrab; 99592Sbill 100592Sbill #ifdef DEBUG 101592Sbill fflush(stdout); 102592Sbill #endif 103592Sbill if (passno == 2) 104592Sbill goto PASS2; 105592Sbill 106629Shenry dotp->e_xvalue += n+1; /* 1 for the opcode, at least 1 per arg */ 107629Shenry for (i=0; i<n; i++,ap++) { /* some args take more than 1 byte */ 108629Shenry a = ap->a_atype; 109592Sbill if (a & AINDX) 110629Shenry dotp->e_xvalue++; 111592Sbill switch (a&~(AINDX|ASTAR)) { 112592Sbill case AEXP: 113629Shenry a = fetcharg(itab[op], i); 114592Sbill if (a == ACCB+TYPB) 115592Sbill break; 116592Sbill if (a==ACCB+TYPW){ 117629Shenry dotp->e_xvalue++; 118592Sbill break; 119592Sbill } 120592Sbill /* 121592Sbill * Reduces to PC relative 122592Sbill */ 123629Shenry dotp->e_xvalue += ap->a_dispsize; 124592Sbill break; 125592Sbill 126592Sbill case ADISP: 127629Shenry xp=ap->a_xp; 128629Shenry if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){ 129629Shenry dotp->e_xvalue += ap->a_dispsize; 130592Sbill break; 131592Sbill } 132629Shenry if (xp->e_xvalue==0 && !(a&ASTAR)) 133592Sbill break; 134629Shenry dotp->e_xvalue++; 135629Shenry if ((xp->e_xvalue<MINBYTE) || (xp->e_xvalue>MAXBYTE)) 136629Shenry dotp->e_xvalue++; 137629Shenry if ((xp->e_xvalue<MINWORD) || (xp->e_xvalue>MAXWORD)) 138629Shenry dotp->e_xvalue += 2; 139592Sbill break; 140592Sbill 141592Sbill case AIMM: 142629Shenry if (ap->a_atype&ASTAR) a=TYPL; 143592Sbill else { 144629Shenry a = fetcharg(itab[op], i); 145592Sbill if (a&ACCA) 146592Sbill a = TYPL; 147592Sbill else 148592Sbill a &= TYPMASK; 149629Shenry xp = ap->a_xp; 150629Shenry if ( ((xp->e_xtype&XTYPE)==XABS) 151629Shenry && (!(xp->e_xtype&XFORW)) 152629Shenry && (xp->e_xvalue>=0) 153629Shenry && (xp->e_xvalue<=63) 154629Shenry && (xp->e_yvalue == 0) 155592Sbill && (a != TYPD) 156592Sbill && (a != TYPF) 157592Sbill ) 158592Sbill break; 159592Sbill } 160592Sbill switch (a) { 161592Sbill case TYPD: 162592Sbill case TYPF: 163629Shenry if ( !(((xp->e_xtype&XTYPE)==XABS) 164629Shenry && (!(xp->e_xtype&XFORW)) 165592Sbill && (slitflt(xp))) 166592Sbill ){ 167592Sbill /* it is NOT short */ 168629Shenry dotp->e_xvalue += ((a==TYPF)? 169592Sbill 4 : 8); 170592Sbill } 171592Sbill break; 172592Sbill case TYPQ: 173629Shenry dotp->e_xvalue += 8;break; 174592Sbill case TYPL: 175629Shenry dotp->e_xvalue += 4;break; 176592Sbill case TYPW: 177629Shenry dotp->e_xvalue += 2;break; 178592Sbill case TYPB: 179629Shenry dotp->e_xvalue += 1;break; 180592Sbill } /*end of the switch on a*/ 181592Sbill } /*end of the switch on the type*/ 182592Sbill } /*end of looping for all arguments*/ 183592Sbill return; 184592Sbill 185592Sbill PASS2: 186592Sbill 187592Sbill #ifdef UNIX 188592Sbill outb(op); /* the opcode */ 189592Sbill #endif UNIX 190592Sbill #ifdef VMS 191592Sbill *vms_obj_ptr++ = -1; *vms_obj_ptr++ = (char)op; 192629Shenry dotp->e_xvalue += 1; 193592Sbill #endif VMS 194592Sbill 195592Sbill for (i=0; i<n; i++,ap++) {/* now for the arguments */ 196629Shenry a=ap->a_atype; 197629Shenry xp=ap->a_xp; 198592Sbill xtrab=0; 199592Sbill if (a&AINDX) { 200592Sbill #ifdef UNIX 201629Shenry { outb(0x40 | ap->a_areg2); } 202592Sbill #endif UNIX 203592Sbill #ifdef VMS 204592Sbill { *vms_obj_ptr++ = -1; 205629Shenry *vms_obj_ptr++ = (0x40 | ap->a_areg2); 206629Shenry dotp->e_xvalue += 1; } 207592Sbill #endif VMS 208592Sbill a &= ~AINDX; 209592Sbill } 210592Sbill if (a&ASTAR) { 211629Shenry ap->a_areg1 |= 0x10; 212592Sbill a &= ~ASTAR; 213592Sbill } 214592Sbill switch (a) { 215592Sbill case AREG: /* %r */ 216629Shenry ap->a_areg1 |= 0x50; 217592Sbill break; 218592Sbill case ABASE: /* (%r) */ 219629Shenry ap->a_areg1 |= 0x60; 220592Sbill break; 221592Sbill case ADECR: /* -(%r) */ 222629Shenry ap->a_areg1 |= 0x70; 223592Sbill break; 224*665Shenry case AINCR: /* (%r)+ */ 225629Shenry ap->a_areg1 |= 0x80; 226592Sbill break; 227592Sbill case AEXP: /* expr */ 228629Shenry a = fetcharg(itab[op], i); 229592Sbill if (a == ACCB+TYPB) { 230629Shenry ap->a_areg1 = a = 231629Shenry xp->e_xvalue - (dotp->e_xvalue + 1); 232592Sbill if (a<MINBYTE || a>MAXBYTE) 233592Sbill yyerror("Branch too far"); break; 234592Sbill } 235592Sbill if (a == ACCB+TYPW) { 236629Shenry ap->a_areg1 = a = xp->e_xvalue 237629Shenry -= dotp->e_xvalue + 2; 238629Shenry xp->e_xtype = XABS; 239592Sbill if (a<MINWORD || a>MAXWORD) 240592Sbill yyerror("Branch too far"); 241629Shenry xp->e_xvalue = a>>8; 242592Sbill xtrab = LEN1; 243592Sbill break; 244592Sbill } 245592Sbill /* reduces to expr(pc) mode */ 246629Shenry ap->a_areg1 |= (0xAF + mod124[ap->a_dispsize]); 247629Shenry xtrab = len124[ap->a_dispsize]+PCREL; 248592Sbill break; 249592Sbill 250592Sbill case ADISP: /* expr(%r) */ 251629Shenry ap->a_areg1 |= 0xA0; 252629Shenry if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){ 253629Shenry ap->a_areg1 += mod124[ap->a_dispsize]; 254629Shenry xtrab=len124[ap->a_dispsize]; 255592Sbill break; 256592Sbill } 257629Shenry if (xp->e_xvalue==0 && !(ap->a_areg1&0x10)) { 258629Shenry ap->a_areg1 ^= 0xC0; 259592Sbill break; 260592Sbill } 261592Sbill xtrab=LEN1; 262629Shenry if ((xp->e_xvalue<MINBYTE) || (xp->e_xvalue>MAXBYTE)){ 263629Shenry ap->a_areg1 += 0x20; 264592Sbill xtrab=LEN2; 265592Sbill } 266629Shenry if ((xp->e_xvalue<MINWORD) || (xp->e_xvalue>MAXWORD)){ 267629Shenry ap->a_areg1 += 0x20; 268592Sbill xtrab=LEN4; 269592Sbill } 270592Sbill break; 271592Sbill 272592Sbill case AIMM: /* $expr */ 273629Shenry if (ap->a_atype&ASTAR) 274592Sbill a=TYPL; 275592Sbill else { 276629Shenry a = fetcharg(itab[op], i); 277592Sbill if (a&ACCA) 278592Sbill a=TYPL; 279592Sbill else 280592Sbill a &= TYPMASK; 281629Shenry if ( ( (xp->e_xtype&XTYPE) == XABS) 282629Shenry && !(xp->e_xtype&XFORW) 283629Shenry && (xp->e_xvalue >= 0) 284629Shenry && (xp->e_xvalue <= 63) 285629Shenry && (xp->e_yvalue == 0) 286592Sbill && (a != TYPF) 287592Sbill && (a != TYPD) ) { 288629Shenry ap->a_areg1 = xp->e_xvalue; 289592Sbill break; 290592Sbill } 291592Sbill } 292629Shenry ap->a_areg1 |= 0x8F; 293592Sbill switch (a) { 294592Sbill case TYPD: 295592Sbill case TYPF: 296629Shenry if ( ((xp->e_xtype&XTYPE)==XABS) 297629Shenry && (!(xp->e_xtype&XFORW)) 298592Sbill && (slitflt(xp)) 299592Sbill ){ 300629Shenry ap->a_areg1=extlitflt(xp); 301592Sbill } else { 302592Sbill xtrab = (a==TYPF) ? LEN4: LEN8; 303592Sbill } 304592Sbill break; 305592Sbill case TYPQ: xtrab = LEN8; break; 306592Sbill case TYPL: xtrab = LEN4; break; 307592Sbill case TYPW: xtrab = LEN2; break; 308592Sbill case TYPB: xtrab = LEN1; break; 309592Sbill } 310592Sbill break; 311592Sbill 312592Sbill } /*end of the switch on a*/ 313592Sbill /* 314592Sbill * use the first byte to describe the argument 315592Sbill */ 316592Sbill #ifdef UNIX 317629Shenry outb(ap->a_areg1); 318592Sbill #endif UNIX 319592Sbill #ifdef VMS 320629Shenry *vms_obj_ptr++ = -1; *vms_obj_ptr++ = (char)(ap->a_areg1); 321629Shenry dotp->e_xvalue += 1; 322592Sbill if ((vms_obj_ptr-sobuf) > 400) { 323592Sbill write(objfil,sobuf,vms_obj_ptr-sobuf); 324592Sbill vms_obj_ptr=sobuf+1; 325592Sbill } 326592Sbill #endif VMS 327592Sbill if (xtrab) 328592Sbill /* 329592Sbill * Floating point numbers are written to a.out 330592Sbill * by outrel; they require that the least significant 331592Sbill * 4 bytes of an 8 byte double precision number 332592Sbill * immediately follow the field xvalue, which 333592Sbill * they do. 334592Sbill */ 335629Shenry outrel(&xp->e_xvalue, xtrab, xp->e_xtype, xp->e_xname); 336592Sbill } /*end of the for to pick up all arguments*/ 337592Sbill } 338