diff options
author | Jing Yu <jingyu@google.com> | 2011-01-30 22:09:54 -0800 |
---|---|---|
committer | Jing Yu <jingyu@google.com> | 2011-01-30 22:09:54 -0800 |
commit | a9a8b9e7e4aee6a3846ba62703283d10849bc0a6 (patch) | |
tree | bfd550c5e600ab0c227d3615fb5183127604870d /binutils-2.20.1/gas/config/tc-ip2k.c | |
parent | 8a5a8339de3149b7f99caf08e9cb72467d60cd01 (diff) | |
download | toolchain_binutils-a9a8b9e7e4aee6a3846ba62703283d10849bc0a6.zip toolchain_binutils-a9a8b9e7e4aee6a3846ba62703283d10849bc0a6.tar.gz toolchain_binutils-a9a8b9e7e4aee6a3846ba62703283d10849bc0a6.tar.bz2 |
Upgrade binutils and gold.
upgrade binutils-2.19 to binutils-2.20.1
upgrade gold to a relatively new version binutils-20100303
Before, both binutils and gold were built from binutils-2.19.
Now binutils will be built from binutils-2.20.1 and gold will
be built from binutils-20100303.
Change-Id: Ibd0130756723337d2b4783d5b1d5e5b02a1adc83
Diffstat (limited to 'binutils-2.20.1/gas/config/tc-ip2k.c')
-rw-r--r-- | binutils-2.20.1/gas/config/tc-ip2k.c | 427 |
1 files changed, 427 insertions, 0 deletions
diff --git a/binutils-2.20.1/gas/config/tc-ip2k.c b/binutils-2.20.1/gas/config/tc-ip2k.c new file mode 100644 index 0000000..3836cc9 --- /dev/null +++ b/binutils-2.20.1/gas/config/tc-ip2k.c @@ -0,0 +1,427 @@ +/* tc-ip2k.c -- Assembler for the Scenix IP2xxx. + Copyright (C) 2000, 2002, 2003, 2005, 2006, 2007, 2009 + Free Software Foundation. Inc. + + This file is part of GAS, the GNU Assembler. + + GAS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GAS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GAS; see the file COPYING. If not, write to + the Free Software Foundation, 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#include "as.h" +#include "subsegs.h" +#include "symcat.h" +#include "opcodes/ip2k-desc.h" +#include "opcodes/ip2k-opc.h" +#include "cgen.h" +#include "elf/common.h" +#include "elf/ip2k.h" +#include "libbfd.h" + +/* Structure to hold all of the different components describing + an individual instruction. */ +typedef struct +{ + const CGEN_INSN * insn; + const CGEN_INSN * orig_insn; + CGEN_FIELDS fields; +#if CGEN_INT_INSN_P + CGEN_INSN_INT buffer [1]; +#define INSN_VALUE(buf) (*(buf)) +#else + unsigned char buffer [CGEN_MAX_INSN_SIZE]; +#define INSN_VALUE(buf) (buf) +#endif + char * addr; + fragS * frag; + int num_fixups; + fixS * fixups [GAS_CGEN_MAX_FIXUPS]; + int indices [MAX_OPERAND_INSTANCES]; +} +ip2k_insn; + +const char comment_chars[] = ";"; +const char line_comment_chars[] = "#"; +const char line_separator_chars[] = ""; +const char EXP_CHARS[] = "eE"; +const char FLT_CHARS[] = "dD"; + +/* Flag to detect when switching to code section where insn alignment is + implied. */ +static int force_code_align = 0; + +/* Mach selected from command line. */ +static int ip2k_mach = 0; +static unsigned ip2k_mach_bitmask = 0; + + +static void +ip2k_elf_section_rtn (int i) +{ + obj_elf_section(i); + + if (force_code_align) + { + /* The s_align_ptwo function expects that we are just after a .align + directive and it will either try and read the align value or stop + if end of line so we must fake it out so it thinks we are at the + end of the line. */ + char *old_input_line_pointer = input_line_pointer; + input_line_pointer = "\n"; + s_align_ptwo (1); + force_code_align = 0; + /* Restore. */ + input_line_pointer = old_input_line_pointer; + } +} + +static void +ip2k_elf_section_text (int i) +{ + char *old_input_line_pointer; + obj_elf_text(i); + + /* the s_align_ptwo function expects that we are just after a .align + directive and it will either try and read the align value or stop if + end of line so we must fake it out so it thinks we are at the end of + the line. */ + old_input_line_pointer = input_line_pointer; + input_line_pointer = "\n"; + s_align_ptwo (1); + force_code_align = 0; + /* Restore. */ + input_line_pointer = old_input_line_pointer; +} + +/* The target specific pseudo-ops which we support. */ +const pseudo_typeS md_pseudo_table[] = +{ + { "text", ip2k_elf_section_text, 0 }, + { "sect", ip2k_elf_section_rtn, 0 }, + { NULL, NULL, 0 } +}; + + + +enum options +{ + OPTION_CPU_IP2022 = OPTION_MD_BASE, + OPTION_CPU_IP2022EXT +}; + +struct option md_longopts[] = +{ + { "mip2022", no_argument, NULL, OPTION_CPU_IP2022 }, + { "mip2022ext", no_argument, NULL, OPTION_CPU_IP2022EXT }, + { NULL, no_argument, NULL, 0 }, +}; +size_t md_longopts_size = sizeof (md_longopts); + +const char * md_shortopts = ""; + +int +md_parse_option (int c ATTRIBUTE_UNUSED, char * arg ATTRIBUTE_UNUSED) +{ + switch (c) + { + case OPTION_CPU_IP2022: + ip2k_mach = bfd_mach_ip2022; + ip2k_mach_bitmask = 1 << MACH_IP2022; + break; + + case OPTION_CPU_IP2022EXT: + ip2k_mach = bfd_mach_ip2022ext; + ip2k_mach_bitmask = 1 << MACH_IP2022EXT; + break; + + default: + return 0; + } + + return 1; +} + +void +md_show_usage (FILE * stream) +{ + fprintf (stream, _("IP2K specific command line options:\n")); + fprintf (stream, _(" -mip2022 restrict to IP2022 insns \n")); + fprintf (stream, _(" -mip2022ext permit extended IP2022 insn\n")); +} + + +void +md_begin (void) +{ + /* Initialize the `cgen' interface. */ + + /* Set the machine number and endian. */ + gas_cgen_cpu_desc = ip2k_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, + ip2k_mach_bitmask, + CGEN_CPU_OPEN_ENDIAN, + CGEN_ENDIAN_BIG, + CGEN_CPU_OPEN_END); + ip2k_cgen_init_asm (gas_cgen_cpu_desc); + + /* This is a callback from cgen to gas to parse operands. */ + cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand); + + /* Set the machine type. */ + bfd_default_set_arch_mach (stdoutput, bfd_arch_ip2k, ip2k_mach); +} + + +void +md_assemble (char * str) +{ + ip2k_insn insn; + char * errmsg; + + /* Initialize GAS's cgen interface for a new instruction. */ + gas_cgen_init_parse (); + + insn.insn = ip2k_cgen_assemble_insn + (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, & errmsg); + + if (!insn.insn) + { + as_bad ("%s", errmsg); + return; + } + + /* Check for special relocation required by SKIP instructions. */ + if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_SKIPA)) + /* Unconditional skip has a 1-bit relocation of the current pc, so + that we emit either sb pcl.0 or snb pcl.0 depending on whether + the PCL (pc + 2) >> 1 is odd or even. */ + { + enum cgen_parse_operand_result result_type; + bfd_vma value; + const char *curpc_plus_2 = ".+2"; + const char *err; + + err = cgen_parse_address (gas_cgen_cpu_desc, & curpc_plus_2, + IP2K_OPERAND_ADDR16CJP, + BFD_RELOC_IP2K_PC_SKIP, + & result_type, & value); + if (err) + { + as_bad ("%s", err); + return; + } + } + + /* Doesn't really matter what we pass for RELAX_P here. */ + gas_cgen_finish_insn (insn.insn, insn.buffer, + CGEN_FIELDS_BITSIZE (& insn.fields), 1, NULL); +} + +valueT +md_section_align (segT segment, valueT size) +{ + int align = bfd_get_section_alignment (stdoutput, segment); + + return ((size + (1 << align) - 1) & (-1 << align)); +} + + +symbolS * +md_undefined_symbol (char * name ATTRIBUTE_UNUSED) +{ + return 0; +} + +int +md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED, + segT segment ATTRIBUTE_UNUSED) +{ + as_fatal (_("relaxation not supported\n")); + return 1; +} + + +/* *fragP has been relaxed to its final size, and now needs to have + the bytes inside it modified to conform to the new size. + + Called after relaxation is finished. + fragP->fr_type == rs_machine_dependent. + fragP->fr_subtype is the subtype of what the address relaxed to. */ + +void +md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, + segT sec ATTRIBUTE_UNUSED, + fragS * fragP ATTRIBUTE_UNUSED) +{ +} + + +/* Functions concerning relocs. */ + +long +md_pcrel_from (fixS *fixP ATTRIBUTE_UNUSED) +{ + abort (); +} + + +/* Return the bfd reloc type for OPERAND of INSN at fixup FIXP. + Returns BFD_RELOC_NONE if no reloc type can be found. + *FIXP may be modified if desired. */ + +bfd_reloc_code_real_type +md_cgen_lookup_reloc (const CGEN_INSN * insn ATTRIBUTE_UNUSED, + const CGEN_OPERAND * operand, + fixS * fixP ATTRIBUTE_UNUSED) +{ + bfd_reloc_code_real_type result; + + result = BFD_RELOC_NONE; + + switch (operand->type) + { + case IP2K_OPERAND_FR: + case IP2K_OPERAND_ADDR16L: + case IP2K_OPERAND_ADDR16H: + case IP2K_OPERAND_LIT8: + /* These may have been processed at parse time. */ + if (fixP->fx_cgen.opinfo != 0) + result = fixP->fx_cgen.opinfo; + fixP->fx_no_overflow = 1; + break; + + case IP2K_OPERAND_ADDR16CJP: + result = fixP->fx_cgen.opinfo; + if (result == 0 || result == BFD_RELOC_NONE) + result = BFD_RELOC_IP2K_ADDR16CJP; + fixP->fx_no_overflow = 1; + break; + + case IP2K_OPERAND_ADDR16P: + result = BFD_RELOC_IP2K_PAGE3; + fixP->fx_no_overflow = 1; + break; + + default: + result = BFD_RELOC_NONE; + break; + } + + return result; +} + + +/* Write a value out to the object file, using the appropriate endianness. */ + +void +md_number_to_chars (char * buf, valueT val, int n) +{ + number_to_chars_bigendian (buf, val, n); +} + +char * +md_atof (int type, char * litP, int * sizeP) +{ + return ieee_md_atof (type, litP, sizeP, TRUE); +} + + +/* See whether we need to force a relocation into the output file. + Force most of them, since the linker's bfd relocation engine + understands range limits better than gas' cgen fixup engine. + Consider the case of a fixup intermediate value being larger than + the instruction it will be eventually encoded within. */ + +int +ip2k_force_relocation (fixS * fix) +{ + switch (fix->fx_r_type) + { + case BFD_RELOC_IP2K_FR9: + case BFD_RELOC_IP2K_FR_OFFSET: + case BFD_RELOC_IP2K_BANK: + case BFD_RELOC_IP2K_ADDR16CJP: + case BFD_RELOC_IP2K_PAGE3: + case BFD_RELOC_IP2K_LO8DATA: + case BFD_RELOC_IP2K_HI8DATA: + case BFD_RELOC_IP2K_EX8DATA: + case BFD_RELOC_IP2K_LO8INSN: + case BFD_RELOC_IP2K_HI8INSN: + case BFD_RELOC_IP2K_PC_SKIP: + case BFD_RELOC_IP2K_TEXT: + return 1; + + case BFD_RELOC_16: + if (fix->fx_subsy && S_IS_DEFINED (fix->fx_subsy) + && fix->fx_addsy && S_IS_DEFINED (fix->fx_addsy) + && (S_GET_SEGMENT (fix->fx_addsy)->flags & SEC_CODE)) + { + fix->fx_r_type = BFD_RELOC_IP2K_TEXT; + return 0; + } + break; + + default: + break; + } + + return generic_force_reloc (fix); +} + +void +ip2k_apply_fix (fixS *fixP, valueT *valueP, segT seg) +{ + if (fixP->fx_r_type == BFD_RELOC_IP2K_TEXT + && ! fixP->fx_addsy + && ! fixP->fx_subsy) + { + *valueP = ((int)(* valueP)) / 2; + fixP->fx_r_type = BFD_RELOC_16; + } + else if (fixP->fx_r_type == BFD_RELOC_UNUSED + IP2K_OPERAND_FR) + { + /* Must be careful when we are fixing up an FR. We could be + fixing up an offset to (SP) or (DP) in which case we don't + want to step on the top 2 bits of the FR operand. The + gas_cgen_md_apply_fix doesn't know any better and overwrites + the entire operand. We counter this by adding the bits + to the new value. */ + char *where = fixP->fx_frag->fr_literal + fixP->fx_where; + + /* Canonical name, since used a lot. */ + CGEN_CPU_DESC cd = gas_cgen_cpu_desc; + CGEN_INSN_INT insn_value + = cgen_get_insn_value (cd, (unsigned char *) where, + CGEN_INSN_BITSIZE (fixP->fx_cgen.insn)); + /* Preserve (DP) or (SP) specification. */ + *valueP += (insn_value & 0x180); + } + + gas_cgen_md_apply_fix (fixP, valueP, seg); +} + +int +ip2k_elf_section_flags (flagword flags, + bfd_vma attr ATTRIBUTE_UNUSED, + int type ATTRIBUTE_UNUSED) +{ + /* This is used to detect when the section changes to an executable section. + This function is called by the elf section processing. When we note an + executable section specifier we set an internal flag to denote when + word alignment should be forced. */ + if (flags & SEC_CODE) + force_code_align = 1; + + return flags; +} + |