📄 tc-v850.c
字号:
{ "r19", 19 }, { "r2", 2 }, { "r20", 20 }, { "r21", 21 }, { "r22", 22 }, { "r23", 23 }, { "r24", 24 }, { "r25", 25 }, { "r26", 26 }, { "r27", 27 }, { "r28", 28 }, { "r29", 29 }, { "r3", 3 }, { "r30", 30 }, { "r31", 31 }, { "r4", 4 }, { "r5", 5 }, { "r6", 6 }, { "r7", 7 }, { "r8", 8 }, { "r9", 9 }, { "sp", 3 }, /* sp - stack ptr */ { "tp", 5 }, /* tp - text ptr */ { "zero", 0 },};#define REG_NAME_CNT \ (sizeof (pre_defined_registers) / sizeof (struct reg_name))static const struct reg_name system_registers[] = { { "ctbp", 20 }, { "ctpc", 16 }, { "ctpsw", 17 }, { "dbpc", 18 }, { "dbpsw", 19 }, { "ecr", 4 }, { "eipc", 0 }, { "eipsw", 1 }, { "fepc", 2 }, { "fepsw", 3 }, { "psw", 5 },};#define SYSREG_NAME_CNT \ (sizeof (system_registers) / sizeof (struct reg_name))static const struct reg_name system_list_registers[] = { {"PS", 5 }, {"SR", 0 + 1}};#define SYSREGLIST_NAME_CNT \ (sizeof (system_list_registers) / sizeof (struct reg_name))static const struct reg_name cc_names[] = { { "c", 0x1 }, { "e", 0x2 }, { "ge", 0xe }, { "gt", 0xf }, { "h", 0xb }, { "l", 0x1 }, { "le", 0x7 }, { "lt", 0x6 }, { "n", 0x4 }, { "nc", 0x9 }, { "ne", 0xa }, { "nh", 0x3 }, { "nl", 0x9 }, { "ns", 0xc }, { "nv", 0x8 }, { "nz", 0xa }, { "p", 0xc }, { "s", 0x4 }, { "sa", 0xd }, { "t", 0x5 }, { "v", 0x0 }, { "z", 0x2 },};#define CC_NAME_CNT \ (sizeof (cc_names) / sizeof (struct reg_name))/* Do a binary search of the given register table to see if NAME is a valid regiter name. Return the register number from the array on success, or -1 on failure. */static intreg_name_search (regs, regcount, name, accept_numbers) const struct reg_name *regs; int regcount; const char *name; boolean accept_numbers;{ int middle, low, high; int cmp; symbolS *symbolP; /* If the register name is a symbol, then evaluate it. */ if ((symbolP = symbol_find (name)) != NULL) { /* If the symbol is an alias for another name then use that. If the symbol is an alias for a number, then return the number. */ if (symbol_equated_p (symbolP)) { name = S_GET_NAME (symbol_get_value_expression (symbolP)->X_add_symbol); } else if (accept_numbers) { int reg = S_GET_VALUE (symbolP); if (reg >= 0 && reg <= 31) return reg; } /* Otherwise drop through and try parsing name normally. */ } low = 0; high = regcount - 1; do { middle = (low + high) / 2; cmp = strcasecmp (name, regs[middle].name); if (cmp < 0) high = middle - 1; else if (cmp > 0) low = middle + 1; else return regs[middle].value; } while (low <= high); return -1;}/* Summary of register_name(). * * in: Input_line_pointer points to 1st char of operand. * * out: A expressionS. * The operand may have been a register: in this case, X_op == O_register, * X_add_number is set to the register number, and truth is returned. * Input_line_pointer->(next non-blank) char after operand, or is in * its original state. */static booleanregister_name (expressionP) expressionS *expressionP;{ int reg_number; char *name; char *start; char c; /* Find the spelling of the operand. */ start = name = input_line_pointer; c = get_symbol_end (); reg_number = reg_name_search (pre_defined_registers, REG_NAME_CNT, name, FALSE); /* Put back the delimiting char. */ *input_line_pointer = c; /* Look to see if it's in the register table. */ if (reg_number >= 0) { expressionP->X_op = O_register; expressionP->X_add_number = reg_number; /* Make the rest nice. */ expressionP->X_add_symbol = NULL; expressionP->X_op_symbol = NULL; return true; } else { /* Reset the line as if we had not done anything. */ input_line_pointer = start; return false; }}/* Summary of system_register_name(). * * in: INPUT_LINE_POINTER points to 1st char of operand. * EXPRESSIONP points to an expression structure to be filled in. * ACCEPT_NUMBERS is true iff numerical register names may be used. * ACCEPT_LIST_NAMES is true iff the special names PS and SR may be * accepted. * * out: A expressionS structure in expressionP. * The operand may have been a register: in this case, X_op == O_register, * X_add_number is set to the register number, and truth is returned. * Input_line_pointer->(next non-blank) char after operand, or is in * its original state. */static booleansystem_register_name (expressionP, accept_numbers, accept_list_names) expressionS *expressionP; boolean accept_numbers; boolean accept_list_names;{ int reg_number; char *name; char *start; char c; /* Find the spelling of the operand. */ start = name = input_line_pointer; c = get_symbol_end (); reg_number = reg_name_search (system_registers, SYSREG_NAME_CNT, name, accept_numbers); /* Put back the delimiting char. */ *input_line_pointer = c; if (reg_number < 0 && accept_numbers) { /* Reset input_line pointer. */ input_line_pointer = start; if (isdigit (*input_line_pointer)) { reg_number = strtol (input_line_pointer, &input_line_pointer, 10); /* Make sure that the register number is allowable. */ if (reg_number < 0 || (reg_number > 5 && reg_number < 16) || reg_number > 20) { reg_number = -1; } } else if (accept_list_names) { c = get_symbol_end (); reg_number = reg_name_search (system_list_registers, SYSREGLIST_NAME_CNT, name, FALSE); /* Put back the delimiting char. */ *input_line_pointer = c; } } /* Look to see if it's in the register table. */ if (reg_number >= 0) { expressionP->X_op = O_register; expressionP->X_add_number = reg_number; /* Make the rest nice. */ expressionP->X_add_symbol = NULL; expressionP->X_op_symbol = NULL; return true; } else { /* Reset the line as if we had not done anything. */ input_line_pointer = start; return false; }}/* Summary of cc_name(). * * in: INPUT_LINE_POINTER points to 1st char of operand. * * out: A expressionS. * The operand may have been a register: in this case, X_op == O_register, * X_add_number is set to the register number, and truth is returned. * Input_line_pointer->(next non-blank) char after operand, or is in * its original state. */static booleancc_name (expressionP) expressionS *expressionP;{ int reg_number; char *name; char *start; char c; /* Find the spelling of the operand. */ start = name = input_line_pointer; c = get_symbol_end (); reg_number = reg_name_search (cc_names, CC_NAME_CNT, name, FALSE); /* Put back the delimiting char. */ *input_line_pointer = c; /* Look to see if it's in the register table. */ if (reg_number >= 0) { expressionP->X_op = O_constant; expressionP->X_add_number = reg_number; /* Make the rest nice. */ expressionP->X_add_symbol = NULL; expressionP->X_op_symbol = NULL; return true; } else { /* Reset the line as if we had not done anything. */ input_line_pointer = start; return false; }}static voidskip_white_space (void){ while (*input_line_pointer == ' ' || *input_line_pointer == '\t') ++input_line_pointer;}/* Summary of parse_register_list (). * * in: INPUT_LINE_POINTER points to 1st char of a list of registers. * INSN is the partially constructed instruction. * OPERAND is the operand being inserted. * * out: NULL if the parse completed successfully, otherwise a * pointer to an error message is returned. If the parse * completes the correct bit fields in the instruction * will be filled in. * * Parses register lists with the syntax: * * { rX } * { rX, rY } * { rX - rY } * { rX - rY, rZ } * etc * * and also parses constant epxressions whoes bits indicate the * registers in the lists. The LSB in the expression refers to * the lowest numbered permissable register in the register list, * and so on upwards. System registers are considered to be very * high numbers. */static char *parse_register_list (insn, operand) unsigned long *insn; const struct v850_operand *operand;{ static int type1_regs[32] = { 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 }; static int type2_regs[32] = { 19, 18, 17, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 }; static int type3_regs[32] = { 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 15, 13, 12, 7, 6, 5, 4, 11, 10, 9, 8 }; int *regs; expressionS exp; /* Select a register array to parse. */ switch (operand->shift) { case 0xffe00001: regs = type1_regs; break; case 0xfff8000f: regs = type2_regs; break; case 0xfff8001f: regs = type3_regs; break; default: as_bad (_("unknown operand shift: %x\n"), operand->shift); return _("internal failure in parse_register_list"); } skip_white_space (); /* If the expression starts with a curly brace it is a register list. Otherwise it is a constant expression, whoes bits indicate which registers are to be included in the list. */ if (*input_line_pointer != '{') { int reg; int i; expression (&exp); if (exp.X_op != O_constant) return _("constant expression or register list expected"); if (regs == type1_regs) { if (exp.X_add_number & 0xFFFFF000) return _("high bits set in register list expression"); for (reg = 20; reg < 32; reg++) if (exp.X_add_number & (1 << (reg - 20))) { for (i = 0; i < 32; i++) if (regs[i] == reg) *insn |= (1 << i); } } else if (regs == type2_regs) { if (exp.X_add_number & 0xFFFE0000) return _("high bits set in register list expression"); for (reg = 1; reg < 16; reg++) if (exp.X_add_number & (1 << (reg - 1))) { for (i = 0; i < 32; i++) if (regs[i] == reg) *insn |= (1 << i); } if (exp.X_add_number & (1 << 15)) *insn |= (1 << 3); if (exp.X_add_number & (1 << 16)) *insn |= (1 << 19); } else /* regs == type3_regs */ { if (exp.X_add_number & 0xFFFE0000) return _("high bits set in register list expression"); for (reg = 16; reg < 32; reg++) if (exp.X_add_number & (1 << (reg - 16))) { for (i = 0; i < 32; i++) if (regs[i] == reg) *insn |= (1 << i); } if (exp.X_add_number & (1 << 16)) *insn |= (1 << 19); } return NULL; } input_line_pointer++; /* Parse the register list until a terminator (closing curly brace or new-line) is found. */ for (;;) { if (register_name (&exp)) { int i; /* Locate the given register in the list, and if it is there, insert the corresponding bit into the instruction. */ for (i = 0; i < 32; i++) { if (regs[i] == exp.X_add_number) { *insn |= (1 << i); break; } } if (i == 32) { return _("illegal register included in list"); } } else if (system_register_name (&exp, true, true)) { if (regs == type1_regs) { return _("system registers cannot be included in list"); } else if (exp.X_add_number == 5) { if (regs == type2_regs) return _("PSW cannot be included in list"); else *insn |= 0x8; } else if (exp.X_add_number < 4) *insn |= 0x80000; else return _("High value system registers cannot be included in list"); } else if (*input_line_pointer == '}') { input_line_pointer++; break; } else if (*input_line_pointer == ',') { input_line_pointer++; continue; } else if (*input_line_pointer == '-') { /* We have encountered a range of registers: rX - rY. */ int j; expressionS exp2; /* Skip the dash. */ ++input_line_pointer; /* Get the second register in the range. */ if (! register_name (&exp2)) { return _("second register should follow dash in register list"); exp2.X_add_number = exp.X_add_number; } /* Add the rest of the registers in the range. */ for (j = exp.X_add_number + 1; j <= exp2.X_add_number; j++) { int i; /* Locate the given register in the list, and if it is there, insert the corresponding bit into the instruction. */ for (i = 0; i < 32; i++) { if (regs[i] == j) { *insn |= (1 << i); break; } } if (i == 32) return _("illegal register included in list"); } } else { break; } skip_white_space (); } return NULL;}CONST char *md_shortopts = "m:";struct option md_longopts[] = { {NULL, no_argument, NULL, 0}};size_t md_longopts_size = sizeof (md_longopts);voidmd_show_usage (stream) FILE *stream;{ fprintf (stream, _(" V850 options:\n")); fprintf (stream, _(" -mwarn-signed-overflow Warn if signed immediate values overflow\n")); fprintf (stream, _(" -mwarn-unsigned-overflow Warn if unsigned immediate values overflow\n")); fprintf (stream, _(" -mv850 The code is targeted at the v850\n")); fprintf (stream, _(" -mv850e The code is targeted at the v850e\n")); fprintf (stream, _(" -mv850ea The code is targeted at the v850ea\n")); fprintf (stream, _(" -mv850any The code is generic, despite any processor specific instructions\n"));}intmd_parse_option (c, arg) int c; char *arg;{ if (c != 'm') { if (c != 'a') /* xgettext:c-format */ fprintf (stderr, _("unknown command line option: -%c%s\n"), c, arg); return 0; } if (strcmp (arg, "warn-signed-overflow") == 0) { warn_signed_overflows = TRUE; } else if (strcmp (arg, "warn-unsigned-overflow") == 0) { warn_unsigned_overflows = TRUE; } else if (strcmp (arg, "v850") == 0) { machine = 0; processor_mask = PROCESSOR_V850; } else if (strcmp (arg, "v850e") == 0) { machine = bfd_mach_v850e; processor_mask = PROCESSOR_V850E; } else if (strcmp (arg, "v850ea") == 0) { machine = bfd_mach_v850ea; processor_mask = PROCESSOR_V850EA; } else if (strcmp (arg, "v850any") == 0) { /* Tell the world that this is for any v850 chip. */ machine = 0; /* But support instructions for the extended versions. */ processor_mask = PROCESSOR_V850EA; } else { /* xgettext:c-format */ fprintf (stderr, _("unknown command line option: -%c%s\n"), c, arg); return 0; } return 1;}symbolS *md_undefined_symbol (name) char *name ATTRIBUTE_UNUSED;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -