1592Sbill /* Copyright (c) 1980 Regents of the University of California */ 2*853Shenry static char sccsid[] = "@(#)ascode.c 4.6 09/08/80"; 3592Sbill #include <stdio.h> 4592Sbill #include "as.h" 5592Sbill #include "assyms.h" 6592Sbill 7673Shenry /* 8673Shenry * Loader reference types (plust PCREL) to bytes and lg bytes 9673Shenry */ 10673Shenry /* LEN1 LEN1+PC LEN2 LEN2+PC LEN4 LEN4+PC LEN8 LEN8+PC*/ 11673Shenry int reflen[] = /* {LEN*+PCREL} ==> number of bytes */ 12673Shenry {0, 0, 1, 1, 2, 2, 4, 4, 8, 8}; 13673Shenry int lgreflen[] = /* {LEN*+PCREL} ==> lg number of bytes */ 14673Shenry {-1, -1, 0, 0, 1, 1, 2, 2, 3, 3}; 15673Shenry 16673Shenry /* 17673Shenry * Sizes to Loader reference types and type flags 18673Shenry */ 19673Shenry /*0 1 2 3 4 5 6 7 8*/ 20673Shenry int len124[] = /* {1,2,4,8} ==> {LEN1, LEN2, LEN4, LEN8} */ 21673Shenry {0, LEN1, LEN2, 0, LEN4, 0, 0, 0, LEN8}; 22673Shenry char mod124[] = /* {1,2,4,8} ==> {bits to construct operands */ 23673Shenry {0, 0x00, 0x20, 0, 0x40, 0, 0, 0, 0}; 24673Shenry int type_124[] = /* {1,2,4,8} ==> {TYPB, TYPW, TYPL, TYPQ} */ 25673Shenry {0, TYPB, TYPW, 0, TYPL, 0, 0, 0, TYPQ}; 26673Shenry 27673Shenry /* 28673Shenry * type flags to Loader reference and byte lengths 29673Shenry */ 30673Shenry /*TYPB TYPW TYPL TYPQ TYPF TYPD*/ 31673Shenry int ty_NORELOC[] = /* {TYPB..TYPD} ==> {1 if relocation not OK */ 32673Shenry {0, 0, 0, 1, 1, 1}; 33673Shenry int ty_LEN[] = /* {TYPB..TYPD} ==> {LEN1..LEN8} */ 34673Shenry {LEN1, LEN2, LEN4, LEN8, LEN4, LEN8}; 35673Shenry int ty_nbyte[] = /* {TYPB..TYPD} ==> {1,2,4,8} */ 36673Shenry {1, 2, 4, 8, 4, 8}; 37673Shenry int ty_nlg[] = /* {TYPB..TYPD} ==> lg{1,2,4,8} */ 38673Shenry {0, 1, 2, 3, 2, 3}; 39673Shenry 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++){ 65673Shenry ap_type = ap_walk->a_atype; 66667Shenry ap_type_mask = ap_type & AMASK; 67673Shenry 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; 104673Shenry case ADECR: 105673Shenry 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; 128*853Shenry register int argtype; 129673Shenry int i; 130673Shenry 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 */ 140*853Shenry argtype = ap->a_atype; 141*853Shenry if (argtype & AINDX) 142629Shenry dotp->e_xvalue++; 143*853Shenry switch (argtype&~(AINDX|ASTAR)) { 144592Sbill case AEXP: 145*853Shenry argtype = fetcharg(itab[op], i); 146*853Shenry if (argtype == ACCB+TYPB) 147592Sbill break; 148*853Shenry if (argtype==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 } 164*853Shenry if (xp->e_xvalue==0 && !(argtype&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: 174*853Shenry if (ap->a_atype&ASTAR) argtype=TYPL; 175592Sbill else { 176*853Shenry argtype = fetcharg(itab[op], i); 177*853Shenry if (argtype&ACCA) 178*853Shenry argtype = TYPL; 179592Sbill else 180*853Shenry argtype &= 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) 187*853Shenry && (argtype != TYPD) 188*853Shenry && (argtype != TYPF) 189592Sbill ) 190592Sbill break; 191592Sbill } 192*853Shenry switch (argtype) { 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 */ 200*853Shenry dotp->e_xvalue += ((argtype==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; 212*853Shenry } /*end of the switch on argtype*/ 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 */ 228*853Shenry argtype=ap->a_atype; 229629Shenry xp=ap->a_xp; 230673Shenry reloc_how = TYPNONE; 231*853Shenry if (argtype&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 240*853Shenry argtype &= ~AINDX; 241592Sbill } 242*853Shenry if (argtype&ASTAR) { 243629Shenry ap->a_areg1 |= 0x10; 244*853Shenry argtype &= ~ASTAR; 245592Sbill } 246*853Shenry switch (argtype) { 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 */ 260*853Shenry argtype = fetcharg(itab[op], i); 261*853Shenry if (argtype == ACCB+TYPB) { 262*853Shenry ap->a_areg1 = argtype = 263629Shenry xp->e_xvalue - (dotp->e_xvalue + 1); 264*853Shenry if (argtype<MINBYTE || argtype>MAXBYTE) 265592Sbill yyerror("Branch too far"); break; 266592Sbill } 267*853Shenry if (argtype == ACCB+TYPW) { 268*853Shenry ap->a_areg1 = argtype = xp->e_xvalue 269629Shenry -= dotp->e_xvalue + 2; 270629Shenry xp->e_xtype = XABS; 271*853Shenry if (argtype<MINWORD || argtype>MAXWORD) 272592Sbill yyerror("Branch too far"); 273*853Shenry xp->e_xvalue = argtype>>8; 274673Shenry reloc_how = TYPB; 275592Sbill break; 276592Sbill } 277592Sbill /* reduces to expr(pc) mode */ 278629Shenry ap->a_areg1 |= (0xAF + mod124[ap->a_dispsize]); 279673Shenry 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]; 286673Shenry 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 } 293673Shenry reloc_how = TYPB; 294629Shenry if ((xp->e_xvalue<MINBYTE) || (xp->e_xvalue>MAXBYTE)){ 295629Shenry ap->a_areg1 += 0x20; 296673Shenry reloc_how = TYPW; 297592Sbill } 298629Shenry if ((xp->e_xvalue<MINWORD) || (xp->e_xvalue>MAXWORD)){ 299629Shenry ap->a_areg1 += 0x20; 300673Shenry reloc_how = TYPL; 301592Sbill } 302592Sbill break; 303592Sbill 304592Sbill case AIMM: /* $expr */ 305629Shenry if (ap->a_atype&ASTAR) 306*853Shenry argtype=TYPL; 307592Sbill else { 308*853Shenry argtype = fetcharg(itab[op], i); 309*853Shenry if (argtype&ACCA) 310*853Shenry argtype=TYPL; 311592Sbill else 312*853Shenry argtype &= 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) 318*853Shenry && (argtype != TYPF) 319*853Shenry && (argtype != TYPD) ) { 320629Shenry ap->a_areg1 = xp->e_xvalue; 321592Sbill break; 322592Sbill } 323592Sbill } 324629Shenry ap->a_areg1 |= 0x8F; 325*853Shenry reloc_how = argtype; 326673Shenry if (reloc_how == TYPD || reloc_how == TYPF){ 327629Shenry if ( ((xp->e_xtype&XTYPE)==XABS) 328629Shenry && (!(xp->e_xtype&XFORW)) 329592Sbill && (slitflt(xp)) 330592Sbill ){ 331673Shenry reloc_how = TYPNONE; 332629Shenry ap->a_areg1=extlitflt(xp); 333592Sbill } 334592Sbill } 335592Sbill break; 336592Sbill 337*853Shenry } /*end of the switch on argtype*/ 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 352673Shenry if (reloc_how != TYPNONE) 353673Shenry outrel(xp, reloc_how); 354592Sbill } /*end of the for to pick up all arguments*/ 355592Sbill } 356