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