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