m68k-parse.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,067 行 · 第 1/4 页
C
2,067 行
} /* Else will try to reuse lookahead token after shifting the error token. */ yyerrstatus = 3; /* Each real token shifted decrements this */ goto yyerrhandle;yyerrdefault: /* current state does not do anything special for the error token. */#if 0 /* This is wrong; only states that explicitly want error tokens should shift them. */ yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ if (yyn) goto yydefault;#endifyyerrpop: /* pop the current state because it cannot handle the error token */ if (yyssp == yyss) YYABORT; yyvsp--; yystate = *--yyssp;#ifdef YYLSP_NEEDED yylsp--;#endif#if YYDEBUG != 0 if (yydebug) { short *ssp1 = yyss - 1; fprintf (stderr, "Error: state stack now"); while (ssp1 != yyssp) fprintf (stderr, " %d", *++ssp1); fprintf (stderr, "\n"); }#endifyyerrhandle: yyn = yypact[yystate]; if (yyn == YYFLAG) goto yyerrdefault; yyn += YYTERROR; if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) goto yyerrdefault; yyn = yytable[yyn]; if (yyn < 0) { if (yyn == YYFLAG) goto yyerrpop; yyn = -yyn; goto yyreduce; } else if (yyn == 0) goto yyerrpop; if (yyn == YYFINAL) YYACCEPT;#if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Shifting error token, ");#endif *++yyvsp = yylval;#ifdef YYLSP_NEEDED *++yylsp = yylloc;#endif yystate = yyn; goto yynewstate; yyacceptlab: /* YYACCEPT comes here. */ if (yyfree_stacks) { free (yyss); free (yyvs);#ifdef YYLSP_NEEDED free (yyls);#endif } return 0; yyabortlab: /* YYABORT comes here. */ if (yyfree_stacks) { free (yyss); free (yyvs);#ifdef YYLSP_NEEDED free (yyls);#endif } return 1;}#line 647 "m68k-parse.y"/* The string to parse is stored here, and modified by yylex. */static char *str;/* The original string pointer. */static char *strorig;/* If *CCP could be a register, return the register number and advance *CCP. Otherwise don't change *CCP, and return 0. */static enum m68k_registerm68k_reg_parse (ccp) register char **ccp;{ char *start = *ccp; char c; char *p; symbolS *symbolp; if (flag_reg_prefix_optional) { if (*start == REGISTER_PREFIX) start++; p = start; } else { if (*start != REGISTER_PREFIX) return 0; p = start + 1; } if (! is_name_beginner (*p)) return 0; p++; while (is_part_of_name (*p) && *p != '.' && *p != ':' && *p != '*') p++; c = *p; *p = 0; symbolp = symbol_find (start); *p = c; if (symbolp != NULL && S_GET_SEGMENT (symbolp) == reg_section) { *ccp = p; return S_GET_VALUE (symbolp); } /* In MRI mode, something like foo.bar can be equated to a register name. */ while (flag_mri && c == '.') { ++p; while (is_part_of_name (*p) && *p != '.' && *p != ':' && *p != '*') p++; c = *p; *p = '\0'; symbolp = symbol_find (start); *p = c; if (symbolp != NULL && S_GET_SEGMENT (symbolp) == reg_section) { *ccp = p; return S_GET_VALUE (symbolp); } } return 0;}/* The lexer. */static intyylex (){ enum m68k_register reg; char *s; int parens; int c = 0; int tail = 0; char *hold; if (*str == ' ') ++str; if (*str == '\0') return 0; /* Various special characters are just returned directly. */ switch (*str) { case '@': /* In MRI mode, this can be the start of an octal number. */ if (flag_mri) { if (isdigit (str[1]) || ((str[1] == '+' || str[1] == '-') && isdigit (str[2]))) break; } /* Fall through. */ case '#': case '&': case ',': case ')': case '/': case '[': case ']': return *str++; case '+': /* It so happens that a '+' can only appear at the end of an operand. If it appears anywhere else, it must be a unary plus on an expression. */ if (str[1] == '\0') return *str++; break; case '-': /* A '-' can only appear in -(ar), rn-rn, or ar@-. If it appears anywhere else, it must be a unary minus on an expression. */ if (str[1] == '\0') return *str++; s = str + 1; if (*s == '(') ++s; if (m68k_reg_parse (&s) != 0) return *str++; break; case '(': /* A '(' can only appear in `(reg)', `(expr,...', `([', `@(', or `)('. If it appears anywhere else, it must be starting an expression. */ if (str[1] == '[' || (str > strorig && (str[-1] == '@' || str[-1] == ')'))) return *str++; s = str + 1; if (m68k_reg_parse (&s) != 0) return *str++; /* Check for the case of '(expr,...' by scanning ahead. If we find a comma outside of balanced parentheses, we return '('. If we find an unbalanced right parenthesis, then presumably the '(' really starts an expression. */ parens = 0; for (s = str + 1; *s != '\0'; s++) { if (*s == '(') ++parens; else if (*s == ')') { if (parens == 0) break; --parens; } else if (*s == ',' && parens == 0) { /* A comma can not normally appear in an expression, so this is a case of '(expr,...'. */ return *str++; } } } /* See if it's a register. */ reg = m68k_reg_parse (&str); if (reg != 0) { int ret; yylval.reg = reg; if (reg >= DATA0 && reg <= DATA7) ret = DR; else if (reg >= ADDR0 && reg <= ADDR7) ret = AR; else if (reg >= FP0 && reg <= FP7) return FPR; else if (reg == FPI || reg == FPS || reg == FPC) return FPCR; else if (reg == PC) return LPC; else if (reg >= ZDATA0 && reg <= ZDATA7) ret = ZDR; else if (reg >= ZADDR0 && reg <= ZADDR7) ret = ZAR; else if (reg == ZPC) return LZPC; else return CREG; /* If we get here, we have a data or address register. We must check for a size or scale; if we find one, we must return INDEXREG. */ s = str; if (*s != '.' && *s != ':' && *s != '*') return ret; yylval.indexreg.reg = reg; if (*s != '.' && *s != ':') yylval.indexreg.size = SIZE_UNSPEC; else { ++s; switch (*s) { case 'w': case 'W': yylval.indexreg.size = SIZE_WORD; ++s; break; case 'l': case 'L': yylval.indexreg.size = SIZE_LONG; ++s; break; default: yyerror (_("illegal size specification")); yylval.indexreg.size = SIZE_UNSPEC; break; } } yylval.indexreg.scale = 1; if (*s == '*' || *s == ':') { expressionS scale; ++s; hold = input_line_pointer; input_line_pointer = s; expression (&scale); s = input_line_pointer; input_line_pointer = hold; if (scale.X_op != O_constant) yyerror (_("scale specification must resolve to a number")); else { switch (scale.X_add_number) { case 1: case 2: case 4: case 8: yylval.indexreg.scale = scale.X_add_number; break; default: yyerror (_("invalid scale value")); break; } } } str = s; return INDEXREG; } /* It must be an expression. Before we call expression, we need to look ahead to see if there is a size specification. We must do that first, because otherwise foo.l will be treated as the symbol foo.l, rather than as the symbol foo with a long size specification. The grammar requires that all expressions end at the end of the operand, or with ',', '(', ']', ')'. */ parens = 0; for (s = str; *s != '\0'; s++) { if (*s == '(') { if (parens == 0 && s > str && (s[-1] == ')' || isalnum ((unsigned char) s[-1]))) break; ++parens; } else if (*s == ')') { if (parens == 0) break; --parens; } else if (parens == 0 && (*s == ',' || *s == ']')) break; } yylval.exp.size = SIZE_UNSPEC; if (s <= str + 2 || (s[-2] != '.' && s[-2] != ':')) tail = 0; else { switch (s[-1]) { case 's': case 'S': case 'b': case 'B': yylval.exp.size = SIZE_BYTE; break; case 'w': case 'W': yylval.exp.size = SIZE_WORD; break; case 'l': case 'L': yylval.exp.size = SIZE_LONG; break; default: break; } if (yylval.exp.size != SIZE_UNSPEC) tail = 2; }#ifdef OBJ_ELF { /* Look for @PLTPC, etc. */ char *cp; yylval.exp.pic_reloc = pic_none; cp = s - tail; if (cp - 6 > str && cp[-6] == '@') { if (strncmp (cp - 6, "@PLTPC", 6) == 0) { yylval.exp.pic_reloc = pic_plt_pcrel; tail += 6; } else if (strncmp (cp - 6, "@GOTPC", 6) == 0) { yylval.exp.pic_reloc = pic_got_pcrel; tail += 6; } } else if (cp - 4 > str && cp[-4] == '@') { if (strncmp (cp - 4, "@PLT", 4) == 0) { yylval.exp.pic_reloc = pic_plt_off; tail += 4; } else if (strncmp (cp - 4, "@GOT", 4) == 0) { yylval.exp.pic_reloc = pic_got_off; tail += 4; } } }#endif if (tail != 0) { c = s[-tail]; s[-tail] = 0; } hold = input_line_pointer; input_line_pointer = str; expression (&yylval.exp.exp); str = input_line_pointer; input_line_pointer = hold; if (tail != 0) { s[-tail] = c; str = s; } return EXPR;}/* Parse an m68k operand. This is the only function which is called from outside this file. */intm68k_ip_op (s, oparg) char *s; struct m68k_op *oparg;{ memset (oparg, 0, sizeof *oparg); oparg->error = NULL; oparg->index.reg = ZDATA0; oparg->index.scale = 1; oparg->disp.exp.X_op = O_absent; oparg->odisp.exp.X_op = O_absent; str = strorig = s; op = oparg; return yyparse ();}/* The error handler. */static voidyyerror (s) const char *s;{ op->error = s;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?