X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/593d71c1507d8a737b72d44762922bfa0b9590a0..10973e2e500f094b19046c71a5083ccac39fec28:/usr/src/old/as.vax/ascode.c diff --git a/usr/src/old/as.vax/ascode.c b/usr/src/old/as.vax/ascode.c index f47949c164..e9de76bd7e 100644 --- a/usr/src/old/as.vax/ascode.c +++ b/usr/src/old/as.vax/ascode.c @@ -1,91 +1,132 @@ /* Copyright (c) 1980 Regents of the University of California */ -static char sccsid[] = "@(#)ascode.c 4.3 %G%"; +static char sccsid[] = "@(#)ascode.c 4.7 %G%"; #include #include "as.h" #include "assyms.h" +/* + * Loader reference types (plust PCREL) to bytes and lg bytes + */ +/* LEN1 LEN1+PC LEN2 LEN2+PC LEN4 LEN4+PC LEN8 LEN8+PC*/ +int reflen[] = /* {LEN*+PCREL} ==> number of bytes */ +{0, 0, 1, 1, 2, 2, 4, 4, 8, 8}; +int lgreflen[] = /* {LEN*+PCREL} ==> lg number of bytes */ +{-1, -1, 0, 0, 1, 1, 2, 2, 3, 3}; + +/* + * Sizes to Loader reference types and type flags + */ +/*0 1 2 3 4 5 6 7 8*/ +int len124[] = /* {1,2,4,8} ==> {LEN1, LEN2, LEN4, LEN8} */ +{0, LEN1, LEN2, 0, LEN4, 0, 0, 0, LEN8}; +char mod124[] = /* {1,2,4,8} ==> {bits to construct operands */ +{0, 0x00, 0x20, 0, 0x40, 0, 0, 0, 0}; +int type_124[] = /* {1,2,4,8} ==> {TYPB, TYPW, TYPL, TYPQ} */ +{0, TYPB, TYPW, 0, TYPL, 0, 0, 0, TYPQ}; + +/* + * type flags to Loader reference and byte lengths + */ +/*TYPB TYPW TYPL TYPQ TYPF TYPD*/ +int ty_NORELOC[] = /* {TYPB..TYPD} ==> {1 if relocation not OK */ +{0, 0, 0, 1, 1, 1}; +int ty_LEN[] = /* {TYPB..TYPD} ==> {LEN1..LEN8} */ +{LEN1, LEN2, LEN4, LEN8, LEN4, LEN8}; +int ty_nbyte[] = /* {TYPB..TYPD} ==> {1,2,4,8} */ +{1, 2, 4, 8, 4, 8}; +int ty_nlg[] = /* {TYPB..TYPD} ==> lg{1,2,4,8} */ +{0, 1, 2, 3, 2, 3}; + insout(op, ap, nact) struct arg *ap; { - int jxxflg; - + int jxxflg; + register struct instab *ip; /* the instruction */ + register struct arg *ap_walk; /* actual param walk */ + register int i; + register int ap_type; /* actual param type */ + register int ap_type_mask; /* masked actual param */ op &= 0xFF; jxxflg = nact; if (nact < 0) nact = -nact; if (passno == 1) { - register struct arg *ap2; - register struct instab *ip; - int i,nexp; - ip = itab[op]; - nexp = ip->i_nargs; - if (nact < nexp) - yyerror("Too few arguments"); - if (nact > nexp) { - yyerror("Too many arguments"); - nact = nexp; - } + ip = itab[op]; + if (nact < ip->i_nargs) + yyerror("Too few arguments"); + if (nact > ip->i_nargs) { + yyerror("Too many arguments"); + nact = ip->i_nargs; + } + /* + * Check argument compatability with instruction template + */ + for (ap_walk = ap, i = 1; i <= nact; ap_walk++, i++){ + ap_type = ap_walk->a_atype; + ap_type_mask = ap_type & AMASK; /* - * Check argument compatability with instruction template + * The switch value is >> by 3 so that the switch + * code is dense, not implemented as a sequence + * of branches but implemented as a casel. + * In addition, cases ACCI and ACCR are added to force + * dense switch code. */ - for (ap2 = ap+nact, i = nact; --i >= 0;) - argcompat(--ap2, fetcharg(ip, i), i+1); - } + switch( ((fetcharg(ip, i-1)) & ACCESSMASK)>>3){ /* type of fp */ + case ACCI >> 3: + case ACCR >> 3: + break; + case ACCB >> 3: + if ( !((ap_type_mask == AEXP) || (ap_type_mask == AIMM)) ){ + yyerror("arg %d, branch displacement must be an expression",i); + return; + } + break; + case ACCA >> 3: + switch(ap_type_mask){ + case AREG: yyerror("arg %d, addressing a register",i); + return; + case AIMM: if ( !(ap_type & ASTAR) ){ + yyerror("arg %d, addressing an immediate operand",i); + return; + } + } + break; + case ACCM >> 3: + case ACCW >> 3: + switch(ap_type_mask){ + case AIMM: if (!(ap_type&ASTAR)) { + yyerror("arg %d, modifying a constant",i); + return; + } + } + break; + } /* end of the switch on fp_type */ + if (ap_type & AINDX) { + if (ap_walk->a_areg2==0xF) { + yyerror("arg %d, PC used as index",i); + return; + } + switch(ap_type_mask){ + case AREG: yyerror("arg %d, indexing the register file",i); + return; + case AIMM: yyerror("arg %d, indexing a constant",i); + return; + case ADECR: + case AINCR: if (ap_walk->a_areg1==ap_walk->a_areg2) { + yyerror("arg %d, indexing with modified register",i); + return; + } + break; + } /* end of switch on ap_type_mask */ + } /* end of AINDX */ + } + } /* both passes here */ if (jxxflg < 0) ijxout(op, ap, nact); else putins(op, ap, nact); } -argcompat(act, exp, i) - struct arg *act; - int exp,i; -{ - register at,atm; - - at = act->a_atype; - atm = at & AMASK; - - if ( (exp & ACCB) && (!((atm == AEXP) || (atm == AIMM))) ){ - yyerror("arg %d, branch displacement must be an expression",i); - return; - } - if (exp & ACCA){ - if (atm == AREG) { - yyerror("arg %d, addressing a register",i); - return; - } - if ( (atm == AIMM) && !(at & ASTAR) ){ - yyerror("arg %d, addressing an immediate operand",i); - return; - } - } - if ((exp&ACCW) && (atm==AIMM) && !(at&ASTAR)) { - yyerror("arg %d, modifying a constant",i); - return; - } - if (at & AINDX) { - if (act->a_areg2==017) { - yyerror("arg %d, PC used as index",i); - return; - } - if (atm==AREG) { - yyerror("arg %d, indexing the register file",i); - return; - } - if (atm==AIMM) { - yyerror("arg %d, indexing a constant",i); - return; - } - if (((atm==ADECR) || (atm==AINCR)) && (act->a_areg1==act->a_areg2)) { - yyerror("arg %d, indexing with modified register",i); - return; - } - } -} - extern int d124; - int len124[] = {0,LEN1,LEN2,0,LEN4}; - char mod124[] = {0,0x00,0x20,0,0x40}; putins(op, ap, n) /* @@ -94,8 +135,9 @@ putins(op, ap, n) register struct arg *ap; { register struct exp *xp; - register int a; - int i,xtrab; + register int argtype; + int i; + int reloc_how; #ifdef DEBUG fflush(stdout); @@ -105,15 +147,25 @@ putins(op, ap, n) dotp->e_xvalue += n+1; /* 1 for the opcode, at least 1 per arg */ for (i=0; ia_atype; - if (a & AINDX) + argtype = ap->a_atype; + if (argtype & AINDX) dotp->e_xvalue++; - switch (a&~(AINDX|ASTAR)) { + /* + * This switch has been fixed by enumerating the no action + * alternatives (those that have 1 one byte of code) + * so that a casel instruction is emitted. + */ + switch (argtype&~(AINDX|ASTAR)) { + case AREG: + case ABASE: + case ADECR: + case AINCR: + break; case AEXP: - a = fetcharg(itab[op], i); - if (a == ACCB+TYPB) + argtype = fetcharg(itab[op], i); + if (argtype == ACCB+TYPB) break; - if (a==ACCB+TYPW){ + if (argtype==ACCB+TYPW){ dotp->e_xvalue++; break; } @@ -129,7 +181,7 @@ putins(op, ap, n) dotp->e_xvalue += ap->a_dispsize; break; } - if (xp->e_xvalue==0 && !(a&ASTAR)) + if (xp->e_xvalue==0 && !(argtype&ASTAR)) break; dotp->e_xvalue++; if ((xp->e_xvaluee_xvalue>MAXBYTE)) @@ -139,25 +191,25 @@ putins(op, ap, n) break; case AIMM: - if (ap->a_atype&ASTAR) a=TYPL; + if (ap->a_atype&ASTAR) argtype=TYPL; else { - a = fetcharg(itab[op], i); - if (a&ACCA) - a = TYPL; + argtype = fetcharg(itab[op], i); + if (argtype&ACCA) + argtype = TYPL; else - a &= TYPMASK; + argtype &= TYPMASK; xp = ap->a_xp; if ( ((xp->e_xtype&XTYPE)==XABS) && (!(xp->e_xtype&XFORW)) && (xp->e_xvalue>=0) && (xp->e_xvalue<=63) && (xp->e_yvalue == 0) - && (a != TYPD) - && (a != TYPF) + && (argtype != TYPD) + && (argtype != TYPF) ) break; } - switch (a) { + switch (argtype) { case TYPD: case TYPF: if ( !(((xp->e_xtype&XTYPE)==XABS) @@ -165,7 +217,7 @@ putins(op, ap, n) && (slitflt(xp))) ){ /* it is NOT short */ - dotp->e_xvalue += ((a==TYPF)? + dotp->e_xvalue += ((argtype==TYPF)? 4 : 8); } break; @@ -177,7 +229,7 @@ putins(op, ap, n) dotp->e_xvalue += 2;break; case TYPB: dotp->e_xvalue += 1;break; - } /*end of the switch on a*/ + } /*end of the switch on argtype*/ } /*end of the switch on the type*/ } /*end of looping for all arguments*/ return; @@ -193,10 +245,10 @@ PASS2: #endif VMS for (i=0; ia_atype; + argtype=ap->a_atype; xp=ap->a_xp; - xtrab=0; - if (a&AINDX) { + reloc_how = TYPNONE; + if (argtype&AINDX) { #ifdef UNIX { outb(0x40 | ap->a_areg2); } #endif UNIX @@ -205,13 +257,13 @@ PASS2: *vms_obj_ptr++ = (0x40 | ap->a_areg2); dotp->e_xvalue += 1; } #endif VMS - a &= ~AINDX; + argtype &= ~AINDX; } - if (a&ASTAR) { + if (argtype&ASTAR) { ap->a_areg1 |= 0x10; - a &= ~ASTAR; + argtype &= ~ASTAR; } - switch (a) { + switch (argtype) { case AREG: /* %r */ ap->a_areg1 |= 0x50; break; @@ -225,91 +277,84 @@ PASS2: ap->a_areg1 |= 0x80; break; case AEXP: /* expr */ - a = fetcharg(itab[op], i); - if (a == ACCB+TYPB) { - ap->a_areg1 = a = + argtype = fetcharg(itab[op], i); + if (argtype == ACCB+TYPB) { + ap->a_areg1 = argtype = xp->e_xvalue - (dotp->e_xvalue + 1); - if (aMAXBYTE) + if (argtypeMAXBYTE) yyerror("Branch too far"); break; } - if (a == ACCB+TYPW) { - ap->a_areg1 = a = xp->e_xvalue + if (argtype == ACCB+TYPW) { + ap->a_areg1 = argtype = xp->e_xvalue -= dotp->e_xvalue + 2; xp->e_xtype = XABS; - if (aMAXWORD) + if (argtypeMAXWORD) yyerror("Branch too far"); - xp->e_xvalue = a>>8; - xtrab = LEN1; + xp->e_xvalue = argtype>>8; + reloc_how = TYPB; break; } /* reduces to expr(pc) mode */ ap->a_areg1 |= (0xAF + mod124[ap->a_dispsize]); - xtrab = len124[ap->a_dispsize]+PCREL; + reloc_how = type_124[ap->a_dispsize] + RELOC_PCREL; break; case ADISP: /* expr(%r) */ ap->a_areg1 |= 0xA0; if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){ ap->a_areg1 += mod124[ap->a_dispsize]; - xtrab=len124[ap->a_dispsize]; + reloc_how = type_124[ap->a_dispsize]; break; } if (xp->e_xvalue==0 && !(ap->a_areg1&0x10)) { ap->a_areg1 ^= 0xC0; break; } - xtrab=LEN1; + reloc_how = TYPB; if ((xp->e_xvaluee_xvalue>MAXBYTE)){ ap->a_areg1 += 0x20; - xtrab=LEN2; + reloc_how = TYPW; } if ((xp->e_xvaluee_xvalue>MAXWORD)){ ap->a_areg1 += 0x20; - xtrab=LEN4; + reloc_how = TYPL; } break; case AIMM: /* $expr */ if (ap->a_atype&ASTAR) - a=TYPL; + argtype=TYPL; else { - a = fetcharg(itab[op], i); - if (a&ACCA) - a=TYPL; + argtype = fetcharg(itab[op], i); + if (argtype&ACCA) + argtype=TYPL; else - a &= TYPMASK; + argtype &= TYPMASK; if ( ( (xp->e_xtype&XTYPE) == XABS) && !(xp->e_xtype&XFORW) && (xp->e_xvalue >= 0) && (xp->e_xvalue <= 63) && (xp->e_yvalue == 0) - && (a != TYPF) - && (a != TYPD) ) { + && (argtype != TYPF) + && (argtype != TYPD) ) { ap->a_areg1 = xp->e_xvalue; break; } } ap->a_areg1 |= 0x8F; - switch (a) { - case TYPD: - case TYPF: + reloc_how = argtype; + if (reloc_how == TYPD || reloc_how == TYPF){ if ( ((xp->e_xtype&XTYPE)==XABS) && (!(xp->e_xtype&XFORW)) && (slitflt(xp)) ){ + reloc_how = TYPNONE; ap->a_areg1=extlitflt(xp); - } else { - xtrab = (a==TYPF) ? LEN4: LEN8; } - break; - case TYPQ: xtrab = LEN8; break; - case TYPL: xtrab = LEN4; break; - case TYPW: xtrab = LEN2; break; - case TYPB: xtrab = LEN1; break; } break; - } /*end of the switch on a*/ + } /*end of the switch on argtype*/ /* * use the first byte to describe the argument */ @@ -324,14 +369,7 @@ PASS2: vms_obj_ptr=sobuf+1; } #endif VMS - if (xtrab) - /* - * Floating point numbers are written to a.out - * by outrel; they require that the least significant - * 4 bytes of an 8 byte double precision number - * immediately follow the field xvalue, which - * they do. - */ - outrel(&xp->e_xvalue, xtrab, xp->e_xtype, xp->e_xname); + if (reloc_how != TYPNONE) + outrel(xp, reloc_how); } /*end of the for to pick up all arguments*/ }