Home | History | Annotate | Line # | Download | only in config
tc-mt.c revision 1.1
      1  1.1  skrll /* tc-mt.c -- Assembler for the Morpho Technologies mt .
      2  1.1  skrll    Copyright (C) 2005, 2006, 2007 Free Software Foundation.
      3  1.1  skrll 
      4  1.1  skrll    This file is part of GAS, the GNU Assembler.
      5  1.1  skrll 
      6  1.1  skrll    GAS is free software; you can redistribute it and/or modify
      7  1.1  skrll    it under the terms of the GNU General Public License as published by
      8  1.1  skrll    the Free Software Foundation; either version 3, or (at your option)
      9  1.1  skrll    any later version.
     10  1.1  skrll 
     11  1.1  skrll    GAS is distributed in the hope that it will be useful,
     12  1.1  skrll    but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  1.1  skrll    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14  1.1  skrll    GNU General Public License for more details.
     15  1.1  skrll 
     16  1.1  skrll    You should have received a copy of the GNU General Public License
     17  1.1  skrll    along with GAS; see the file COPYING.  If not, write to
     18  1.1  skrll    the Free Software Foundation, 59 Temple Place - Suite 330,
     19  1.1  skrll    Boston, MA 02111-1307, USA.  */
     20  1.1  skrll 
     21  1.1  skrll #include "as.h"
     22  1.1  skrll #include "dwarf2dbg.h"
     23  1.1  skrll #include "subsegs.h"
     24  1.1  skrll #include "symcat.h"
     25  1.1  skrll #include "opcodes/mt-desc.h"
     26  1.1  skrll #include "opcodes/mt-opc.h"
     27  1.1  skrll #include "cgen.h"
     28  1.1  skrll #include "elf/common.h"
     29  1.1  skrll #include "elf/mt.h"
     30  1.1  skrll #include "libbfd.h"
     31  1.1  skrll 
     32  1.1  skrll /* Structure to hold all of the different components
     33  1.1  skrll    describing an individual instruction.  */
     34  1.1  skrll typedef struct
     35  1.1  skrll {
     36  1.1  skrll   const CGEN_INSN *	insn;
     37  1.1  skrll   const CGEN_INSN *	orig_insn;
     38  1.1  skrll   CGEN_FIELDS		fields;
     39  1.1  skrll #if CGEN_INT_INSN_P
     40  1.1  skrll   CGEN_INSN_INT         buffer [1];
     41  1.1  skrll #define INSN_VALUE(buf) (*(buf))
     42  1.1  skrll #else
     43  1.1  skrll   unsigned char         buffer [CGEN_MAX_INSN_SIZE];
     44  1.1  skrll #define INSN_VALUE(buf) (buf)
     45  1.1  skrll #endif
     46  1.1  skrll   char *		addr;
     47  1.1  skrll   fragS *		frag;
     48  1.1  skrll   int                   num_fixups;
     49  1.1  skrll   fixS *                fixups [GAS_CGEN_MAX_FIXUPS];
     50  1.1  skrll   int                   indices [MAX_OPERAND_INSTANCES];
     51  1.1  skrll }
     52  1.1  skrll mt_insn;
     53  1.1  skrll 
     54  1.1  skrll 
     55  1.1  skrll const char comment_chars[]        = ";";
     56  1.1  skrll const char line_comment_chars[]   = "#";
     57  1.1  skrll const char line_separator_chars[] = "";
     58  1.1  skrll const char EXP_CHARS[]            = "eE";
     59  1.1  skrll const char FLT_CHARS[]            = "dD";
     60  1.1  skrll 
     61  1.1  skrll /* The target specific pseudo-ops which we support.  */
     62  1.1  skrll const pseudo_typeS md_pseudo_table[] =
     63  1.1  skrll {
     64  1.1  skrll     { "word",   cons,                   4 },
     65  1.1  skrll     { NULL, 	NULL,			0 }
     66  1.1  skrll };
     67  1.1  skrll 
     68  1.1  skrll 
     69  1.1  skrll 
     71  1.1  skrll static int no_scheduling_restrictions = 0;
     72  1.1  skrll 
     73  1.1  skrll struct option md_longopts[] =
     74  1.1  skrll {
     75  1.1  skrll #define OPTION_NO_SCHED_REST	(OPTION_MD_BASE)
     76  1.1  skrll   { "nosched",	   no_argument, NULL, OPTION_NO_SCHED_REST },
     77  1.1  skrll #define OPTION_MARCH		(OPTION_MD_BASE + 1)
     78  1.1  skrll   { "march", required_argument, NULL, OPTION_MARCH},
     79  1.1  skrll   { NULL,	   no_argument, NULL, 0 },
     80  1.1  skrll };
     81  1.1  skrll size_t md_longopts_size = sizeof (md_longopts);
     82  1.1  skrll 
     83  1.1  skrll const char * md_shortopts = "";
     84  1.1  skrll 
     85  1.1  skrll /* Mach selected from command line.  */
     86  1.1  skrll static int mt_mach = bfd_mach_ms1;
     87  1.1  skrll static unsigned mt_mach_bitmask = 1 << MACH_MS1;
     88  1.1  skrll 
     89  1.1  skrll /* Flags to set in the elf header */
     90  1.1  skrll static flagword mt_flags = EF_MT_CPU_MRISC;
     91  1.1  skrll 
     92  1.1  skrll /* The architecture to use.  */
     93  1.1  skrll enum mt_architectures
     94  1.1  skrll   {
     95  1.1  skrll     ms1_64_001,
     96  1.1  skrll     ms1_16_002,
     97  1.1  skrll     ms1_16_003,
     98  1.1  skrll     ms2
     99  1.1  skrll   };
    100  1.1  skrll 
    101  1.1  skrll /* MT architecture we are using for this output file.  */
    102  1.1  skrll static enum mt_architectures mt_arch = ms1_16_002;
    103  1.1  skrll 
    104  1.1  skrll int
    105  1.1  skrll md_parse_option (int c ATTRIBUTE_UNUSED, char * arg)
    106  1.1  skrll {
    107  1.1  skrll   switch (c)
    108  1.1  skrll     {
    109  1.1  skrll     case OPTION_MARCH:
    110  1.1  skrll       if (strcmp (arg, "ms1-64-001") == 0)
    111  1.1  skrll  	{
    112  1.1  skrll  	  mt_flags = (mt_flags & ~EF_MT_CPU_MASK) | EF_MT_CPU_MRISC;
    113  1.1  skrll  	  mt_mach = bfd_mach_ms1;
    114  1.1  skrll  	  mt_mach_bitmask = 1 << MACH_MS1;
    115  1.1  skrll  	  mt_arch = ms1_64_001;
    116  1.1  skrll  	}
    117  1.1  skrll       else if (strcmp (arg, "ms1-16-002") == 0)
    118  1.1  skrll  	{
    119  1.1  skrll  	  mt_flags = (mt_flags & ~EF_MT_CPU_MASK) | EF_MT_CPU_MRISC;
    120  1.1  skrll  	  mt_mach = bfd_mach_ms1;
    121  1.1  skrll  	  mt_mach_bitmask = 1 << MACH_MS1;
    122  1.1  skrll  	  mt_arch = ms1_16_002;
    123  1.1  skrll  	}
    124  1.1  skrll       else if (strcmp (arg, "ms1-16-003") == 0)
    125  1.1  skrll  	{
    126  1.1  skrll  	  mt_flags = (mt_flags & ~EF_MT_CPU_MASK) | EF_MT_CPU_MRISC2;
    127  1.1  skrll  	  mt_mach = bfd_mach_mrisc2;
    128  1.1  skrll  	  mt_mach_bitmask = 1 << MACH_MS1_003;
    129  1.1  skrll  	  mt_arch = ms1_16_003;
    130  1.1  skrll  	}
    131  1.1  skrll       else if (strcmp (arg, "ms2") == 0)
    132  1.1  skrll  	{
    133  1.1  skrll  	  mt_flags = (mt_flags & ~EF_MT_CPU_MASK) | EF_MT_CPU_MS2;
    134  1.1  skrll  	  mt_mach = bfd_mach_mrisc2;
    135  1.1  skrll  	  mt_mach_bitmask = 1 << MACH_MS2;
    136  1.1  skrll  	  mt_arch = ms2;
    137  1.1  skrll  	}
    138  1.1  skrll     case OPTION_NO_SCHED_REST:
    139  1.1  skrll       no_scheduling_restrictions = 1;
    140  1.1  skrll       break;
    141  1.1  skrll     default:
    142  1.1  skrll       return 0;
    143  1.1  skrll     }
    144  1.1  skrll 
    145  1.1  skrll   return 1;
    146  1.1  skrll }
    147  1.1  skrll 
    148  1.1  skrll 
    149  1.1  skrll void
    150  1.1  skrll md_show_usage (FILE * stream)
    151  1.1  skrll {
    152  1.1  skrll   fprintf (stream, _("MT specific command line options:\n"));
    153  1.1  skrll   fprintf (stream, _("  -march=ms1-64-001         allow ms1-64-001 instructions\n"));
    154  1.1  skrll   fprintf (stream, _("  -march=ms1-16-002         allow ms1-16-002 instructions (default)\n"));
    155  1.1  skrll   fprintf (stream, _("  -march=ms1-16-003         allow ms1-16-003 instructions\n"));
    156  1.1  skrll   fprintf (stream, _("  -march=ms2                allow ms2 instructions \n"));
    157  1.1  skrll   fprintf (stream, _("  -nosched                  disable scheduling restrictions\n"));
    158  1.1  skrll }
    159  1.1  skrll 
    160  1.1  skrll 
    161  1.1  skrll void
    163  1.1  skrll md_begin (void)
    164  1.1  skrll {
    165  1.1  skrll   /* Initialize the `cgen' interface.  */
    166  1.1  skrll 
    167  1.1  skrll   /* Set the machine number and endian.  */
    168  1.1  skrll   gas_cgen_cpu_desc = mt_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, mt_mach_bitmask,
    169  1.1  skrll 					CGEN_CPU_OPEN_ENDIAN,
    170  1.1  skrll 					CGEN_ENDIAN_BIG,
    171  1.1  skrll 					CGEN_CPU_OPEN_END);
    172  1.1  skrll   mt_cgen_init_asm (gas_cgen_cpu_desc);
    173  1.1  skrll 
    174  1.1  skrll   /* This is a callback from cgen to gas to parse operands.  */
    175  1.1  skrll   cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand);
    176  1.1  skrll 
    177  1.1  skrll   /* Set the ELF flags if desired. */
    178  1.1  skrll   if (mt_flags)
    179  1.1  skrll     bfd_set_private_flags (stdoutput, mt_flags);
    180  1.1  skrll 
    181  1.1  skrll   /* Set the machine type.  */
    182  1.1  skrll   bfd_default_set_arch_mach (stdoutput, bfd_arch_mt, mt_mach);
    183  1.1  skrll }
    184  1.1  skrll 
    185  1.1  skrll void
    186  1.1  skrll md_assemble (char * str)
    187  1.1  skrll {
    188  1.1  skrll   static long delayed_load_register = 0;
    189  1.1  skrll   static long prev_delayed_load_register = 0;
    190  1.1  skrll   static int last_insn_had_delay_slot = 0;
    191  1.1  skrll   static int last_insn_in_noncond_delay_slot = 0;
    192  1.1  skrll   static int last_insn_has_load_delay = 0;
    193  1.1  skrll   static int last_insn_was_memory_access = 0;
    194  1.1  skrll   static int last_insn_was_io_insn = 0;
    195  1.1  skrll   static int last_insn_was_arithmetic_or_logic = 0;
    196  1.1  skrll   static int last_insn_was_branch_insn = 0;
    197  1.1  skrll   static int last_insn_was_conditional_branch_insn = 0;
    198  1.1  skrll 
    199  1.1  skrll   mt_insn insn;
    200  1.1  skrll   char * errmsg;
    201  1.1  skrll 
    202  1.1  skrll   /* Initialize GAS's cgen interface for a new instruction.  */
    203  1.1  skrll   gas_cgen_init_parse ();
    204  1.1  skrll 
    205  1.1  skrll   insn.insn = mt_cgen_assemble_insn
    206  1.1  skrll       (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, & errmsg);
    207  1.1  skrll 
    208  1.1  skrll   if (!insn.insn)
    209  1.1  skrll     {
    210  1.1  skrll       as_bad ("%s", errmsg);
    211  1.1  skrll       return;
    212  1.1  skrll     }
    213  1.1  skrll 
    214  1.1  skrll   /* Doesn't really matter what we pass for RELAX_P here.  */
    215  1.1  skrll   gas_cgen_finish_insn (insn.insn, insn.buffer,
    216  1.1  skrll 			CGEN_FIELDS_BITSIZE (& insn.fields), 1, NULL);
    217  1.1  skrll 
    218  1.1  skrll 
    219  1.1  skrll   /* Handle Scheduling Restrictions.  */
    220  1.1  skrll   if (!no_scheduling_restrictions)
    221  1.1  skrll     {
    222  1.1  skrll       /* Detect consecutive Memory Accesses.  */
    223  1.1  skrll       if (last_insn_was_memory_access
    224  1.1  skrll 	  && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_MEMORY_ACCESS)
    225  1.1  skrll 	  && mt_mach == ms1_64_001)
    226  1.1  skrll 	as_warn (_("instruction %s may not follow another memory access instruction."),
    227  1.1  skrll 		 CGEN_INSN_NAME (insn.insn));
    228  1.1  skrll 
    229  1.1  skrll       /* Detect consecutive I/O Instructions.  */
    230  1.1  skrll       else if (last_insn_was_io_insn
    231  1.1  skrll 	       && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_IO_INSN))
    232  1.1  skrll 	as_warn (_("instruction %s may not follow another I/O instruction."),
    233  1.1  skrll 		 CGEN_INSN_NAME (insn.insn));
    234  1.1  skrll 
    235  1.1  skrll       /* Detect consecutive branch instructions.  */
    236  1.1  skrll       else if (last_insn_was_branch_insn
    237  1.1  skrll 	       && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_BR_INSN))
    238  1.1  skrll 	as_warn (_("%s may not occupy the delay slot of another branch insn."),
    239  1.1  skrll 		 CGEN_INSN_NAME (insn.insn));
    240  1.1  skrll 
    241  1.1  skrll       /* Detect data dependencies on delayed loads: memory and input insns.  */
    242  1.1  skrll       if (last_insn_has_load_delay && delayed_load_register)
    243  1.1  skrll 	{
    244  1.1  skrll 	  if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR1)
    245  1.1  skrll 	      && insn.fields.f_sr1 == delayed_load_register)
    246  1.1  skrll 	    as_warn (_("operand references R%ld of previous load."),
    247  1.1  skrll 		     insn.fields.f_sr1);
    248  1.1  skrll 
    249  1.1  skrll 	  if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR2)
    250  1.1  skrll 	      && insn.fields.f_sr2 == delayed_load_register)
    251  1.1  skrll 	    as_warn (_("operand references R%ld of previous load."),
    252  1.1  skrll 		     insn.fields.f_sr2);
    253  1.1  skrll 	}
    254  1.1  skrll 
    255  1.1  skrll       /* Detect JAL/RETI hazard */
    256  1.1  skrll       if (mt_mach == ms2
    257  1.1  skrll 	  && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_JAL_HAZARD))
    258  1.1  skrll 	{
    259  1.1  skrll 	  if ((CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR1)
    260  1.1  skrll 	       && insn.fields.f_sr1 == delayed_load_register)
    261  1.1  skrll 	      || (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR2)
    262  1.1  skrll 		  && insn.fields.f_sr2 == delayed_load_register))
    263  1.1  skrll 	    as_warn (_("operand references R%ld of previous instrutcion."),
    264  1.1  skrll 		     delayed_load_register);
    265  1.1  skrll 	  else if ((CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR1)
    266  1.1  skrll 		    && insn.fields.f_sr1 == prev_delayed_load_register)
    267  1.1  skrll 		   || (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR2)
    268  1.1  skrll 		       && insn.fields.f_sr2 == prev_delayed_load_register))
    269  1.1  skrll 	    as_warn (_("operand references R%ld of instructcion before previous."),
    270  1.1  skrll 		     prev_delayed_load_register);
    271  1.1  skrll 	}
    272  1.1  skrll 
    273  1.1  skrll       /* Detect data dependency between conditional branch instruction
    274  1.1  skrll          and an immediately preceding arithmetic or logical instruction.  */
    275  1.1  skrll       if (last_insn_was_arithmetic_or_logic
    276  1.1  skrll 	  && !last_insn_in_noncond_delay_slot
    277  1.1  skrll 	  && (delayed_load_register != 0)
    278  1.1  skrll 	  && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_BR_INSN)
    279  1.1  skrll 	  && mt_arch == ms1_64_001)
    280  1.1  skrll 	{
    281  1.1  skrll 	  if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR1)
    282  1.1  skrll 	      && insn.fields.f_sr1 == delayed_load_register)
    283  1.1  skrll 	    as_warn (_("conditional branch or jal insn's operand references R%ld of previous arithmetic or logic insn."),
    284  1.1  skrll 		     insn.fields.f_sr1);
    285  1.1  skrll 
    286  1.1  skrll 	  if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR2)
    287  1.1  skrll 	      && insn.fields.f_sr2 == delayed_load_register)
    288  1.1  skrll 	    as_warn (_("conditional branch or jal insn's operand references R%ld of previous arithmetic or logic insn."),
    289  1.1  skrll 		     insn.fields.f_sr2);
    290  1.1  skrll 	}
    291  1.1  skrll     }
    292  1.1  skrll 
    293  1.1  skrll   /* Keep track of details of this insn for processing next insn.  */
    294  1.1  skrll   last_insn_in_noncond_delay_slot = last_insn_was_branch_insn
    295  1.1  skrll     && !last_insn_was_conditional_branch_insn;
    296  1.1  skrll 
    297  1.1  skrll   last_insn_had_delay_slot =
    298  1.1  skrll     CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_DELAY_SLOT);
    299  1.1  skrll 
    300  1.1  skrll   last_insn_has_load_delay =
    301  1.1  skrll     CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_LOAD_DELAY);
    302  1.1  skrll 
    303  1.1  skrll   last_insn_was_memory_access =
    304  1.1  skrll     CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_MEMORY_ACCESS);
    305  1.1  skrll 
    306  1.1  skrll   last_insn_was_io_insn =
    307  1.1  skrll     CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_IO_INSN);
    308  1.1  skrll 
    309  1.1  skrll   last_insn_was_arithmetic_or_logic =
    310  1.1  skrll     CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_AL_INSN);
    311  1.1  skrll 
    312  1.1  skrll   last_insn_was_branch_insn =
    313  1.1  skrll     CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_BR_INSN);
    314  1.1  skrll 
    315  1.1  skrll   last_insn_was_conditional_branch_insn =
    316  1.1  skrll   CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_BR_INSN)
    317  1.1  skrll     && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR2);
    318  1.1  skrll 
    319  1.1  skrll   prev_delayed_load_register = delayed_load_register;
    320  1.1  skrll 
    321  1.1  skrll   if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRDR))
    322  1.1  skrll      delayed_load_register = insn.fields.f_dr;
    323  1.1  skrll   else if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRDRRR))
    324  1.1  skrll      delayed_load_register = insn.fields.f_drrr;
    325  1.1  skrll   else  /* Insns has no destination register.  */
    326  1.1  skrll      delayed_load_register = 0;
    327  1.1  skrll 
    328  1.1  skrll   /* Generate dwarf2 line numbers.  */
    329  1.1  skrll   dwarf2_emit_insn (4);
    330  1.1  skrll }
    331  1.1  skrll 
    332  1.1  skrll valueT
    333  1.1  skrll md_section_align (segT segment, valueT size)
    334  1.1  skrll {
    335  1.1  skrll   int align = bfd_get_section_alignment (stdoutput, segment);
    336  1.1  skrll 
    337  1.1  skrll   return ((size + (1 << align) - 1) & (-1 << align));
    338  1.1  skrll }
    339  1.1  skrll 
    340  1.1  skrll symbolS *
    341  1.1  skrll md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
    342  1.1  skrll {
    343  1.1  skrll     return NULL;
    344  1.1  skrll }
    345  1.1  skrll 
    346  1.1  skrll int
    348  1.1  skrll md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED,
    349  1.1  skrll 			       segT    segment ATTRIBUTE_UNUSED)
    350  1.1  skrll {
    351  1.1  skrll   as_fatal (_("md_estimate_size_before_relax\n"));
    352  1.1  skrll   return 1;
    353  1.1  skrll }
    354  1.1  skrll 
    355  1.1  skrll /* *fragP has been relaxed to its final size, and now needs to have
    356  1.1  skrll    the bytes inside it modified to conform to the new size.
    357  1.1  skrll 
    358  1.1  skrll    Called after relaxation is finished.
    359  1.1  skrll    fragP->fr_type == rs_machine_dependent.
    360  1.1  skrll    fragP->fr_subtype is the subtype of what the address relaxed to.  */
    361  1.1  skrll 
    362  1.1  skrll void
    363  1.1  skrll md_convert_frag (bfd   * abfd  ATTRIBUTE_UNUSED,
    364  1.1  skrll 		 segT    sec   ATTRIBUTE_UNUSED,
    365  1.1  skrll 		 fragS * fragP ATTRIBUTE_UNUSED)
    366  1.1  skrll {
    367  1.1  skrll }
    368  1.1  skrll 
    369  1.1  skrll 
    370  1.1  skrll /* Functions concerning relocs.  */
    372  1.1  skrll 
    373  1.1  skrll long
    374  1.1  skrll md_pcrel_from_section (fixS *fixP, segT sec)
    375  1.1  skrll {
    376  1.1  skrll   if (fixP->fx_addsy != (symbolS *) NULL
    377  1.1  skrll       && (!S_IS_DEFINED (fixP->fx_addsy)
    378  1.1  skrll 	  || S_GET_SEGMENT (fixP->fx_addsy) != sec))
    379  1.1  skrll     /* The symbol is undefined (or is defined but not in this section).
    380  1.1  skrll        Let the linker figure it out.  */
    381  1.1  skrll     return 0;
    382  1.1  skrll 
    383  1.1  skrll   /* Return the address of the opcode - cgen adjusts for opcode size
    384  1.1  skrll      itself, to be consistent with the disassembler, which must do
    385  1.1  skrll      so.  */
    386  1.1  skrll   return fixP->fx_where + fixP->fx_frag->fr_address;
    387  1.1  skrll }
    388  1.1  skrll 
    389  1.1  skrll 
    390  1.1  skrll /* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
    391  1.1  skrll    Returns BFD_RELOC_NONE if no reloc type can be found.
    392  1.1  skrll    *FIXP may be modified if desired.  */
    393  1.1  skrll 
    394  1.1  skrll bfd_reloc_code_real_type
    395  1.1  skrll md_cgen_lookup_reloc (const CGEN_INSN *    insn     ATTRIBUTE_UNUSED,
    396  1.1  skrll 		      const CGEN_OPERAND * operand,
    397  1.1  skrll 		      fixS *               fixP     ATTRIBUTE_UNUSED)
    398  1.1  skrll {
    399  1.1  skrll   bfd_reloc_code_real_type result;
    400  1.1  skrll 
    401  1.1  skrll   result = BFD_RELOC_NONE;
    402  1.1  skrll 
    403  1.1  skrll   switch (operand->type)
    404  1.1  skrll     {
    405  1.1  skrll     case MT_OPERAND_IMM16O:
    406  1.1  skrll       result = BFD_RELOC_16_PCREL;
    407  1.1  skrll       fixP->fx_pcrel = 1;
    408  1.1  skrll       /* fixP->fx_no_overflow = 1; */
    409  1.1  skrll       break;
    410  1.1  skrll     case MT_OPERAND_IMM16:
    411  1.1  skrll     case MT_OPERAND_IMM16Z:
    412  1.1  skrll       /* These may have been processed at parse time.  */
    413  1.1  skrll       if (fixP->fx_cgen.opinfo != 0)
    414  1.1  skrll         result = fixP->fx_cgen.opinfo;
    415  1.1  skrll       fixP->fx_no_overflow = 1;
    416  1.1  skrll       break;
    417  1.1  skrll     case MT_OPERAND_LOOPSIZE:
    418  1.1  skrll       result = BFD_RELOC_MT_PCINSN8;
    419  1.1  skrll       fixP->fx_pcrel = 1;
    420  1.1  skrll       /* Adjust for the delay slot, which is not part of the loop  */
    421  1.1  skrll       fixP->fx_offset -= 8;
    422  1.1  skrll       break;
    423  1.1  skrll     default:
    424  1.1  skrll       result = BFD_RELOC_NONE;
    425  1.1  skrll       break;
    426  1.1  skrll     }
    427  1.1  skrll 
    428  1.1  skrll   return result;
    429  1.1  skrll }
    430  1.1  skrll 
    431  1.1  skrll /* Write a value out to the object file, using the appropriate endianness.  */
    432  1.1  skrll 
    433  1.1  skrll void
    434  1.1  skrll md_number_to_chars (char * buf, valueT val, int n)
    435  1.1  skrll {
    436  1.1  skrll   number_to_chars_bigendian (buf, val, n);
    437  1.1  skrll }
    438  1.1  skrll 
    439  1.1  skrll char *
    440  1.1  skrll md_atof (int type, char * litP, int * sizeP)
    441  1.1  skrll {
    442  1.1  skrll   return ieee_md_atof (type, litP, sizeP, FALSE);
    443  1.1  skrll }
    444  1.1  skrll 
    445  1.1  skrll /* See whether we need to force a relocation into the output file.  */
    446  1.1  skrll 
    447  1.1  skrll int
    448  1.1  skrll mt_force_relocation (fixS * fixp ATTRIBUTE_UNUSED)
    449  1.1  skrll {
    450  1.1  skrll   return 0;
    451  1.1  skrll }
    452  1.1  skrll 
    453  1.1  skrll void
    454  1.1  skrll mt_apply_fix (fixS *fixP, valueT *valueP, segT seg)
    455  1.1  skrll {
    456  1.1  skrll   if ((fixP->fx_pcrel != 0) && (fixP->fx_r_type == BFD_RELOC_32))
    457  1.1  skrll     fixP->fx_r_type = BFD_RELOC_32_PCREL;
    458  1.1  skrll 
    459  1.1  skrll   gas_cgen_md_apply_fix (fixP, valueP, seg);
    460  1.1  skrll }
    461  1.1  skrll 
    462  1.1  skrll bfd_boolean
    463  1.1  skrll mt_fix_adjustable (fixS * fixP)
    464  1.1  skrll {
    465  1.1  skrll   bfd_reloc_code_real_type reloc_type;
    466  1.1  skrll 
    467  1.1  skrll   if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
    468  1.1  skrll     {
    469  1.1  skrll       const CGEN_INSN *insn = NULL;
    470  1.1  skrll       int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
    471  1.1  skrll       const CGEN_OPERAND *operand;
    472  1.1  skrll 
    473  1.1  skrll       operand = cgen_operand_lookup_by_num(gas_cgen_cpu_desc, opindex);
    474  1.1  skrll       reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
    475  1.1  skrll     }
    476  1.1  skrll   else
    477  1.1  skrll     reloc_type = fixP->fx_r_type;
    478  1.1  skrll 
    479  1.1  skrll   if (fixP->fx_addsy == NULL)
    480  1.1  skrll     return TRUE;
    481  1.1  skrll 
    482  1.1  skrll   /* Prevent all adjustments to global symbols.  */
    483  1.1  skrll   if (S_IS_EXTERNAL (fixP->fx_addsy))
    484  1.1  skrll     return FALSE;
    485  1.1  skrll 
    486  1.1  skrll   if (S_IS_WEAK (fixP->fx_addsy))
    487                 return FALSE;
    488             
    489               return 1;
    490             }
    491