X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/2b84abb596f52ab2068d52108adc96838ad4340a..31cef89cb428866f787983e68246030321893df4:/usr/src/cmd/as/ascode.c diff --git a/usr/src/cmd/as/ascode.c b/usr/src/cmd/as/ascode.c index cd33244278..1cf20f596e 100644 --- a/usr/src/cmd/as/ascode.c +++ b/usr/src/cmd/as/ascode.c @@ -1,80 +1,132 @@ -/* Copyright (c) 1979 Regents of the University of California */ +/* Copyright (c) 1980 Regents of the University of California */ +static char sccsid[] = "@(#)ascode.c 4.7 11/5/80"; #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!=2) { - register struct arg *ap2; - register struct instab *ip; - int i,nexp; - ip = itab[op]; - nexp = ip->nargs; - if (nact < nexp) - yyerror("Too few arguments"); - if (nact > nexp) { - yyerror("Too many arguments"); - nact = nexp; - } + if (passno == 1) { + 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, ip->argtype[i], i); - } + 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->atype; - atm = at & AMASK; - - if ((exp & ACCA) && (atm == AREG)) { - yyerror("arg %d, addressing a register",i); - return; - } - if ((exp&ACCW) && (atm==AIMM) && !(at&ASTAR)) { - yyerror("arg %d, modifying a constant",i); - return; - } - if (at & AINDX) { - if (act->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->areg1==act->areg2)) { - yyerror("arg %d, indexing with modified register",i); - return; - } - } -} - -int d124 = {4}; -int len124[] = {0,LEN1,LEN2,0,LEN4}; -char mod124[] = {0,0x00,0x20,0,0x40}; +extern int d124; putins(op, ap, n) /* @@ -83,192 +135,241 @@ 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; - if (passno!=2) { - dotp->xvalue += n+1; /* 1 for the opcode, at least 1 per arg */ - for (i=0; iatype; - if (a & AINDX) - dotp->xvalue++; - switch (a&~(AINDX|ASTAR)) { - case AEXP: { - a = itab[op]->argtype[i]; - if (a == ACCB+TYPB) - break; - if (a==ACCB+TYPW){ - dotp->xvalue++; - break; - } - dotp->xvalue += ap->dispsize; - break; - } - case ADISP: { - xp=ap->xp; - if ((xp->xtype&XTYPE)!=XABS || xp->xtype&XFORW){ - dotp->xvalue += ap->dispsize; - break; - } - if (xp->xvalue==0 && !(a&ASTAR)) +#ifdef DEBUG + fflush(stdout); +#endif + if (passno == 2) + goto PASS2; + + dotp->e_xvalue += n+1; /* 1 for the opcode, at least 1 per arg */ + for (i=0; ia_atype; + if (argtype & AINDX) + dotp->e_xvalue++; + /* + * 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: + argtype = fetcharg(itab[op], i); + if (argtype == ACCB+TYPB) + break; + if (argtype==ACCB+TYPW){ + dotp->e_xvalue++; + break; + } + /* + * Reduces to PC relative + */ + dotp->e_xvalue += ap->a_dispsize; + break; + + case ADISP: + xp=ap->a_xp; + if ((xp->e_xtype&XTYPE)!=XABS || xp->e_xtype&XFORW){ + dotp->e_xvalue += ap->a_dispsize; + break; + } + if (xp->e_xvalue==0 && !(argtype&ASTAR)) + break; + dotp->e_xvalue++; + if ((xp->e_xvaluee_xvalue>MAXBYTE)) + dotp->e_xvalue++; + if ((xp->e_xvaluee_xvalue>MAXWORD)) + dotp->e_xvalue += 2; + break; + + case AIMM: + if (ap->a_atype&ASTAR) argtype=TYPL; + else { + argtype = fetcharg(itab[op], i); + if (argtype&ACCA) + argtype = TYPL; + else + 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) + && (argtype != TYPD) + && (argtype != TYPF) + ) break; - dotp->xvalue++; - if ((xp->xvaluexvalue>MAXBYTE)) - dotp->xvalue++; - if ((xp->xvaluexvalue>MAXWORD)) - dotp->xvalue += 2; - break; + } + switch (argtype) { + case TYPD: + case TYPF: + if ( !(((xp->e_xtype&XTYPE)==XABS) + && (!(xp->e_xtype&XFORW)) + && (slitflt(xp))) + ){ + /* it is NOT short */ + dotp->e_xvalue += ((argtype==TYPF)? + 4 : 8); } - case AIMM: { - if (ap->atype&ASTAR) a=TYPL; - else { - xp = ap->xp; - if ((xp->xtype&XTYPE)==XABS && !(xp->xtype&XFORW) - && xp->xvalue>=0 && xp->xvalue<=63) - break; - a = itab[op]->argtype[i]; - if (a&ACCA) - a = TYPL; - else - a &= TYPMASK; - } - switch (a) { - case TYPD: - case TYPF: - if (slitflt(xp)) - break; - if (a==TYPF) - dotp->xvalue -= 4; - case TYPQ: - dotp->xvalue += 4; - case TYPL: - dotp->xvalue += 2; - case TYPW: - dotp->xvalue++; - case TYPB: - dotp->xvalue++; - } /*end of the switch on a*/ - } /*end of case AIMM*/ - } /*end of the switch on the type*/ - } /*end of looping for all arguments*/ - return; - } /*end of it being time for pass 1*/ - /* - * PASS2 HERE - */ + break; + case TYPQ: + dotp->e_xvalue += 8;break; + case TYPL: + dotp->e_xvalue += 4;break; + case TYPW: + dotp->e_xvalue += 2;break; + case TYPB: + dotp->e_xvalue += 1;break; + } /*end of the switch on argtype*/ + } /*end of the switch on the type*/ + } /*end of looping for all arguments*/ + return; + +PASS2: +#ifdef UNIX outb(op); /* the opcode */ +#endif UNIX +#ifdef VMS + *vms_obj_ptr++ = -1; *vms_obj_ptr++ = (char)op; + dotp->e_xvalue += 1; +#endif VMS + for (i=0; iatype; - xp=ap->xp; - xtrab=0; - if (a&AINDX) { - { outb(0x40 | ap->areg2); } - a &= ~AINDX; + argtype=ap->a_atype; + xp=ap->a_xp; + reloc_how = TYPNONE; + if (argtype&AINDX) { +#ifdef UNIX + { outb(0x40 | ap->a_areg2); } +#endif UNIX +#ifdef VMS + { *vms_obj_ptr++ = -1; + *vms_obj_ptr++ = (0x40 | ap->a_areg2); + dotp->e_xvalue += 1; } +#endif VMS + argtype &= ~AINDX; } - if (a&ASTAR) { - ap->areg1 |= 0x10; - a &= ~ASTAR; + if (argtype&ASTAR) { + ap->a_areg1 |= 0x10; + argtype &= ~ASTAR; } - switch (a) { - case AREG: /* %r */ - ap->areg1 |= 0x50; - break; - case ABASE: /* (%r) */ - ap->areg1 |= 0x60; - break; - case ADECR: /* -(%r) */ - ap->areg1 |= 0x70; - break; - case AINCR: /* (%r) */ - ap->areg1 |= 0x80; + switch (argtype) { + case AREG: /* %r */ + ap->a_areg1 |= 0x50; + break; + case ABASE: /* (%r) */ + ap->a_areg1 |= 0x60; + break; + case ADECR: /* -(%r) */ + ap->a_areg1 |= 0x70; + break; + case AINCR: /* (%r)+ */ + ap->a_areg1 |= 0x80; + break; + case AEXP: /* expr */ + argtype = fetcharg(itab[op], i); + if (argtype == ACCB+TYPB) { + ap->a_areg1 = argtype = + xp->e_xvalue - (dotp->e_xvalue + 1); + if (argtypeMAXBYTE) + yyerror("Branch too far"); break; + } + if (argtype == ACCB+TYPW) { + ap->a_areg1 = argtype = xp->e_xvalue + -= dotp->e_xvalue + 2; + xp->e_xtype = XABS; + if (argtypeMAXWORD) + yyerror("Branch too far"); + xp->e_xvalue = argtype>>8; + reloc_how = TYPB; break; - case AEXP: {/* expr */ - a = itab[op]->argtype[i]; - if (a == ACCB+TYPB) { - ap->areg1 = a = - xp->xvalue - (dotp->xvalue + 1); - if (aMAXBYTE) - yyerror("Branch too far"); break; - } - if (a == ACCB+TYPW) { - ap->areg1 = a = xp->xvalue - -= dotp->xvalue + 2; - xp->xtype = XABS; - if (aMAXWORD) - yyerror("Branch too far"); - xp->xvalue = a>>8; - xtrab = LEN1; - break; - } - /* reduces to expr(pc) mode */ - ap->areg1 |= (0xAF + mod124[ap->dispsize]); - xtrab = len124[ap->dispsize]+PCREL; + } + /* reduces to expr(pc) mode */ + ap->a_areg1 |= (0xAF + mod124[ap->a_dispsize]); + 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]; + reloc_how = type_124[ap->a_dispsize]; break; } - case ADISP: {/* expr(%r) */ - ap->areg1 |= 0xA0; - if ((xp->xtype&XTYPE)!=XABS || xp->xtype&XFORW){ - ap->areg1 += mod124[ap->dispsize]; - xtrab=len124[ap->dispsize]; - break; - } - if (xp->xvalue==0 && !(ap->areg1&0x10)) { - ap->areg1 ^= 0xC0; - break; - } - xtrab=LEN1; - if ((xp->xvaluexvalue>MAXBYTE)){ - ap->areg1 += 0x20; - xtrab=LEN2; - } - if ((xp->xvaluexvalue>MAXWORD)){ - ap->areg1 += 0x20; - xtrab=LEN4; - } + if (xp->e_xvalue==0 && !(ap->a_areg1&0x10)) { + ap->a_areg1 ^= 0xC0; break; } - case AIMM: { /* $expr */ - if (ap->atype&ASTAR) - a=TYPL; - else { - if ( ( (xp->xtype&XTYPE) == XABS) - && !(xp->xtype&XFORW) - && (xp->xvalue >= 0) - && (xp->xvalue <= 63) ) { - ap->areg1 = xp->xvalue; - break; - } - a = itab[op]->argtype[i]; - if (a&ACCA) - a=TYPL; - else - a &= TYPMASK; + reloc_how = TYPB; + if ((xp->e_xvaluee_xvalue>MAXBYTE)){ + ap->a_areg1 += 0x20; + reloc_how = TYPW; + } + if ((xp->e_xvaluee_xvalue>MAXWORD)){ + ap->a_areg1 += 0x20; + reloc_how = TYPL; + } + break; + + case AIMM: /* $expr */ + if (ap->a_atype&ASTAR) + argtype=TYPL; + else { + argtype = fetcharg(itab[op], i); + if (argtype&ACCA) + argtype=TYPL; + else + argtype &= TYPMASK; + if ( ( (xp->e_xtype&XTYPE) == XABS) + && !(xp->e_xtype&XFORW) + && (xp->e_xvalue >= 0) + && (xp->e_xvalue <= 63) + && (xp->e_yvalue == 0) + && (argtype != TYPF) + && (argtype != TYPD) ) { + ap->a_areg1 = xp->e_xvalue; + break; } - ap->areg1 |= 0x8F; - switch (a) { - case TYPD: - case TYPF: - if (slitflt(xp)){ - ap->areg1=extlitflt(xp); - break; - } - if (a==TYPF) { - xtrab = LEN4; - break; - } - case TYPQ: xtrab = LEN8; break; - case TYPL: xtrab = LEN4; break; - case TYPW: xtrab = LEN2; break; - case TYPB: xtrab = LEN1; break; + } + ap->a_areg1 |= 0x8F; + 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); } - } /*end of the switch on AIMM*/ - } /*end of the switch on a*/ + } + break; + + } /*end of the switch on argtype*/ /* * use the first byte to describe the argument */ - outb(ap->areg1); - if (xtrab) - outrel(&xp->xvalue, xtrab, xp->xtype, xp->xname); +#ifdef UNIX + outb(ap->a_areg1); +#endif UNIX +#ifdef VMS + *vms_obj_ptr++ = -1; *vms_obj_ptr++ = (char)(ap->a_areg1); + dotp->e_xvalue += 1; + if ((vms_obj_ptr-sobuf) > 400) { + write(objfil,sobuf,vms_obj_ptr-sobuf); + vms_obj_ptr=sobuf+1; + } +#endif VMS + if (reloc_how != TYPNONE) + outrel(xp, reloc_how); } /*end of the for to pick up all arguments*/ }