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