📄 asparse.c
字号:
shift; /* bring in the first token for the arg list*/ } for (argcnt = 1; argcnt <= 6; argcnt++, ap++){ /* * code to process an argument proper */ sawindex = sawmul = sawsize = 0; { switch(val) { default: disp: if( !(INTOKSET(val, EBEGOPS +YUKKYEXPRBEG +SAFEEXPRBEG)) ) { ERROR("expression expected"); } expr(ap->a_xp,val); overdisp: if ( val == LP || sawsize){ shiftover(LP); findreg(regno); shiftover(RP); ap->a_atype = ADISP; ap->a_areg1 = regno; } else { ap->a_atype = AEXP; ap->a_areg1 = 0; } goto index; case SIZESPEC: sizespec: sawsize = yylval; shift; goto disp; case REG: case REGOP: findreg(regno); ap->a_atype = AREG; ap->a_areg1 = regno; break; case VREG: findvreg(regno); ap->a_atype = AVREG; ap->a_areg1 = regno; break; case MUL: sawmul = 1; shift; if (val == LP) goto base; if (val == LITOP) goto imm; if (val == SIZESPEC) goto sizespec; if (INTOKSET(val, EBEGOPS +YUKKYEXPRBEG +SAFEEXPRBEG)) goto disp; ERROR("expression, '(' or '$' expected"); break; case LP: base: shift; /*consume the LP*/ /* * hack the ambiguity of * movl (expr) (rn), ... * note that (expr) could also * be (rn) (by special hole in the * grammar), which we ensure * means register indirection, instead * of an expression with value n */ if (val != REG && val != REGOP){ droppedLP = 1; val = exprparse(val, &(ap->a_xp)); droppedLP = 0; goto overdisp; } findreg(regno); shiftover(RP); if (val == PLUS){ shift; ap->a_atype = AINCR; } else ap->a_atype = ABASE; ap->a_areg1 = regno; goto index; case LITOP: imm: shift; expr(locxp, val); ap->a_atype = AIMM; ap->a_areg1 = 0; ap->a_xp = locxp; goto index; case MP: shift; /* -(reg) */ findreg(regno); shiftover(RP); ap->a_atype = ADECR; ap->a_areg1 = regno; index: /*look for [reg] */ if (val == LB){ shift; findreg(regno); shiftover(RB); sawindex = 1; ap->a_areg2 = regno; } break; } /*end of the switch to process an arg*/ } /*end of processing an argument*/ if (sawmul){ /* * Make a concession for *(%r) * meaning *0(%r) */ if (ap->a_atype == ABASE) { ap->a_atype = ADISP; xp->e_xtype = XABS; xp->e_number = Znumber; xp->e_number.num_tag = TYPL; xp->e_xloc = 0; ap->a_xp = xp++; } ap->a_atype |= ASTAR; sawmul = 0; } if (sawindex){ ap->a_atype |= AINDX; sawindex = 0; } ap->a_dispsize = sawsize == 0 ? d124 : sawsize; if (val != CM) break; shiftover(CM); } /*processing all the arguments*/ if (argcnt > 6){ yyerror("More than 6 arguments"); goto errorfix; } if (auxval == VINSTn) { format_vinst (np, &vmod, arglist); } else { /* * See if this is a case instruction, * so we can set up tests on the following * vector of branch displacements */ if (yyopcode.Op_eopcode == CORE){ switch(yyopcode.Op_popcode){ case 0x8f: /* caseb */ case 0xaf: /* casew */ case 0xcf: /* casel */ incasetable++; break; default: incasetable = 0; break; } } insout(yyopcode, arglist, auxval == INSTn ? argcnt : - argcnt); } break; case IQUAD: toconv = TYPQ; goto bignumlist; case IOCTA: toconv = TYPO; goto bignumlist; case IFFLOAT: toconv = TYPF; goto bignumlist; case IDFLOAT: toconv = TYPD; goto bignumlist; case IGFLOAT: toconv = TYPG; goto bignumlist; case IHFLOAT: toconv = TYPH; goto bignumlist; bignumlist: /* * eat a list of non 32 bit numbers. * IQUAD and IOCTA can, possibly, return * INT's, if the numbers are "small". * * The value of the numbers is coming back * as an expression, NOT in yybignum. */ shift; /* over the opener */ if ((val == BIGNUM) || (val == INT)){ do{ if ((val != BIGNUM) && (val != INT)){ ERROR(ty_float[toconv] ? "floating number expected" : "integer number expected" ); } dotp->e_xvalue += ty_nbyte[toconv]; if (passno == 2){ bignumwrite( ((struct exp *)yylval)->e_number, toconv); } xp = explist; shift; /* over this number */ if (auxval = (val == CM)) shift; /* over the comma */ } while (auxval); /* as long as there are commas */ } break; /* end of the case for initialized big numbers */ } /*end of the switch for looking at each reserved word*/ continue; errorfix: /* * got here by either requesting to skip to the * end of this statement, or by erroring out and * wanting to apply panic mode recovery */ while ( (val != NL) && (val != SEMI) && (val != PARSEEOF) ){ shift; } if (val == NL) lineno++; shift; } /*end of the loop to read the entire file, line by line*/} /*end of yyparse*/ format_vinst(stp, vmodp, ap) struct symtab *stp; union Vinst_mod *vmodp; struct arg *ap;/* This routine is called to reformat the vector instruction from the * assembler notation format into the vector instruction format as * specified in the instrs opcode table. It builds vector instruction * control word, sets the appropriate qualifier fields in the control * word, sets the vector register fields and the compare/convert codes * in the control word, reshuffles the operands, and then calls the * insout routine to output the instruction to the object file, in a * normal way. The routine is driven by the vinst_fmt table, whose entries * represent groups of like vector instructions. */{ reg int i,j; int arg_num; int avalue; int argtype; struct Opcode opcode; u_char ctrlcode; struct arg *vap; /* first free vinst argument */ struct Vinst_fmt fmt; struct Vinst_arg vi_arg; struct Ctrl_word ctrl_word, *ctrl_word_ptr = &ctrl_word; int mod_length; char ch; /* Pick up info from symbol table */ opcode.Op_popcode = ((Iptr)stp)->i_popcode; opcode.Op_eopcode = ((Iptr)stp)->i_eopcode; ctrlcode = ((Iptr)stp)->i_ctrlcode; fmt = vinst_fmt[((Iptr)stp)->s_format]; /* Following is a kluge to allow vector instructions use the * same mapping mechanism from opcode to the symbol table entry, * as regular instructions */ itab[opcode.Op_eopcode][opcode.Op_popcode] = (Iptr) stp; vap = varglist; *(int *)ctrl_word_ptr = 0; for (i = 0; i < fmt.vi_nargs; i++) /* process args according to format */ { vi_arg = fmt.vi_args[i]; switch (vi_arg.va_tag) { default: break; /* argument type not defined */ case VOPND: /* Move source argument into specified vector instruction operand */ arg_num = vi_arg.va_args[0] - 1; varglist[i] = arglist[arg_num]; argtype = fetcharg(stp, i); if ((argtype & TYPMASK) == TYPF4) { /* Special check for vmergef */ if ((varglist[i].a_atype & AMASK) != AIMM) yyerror ("Illegal mode"); } varglist[i].a_atype |= AVECT; break; case VLTRL: /* Generate literal as the instruction's first operand */ xp->e_xvalue = ctrlcode; xp->e_number.num_tag = TYPL; xp->e_xloc = 0; xp->e_xtype = XABS; vap->a_atype = AIMM; vap->a_areg1 = 0; if (xp >= &explist[NEXP]) yyerror("Too many expressions; try simplyfing"); else vap->a_xp = xp++; break; case VCTRL: /* Generate control word */ for (j = 0; j < 3; j++) { /* Set va, vb, vc registers in the control word */ if (vi_arg.va_args[j] != 0) { arg_num = vi_arg.va_args[j]; if (arg_num == VCODE) avalue = ctrlcode; /* set cmp/cvt code */ else { arg_num--; argtype = arglist[arg_num].a_atype; if (argtype != AVREG) yyerror("arg %d, must specify a vector register", arg_num + 1); else avalue = arglist[arg_num].a_areg1; } switch (j) { case VA: ctrl_word.va_bits = avalue; break; case VB: ctrl_word.vb_bits = avalue; break; case VC: ctrl_word.vc_bits = avalue; break; } /* end switch */ } /* end if */ } /* end for */ break; } /* end switch */ } /* end for */ /* Process vector instruction modifiers into control word */ mod_length = vmodp->mod_value.mod_length; if (fmt.vi_args[0].va_tag == VCTRL) { ctrl_word.mod_bits |= fmt.vi_mod_dflt; if (mod_length > 0) { for (i = 1; i <= mod_length; i++) { switch (ch = vmodp->mod_value.mod_ch[i-1]) { case 'm': if ((fmt.vi_mod_mask & MI) != 0) ctrl_word.mod_bits |= mi_bit; else goto moderror; break; case 'u': case 'v': if ((fmt.vi_mod_mask & EXC) != 0) ctrl_word.mod_bits |= exc_bit; else goto moderror; break; case '0': if ((fmt.vi_mod_mask & MTF) != 0) { if ((fmt.vi_mod_mask & MOE) != 0) ctrl_word.mod_bits |= moe_bit; } else goto moderror; break; case '1': if ((fmt.vi_mod_mask & MTF) != 0) { if ((fmt.vi_mod_mask & MOE) != 0) ctrl_word.mod_bits |= moe_bit; ctrl_word.mod_bits |= mtf_bit; } else goto moderror; break; default: break; } /* end switch */ continue; moderror: yyerror("vector opcode qualifier %c is not valid for this opcode", ch); } /* end for */ } /* end if */ /* Finally set up control word as instruction's first operand */ xp->e_xtype = XABS; xp->e_xvalue = *(int *)ctrl_word_ptr; xp->e_number.num_tag = TYPW; xp->e_xloc = 0; vap->a_atype = AVECT; vap->a_areg1 = 0; if (xp >= &explist[NEXP]) yyerror("Too many expressions; try simplyfing"); else vap->a_xp = xp++; } /* end if */ else if (mod_length > 0) yyerror("Vector opcode qualifiers are not valid for this opcode"); /* Finally output this instruction */ insout(opcode, varglist, fmt.vi_nargs);} /* * Process a register declaration of the form * % <expr> * * Note: * The scanner has already processed funny registers of the form * %dd[+-]*, where dd is a decimal number in the range 00 to 15 (optional * preceding zero digit). If there was any space between the % and * the digit, the scanner wouldn't have recognized it, so we * hack it out here. /* * Process a register declaration of the form * % <expr> * * Note: * The scanner has already processed funny registers of the form * %dd[+-]*, where dd is a decimal number in the range 00 to 15 (optional * preceding zero digit). If there was any space between the % and * the digit, the scanner wouldn't have recognized it, so we * hack it out here. */inttoktype funnyreg(val, regnoback) /*what the read head will sit on*/ inttoktype val; /*what the read head is sitting on*/ int *regnoback; /*call by return*/{ reg struct exp *locxp; struct exp *loc1xp; struct exp **ptrloc1xp = & loc1xp; expr(locxp, val); /*and leave the current read head with value*/ if ( (passno == 2) && ( (locxp->e_xtype & XTYPE) != XABS || (locxp->e_xvalue < 0) || (locxp->e_xvalue >= 16) ) ){ yyerror("Illegal register"); return(0); } *regnoback = locxp->e_xvalue; return(val);} /* * Shift over error */shiftoerror(token) int token;{ char *tok_to_name(); yyerror("%s expected", tok_to_name(token));}/*VARARGS1*/yyerror(s, a1, a2,a3,a4,a5) char *s;{#define sink stdout if (anyerrs == 0 && anywarnings == 0 && ! silent) fprintf(sink, "Assembler:\n"); anyerrs++; if (silent) return; fprintf(sink, "\"%s\", line %d: ", dotsname, lineno); fprintf(sink, s, a1, a2,a3,a4,a5); fprintf(sink, "\n");#undef sink}/*VARARGS1*/yywarning(s, a1, a2,a3,a4,a5) char *s;{#define sink stdout if (anyerrs == 0 && anywarnings == 0 && ! silent) fprintf(sink, "Assembler:\n"); anywarnings++; if (silent) return; fprintf(sink, "\"%s\", line %d: WARNING: ", dotsname, lineno); fprintf(sink, s, a1, a2,a3,a4,a5); fprintf(sink, "\n");#undef sink}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -