From 2cafa61b4b039e5ac3b876fc44a05c61d66df4d4 Mon Sep 17 00:00:00 2001 From: Jing Yu Date: Thu, 5 Nov 2009 16:55:30 -0800 Subject: check in binutils sources for prebuilt toolchains in Eclair. --- binutils-2.17/gas/config/tc-openrisc.c | 403 +++++++++++++++++++++++++++++++++ 1 file changed, 403 insertions(+) create mode 100644 binutils-2.17/gas/config/tc-openrisc.c (limited to 'binutils-2.17/gas/config/tc-openrisc.c') diff --git a/binutils-2.17/gas/config/tc-openrisc.c b/binutils-2.17/gas/config/tc-openrisc.c new file mode 100644 index 00000000..50597a7f --- /dev/null +++ b/binutils-2.17/gas/config/tc-openrisc.c @@ -0,0 +1,403 @@ +/* tc-openrisc.c -- Assembler for the OpenRISC family. + Copyright 2001, 2002, 2003, 2005 Free Software Foundation. + Contributed by Johan Rydberg, jrydberg@opencores.org + + 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 2, 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 +#include "as.h" +#include "subsegs.h" +#include "symcat.h" +#include "opcodes/openrisc-desc.h" +#include "opcodes/openrisc-opc.h" +#include "cgen.h" + +/* Structure to hold all of the different components describing + an individual instruction. */ +typedef struct openrisc_insn openrisc_insn; + +struct openrisc_insn +{ + 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]; +}; + + +const char comment_chars[] = "#"; +const char line_comment_chars[] = "#"; +const char line_separator_chars[] = ";"; +const char EXP_CHARS[] = "eE"; +const char FLT_CHARS[] = "dD"; + + +#define OPENRISC_SHORTOPTS "m:" +const char * md_shortopts = OPENRISC_SHORTOPTS; + +struct option md_longopts[] = +{ + {NULL, no_argument, NULL, 0} +}; +size_t md_longopts_size = sizeof (md_longopts); + +unsigned long openrisc_machine = 0; /* default */ + +int +md_parse_option (int c ATTRIBUTE_UNUSED, char * arg ATTRIBUTE_UNUSED) +{ + return 0; +} + +void +md_show_usage (FILE * stream ATTRIBUTE_UNUSED) +{ +} + +static void +ignore_pseudo (int val ATTRIBUTE_UNUSED) +{ + discard_rest_of_line (); +} + +const char openrisc_comment_chars [] = ";#"; + +/* The target specific pseudo-ops which we support. */ +const pseudo_typeS md_pseudo_table[] = +{ + { "word", cons, 4 }, + { "proc", ignore_pseudo, 0 }, + { "endproc", ignore_pseudo, 0 }, + { NULL, NULL, 0 } +}; + + + +void +md_begin (void) +{ + /* Initialize the `cgen' interface. */ + + /* Set the machine number and endian. */ + gas_cgen_cpu_desc = openrisc_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, 0, + CGEN_CPU_OPEN_ENDIAN, + CGEN_ENDIAN_BIG, + CGEN_CPU_OPEN_END); + openrisc_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); +} + +void +md_assemble (char * str) +{ + static int last_insn_had_delay_slot = 0; + openrisc_insn insn; + char * errmsg; + + /* Initialize GAS's cgen interface for a new instruction. */ + gas_cgen_init_parse (); + + insn.insn = openrisc_cgen_assemble_insn + (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, & errmsg); + + if (!insn.insn) + { + as_bad (errmsg); + 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); + + last_insn_had_delay_slot + = CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_DELAY_SLOT); +} + + +/* The syntax in the manual says constants begin with '#'. + We just ignore it. */ + +void +md_operand (expressionS * expressionP) +{ + if (* input_line_pointer == '#') + { + input_line_pointer ++; + expression (expressionP); + } +} + +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; +} + + +/* Interface to relax_segment. */ + +/* FIXME: Look through this. */ + +const relax_typeS md_relax_table[] = +{ +/* The fields are: + 1) most positive reach of this state, + 2) most negative reach of this state, + 3) how many bytes this mode will add to the size of the current frag + 4) which index into the table to try if we can't fit into this one. */ + + /* The first entry must be unused because an `rlx_more' value of zero ends + each list. */ + {1, 1, 0, 0}, + + /* The displacement used by GAS is from the end of the 2 byte insn, + so we subtract 2 from the following. */ + /* 16 bit insn, 8 bit disp -> 10 bit range. + This doesn't handle a branch in the right slot at the border: + the "& -4" isn't taken into account. It's not important enough to + complicate things over it, so we subtract an extra 2 (or + 2 in -ve + case). */ + {511 - 2 - 2, -512 - 2 + 2, 0, 2 }, + /* 32 bit insn, 24 bit disp -> 26 bit range. */ + {0x2000000 - 1 - 2, -0x2000000 - 2, 2, 0 }, + /* Same thing, but with leading nop for alignment. */ + {0x2000000 - 1 - 2, -0x2000000 - 2, 4, 0 } +}; + +/* Return an initial guess of the length by which a fragment must grow to + hold a branch to reach its destination. + Also updates fr_type/fr_subtype as necessary. + + Called just before doing relaxation. + Any symbol that is now undefined will not become defined. + The guess for fr_var is ACTUALLY the growth beyond fr_fix. + Whatever we do to grow fr_fix or fr_var contributes to our returned value. + Although it may not be explicit in the frag, pretend fr_var starts with a + 0 value. */ + +int +md_estimate_size_before_relax (fragS * fragP, segT segment) +{ + /* The only thing we have to handle here are symbols outside of the + current segment. They may be undefined or in a different segment in + which case linker scripts may place them anywhere. + However, we can't finish the fragment here and emit the reloc as insn + alignment requirements may move the insn about. */ + + if (S_GET_SEGMENT (fragP->fr_symbol) != segment) + { + /* The symbol is undefined in this segment. + Change the relaxation subtype to the max allowable and leave + all further handling to md_convert_frag. */ + fragP->fr_subtype = 2; + + { + const CGEN_INSN * insn; + int i; + + /* Update the recorded insn. + Fortunately we don't have to look very far. + FIXME: Change this to record in the instruction the next higher + relaxable insn to use. */ + for (i = 0, insn = fragP->fr_cgen.insn; i < 4; i++, insn++) + { + if ((strcmp (CGEN_INSN_MNEMONIC (insn), + CGEN_INSN_MNEMONIC (fragP->fr_cgen.insn)) + == 0) + && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED)) + break; + } + if (i == 4) + abort (); + + fragP->fr_cgen.insn = insn; + return 2; + } + } + + return md_relax_table[fragP->fr_subtype].rlx_length; +} + +/* *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) +{ + /* FIXME */ +} + + +/* Functions concerning relocs. */ + +/* The location from which a PC relative jump should be calculated, + given a PC relative reloc. */ + +long +md_pcrel_from_section (fixS * fixP, segT sec) +{ + if (fixP->fx_addsy != (symbolS *) NULL + && (! S_IS_DEFINED (fixP->fx_addsy) + || S_GET_SEGMENT (fixP->fx_addsy) != sec)) + /* The symbol is undefined (or is defined but not in this section). + Let the linker figure it out. */ + return 0; + + return (fixP->fx_frag->fr_address + fixP->fx_where) & ~1; +} + + +/* 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) +{ + bfd_reloc_code_real_type type; + + switch (operand->type) + { + case OPENRISC_OPERAND_ABS_26: + fixP->fx_pcrel = 0; + type = BFD_RELOC_OPENRISC_ABS_26; + goto emit; + case OPENRISC_OPERAND_DISP_26: + fixP->fx_pcrel = 1; + type = BFD_RELOC_OPENRISC_REL_26; + goto emit; + + case OPENRISC_OPERAND_HI16: + type = BFD_RELOC_HI16; + goto emit; + + case OPENRISC_OPERAND_LO16: + type = BFD_RELOC_LO16; + goto emit; + + emit: + return type; + + default : /* avoid -Wall warning */ + break; + } + + return BFD_RELOC_NONE; +} + +/* 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); +} + +/* Turn a string in input_line_pointer into a floating point constant of type + type, and store the appropriate bytes in *litP. The number of LITTLENUMS + emitted is stored in *sizeP . An error message is returned, or NULL on OK. +*/ + +/* Equal to MAX_PRECISION in atof-ieee.c */ +#define MAX_LITTLENUMS 6 + +char * +md_atof (int type, char * litP, int * sizeP) +{ + int i; + int prec; + LITTLENUM_TYPE words [MAX_LITTLENUMS]; + char * t; + + switch (type) + { + case 'f': + case 'F': + case 's': + case 'S': + prec = 2; + break; + + case 'd': + case 'D': + case 'r': + case 'R': + prec = 4; + break; + + /* FIXME: Some targets allow other format chars for bigger sizes here. */ + + 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 * sizeof (LITTLENUM_TYPE); + + for (i = 0; i < prec; i++) + { + md_number_to_chars (litP, (valueT) words[i], + sizeof (LITTLENUM_TYPE)); + litP += sizeof (LITTLENUM_TYPE); + } + + return 0; +} + +bfd_boolean +openrisc_fix_adjustable (fixS * fixP) +{ + /* We need the symbol name for the VTABLE entries. */ + if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT + || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY) + return 0; + + return 1; +} -- cgit v1.2.3