Home | History | Annotate | Line # | Download | only in config
tc-frv.c revision 1.1
      1  1.1  skrll /* tc-frv.c -- Assembler for the Fujitsu FRV.
      2  1.1  skrll    Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008
      3  1.1  skrll    Free Software Foundation. Inc.
      4  1.1  skrll 
      5  1.1  skrll    This file is part of GAS, the GNU Assembler.
      6  1.1  skrll 
      7  1.1  skrll    GAS is free software; you can redistribute it and/or modify
      8  1.1  skrll    it under the terms of the GNU General Public License as published by
      9  1.1  skrll    the Free Software Foundation; either version 3, or (at your option)
     10  1.1  skrll    any later version.
     11  1.1  skrll 
     12  1.1  skrll    GAS is distributed in the hope that it will be useful,
     13  1.1  skrll    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  1.1  skrll    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15  1.1  skrll    GNU General Public License for more details.
     16  1.1  skrll 
     17  1.1  skrll    You should have received a copy of the GNU General Public License
     18  1.1  skrll    along with GAS; see the file COPYING.  If not, write to
     19  1.1  skrll    the Free Software Foundation, 51 Franklin Street - Fifth Floor,
     20  1.1  skrll    Boston, MA 02110-1301, USA.  */
     21  1.1  skrll 
     22  1.1  skrll #include "as.h"
     23  1.1  skrll #include "subsegs.h"
     24  1.1  skrll #include "symcat.h"
     25  1.1  skrll #include "opcodes/frv-desc.h"
     26  1.1  skrll #include "opcodes/frv-opc.h"
     27  1.1  skrll #include "cgen.h"
     28  1.1  skrll #include "libbfd.h"
     29  1.1  skrll #include "elf/common.h"
     30  1.1  skrll #include "elf/frv.h"
     31  1.1  skrll 
     32  1.1  skrll /* Structure to hold all of the different components describing
     33  1.1  skrll    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 frv_insn;
     53  1.1  skrll 
     54  1.1  skrll enum vliw_insn_type
     55  1.1  skrll {
     56  1.1  skrll   VLIW_GENERIC_TYPE,		/* Don't care about this insn.  */
     57  1.1  skrll   VLIW_BRANCH_TYPE,		/* A Branch.  */
     58  1.1  skrll   VLIW_LABEL_TYPE,		/* A Label.  */
     59  1.1  skrll   VLIW_NOP_TYPE,		/* A NOP.  */
     60  1.1  skrll   VLIW_BRANCH_HAS_NOPS		/* A Branch that requires NOPS.  */
     61  1.1  skrll };
     62  1.1  skrll 
     63  1.1  skrll /* We're going to use these in the fr_subtype field to mark
     64  1.1  skrll    whether to keep inserted nops.  */
     65  1.1  skrll 
     66  1.1  skrll #define NOP_KEEP 1		/* Keep these NOPS.  */
     67  1.1  skrll #define NOP_DELETE 2		/* Delete these NOPS.  */
     68  1.1  skrll 
     69  1.1  skrll #define DO_COUNT    TRUE
     70  1.1  skrll #define DONT_COUNT  FALSE
     71  1.1  skrll 
     72  1.1  skrll /* A list of insns within a VLIW insn.  */
     73  1.1  skrll struct vliw_insn_list
     74  1.1  skrll {
     75  1.1  skrll   /*  The type of this insn.  */
     76  1.1  skrll   enum vliw_insn_type	type;
     77  1.1  skrll 
     78  1.1  skrll   /*  The corresponding gas insn information.  */
     79  1.1  skrll   const CGEN_INSN	*insn;
     80  1.1  skrll 
     81  1.1  skrll   /*  For branches and labels, the symbol that is referenced.  */
     82  1.1  skrll   symbolS		*sym;
     83  1.1  skrll 
     84  1.1  skrll   /*  For branches, the frag containing the single nop that was generated.  */
     85  1.1  skrll   fragS			*snop_frag;
     86  1.1  skrll 
     87  1.1  skrll   /*  For branches, the frag containing the double nop that was generated.  */
     88  1.1  skrll   fragS			*dnop_frag;
     89  1.1  skrll 
     90  1.1  skrll   /*  Pointer to raw data for this insn.  */
     91  1.1  skrll   char			*address;
     92  1.1  skrll 
     93  1.1  skrll   /* Next insn in list.  */
     94  1.1  skrll   struct vliw_insn_list *next;
     95  1.1  skrll };
     96  1.1  skrll 
     97  1.1  skrll static struct vliw_insn_list single_nop_insn = {
     98  1.1  skrll    VLIW_NOP_TYPE, NULL, NULL, NULL, NULL, NULL, NULL };
     99  1.1  skrll 
    100  1.1  skrll static struct vliw_insn_list double_nop_insn = {
    101  1.1  skrll    VLIW_NOP_TYPE, NULL, NULL, NULL, NULL, NULL, NULL };
    102  1.1  skrll 
    103  1.1  skrll struct vliw_chain
    104  1.1  skrll {
    105  1.1  skrll   int			num;
    106  1.1  skrll   int			insn_count;
    107  1.1  skrll   struct vliw_insn_list *insn_list;
    108  1.1  skrll   struct vliw_chain     *next;
    109  1.1  skrll };
    110  1.1  skrll 
    111  1.1  skrll static struct vliw_chain	*vliw_chain_top;
    112  1.1  skrll static struct vliw_chain	*current_vliw_chain;
    113  1.1  skrll static struct vliw_chain	*previous_vliw_chain;
    114  1.1  skrll static struct vliw_insn_list	*current_vliw_insn;
    115  1.1  skrll 
    116  1.1  skrll const char comment_chars[]        = ";";
    117  1.1  skrll const char line_comment_chars[]   = "#";
    118  1.1  skrll const char line_separator_chars[] = "!";
    119  1.1  skrll const char EXP_CHARS[]            = "eE";
    120  1.1  skrll const char FLT_CHARS[]            = "dD";
    121  1.1  skrll 
    122  1.1  skrll static FRV_VLIW vliw;
    123  1.1  skrll 
    124  1.1  skrll /* Default machine */
    125  1.1  skrll 
    126  1.1  skrll #ifdef  DEFAULT_CPU_FRV
    127  1.1  skrll #define DEFAULT_MACHINE bfd_mach_frv
    128  1.1  skrll #define DEFAULT_FLAGS	EF_FRV_CPU_GENERIC
    129  1.1  skrll 
    130  1.1  skrll #else
    131  1.1  skrll #ifdef  DEFAULT_CPU_FR300
    132  1.1  skrll #define DEFAULT_MACHINE	bfd_mach_fr300
    133  1.1  skrll #define DEFAULT_FLAGS	EF_FRV_CPU_FR300
    134  1.1  skrll 
    135  1.1  skrll #else
    136  1.1  skrll #ifdef	DEFAULT_CPU_SIMPLE
    137  1.1  skrll #define	DEFAULT_MACHINE bfd_mach_frvsimple
    138  1.1  skrll #define DEFAULT_FLAGS	EF_FRV_CPU_SIMPLE
    139  1.1  skrll 
    140  1.1  skrll #else
    141  1.1  skrll #ifdef	DEFAULT_CPU_TOMCAT
    142  1.1  skrll #define	DEFAULT_MACHINE bfd_mach_frvtomcat
    143  1.1  skrll #define DEFAULT_FLAGS	EF_FRV_CPU_TOMCAT
    144  1.1  skrll 
    145  1.1  skrll #else
    146  1.1  skrll #ifdef  DEFAULT_CPU_FR400
    147  1.1  skrll #define DEFAULT_MACHINE	bfd_mach_fr400
    148  1.1  skrll #define DEFAULT_FLAGS	EF_FRV_CPU_FR400
    149  1.1  skrll 
    150  1.1  skrll #else
    151  1.1  skrll #ifdef  DEFAULT_CPU_FR550
    152  1.1  skrll #define DEFAULT_MACHINE	bfd_mach_fr550
    153  1.1  skrll #define DEFAULT_FLAGS	EF_FRV_CPU_FR550
    154  1.1  skrll 
    155  1.1  skrll #else
    156  1.1  skrll #define DEFAULT_MACHINE	bfd_mach_fr500
    157  1.1  skrll #define DEFAULT_FLAGS	EF_FRV_CPU_FR500
    158  1.1  skrll #endif
    159  1.1  skrll #endif
    160  1.1  skrll #endif
    161  1.1  skrll #endif
    162  1.1  skrll #endif
    163  1.1  skrll #endif
    164  1.1  skrll 
    165  1.1  skrll #ifdef TE_LINUX
    166  1.1  skrll # define DEFAULT_FDPIC	EF_FRV_FDPIC
    167  1.1  skrll #else
    168  1.1  skrll # define DEFAULT_FDPIC	0
    169  1.1  skrll #endif
    170  1.1  skrll 
    171  1.1  skrll static unsigned long frv_mach = bfd_mach_frv;
    172  1.1  skrll static bfd_boolean fr400_audio;
    173  1.1  skrll 
    174  1.1  skrll /* Flags to set in the elf header */
    175  1.1  skrll static flagword frv_flags = DEFAULT_FLAGS | DEFAULT_FDPIC;
    176  1.1  skrll 
    177  1.1  skrll static int frv_user_set_flags_p = 0;
    178  1.1  skrll static int frv_pic_p = 0;
    179  1.1  skrll static const char *frv_pic_flag = DEFAULT_FDPIC ? "-mfdpic" : (const char *)0;
    180  1.1  skrll 
    181  1.1  skrll /* Print tomcat-specific debugging info.  */
    182  1.1  skrll static int tomcat_debug = 0;
    183  1.1  skrll 
    184  1.1  skrll /* Tomcat-specific NOP statistics.  */
    185  1.1  skrll static int tomcat_stats = 0;
    186  1.1  skrll static int tomcat_doubles = 0;
    187  1.1  skrll static int tomcat_singles = 0;
    188  1.1  skrll 
    189  1.1  skrll /* Forward reference to static functions */
    190  1.1  skrll static void frv_set_flags (int);
    191  1.1  skrll static void frv_pic_ptr (int);
    192  1.1  skrll 
    193  1.1  skrll /* The target specific pseudo-ops which we support.  */
    194  1.1  skrll const pseudo_typeS md_pseudo_table[] =
    195  1.1  skrll {
    196  1.1  skrll   { "eflags",	frv_set_flags,		0 },
    197  1.1  skrll   { "word",	cons,			4 },
    198  1.1  skrll   { "picptr",	frv_pic_ptr,		4 },
    199  1.1  skrll   { NULL, 	NULL,			0 }
    200  1.1  skrll };
    201  1.1  skrll 
    202  1.1  skrll 
    203  1.1  skrll #define FRV_SHORTOPTS "G:"
    205  1.1  skrll const char * md_shortopts = FRV_SHORTOPTS;
    206  1.1  skrll 
    207  1.1  skrll #define OPTION_GPR_32		(OPTION_MD_BASE)
    208  1.1  skrll #define OPTION_GPR_64		(OPTION_MD_BASE + 1)
    209  1.1  skrll #define OPTION_FPR_32		(OPTION_MD_BASE + 2)
    210  1.1  skrll #define OPTION_FPR_64		(OPTION_MD_BASE + 3)
    211  1.1  skrll #define OPTION_SOFT_FLOAT	(OPTION_MD_BASE + 4)
    212  1.1  skrll #define OPTION_DWORD_YES	(OPTION_MD_BASE + 5)
    213  1.1  skrll #define OPTION_DWORD_NO		(OPTION_MD_BASE + 6)
    214  1.1  skrll #define OPTION_DOUBLE		(OPTION_MD_BASE + 7)
    215  1.1  skrll #define OPTION_NO_DOUBLE	(OPTION_MD_BASE + 8)
    216  1.1  skrll #define OPTION_MEDIA		(OPTION_MD_BASE + 9)
    217  1.1  skrll #define OPTION_NO_MEDIA		(OPTION_MD_BASE + 10)
    218  1.1  skrll #define OPTION_CPU		(OPTION_MD_BASE + 11)
    219  1.1  skrll #define OPTION_PIC		(OPTION_MD_BASE + 12)
    220  1.1  skrll #define OPTION_BIGPIC		(OPTION_MD_BASE + 13)
    221  1.1  skrll #define OPTION_LIBPIC		(OPTION_MD_BASE + 14)
    222  1.1  skrll #define OPTION_MULADD		(OPTION_MD_BASE + 15)
    223  1.1  skrll #define OPTION_NO_MULADD	(OPTION_MD_BASE + 16)
    224  1.1  skrll #define OPTION_TOMCAT_DEBUG	(OPTION_MD_BASE + 17)
    225  1.1  skrll #define OPTION_TOMCAT_STATS	(OPTION_MD_BASE + 18)
    226  1.1  skrll #define OPTION_PACK	        (OPTION_MD_BASE + 19)
    227  1.1  skrll #define OPTION_NO_PACK	        (OPTION_MD_BASE + 20)
    228  1.1  skrll #define OPTION_FDPIC		(OPTION_MD_BASE + 21)
    229  1.1  skrll #define OPTION_NOPIC		(OPTION_MD_BASE + 22)
    230  1.1  skrll 
    231  1.1  skrll struct option md_longopts[] =
    232  1.1  skrll {
    233  1.1  skrll   { "mgpr-32",		no_argument,		NULL, OPTION_GPR_32        },
    234  1.1  skrll   { "mgpr-64",		no_argument,		NULL, OPTION_GPR_64        },
    235  1.1  skrll   { "mfpr-32",		no_argument,		NULL, OPTION_FPR_32        },
    236  1.1  skrll   { "mfpr-64",		no_argument,		NULL, OPTION_FPR_64        },
    237  1.1  skrll   { "mhard-float",	no_argument,		NULL, OPTION_FPR_64        },
    238  1.1  skrll   { "msoft-float",	no_argument,		NULL, OPTION_SOFT_FLOAT    },
    239  1.1  skrll   { "mdword",		no_argument,		NULL, OPTION_DWORD_YES     },
    240  1.1  skrll   { "mno-dword",	no_argument,		NULL, OPTION_DWORD_NO      },
    241  1.1  skrll   { "mdouble",		no_argument,		NULL, OPTION_DOUBLE        },
    242  1.1  skrll   { "mno-double",	no_argument,		NULL, OPTION_NO_DOUBLE     },
    243  1.1  skrll   { "mmedia",		no_argument,		NULL, OPTION_MEDIA         },
    244  1.1  skrll   { "mno-media",	no_argument,		NULL, OPTION_NO_MEDIA      },
    245  1.1  skrll   { "mcpu",		required_argument,	NULL, OPTION_CPU           },
    246  1.1  skrll   { "mpic",		no_argument,		NULL, OPTION_PIC           },
    247  1.1  skrll   { "mPIC",		no_argument,		NULL, OPTION_BIGPIC        },
    248  1.1  skrll   { "mlibrary-pic",	no_argument,		NULL, OPTION_LIBPIC        },
    249  1.1  skrll   { "mmuladd",		no_argument,		NULL, OPTION_MULADD        },
    250  1.1  skrll   { "mno-muladd",	no_argument,		NULL, OPTION_NO_MULADD     },
    251  1.1  skrll   { "mtomcat-debug",    no_argument,            NULL, OPTION_TOMCAT_DEBUG  },
    252  1.1  skrll   { "mtomcat-stats",	no_argument,		NULL, OPTION_TOMCAT_STATS  },
    253  1.1  skrll   { "mpack",        	no_argument,		NULL, OPTION_PACK          },
    254  1.1  skrll   { "mno-pack",        	no_argument,		NULL, OPTION_NO_PACK       },
    255  1.1  skrll   { "mfdpic",		no_argument,		NULL, OPTION_FDPIC	   },
    256  1.1  skrll   { "mnopic",		no_argument,		NULL, OPTION_NOPIC	   },
    257  1.1  skrll   { NULL,		no_argument,		NULL, 0                 },
    258  1.1  skrll };
    259  1.1  skrll 
    260  1.1  skrll size_t md_longopts_size = sizeof (md_longopts);
    261  1.1  skrll 
    262  1.1  skrll /* What value to give to bfd_set_gp_size.  */
    263  1.1  skrll static int g_switch_value = 8;
    264  1.1  skrll 
    265  1.1  skrll int
    266  1.1  skrll md_parse_option (int c, char *arg)
    267  1.1  skrll {
    268  1.1  skrll   switch (c)
    269  1.1  skrll     {
    270  1.1  skrll     default:
    271  1.1  skrll       return 0;
    272  1.1  skrll 
    273  1.1  skrll     case 'G':
    274  1.1  skrll       g_switch_value = atoi (arg);
    275  1.1  skrll       if (! g_switch_value)
    276  1.1  skrll 	frv_flags |= EF_FRV_G0;
    277  1.1  skrll       break;
    278  1.1  skrll 
    279  1.1  skrll     case OPTION_GPR_32:
    280  1.1  skrll       frv_flags = (frv_flags & ~EF_FRV_GPR_MASK) | EF_FRV_GPR_32;
    281  1.1  skrll       break;
    282  1.1  skrll 
    283  1.1  skrll     case OPTION_GPR_64:
    284  1.1  skrll       frv_flags = (frv_flags & ~EF_FRV_GPR_MASK) | EF_FRV_GPR_64;
    285  1.1  skrll       break;
    286  1.1  skrll 
    287  1.1  skrll     case OPTION_FPR_32:
    288  1.1  skrll       frv_flags = (frv_flags & ~EF_FRV_FPR_MASK) | EF_FRV_FPR_32;
    289  1.1  skrll       break;
    290  1.1  skrll 
    291  1.1  skrll     case OPTION_FPR_64:
    292  1.1  skrll       frv_flags = (frv_flags & ~EF_FRV_FPR_MASK) | EF_FRV_FPR_64;
    293  1.1  skrll       break;
    294  1.1  skrll 
    295  1.1  skrll     case OPTION_SOFT_FLOAT:
    296  1.1  skrll       frv_flags = (frv_flags & ~EF_FRV_FPR_MASK) | EF_FRV_FPR_NONE;
    297  1.1  skrll       break;
    298  1.1  skrll 
    299  1.1  skrll     case OPTION_DWORD_YES:
    300  1.1  skrll       frv_flags = (frv_flags & ~EF_FRV_DWORD_MASK) | EF_FRV_DWORD_YES;
    301  1.1  skrll       break;
    302  1.1  skrll 
    303  1.1  skrll     case OPTION_DWORD_NO:
    304  1.1  skrll       frv_flags = (frv_flags & ~EF_FRV_DWORD_MASK) | EF_FRV_DWORD_NO;
    305  1.1  skrll       break;
    306  1.1  skrll 
    307  1.1  skrll     case OPTION_DOUBLE:
    308  1.1  skrll       frv_flags |= EF_FRV_DOUBLE;
    309  1.1  skrll       break;
    310  1.1  skrll 
    311  1.1  skrll     case OPTION_NO_DOUBLE:
    312  1.1  skrll       frv_flags &= ~EF_FRV_DOUBLE;
    313  1.1  skrll       break;
    314  1.1  skrll 
    315  1.1  skrll     case OPTION_MEDIA:
    316  1.1  skrll       frv_flags |= EF_FRV_MEDIA;
    317  1.1  skrll       break;
    318  1.1  skrll 
    319  1.1  skrll     case OPTION_NO_MEDIA:
    320  1.1  skrll       frv_flags &= ~EF_FRV_MEDIA;
    321  1.1  skrll       break;
    322  1.1  skrll 
    323  1.1  skrll     case OPTION_MULADD:
    324  1.1  skrll       frv_flags |= EF_FRV_MULADD;
    325  1.1  skrll       break;
    326  1.1  skrll 
    327  1.1  skrll     case OPTION_NO_MULADD:
    328  1.1  skrll       frv_flags &= ~EF_FRV_MULADD;
    329  1.1  skrll       break;
    330  1.1  skrll 
    331  1.1  skrll     case OPTION_PACK:
    332  1.1  skrll       frv_flags &= ~EF_FRV_NOPACK;
    333  1.1  skrll       break;
    334  1.1  skrll 
    335  1.1  skrll     case OPTION_NO_PACK:
    336  1.1  skrll       frv_flags |= EF_FRV_NOPACK;
    337  1.1  skrll       break;
    338  1.1  skrll 
    339  1.1  skrll     case OPTION_CPU:
    340  1.1  skrll       {
    341  1.1  skrll 	char *p;
    342  1.1  skrll 	int cpu_flags = EF_FRV_CPU_GENERIC;
    343  1.1  skrll 
    344  1.1  skrll 	/* Identify the processor type */
    345  1.1  skrll 	p = arg;
    346  1.1  skrll 	if (strcmp (p, "frv") == 0)
    347  1.1  skrll 	  {
    348  1.1  skrll 	    cpu_flags = EF_FRV_CPU_GENERIC;
    349  1.1  skrll 	    frv_mach = bfd_mach_frv;
    350  1.1  skrll 	  }
    351  1.1  skrll 
    352  1.1  skrll 	else if (strcmp (p, "fr500") == 0)
    353  1.1  skrll 	  {
    354  1.1  skrll 	    cpu_flags = EF_FRV_CPU_FR500;
    355  1.1  skrll 	    frv_mach = bfd_mach_fr500;
    356  1.1  skrll 	  }
    357  1.1  skrll 
    358  1.1  skrll 	else if (strcmp (p, "fr550") == 0)
    359  1.1  skrll 	  {
    360  1.1  skrll 	    cpu_flags = EF_FRV_CPU_FR550;
    361  1.1  skrll 	    frv_mach = bfd_mach_fr550;
    362  1.1  skrll 	  }
    363  1.1  skrll 
    364  1.1  skrll 	else if (strcmp (p, "fr450") == 0)
    365  1.1  skrll 	  {
    366  1.1  skrll 	    cpu_flags = EF_FRV_CPU_FR450;
    367  1.1  skrll 	    frv_mach = bfd_mach_fr450;
    368  1.1  skrll 	  }
    369  1.1  skrll 
    370  1.1  skrll 	else if (strcmp (p, "fr405") == 0)
    371  1.1  skrll 	  {
    372  1.1  skrll 	    cpu_flags = EF_FRV_CPU_FR405;
    373  1.1  skrll 	    frv_mach = bfd_mach_fr400;
    374  1.1  skrll 	    fr400_audio = TRUE;
    375  1.1  skrll 	  }
    376  1.1  skrll 
    377  1.1  skrll 	else if (strcmp (p, "fr400") == 0)
    378  1.1  skrll 	  {
    379  1.1  skrll 	    cpu_flags = EF_FRV_CPU_FR400;
    380  1.1  skrll 	    frv_mach = bfd_mach_fr400;
    381  1.1  skrll 	    fr400_audio = FALSE;
    382  1.1  skrll 	  }
    383  1.1  skrll 
    384  1.1  skrll 	else if (strcmp (p, "fr300") == 0)
    385  1.1  skrll 	  {
    386  1.1  skrll 	    cpu_flags = EF_FRV_CPU_FR300;
    387  1.1  skrll 	    frv_mach = bfd_mach_fr300;
    388  1.1  skrll 	  }
    389  1.1  skrll 
    390  1.1  skrll 	else if (strcmp (p, "simple") == 0)
    391  1.1  skrll 	  {
    392  1.1  skrll 	    cpu_flags = EF_FRV_CPU_SIMPLE;
    393  1.1  skrll 	    frv_mach = bfd_mach_frvsimple;
    394  1.1  skrll 	    frv_flags |= EF_FRV_NOPACK;
    395  1.1  skrll 	  }
    396  1.1  skrll 
    397  1.1  skrll         else if (strcmp (p, "tomcat") == 0)
    398  1.1  skrll           {
    399  1.1  skrll             cpu_flags = EF_FRV_CPU_TOMCAT;
    400  1.1  skrll             frv_mach = bfd_mach_frvtomcat;
    401  1.1  skrll           }
    402  1.1  skrll 
    403  1.1  skrll 	else
    404  1.1  skrll 	  {
    405  1.1  skrll 	    as_fatal (_("Unknown cpu -mcpu=%s"), arg);
    406  1.1  skrll 	    return 0;
    407  1.1  skrll 	  }
    408  1.1  skrll 
    409  1.1  skrll 	frv_flags = (frv_flags & ~EF_FRV_CPU_MASK) | cpu_flags;
    410  1.1  skrll       }
    411  1.1  skrll       break;
    412  1.1  skrll 
    413  1.1  skrll     case OPTION_PIC:
    414  1.1  skrll       frv_flags |= EF_FRV_PIC;
    415  1.1  skrll       frv_pic_p = 1;
    416  1.1  skrll       frv_pic_flag = "-fpic";
    417  1.1  skrll       break;
    418  1.1  skrll 
    419  1.1  skrll     case OPTION_BIGPIC:
    420  1.1  skrll       frv_flags |= EF_FRV_BIGPIC;
    421  1.1  skrll       frv_pic_p = 1;
    422  1.1  skrll       frv_pic_flag = "-fPIC";
    423  1.1  skrll       break;
    424  1.1  skrll 
    425  1.1  skrll     case OPTION_LIBPIC:
    426  1.1  skrll       frv_flags |= (EF_FRV_LIBPIC | EF_FRV_G0);
    427  1.1  skrll       frv_pic_p = 1;
    428  1.1  skrll       frv_pic_flag = "-mlibrary-pic";
    429  1.1  skrll       g_switch_value = 0;
    430  1.1  skrll       break;
    431  1.1  skrll 
    432  1.1  skrll     case OPTION_FDPIC:
    433  1.1  skrll       frv_flags |= EF_FRV_FDPIC;
    434  1.1  skrll       frv_pic_flag = "-mfdpic";
    435  1.1  skrll       break;
    436  1.1  skrll 
    437  1.1  skrll     case OPTION_NOPIC:
    438  1.1  skrll       frv_flags &= ~(EF_FRV_FDPIC | EF_FRV_PIC
    439  1.1  skrll 		     | EF_FRV_BIGPIC | EF_FRV_LIBPIC);
    440  1.1  skrll       frv_pic_flag = 0;
    441  1.1  skrll       break;
    442  1.1  skrll 
    443  1.1  skrll     case OPTION_TOMCAT_DEBUG:
    444  1.1  skrll       tomcat_debug = 1;
    445  1.1  skrll       break;
    446  1.1  skrll 
    447  1.1  skrll     case OPTION_TOMCAT_STATS:
    448  1.1  skrll       tomcat_stats = 1;
    449  1.1  skrll       break;
    450  1.1  skrll     }
    451  1.1  skrll 
    452  1.1  skrll   return 1;
    453  1.1  skrll }
    454  1.1  skrll 
    455  1.1  skrll void
    456  1.1  skrll md_show_usage (FILE * stream)
    457  1.1  skrll {
    458  1.1  skrll   fprintf (stream, _("FRV specific command line options:\n"));
    459  1.1  skrll   fprintf (stream, _("-G n            Put data <= n bytes in the small data area\n"));
    460  1.1  skrll   fprintf (stream, _("-mgpr-32        Mark generated file as only using 32 GPRs\n"));
    461  1.1  skrll   fprintf (stream, _("-mgpr-64        Mark generated file as using all 64 GPRs\n"));
    462  1.1  skrll   fprintf (stream, _("-mfpr-32        Mark generated file as only using 32 FPRs\n"));
    463  1.1  skrll   fprintf (stream, _("-mfpr-64        Mark generated file as using all 64 FPRs\n"));
    464  1.1  skrll   fprintf (stream, _("-msoft-float    Mark generated file as using software FP\n"));
    465  1.1  skrll   fprintf (stream, _("-mdword         Mark generated file as using a 8-byte stack alignment\n"));
    466  1.1  skrll   fprintf (stream, _("-mno-dword      Mark generated file as using a 4-byte stack alignment\n"));
    467  1.1  skrll   fprintf (stream, _("-mdouble        Mark generated file as using double precision FP insns\n"));
    468  1.1  skrll   fprintf (stream, _("-mmedia         Mark generated file as using media insns\n"));
    469  1.1  skrll   fprintf (stream, _("-mmuladd        Mark generated file as using multiply add/subtract insns\n"));
    470  1.1  skrll   fprintf (stream, _("-mpack          Allow instructions to be packed\n"));
    471  1.1  skrll   fprintf (stream, _("-mno-pack       Do not allow instructions to be packed\n"));
    472  1.1  skrll   fprintf (stream, _("-mpic           Mark generated file as using small position independent code\n"));
    473  1.1  skrll   fprintf (stream, _("-mPIC           Mark generated file as using large position independent code\n"));
    474  1.1  skrll   fprintf (stream, _("-mlibrary-pic   Mark generated file as using position indepedent code for libraries\n"));
    475  1.1  skrll   fprintf (stream, _("-mfdpic         Assemble for the FDPIC ABI\n"));
    476  1.1  skrll   fprintf (stream, _("-mnopic         Disable -mpic, -mPIC, -mlibrary-pic and -mfdpic\n"));
    477  1.1  skrll   fprintf (stream, _("-mcpu={fr500|fr550|fr400|fr405|fr450|fr300|frv|simple|tomcat}\n"));
    478  1.1  skrll   fprintf (stream, _("                Record the cpu type\n"));
    479  1.1  skrll   fprintf (stream, _("-mtomcat-stats  Print out stats for tomcat workarounds\n"));
    480  1.1  skrll   fprintf (stream, _("-mtomcat-debug  Debug tomcat workarounds\n"));
    481  1.1  skrll }
    482  1.1  skrll 
    483  1.1  skrll 
    484  1.1  skrll void
    486  1.1  skrll md_begin (void)
    487  1.1  skrll {
    488  1.1  skrll   /* Initialize the `cgen' interface.  */
    489  1.1  skrll 
    490  1.1  skrll   /* Set the machine number and endian.  */
    491  1.1  skrll   gas_cgen_cpu_desc = frv_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, 0,
    492  1.1  skrll 					 CGEN_CPU_OPEN_ENDIAN,
    493  1.1  skrll 					 CGEN_ENDIAN_BIG,
    494  1.1  skrll 					 CGEN_CPU_OPEN_END);
    495  1.1  skrll   frv_cgen_init_asm (gas_cgen_cpu_desc);
    496  1.1  skrll 
    497  1.1  skrll   /* This is a callback from cgen to gas to parse operands.  */
    498  1.1  skrll   cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand);
    499  1.1  skrll 
    500  1.1  skrll   /* Set the ELF flags if desired. */
    501  1.1  skrll   if (frv_flags)
    502  1.1  skrll     bfd_set_private_flags (stdoutput, frv_flags);
    503  1.1  skrll 
    504  1.1  skrll   /* Set the machine type */
    505  1.1  skrll   bfd_default_set_arch_mach (stdoutput, bfd_arch_frv, frv_mach);
    506  1.1  skrll 
    507  1.1  skrll   /* Set up gp size so we can put local common items in .sbss */
    508  1.1  skrll   bfd_set_gp_size (stdoutput, g_switch_value);
    509  1.1  skrll 
    510  1.1  skrll   frv_vliw_reset (& vliw, frv_mach, frv_flags);
    511  1.1  skrll }
    512  1.1  skrll 
    513  1.1  skrll bfd_boolean
    514  1.1  skrll frv_md_fdpic_enabled (void)
    515  1.1  skrll {
    516  1.1  skrll   return (frv_flags & EF_FRV_FDPIC) != 0;
    517  1.1  skrll }
    518  1.1  skrll 
    519  1.1  skrll int chain_num = 0;
    520  1.1  skrll 
    521  1.1  skrll static struct vliw_insn_list *
    522  1.1  skrll frv_insert_vliw_insn (bfd_boolean count)
    523  1.1  skrll {
    524  1.1  skrll   struct vliw_insn_list *vliw_insn_list_entry;
    525  1.1  skrll   struct vliw_chain     *vliw_chain_entry;
    526  1.1  skrll 
    527  1.1  skrll   if (current_vliw_chain == NULL)
    528  1.1  skrll     {
    529  1.1  skrll       vliw_chain_entry = (struct vliw_chain *) xmalloc (sizeof (struct vliw_chain));
    530  1.1  skrll       vliw_chain_entry->insn_count = 0;
    531  1.1  skrll       vliw_chain_entry->insn_list  = NULL;
    532  1.1  skrll       vliw_chain_entry->next       = NULL;
    533  1.1  skrll       vliw_chain_entry->num        = chain_num++;
    534  1.1  skrll 
    535  1.1  skrll       if (!vliw_chain_top)
    536  1.1  skrll 	vliw_chain_top = vliw_chain_entry;
    537  1.1  skrll       current_vliw_chain = vliw_chain_entry;
    538  1.1  skrll       if (previous_vliw_chain)
    539  1.1  skrll 	previous_vliw_chain->next = vliw_chain_entry;
    540  1.1  skrll     }
    541  1.1  skrll 
    542  1.1  skrll   vliw_insn_list_entry = (struct vliw_insn_list *) xmalloc (sizeof (struct vliw_insn_list));
    543  1.1  skrll   vliw_insn_list_entry->type      = VLIW_GENERIC_TYPE;
    544  1.1  skrll   vliw_insn_list_entry->insn      = NULL;
    545  1.1  skrll   vliw_insn_list_entry->sym       = NULL;
    546  1.1  skrll   vliw_insn_list_entry->snop_frag = NULL;
    547  1.1  skrll   vliw_insn_list_entry->dnop_frag = NULL;
    548  1.1  skrll   vliw_insn_list_entry->next      = NULL;
    549  1.1  skrll 
    550  1.1  skrll   if (count)
    551  1.1  skrll     current_vliw_chain->insn_count++;
    552  1.1  skrll 
    553  1.1  skrll   if (current_vliw_insn)
    554  1.1  skrll     current_vliw_insn->next = vliw_insn_list_entry;
    555  1.1  skrll   current_vliw_insn = vliw_insn_list_entry;
    556  1.1  skrll 
    557  1.1  skrll   if (!current_vliw_chain->insn_list)
    558  1.1  skrll     current_vliw_chain->insn_list = current_vliw_insn;
    559  1.1  skrll 
    560  1.1  skrll   return vliw_insn_list_entry;
    561  1.1  skrll }
    562  1.1  skrll 
    563  1.1  skrll   /* Identify the following cases:
    564  1.1  skrll 
    565  1.1  skrll      1) A VLIW insn that contains both a branch and the branch destination.
    566  1.1  skrll         This requires the insertion of two vliw instructions before the
    567  1.1  skrll         branch.  The first consists of two nops.  The second consists of
    568  1.1  skrll         a single nop.
    569  1.1  skrll 
    570  1.1  skrll      2) A single instruction VLIW insn which is the destination of a branch
    571  1.1  skrll         that is in the next VLIW insn.  This requires the insertion of a vliw
    572  1.1  skrll         insn containing two nops before the branch.
    573  1.1  skrll 
    574  1.1  skrll      3) A double instruction VLIW insn which contains the destination of a
    575  1.1  skrll         branch that is in the next VLIW insn.  This requires the insertion of
    576  1.1  skrll         a VLIW insn containing a single nop before the branch.
    577  1.1  skrll 
    578  1.1  skrll      4) A single instruction VLIW insn which contains branch destination (x),
    579  1.1  skrll         followed by a single instruction VLIW insn which does not contain
    580  1.1  skrll         the branch to (x), followed by a VLIW insn which does contain the branch
    581  1.1  skrll         to (x).  This requires the insertion of a VLIW insn containing a single
    582  1.1  skrll         nop before the VLIW instruction containing the branch.
    583  1.1  skrll 
    584  1.1  skrll   */
    585  1.1  skrll #define FRV_IS_NOP(insn) (insn.buffer[0] == FRV_NOP_PACK || insn.buffer[0] == FRV_NOP_NOPACK)
    586  1.1  skrll #define FRV_NOP_PACK   0x00880000  /* ori.p  gr0,0,gr0 */
    587  1.1  skrll #define FRV_NOP_NOPACK 0x80880000  /* ori    gr0,0,gr0 */
    588  1.1  skrll 
    589  1.1  skrll /* Check a vliw insn for an insn of type containing the sym passed in label_sym.  */
    590  1.1  skrll 
    591  1.1  skrll static struct vliw_insn_list *
    592  1.1  skrll frv_find_in_vliw (enum vliw_insn_type vliw_insn_type,
    593  1.1  skrll 		  struct vliw_chain *this_chain,
    594  1.1  skrll 		  symbolS *label_sym)
    595  1.1  skrll {
    596  1.1  skrll 
    597  1.1  skrll   struct vliw_insn_list *the_insn;
    598  1.1  skrll 
    599  1.1  skrll   if (!this_chain)
    600  1.1  skrll     return NULL;
    601  1.1  skrll 
    602  1.1  skrll   for (the_insn = this_chain->insn_list; the_insn; the_insn = the_insn->next)
    603  1.1  skrll     {
    604  1.1  skrll       if (the_insn->type == vliw_insn_type
    605  1.1  skrll 	  && the_insn->sym == label_sym)
    606  1.1  skrll 	return the_insn;
    607  1.1  skrll     }
    608  1.1  skrll 
    609  1.1  skrll   return NULL;
    610  1.1  skrll }
    611  1.1  skrll 
    612  1.1  skrll enum vliw_nop_type
    613  1.1  skrll {
    614  1.1  skrll   /* A Vliw insn containing a single nop insn.  */
    615  1.1  skrll   VLIW_SINGLE_NOP,
    616  1.1  skrll 
    617  1.1  skrll   /* A Vliw insn containing two nop insns.  */
    618  1.1  skrll   VLIW_DOUBLE_NOP,
    619  1.1  skrll 
    620  1.1  skrll   /* Two vliw insns.  The first containing two nop insns.
    621  1.1  skrll      The second contain a single nop insn.  */
    622  1.1  skrll   VLIW_DOUBLE_THEN_SINGLE_NOP
    623  1.1  skrll };
    624  1.1  skrll 
    625  1.1  skrll static void
    626  1.1  skrll frv_debug_tomcat (struct vliw_chain *start_chain)
    627  1.1  skrll {
    628  1.1  skrll    struct vliw_chain *this_chain;
    629  1.1  skrll    struct vliw_insn_list *this_insn;
    630  1.1  skrll    int i = 1;
    631  1.1  skrll 
    632  1.1  skrll   for (this_chain = start_chain; this_chain; this_chain = this_chain->next, i++)
    633  1.1  skrll     {
    634  1.1  skrll       fprintf (stderr, "\nVliw Insn #%d, #insns: %d\n", i, this_chain->insn_count);
    635  1.1  skrll 
    636  1.1  skrll       for (this_insn = this_chain->insn_list; this_insn; this_insn = this_insn->next)
    637  1.1  skrll 	{
    638  1.1  skrll 	  if (this_insn->type == VLIW_LABEL_TYPE)
    639  1.1  skrll 	    fprintf (stderr, "Label Value: %p\n", this_insn->sym);
    640  1.1  skrll 	  else if (this_insn->type == VLIW_BRANCH_TYPE)
    641  1.1  skrll 	    fprintf (stderr, "%s to %p\n", this_insn->insn->base->name, this_insn->sym);
    642  1.1  skrll 	  else if (this_insn->type == VLIW_BRANCH_HAS_NOPS)
    643  1.1  skrll 	    fprintf (stderr, "nop'd %s to %p\n", this_insn->insn->base->name, this_insn->sym);
    644  1.1  skrll 	  else if (this_insn->type == VLIW_NOP_TYPE)
    645  1.1  skrll 	    fprintf (stderr, "Nop\n");
    646  1.1  skrll 	  else
    647  1.1  skrll 	    fprintf (stderr, "	%s\n", this_insn->insn->base->name);
    648  1.1  skrll 	}
    649  1.1  skrll    }
    650  1.1  skrll }
    651  1.1  skrll 
    652  1.1  skrll static void
    653  1.1  skrll frv_adjust_vliw_count (struct vliw_chain *this_chain)
    654  1.1  skrll {
    655  1.1  skrll   struct vliw_insn_list *this_insn;
    656  1.1  skrll 
    657  1.1  skrll   this_chain->insn_count = 0;
    658  1.1  skrll 
    659  1.1  skrll   for (this_insn = this_chain->insn_list;
    660  1.1  skrll        this_insn;
    661  1.1  skrll        this_insn = this_insn->next)
    662  1.1  skrll     {
    663  1.1  skrll       if (this_insn->type != VLIW_LABEL_TYPE)
    664  1.1  skrll   	this_chain->insn_count++;
    665  1.1  skrll     }
    666  1.1  skrll 
    667  1.1  skrll }
    668  1.1  skrll 
    669  1.1  skrll /* Insert the desired nop combination in the vliw chain before insert_before_insn.
    670  1.1  skrll    Rechain the vliw insn.  */
    671  1.1  skrll 
    672  1.1  skrll static struct vliw_chain *
    673  1.1  skrll frv_tomcat_shuffle (enum vliw_nop_type this_nop_type,
    674  1.1  skrll 		    struct vliw_chain *vliw_to_split,
    675  1.1  skrll 		    struct vliw_insn_list *insert_before_insn)
    676  1.1  skrll {
    677  1.1  skrll 
    678  1.1  skrll   bfd_boolean pack_prev = FALSE;
    679  1.1  skrll   struct vliw_chain *return_me = NULL;
    680  1.1  skrll   struct vliw_insn_list *prev_insn = NULL;
    681  1.1  skrll   struct vliw_insn_list *curr_insn = vliw_to_split->insn_list;
    682  1.1  skrll 
    683  1.1  skrll   struct vliw_chain *double_nop = (struct vliw_chain *) xmalloc (sizeof (struct vliw_chain));
    684  1.1  skrll   struct vliw_chain *single_nop = (struct vliw_chain *) xmalloc (sizeof (struct vliw_chain));
    685  1.1  skrll   struct vliw_chain *second_part = (struct vliw_chain *) xmalloc (sizeof (struct vliw_chain));
    686  1.1  skrll   struct vliw_chain *curr_vliw = vliw_chain_top;
    687  1.1  skrll   struct vliw_chain *prev_vliw = NULL;
    688  1.1  skrll 
    689  1.1  skrll   while (curr_insn && curr_insn != insert_before_insn)
    690  1.1  skrll     {
    691  1.1  skrll       /* We can't set the packing bit on a label.  If we have the case
    692  1.1  skrll 	 label 1:
    693  1.1  skrll 	 label 2:
    694  1.1  skrll 	 label 3:
    695  1.1  skrll 	   branch that needs nops
    696  1.1  skrll 	Then don't set pack bit later.  */
    697  1.1  skrll 
    698  1.1  skrll       if (curr_insn->type != VLIW_LABEL_TYPE)
    699  1.1  skrll 	pack_prev = TRUE;
    700  1.1  skrll       prev_insn = curr_insn;
    701  1.1  skrll       curr_insn = curr_insn->next;
    702  1.1  skrll     }
    703  1.1  skrll 
    704  1.1  skrll   while (curr_vliw && curr_vliw != vliw_to_split)
    705  1.1  skrll     {
    706  1.1  skrll       prev_vliw = curr_vliw;
    707  1.1  skrll       curr_vliw = curr_vliw->next;
    708  1.1  skrll     }
    709  1.1  skrll 
    710  1.1  skrll   switch (this_nop_type)
    711  1.1  skrll     {
    712  1.1  skrll     case VLIW_SINGLE_NOP:
    713  1.1  skrll       if (!prev_insn)
    714  1.1  skrll 	{
    715  1.1  skrll 	/* Branch is first,  Insert the NOP prior to this vliw insn.  */
    716  1.1  skrll 	if (prev_vliw)
    717  1.1  skrll 	  prev_vliw->next = single_nop;
    718  1.1  skrll 	else
    719  1.1  skrll 	  vliw_chain_top = single_nop;
    720  1.1  skrll 	single_nop->next = vliw_to_split;
    721  1.1  skrll 	vliw_to_split->insn_list->type = VLIW_BRANCH_HAS_NOPS;
    722  1.1  skrll 	return_me = vliw_to_split;
    723  1.1  skrll 	}
    724  1.1  skrll       else
    725  1.1  skrll 	{
    726  1.1  skrll 	  /* Set the packing bit on the previous insn.  */
    727  1.1  skrll 	  if (pack_prev)
    728  1.1  skrll 	    {
    729  1.1  skrll 	      char *buffer = prev_insn->address;
    730  1.1  skrll 	      buffer[0] |= 0x80;
    731  1.1  skrll 	    }
    732  1.1  skrll 	  /* The branch is in the middle.  Split this vliw insn into first
    733  1.1  skrll 	     and second parts.  Insert the NOP inbetween.  */
    734  1.1  skrll 
    735  1.1  skrll           second_part->insn_list = insert_before_insn;
    736  1.1  skrll 	  second_part->insn_list->type = VLIW_BRANCH_HAS_NOPS;
    737  1.1  skrll           second_part->next      = vliw_to_split->next;
    738  1.1  skrll  	  frv_adjust_vliw_count (second_part);
    739  1.1  skrll 
    740  1.1  skrll           single_nop->next       = second_part;
    741  1.1  skrll 
    742  1.1  skrll           vliw_to_split->next    = single_nop;
    743  1.1  skrll           prev_insn->next        = NULL;
    744  1.1  skrll 
    745  1.1  skrll           return_me = second_part;
    746  1.1  skrll 	  frv_adjust_vliw_count (vliw_to_split);
    747  1.1  skrll 	}
    748  1.1  skrll       break;
    749  1.1  skrll 
    750  1.1  skrll     case VLIW_DOUBLE_NOP:
    751  1.1  skrll       if (!prev_insn)
    752  1.1  skrll 	{
    753  1.1  skrll 	/* Branch is first,  Insert the NOP prior to this vliw insn.  */
    754  1.1  skrll         if (prev_vliw)
    755  1.1  skrll           prev_vliw->next = double_nop;
    756  1.1  skrll         else
    757  1.1  skrll           vliw_chain_top = double_nop;
    758  1.1  skrll 
    759  1.1  skrll 	double_nop->next = vliw_to_split;
    760  1.1  skrll 	return_me = vliw_to_split;
    761  1.1  skrll 	vliw_to_split->insn_list->type = VLIW_BRANCH_HAS_NOPS;
    762  1.1  skrll 	}
    763  1.1  skrll       else
    764  1.1  skrll 	{
    765  1.1  skrll 	  /* Set the packing bit on the previous insn.  */
    766  1.1  skrll 	  if (pack_prev)
    767  1.1  skrll 	    {
    768  1.1  skrll 	      char *buffer = prev_insn->address;
    769  1.1  skrll 	      buffer[0] |= 0x80;
    770  1.1  skrll 	    }
    771  1.1  skrll 
    772  1.1  skrll 	/* The branch is in the middle.  Split this vliw insn into first
    773  1.1  skrll 	   and second parts.  Insert the NOP inbetween.  */
    774  1.1  skrll           second_part->insn_list = insert_before_insn;
    775  1.1  skrll 	  second_part->insn_list->type = VLIW_BRANCH_HAS_NOPS;
    776  1.1  skrll           second_part->next      = vliw_to_split->next;
    777  1.1  skrll  	  frv_adjust_vliw_count (second_part);
    778  1.1  skrll 
    779  1.1  skrll           double_nop->next       = second_part;
    780  1.1  skrll 
    781  1.1  skrll           vliw_to_split->next    = single_nop;
    782  1.1  skrll           prev_insn->next        = NULL;
    783  1.1  skrll  	  frv_adjust_vliw_count (vliw_to_split);
    784  1.1  skrll 
    785  1.1  skrll           return_me = second_part;
    786  1.1  skrll 	}
    787  1.1  skrll       break;
    788  1.1  skrll 
    789  1.1  skrll     case VLIW_DOUBLE_THEN_SINGLE_NOP:
    790  1.1  skrll       double_nop->next = single_nop;
    791  1.1  skrll       double_nop->insn_count = 2;
    792  1.1  skrll       double_nop->insn_list = &double_nop_insn;
    793  1.1  skrll       single_nop->insn_count = 1;
    794  1.1  skrll       single_nop->insn_list = &single_nop_insn;
    795  1.1  skrll 
    796  1.1  skrll       if (!prev_insn)
    797  1.1  skrll 	{
    798  1.1  skrll 	  /* The branch is the first insn in this vliw.  Don't split the vliw.  Insert
    799  1.1  skrll 	     the nops prior to this vliw.  */
    800  1.1  skrll           if (prev_vliw)
    801  1.1  skrll             prev_vliw->next = double_nop;
    802  1.1  skrll           else
    803  1.1  skrll             vliw_chain_top = double_nop;
    804  1.1  skrll 
    805  1.1  skrll 	  single_nop->next = vliw_to_split;
    806  1.1  skrll 	  return_me = vliw_to_split;
    807  1.1  skrll 	  vliw_to_split->insn_list->type = VLIW_BRANCH_HAS_NOPS;
    808  1.1  skrll 	}
    809  1.1  skrll       else
    810  1.1  skrll 	{
    811  1.1  skrll 	  /* Set the packing bit on the previous insn.  */
    812  1.1  skrll 	  if (pack_prev)
    813  1.1  skrll 	    {
    814  1.1  skrll 	      char *buffer = prev_insn->address;
    815  1.1  skrll 	      buffer[0] |= 0x80;
    816  1.1  skrll 	    }
    817  1.1  skrll 
    818  1.1  skrll 	  /* The branch is in the middle of this vliw insn.  Split into first and
    819  1.1  skrll 	     second parts.  Insert the nop vliws in between.  */
    820  1.1  skrll 	  second_part->insn_list = insert_before_insn;
    821  1.1  skrll 	  second_part->insn_list->type = VLIW_BRANCH_HAS_NOPS;
    822  1.1  skrll 	  second_part->next      = vliw_to_split->next;
    823  1.1  skrll  	  frv_adjust_vliw_count (second_part);
    824  1.1  skrll 
    825  1.1  skrll 	  single_nop->next       = second_part;
    826  1.1  skrll 
    827  1.1  skrll 	  vliw_to_split->next	 = double_nop;
    828  1.1  skrll 	  prev_insn->next	 = NULL;
    829  1.1  skrll  	  frv_adjust_vliw_count (vliw_to_split);
    830  1.1  skrll 
    831  1.1  skrll 	  return_me = second_part;
    832  1.1  skrll 	}
    833  1.1  skrll       break;
    834  1.1  skrll     }
    835  1.1  skrll 
    836  1.1  skrll   return return_me;
    837  1.1  skrll }
    838  1.1  skrll 
    839  1.1  skrll static void
    840  1.1  skrll frv_tomcat_analyze_vliw_chains (void)
    841  1.1  skrll {
    842  1.1  skrll   struct vliw_chain *vliw1 = NULL;
    843  1.1  skrll   struct vliw_chain *vliw2 = NULL;
    844  1.1  skrll   struct vliw_chain *vliw3 = NULL;
    845  1.1  skrll 
    846  1.1  skrll   struct vliw_insn_list *this_insn = NULL;
    847  1.1  skrll   struct vliw_insn_list *temp_insn = NULL;
    848  1.1  skrll 
    849  1.1  skrll   /* We potentially need to look at three VLIW insns to determine if the
    850  1.1  skrll      workaround is required.  Set them up.  Ignore existing nops during analysis. */
    851  1.1  skrll 
    852  1.1  skrll #define FRV_SET_VLIW_WINDOW(VLIW1, VLIW2, VLIW3) \
    853  1.1  skrll   if (VLIW1 && VLIW1->next)			 \
    854  1.1  skrll     VLIW2 = VLIW1->next;			 \
    855  1.1  skrll   else						 \
    856  1.1  skrll     VLIW2 = NULL;				 \
    857  1.1  skrll   if (VLIW2 && VLIW2->next)			 \
    858  1.1  skrll     VLIW3 = VLIW2->next;			 \
    859  1.1  skrll   else						 \
    860  1.1  skrll     VLIW3 = NULL
    861  1.1  skrll 
    862  1.1  skrll   vliw1 = vliw_chain_top;
    863  1.1  skrll 
    864  1.1  skrll workaround_top:
    865  1.1  skrll 
    866  1.1  skrll   FRV_SET_VLIW_WINDOW (vliw1, vliw2, vliw3);
    867  1.1  skrll 
    868  1.1  skrll   if (!vliw1)
    869  1.1  skrll     return;
    870  1.1  skrll 
    871  1.1  skrll   if (vliw1->insn_count == 1)
    872  1.1  skrll     {
    873  1.1  skrll       /* check vliw1 for a label. */
    874  1.1  skrll       if (vliw1->insn_list->type == VLIW_LABEL_TYPE)
    875  1.1  skrll 	{
    876  1.1  skrll 	  temp_insn = frv_find_in_vliw (VLIW_BRANCH_TYPE, vliw2, vliw1->insn_list->sym);
    877  1.1  skrll 	  if (temp_insn)
    878  1.1  skrll 	    {
    879  1.1  skrll 	      vliw1 = frv_tomcat_shuffle (VLIW_DOUBLE_NOP, vliw2, vliw1->insn_list);
    880  1.1  skrll 	      temp_insn->dnop_frag->fr_subtype = NOP_KEEP;
    881  1.1  skrll 	      vliw1 = vliw1->next;
    882  1.1  skrll 	      if (tomcat_stats)
    883  1.1  skrll 		tomcat_doubles++;
    884  1.1  skrll 	      goto workaround_top;
    885  1.1  skrll 	    }
    886  1.1  skrll 	  else if (vliw2
    887  1.1  skrll 		   && vliw2->insn_count == 1
    888  1.1  skrll 		   && (temp_insn = frv_find_in_vliw (VLIW_BRANCH_TYPE, vliw3, vliw1->insn_list->sym)) != NULL)
    889  1.1  skrll 	    {
    890  1.1  skrll 	      temp_insn->snop_frag->fr_subtype = NOP_KEEP;
    891  1.1  skrll 	      vliw1 = frv_tomcat_shuffle (VLIW_SINGLE_NOP, vliw3, vliw3->insn_list);
    892  1.1  skrll 	      if (tomcat_stats)
    893  1.1  skrll 		tomcat_singles++;
    894  1.1  skrll 	      goto workaround_top;
    895  1.1  skrll 	    }
    896  1.1  skrll 	}
    897  1.1  skrll     }
    898  1.1  skrll 
    899  1.1  skrll   if (vliw1->insn_count == 2)
    900  1.1  skrll     {
    901  1.1  skrll       struct vliw_insn_list *this_insn;
    902  1.1  skrll 
    903  1.1  skrll       /* check vliw1 for a label. */
    904  1.1  skrll       for (this_insn = vliw1->insn_list; this_insn; this_insn = this_insn->next)
    905  1.1  skrll 	{
    906  1.1  skrll 	  if (this_insn->type == VLIW_LABEL_TYPE)
    907  1.1  skrll 	    {
    908  1.1  skrll 	      if ((temp_insn = frv_find_in_vliw (VLIW_BRANCH_TYPE, vliw2, this_insn->sym)) != NULL)
    909  1.1  skrll 		{
    910  1.1  skrll 		  temp_insn->snop_frag->fr_subtype = NOP_KEEP;
    911  1.1  skrll 		  vliw1 = frv_tomcat_shuffle (VLIW_SINGLE_NOP, vliw2, this_insn);
    912  1.1  skrll 		  if (tomcat_stats)
    913  1.1  skrll 		    tomcat_singles++;
    914  1.1  skrll 		}
    915  1.1  skrll 	      else
    916  1.1  skrll 		vliw1 = vliw1->next;
    917  1.1  skrll               goto workaround_top;
    918  1.1  skrll             }
    919  1.1  skrll 	}
    920  1.1  skrll     }
    921  1.1  skrll   /* Examine each insn in this VLIW.  Look for the workaround criteria.  */
    922  1.1  skrll   for (this_insn = vliw1->insn_list; this_insn; this_insn = this_insn->next)
    923  1.1  skrll     {
    924  1.1  skrll       /* Don't look at labels or nops.  */
    925  1.1  skrll       while (this_insn
    926  1.1  skrll 	     && (this_insn->type == VLIW_LABEL_TYPE
    927  1.1  skrll                  || this_insn->type == VLIW_NOP_TYPE
    928  1.1  skrll 		 || this_insn->type == VLIW_BRANCH_HAS_NOPS))
    929  1.1  skrll 	this_insn = this_insn->next;
    930  1.1  skrll 
    931  1.1  skrll       if (!this_insn)
    932  1.1  skrll         {
    933  1.1  skrll 	  vliw1 = vliw2;
    934  1.1  skrll 	  goto workaround_top;
    935  1.1  skrll 	}
    936  1.1  skrll 
    937  1.1  skrll       if (frv_is_branch_insn (this_insn->insn))
    938  1.1  skrll 	{
    939  1.1  skrll 	  if ((temp_insn = frv_find_in_vliw (VLIW_LABEL_TYPE, vliw1, this_insn->sym)) != NULL)
    940  1.1  skrll 	    {
    941  1.1  skrll 	      /* Insert [nop/nop] [nop] before branch.  */
    942  1.1  skrll 	      this_insn->snop_frag->fr_subtype = NOP_KEEP;
    943  1.1  skrll 	      this_insn->dnop_frag->fr_subtype = NOP_KEEP;
    944  1.1  skrll 	      vliw1 = frv_tomcat_shuffle (VLIW_DOUBLE_THEN_SINGLE_NOP, vliw1, this_insn);
    945  1.1  skrll 	      goto workaround_top;
    946  1.1  skrll 	    }
    947  1.1  skrll 	}
    948  1.1  skrll 
    949  1.1  skrll 
    950  1.1  skrll     }
    951  1.1  skrll   /* This vliw insn checks out okay.  Take a look at the next one.  */
    952  1.1  skrll   vliw1 = vliw1->next;
    953  1.1  skrll   goto workaround_top;
    954  1.1  skrll }
    955  1.1  skrll 
    956  1.1  skrll void
    957  1.1  skrll frv_tomcat_workaround (void)
    958  1.1  skrll {
    959  1.1  skrll   if (frv_mach != bfd_mach_frvtomcat)
    960  1.1  skrll     return;
    961  1.1  skrll 
    962  1.1  skrll   if (tomcat_debug)
    963  1.1  skrll     frv_debug_tomcat (vliw_chain_top);
    964  1.1  skrll 
    965  1.1  skrll   frv_tomcat_analyze_vliw_chains ();
    966  1.1  skrll 
    967  1.1  skrll   if (tomcat_stats)
    968  1.1  skrll     {
    969  1.1  skrll       fprintf (stderr, "Inserted %d Single Nops\n", tomcat_singles);
    970  1.1  skrll       fprintf (stderr, "Inserted %d Double Nops\n", tomcat_doubles);
    971  1.1  skrll     }
    972  1.1  skrll }
    973  1.1  skrll 
    974  1.1  skrll static int
    975  1.1  skrll fr550_check_insn_acc_range (frv_insn *insn, int low, int hi)
    976  1.1  skrll {
    977  1.1  skrll   int acc;
    978  1.1  skrll   switch (CGEN_INSN_NUM (insn->insn))
    979  1.1  skrll     {
    980  1.1  skrll     case FRV_INSN_MADDACCS:
    981  1.1  skrll     case FRV_INSN_MSUBACCS:
    982  1.1  skrll     case FRV_INSN_MDADDACCS:
    983  1.1  skrll     case FRV_INSN_MDSUBACCS:
    984  1.1  skrll     case FRV_INSN_MASACCS:
    985  1.1  skrll     case FRV_INSN_MDASACCS:
    986  1.1  skrll       acc = insn->fields.f_ACC40Si;
    987  1.1  skrll       if (acc < low || acc > hi)
    988  1.1  skrll 	return 1; /* out of range */
    989  1.1  skrll       acc = insn->fields.f_ACC40Sk;
    990  1.1  skrll       if (acc < low || acc > hi)
    991  1.1  skrll 	return 1; /* out of range */
    992  1.1  skrll       break;
    993  1.1  skrll     case FRV_INSN_MMULHS:
    994  1.1  skrll     case FRV_INSN_MMULHU:
    995  1.1  skrll     case FRV_INSN_MMULXHS:
    996  1.1  skrll     case FRV_INSN_MMULXHU:
    997  1.1  skrll     case FRV_INSN_CMMULHS:
    998  1.1  skrll     case FRV_INSN_CMMULHU:
    999  1.1  skrll     case FRV_INSN_MQMULHS:
   1000  1.1  skrll     case FRV_INSN_MQMULHU:
   1001  1.1  skrll     case FRV_INSN_MQMULXHS:
   1002  1.1  skrll     case FRV_INSN_MQMULXHU:
   1003  1.1  skrll     case FRV_INSN_CMQMULHS:
   1004  1.1  skrll     case FRV_INSN_CMQMULHU:
   1005  1.1  skrll     case FRV_INSN_MMACHS:
   1006  1.1  skrll     case FRV_INSN_MMRDHS:
   1007  1.1  skrll     case FRV_INSN_CMMACHS:
   1008  1.1  skrll     case FRV_INSN_MQMACHS:
   1009  1.1  skrll     case FRV_INSN_CMQMACHS:
   1010  1.1  skrll     case FRV_INSN_MQXMACHS:
   1011  1.1  skrll     case FRV_INSN_MQXMACXHS:
   1012  1.1  skrll     case FRV_INSN_MQMACXHS:
   1013  1.1  skrll     case FRV_INSN_MCPXRS:
   1014  1.1  skrll     case FRV_INSN_MCPXIS:
   1015  1.1  skrll     case FRV_INSN_CMCPXRS:
   1016  1.1  skrll     case FRV_INSN_CMCPXIS:
   1017  1.1  skrll     case FRV_INSN_MQCPXRS:
   1018  1.1  skrll     case FRV_INSN_MQCPXIS:
   1019  1.1  skrll      acc = insn->fields.f_ACC40Sk;
   1020  1.1  skrll       if (acc < low || acc > hi)
   1021  1.1  skrll 	return 1; /* out of range */
   1022  1.1  skrll       break;
   1023  1.1  skrll     case FRV_INSN_MMACHU:
   1024  1.1  skrll     case FRV_INSN_MMRDHU:
   1025  1.1  skrll     case FRV_INSN_CMMACHU:
   1026  1.1  skrll     case FRV_INSN_MQMACHU:
   1027  1.1  skrll     case FRV_INSN_CMQMACHU:
   1028  1.1  skrll     case FRV_INSN_MCPXRU:
   1029  1.1  skrll     case FRV_INSN_MCPXIU:
   1030  1.1  skrll     case FRV_INSN_CMCPXRU:
   1031  1.1  skrll     case FRV_INSN_CMCPXIU:
   1032  1.1  skrll     case FRV_INSN_MQCPXRU:
   1033  1.1  skrll     case FRV_INSN_MQCPXIU:
   1034  1.1  skrll       acc = insn->fields.f_ACC40Uk;
   1035  1.1  skrll       if (acc < low || acc > hi)
   1036  1.1  skrll 	return 1; /* out of range */
   1037  1.1  skrll       break;
   1038  1.1  skrll     default:
   1039  1.1  skrll       break;
   1040  1.1  skrll     }
   1041  1.1  skrll   return 0; /* all is ok */
   1042  1.1  skrll }
   1043  1.1  skrll 
   1044  1.1  skrll static int
   1045  1.1  skrll fr550_check_acc_range (FRV_VLIW *vliw, frv_insn *insn)
   1046  1.1  skrll {
   1047  1.1  skrll   switch ((*vliw->current_vliw)[vliw->next_slot - 1])
   1048  1.1  skrll     {
   1049  1.1  skrll     case UNIT_FM0:
   1050  1.1  skrll     case UNIT_FM2:
   1051  1.1  skrll       return fr550_check_insn_acc_range (insn, 0, 3);
   1052  1.1  skrll     case UNIT_FM1:
   1053  1.1  skrll     case UNIT_FM3:
   1054  1.1  skrll       return fr550_check_insn_acc_range (insn, 4, 7);
   1055  1.1  skrll     default:
   1056  1.1  skrll       break;
   1057  1.1  skrll     }
   1058  1.1  skrll   return 0; /* all is ok */
   1059  1.1  skrll }
   1060  1.1  skrll 
   1061  1.1  skrll /* Return true if the target implements instruction INSN.  */
   1062  1.1  skrll 
   1063  1.1  skrll static bfd_boolean
   1064  1.1  skrll target_implements_insn_p (const CGEN_INSN *insn)
   1065  1.1  skrll {
   1066  1.1  skrll   switch (frv_mach)
   1067  1.1  skrll     {
   1068  1.1  skrll     default:
   1069  1.1  skrll       /* bfd_mach_frv or generic.  */
   1070  1.1  skrll       return TRUE;
   1071  1.1  skrll 
   1072  1.1  skrll     case bfd_mach_fr300:
   1073  1.1  skrll     case bfd_mach_frvsimple:
   1074  1.1  skrll       return CGEN_INSN_MACH_HAS_P (insn, MACH_SIMPLE);
   1075  1.1  skrll 
   1076  1.1  skrll     case bfd_mach_fr400:
   1077  1.1  skrll       return ((fr400_audio || !CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_AUDIO))
   1078  1.1  skrll 	      && CGEN_INSN_MACH_HAS_P (insn, MACH_FR400));
   1079  1.1  skrll 
   1080  1.1  skrll     case bfd_mach_fr450:
   1081  1.1  skrll       return CGEN_INSN_MACH_HAS_P (insn, MACH_FR450);
   1082  1.1  skrll 
   1083  1.1  skrll     case bfd_mach_fr500:
   1084  1.1  skrll       return CGEN_INSN_MACH_HAS_P (insn, MACH_FR500);
   1085  1.1  skrll 
   1086  1.1  skrll     case bfd_mach_fr550:
   1087  1.1  skrll       return CGEN_INSN_MACH_HAS_P (insn, MACH_FR550);
   1088  1.1  skrll     }
   1089  1.1  skrll }
   1090  1.1  skrll 
   1091  1.1  skrll void
   1092  1.1  skrll md_assemble (char *str)
   1093  1.1  skrll {
   1094  1.1  skrll   frv_insn insn;
   1095  1.1  skrll   char *errmsg;
   1096  1.1  skrll   int packing_constraint;
   1097  1.1  skrll   finished_insnS  finished_insn;
   1098  1.1  skrll   fragS *double_nop_frag = NULL;
   1099  1.1  skrll   fragS *single_nop_frag = NULL;
   1100  1.1  skrll   struct vliw_insn_list *vliw_insn_list_entry = NULL;
   1101  1.1  skrll 
   1102  1.1  skrll   /* Initialize GAS's cgen interface for a new instruction.  */
   1103  1.1  skrll   gas_cgen_init_parse ();
   1104  1.1  skrll 
   1105  1.1  skrll   memset (&insn, 0, sizeof (insn));
   1106  1.1  skrll 
   1107  1.1  skrll   insn.insn = frv_cgen_assemble_insn
   1108  1.1  skrll     (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, &errmsg);
   1109  1.1  skrll 
   1110  1.1  skrll   if (!insn.insn)
   1111  1.1  skrll     {
   1112  1.1  skrll       as_bad (errmsg);
   1113  1.1  skrll       return;
   1114  1.1  skrll     }
   1115  1.1  skrll 
   1116  1.1  skrll   /* If the cpu is tomcat, then we need to insert nops to workaround
   1117  1.1  skrll      hardware limitations.  We need to keep track of each vliw unit
   1118  1.1  skrll      and examine the length of the unit and the individual insns
   1119  1.1  skrll      within the unit to determine the number and location of the
   1120  1.1  skrll      required nops.  */
   1121  1.1  skrll   if (frv_mach == bfd_mach_frvtomcat)
   1122  1.1  skrll     {
   1123  1.1  skrll       /* If we've just finished a VLIW insn OR this is a branch,
   1124  1.1  skrll 	 then start up a new frag.  Fill it with nops.  We will get rid
   1125  1.1  skrll 	 of those that are not required after we've seen all of the
   1126  1.1  skrll 	 instructions but before we start resolving fixups.  */
   1127  1.1  skrll       if ( !FRV_IS_NOP (insn)
   1128  1.1  skrll 	  && (frv_is_branch_insn (insn.insn) || insn.fields.f_pack))
   1129  1.1  skrll 	{
   1130  1.1  skrll 	  char *buffer;
   1131  1.1  skrll 
   1132  1.1  skrll 	  frag_wane (frag_now);
   1133  1.1  skrll 	  frag_new (0);
   1134  1.1  skrll 	  double_nop_frag = frag_now;
   1135  1.1  skrll 	  buffer = frag_var (rs_machine_dependent, 8, 8, NOP_DELETE, NULL, 0, 0);
   1136  1.1  skrll 	  md_number_to_chars (buffer, FRV_NOP_PACK, 4);
   1137  1.1  skrll 	  md_number_to_chars (buffer+4, FRV_NOP_NOPACK, 4);
   1138  1.1  skrll 
   1139  1.1  skrll 	  frag_wane (frag_now);
   1140  1.1  skrll 	  frag_new (0);
   1141  1.1  skrll 	  single_nop_frag = frag_now;
   1142  1.1  skrll 	  buffer = frag_var (rs_machine_dependent, 4, 4, NOP_DELETE, NULL, 0, 0);
   1143  1.1  skrll 	  md_number_to_chars (buffer, FRV_NOP_NOPACK, 4);
   1144  1.1  skrll 	}
   1145  1.1  skrll 
   1146  1.1  skrll       vliw_insn_list_entry = frv_insert_vliw_insn (DO_COUNT);
   1147  1.1  skrll       vliw_insn_list_entry->insn   = insn.insn;
   1148  1.1  skrll       if (frv_is_branch_insn (insn.insn))
   1149  1.1  skrll 	vliw_insn_list_entry->type = VLIW_BRANCH_TYPE;
   1150  1.1  skrll 
   1151  1.1  skrll       if ( !FRV_IS_NOP (insn)
   1152  1.1  skrll 	  && (frv_is_branch_insn (insn.insn) || insn.fields.f_pack))
   1153  1.1  skrll 	{
   1154  1.1  skrll 	  vliw_insn_list_entry->snop_frag = single_nop_frag;
   1155  1.1  skrll 	  vliw_insn_list_entry->dnop_frag = double_nop_frag;
   1156  1.1  skrll 	}
   1157  1.1  skrll     }
   1158  1.1  skrll 
   1159  1.1  skrll   /* Make sure that this insn does not violate the VLIW packing constraints.  */
   1160  1.1  skrll   /* -mno-pack disallows any packing whatsoever.  */
   1161  1.1  skrll   if (frv_flags & EF_FRV_NOPACK)
   1162  1.1  skrll     {
   1163  1.1  skrll       if (! insn.fields.f_pack)
   1164  1.1  skrll 	{
   1165  1.1  skrll 	  as_bad (_("VLIW packing used for -mno-pack"));
   1166  1.1  skrll 	  return;
   1167  1.1  skrll 	}
   1168  1.1  skrll     }
   1169  1.1  skrll   /* -mcpu=FRV is an idealized FR-V implementation that supports all of the
   1170  1.1  skrll      instructions, don't do vliw checking.  */
   1171  1.1  skrll   else if (frv_mach != bfd_mach_frv)
   1172  1.1  skrll     {
   1173  1.1  skrll       if (!target_implements_insn_p (insn.insn))
   1174  1.1  skrll 	{
   1175  1.1  skrll 	  as_bad (_("Instruction not supported by this architecture"));
   1176  1.1  skrll 	  return;
   1177  1.1  skrll 	}
   1178  1.1  skrll       packing_constraint = frv_vliw_add_insn (& vliw, insn.insn);
   1179  1.1  skrll       if (frv_mach == bfd_mach_fr550 && ! packing_constraint)
   1180  1.1  skrll 	packing_constraint = fr550_check_acc_range (& vliw, & insn);
   1181  1.1  skrll       if (insn.fields.f_pack)
   1182  1.1  skrll 	frv_vliw_reset (& vliw, frv_mach, frv_flags);
   1183  1.1  skrll       if (packing_constraint)
   1184  1.1  skrll 	{
   1185  1.1  skrll 	  as_bad (_("VLIW packing constraint violation"));
   1186  1.1  skrll 	  return;
   1187  1.1  skrll 	}
   1188  1.1  skrll     }
   1189  1.1  skrll 
   1190  1.1  skrll   /* Doesn't really matter what we pass for RELAX_P here.  */
   1191  1.1  skrll   gas_cgen_finish_insn (insn.insn, insn.buffer,
   1192  1.1  skrll 			CGEN_FIELDS_BITSIZE (& insn.fields), 1, &finished_insn);
   1193  1.1  skrll 
   1194  1.1  skrll 
   1195  1.1  skrll   /* If the cpu is tomcat, then we need to insert nops to workaround
   1196  1.1  skrll      hardware limitations.  We need to keep track of each vliw unit
   1197  1.1  skrll      and examine the length of the unit and the individual insns
   1198  1.1  skrll      within the unit to determine the number and location of the
   1199  1.1  skrll      required nops.  */
   1200  1.1  skrll   if (frv_mach == bfd_mach_frvtomcat)
   1201  1.1  skrll     {
   1202  1.1  skrll       if (vliw_insn_list_entry)
   1203  1.1  skrll         vliw_insn_list_entry->address = finished_insn.addr;
   1204  1.1  skrll       else
   1205  1.1  skrll 	abort();
   1206  1.1  skrll 
   1207  1.1  skrll       if (insn.fields.f_pack)
   1208  1.1  skrll 	{
   1209  1.1  skrll 	  /* We've completed a VLIW insn.  */
   1210  1.1  skrll 	  previous_vliw_chain = current_vliw_chain;
   1211  1.1  skrll 	  current_vliw_chain = NULL;
   1212  1.1  skrll 	  current_vliw_insn  = NULL;
   1213  1.1  skrll         }
   1214  1.1  skrll     }
   1215  1.1  skrll }
   1216  1.1  skrll 
   1217  1.1  skrll /* The syntax in the manual says constants begin with '#'.
   1218  1.1  skrll    We just ignore it.  */
   1219  1.1  skrll 
   1220  1.1  skrll void
   1221  1.1  skrll md_operand (expressionS *expressionP)
   1222  1.1  skrll {
   1223  1.1  skrll   if (* input_line_pointer == '#')
   1224  1.1  skrll     {
   1225  1.1  skrll       input_line_pointer ++;
   1226  1.1  skrll       expression (expressionP);
   1227  1.1  skrll     }
   1228  1.1  skrll }
   1229  1.1  skrll 
   1230  1.1  skrll valueT
   1231  1.1  skrll md_section_align (segT segment, valueT size)
   1232  1.1  skrll {
   1233  1.1  skrll   int align = bfd_get_section_alignment (stdoutput, segment);
   1234  1.1  skrll   return ((size + (1 << align) - 1) & (-1 << align));
   1235  1.1  skrll }
   1236  1.1  skrll 
   1237  1.1  skrll symbolS *
   1238  1.1  skrll md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
   1239  1.1  skrll {
   1240  1.1  skrll   return 0;
   1241  1.1  skrll }
   1242  1.1  skrll 
   1243  1.1  skrll /* Interface to relax_segment.  */
   1245  1.1  skrll 
   1246  1.1  skrll /* FIXME: Build table by hand, get it working, then machine generate.  */
   1247  1.1  skrll const relax_typeS md_relax_table[] =
   1248  1.1  skrll {
   1249  1.1  skrll   {1, 1, 0, 0},
   1250  1.1  skrll   {511 - 2 - 2, -512 - 2 + 2, 0, 2 },
   1251  1.1  skrll   {0x2000000 - 1 - 2, -0x2000000 - 2, 2, 0 },
   1252  1.1  skrll   {0x2000000 - 1 - 2, -0x2000000 - 2, 4, 0 }
   1253  1.1  skrll };
   1254  1.1  skrll 
   1255  1.1  skrll long
   1256  1.1  skrll frv_relax_frag (fragS *fragP ATTRIBUTE_UNUSED, long stretch ATTRIBUTE_UNUSED)
   1257  1.1  skrll {
   1258  1.1  skrll   return 0;
   1259  1.1  skrll }
   1260  1.1  skrll 
   1261  1.1  skrll /* Return an initial guess of the length by which a fragment must grow to
   1262  1.1  skrll    hold a branch to reach its destination.
   1263  1.1  skrll    Also updates fr_type/fr_subtype as necessary.
   1264  1.1  skrll 
   1265  1.1  skrll    Called just before doing relaxation.
   1266  1.1  skrll    Any symbol that is now undefined will not become defined.
   1267  1.1  skrll    The guess for fr_var is ACTUALLY the growth beyond fr_fix.
   1268  1.1  skrll    Whatever we do to grow fr_fix or fr_var contributes to our returned value.
   1269  1.1  skrll    Although it may not be explicit in the frag, pretend fr_var starts with a
   1270  1.1  skrll    0 value.  */
   1271  1.1  skrll 
   1272  1.1  skrll int
   1273  1.1  skrll md_estimate_size_before_relax (fragS *fragP, segT segment ATTRIBUTE_UNUSED)
   1274  1.1  skrll {
   1275  1.1  skrll   switch (fragP->fr_subtype)
   1276  1.1  skrll     {
   1277  1.1  skrll     case NOP_KEEP:
   1278  1.1  skrll       return fragP->fr_var;
   1279  1.1  skrll 
   1280  1.1  skrll     default:
   1281  1.1  skrll     case NOP_DELETE:
   1282  1.1  skrll       return 0;
   1283  1.1  skrll     }
   1284  1.1  skrll }
   1285  1.1  skrll 
   1286  1.1  skrll /* *fragP has been relaxed to its final size, and now needs to have
   1287  1.1  skrll    the bytes inside it modified to conform to the new size.
   1288  1.1  skrll 
   1289  1.1  skrll    Called after relaxation is finished.
   1290  1.1  skrll    fragP->fr_type == rs_machine_dependent.
   1291  1.1  skrll    fragP->fr_subtype is the subtype of what the address relaxed to.  */
   1292  1.1  skrll 
   1293  1.1  skrll void
   1294  1.1  skrll md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
   1295  1.1  skrll 		 segT sec ATTRIBUTE_UNUSED,
   1296  1.1  skrll 		 fragS *fragP)
   1297  1.1  skrll {
   1298  1.1  skrll   switch (fragP->fr_subtype)
   1299  1.1  skrll     {
   1300  1.1  skrll     default:
   1301  1.1  skrll     case NOP_DELETE:
   1302  1.1  skrll       return;
   1303  1.1  skrll 
   1304  1.1  skrll     case NOP_KEEP:
   1305  1.1  skrll       fragP->fr_fix = fragP->fr_var;
   1306  1.1  skrll       fragP->fr_var = 0;
   1307  1.1  skrll       return;
   1308  1.1  skrll     }
   1309  1.1  skrll }
   1310  1.1  skrll 
   1311  1.1  skrll /* Functions concerning relocs.  */
   1313  1.1  skrll 
   1314  1.1  skrll /* The location from which a PC relative jump should be calculated,
   1315  1.1  skrll    given a PC relative reloc.  */
   1316  1.1  skrll 
   1317  1.1  skrll long
   1318  1.1  skrll md_pcrel_from_section (fixS *fixP, segT sec)
   1319  1.1  skrll {
   1320  1.1  skrll   if (TC_FORCE_RELOCATION (fixP)
   1321  1.1  skrll       || (fixP->fx_addsy != (symbolS *) NULL
   1322  1.1  skrll 	  && S_GET_SEGMENT (fixP->fx_addsy) != sec))
   1323  1.1  skrll     {
   1324  1.1  skrll       /* If we can't adjust this relocation, or if it references a
   1325  1.1  skrll 	 local symbol in a different section (which
   1326  1.1  skrll 	 TC_FORCE_RELOCATION can't check), let the linker figure it
   1327  1.1  skrll 	 out.  */
   1328  1.1  skrll       return 0;
   1329  1.1  skrll     }
   1330  1.1  skrll 
   1331  1.1  skrll   return (fixP->fx_frag->fr_address + fixP->fx_where) & ~1;
   1332  1.1  skrll }
   1333  1.1  skrll 
   1334  1.1  skrll /* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
   1335  1.1  skrll    Returns BFD_RELOC_NONE if no reloc type can be found.
   1336  1.1  skrll    *FIXP may be modified if desired.  */
   1337  1.1  skrll 
   1338  1.1  skrll bfd_reloc_code_real_type
   1339  1.1  skrll md_cgen_lookup_reloc (const CGEN_INSN *insn ATTRIBUTE_UNUSED,
   1340  1.1  skrll 		      const CGEN_OPERAND *operand,
   1341  1.1  skrll 		      fixS *fixP)
   1342  1.1  skrll {
   1343  1.1  skrll   switch (operand->type)
   1344  1.1  skrll     {
   1345  1.1  skrll     case FRV_OPERAND_LABEL16:
   1346  1.1  skrll       fixP->fx_pcrel = TRUE;
   1347  1.1  skrll       return BFD_RELOC_FRV_LABEL16;
   1348  1.1  skrll 
   1349  1.1  skrll     case FRV_OPERAND_LABEL24:
   1350  1.1  skrll       fixP->fx_pcrel = TRUE;
   1351  1.1  skrll 
   1352  1.1  skrll       if (fixP->fx_cgen.opinfo != 0)
   1353  1.1  skrll 	return fixP->fx_cgen.opinfo;
   1354  1.1  skrll 
   1355  1.1  skrll       return BFD_RELOC_FRV_LABEL24;
   1356  1.1  skrll 
   1357  1.1  skrll     case FRV_OPERAND_UHI16:
   1358  1.1  skrll     case FRV_OPERAND_ULO16:
   1359  1.1  skrll     case FRV_OPERAND_SLO16:
   1360  1.1  skrll     case FRV_OPERAND_CALLANN:
   1361  1.1  skrll     case FRV_OPERAND_LDANN:
   1362  1.1  skrll     case FRV_OPERAND_LDDANN:
   1363  1.1  skrll       /* The relocation type should be recorded in opinfo */
   1364  1.1  skrll       if (fixP->fx_cgen.opinfo != 0)
   1365  1.1  skrll         return fixP->fx_cgen.opinfo;
   1366  1.1  skrll       break;
   1367  1.1  skrll 
   1368  1.1  skrll     case FRV_OPERAND_D12:
   1369  1.1  skrll     case FRV_OPERAND_S12:
   1370  1.1  skrll       if (fixP->fx_cgen.opinfo != 0)
   1371  1.1  skrll 	return fixP->fx_cgen.opinfo;
   1372  1.1  skrll 
   1373  1.1  skrll       return BFD_RELOC_FRV_GPREL12;
   1374  1.1  skrll 
   1375  1.1  skrll     case FRV_OPERAND_U12:
   1376  1.1  skrll       return BFD_RELOC_FRV_GPRELU12;
   1377  1.1  skrll 
   1378  1.1  skrll     default:
   1379  1.1  skrll       break;
   1380  1.1  skrll     }
   1381  1.1  skrll   return BFD_RELOC_NONE;
   1382  1.1  skrll }
   1383  1.1  skrll 
   1384  1.1  skrll 
   1385  1.1  skrll /* See whether we need to force a relocation into the output file.
   1386  1.1  skrll    This is used to force out switch and PC relative relocations when
   1387  1.1  skrll    relaxing.  */
   1388  1.1  skrll 
   1389  1.1  skrll int
   1390  1.1  skrll frv_force_relocation (fixS *fix)
   1391  1.1  skrll {
   1392  1.1  skrll   switch (fix->fx_r_type < BFD_RELOC_UNUSED
   1393  1.1  skrll 	  ? (int) fix->fx_r_type
   1394  1.1  skrll 	  : fix->fx_cgen.opinfo)
   1395  1.1  skrll     {
   1396  1.1  skrll     case BFD_RELOC_FRV_GPREL12:
   1397  1.1  skrll     case BFD_RELOC_FRV_GPRELU12:
   1398  1.1  skrll     case BFD_RELOC_FRV_GPREL32:
   1399  1.1  skrll     case BFD_RELOC_FRV_GPRELHI:
   1400  1.1  skrll     case BFD_RELOC_FRV_GPRELLO:
   1401  1.1  skrll     case BFD_RELOC_FRV_GOT12:
   1402  1.1  skrll     case BFD_RELOC_FRV_GOTHI:
   1403  1.1  skrll     case BFD_RELOC_FRV_GOTLO:
   1404  1.1  skrll     case BFD_RELOC_FRV_FUNCDESC_VALUE:
   1405  1.1  skrll     case BFD_RELOC_FRV_FUNCDESC_GOTOFF12:
   1406  1.1  skrll     case BFD_RELOC_FRV_FUNCDESC_GOTOFFHI:
   1407  1.1  skrll     case BFD_RELOC_FRV_FUNCDESC_GOTOFFLO:
   1408  1.1  skrll     case BFD_RELOC_FRV_GOTOFF12:
   1409  1.1  skrll     case BFD_RELOC_FRV_GOTOFFHI:
   1410  1.1  skrll     case BFD_RELOC_FRV_GOTOFFLO:
   1411  1.1  skrll     case BFD_RELOC_FRV_GETTLSOFF:
   1412  1.1  skrll     case BFD_RELOC_FRV_TLSDESC_VALUE:
   1413  1.1  skrll     case BFD_RELOC_FRV_GOTTLSDESC12:
   1414  1.1  skrll     case BFD_RELOC_FRV_GOTTLSDESCHI:
   1415  1.1  skrll     case BFD_RELOC_FRV_GOTTLSDESCLO:
   1416  1.1  skrll     case BFD_RELOC_FRV_TLSMOFF12:
   1417  1.1  skrll     case BFD_RELOC_FRV_TLSMOFFHI:
   1418  1.1  skrll     case BFD_RELOC_FRV_TLSMOFFLO:
   1419  1.1  skrll     case BFD_RELOC_FRV_GOTTLSOFF12:
   1420  1.1  skrll     case BFD_RELOC_FRV_GOTTLSOFFHI:
   1421  1.1  skrll     case BFD_RELOC_FRV_GOTTLSOFFLO:
   1422  1.1  skrll     case BFD_RELOC_FRV_TLSOFF:
   1423  1.1  skrll     case BFD_RELOC_FRV_TLSDESC_RELAX:
   1424  1.1  skrll     case BFD_RELOC_FRV_GETTLSOFF_RELAX:
   1425  1.1  skrll     case BFD_RELOC_FRV_TLSOFF_RELAX:
   1426  1.1  skrll       return 1;
   1427  1.1  skrll 
   1428  1.1  skrll     default:
   1429  1.1  skrll       break;
   1430  1.1  skrll     }
   1431  1.1  skrll 
   1432  1.1  skrll   return generic_force_reloc (fix);
   1433  1.1  skrll }
   1434  1.1  skrll 
   1435  1.1  skrll /* Apply a fixup that could be resolved within the assembler.  */
   1436  1.1  skrll 
   1437  1.1  skrll void
   1438  1.1  skrll md_apply_fix (fixS *fixP, valueT *valP, segT seg)
   1439  1.1  skrll {
   1440  1.1  skrll   if (fixP->fx_addsy == 0)
   1441  1.1  skrll     switch (fixP->fx_cgen.opinfo)
   1442  1.1  skrll       {
   1443  1.1  skrll       case BFD_RELOC_FRV_HI16:
   1444  1.1  skrll 	*valP >>= 16;
   1445  1.1  skrll 	/* Fall through.  */
   1446  1.1  skrll       case BFD_RELOC_FRV_LO16:
   1447  1.1  skrll 	*valP &= 0xffff;
   1448  1.1  skrll 	break;
   1449  1.1  skrll 
   1450  1.1  skrll 	/* We need relocations for these, even if their symbols reduce
   1451  1.1  skrll 	   to constants.  */
   1452  1.1  skrll       case BFD_RELOC_FRV_GPREL12:
   1453  1.1  skrll       case BFD_RELOC_FRV_GPRELU12:
   1454  1.1  skrll       case BFD_RELOC_FRV_GPREL32:
   1455  1.1  skrll       case BFD_RELOC_FRV_GPRELHI:
   1456  1.1  skrll       case BFD_RELOC_FRV_GPRELLO:
   1457  1.1  skrll       case BFD_RELOC_FRV_GOT12:
   1458  1.1  skrll       case BFD_RELOC_FRV_GOTHI:
   1459  1.1  skrll       case BFD_RELOC_FRV_GOTLO:
   1460  1.1  skrll       case BFD_RELOC_FRV_FUNCDESC_VALUE:
   1461  1.1  skrll       case BFD_RELOC_FRV_FUNCDESC_GOTOFF12:
   1462  1.1  skrll       case BFD_RELOC_FRV_FUNCDESC_GOTOFFHI:
   1463  1.1  skrll       case BFD_RELOC_FRV_FUNCDESC_GOTOFFLO:
   1464  1.1  skrll       case BFD_RELOC_FRV_GOTOFF12:
   1465  1.1  skrll       case BFD_RELOC_FRV_GOTOFFHI:
   1466  1.1  skrll       case BFD_RELOC_FRV_GOTOFFLO:
   1467  1.1  skrll       case BFD_RELOC_FRV_GETTLSOFF:
   1468  1.1  skrll       case BFD_RELOC_FRV_TLSDESC_VALUE:
   1469  1.1  skrll       case BFD_RELOC_FRV_GOTTLSDESC12:
   1470  1.1  skrll       case BFD_RELOC_FRV_GOTTLSDESCHI:
   1471  1.1  skrll       case BFD_RELOC_FRV_GOTTLSDESCLO:
   1472  1.1  skrll       case BFD_RELOC_FRV_TLSMOFF12:
   1473  1.1  skrll       case BFD_RELOC_FRV_TLSMOFFHI:
   1474  1.1  skrll       case BFD_RELOC_FRV_TLSMOFFLO:
   1475  1.1  skrll       case BFD_RELOC_FRV_GOTTLSOFF12:
   1476  1.1  skrll       case BFD_RELOC_FRV_GOTTLSOFFHI:
   1477  1.1  skrll       case BFD_RELOC_FRV_GOTTLSOFFLO:
   1478  1.1  skrll       case BFD_RELOC_FRV_TLSOFF:
   1479  1.1  skrll       case BFD_RELOC_FRV_TLSDESC_RELAX:
   1480  1.1  skrll       case BFD_RELOC_FRV_GETTLSOFF_RELAX:
   1481  1.1  skrll       case BFD_RELOC_FRV_TLSOFF_RELAX:
   1482  1.1  skrll 	fixP->fx_addsy = abs_section_sym;
   1483  1.1  skrll 	break;
   1484  1.1  skrll       }
   1485  1.1  skrll   else
   1486  1.1  skrll     switch (fixP->fx_cgen.opinfo)
   1487  1.1  skrll       {
   1488  1.1  skrll       case BFD_RELOC_FRV_GETTLSOFF:
   1489  1.1  skrll       case BFD_RELOC_FRV_TLSDESC_VALUE:
   1490  1.1  skrll       case BFD_RELOC_FRV_GOTTLSDESC12:
   1491  1.1  skrll       case BFD_RELOC_FRV_GOTTLSDESCHI:
   1492  1.1  skrll       case BFD_RELOC_FRV_GOTTLSDESCLO:
   1493  1.1  skrll       case BFD_RELOC_FRV_TLSMOFF12:
   1494  1.1  skrll       case BFD_RELOC_FRV_TLSMOFFHI:
   1495  1.1  skrll       case BFD_RELOC_FRV_TLSMOFFLO:
   1496  1.1  skrll       case BFD_RELOC_FRV_GOTTLSOFF12:
   1497  1.1  skrll       case BFD_RELOC_FRV_GOTTLSOFFHI:
   1498  1.1  skrll       case BFD_RELOC_FRV_GOTTLSOFFLO:
   1499  1.1  skrll       case BFD_RELOC_FRV_TLSOFF:
   1500  1.1  skrll       case BFD_RELOC_FRV_TLSDESC_RELAX:
   1501  1.1  skrll       case BFD_RELOC_FRV_GETTLSOFF_RELAX:
   1502  1.1  skrll       case BFD_RELOC_FRV_TLSOFF_RELAX:
   1503  1.1  skrll 	/* Mark TLS symbols as such.  */
   1504  1.1  skrll 	if (S_GET_SEGMENT (fixP->fx_addsy) != absolute_section)
   1505  1.1  skrll 	  S_SET_THREAD_LOCAL (fixP->fx_addsy);
   1506  1.1  skrll 	break;
   1507  1.1  skrll       }
   1508  1.1  skrll 
   1509  1.1  skrll   gas_cgen_md_apply_fix (fixP, valP, seg);
   1510  1.1  skrll   return;
   1511  1.1  skrll }
   1512  1.1  skrll 
   1513  1.1  skrll 
   1514  1.1  skrll /* Write a value out to the object file, using the appropriate endianness.  */
   1516  1.1  skrll 
   1517  1.1  skrll void
   1518  1.1  skrll frv_md_number_to_chars (char *buf, valueT val, int n)
   1519  1.1  skrll {
   1520  1.1  skrll   number_to_chars_bigendian (buf, val, n);
   1521  1.1  skrll }
   1522  1.1  skrll 
   1523  1.1  skrll char *
   1524  1.1  skrll md_atof (int type, char *litP, int *sizeP)
   1525  1.1  skrll {
   1526  1.1  skrll   return ieee_md_atof (type, litP, sizeP, TRUE);
   1527  1.1  skrll }
   1528  1.1  skrll 
   1529  1.1  skrll bfd_boolean
   1530  1.1  skrll frv_fix_adjustable (fixS *fixP)
   1531  1.1  skrll {
   1532  1.1  skrll   bfd_reloc_code_real_type reloc_type;
   1533  1.1  skrll 
   1534  1.1  skrll   if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
   1535  1.1  skrll     {
   1536  1.1  skrll       const CGEN_INSN *insn = NULL;
   1537  1.1  skrll       int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
   1538  1.1  skrll       const CGEN_OPERAND *operand = cgen_operand_lookup_by_num(gas_cgen_cpu_desc, opindex);
   1539  1.1  skrll       reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
   1540  1.1  skrll     }
   1541  1.1  skrll   else
   1542  1.1  skrll     reloc_type = fixP->fx_r_type;
   1543  1.1  skrll 
   1544  1.1  skrll   /* We need the symbol name for the VTABLE entries */
   1545  1.1  skrll   if (   reloc_type == BFD_RELOC_VTABLE_INHERIT
   1546  1.1  skrll       || reloc_type == BFD_RELOC_VTABLE_ENTRY
   1547  1.1  skrll       || reloc_type == BFD_RELOC_FRV_GPREL12
   1548  1.1  skrll       || reloc_type == BFD_RELOC_FRV_GPRELU12)
   1549  1.1  skrll     return 0;
   1550  1.1  skrll 
   1551  1.1  skrll   return 1;
   1552  1.1  skrll }
   1553  1.1  skrll 
   1554  1.1  skrll /* Allow user to set flags bits.  */
   1555  1.1  skrll void
   1556  1.1  skrll frv_set_flags (int arg ATTRIBUTE_UNUSED)
   1557  1.1  skrll {
   1558  1.1  skrll   flagword new_flags = get_absolute_expression ();
   1559  1.1  skrll   flagword new_mask = ~ (flagword)0;
   1560  1.1  skrll 
   1561  1.1  skrll   frv_user_set_flags_p = 1;
   1562  1.1  skrll   if (*input_line_pointer == ',')
   1563  1.1  skrll     {
   1564  1.1  skrll       ++input_line_pointer;
   1565  1.1  skrll       new_mask = get_absolute_expression ();
   1566  1.1  skrll     }
   1567  1.1  skrll 
   1568  1.1  skrll   frv_flags = (frv_flags & ~new_mask) | (new_flags & new_mask);
   1569  1.1  skrll   bfd_set_private_flags (stdoutput, frv_flags);
   1570  1.1  skrll }
   1571  1.1  skrll 
   1572  1.1  skrll /* Frv specific function to handle 4 byte initializations for pointers that are
   1573  1.1  skrll    considered 'safe' for use with pic support.  Until frv_frob_file{,_section}
   1574  1.1  skrll    is run, we encode it a BFD_RELOC_CTOR, and it is turned back into a normal
   1575  1.1  skrll    BFD_RELOC_32 at that time.  */
   1576  1.1  skrll 
   1577  1.1  skrll void
   1578  1.1  skrll frv_pic_ptr (int nbytes)
   1579  1.1  skrll {
   1580  1.1  skrll   expressionS exp;
   1581  1.1  skrll   char *p;
   1582  1.1  skrll 
   1583  1.1  skrll   if (nbytes != 4)
   1584  1.1  skrll     abort ();
   1585  1.1  skrll 
   1586  1.1  skrll #ifdef md_flush_pending_output
   1587  1.1  skrll   md_flush_pending_output ();
   1588  1.1  skrll #endif
   1589  1.1  skrll 
   1590  1.1  skrll   if (is_it_end_of_statement ())
   1591  1.1  skrll     {
   1592  1.1  skrll       demand_empty_rest_of_line ();
   1593  1.1  skrll       return;
   1594  1.1  skrll     }
   1595  1.1  skrll 
   1596  1.1  skrll #ifdef md_cons_align
   1597  1.1  skrll   md_cons_align (nbytes);
   1598  1.1  skrll #endif
   1599  1.1  skrll 
   1600  1.1  skrll   do
   1601  1.1  skrll     {
   1602  1.1  skrll       bfd_reloc_code_real_type reloc_type = BFD_RELOC_CTOR;
   1603  1.1  skrll 
   1604  1.1  skrll       if (strncasecmp (input_line_pointer, "funcdesc(", 9) == 0)
   1605  1.1  skrll 	{
   1606  1.1  skrll 	  input_line_pointer += 9;
   1607  1.1  skrll 	  expression (&exp);
   1608  1.1  skrll 	  if (*input_line_pointer == ')')
   1609  1.1  skrll 	    input_line_pointer++;
   1610  1.1  skrll 	  else
   1611  1.1  skrll 	    as_bad (_("missing ')'"));
   1612  1.1  skrll 	  reloc_type = BFD_RELOC_FRV_FUNCDESC;
   1613  1.1  skrll 	}
   1614  1.1  skrll       else if (strncasecmp (input_line_pointer, "tlsmoff(", 8) == 0)
   1615  1.1  skrll 	{
   1616  1.1  skrll 	  input_line_pointer += 8;
   1617  1.1  skrll 	  expression (&exp);
   1618  1.1  skrll 	  if (*input_line_pointer == ')')
   1619  1.1  skrll 	    input_line_pointer++;
   1620  1.1  skrll 	  else
   1621  1.1  skrll 	    as_bad (_("missing ')'"));
   1622  1.1  skrll 	  reloc_type = BFD_RELOC_FRV_TLSMOFF;
   1623  1.1  skrll 	}
   1624  1.1  skrll       else
   1625  1.1  skrll 	expression (&exp);
   1626  1.1  skrll 
   1627  1.1  skrll       p = frag_more (4);
   1628  1.1  skrll       memset (p, 0, 4);
   1629  1.1  skrll       fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &exp, 0,
   1630  1.1  skrll 		   reloc_type);
   1631  1.1  skrll     }
   1632  1.1  skrll   while (*input_line_pointer++ == ',');
   1633  1.1  skrll 
   1634  1.1  skrll   input_line_pointer--;			/* Put terminator back into stream. */
   1635  1.1  skrll   demand_empty_rest_of_line ();
   1636  1.1  skrll }
   1637  1.1  skrll 
   1638  1.1  skrll 
   1639  1.1  skrll 
   1641  1.1  skrll #ifdef DEBUG
   1642  1.1  skrll #define DPRINTF1(A)	fprintf (stderr, A)
   1643  1.1  skrll #define DPRINTF2(A,B)	fprintf (stderr, A, B)
   1644  1.1  skrll #define DPRINTF3(A,B,C)	fprintf (stderr, A, B, C)
   1645  1.1  skrll 
   1646  1.1  skrll #else
   1647  1.1  skrll #define DPRINTF1(A)
   1648  1.1  skrll #define DPRINTF2(A,B)
   1649  1.1  skrll #define DPRINTF3(A,B,C)
   1650  1.1  skrll #endif
   1651  1.1  skrll 
   1652  1.1  skrll /* Go through a the sections looking for relocations that are problematical for
   1653  1.1  skrll    pic.  If not pic, just note that this object can't be linked with pic.  If
   1654  1.1  skrll    it is pic, see if it needs to be marked so that it will be fixed up, or if
   1655  1.1  skrll    not possible, issue an error.  */
   1656  1.1  skrll 
   1657  1.1  skrll static void
   1658  1.1  skrll frv_frob_file_section (bfd *abfd, asection *sec, void *ptr ATTRIBUTE_UNUSED)
   1659  1.1  skrll {
   1660  1.1  skrll   segment_info_type *seginfo = seg_info (sec);
   1661  1.1  skrll   fixS *fixp;
   1662  1.1  skrll   CGEN_CPU_DESC cd = gas_cgen_cpu_desc;
   1663  1.1  skrll   flagword flags = bfd_get_section_flags (abfd, sec);
   1664  1.1  skrll 
   1665  1.1  skrll   /* Skip relocations in known sections (.ctors, .dtors, and .gcc_except_table)
   1666  1.1  skrll      since we can fix those up by hand.  */
   1667  1.1  skrll   int known_section_p = (sec->name
   1668  1.1  skrll 			 && sec->name[0] == '.'
   1669  1.1  skrll 			 && ((sec->name[1] == 'c'
   1670  1.1  skrll 			      && strcmp (sec->name, ".ctor") == 0)
   1671  1.1  skrll 			     || (sec->name[1] == 'd'
   1672  1.1  skrll 				 && strcmp (sec->name, ".dtor") == 0)
   1673  1.1  skrll 			     || (sec->name[1] == 'g'
   1674  1.1  skrll 				 && strcmp (sec->name, ".gcc_except_table") == 0)));
   1675  1.1  skrll 
   1676  1.1  skrll   DPRINTF3 ("\nFrv section %s%s\n", sec->name, (known_section_p) ? ", known section" : "");
   1677  1.1  skrll   if ((flags & SEC_ALLOC) == 0)
   1678  1.1  skrll     {
   1679  1.1  skrll       DPRINTF1 ("\tSkipping non-loaded section\n");
   1680  1.1  skrll       return;
   1681  1.1  skrll     }
   1682  1.1  skrll 
   1683  1.1  skrll   for (fixp = seginfo->fix_root; fixp; fixp = fixp->fx_next)
   1684  1.1  skrll     {
   1685  1.1  skrll       symbolS *s = fixp->fx_addsy;
   1686  1.1  skrll       bfd_reloc_code_real_type reloc;
   1687  1.1  skrll       int non_pic_p;
   1688  1.1  skrll       int opindex;
   1689  1.1  skrll       const CGEN_OPERAND *operand;
   1690  1.1  skrll       const CGEN_INSN *insn = fixp->fx_cgen.insn;
   1691  1.1  skrll 
   1692  1.1  skrll       if (fixp->fx_done)
   1693  1.1  skrll 	{
   1694  1.1  skrll 	  DPRINTF1 ("\tSkipping reloc that has already been done\n");
   1695  1.1  skrll 	  continue;
   1696  1.1  skrll 	}
   1697  1.1  skrll 
   1698  1.1  skrll       if (fixp->fx_pcrel)
   1699  1.1  skrll 	{
   1700  1.1  skrll 	  DPRINTF1 ("\tSkipping reloc that is PC relative\n");
   1701  1.1  skrll 	  continue;
   1702  1.1  skrll 	}
   1703  1.1  skrll 
   1704  1.1  skrll       if (! s)
   1705  1.1  skrll 	{
   1706  1.1  skrll 	  DPRINTF1 ("\tSkipping reloc without symbol\n");
   1707  1.1  skrll 	  continue;
   1708  1.1  skrll 	}
   1709  1.1  skrll 
   1710  1.1  skrll       if (fixp->fx_r_type < BFD_RELOC_UNUSED)
   1711  1.1  skrll 	{
   1712  1.1  skrll 	  opindex = -1;
   1713  1.1  skrll 	  reloc = fixp->fx_r_type;
   1714  1.1  skrll 	}
   1715  1.1  skrll       else
   1716  1.1  skrll 	{
   1717  1.1  skrll 	  opindex = (int) fixp->fx_r_type - (int) BFD_RELOC_UNUSED;
   1718  1.1  skrll 	  operand = cgen_operand_lookup_by_num (cd, opindex);
   1719  1.1  skrll 	  reloc = md_cgen_lookup_reloc (insn, operand, fixp);
   1720  1.1  skrll 	}
   1721  1.1  skrll 
   1722  1.1  skrll       DPRINTF3 ("\treloc %s\t%s", bfd_get_reloc_code_name (reloc), S_GET_NAME (s));
   1723  1.1  skrll 
   1724  1.1  skrll       non_pic_p = 0;
   1725  1.1  skrll       switch (reloc)
   1726  1.1  skrll 	{
   1727  1.1  skrll 	default:
   1728  1.1  skrll 	  break;
   1729  1.1  skrll 
   1730  1.1  skrll 	case BFD_RELOC_32:
   1731  1.1  skrll 	  /* Skip relocations in known sections (.ctors, .dtors, and
   1732  1.1  skrll 	     .gcc_except_table) since we can fix those up by hand.  Also
   1733  1.1  skrll 	     skip forward references to constants.  Also skip a difference
   1734  1.1  skrll 	     of two symbols, which still uses the BFD_RELOC_32 at this
   1735  1.1  skrll 	     point.  */
   1736  1.1  skrll 	  if (! known_section_p
   1737  1.1  skrll 	      && S_GET_SEGMENT (s) != absolute_section
   1738  1.1  skrll 	      && !fixp->fx_subsy
   1739  1.1  skrll 	      && (flags & (SEC_READONLY | SEC_CODE)) == 0)
   1740  1.1  skrll 	    {
   1741  1.1  skrll 	      non_pic_p = 1;
   1742  1.1  skrll 	    }
   1743  1.1  skrll 	  break;
   1744  1.1  skrll 
   1745  1.1  skrll 	  /* FIXME -- should determine if any of the GP relocation really uses
   1746  1.1  skrll 	     gr16 (which is not pic safe) or not.  Right now, assume if we
   1747  1.1  skrll 	     aren't being compiled with -mpic, the usage is non pic safe, but
   1748  1.1  skrll 	     is safe with -mpic.  */
   1749  1.1  skrll 	case BFD_RELOC_FRV_GPREL12:
   1750  1.1  skrll 	case BFD_RELOC_FRV_GPRELU12:
   1751  1.1  skrll 	case BFD_RELOC_FRV_GPREL32:
   1752  1.1  skrll 	case BFD_RELOC_FRV_GPRELHI:
   1753  1.1  skrll 	case BFD_RELOC_FRV_GPRELLO:
   1754  1.1  skrll 	  non_pic_p = ! frv_pic_p;
   1755  1.1  skrll 	  break;
   1756  1.1  skrll 
   1757  1.1  skrll 	case BFD_RELOC_FRV_LO16:
   1758  1.1  skrll 	case BFD_RELOC_FRV_HI16:
   1759  1.1  skrll 	  if (S_GET_SEGMENT (s) != absolute_section)
   1760  1.1  skrll 	    non_pic_p = 1;
   1761  1.1  skrll 	  break;
   1762  1.1  skrll 
   1763  1.1  skrll 	case BFD_RELOC_VTABLE_INHERIT:
   1764  1.1  skrll 	case BFD_RELOC_VTABLE_ENTRY:
   1765  1.1  skrll 	  non_pic_p = 1;
   1766  1.1  skrll 	  break;
   1767  1.1  skrll 
   1768  1.1  skrll 	  /* If this is a blessed BFD_RELOC_32, convert it back to the normal
   1769  1.1  skrll              relocation.  */
   1770  1.1  skrll 	case BFD_RELOC_CTOR:
   1771  1.1  skrll 	  fixp->fx_r_type = BFD_RELOC_32;
   1772  1.1  skrll 	  break;
   1773  1.1  skrll 	}
   1774  1.1  skrll 
   1775  1.1  skrll       if (non_pic_p)
   1776  1.1  skrll 	{
   1777  1.1  skrll 	  DPRINTF1 (" (Non-pic relocation)\n");
   1778  1.1  skrll 	  if (frv_pic_p)
   1779  1.1  skrll 	    as_warn_where (fixp->fx_file, fixp->fx_line,
   1780  1.1  skrll 			   _("Relocation %s is not safe for %s"),
   1781  1.1  skrll 			   bfd_get_reloc_code_name (reloc), frv_pic_flag);
   1782  1.1  skrll 
   1783  1.1  skrll 	  else if ((frv_flags & EF_FRV_NON_PIC_RELOCS) == 0)
   1784  1.1  skrll 	    {
   1785  1.1  skrll 	      frv_flags |= EF_FRV_NON_PIC_RELOCS;
   1786  1.1  skrll 	      bfd_set_private_flags (abfd, frv_flags);
   1787  1.1  skrll 	    }
   1788  1.1  skrll 	}
   1789  1.1  skrll #ifdef DEBUG
   1790  1.1  skrll       else
   1791  1.1  skrll 	DPRINTF1 ("\n");
   1792  1.1  skrll #endif
   1793  1.1  skrll     }
   1794  1.1  skrll }
   1795  1.1  skrll 
   1796  1.1  skrll /* After all of the symbols have been adjusted, go over the file looking
   1797  1.1  skrll    for any relocations that pic won't support.  */
   1798  1.1  skrll 
   1799  1.1  skrll void
   1800  1.1  skrll frv_frob_file (void)
   1801  1.1  skrll {
   1802  1.1  skrll   bfd_map_over_sections (stdoutput, frv_frob_file_section, (void *) 0);
   1803  1.1  skrll }
   1804  1.1  skrll 
   1805  1.1  skrll void
   1806  1.1  skrll frv_frob_label (symbolS *this_label)
   1807  1.1  skrll {
   1808  1.1  skrll   struct vliw_insn_list *vliw_insn_list_entry;
   1809  1.1  skrll 
   1810  1.1  skrll   if (frv_mach != bfd_mach_frvtomcat)
   1811  1.1  skrll     return;
   1812  1.1  skrll 
   1813  1.1  skrll   if (now_seg != text_section)
   1814  1.1  skrll     return;
   1815  1.1  skrll 
   1816  1.1  skrll   vliw_insn_list_entry = frv_insert_vliw_insn(DONT_COUNT);
   1817  1.1  skrll   vliw_insn_list_entry->type = VLIW_LABEL_TYPE;
   1818  1.1  skrll   vliw_insn_list_entry->sym  = this_label;
   1819  1.1  skrll }
   1820  1.1  skrll 
   1821  1.1  skrll fixS *
   1822  1.1  skrll frv_cgen_record_fixup_exp (fragS *frag,
   1823  1.1  skrll 			   int where,
   1824  1.1  skrll 			   const CGEN_INSN *insn,
   1825  1.1  skrll 			   int length,
   1826  1.1  skrll 			   const CGEN_OPERAND *operand,
   1827  1.1  skrll 			   int opinfo,
   1828  1.1  skrll 			   expressionS *exp)
   1829  1.1  skrll {
   1830  1.1  skrll   fixS * fixP = gas_cgen_record_fixup_exp (frag, where, insn, length,
   1831  1.1  skrll                                            operand, opinfo, exp);
   1832  1.1  skrll 
   1833  1.1  skrll   if (frv_mach == bfd_mach_frvtomcat
   1834  1.1  skrll       && current_vliw_insn
   1835                   && current_vliw_insn->type == VLIW_BRANCH_TYPE
   1836                   && exp != NULL)
   1837                 current_vliw_insn->sym = exp->X_add_symbol;
   1838             
   1839               return fixP;
   1840             }
   1841