📄 tc-v850.c
字号:
{ return 0;}char *md_atof (type, litp, sizep) int type; char *litp; int *sizep;{ int prec; LITTLENUM_TYPE words[4]; char *t; int i; switch (type) { case 'f': prec = 2; break; case 'd': prec = 4; break; default: *sizep = 0; return _("bad call to md_atof"); } t = atof_ieee (input_line_pointer, type, words); if (t) input_line_pointer = t; *sizep = prec * 2; for (i = prec - 1; i >= 0; i--) { md_number_to_chars (litp, (valueT) words[i], 2); litp += 2; } return NULL;}/* Very gross. */voidmd_convert_frag (abfd, sec, fragP) bfd *abfd ATTRIBUTE_UNUSED; asection *sec; fragS *fragP;{ subseg_change (sec, 0); /* In range conditional or unconditional branch. */ if (fragP->fr_subtype == 0 || fragP->fr_subtype == 2) { fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol, fragP->fr_offset, 1, BFD_RELOC_UNUSED + (int)fragP->fr_opcode); fragP->fr_fix += 2; } /* Out of range conditional branch. Emit a branch around a jump. */ else if (fragP->fr_subtype == 1) { unsigned char *buffer = (unsigned char *) (fragP->fr_fix + fragP->fr_literal); /* Reverse the condition of the first branch. */ buffer[0] ^= 0x08; /* Mask off all the displacement bits. */ buffer[0] &= 0x8f; buffer[1] &= 0x07; /* Now set the displacement bits so that we branch around the unconditional branch. */ buffer[0] |= 0x30; /* Now create the unconditional branch + fixup to the final target. */ md_number_to_chars (buffer + 2, 0x00000780, 4); fix_new (fragP, fragP->fr_fix + 2, 4, fragP->fr_symbol, fragP->fr_offset, 1, BFD_RELOC_UNUSED + (int) fragP->fr_opcode + 1); fragP->fr_fix += 6; } /* Out of range unconditional branch. Emit a jump. */ else if (fragP->fr_subtype == 3) { md_number_to_chars (fragP->fr_fix + fragP->fr_literal, 0x00000780, 4); fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol, fragP->fr_offset, 1, BFD_RELOC_UNUSED + (int) fragP->fr_opcode + 1); fragP->fr_fix += 4; } else abort ();}valueTmd_section_align (seg, addr) asection *seg; valueT addr;{ int align = bfd_get_section_alignment (stdoutput, seg); return ((addr + (1 << align) - 1) & (-1 << align));}voidmd_begin (){ char *prev_name = ""; register const struct v850_opcode *op; flagword applicable; if (strncmp (TARGET_CPU, "v850ea", 6) == 0) { if (machine == -1) machine = bfd_mach_v850ea; if (processor_mask == -1) processor_mask = PROCESSOR_V850EA; } else if (strncmp (TARGET_CPU, "v850e", 5) == 0) { if (machine == -1) machine = bfd_mach_v850e; if (processor_mask == -1) processor_mask = PROCESSOR_V850E; } else if (strncmp (TARGET_CPU, "v850", 4) == 0) { if (machine == -1) machine = 0; if (processor_mask == -1) processor_mask = PROCESSOR_V850; } else /* xgettext:c-format */ as_bad (_("Unable to determine default target processor from string: %s"), TARGET_CPU); v850_hash = hash_new (); /* Insert unique names into hash table. The V850 instruction set has many identical opcode names that have different opcodes based on the operands. This hash table then provides a quick index to the first opcode with a particular name in the opcode table. */ op = v850_opcodes; while (op->name) { if (strcmp (prev_name, op->name)) { prev_name = (char *) op->name; hash_insert (v850_hash, op->name, (char *) op); } op++; } bfd_set_arch_mach (stdoutput, TARGET_ARCH, machine); applicable = bfd_applicable_section_flags (stdoutput); call_table_data_section = subseg_new (".call_table_data", 0); bfd_set_section_flags (stdoutput, call_table_data_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA | SEC_HAS_CONTENTS)); call_table_text_section = subseg_new (".call_table_text", 0); bfd_set_section_flags (stdoutput, call_table_text_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE)); /* Restore text section as the current default. */ subseg_set (text_section, 0);}static bfd_reloc_code_real_typehandle_ctoff (const struct v850_operand *operand){ if (operand == NULL) return BFD_RELOC_V850_CALLT_16_16_OFFSET; if (operand->bits != 6 || operand->shift != 0) { as_bad (_("ctoff() relocation used on an instruction which does not support it")); return BFD_RELOC_64; /* Used to indicate an error condition. */ } return BFD_RELOC_V850_CALLT_6_7_OFFSET;}static bfd_reloc_code_real_typehandle_sdaoff (const struct v850_operand *operand){ if (operand == NULL) return BFD_RELOC_V850_SDA_16_16_OFFSET; if (operand->bits == 15 && operand->shift == 17) return BFD_RELOC_V850_SDA_15_16_OFFSET; if (operand->bits == -1) return BFD_RELOC_V850_SDA_16_16_SPLIT_OFFSET; if (operand->bits != 16 || operand->shift != 16) { as_bad (_("sdaoff() relocation used on an instruction which does not support it")); return BFD_RELOC_64; /* Used to indicate an error condition. */ } return BFD_RELOC_V850_SDA_16_16_OFFSET;}static bfd_reloc_code_real_typehandle_zdaoff (const struct v850_operand *operand){ if (operand == NULL) return BFD_RELOC_V850_ZDA_16_16_OFFSET; if (operand->bits == 15 && operand->shift == 17) return BFD_RELOC_V850_ZDA_15_16_OFFSET; if (operand->bits == -1) return BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET; if (operand->bits != 16 || operand->shift != 16) { as_bad (_("zdaoff() relocation used on an instruction which does not support it")); /* Used to indicate an error condition. */ return BFD_RELOC_64; } return BFD_RELOC_V850_ZDA_16_16_OFFSET;}static bfd_reloc_code_real_typehandle_tdaoff (const struct v850_operand *operand){ if (operand == NULL) /* Data item, not an instruction. */ return BFD_RELOC_V850_TDA_7_7_OFFSET; if (operand->bits == 6 && operand->shift == 1) /* sld.w/sst.w, operand: D8_6 */ return BFD_RELOC_V850_TDA_6_8_OFFSET; if (operand->bits == 4 && operand->insert != NULL) /* sld.hu, operand: D5-4 */ return BFD_RELOC_V850_TDA_4_5_OFFSET; if (operand->bits == 4 && operand->insert == NULL) /* sld.bu, operand: D4 */ return BFD_RELOC_V850_TDA_4_4_OFFSET; if (operand->bits == 16 && operand->shift == 16) /* set1 & chums, operands: D16 */ return BFD_RELOC_V850_TDA_16_16_OFFSET; if (operand->bits != 7) { as_bad (_("tdaoff() relocation used on an instruction which does not support it")); /* Used to indicate an error condition. */ return BFD_RELOC_64; } return operand->insert != NULL ? BFD_RELOC_V850_TDA_7_8_OFFSET /* sld.h/sst.h, operand: D8_7 */ : BFD_RELOC_V850_TDA_7_7_OFFSET; /* sld.b/sst.b, opreand: D7 */}/* Warning: The code in this function relies upon the definitions in the v850_operands[] array (defined in opcodes/v850-opc.c) matching the hard coded values contained herein. */static bfd_reloc_code_real_typev850_reloc_prefix (const struct v850_operand *operand){ boolean paren_skipped = false; /* Skip leading opening parenthesis. */ if (*input_line_pointer == '(') { ++input_line_pointer; paren_skipped = true; }#define CHECK_(name, reloc) \ if (strncmp (input_line_pointer, name##"(", strlen (name) + 1) == 0) \ { \ input_line_pointer += strlen (name); \ return reloc; \ } CHECK_ ("hi0", BFD_RELOC_HI16 ); CHECK_ ("hi", BFD_RELOC_HI16_S ); CHECK_ ("lo", BFD_RELOC_LO16 ); CHECK_ ("sdaoff", handle_sdaoff (operand)); CHECK_ ("zdaoff", handle_zdaoff (operand)); CHECK_ ("tdaoff", handle_tdaoff (operand)); CHECK_ ("hilo", BFD_RELOC_32 ); CHECK_ ("ctoff", handle_ctoff (operand) ); /* Restore skipped parenthesis. */ if (paren_skipped) --input_line_pointer; return BFD_RELOC_UNUSED;}/* Insert an operand value into an instruction. */static unsigned longv850_insert_operand (insn, operand, val, file, line, str) unsigned long insn; const struct v850_operand *operand; offsetT val; char *file; unsigned int line; char *str;{ if (operand->insert) { const char *message = NULL; insn = operand->insert (insn, val, &message); if (message != NULL) { if ((operand->flags & V850_OPERAND_SIGNED) && ! warn_signed_overflows && strstr (message, "out of range") != NULL) { /* Skip warning... */ } else if ((operand->flags & V850_OPERAND_SIGNED) == 0 && ! warn_unsigned_overflows && strstr (message, "out of range") != NULL) { /* Skip warning... */ } else if (str) { if (file == (char *) NULL) as_warn ("%s: %s", str, message); else as_warn_where (file, line, "%s: %s", str, message); } else { if (file == (char *) NULL) as_warn (message); else as_warn_where (file, line, message); } } } else { if (operand->bits != 32) { long min, max; if ((operand->flags & V850_OPERAND_SIGNED) != 0) { if (! warn_signed_overflows) max = (1 << operand->bits) - 1; else max = (1 << (operand->bits - 1)) - 1; min = -(1 << (operand->bits - 1)); } else { max = (1 << operand->bits) - 1; if (! warn_unsigned_overflows) min = -(1 << (operand->bits - 1)); else min = 0; } if (val < (offsetT) min || val > (offsetT) max) { /* xgettext:c-format */ const char *err = _("operand out of range (%s not between %ld and %ld)"); char buf[100]; /* Restore min and mix to expected values for decimal ranges. */ if ((operand->flags & V850_OPERAND_SIGNED) && ! warn_signed_overflows) max = (1 << (operand->bits - 1)) - 1; if (! (operand->flags & V850_OPERAND_SIGNED) && ! warn_unsigned_overflows) min = 0; if (str) { sprintf (buf, "%s: ", str); sprint_value (buf + strlen (buf), val); } else sprint_value (buf, val); if (file == (char *) NULL) as_warn (err, buf, min, max); else as_warn_where (file, line, err, buf, min, max); } } insn |= (((long) val & ((1 << operand->bits) - 1)) << operand->shift); } return insn;}static char copy_of_instruction[128];voidmd_assemble (str) char *str;{ char *s; char *start_of_operands; struct v850_opcode *opcode; struct v850_opcode *next_opcode; const unsigned char *opindex_ptr; int next_opindex; int relaxable = 0; unsigned long insn; unsigned long insn_size; char *f; int i; int match; boolean extra_data_after_insn = false; unsigned extra_data_len = 0; unsigned long extra_data = 0; char *saved_input_line_pointer; strncpy (copy_of_instruction, str, sizeof (copy_of_instruction) - 1); /* Get the opcode. */ for (s = str; *s != '\0' && ! isspace (*s); s++) continue; if (*s != '\0') *s++ = '\0'; /* Find the first opcode with the proper name. */ opcode = (struct v850_opcode *) hash_find (v850_hash, str); if (opcode == NULL) { /* xgettext:c-format */ as_bad (_("Unrecognized opcode: `%s'"), str); ignore_rest_of_line (); return; } str = s; while (isspace (*str)) ++str; start_of_operands = str; saved_input_line_pointer = input_line_pointer; for (;;) { const char *errmsg = NULL; match = 0; if ((opcode->processors & processor_mask) == 0) { errmsg = _("Target processor does not support this instruction."); goto error; } relaxable = 0; fc = 0; next_opindex = 0; insn = opcode->opcode; extra_data_after_insn = false; input_line_pointer = str = start_of_operands; for (opindex_ptr = opcode->operands; *opindex_ptr != 0; opindex_ptr++) { const struct v850_operand *operand; char *hold; expressionS ex; bfd_reloc_code_real_type reloc; if (next_opindex == 0) { operand = &v850_operands[*opindex_ptr]; } else { operand = &v850_operands[next_opindex]; next_opindex = 0; } errmsg = NULL; while (*str == ' ' || *str == ',' || *str == '[' || *str == ']') ++str; if (operand->flags & V850_OPERAND_RELAX) relaxable = 1; /* Gather the operand. */ hold = input_line_pointer; input_line_pointer = str; /* lo(), hi(), hi0(), etc... */ if ((reloc = v850_reloc_prefix (operand)) != BFD_RELOC_UNUSED) { /* This is a fake reloc, used to indicate an error condition. */ if (reloc == BFD_RELOC_64) { match = 1; goto error; } expression (&ex); if (ex.X_op == O_constant) { switch (reloc) { case BFD_RELOC_V850_ZDA_16_16_OFFSET: /* To cope with "not1 7, zdaoff(0xfffff006)[r0]" and the like. */ /* Fall through. */ case BFD_RELOC_LO16: { /* Truncate, then sign extend the value. */ ex.X_add_number = SEXT16 (ex.X_add_number); break; } case BFD_RELOC_HI16: { /* Truncate, then sign extend the value. */ ex.X_add_number = SEXT16 (ex.X_add_number >> 16); break; } case BFD_RELOC_HI16_S: { /* Truncate, then sign extend the value. */ int temp = (ex.X_add_number >> 16) & 0xffff; temp += (ex.X_add_number >> 15) & 1; ex.X_add_number = SEXT16 (temp); break; } case BFD_RELOC_32: if ((operand->flags & V850E_IMMEDIATE32) == 0) { errmsg = _("immediate operand is too large"); goto error; } extra_data_after_insn = true; extra_data_len = 4; extra_data = ex.X_add_number; ex.X_add_number = 0; break; default: fprintf (stderr, "reloc: %d\n", reloc); as_bad (_("AAARG -> unhandled constant reloc")); break; } if (fc > MAX_INSN_FIXUPS) as_fatal (_("too many fixups")); fixups[fc].exp = ex; fixups[fc].opindex = *opindex_ptr; fixups[fc].reloc = reloc; fc++; } else { if (reloc == BFD_RELOC_32) { if ((operand->flags & V850E_IMMEDIATE32) == 0) { errmsg = _("immediate operand is too large"); goto error; } extra_data_after_insn = true; extra_data_len = 4; extra_data = ex.X_add_number; } if (fc > MAX_INSN_FIXUPS) as_fatal (_("too many fixups")); fixups[fc].exp = ex; fixups[fc].opindex = *opindex_ptr; fixups[fc].reloc = reloc; fc++; } } else { errmsg = NULL; if ((operand->flags & V850_OPERAND_REG) != 0) { if (!register_name (&ex)) { errmsg = _("invalid register name"); } else if ((operand->flags & V850_NOT_R0) && ex.X_add_number == 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -