1592Sbill /* Copyright (c) 1980 Regents of the University of California */ 2*673Shenry static char sccsid[] = "@(#)ascode.c 4.5 08/20/80"; 3592Sbill #include <stdio.h> 4592Sbill #include "as.h" 5592Sbill #include "assyms.h" 6592Sbill 7*673Shenry /* 8*673Shenry * Loader reference types (plust PCREL) to bytes and lg bytes 9*673Shenry */ 10*673Shenry /* LEN1 LEN1+PC LEN2 LEN2+PC LEN4 LEN4+PC LEN8 LEN8+PC*/ 11*673Shenry int reflen[] = /* {LEN*+PCREL} ==> number of bytes */ 12*673Shenry {0, 0, 1, 1, 2, 2, 4, 4, 8, 8}; 13*673Shenry int lgreflen[] = /* {LEN*+PCREL} ==> lg number of bytes */ 14*673Shenry {-1, -1, 0, 0, 1, 1, 2, 2, 3, 3}; 15*673Shenry 16*673Shenry /* 17*673Shenry * Sizes to Loader reference types and type flags 18*673Shenry */ 19*673Shenry /*0 1 2 3 4 5 6 7 8*/ 20*673Shenry int len124[] = /* {1,2,4,8} ==> {LEN1, LEN2, LEN4, LEN8} */ 21*673Shenry {0, LEN1, LEN2, 0, LEN4, 0, 0, 0, LEN8}; 22*673Shenry char mod124[] = /* {1,2,4,8} ==> {bits to construct operands */ 23*673Shenry {0, 0x00, 0x20, 0, 0x40, 0, 0, 0, 0}; 24*673Shenry int type_124[] = /* {1,2,4,8} ==> {TYPB, TYPW, TYPL, TYPQ} */ 25*673Shenry {0, TYPB, TYPW, 0, TYPL, 0, 0, 0, TYPQ}; 26*673Shenry 27*673Shenry /* 28*673Shenry * type flags to Loader reference and byte lengths 29*673Shenry */ 30*673Shenry /*TYPB TYPW TYPL TYPQ TYPF TYPD*/ 31*673Shenry int ty_NORELOC[] = /* {TYPB..TYPD} ==> {1 if relocation not OK */ 32*673Shenry {0, 0, 0, 1, 1, 1}; 33*673Shenry int ty_LEN[] = /* {TYPB..TYPD} ==> {LEN1..LEN8} */ 34*673Shenry {LEN1, LEN2, LEN4, LEN8, LEN4, LEN8}; 35*673Shenry int ty_nbyte[] = /* {TYPB..TYPD} ==> {1,2,4,8} */ 36*673Shenry {1, 2, 4, 8, 4, 8}; 37*673Shenry int ty_nlg[] = /* {TYPB..TYPD} ==> lg{1,2,4,8} */ 38*673Shenry {0, 1, 2, 3, 2, 3}; 39*673Shenry 40592Sbill insout(op, ap, nact) 41592Sbill struct arg *ap; 42592Sbill { 43667Shenry int jxxflg; 44667Shenry register struct instab *ip; /* the instruction */ 45667Shenry register struct arg *ap_walk; /* actual param walk */ 46667Shenry register int i; 47667Shenry register int ap_type; /* actual param type */ 48667Shenry register int ap_type_mask; /* masked actual param */ 49592Sbill op &= 0xFF; 50592Sbill jxxflg = nact; 51592Sbill if (nact < 0) 52592Sbill nact = -nact; 53592Sbill if (passno == 1) { 54667Shenry ip = itab[op]; 55667Shenry if (nact < ip->i_nargs) 56667Shenry yyerror("Too few arguments"); 57667Shenry if (nact > ip->i_nargs) { 58667Shenry yyerror("Too many arguments"); 59667Shenry nact = ip->i_nargs; 60667Shenry } 61667Shenry /* 62667Shenry * Check argument compatability with instruction template 63667Shenry */ 64667Shenry for (ap_walk = ap, i = 1; i <= nact; ap_walk++, i++){ 65*673Shenry ap_type = ap_walk->a_atype; 66667Shenry ap_type_mask = ap_type & AMASK; 67*673Shenry switch( (fetcharg(ip, i-1)) & ACCESSMASK){ /* type of fp */ 68667Shenry case ACCB: 69667Shenry if ( !((ap_type_mask == AEXP) || (ap_type_mask == AIMM)) ){ 70667Shenry yyerror("arg %d, branch displacement must be an expression",i); 71667Shenry return; 72667Shenry } 73667Shenry break; 74667Shenry case ACCA: 75667Shenry switch(ap_type_mask){ 76667Shenry case AREG: yyerror("arg %d, addressing a register",i); 77667Shenry return; 78667Shenry case AIMM: if ( !(ap_type & ASTAR) ){ 79667Shenry yyerror("arg %d, addressing an immediate operand",i); 80667Shenry return; 81667Shenry } 82667Shenry } 83667Shenry break; 84667Shenry case ACCM: 85667Shenry case ACCW: 86667Shenry switch(ap_type_mask){ 87667Shenry case AIMM: if (!(ap_type&ASTAR)) { 88667Shenry yyerror("arg %d, modifying a constant",i); 89667Shenry return; 90667Shenry } 91667Shenry } 92667Shenry break; 93667Shenry } /* end of the switch on fp_type */ 94667Shenry if (ap_type & AINDX) { 95667Shenry if (ap_walk->a_areg2==0xF) { 96667Shenry yyerror("arg %d, PC used as index",i); 97667Shenry return; 98667Shenry } 99667Shenry switch(ap_type_mask){ 100667Shenry case AREG: yyerror("arg %d, indexing the register file",i); 101667Shenry return; 102667Shenry case AIMM: yyerror("arg %d, indexing a constant",i); 103667Shenry return; 104*673Shenry case ADECR: 105*673Shenry case AINCR: if (ap_walk->a_areg1==ap_walk->a_areg2) { 106667Shenry yyerror("arg %d, indexing with modified register",i); 107667Shenry return; 108667Shenry } 109667Shenry break; 110667Shenry } /* end of switch on ap_type_mask */ 111667Shenry } /* end of AINDX */ 112667Shenry } 113667Shenry } /* both passes here */ 114592Sbill if (jxxflg < 0) 115592Sbill ijxout(op, ap, nact); 116592Sbill else putins(op, ap, nact); 117592Sbill } 118592Sbill 119592Sbill extern int d124; 120592Sbill 121592Sbill putins(op, ap, n) 122592Sbill /* 123592Sbill * n had better be positive 124592Sbill */ 125592Sbill register struct arg *ap; 126592Sbill { 127592Sbill register struct exp *xp; 128592Sbill register int a; 129*673Shenry int i; 130*673Shenry int reloc_how; 131592Sbill 132592Sbill #ifdef DEBUG 133592Sbill fflush(stdout); 134592Sbill #endif 135592Sbill if (passno == 2) 136592Sbill goto PASS2; 137592Sbill 138629Shenry dotp->e_xvalue += n+1; /* 1 for the opcode, at least 1 per arg */ 139629Shenry for (i=0; i<n; i++,ap++) { /* some args take more than 1 byte */ 140629Shenry a = ap->a_atype; 141592Sbill if (a & AINDX) 142629Shenry dotp->e_xvalue++; 143592Sbill switch (a&~(AINDX|ASTAR)) { 144592Sbill case AEXP: 145629Shenry a = fetcharg(itab[op], i); 146592Sbill if (a == ACCB+TYPB) 147592Sbill break; 148592Sbill if (a==ACCB+TYPW){ 149629Shenry dotp->e_xvalue++; 150592Sbill break; 151592Sbill } 152592Sbill /* 153592Sbill * Reduces to PC relative 154592Sbill */ 155629Shenry dotp->e_xvalue += ap->a_dispsize; 156592Sbill break; 157592Sbill 158592Sbill case ADISP: 159629Shenry xp=ap->a_xp; 160629Shenry if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){ 161629Shenry dotp->e_xvalue += ap->a_dispsize; 162592Sbill break; 163592Sbill } 164629Shenry if (xp->e_xvalue==0 && !(a&ASTAR)) 165592Sbill break; 166629Shenry dotp->e_xvalue++; 167629Shenry if ((xp->e_xvalue<MINBYTE) || (xp->e_xvalue>MAXBYTE)) 168629Shenry dotp->e_xvalue++; 169629Shenry if ((xp->e_xvalue<MINWORD) || (xp->e_xvalue>MAXWORD)) 170629Shenry dotp->e_xvalue += 2; 171592Sbill break; 172592Sbill 173592Sbill case AIMM: 174629Shenry if (ap->a_atype&ASTAR) a=TYPL; 175592Sbill else { 176629Shenry a = fetcharg(itab[op], i); 177592Sbill if (a&ACCA) 178592Sbill a = TYPL; 179592Sbill else 180592Sbill a &= TYPMASK; 181629Shenry xp = ap->a_xp; 182629Shenry if ( ((xp->e_xtype&XTYPE)==XABS) 183629Shenry && (!(xp->e_xtype&XFORW)) 184629Shenry && (xp->e_xvalue>=0) 185629Shenry && (xp->e_xvalue<=63) 186629Shenry && (xp->e_yvalue == 0) 187592Sbill && (a != TYPD) 188592Sbill && (a != TYPF) 189592Sbill ) 190592Sbill break; 191592Sbill } 192592Sbill switch (a) { 193592Sbill case TYPD: 194592Sbill case TYPF: 195629Shenry if ( !(((xp->e_xtype&XTYPE)==XABS) 196629Shenry && (!(xp->e_xtype&XFORW)) 197592Sbill && (slitflt(xp))) 198592Sbill ){ 199592Sbill /* it is NOT short */ 200629Shenry dotp->e_xvalue += ((a==TYPF)? 201592Sbill 4 : 8); 202592Sbill } 203592Sbill break; 204592Sbill case TYPQ: 205629Shenry dotp->e_xvalue += 8;break; 206592Sbill case TYPL: 207629Shenry dotp->e_xvalue += 4;break; 208592Sbill case TYPW: 209629Shenry dotp->e_xvalue += 2;break; 210592Sbill case TYPB: 211629Shenry dotp->e_xvalue += 1;break; 212592Sbill } /*end of the switch on a*/ 213592Sbill } /*end of the switch on the type*/ 214592Sbill } /*end of looping for all arguments*/ 215592Sbill return; 216592Sbill 217592Sbill PASS2: 218592Sbill 219592Sbill #ifdef UNIX 220592Sbill outb(op); /* the opcode */ 221592Sbill #endif UNIX 222592Sbill #ifdef VMS 223592Sbill *vms_obj_ptr++ = -1; *vms_obj_ptr++ = (char)op; 224629Shenry dotp->e_xvalue += 1; 225592Sbill #endif VMS 226592Sbill 227592Sbill for (i=0; i<n; i++,ap++) {/* now for the arguments */ 228629Shenry a=ap->a_atype; 229629Shenry xp=ap->a_xp; 230*673Shenry reloc_how = TYPNONE; 231592Sbill if (a&AINDX) { 232592Sbill #ifdef UNIX 233629Shenry { outb(0x40 | ap->a_areg2); } 234592Sbill #endif UNIX 235592Sbill #ifdef VMS 236592Sbill { *vms_obj_ptr++ = -1; 237629Shenry *vms_obj_ptr++ = (0x40 | ap->a_areg2); 238629Shenry dotp->e_xvalue += 1; } 239592Sbill #endif VMS 240592Sbill a &= ~AINDX; 241592Sbill } 242592Sbill if (a&ASTAR) { 243629Shenry ap->a_areg1 |= 0x10; 244592Sbill a &= ~ASTAR; 245592Sbill } 246592Sbill switch (a) { 247592Sbill case AREG: /* %r */ 248629Shenry ap->a_areg1 |= 0x50; 249592Sbill break; 250592Sbill case ABASE: /* (%r) */ 251629Shenry ap->a_areg1 |= 0x60; 252592Sbill break; 253592Sbill case ADECR: /* -(%r) */ 254629Shenry ap->a_areg1 |= 0x70; 255592Sbill break; 256665Shenry case AINCR: /* (%r)+ */ 257629Shenry ap->a_areg1 |= 0x80; 258592Sbill break; 259592Sbill case AEXP: /* expr */ 260629Shenry a = fetcharg(itab[op], i); 261592Sbill if (a == ACCB+TYPB) { 262629Shenry ap->a_areg1 = a = 263629Shenry xp->e_xvalue - (dotp->e_xvalue + 1); 264592Sbill if (a<MINBYTE || a>MAXBYTE) 265592Sbill yyerror("Branch too far"); break; 266592Sbill } 267592Sbill if (a == ACCB+TYPW) { 268629Shenry ap->a_areg1 = a = xp->e_xvalue 269629Shenry -= dotp->e_xvalue + 2; 270629Shenry xp->e_xtype = XABS; 271592Sbill if (a<MINWORD || a>MAXWORD) 272592Sbill yyerror("Branch too far"); 273629Shenry xp->e_xvalue = a>>8; 274*673Shenry reloc_how = TYPB; 275592Sbill break; 276592Sbill } 277592Sbill /* reduces to expr(pc) mode */ 278629Shenry ap->a_areg1 |= (0xAF + mod124[ap->a_dispsize]); 279*673Shenry reloc_how = type_124[ap->a_dispsize] + RELOC_PCREL; 280592Sbill break; 281592Sbill 282592Sbill case ADISP: /* expr(%r) */ 283629Shenry ap->a_areg1 |= 0xA0; 284629Shenry if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){ 285629Shenry ap->a_areg1 += mod124[ap->a_dispsize]; 286*673Shenry reloc_how = type_124[ap->a_dispsize]; 287592Sbill break; 288592Sbill } 289629Shenry if (xp->e_xvalue==0 && !(ap->a_areg1&0x10)) { 290629Shenry ap->a_areg1 ^= 0xC0; 291592Sbill break; 292592Sbill } 293*673Shenry reloc_how = TYPB; 294629Shenry if ((xp->e_xvalue<MINBYTE) || (xp->e_xvalue>MAXBYTE)){ 295629Shenry ap->a_areg1 += 0x20; 296*673Shenry reloc_how = TYPW; 297592Sbill } 298629Shenry if ((xp->e_xvalue<MINWORD) || (xp->e_xvalue>MAXWORD)){ 299629Shenry ap->a_areg1 += 0x20; 300*673Shenry reloc_how = TYPL; 301592Sbill } 302592Sbill break; 303592Sbill 304592Sbill case AIMM: /* $expr */ 305629Shenry if (ap->a_atype&ASTAR) 306592Sbill a=TYPL; 307592Sbill else { 308629Shenry a = fetcharg(itab[op], i); 309592Sbill if (a&ACCA) 310592Sbill a=TYPL; 311592Sbill else 312592Sbill a &= TYPMASK; 313629Shenry if ( ( (xp->e_xtype&XTYPE) == XABS) 314629Shenry && !(xp->e_xtype&XFORW) 315629Shenry && (xp->e_xvalue >= 0) 316629Shenry && (xp->e_xvalue <= 63) 317629Shenry && (xp->e_yvalue == 0) 318592Sbill && (a != TYPF) 319592Sbill && (a != TYPD) ) { 320629Shenry ap->a_areg1 = xp->e_xvalue; 321592Sbill break; 322592Sbill } 323592Sbill } 324629Shenry ap->a_areg1 |= 0x8F; 325*673Shenry reloc_how = a; 326*673Shenry if (reloc_how == TYPD || reloc_how == TYPF){ 327629Shenry if ( ((xp->e_xtype&XTYPE)==XABS) 328629Shenry && (!(xp->e_xtype&XFORW)) 329592Sbill && (slitflt(xp)) 330592Sbill ){ 331*673Shenry reloc_how = TYPNONE; 332629Shenry ap->a_areg1=extlitflt(xp); 333592Sbill } 334592Sbill } 335592Sbill break; 336592Sbill 337592Sbill } /*end of the switch on a*/ 338592Sbill /* 339592Sbill * use the first byte to describe the argument 340592Sbill */ 341592Sbill #ifdef UNIX 342629Shenry outb(ap->a_areg1); 343592Sbill #endif UNIX 344592Sbill #ifdef VMS 345629Shenry *vms_obj_ptr++ = -1; *vms_obj_ptr++ = (char)(ap->a_areg1); 346629Shenry dotp->e_xvalue += 1; 347592Sbill if ((vms_obj_ptr-sobuf) > 400) { 348592Sbill write(objfil,sobuf,vms_obj_ptr-sobuf); 349592Sbill vms_obj_ptr=sobuf+1; 350592Sbill } 351592Sbill #endif VMS 352*673Shenry if (reloc_how != TYPNONE) 353*673Shenry outrel(xp, reloc_how); 354592Sbill } /*end of the for to pick up all arguments*/ 355592Sbill } 356