📄 tc-alpha.c
字号:
expressionS *orig_tok = tok;#endif#ifdef RELOC_OP_P char *p; const struct alpha_reloc_op_tag *r; int c, i; size_t len; int reloc_found_p = 0;#endif memset (tok, 0, sizeof (*tok) * ntok); /* Save and restore input_line_pointer around this function */ old_input_line_pointer = input_line_pointer; input_line_pointer = str; while (tok < end_tok && *input_line_pointer) { SKIP_WHITESPACE (); switch (*input_line_pointer) { case '\0': goto fini;#ifdef RELOC_OP_P case '!': /* A relocation operand can be placed after the normal operand on an assembly language statement, and has the following form: !relocation_type!sequence_number. */ if (reloc_found_p) { /* only support one relocation op per insn */ as_bad (_("More than one relocation op per insn")); goto err_report; } if (!saw_arg) goto err; for (p = ++input_line_pointer; ((c = *p) != '!' && c != ';' && c != '#' && c != ',' && !is_end_of_line[c]); p++) ; /* Parse !relocation_type */ len = p - input_line_pointer; if (len == 0) { as_bad (_("No relocation operand")); goto err_report; } if (c != '!') { as_bad (_("No !sequence-number after !%s"), input_line_pointer); goto err_report; } r = &alpha_reloc_op[0]; for (i = alpha_num_reloc_op - 1; i >= 0; i--, r++) { if (len == r->length && memcmp (input_line_pointer, r->name, len) == 0) break; } if (i < 0) { as_bad (_("Unknown relocation operand: !%s"), input_line_pointer); goto err_report; } input_line_pointer = ++p; /* Parse !sequence_number */ memset (tok, '\0', sizeof (expressionS)); expression (tok); if (tok->X_op != O_constant || ! ALPHA_RELOC_SEQUENCE_OK (tok->X_add_number)) { as_bad (_("Bad sequence number: !%s!%s"), r->name, input_line_pointer); goto err_report; } tok->X_op = r->op; reloc_found_p = 1; ++tok; break;#endif case ',': ++input_line_pointer; if (saw_comma || !saw_arg) goto err; saw_comma = 1; break; case '(': { char *hold = input_line_pointer++; /* First try for parenthesized register ... */ expression (tok); if (*input_line_pointer == ')' && tok->X_op == O_register) { tok->X_op = (saw_comma ? O_cpregister : O_pregister); saw_comma = 0; saw_arg = 1; ++input_line_pointer; ++tok; break; } /* ... then fall through to plain expression */ input_line_pointer = hold; } default: if (saw_arg && !saw_comma) goto err; expression (tok); if (tok->X_op == O_illegal || tok->X_op == O_absent) goto err; saw_comma = 0; saw_arg = 1; ++tok; break; } }fini: if (saw_comma) goto err; input_line_pointer = old_input_line_pointer;#ifdef DEBUG_ALPHA debug_exp (orig_tok, ntok - (end_tok - tok));#endif return ntok - (end_tok - tok);err: input_line_pointer = old_input_line_pointer; return TOKENIZE_ERROR;#ifdef RELOC_OP_Perr_report: input_line_pointer = old_input_line_pointer; return TOKENIZE_ERROR_REPORT;#endif}/* Search forward through all variants of an opcode looking for a syntax match. */static const struct alpha_opcode *find_opcode_match (first_opcode, tok, pntok, pcpumatch) const struct alpha_opcode *first_opcode; const expressionS *tok; int *pntok; int *pcpumatch;{ const struct alpha_opcode *opcode = first_opcode; int ntok = *pntok; int got_cpu_match = 0; do { const unsigned char *opidx; int tokidx = 0; /* Don't match opcodes that don't exist on this architecture */ if (!(opcode->flags & alpha_target)) goto match_failed; got_cpu_match = 1; for (opidx = opcode->operands; *opidx; ++opidx) { const struct alpha_operand *operand = &alpha_operands[*opidx]; /* only take input from real operands */ if (operand->flags & AXP_OPERAND_FAKE) continue; /* when we expect input, make sure we have it */ if (tokidx >= ntok) { if ((operand->flags & AXP_OPERAND_OPTIONAL_MASK) == 0) goto match_failed; continue; } /* match operand type with expression type */ switch (operand->flags & AXP_OPERAND_TYPECHECK_MASK) { case AXP_OPERAND_IR: if (tok[tokidx].X_op != O_register || !is_ir_num (tok[tokidx].X_add_number)) goto match_failed; break; case AXP_OPERAND_FPR: if (tok[tokidx].X_op != O_register || !is_fpr_num (tok[tokidx].X_add_number)) goto match_failed; break; case AXP_OPERAND_IR | AXP_OPERAND_PARENS: if (tok[tokidx].X_op != O_pregister || !is_ir_num (tok[tokidx].X_add_number)) goto match_failed; break; case AXP_OPERAND_IR | AXP_OPERAND_PARENS | AXP_OPERAND_COMMA: if (tok[tokidx].X_op != O_cpregister || !is_ir_num (tok[tokidx].X_add_number)) goto match_failed; break; case AXP_OPERAND_RELATIVE: case AXP_OPERAND_SIGNED: case AXP_OPERAND_UNSIGNED: switch (tok[tokidx].X_op) { case O_illegal: case O_absent: case O_register: case O_pregister: case O_cpregister: goto match_failed; default: break; } break; default: /* everything else should have been fake */ abort (); } ++tokidx; } /* possible match -- did we use all of our input? */ if (tokidx == ntok) { *pntok = ntok; return opcode; } match_failed:; } while (++opcode - alpha_opcodes < alpha_num_opcodes && !strcmp (opcode->name, first_opcode->name)); if (*pcpumatch) *pcpumatch = got_cpu_match; return NULL;}/* Search forward through all variants of a macro looking for a syntax match. */static const struct alpha_macro *find_macro_match (first_macro, tok, pntok) const struct alpha_macro *first_macro; const expressionS *tok; int *pntok;{ const struct alpha_macro *macro = first_macro; int ntok = *pntok; do { const enum alpha_macro_arg *arg = macro->argsets; int tokidx = 0; while (*arg) { switch (*arg) { case MACRO_EOA: if (tokidx == ntok) return macro; else tokidx = 0; break; /* index register */ case MACRO_IR: if (tokidx >= ntok || tok[tokidx].X_op != O_register || !is_ir_num (tok[tokidx].X_add_number)) goto match_failed; ++tokidx; break; /* parenthesized index register */ case MACRO_PIR: if (tokidx >= ntok || tok[tokidx].X_op != O_pregister || !is_ir_num (tok[tokidx].X_add_number)) goto match_failed; ++tokidx; break; /* optional parenthesized index register */ case MACRO_OPIR: if (tokidx < ntok && tok[tokidx].X_op == O_pregister && is_ir_num (tok[tokidx].X_add_number)) ++tokidx; break; /* leading comma with a parenthesized index register */ case MACRO_CPIR: if (tokidx >= ntok || tok[tokidx].X_op != O_cpregister || !is_ir_num (tok[tokidx].X_add_number)) goto match_failed; ++tokidx; break; /* floating point register */ case MACRO_FPR: if (tokidx >= ntok || tok[tokidx].X_op != O_register || !is_fpr_num (tok[tokidx].X_add_number)) goto match_failed; ++tokidx; break; /* normal expression */ case MACRO_EXP: if (tokidx >= ntok) goto match_failed; switch (tok[tokidx].X_op) { case O_illegal: case O_absent: case O_register: case O_pregister: case O_cpregister:#ifdef RELOC_OP_P case O_literal: case O_lituse_base: case O_lituse_bytoff: case O_lituse_jsr: case O_gpdisp: case O_gprelhigh: case O_gprellow:#endif goto match_failed; default: break; } ++tokidx; break; /* optional !literal!<number> */ case MACRO_LITERAL:#ifdef RELOC_OP_P if (tokidx < ntok && tok[tokidx].X_op == O_literal) tokidx++;#endif break; /* optional !lituse_base!<number> */ case MACRO_BASE:#ifdef RELOC_OP_P if (tokidx < ntok && tok[tokidx].X_op == O_lituse_base) tokidx++;#endif break; /* optional !lituse_bytoff!<number> */ case MACRO_BYTOFF:#ifdef RELOC_OP_P if (tokidx < ntok && tok[tokidx].X_op == O_lituse_bytoff) tokidx++;#endif break; /* optional !lituse_jsr!<number> */ case MACRO_JSR:#ifdef RELOC_OP_P if (tokidx < ntok && tok[tokidx].X_op == O_lituse_jsr) tokidx++;#endif break; match_failed: while (*arg != MACRO_EOA) ++arg; tokidx = 0; break; } ++arg; } } while (++macro - alpha_macros < alpha_num_macros && !strcmp (macro->name, first_macro->name)); return NULL;}/* Insert an operand value into an instruction. */static unsignedinsert_operand (insn, operand, val, file, line) unsigned insn; const struct alpha_operand *operand; offsetT val; char *file; unsigned line;{ if (operand->bits != 32 && !(operand->flags & AXP_OPERAND_NOOVERFLOW)) { offsetT min, max; if (operand->flags & AXP_OPERAND_SIGNED) { max = (1 << (operand->bits - 1)) - 1; min = -(1 << (operand->bits - 1)); } else { max = (1 << operand->bits) - 1; min = 0; } if (val < min || val > max) { const char *err = _("operand out of range (%s not between %d and %d)"); char buf[sizeof (val) * 3 + 2]; sprint_value (buf, val); if (file) as_warn_where (file, line, err, buf, min, max); else as_warn (err, buf, min, max); } } if (operand->insert) { const char *errmsg = NULL; insn = (*operand->insert) (insn, val, &errmsg); if (errmsg) as_warn (errmsg); } else insn |= ((val & ((1 << operand->bits) - 1)) << operand->shift); return insn;}/* * Turn an opcode description and a set of arguments into * an instruction and a fixup. */static voidassemble_insn (opcode, tok, ntok, insn) const struct alpha_opcode *opcode; const expressionS *tok; int ntok; struct alpha_insn *insn;{ const unsigned char *argidx; unsigned image; int tokidx = 0; memset (insn, 0, sizeof (*insn));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -