OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [trunk/] [gnu-src/] [binutils-2.18.50/] [gas/] [config/] [tc-bfin.c] - Diff between revs 38 and 156

Only display areas with differences | Details | Blame | View Log

Rev 38 Rev 156
/* tc-bfin.c -- Assembler for the ADI Blackfin.
/* tc-bfin.c -- Assembler for the ADI Blackfin.
   Copyright 2005, 2006, 2007
   Copyright 2005, 2006, 2007
   Free Software Foundation, Inc.
   Free Software Foundation, Inc.
 
 
   This file is part of GAS, the GNU Assembler.
   This file is part of GAS, the GNU Assembler.
 
 
   GAS is free software; you can redistribute it and/or modify
   GAS is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3, or (at your option)
   the Free Software Foundation; either version 3, or (at your option)
   any later version.
   any later version.
 
 
   GAS is distributed in the hope that it will be useful,
   GAS is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   GNU General Public License for more details.
 
 
   You should have received a copy of the GNU General Public License
   You should have received a copy of the GNU General Public License
   along with GAS; see the file COPYING.  If not, write to the Free
   along with GAS; see the file COPYING.  If not, write to the Free
   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
   02110-1301, USA.  */
   02110-1301, USA.  */
 
 
#include "as.h"
#include "as.h"
#include "struc-symbol.h"
#include "struc-symbol.h"
#include "bfin-defs.h"
#include "bfin-defs.h"
#include "obstack.h"
#include "obstack.h"
#include "safe-ctype.h"
#include "safe-ctype.h"
#ifdef OBJ_ELF
#ifdef OBJ_ELF
#include "dwarf2dbg.h"
#include "dwarf2dbg.h"
#endif
#endif
#include "libbfd.h"
#include "libbfd.h"
#include "elf/common.h"
#include "elf/common.h"
#include "elf/bfin.h"
#include "elf/bfin.h"
 
 
extern int yyparse (void);
extern int yyparse (void);
struct yy_buffer_state;
struct yy_buffer_state;
typedef struct yy_buffer_state *YY_BUFFER_STATE;
typedef struct yy_buffer_state *YY_BUFFER_STATE;
extern YY_BUFFER_STATE yy_scan_string (const char *yy_str);
extern YY_BUFFER_STATE yy_scan_string (const char *yy_str);
extern void yy_delete_buffer (YY_BUFFER_STATE b);
extern void yy_delete_buffer (YY_BUFFER_STATE b);
static parse_state parse (char *line);
static parse_state parse (char *line);
static void bfin_s_bss PARAMS ((int));
static void bfin_s_bss PARAMS ((int));
static int md_chars_to_number PARAMS ((char *, int));
static int md_chars_to_number PARAMS ((char *, int));
 
 
/* Global variables. */
/* Global variables. */
struct bfin_insn *insn;
struct bfin_insn *insn;
int last_insn_size;
int last_insn_size;
 
 
extern struct obstack mempool;
extern struct obstack mempool;
FILE *errorf;
FILE *errorf;
 
 
/* Flags to set in the elf header */
/* Flags to set in the elf header */
#define DEFAULT_FLAGS 0
#define DEFAULT_FLAGS 0
 
 
#ifdef OBJ_FDPIC_ELF
#ifdef OBJ_FDPIC_ELF
# define DEFAULT_FDPIC EF_BFIN_FDPIC
# define DEFAULT_FDPIC EF_BFIN_FDPIC
#else
#else
# define DEFAULT_FDPIC 0
# define DEFAULT_FDPIC 0
#endif
#endif
 
 
static flagword bfin_flags = DEFAULT_FLAGS | DEFAULT_FDPIC;
static flagword bfin_flags = DEFAULT_FLAGS | DEFAULT_FDPIC;
static const char *bfin_pic_flag = DEFAULT_FDPIC ? "-mfdpic" : (const char *)0;
static const char *bfin_pic_flag = DEFAULT_FDPIC ? "-mfdpic" : (const char *)0;
 
 
/* Registers list.  */
/* Registers list.  */
struct bfin_reg_entry
struct bfin_reg_entry
{
{
  const char *name;
  const char *name;
  int number;
  int number;
};
};
 
 
static const struct bfin_reg_entry bfin_reg_info[] = {
static const struct bfin_reg_entry bfin_reg_info[] = {
  {"R0.L", REG_RL0},
  {"R0.L", REG_RL0},
  {"R1.L", REG_RL1},
  {"R1.L", REG_RL1},
  {"R2.L", REG_RL2},
  {"R2.L", REG_RL2},
  {"R3.L", REG_RL3},
  {"R3.L", REG_RL3},
  {"R4.L", REG_RL4},
  {"R4.L", REG_RL4},
  {"R5.L", REG_RL5},
  {"R5.L", REG_RL5},
  {"R6.L", REG_RL6},
  {"R6.L", REG_RL6},
  {"R7.L", REG_RL7},
  {"R7.L", REG_RL7},
  {"R0.H", REG_RH0},
  {"R0.H", REG_RH0},
  {"R1.H", REG_RH1},
  {"R1.H", REG_RH1},
  {"R2.H", REG_RH2},
  {"R2.H", REG_RH2},
  {"R3.H", REG_RH3},
  {"R3.H", REG_RH3},
  {"R4.H", REG_RH4},
  {"R4.H", REG_RH4},
  {"R5.H", REG_RH5},
  {"R5.H", REG_RH5},
  {"R6.H", REG_RH6},
  {"R6.H", REG_RH6},
  {"R7.H", REG_RH7},
  {"R7.H", REG_RH7},
  {"R0", REG_R0},
  {"R0", REG_R0},
  {"R1", REG_R1},
  {"R1", REG_R1},
  {"R2", REG_R2},
  {"R2", REG_R2},
  {"R3", REG_R3},
  {"R3", REG_R3},
  {"R4", REG_R4},
  {"R4", REG_R4},
  {"R5", REG_R5},
  {"R5", REG_R5},
  {"R6", REG_R6},
  {"R6", REG_R6},
  {"R7", REG_R7},
  {"R7", REG_R7},
  {"P0", REG_P0},
  {"P0", REG_P0},
  {"P0.H", REG_P0},
  {"P0.H", REG_P0},
  {"P0.L", REG_P0},
  {"P0.L", REG_P0},
  {"P1", REG_P1},
  {"P1", REG_P1},
  {"P1.H", REG_P1},
  {"P1.H", REG_P1},
  {"P1.L", REG_P1},
  {"P1.L", REG_P1},
  {"P2", REG_P2},
  {"P2", REG_P2},
  {"P2.H", REG_P2},
  {"P2.H", REG_P2},
  {"P2.L", REG_P2},
  {"P2.L", REG_P2},
  {"P3", REG_P3},
  {"P3", REG_P3},
  {"P3.H", REG_P3},
  {"P3.H", REG_P3},
  {"P3.L", REG_P3},
  {"P3.L", REG_P3},
  {"P4", REG_P4},
  {"P4", REG_P4},
  {"P4.H", REG_P4},
  {"P4.H", REG_P4},
  {"P4.L", REG_P4},
  {"P4.L", REG_P4},
  {"P5", REG_P5},
  {"P5", REG_P5},
  {"P5.H", REG_P5},
  {"P5.H", REG_P5},
  {"P5.L", REG_P5},
  {"P5.L", REG_P5},
  {"SP", REG_SP},
  {"SP", REG_SP},
  {"SP.L", REG_SP},
  {"SP.L", REG_SP},
  {"SP.H", REG_SP},
  {"SP.H", REG_SP},
  {"FP", REG_FP},
  {"FP", REG_FP},
  {"FP.L", REG_FP},
  {"FP.L", REG_FP},
  {"FP.H", REG_FP},
  {"FP.H", REG_FP},
  {"A0x", REG_A0x},
  {"A0x", REG_A0x},
  {"A1x", REG_A1x},
  {"A1x", REG_A1x},
  {"A0w", REG_A0w},
  {"A0w", REG_A0w},
  {"A1w", REG_A1w},
  {"A1w", REG_A1w},
  {"A0.x", REG_A0x},
  {"A0.x", REG_A0x},
  {"A1.x", REG_A1x},
  {"A1.x", REG_A1x},
  {"A0.w", REG_A0w},
  {"A0.w", REG_A0w},
  {"A1.w", REG_A1w},
  {"A1.w", REG_A1w},
  {"A0", REG_A0},
  {"A0", REG_A0},
  {"A0.L", REG_A0},
  {"A0.L", REG_A0},
  {"A0.H", REG_A0},
  {"A0.H", REG_A0},
  {"A1", REG_A1},
  {"A1", REG_A1},
  {"A1.L", REG_A1},
  {"A1.L", REG_A1},
  {"A1.H", REG_A1},
  {"A1.H", REG_A1},
  {"I0", REG_I0},
  {"I0", REG_I0},
  {"I0.L", REG_I0},
  {"I0.L", REG_I0},
  {"I0.H", REG_I0},
  {"I0.H", REG_I0},
  {"I1", REG_I1},
  {"I1", REG_I1},
  {"I1.L", REG_I1},
  {"I1.L", REG_I1},
  {"I1.H", REG_I1},
  {"I1.H", REG_I1},
  {"I2", REG_I2},
  {"I2", REG_I2},
  {"I2.L", REG_I2},
  {"I2.L", REG_I2},
  {"I2.H", REG_I2},
  {"I2.H", REG_I2},
  {"I3", REG_I3},
  {"I3", REG_I3},
  {"I3.L", REG_I3},
  {"I3.L", REG_I3},
  {"I3.H", REG_I3},
  {"I3.H", REG_I3},
  {"M0", REG_M0},
  {"M0", REG_M0},
  {"M0.H", REG_M0},
  {"M0.H", REG_M0},
  {"M0.L", REG_M0},
  {"M0.L", REG_M0},
  {"M1", REG_M1},
  {"M1", REG_M1},
  {"M1.H", REG_M1},
  {"M1.H", REG_M1},
  {"M1.L", REG_M1},
  {"M1.L", REG_M1},
  {"M2", REG_M2},
  {"M2", REG_M2},
  {"M2.H", REG_M2},
  {"M2.H", REG_M2},
  {"M2.L", REG_M2},
  {"M2.L", REG_M2},
  {"M3", REG_M3},
  {"M3", REG_M3},
  {"M3.H", REG_M3},
  {"M3.H", REG_M3},
  {"M3.L", REG_M3},
  {"M3.L", REG_M3},
  {"B0", REG_B0},
  {"B0", REG_B0},
  {"B0.H", REG_B0},
  {"B0.H", REG_B0},
  {"B0.L", REG_B0},
  {"B0.L", REG_B0},
  {"B1", REG_B1},
  {"B1", REG_B1},
  {"B1.H", REG_B1},
  {"B1.H", REG_B1},
  {"B1.L", REG_B1},
  {"B1.L", REG_B1},
  {"B2", REG_B2},
  {"B2", REG_B2},
  {"B2.H", REG_B2},
  {"B2.H", REG_B2},
  {"B2.L", REG_B2},
  {"B2.L", REG_B2},
  {"B3", REG_B3},
  {"B3", REG_B3},
  {"B3.H", REG_B3},
  {"B3.H", REG_B3},
  {"B3.L", REG_B3},
  {"B3.L", REG_B3},
  {"L0", REG_L0},
  {"L0", REG_L0},
  {"L0.H", REG_L0},
  {"L0.H", REG_L0},
  {"L0.L", REG_L0},
  {"L0.L", REG_L0},
  {"L1", REG_L1},
  {"L1", REG_L1},
  {"L1.H", REG_L1},
  {"L1.H", REG_L1},
  {"L1.L", REG_L1},
  {"L1.L", REG_L1},
  {"L2", REG_L2},
  {"L2", REG_L2},
  {"L2.H", REG_L2},
  {"L2.H", REG_L2},
  {"L2.L", REG_L2},
  {"L2.L", REG_L2},
  {"L3", REG_L3},
  {"L3", REG_L3},
  {"L3.H", REG_L3},
  {"L3.H", REG_L3},
  {"L3.L", REG_L3},
  {"L3.L", REG_L3},
  {"AZ", S_AZ},
  {"AZ", S_AZ},
  {"AN", S_AN},
  {"AN", S_AN},
  {"AC0", S_AC0},
  {"AC0", S_AC0},
  {"AC1", S_AC1},
  {"AC1", S_AC1},
  {"AV0", S_AV0},
  {"AV0", S_AV0},
  {"AV0S", S_AV0S},
  {"AV0S", S_AV0S},
  {"AV1", S_AV1},
  {"AV1", S_AV1},
  {"AV1S", S_AV1S},
  {"AV1S", S_AV1S},
  {"AQ", S_AQ},
  {"AQ", S_AQ},
  {"V", S_V},
  {"V", S_V},
  {"VS", S_VS},
  {"VS", S_VS},
  {"sftreset", REG_sftreset},
  {"sftreset", REG_sftreset},
  {"omode", REG_omode},
  {"omode", REG_omode},
  {"excause", REG_excause},
  {"excause", REG_excause},
  {"emucause", REG_emucause},
  {"emucause", REG_emucause},
  {"idle_req", REG_idle_req},
  {"idle_req", REG_idle_req},
  {"hwerrcause", REG_hwerrcause},
  {"hwerrcause", REG_hwerrcause},
  {"CC", REG_CC},
  {"CC", REG_CC},
  {"LC0", REG_LC0},
  {"LC0", REG_LC0},
  {"LC1", REG_LC1},
  {"LC1", REG_LC1},
  {"ASTAT", REG_ASTAT},
  {"ASTAT", REG_ASTAT},
  {"RETS", REG_RETS},
  {"RETS", REG_RETS},
  {"LT0", REG_LT0},
  {"LT0", REG_LT0},
  {"LB0", REG_LB0},
  {"LB0", REG_LB0},
  {"LT1", REG_LT1},
  {"LT1", REG_LT1},
  {"LB1", REG_LB1},
  {"LB1", REG_LB1},
  {"CYCLES", REG_CYCLES},
  {"CYCLES", REG_CYCLES},
  {"CYCLES2", REG_CYCLES2},
  {"CYCLES2", REG_CYCLES2},
  {"USP", REG_USP},
  {"USP", REG_USP},
  {"SEQSTAT", REG_SEQSTAT},
  {"SEQSTAT", REG_SEQSTAT},
  {"SYSCFG", REG_SYSCFG},
  {"SYSCFG", REG_SYSCFG},
  {"RETI", REG_RETI},
  {"RETI", REG_RETI},
  {"RETX", REG_RETX},
  {"RETX", REG_RETX},
  {"RETN", REG_RETN},
  {"RETN", REG_RETN},
  {"RETE", REG_RETE},
  {"RETE", REG_RETE},
  {"EMUDAT", REG_EMUDAT},
  {"EMUDAT", REG_EMUDAT},
  {0, 0}
  {0, 0}
};
};
 
 
/* Blackfin specific function to handle FD-PIC pointer initializations.  */
/* Blackfin specific function to handle FD-PIC pointer initializations.  */
 
 
static void
static void
bfin_pic_ptr (int nbytes)
bfin_pic_ptr (int nbytes)
{
{
  expressionS exp;
  expressionS exp;
  char *p;
  char *p;
 
 
  if (nbytes != 4)
  if (nbytes != 4)
    abort ();
    abort ();
 
 
#ifdef md_flush_pending_output
#ifdef md_flush_pending_output
  md_flush_pending_output ();
  md_flush_pending_output ();
#endif
#endif
 
 
  if (is_it_end_of_statement ())
  if (is_it_end_of_statement ())
    {
    {
      demand_empty_rest_of_line ();
      demand_empty_rest_of_line ();
      return;
      return;
    }
    }
 
 
#ifdef md_cons_align
#ifdef md_cons_align
  md_cons_align (nbytes);
  md_cons_align (nbytes);
#endif
#endif
 
 
  do
  do
    {
    {
      bfd_reloc_code_real_type reloc_type = BFD_RELOC_BFIN_FUNCDESC;
      bfd_reloc_code_real_type reloc_type = BFD_RELOC_BFIN_FUNCDESC;
 
 
      if (strncasecmp (input_line_pointer, "funcdesc(", 9) == 0)
      if (strncasecmp (input_line_pointer, "funcdesc(", 9) == 0)
        {
        {
          input_line_pointer += 9;
          input_line_pointer += 9;
          expression (&exp);
          expression (&exp);
          if (*input_line_pointer == ')')
          if (*input_line_pointer == ')')
            input_line_pointer++;
            input_line_pointer++;
          else
          else
            as_bad (_("missing ')'"));
            as_bad (_("missing ')'"));
        }
        }
      else
      else
        error ("missing funcdesc in picptr");
        error ("missing funcdesc in picptr");
 
 
      p = frag_more (4);
      p = frag_more (4);
      memset (p, 0, 4);
      memset (p, 0, 4);
      fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &exp, 0,
      fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &exp, 0,
                   reloc_type);
                   reloc_type);
    }
    }
  while (*input_line_pointer++ == ',');
  while (*input_line_pointer++ == ',');
 
 
  input_line_pointer--;                 /* Put terminator back into stream. */
  input_line_pointer--;                 /* Put terminator back into stream. */
  demand_empty_rest_of_line ();
  demand_empty_rest_of_line ();
}
}
 
 
static void
static void
bfin_s_bss (int ignore ATTRIBUTE_UNUSED)
bfin_s_bss (int ignore ATTRIBUTE_UNUSED)
{
{
  register int temp;
  register int temp;
 
 
  temp = get_absolute_expression ();
  temp = get_absolute_expression ();
  subseg_set (bss_section, (subsegT) temp);
  subseg_set (bss_section, (subsegT) temp);
  demand_empty_rest_of_line ();
  demand_empty_rest_of_line ();
}
}
 
 
const pseudo_typeS md_pseudo_table[] = {
const pseudo_typeS md_pseudo_table[] = {
  {"align", s_align_bytes, 0},
  {"align", s_align_bytes, 0},
  {"byte2", cons, 2},
  {"byte2", cons, 2},
  {"byte4", cons, 4},
  {"byte4", cons, 4},
  {"picptr", bfin_pic_ptr, 4},
  {"picptr", bfin_pic_ptr, 4},
  {"code", obj_elf_section, 0},
  {"code", obj_elf_section, 0},
  {"db", cons, 1},
  {"db", cons, 1},
  {"dd", cons, 4},
  {"dd", cons, 4},
  {"dw", cons, 2},
  {"dw", cons, 2},
  {"p", s_ignore, 0},
  {"p", s_ignore, 0},
  {"pdata", s_ignore, 0},
  {"pdata", s_ignore, 0},
  {"var", s_ignore, 0},
  {"var", s_ignore, 0},
  {"bss", bfin_s_bss, 0},
  {"bss", bfin_s_bss, 0},
  {0, 0, 0}
  {0, 0, 0}
};
};
 
 
/* Characters that are used to denote comments and line separators. */
/* Characters that are used to denote comments and line separators. */
const char comment_chars[] = "";
const char comment_chars[] = "";
const char line_comment_chars[] = "#";
const char line_comment_chars[] = "#";
const char line_separator_chars[] = ";";
const char line_separator_chars[] = ";";
 
 
/* Characters that can be used to separate the mantissa from the
/* Characters that can be used to separate the mantissa from the
   exponent in floating point numbers. */
   exponent in floating point numbers. */
const char EXP_CHARS[] = "eE";
const char EXP_CHARS[] = "eE";
 
 
/* Characters that mean this number is a floating point constant.
/* Characters that mean this number is a floating point constant.
   As in 0f12.456 or  0d1.2345e12.  */
   As in 0f12.456 or  0d1.2345e12.  */
const char FLT_CHARS[] = "fFdDxX";
const char FLT_CHARS[] = "fFdDxX";
 
 
/* Define bfin-specific command-line options (there are none). */
/* Define bfin-specific command-line options (there are none). */
const char *md_shortopts = "";
const char *md_shortopts = "";
 
 
#define OPTION_FDPIC            (OPTION_MD_BASE)
#define OPTION_FDPIC            (OPTION_MD_BASE)
#define OPTION_NOPIC            (OPTION_MD_BASE + 1)
#define OPTION_NOPIC            (OPTION_MD_BASE + 1)
 
 
struct option md_longopts[] =
struct option md_longopts[] =
{
{
  { "mfdpic",           no_argument,            NULL, OPTION_FDPIC      },
  { "mfdpic",           no_argument,            NULL, OPTION_FDPIC      },
  { "mnopic",           no_argument,            NULL, OPTION_NOPIC      },
  { "mnopic",           no_argument,            NULL, OPTION_NOPIC      },
  { "mno-fdpic",        no_argument,            NULL, OPTION_NOPIC      },
  { "mno-fdpic",        no_argument,            NULL, OPTION_NOPIC      },
  { NULL,               no_argument,            NULL, 0                 },
  { NULL,               no_argument,            NULL, 0                 },
};
};
 
 
size_t md_longopts_size = sizeof (md_longopts);
size_t md_longopts_size = sizeof (md_longopts);
 
 
 
 
int
int
md_parse_option (int c ATTRIBUTE_UNUSED, char *arg ATTRIBUTE_UNUSED)
md_parse_option (int c ATTRIBUTE_UNUSED, char *arg ATTRIBUTE_UNUSED)
{
{
  switch (c)
  switch (c)
    {
    {
    default:
    default:
      return 0;
      return 0;
 
 
    case OPTION_FDPIC:
    case OPTION_FDPIC:
      bfin_flags |= EF_BFIN_FDPIC;
      bfin_flags |= EF_BFIN_FDPIC;
      bfin_pic_flag = "-mfdpic";
      bfin_pic_flag = "-mfdpic";
      break;
      break;
 
 
    case OPTION_NOPIC:
    case OPTION_NOPIC:
      bfin_flags &= ~(EF_BFIN_FDPIC);
      bfin_flags &= ~(EF_BFIN_FDPIC);
      bfin_pic_flag = 0;
      bfin_pic_flag = 0;
      break;
      break;
    }
    }
 
 
  return 1;
  return 1;
}
}
 
 
void
void
md_show_usage (FILE * stream ATTRIBUTE_UNUSED)
md_show_usage (FILE * stream ATTRIBUTE_UNUSED)
{
{
  fprintf (stream, _(" BFIN specific command line options:\n"));
  fprintf (stream, _(" BFIN specific command line options:\n"));
}
}
 
 
/* Perform machine-specific initializations.  */
/* Perform machine-specific initializations.  */
void
void
md_begin ()
md_begin ()
{
{
  /* Set the ELF flags if desired. */
  /* Set the ELF flags if desired. */
  if (bfin_flags)
  if (bfin_flags)
    bfd_set_private_flags (stdoutput, bfin_flags);
    bfd_set_private_flags (stdoutput, bfin_flags);
 
 
  /* Set the default machine type. */
  /* Set the default machine type. */
  if (!bfd_set_arch_mach (stdoutput, bfd_arch_bfin, 0))
  if (!bfd_set_arch_mach (stdoutput, bfd_arch_bfin, 0))
    as_warn (_("Could not set architecture and machine."));
    as_warn (_("Could not set architecture and machine."));
 
 
  /* Ensure that lines can begin with '(', for multiple
  /* Ensure that lines can begin with '(', for multiple
     register stack pops. */
     register stack pops. */
  lex_type ['('] = LEX_BEGIN_NAME;
  lex_type ['('] = LEX_BEGIN_NAME;
 
 
#ifdef OBJ_ELF
#ifdef OBJ_ELF
  record_alignment (text_section, 2);
  record_alignment (text_section, 2);
  record_alignment (data_section, 2);
  record_alignment (data_section, 2);
  record_alignment (bss_section, 2);
  record_alignment (bss_section, 2);
#endif
#endif
 
 
  errorf = stderr;
  errorf = stderr;
  obstack_init (&mempool);
  obstack_init (&mempool);
 
 
#ifdef DEBUG
#ifdef DEBUG
  extern int debug_codeselection;
  extern int debug_codeselection;
  debug_codeselection = 1;
  debug_codeselection = 1;
#endif 
#endif 
 
 
  last_insn_size = 0;
  last_insn_size = 0;
}
}
 
 
/* Perform the main parsing, and assembly of the input here.  Also,
/* Perform the main parsing, and assembly of the input here.  Also,
   call the required routines for alignment and fixups here.
   call the required routines for alignment and fixups here.
   This is called for every line that contains real assembly code.  */
   This is called for every line that contains real assembly code.  */
 
 
void
void
md_assemble (char *line)
md_assemble (char *line)
{
{
  char *toP = 0;
  char *toP = 0;
  extern char *current_inputline;
  extern char *current_inputline;
  int size, insn_size;
  int size, insn_size;
  struct bfin_insn *tmp_insn;
  struct bfin_insn *tmp_insn;
  size_t len;
  size_t len;
  static size_t buffer_len = 0;
  static size_t buffer_len = 0;
  parse_state state;
  parse_state state;
 
 
  len = strlen (line);
  len = strlen (line);
  if (len + 2 > buffer_len)
  if (len + 2 > buffer_len)
    {
    {
      if (buffer_len > 0)
      if (buffer_len > 0)
        free (current_inputline);
        free (current_inputline);
      buffer_len = len + 40;
      buffer_len = len + 40;
      current_inputline = xmalloc (buffer_len);
      current_inputline = xmalloc (buffer_len);
    }
    }
  memcpy (current_inputline, line, len);
  memcpy (current_inputline, line, len);
  current_inputline[len] = ';';
  current_inputline[len] = ';';
  current_inputline[len + 1] = '\0';
  current_inputline[len + 1] = '\0';
 
 
  state = parse (current_inputline);
  state = parse (current_inputline);
  if (state == NO_INSN_GENERATED)
  if (state == NO_INSN_GENERATED)
    return;
    return;
 
 
  for (insn_size = 0, tmp_insn = insn; tmp_insn; tmp_insn = tmp_insn->next)
  for (insn_size = 0, tmp_insn = insn; tmp_insn; tmp_insn = tmp_insn->next)
    if (!tmp_insn->reloc || !tmp_insn->exp->symbol)
    if (!tmp_insn->reloc || !tmp_insn->exp->symbol)
      insn_size += 2;
      insn_size += 2;
 
 
  if (insn_size)
  if (insn_size)
    toP = frag_more (insn_size);
    toP = frag_more (insn_size);
 
 
  last_insn_size = insn_size;
  last_insn_size = insn_size;
 
 
#ifdef DEBUG
#ifdef DEBUG
  printf ("INS:");
  printf ("INS:");
#endif
#endif
  while (insn)
  while (insn)
    {
    {
      if (insn->reloc && insn->exp->symbol)
      if (insn->reloc && insn->exp->symbol)
        {
        {
          char *prev_toP = toP - 2;
          char *prev_toP = toP - 2;
          switch (insn->reloc)
          switch (insn->reloc)
            {
            {
            case BFD_RELOC_BFIN_24_PCREL_JUMP_L:
            case BFD_RELOC_BFIN_24_PCREL_JUMP_L:
            case BFD_RELOC_24_PCREL:
            case BFD_RELOC_24_PCREL:
            case BFD_RELOC_BFIN_16_LOW:
            case BFD_RELOC_BFIN_16_LOW:
            case BFD_RELOC_BFIN_16_HIGH:
            case BFD_RELOC_BFIN_16_HIGH:
              size = 4;
              size = 4;
              break;
              break;
            default:
            default:
              size = 2;
              size = 2;
            }
            }
 
 
          /* Following if condition checks for the arithmetic relocations.
          /* Following if condition checks for the arithmetic relocations.
             If the case then it doesn't required to generate the code.
             If the case then it doesn't required to generate the code.
             It has been assumed that, their ID will be contiguous.  */
             It has been assumed that, their ID will be contiguous.  */
          if ((BFD_ARELOC_BFIN_PUSH <= insn->reloc
          if ((BFD_ARELOC_BFIN_PUSH <= insn->reloc
               && BFD_ARELOC_BFIN_COMP >= insn->reloc)
               && BFD_ARELOC_BFIN_COMP >= insn->reloc)
              || insn->reloc == BFD_RELOC_BFIN_16_IMM)
              || insn->reloc == BFD_RELOC_BFIN_16_IMM)
            {
            {
              size = 2;
              size = 2;
            }
            }
          if (insn->reloc == BFD_ARELOC_BFIN_CONST
          if (insn->reloc == BFD_ARELOC_BFIN_CONST
              || insn->reloc == BFD_ARELOC_BFIN_PUSH)
              || insn->reloc == BFD_ARELOC_BFIN_PUSH)
            size = 4;
            size = 4;
 
 
          fix_new (frag_now,
          fix_new (frag_now,
                   (prev_toP - frag_now->fr_literal),
                   (prev_toP - frag_now->fr_literal),
                   size, insn->exp->symbol, insn->exp->value,
                   size, insn->exp->symbol, insn->exp->value,
                   insn->pcrel, insn->reloc);
                   insn->pcrel, insn->reloc);
        }
        }
      else
      else
        {
        {
          md_number_to_chars (toP, insn->value, 2);
          md_number_to_chars (toP, insn->value, 2);
          toP += 2;
          toP += 2;
        }
        }
 
 
#ifdef DEBUG
#ifdef DEBUG
      printf (" reloc :");
      printf (" reloc :");
      printf (" %02x%02x", ((unsigned char *) &insn->value)[0],
      printf (" %02x%02x", ((unsigned char *) &insn->value)[0],
              ((unsigned char *) &insn->value)[1]);
              ((unsigned char *) &insn->value)[1]);
      printf ("\n");
      printf ("\n");
#endif
#endif
      insn = insn->next;
      insn = insn->next;
    }
    }
#ifdef OBJ_ELF
#ifdef OBJ_ELF
  dwarf2_emit_insn (insn_size);
  dwarf2_emit_insn (insn_size);
#endif
#endif
}
}
 
 
/* Parse one line of instructions, and generate opcode for it.
/* Parse one line of instructions, and generate opcode for it.
   To parse the line, YACC and LEX are used, because the instruction set
   To parse the line, YACC and LEX are used, because the instruction set
   syntax doesn't confirm to the AT&T assembly syntax.
   syntax doesn't confirm to the AT&T assembly syntax.
   To call a YACC & LEX generated parser, we must provide the input via
   To call a YACC & LEX generated parser, we must provide the input via
   a FILE stream, otherwise stdin is used by default.  Below the input
   a FILE stream, otherwise stdin is used by default.  Below the input
   to the function will be put into a temporary file, then the generated
   to the function will be put into a temporary file, then the generated
   parser uses the temporary file for parsing.  */
   parser uses the temporary file for parsing.  */
 
 
static parse_state
static parse_state
parse (char *line)
parse (char *line)
{
{
  parse_state state;
  parse_state state;
  YY_BUFFER_STATE buffstate;
  YY_BUFFER_STATE buffstate;
 
 
  buffstate = yy_scan_string (line);
  buffstate = yy_scan_string (line);
 
 
  /* our lex requires setting the start state to keyword
  /* our lex requires setting the start state to keyword
     every line as the first word may be a keyword.
     every line as the first word may be a keyword.
     Fixes a bug where we could not have keywords as labels.  */
     Fixes a bug where we could not have keywords as labels.  */
  set_start_state ();
  set_start_state ();
 
 
  /* Call yyparse here.  */
  /* Call yyparse here.  */
  state = yyparse ();
  state = yyparse ();
  if (state == SEMANTIC_ERROR)
  if (state == SEMANTIC_ERROR)
    {
    {
      as_bad (_("Parse failed."));
      as_bad (_("Parse failed."));
      insn = 0;
      insn = 0;
    }
    }
 
 
  yy_delete_buffer (buffstate);
  yy_delete_buffer (buffstate);
  return state;
  return state;
}
}
 
 
/* We need to handle various expressions properly.
/* We need to handle various expressions properly.
   Such as, [SP--] = 34, concerned by md_assemble().  */
   Such as, [SP--] = 34, concerned by md_assemble().  */
 
 
void
void
md_operand (expressionS * expressionP)
md_operand (expressionS * expressionP)
{
{
  if (*input_line_pointer == '[')
  if (*input_line_pointer == '[')
    {
    {
      as_tsktsk ("We found a '['!");
      as_tsktsk ("We found a '['!");
      input_line_pointer++;
      input_line_pointer++;
      expression (expressionP);
      expression (expressionP);
    }
    }
}
}
 
 
/* Handle undefined symbols. */
/* Handle undefined symbols. */
symbolS *
symbolS *
md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
{
{
  return (symbolS *) 0;
  return (symbolS *) 0;
}
}
 
 
int
int
md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED,
md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED,
                               segT segment ATTRIBUTE_UNUSED)
                               segT segment ATTRIBUTE_UNUSED)
{
{
  return 0;
  return 0;
}
}
 
 
/* Convert from target byte order to host byte order.  */
/* Convert from target byte order to host byte order.  */
 
 
static int
static int
md_chars_to_number (char *val, int n)
md_chars_to_number (char *val, int n)
{
{
  int retval;
  int retval;
 
 
  for (retval = 0; n--;)
  for (retval = 0; n--;)
    {
    {
      retval <<= 8;
      retval <<= 8;
      retval |= val[n];
      retval |= val[n];
    }
    }
  return retval;
  return retval;
}
}
 
 
void
void
md_apply_fix (fixS *fixP, valueT *valueP, segT seg ATTRIBUTE_UNUSED)
md_apply_fix (fixS *fixP, valueT *valueP, segT seg ATTRIBUTE_UNUSED)
{
{
  char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
  char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
 
 
  long value = *valueP;
  long value = *valueP;
  long newval;
  long newval;
 
 
  switch (fixP->fx_r_type)
  switch (fixP->fx_r_type)
    {
    {
    case BFD_RELOC_BFIN_GOT:
    case BFD_RELOC_BFIN_GOT:
    case BFD_RELOC_BFIN_GOT17M4:
    case BFD_RELOC_BFIN_GOT17M4:
    case BFD_RELOC_BFIN_FUNCDESC_GOT17M4:
    case BFD_RELOC_BFIN_FUNCDESC_GOT17M4:
      fixP->fx_no_overflow = 1;
      fixP->fx_no_overflow = 1;
      newval = md_chars_to_number (where, 2);
      newval = md_chars_to_number (where, 2);
      newval |= 0x0 & 0x7f;
      newval |= 0x0 & 0x7f;
      md_number_to_chars (where, newval, 2);
      md_number_to_chars (where, newval, 2);
      break;
      break;
 
 
    case BFD_RELOC_BFIN_10_PCREL:
    case BFD_RELOC_BFIN_10_PCREL:
      if (!value)
      if (!value)
        break;
        break;
      if (value < -1024 || value > 1022)
      if (value < -1024 || value > 1022)
        as_bad_where (fixP->fx_file, fixP->fx_line,
        as_bad_where (fixP->fx_file, fixP->fx_line,
                      _("pcrel too far BFD_RELOC_BFIN_10"));
                      _("pcrel too far BFD_RELOC_BFIN_10"));
 
 
      /* 11 bit offset even numbered, so we remove right bit.  */
      /* 11 bit offset even numbered, so we remove right bit.  */
      value = value >> 1;
      value = value >> 1;
      newval = md_chars_to_number (where, 2);
      newval = md_chars_to_number (where, 2);
      newval |= value & 0x03ff;
      newval |= value & 0x03ff;
      md_number_to_chars (where, newval, 2);
      md_number_to_chars (where, newval, 2);
      break;
      break;
 
 
    case BFD_RELOC_BFIN_12_PCREL_JUMP:
    case BFD_RELOC_BFIN_12_PCREL_JUMP:
    case BFD_RELOC_BFIN_12_PCREL_JUMP_S:
    case BFD_RELOC_BFIN_12_PCREL_JUMP_S:
    case BFD_RELOC_12_PCREL:
    case BFD_RELOC_12_PCREL:
      if (!value)
      if (!value)
        break;
        break;
 
 
      if (value < -4096 || value > 4094)
      if (value < -4096 || value > 4094)
        as_bad_where (fixP->fx_file, fixP->fx_line, _("pcrel too far BFD_RELOC_BFIN_12"));
        as_bad_where (fixP->fx_file, fixP->fx_line, _("pcrel too far BFD_RELOC_BFIN_12"));
      /* 13 bit offset even numbered, so we remove right bit.  */
      /* 13 bit offset even numbered, so we remove right bit.  */
      value = value >> 1;
      value = value >> 1;
      newval = md_chars_to_number (where, 2);
      newval = md_chars_to_number (where, 2);
      newval |= value & 0xfff;
      newval |= value & 0xfff;
      md_number_to_chars (where, newval, 2);
      md_number_to_chars (where, newval, 2);
      break;
      break;
 
 
    case BFD_RELOC_BFIN_16_LOW:
    case BFD_RELOC_BFIN_16_LOW:
    case BFD_RELOC_BFIN_16_HIGH:
    case BFD_RELOC_BFIN_16_HIGH:
      fixP->fx_done = FALSE;
      fixP->fx_done = FALSE;
      break;
      break;
 
 
    case BFD_RELOC_BFIN_24_PCREL_JUMP_L:
    case BFD_RELOC_BFIN_24_PCREL_JUMP_L:
    case BFD_RELOC_BFIN_24_PCREL_CALL_X:
    case BFD_RELOC_BFIN_24_PCREL_CALL_X:
    case BFD_RELOC_24_PCREL:
    case BFD_RELOC_24_PCREL:
      if (!value)
      if (!value)
        break;
        break;
 
 
      if (value < -16777216 || value > 16777214)
      if (value < -16777216 || value > 16777214)
        as_bad_where (fixP->fx_file, fixP->fx_line, _("pcrel too far BFD_RELOC_BFIN_24"));
        as_bad_where (fixP->fx_file, fixP->fx_line, _("pcrel too far BFD_RELOC_BFIN_24"));
 
 
      /* 25 bit offset even numbered, so we remove right bit.  */
      /* 25 bit offset even numbered, so we remove right bit.  */
      value = value >> 1;
      value = value >> 1;
      value++;
      value++;
 
 
      md_number_to_chars (where - 2, value >> 16, 1);
      md_number_to_chars (where - 2, value >> 16, 1);
      md_number_to_chars (where, value, 1);
      md_number_to_chars (where, value, 1);
      md_number_to_chars (where + 1, value >> 8, 1);
      md_number_to_chars (where + 1, value >> 8, 1);
      break;
      break;
 
 
    case BFD_RELOC_BFIN_5_PCREL:        /* LSETUP (a, b) : "a" */
    case BFD_RELOC_BFIN_5_PCREL:        /* LSETUP (a, b) : "a" */
      if (!value)
      if (!value)
        break;
        break;
      if (value < 4 || value > 30)
      if (value < 4 || value > 30)
        as_bad_where (fixP->fx_file, fixP->fx_line, _("pcrel too far BFD_RELOC_BFIN_5"));
        as_bad_where (fixP->fx_file, fixP->fx_line, _("pcrel too far BFD_RELOC_BFIN_5"));
      value = value >> 1;
      value = value >> 1;
      newval = md_chars_to_number (where, 1);
      newval = md_chars_to_number (where, 1);
      newval = (newval & 0xf0) | (value & 0xf);
      newval = (newval & 0xf0) | (value & 0xf);
      md_number_to_chars (where, newval, 1);
      md_number_to_chars (where, newval, 1);
      break;
      break;
 
 
    case BFD_RELOC_BFIN_11_PCREL:       /* LSETUP (a, b) : "b" */
    case BFD_RELOC_BFIN_11_PCREL:       /* LSETUP (a, b) : "b" */
      if (!value)
      if (!value)
        break;
        break;
      value += 2;
      value += 2;
      if (value < 4 || value > 2046)
      if (value < 4 || value > 2046)
        as_bad_where (fixP->fx_file, fixP->fx_line, _("pcrel too far BFD_RELOC_BFIN_11_PCREL"));
        as_bad_where (fixP->fx_file, fixP->fx_line, _("pcrel too far BFD_RELOC_BFIN_11_PCREL"));
      /* 11 bit unsigned even, so we remove right bit.  */
      /* 11 bit unsigned even, so we remove right bit.  */
      value = value >> 1;
      value = value >> 1;
      newval = md_chars_to_number (where, 2);
      newval = md_chars_to_number (where, 2);
      newval |= value & 0x03ff;
      newval |= value & 0x03ff;
      md_number_to_chars (where, newval, 2);
      md_number_to_chars (where, newval, 2);
      break;
      break;
 
 
    case BFD_RELOC_8:
    case BFD_RELOC_8:
      if (value < -0x80 || value >= 0x7f)
      if (value < -0x80 || value >= 0x7f)
        as_bad_where (fixP->fx_file, fixP->fx_line, _("rel too far BFD_RELOC_8"));
        as_bad_where (fixP->fx_file, fixP->fx_line, _("rel too far BFD_RELOC_8"));
      md_number_to_chars (where, value, 1);
      md_number_to_chars (where, value, 1);
      break;
      break;
 
 
    case BFD_RELOC_BFIN_16_IMM:
    case BFD_RELOC_BFIN_16_IMM:
    case BFD_RELOC_16:
    case BFD_RELOC_16:
      if (value < -0x8000 || value >= 0x7fff)
      if (value < -0x8000 || value >= 0x7fff)
        as_bad_where (fixP->fx_file, fixP->fx_line, _("rel too far BFD_RELOC_16"));
        as_bad_where (fixP->fx_file, fixP->fx_line, _("rel too far BFD_RELOC_16"));
      md_number_to_chars (where, value, 2);
      md_number_to_chars (where, value, 2);
      break;
      break;
 
 
    case BFD_RELOC_32:
    case BFD_RELOC_32:
      md_number_to_chars (where, value, 4);
      md_number_to_chars (where, value, 4);
      break;
      break;
 
 
    case BFD_RELOC_BFIN_PLTPC:
    case BFD_RELOC_BFIN_PLTPC:
      md_number_to_chars (where, value, 2);
      md_number_to_chars (where, value, 2);
      break;
      break;
 
 
    case BFD_RELOC_BFIN_FUNCDESC:
    case BFD_RELOC_BFIN_FUNCDESC:
    case BFD_RELOC_VTABLE_INHERIT:
    case BFD_RELOC_VTABLE_INHERIT:
    case BFD_RELOC_VTABLE_ENTRY:
    case BFD_RELOC_VTABLE_ENTRY:
      fixP->fx_done = FALSE;
      fixP->fx_done = FALSE;
      break;
      break;
 
 
    default:
    default:
      if ((BFD_ARELOC_BFIN_PUSH > fixP->fx_r_type) || (BFD_ARELOC_BFIN_COMP < fixP->fx_r_type))
      if ((BFD_ARELOC_BFIN_PUSH > fixP->fx_r_type) || (BFD_ARELOC_BFIN_COMP < fixP->fx_r_type))
        {
        {
          fprintf (stderr, "Relocation %d not handled in gas." " Contact support.\n", fixP->fx_r_type);
          fprintf (stderr, "Relocation %d not handled in gas." " Contact support.\n", fixP->fx_r_type);
          return;
          return;
        }
        }
    }
    }
 
 
  if (!fixP->fx_addsy)
  if (!fixP->fx_addsy)
    fixP->fx_done = TRUE;
    fixP->fx_done = TRUE;
 
 
}
}
 
 
/* Round up a section size to the appropriate boundary.  */
/* Round up a section size to the appropriate boundary.  */
valueT
valueT
md_section_align (segment, size)
md_section_align (segment, size)
     segT segment;
     segT segment;
     valueT size;
     valueT size;
{
{
  int boundary = bfd_get_section_alignment (stdoutput, segment);
  int boundary = bfd_get_section_alignment (stdoutput, segment);
  return ((size + (1 << boundary) - 1) & (-1 << boundary));
  return ((size + (1 << boundary) - 1) & (-1 << boundary));
}
}
 
 
 
 
char *
char *
md_atof (int type, char * litP, int * sizeP)
md_atof (int type, char * litP, int * sizeP)
{
{
  return ieee_md_atof (type, litP, sizeP, FALSE);
  return ieee_md_atof (type, litP, sizeP, FALSE);
}
}
 
 
 
 
/* If while processing a fixup, a reloc really needs to be created
/* If while processing a fixup, a reloc really needs to be created
   then it is done here.  */
   then it is done here.  */
 
 
arelent *
arelent *
tc_gen_reloc (seg, fixp)
tc_gen_reloc (seg, fixp)
     asection *seg ATTRIBUTE_UNUSED;
     asection *seg ATTRIBUTE_UNUSED;
     fixS *fixp;
     fixS *fixp;
{
{
  arelent *reloc;
  arelent *reloc;
 
 
  reloc               = (arelent *) xmalloc (sizeof (arelent));
  reloc               = (arelent *) xmalloc (sizeof (arelent));
  reloc->sym_ptr_ptr  = (asymbol **) xmalloc (sizeof (asymbol *));
  reloc->sym_ptr_ptr  = (asymbol **) xmalloc (sizeof (asymbol *));
  *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
  *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
  reloc->address      = fixp->fx_frag->fr_address + fixp->fx_where;
  reloc->address      = fixp->fx_frag->fr_address + fixp->fx_where;
 
 
  reloc->addend = fixp->fx_offset;
  reloc->addend = fixp->fx_offset;
  reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
  reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
 
 
  if (reloc->howto == (reloc_howto_type *) NULL)
  if (reloc->howto == (reloc_howto_type *) NULL)
    {
    {
      as_bad_where (fixp->fx_file, fixp->fx_line,
      as_bad_where (fixp->fx_file, fixp->fx_line,
                    /* xgettext:c-format.  */
                    /* xgettext:c-format.  */
                    _("reloc %d not supported by object file format"),
                    _("reloc %d not supported by object file format"),
                    (int) fixp->fx_r_type);
                    (int) fixp->fx_r_type);
 
 
      xfree (reloc);
      xfree (reloc);
 
 
      return NULL;
      return NULL;
    }
    }
 
 
  return reloc;
  return reloc;
}
}
 
 
/*  The location from which a PC relative jump should be calculated,
/*  The location from which a PC relative jump should be calculated,
    given a PC relative reloc.  */
    given a PC relative reloc.  */
 
 
long
long
md_pcrel_from_section (fixP, sec)
md_pcrel_from_section (fixP, sec)
     fixS *fixP;
     fixS *fixP;
     segT sec;
     segT sec;
{
{
  if (fixP->fx_addsy != (symbolS *) NULL
  if (fixP->fx_addsy != (symbolS *) NULL
      && (!S_IS_DEFINED (fixP->fx_addsy)
      && (!S_IS_DEFINED (fixP->fx_addsy)
      || S_GET_SEGMENT (fixP->fx_addsy) != sec))
      || S_GET_SEGMENT (fixP->fx_addsy) != sec))
    {
    {
      /* The symbol is undefined (or is defined but not in this section).
      /* The symbol is undefined (or is defined but not in this section).
         Let the linker figure it out.  */
         Let the linker figure it out.  */
      return 0;
      return 0;
    }
    }
  return fixP->fx_frag->fr_address + fixP->fx_where;
  return fixP->fx_frag->fr_address + fixP->fx_where;
}
}
 
 
/* Return true if the fix can be handled by GAS, false if it must
/* Return true if the fix can be handled by GAS, false if it must
   be passed through to the linker.  */
   be passed through to the linker.  */
 
 
bfd_boolean
bfd_boolean
bfin_fix_adjustable (fixS *fixP)
bfin_fix_adjustable (fixS *fixP)
{
{
  switch (fixP->fx_r_type)
  switch (fixP->fx_r_type)
    {
    {
  /* Adjust_reloc_syms doesn't know about the GOT.  */
  /* Adjust_reloc_syms doesn't know about the GOT.  */
    case BFD_RELOC_BFIN_GOT:
    case BFD_RELOC_BFIN_GOT:
    case BFD_RELOC_BFIN_GOT17M4:
    case BFD_RELOC_BFIN_GOT17M4:
    case BFD_RELOC_BFIN_FUNCDESC_GOT17M4:
    case BFD_RELOC_BFIN_FUNCDESC_GOT17M4:
    case BFD_RELOC_BFIN_PLTPC:
    case BFD_RELOC_BFIN_PLTPC:
  /* We need the symbol name for the VTABLE entries.  */
  /* We need the symbol name for the VTABLE entries.  */
    case BFD_RELOC_VTABLE_INHERIT:
    case BFD_RELOC_VTABLE_INHERIT:
    case BFD_RELOC_VTABLE_ENTRY:
    case BFD_RELOC_VTABLE_ENTRY:
      return 0;
      return 0;
 
 
    default:
    default:
      return 1;
      return 1;
    }
    }
}
}
 
 
 
 
/* Handle the LOOP_BEGIN and LOOP_END statements.
/* Handle the LOOP_BEGIN and LOOP_END statements.
   Parse the Loop_Begin/Loop_End and create a label.  */
   Parse the Loop_Begin/Loop_End and create a label.  */
void
void
bfin_start_line_hook ()
bfin_start_line_hook ()
{
{
  bfd_boolean maybe_begin = FALSE;
  bfd_boolean maybe_begin = FALSE;
  bfd_boolean maybe_end = FALSE;
  bfd_boolean maybe_end = FALSE;
 
 
  char *c1, *label_name;
  char *c1, *label_name;
  symbolS *line_label;
  symbolS *line_label;
  char *c = input_line_pointer;
  char *c = input_line_pointer;
  int cr_num = 0;
  int cr_num = 0;
 
 
  while (ISSPACE (*c))
  while (ISSPACE (*c))
    {
    {
      if (*c == '\n')
      if (*c == '\n')
        cr_num++;
        cr_num++;
      c++;
      c++;
    }
    }
 
 
  /* Look for Loop_Begin or Loop_End statements.  */
  /* Look for Loop_Begin or Loop_End statements.  */
 
 
  if (*c != 'L' && *c != 'l')
  if (*c != 'L' && *c != 'l')
    return;
    return;
 
 
  c++;
  c++;
  if (*c != 'O' && *c != 'o')
  if (*c != 'O' && *c != 'o')
    return;
    return;
 
 
  c++;
  c++;
  if (*c != 'O' && *c != 'o')
  if (*c != 'O' && *c != 'o')
    return;
    return;
 
 
  c++;
  c++;
  if (*c != 'P' && *c != 'p')
  if (*c != 'P' && *c != 'p')
    return;
    return;
 
 
  c++;
  c++;
  if (*c != '_')
  if (*c != '_')
    return;
    return;
 
 
  c++;
  c++;
  if (*c == 'E' || *c == 'e')
  if (*c == 'E' || *c == 'e')
    maybe_end = TRUE;
    maybe_end = TRUE;
  else if (*c == 'B' || *c == 'b')
  else if (*c == 'B' || *c == 'b')
    maybe_begin = TRUE;
    maybe_begin = TRUE;
  else
  else
    return;
    return;
 
 
  if (maybe_end)
  if (maybe_end)
    {
    {
      c++;
      c++;
      if (*c != 'N' && *c != 'n')
      if (*c != 'N' && *c != 'n')
        return;
        return;
 
 
      c++;
      c++;
      if (*c != 'D' && *c != 'd')
      if (*c != 'D' && *c != 'd')
        return;
        return;
    }
    }
 
 
  if (maybe_begin)
  if (maybe_begin)
    {
    {
      c++;
      c++;
      if (*c != 'E' && *c != 'e')
      if (*c != 'E' && *c != 'e')
        return;
        return;
 
 
      c++;
      c++;
      if (*c != 'G' && *c != 'g')
      if (*c != 'G' && *c != 'g')
        return;
        return;
 
 
      c++;
      c++;
      if (*c != 'I' && *c != 'i')
      if (*c != 'I' && *c != 'i')
        return;
        return;
 
 
      c++;
      c++;
      if (*c != 'N' && *c != 'n')
      if (*c != 'N' && *c != 'n')
        return;
        return;
    }
    }
 
 
  c++;
  c++;
  while (ISSPACE (*c)) c++;
  while (ISSPACE (*c)) c++;
  c1 = c;
  c1 = c;
  while (ISALPHA (*c) || ISDIGIT (*c) || *c == '_') c++;
  while (ISALPHA (*c) || ISDIGIT (*c) || *c == '_') c++;
 
 
  if (input_line_pointer[-1] == '\n')
  if (input_line_pointer[-1] == '\n')
    bump_line_counters ();
    bump_line_counters ();
 
 
  while (cr_num--)
  while (cr_num--)
    bump_line_counters ();
    bump_line_counters ();
 
 
  input_line_pointer = c;
  input_line_pointer = c;
  if (maybe_end)
  if (maybe_end)
    {
    {
      label_name = (char *) xmalloc ((c - c1) + strlen ("__END") + 5);
      label_name = (char *) xmalloc ((c - c1) + strlen ("__END") + 5);
      label_name[0] = 0;
      label_name[0] = 0;
      strcat (label_name, "L$L$");
      strcat (label_name, "L$L$");
      strncat (label_name, c1, c-c1);
      strncat (label_name, c1, c-c1);
      strcat (label_name, "__END");
      strcat (label_name, "__END");
    }
    }
  else /* maybe_begin.  */
  else /* maybe_begin.  */
    {
    {
      label_name = (char *) xmalloc ((c - c1) + strlen ("__BEGIN") + 5);
      label_name = (char *) xmalloc ((c - c1) + strlen ("__BEGIN") + 5);
      label_name[0] = 0;
      label_name[0] = 0;
      strcat (label_name, "L$L$");
      strcat (label_name, "L$L$");
      strncat (label_name, c1, c-c1);
      strncat (label_name, c1, c-c1);
      strcat (label_name, "__BEGIN");
      strcat (label_name, "__BEGIN");
    }
    }
 
 
  line_label = colon (label_name);
  line_label = colon (label_name);
 
 
  /* Loop_End follows the last instruction in the loop.
  /* Loop_End follows the last instruction in the loop.
     Adjust label address.  */
     Adjust label address.  */
  if (maybe_end)
  if (maybe_end)
    ((struct local_symbol *) line_label)->lsy_value -= last_insn_size;
    ((struct local_symbol *) line_label)->lsy_value -= last_insn_size;
}
}
 
 
/* Special extra functions that help bfin-parse.y perform its job.  */
/* Special extra functions that help bfin-parse.y perform its job.  */
 
 
#include <assert.h>
#include <assert.h>
 
 
struct obstack mempool;
struct obstack mempool;
 
 
INSTR_T
INSTR_T
conscode (INSTR_T head, INSTR_T tail)
conscode (INSTR_T head, INSTR_T tail)
{
{
  if (!head)
  if (!head)
    return tail;
    return tail;
  head->next = tail;
  head->next = tail;
  return head;
  return head;
}
}
 
 
INSTR_T
INSTR_T
conctcode (INSTR_T head, INSTR_T tail)
conctcode (INSTR_T head, INSTR_T tail)
{
{
  INSTR_T temp = (head);
  INSTR_T temp = (head);
  if (!head)
  if (!head)
    return tail;
    return tail;
  while (temp->next)
  while (temp->next)
    temp = temp->next;
    temp = temp->next;
  temp->next = tail;
  temp->next = tail;
 
 
  return head;
  return head;
}
}
 
 
INSTR_T
INSTR_T
note_reloc (INSTR_T code, Expr_Node * symbol, int reloc, int pcrel)
note_reloc (INSTR_T code, Expr_Node * symbol, int reloc, int pcrel)
{
{
  /* Assert that the symbol is not an operator.  */
  /* Assert that the symbol is not an operator.  */
  assert (symbol->type == Expr_Node_Reloc);
  assert (symbol->type == Expr_Node_Reloc);
 
 
  return note_reloc1 (code, symbol->value.s_value, reloc, pcrel);
  return note_reloc1 (code, symbol->value.s_value, reloc, pcrel);
 
 
}
}
 
 
INSTR_T
INSTR_T
note_reloc1 (INSTR_T code, const char *symbol, int reloc, int pcrel)
note_reloc1 (INSTR_T code, const char *symbol, int reloc, int pcrel)
{
{
  code->reloc = reloc;
  code->reloc = reloc;
  code->exp = mkexpr (0, symbol_find_or_make (symbol));
  code->exp = mkexpr (0, symbol_find_or_make (symbol));
  code->pcrel = pcrel;
  code->pcrel = pcrel;
  return code;
  return code;
}
}
 
 
INSTR_T
INSTR_T
note_reloc2 (INSTR_T code, const char *symbol, int reloc, int value, int pcrel)
note_reloc2 (INSTR_T code, const char *symbol, int reloc, int value, int pcrel)
{
{
  code->reloc = reloc;
  code->reloc = reloc;
  code->exp = mkexpr (value, symbol_find_or_make (symbol));
  code->exp = mkexpr (value, symbol_find_or_make (symbol));
  code->pcrel = pcrel;
  code->pcrel = pcrel;
  return code;
  return code;
}
}
 
 
INSTR_T
INSTR_T
gencode (unsigned long x)
gencode (unsigned long x)
{
{
  INSTR_T cell = (INSTR_T) obstack_alloc (&mempool, sizeof (struct bfin_insn));
  INSTR_T cell = (INSTR_T) obstack_alloc (&mempool, sizeof (struct bfin_insn));
  memset (cell, 0, sizeof (struct bfin_insn));
  memset (cell, 0, sizeof (struct bfin_insn));
  cell->value = (x);
  cell->value = (x);
  return cell;
  return cell;
}
}
 
 
int reloc;
int reloc;
int ninsns;
int ninsns;
int count_insns;
int count_insns;
 
 
static void *
static void *
allocate (int n)
allocate (int n)
{
{
  return (void *) obstack_alloc (&mempool, n);
  return (void *) obstack_alloc (&mempool, n);
}
}
 
 
Expr_Node *
Expr_Node *
Expr_Node_Create (Expr_Node_Type type,
Expr_Node_Create (Expr_Node_Type type,
                  Expr_Node_Value value,
                  Expr_Node_Value value,
                  Expr_Node *Left_Child,
                  Expr_Node *Left_Child,
                  Expr_Node *Right_Child)
                  Expr_Node *Right_Child)
{
{
 
 
 
 
  Expr_Node *node = (Expr_Node *) allocate (sizeof (Expr_Node));
  Expr_Node *node = (Expr_Node *) allocate (sizeof (Expr_Node));
  node->type = type;
  node->type = type;
  node->value = value;
  node->value = value;
  node->Left_Child = Left_Child;
  node->Left_Child = Left_Child;
  node->Right_Child = Right_Child;
  node->Right_Child = Right_Child;
  return node;
  return node;
}
}
 
 
static const char *con = ".__constant";
static const char *con = ".__constant";
static const char *op = ".__operator";
static const char *op = ".__operator";
static INSTR_T Expr_Node_Gen_Reloc_R (Expr_Node * head);
static INSTR_T Expr_Node_Gen_Reloc_R (Expr_Node * head);
INSTR_T Expr_Node_Gen_Reloc (Expr_Node *head, int parent_reloc);
INSTR_T Expr_Node_Gen_Reloc (Expr_Node *head, int parent_reloc);
 
 
INSTR_T
INSTR_T
Expr_Node_Gen_Reloc (Expr_Node * head, int parent_reloc)
Expr_Node_Gen_Reloc (Expr_Node * head, int parent_reloc)
{
{
  /* Top level reloction expression generator VDSP style.
  /* Top level reloction expression generator VDSP style.
   If the relocation is just by itself, generate one item
   If the relocation is just by itself, generate one item
   else generate this convoluted expression.  */
   else generate this convoluted expression.  */
 
 
  INSTR_T note = NULL_CODE;
  INSTR_T note = NULL_CODE;
  INSTR_T note1 = NULL_CODE;
  INSTR_T note1 = NULL_CODE;
  int pcrel = 1;  /* Is the parent reloc pcrelative?
  int pcrel = 1;  /* Is the parent reloc pcrelative?
                  This calculation here and HOWTO should match.  */
                  This calculation here and HOWTO should match.  */
 
 
  if (parent_reloc)
  if (parent_reloc)
    {
    {
      /*  If it's 32 bit quantity then 16bit code needs to be added.  */
      /*  If it's 32 bit quantity then 16bit code needs to be added.  */
      int value = 0;
      int value = 0;
 
 
      if (head->type == Expr_Node_Constant)
      if (head->type == Expr_Node_Constant)
        {
        {
          /* If note1 is not null code, we have to generate a right
          /* If note1 is not null code, we have to generate a right
             aligned value for the constant. Otherwise the reloc is
             aligned value for the constant. Otherwise the reloc is
             a part of the basic command and the yacc file
             a part of the basic command and the yacc file
             generates this.  */
             generates this.  */
          value = head->value.i_value;
          value = head->value.i_value;
        }
        }
      switch (parent_reloc)
      switch (parent_reloc)
        {
        {
          /*  Some relocations will need to allocate extra words.  */
          /*  Some relocations will need to allocate extra words.  */
        case BFD_RELOC_BFIN_16_IMM:
        case BFD_RELOC_BFIN_16_IMM:
        case BFD_RELOC_BFIN_16_LOW:
        case BFD_RELOC_BFIN_16_LOW:
        case BFD_RELOC_BFIN_16_HIGH:
        case BFD_RELOC_BFIN_16_HIGH:
          note1 = conscode (gencode (value), NULL_CODE);
          note1 = conscode (gencode (value), NULL_CODE);
          pcrel = 0;
          pcrel = 0;
          break;
          break;
        case BFD_RELOC_BFIN_PLTPC:
        case BFD_RELOC_BFIN_PLTPC:
          note1 = conscode (gencode (value), NULL_CODE);
          note1 = conscode (gencode (value), NULL_CODE);
          pcrel = 0;
          pcrel = 0;
          break;
          break;
        case BFD_RELOC_16:
        case BFD_RELOC_16:
        case BFD_RELOC_BFIN_GOT:
        case BFD_RELOC_BFIN_GOT:
        case BFD_RELOC_BFIN_GOT17M4:
        case BFD_RELOC_BFIN_GOT17M4:
        case BFD_RELOC_BFIN_FUNCDESC_GOT17M4:
        case BFD_RELOC_BFIN_FUNCDESC_GOT17M4:
          note1 = conscode (gencode (value), NULL_CODE);
          note1 = conscode (gencode (value), NULL_CODE);
          pcrel = 0;
          pcrel = 0;
          break;
          break;
        case BFD_RELOC_24_PCREL:
        case BFD_RELOC_24_PCREL:
        case BFD_RELOC_BFIN_24_PCREL_JUMP_L:
        case BFD_RELOC_BFIN_24_PCREL_JUMP_L:
        case BFD_RELOC_BFIN_24_PCREL_CALL_X:
        case BFD_RELOC_BFIN_24_PCREL_CALL_X:
          /* These offsets are even numbered pcrel.  */
          /* These offsets are even numbered pcrel.  */
          note1 = conscode (gencode (value >> 1), NULL_CODE);
          note1 = conscode (gencode (value >> 1), NULL_CODE);
          break;
          break;
        default:
        default:
          note1 = NULL_CODE;
          note1 = NULL_CODE;
        }
        }
    }
    }
  if (head->type == Expr_Node_Constant)
  if (head->type == Expr_Node_Constant)
    note = note1;
    note = note1;
  else if (head->type == Expr_Node_Reloc)
  else if (head->type == Expr_Node_Reloc)
    {
    {
      note = note_reloc1 (gencode (0), head->value.s_value, parent_reloc, pcrel);
      note = note_reloc1 (gencode (0), head->value.s_value, parent_reloc, pcrel);
      if (note1 != NULL_CODE)
      if (note1 != NULL_CODE)
        note = conscode (note1, note);
        note = conscode (note1, note);
    }
    }
  else if (head->type == Expr_Node_Binop
  else if (head->type == Expr_Node_Binop
           && (head->value.op_value == Expr_Op_Type_Add
           && (head->value.op_value == Expr_Op_Type_Add
               || head->value.op_value == Expr_Op_Type_Sub)
               || head->value.op_value == Expr_Op_Type_Sub)
           && head->Left_Child->type == Expr_Node_Reloc
           && head->Left_Child->type == Expr_Node_Reloc
           && head->Right_Child->type == Expr_Node_Constant)
           && head->Right_Child->type == Expr_Node_Constant)
    {
    {
      int val = head->Right_Child->value.i_value;
      int val = head->Right_Child->value.i_value;
      if (head->value.op_value == Expr_Op_Type_Sub)
      if (head->value.op_value == Expr_Op_Type_Sub)
        val = -val;
        val = -val;
      note = conscode (note_reloc2 (gencode (0), head->Left_Child->value.s_value,
      note = conscode (note_reloc2 (gencode (0), head->Left_Child->value.s_value,
                                    parent_reloc, val, 0),
                                    parent_reloc, val, 0),
                       NULL_CODE);
                       NULL_CODE);
      if (note1 != NULL_CODE)
      if (note1 != NULL_CODE)
        note = conscode (note1, note);
        note = conscode (note1, note);
    }
    }
  else
  else
    {
    {
      /* Call the recursive function.  */
      /* Call the recursive function.  */
      note = note_reloc1 (gencode (0), op, parent_reloc, pcrel);
      note = note_reloc1 (gencode (0), op, parent_reloc, pcrel);
      if (note1 != NULL_CODE)
      if (note1 != NULL_CODE)
        note = conscode (note1, note);
        note = conscode (note1, note);
      note = conctcode (Expr_Node_Gen_Reloc_R (head), note);
      note = conctcode (Expr_Node_Gen_Reloc_R (head), note);
    }
    }
  return note;
  return note;
}
}
 
 
static INSTR_T
static INSTR_T
Expr_Node_Gen_Reloc_R (Expr_Node * head)
Expr_Node_Gen_Reloc_R (Expr_Node * head)
{
{
 
 
  INSTR_T note = 0;
  INSTR_T note = 0;
  INSTR_T note1 = 0;
  INSTR_T note1 = 0;
 
 
  switch (head->type)
  switch (head->type)
    {
    {
    case Expr_Node_Constant:
    case Expr_Node_Constant:
      note = conscode (note_reloc2 (gencode (0), con, BFD_ARELOC_BFIN_CONST, head->value.i_value, 0), NULL_CODE);
      note = conscode (note_reloc2 (gencode (0), con, BFD_ARELOC_BFIN_CONST, head->value.i_value, 0), NULL_CODE);
      break;
      break;
    case Expr_Node_Reloc:
    case Expr_Node_Reloc:
      note = conscode (note_reloc (gencode (0), head, BFD_ARELOC_BFIN_PUSH, 0), NULL_CODE);
      note = conscode (note_reloc (gencode (0), head, BFD_ARELOC_BFIN_PUSH, 0), NULL_CODE);
      break;
      break;
    case Expr_Node_Binop:
    case Expr_Node_Binop:
      note1 = conctcode (Expr_Node_Gen_Reloc_R (head->Left_Child), Expr_Node_Gen_Reloc_R (head->Right_Child));
      note1 = conctcode (Expr_Node_Gen_Reloc_R (head->Left_Child), Expr_Node_Gen_Reloc_R (head->Right_Child));
      switch (head->value.op_value)
      switch (head->value.op_value)
        {
        {
        case Expr_Op_Type_Add:
        case Expr_Op_Type_Add:
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_ADD, 0), NULL_CODE));
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_ADD, 0), NULL_CODE));
          break;
          break;
        case Expr_Op_Type_Sub:
        case Expr_Op_Type_Sub:
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_SUB, 0), NULL_CODE));
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_SUB, 0), NULL_CODE));
          break;
          break;
        case Expr_Op_Type_Mult:
        case Expr_Op_Type_Mult:
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_MULT, 0), NULL_CODE));
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_MULT, 0), NULL_CODE));
          break;
          break;
        case Expr_Op_Type_Div:
        case Expr_Op_Type_Div:
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_DIV, 0), NULL_CODE));
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_DIV, 0), NULL_CODE));
          break;
          break;
        case Expr_Op_Type_Mod:
        case Expr_Op_Type_Mod:
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_MOD, 0), NULL_CODE));
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_MOD, 0), NULL_CODE));
          break;
          break;
        case Expr_Op_Type_Lshift:
        case Expr_Op_Type_Lshift:
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_LSHIFT, 0), NULL_CODE));
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_LSHIFT, 0), NULL_CODE));
          break;
          break;
        case Expr_Op_Type_Rshift:
        case Expr_Op_Type_Rshift:
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_RSHIFT, 0), NULL_CODE));
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_RSHIFT, 0), NULL_CODE));
          break;
          break;
        case Expr_Op_Type_BAND:
        case Expr_Op_Type_BAND:
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_AND, 0), NULL_CODE));
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_AND, 0), NULL_CODE));
          break;
          break;
        case Expr_Op_Type_BOR:
        case Expr_Op_Type_BOR:
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_OR, 0), NULL_CODE));
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_OR, 0), NULL_CODE));
          break;
          break;
        case Expr_Op_Type_BXOR:
        case Expr_Op_Type_BXOR:
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_XOR, 0), NULL_CODE));
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_XOR, 0), NULL_CODE));
          break;
          break;
        case Expr_Op_Type_LAND:
        case Expr_Op_Type_LAND:
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_LAND, 0), NULL_CODE));
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_LAND, 0), NULL_CODE));
          break;
          break;
        case Expr_Op_Type_LOR:
        case Expr_Op_Type_LOR:
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_LOR, 0), NULL_CODE));
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_LOR, 0), NULL_CODE));
          break;
          break;
        default:
        default:
          fprintf (stderr, "%s:%d:Unknown operator found for arithmetic" " relocation", __FILE__, __LINE__);
          fprintf (stderr, "%s:%d:Unknown operator found for arithmetic" " relocation", __FILE__, __LINE__);
 
 
 
 
        }
        }
      break;
      break;
    case Expr_Node_Unop:
    case Expr_Node_Unop:
      note1 = conscode (Expr_Node_Gen_Reloc_R (head->Left_Child), NULL_CODE);
      note1 = conscode (Expr_Node_Gen_Reloc_R (head->Left_Child), NULL_CODE);
      switch (head->value.op_value)
      switch (head->value.op_value)
        {
        {
        case Expr_Op_Type_NEG:
        case Expr_Op_Type_NEG:
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_NEG, 0), NULL_CODE));
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_NEG, 0), NULL_CODE));
          break;
          break;
        case Expr_Op_Type_COMP:
        case Expr_Op_Type_COMP:
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_COMP, 0), NULL_CODE));
          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_COMP, 0), NULL_CODE));
          break;
          break;
        default:
        default:
          fprintf (stderr, "%s:%d:Unknown operator found for arithmetic" " relocation", __FILE__, __LINE__);
          fprintf (stderr, "%s:%d:Unknown operator found for arithmetic" " relocation", __FILE__, __LINE__);
        }
        }
      break;
      break;
    default:
    default:
      fprintf (stderr, "%s:%d:Unknown node expression found during " "arithmetic relocation generation", __FILE__, __LINE__);
      fprintf (stderr, "%s:%d:Unknown node expression found during " "arithmetic relocation generation", __FILE__, __LINE__);
    }
    }
  return note;
  return note;
}
}
 
 
 
 
/* Blackfin opcode generation.  */
/* Blackfin opcode generation.  */
 
 
/* These functions are called by the generated parser
/* These functions are called by the generated parser
   (from bfin-parse.y), the register type classification
   (from bfin-parse.y), the register type classification
   happens in bfin-lex.l.  */
   happens in bfin-lex.l.  */
 
 
#include "bfin-aux.h"
#include "bfin-aux.h"
#include "opcode/bfin.h"
#include "opcode/bfin.h"
 
 
#define INIT(t)  t c_code = init_##t
#define INIT(t)  t c_code = init_##t
#define ASSIGN(x) c_code.opcode |= ((x & c_code.mask_##x)<<c_code.bits_##x)
#define ASSIGN(x) c_code.opcode |= ((x & c_code.mask_##x)<<c_code.bits_##x)
#define ASSIGN_R(x) c_code.opcode |= (((x ? (x->regno & CODE_MASK) : 0) & c_code.mask_##x)<<c_code.bits_##x)
#define ASSIGN_R(x) c_code.opcode |= (((x ? (x->regno & CODE_MASK) : 0) & c_code.mask_##x)<<c_code.bits_##x)
 
 
#define HI(x) ((x >> 16) & 0xffff)
#define HI(x) ((x >> 16) & 0xffff)
#define LO(x) ((x      ) & 0xffff)
#define LO(x) ((x      ) & 0xffff)
 
 
#define GROUP(x) ((x->regno & CLASS_MASK) >> 4)
#define GROUP(x) ((x->regno & CLASS_MASK) >> 4)
 
 
#define GEN_OPCODE32()  \
#define GEN_OPCODE32()  \
        conscode (gencode (HI (c_code.opcode)), \
        conscode (gencode (HI (c_code.opcode)), \
        conscode (gencode (LO (c_code.opcode)), NULL_CODE))
        conscode (gencode (LO (c_code.opcode)), NULL_CODE))
 
 
#define GEN_OPCODE16()  \
#define GEN_OPCODE16()  \
        conscode (gencode (c_code.opcode), NULL_CODE)
        conscode (gencode (c_code.opcode), NULL_CODE)
 
 
 
 
/*  32 BIT INSTRUCTIONS.  */
/*  32 BIT INSTRUCTIONS.  */
 
 
 
 
/* DSP32 instruction generation.  */
/* DSP32 instruction generation.  */
 
 
INSTR_T
INSTR_T
bfin_gen_dsp32mac (int op1, int MM, int mmod, int w1, int P,
bfin_gen_dsp32mac (int op1, int MM, int mmod, int w1, int P,
                   int h01, int h11, int h00, int h10, int op0,
                   int h01, int h11, int h00, int h10, int op0,
                   REG_T dst, REG_T src0, REG_T src1, int w0)
                   REG_T dst, REG_T src0, REG_T src1, int w0)
{
{
  INIT (DSP32Mac);
  INIT (DSP32Mac);
 
 
  ASSIGN (op0);
  ASSIGN (op0);
  ASSIGN (op1);
  ASSIGN (op1);
  ASSIGN (MM);
  ASSIGN (MM);
  ASSIGN (mmod);
  ASSIGN (mmod);
  ASSIGN (w0);
  ASSIGN (w0);
  ASSIGN (w1);
  ASSIGN (w1);
  ASSIGN (h01);
  ASSIGN (h01);
  ASSIGN (h11);
  ASSIGN (h11);
  ASSIGN (h00);
  ASSIGN (h00);
  ASSIGN (h10);
  ASSIGN (h10);
  ASSIGN (P);
  ASSIGN (P);
 
 
  /* If we have full reg assignments, mask out LSB to encode
  /* If we have full reg assignments, mask out LSB to encode
  single or simultaneous even/odd register moves.  */
  single or simultaneous even/odd register moves.  */
  if (P)
  if (P)
    {
    {
      dst->regno &= 0x06;
      dst->regno &= 0x06;
    }
    }
 
 
  ASSIGN_R (dst);
  ASSIGN_R (dst);
  ASSIGN_R (src0);
  ASSIGN_R (src0);
  ASSIGN_R (src1);
  ASSIGN_R (src1);
 
 
  return GEN_OPCODE32 ();
  return GEN_OPCODE32 ();
}
}
 
 
INSTR_T
INSTR_T
bfin_gen_dsp32mult (int op1, int MM, int mmod, int w1, int P,
bfin_gen_dsp32mult (int op1, int MM, int mmod, int w1, int P,
                    int h01, int h11, int h00, int h10, int op0,
                    int h01, int h11, int h00, int h10, int op0,
                    REG_T dst, REG_T src0, REG_T src1, int w0)
                    REG_T dst, REG_T src0, REG_T src1, int w0)
{
{
  INIT (DSP32Mult);
  INIT (DSP32Mult);
 
 
  ASSIGN (op0);
  ASSIGN (op0);
  ASSIGN (op1);
  ASSIGN (op1);
  ASSIGN (MM);
  ASSIGN (MM);
  ASSIGN (mmod);
  ASSIGN (mmod);
  ASSIGN (w0);
  ASSIGN (w0);
  ASSIGN (w1);
  ASSIGN (w1);
  ASSIGN (h01);
  ASSIGN (h01);
  ASSIGN (h11);
  ASSIGN (h11);
  ASSIGN (h00);
  ASSIGN (h00);
  ASSIGN (h10);
  ASSIGN (h10);
  ASSIGN (P);
  ASSIGN (P);
 
 
  if (P)
  if (P)
    {
    {
      dst->regno &= 0x06;
      dst->regno &= 0x06;
    }
    }
 
 
  ASSIGN_R (dst);
  ASSIGN_R (dst);
  ASSIGN_R (src0);
  ASSIGN_R (src0);
  ASSIGN_R (src1);
  ASSIGN_R (src1);
 
 
  return GEN_OPCODE32 ();
  return GEN_OPCODE32 ();
}
}
 
 
INSTR_T
INSTR_T
bfin_gen_dsp32alu (int HL, int aopcde, int aop, int s, int x,
bfin_gen_dsp32alu (int HL, int aopcde, int aop, int s, int x,
              REG_T dst0, REG_T dst1, REG_T src0, REG_T src1)
              REG_T dst0, REG_T dst1, REG_T src0, REG_T src1)
{
{
  INIT (DSP32Alu);
  INIT (DSP32Alu);
 
 
  ASSIGN (HL);
  ASSIGN (HL);
  ASSIGN (aopcde);
  ASSIGN (aopcde);
  ASSIGN (aop);
  ASSIGN (aop);
  ASSIGN (s);
  ASSIGN (s);
  ASSIGN (x);
  ASSIGN (x);
  ASSIGN_R (dst0);
  ASSIGN_R (dst0);
  ASSIGN_R (dst1);
  ASSIGN_R (dst1);
  ASSIGN_R (src0);
  ASSIGN_R (src0);
  ASSIGN_R (src1);
  ASSIGN_R (src1);
 
 
  return GEN_OPCODE32 ();
  return GEN_OPCODE32 ();
}
}
 
 
INSTR_T
INSTR_T
bfin_gen_dsp32shift (int sopcde, REG_T dst0, REG_T src0,
bfin_gen_dsp32shift (int sopcde, REG_T dst0, REG_T src0,
                REG_T src1, int sop, int HLs)
                REG_T src1, int sop, int HLs)
{
{
  INIT (DSP32Shift);
  INIT (DSP32Shift);
 
 
  ASSIGN (sopcde);
  ASSIGN (sopcde);
  ASSIGN (sop);
  ASSIGN (sop);
  ASSIGN (HLs);
  ASSIGN (HLs);
 
 
  ASSIGN_R (dst0);
  ASSIGN_R (dst0);
  ASSIGN_R (src0);
  ASSIGN_R (src0);
  ASSIGN_R (src1);
  ASSIGN_R (src1);
 
 
  return GEN_OPCODE32 ();
  return GEN_OPCODE32 ();
}
}
 
 
INSTR_T
INSTR_T
bfin_gen_dsp32shiftimm (int sopcde, REG_T dst0, int immag,
bfin_gen_dsp32shiftimm (int sopcde, REG_T dst0, int immag,
                   REG_T src1, int sop, int HLs)
                   REG_T src1, int sop, int HLs)
{
{
  INIT (DSP32ShiftImm);
  INIT (DSP32ShiftImm);
 
 
  ASSIGN (sopcde);
  ASSIGN (sopcde);
  ASSIGN (sop);
  ASSIGN (sop);
  ASSIGN (HLs);
  ASSIGN (HLs);
 
 
  ASSIGN_R (dst0);
  ASSIGN_R (dst0);
  ASSIGN (immag);
  ASSIGN (immag);
  ASSIGN_R (src1);
  ASSIGN_R (src1);
 
 
  return GEN_OPCODE32 ();
  return GEN_OPCODE32 ();
}
}
 
 
/* LOOP SETUP.  */
/* LOOP SETUP.  */
 
 
INSTR_T
INSTR_T
bfin_gen_loopsetup (Expr_Node * psoffset, REG_T c, int rop,
bfin_gen_loopsetup (Expr_Node * psoffset, REG_T c, int rop,
               Expr_Node * peoffset, REG_T reg)
               Expr_Node * peoffset, REG_T reg)
{
{
  int soffset, eoffset;
  int soffset, eoffset;
  INIT (LoopSetup);
  INIT (LoopSetup);
 
 
  soffset = (EXPR_VALUE (psoffset) >> 1);
  soffset = (EXPR_VALUE (psoffset) >> 1);
  ASSIGN (soffset);
  ASSIGN (soffset);
  eoffset = (EXPR_VALUE (peoffset) >> 1);
  eoffset = (EXPR_VALUE (peoffset) >> 1);
  ASSIGN (eoffset);
  ASSIGN (eoffset);
  ASSIGN (rop);
  ASSIGN (rop);
  ASSIGN_R (c);
  ASSIGN_R (c);
  ASSIGN_R (reg);
  ASSIGN_R (reg);
 
 
  return
  return
      conscode (gencode (HI (c_code.opcode)),
      conscode (gencode (HI (c_code.opcode)),
                conctcode (Expr_Node_Gen_Reloc (psoffset, BFD_RELOC_BFIN_5_PCREL),
                conctcode (Expr_Node_Gen_Reloc (psoffset, BFD_RELOC_BFIN_5_PCREL),
                           conctcode (gencode (LO (c_code.opcode)), Expr_Node_Gen_Reloc (peoffset, BFD_RELOC_BFIN_11_PCREL))));
                           conctcode (gencode (LO (c_code.opcode)), Expr_Node_Gen_Reloc (peoffset, BFD_RELOC_BFIN_11_PCREL))));
 
 
}
}
 
 
/*  Call, Link.  */
/*  Call, Link.  */
 
 
INSTR_T
INSTR_T
bfin_gen_calla (Expr_Node * addr, int S)
bfin_gen_calla (Expr_Node * addr, int S)
{
{
  int val;
  int val;
  int high_val;
  int high_val;
  int reloc = 0;
  int reloc = 0;
  INIT (CALLa);
  INIT (CALLa);
 
 
  switch(S){
  switch(S){
   case 0 : reloc = BFD_RELOC_BFIN_24_PCREL_JUMP_L; break;
   case 0 : reloc = BFD_RELOC_BFIN_24_PCREL_JUMP_L; break;
   case 1 : reloc = BFD_RELOC_24_PCREL; break;
   case 1 : reloc = BFD_RELOC_24_PCREL; break;
   case 2 : reloc = BFD_RELOC_BFIN_PLTPC; break;
   case 2 : reloc = BFD_RELOC_BFIN_PLTPC; break;
   default : break;
   default : break;
  }
  }
 
 
  ASSIGN (S);
  ASSIGN (S);
 
 
  val = EXPR_VALUE (addr) >> 1;
  val = EXPR_VALUE (addr) >> 1;
  high_val = val >> 16;
  high_val = val >> 16;
 
 
  return conscode (gencode (HI (c_code.opcode) | (high_val & 0xff)),
  return conscode (gencode (HI (c_code.opcode) | (high_val & 0xff)),
                     Expr_Node_Gen_Reloc (addr, reloc));
                     Expr_Node_Gen_Reloc (addr, reloc));
  }
  }
 
 
INSTR_T
INSTR_T
bfin_gen_linkage (int R, int framesize)
bfin_gen_linkage (int R, int framesize)
{
{
  INIT (Linkage);
  INIT (Linkage);
 
 
  ASSIGN (R);
  ASSIGN (R);
  ASSIGN (framesize);
  ASSIGN (framesize);
 
 
  return GEN_OPCODE32 ();
  return GEN_OPCODE32 ();
}
}
 
 
 
 
/* Load and Store.  */
/* Load and Store.  */
 
 
INSTR_T
INSTR_T
bfin_gen_ldimmhalf (REG_T reg, int H, int S, int Z, Expr_Node * phword, int reloc)
bfin_gen_ldimmhalf (REG_T reg, int H, int S, int Z, Expr_Node * phword, int reloc)
{
{
  int grp, hword;
  int grp, hword;
  unsigned val = EXPR_VALUE (phword);
  unsigned val = EXPR_VALUE (phword);
  INIT (LDIMMhalf);
  INIT (LDIMMhalf);
 
 
  ASSIGN (H);
  ASSIGN (H);
  ASSIGN (S);
  ASSIGN (S);
  ASSIGN (Z);
  ASSIGN (Z);
 
 
  ASSIGN_R (reg);
  ASSIGN_R (reg);
  grp = (GROUP (reg));
  grp = (GROUP (reg));
  ASSIGN (grp);
  ASSIGN (grp);
  if (reloc == 2)
  if (reloc == 2)
    {
    {
      return conscode (gencode (HI (c_code.opcode)), Expr_Node_Gen_Reloc (phword, BFD_RELOC_BFIN_16_IMM));
      return conscode (gencode (HI (c_code.opcode)), Expr_Node_Gen_Reloc (phword, BFD_RELOC_BFIN_16_IMM));
    }
    }
  else if (reloc == 1)
  else if (reloc == 1)
    {
    {
      return conscode (gencode (HI (c_code.opcode)), Expr_Node_Gen_Reloc (phword, IS_H (*reg) ? BFD_RELOC_BFIN_16_HIGH : BFD_RELOC_BFIN_16_LOW));
      return conscode (gencode (HI (c_code.opcode)), Expr_Node_Gen_Reloc (phword, IS_H (*reg) ? BFD_RELOC_BFIN_16_HIGH : BFD_RELOC_BFIN_16_LOW));
    }
    }
  else
  else
    {
    {
      hword = val;
      hword = val;
      ASSIGN (hword);
      ASSIGN (hword);
    }
    }
  return GEN_OPCODE32 ();
  return GEN_OPCODE32 ();
}
}
 
 
INSTR_T
INSTR_T
bfin_gen_ldstidxi (REG_T ptr, REG_T reg, int W, int sz, int Z, Expr_Node * poffset)
bfin_gen_ldstidxi (REG_T ptr, REG_T reg, int W, int sz, int Z, Expr_Node * poffset)
{
{
  INIT (LDSTidxI);
  INIT (LDSTidxI);
 
 
  if (!IS_PREG (*ptr) || (!IS_DREG (*reg) && !Z))
  if (!IS_PREG (*ptr) || (!IS_DREG (*reg) && !Z))
    {
    {
      fprintf (stderr, "Warning: possible mixup of Preg/Dreg\n");
      fprintf (stderr, "Warning: possible mixup of Preg/Dreg\n");
      return 0;
      return 0;
    }
    }
 
 
  ASSIGN_R (ptr);
  ASSIGN_R (ptr);
  ASSIGN_R (reg);
  ASSIGN_R (reg);
  ASSIGN (W);
  ASSIGN (W);
  ASSIGN (sz);
  ASSIGN (sz);
 
 
  ASSIGN (Z);
  ASSIGN (Z);
 
 
  if (poffset->type != Expr_Node_Constant)
  if (poffset->type != Expr_Node_Constant)
    {
    {
      /* a GOT relocation such as R0 = [P5 + symbol@GOT] */
      /* a GOT relocation such as R0 = [P5 + symbol@GOT] */
      /* distinguish between R0 = [P5 + symbol@GOT] and
      /* distinguish between R0 = [P5 + symbol@GOT] and
         P5 = [P5 + _current_shared_library_p5_offset_]
         P5 = [P5 + _current_shared_library_p5_offset_]
      */
      */
      if (poffset->type == Expr_Node_Reloc
      if (poffset->type == Expr_Node_Reloc
          && !strcmp (poffset->value.s_value,
          && !strcmp (poffset->value.s_value,
                      "_current_shared_library_p5_offset_"))
                      "_current_shared_library_p5_offset_"))
        {
        {
          return  conscode (gencode (HI (c_code.opcode)),
          return  conscode (gencode (HI (c_code.opcode)),
                            Expr_Node_Gen_Reloc(poffset, BFD_RELOC_16));
                            Expr_Node_Gen_Reloc(poffset, BFD_RELOC_16));
        }
        }
      else if (poffset->type != Expr_Node_GOT_Reloc)
      else if (poffset->type != Expr_Node_GOT_Reloc)
        abort ();
        abort ();
 
 
      return conscode (gencode (HI (c_code.opcode)),
      return conscode (gencode (HI (c_code.opcode)),
                       Expr_Node_Gen_Reloc(poffset->Left_Child,
                       Expr_Node_Gen_Reloc(poffset->Left_Child,
                                           poffset->value.i_value));
                                           poffset->value.i_value));
    }
    }
  else
  else
    {
    {
      int value, offset;
      int value, offset;
      switch (sz)
      switch (sz)
        {                               // load/store access size
        {                               // load/store access size
        case 0:                  // 32 bit
        case 0:                  // 32 bit
          value = EXPR_VALUE (poffset) >> 2;
          value = EXPR_VALUE (poffset) >> 2;
          break;
          break;
        case 1:                 // 16 bit
        case 1:                 // 16 bit
          value = EXPR_VALUE (poffset) >> 1;
          value = EXPR_VALUE (poffset) >> 1;
          break;
          break;
        case 2:                 // 8 bit
        case 2:                 // 8 bit
          value = EXPR_VALUE (poffset);
          value = EXPR_VALUE (poffset);
          break;
          break;
        default:
        default:
          abort ();
          abort ();
        }
        }
 
 
      offset = (value & 0xffff);
      offset = (value & 0xffff);
      ASSIGN (offset);
      ASSIGN (offset);
      return GEN_OPCODE32 ();
      return GEN_OPCODE32 ();
    }
    }
}
}
 
 
 
 
INSTR_T
INSTR_T
bfin_gen_ldst (REG_T ptr, REG_T reg, int aop, int sz, int Z, int W)
bfin_gen_ldst (REG_T ptr, REG_T reg, int aop, int sz, int Z, int W)
{
{
  INIT (LDST);
  INIT (LDST);
 
 
  if (!IS_PREG (*ptr) || (!IS_DREG (*reg) && !Z))
  if (!IS_PREG (*ptr) || (!IS_DREG (*reg) && !Z))
    {
    {
      fprintf (stderr, "Warning: possible mixup of Preg/Dreg\n");
      fprintf (stderr, "Warning: possible mixup of Preg/Dreg\n");
      return 0;
      return 0;
    }
    }
 
 
  ASSIGN_R (ptr);
  ASSIGN_R (ptr);
  ASSIGN_R (reg);
  ASSIGN_R (reg);
  ASSIGN (aop);
  ASSIGN (aop);
  ASSIGN (sz);
  ASSIGN (sz);
  ASSIGN (Z);
  ASSIGN (Z);
  ASSIGN (W);
  ASSIGN (W);
 
 
  return GEN_OPCODE16 ();
  return GEN_OPCODE16 ();
}
}
 
 
INSTR_T
INSTR_T
bfin_gen_ldstii (REG_T ptr, REG_T reg, Expr_Node * poffset, int W, int op)
bfin_gen_ldstii (REG_T ptr, REG_T reg, Expr_Node * poffset, int W, int op)
{
{
  int offset;
  int offset;
  int value = 0;
  int value = 0;
  INIT (LDSTii);
  INIT (LDSTii);
 
 
 
 
  if (!IS_PREG (*ptr))
  if (!IS_PREG (*ptr))
    {
    {
      fprintf (stderr, "Warning: possible mixup of Preg/Dreg\n");
      fprintf (stderr, "Warning: possible mixup of Preg/Dreg\n");
      return 0;
      return 0;
    }
    }
 
 
  switch (op)
  switch (op)
    {
    {
    case 1:
    case 1:
    case 2:
    case 2:
      value = EXPR_VALUE (poffset) >> 1;
      value = EXPR_VALUE (poffset) >> 1;
      break;
      break;
    case 0:
    case 0:
    case 3:
    case 3:
      value = EXPR_VALUE (poffset) >> 2;
      value = EXPR_VALUE (poffset) >> 2;
      break;
      break;
    }
    }
 
 
  ASSIGN_R (ptr);
  ASSIGN_R (ptr);
  ASSIGN_R (reg);
  ASSIGN_R (reg);
 
 
  offset = value;
  offset = value;
  ASSIGN (offset);
  ASSIGN (offset);
  ASSIGN (W);
  ASSIGN (W);
  ASSIGN (op);
  ASSIGN (op);
 
 
  return GEN_OPCODE16 ();
  return GEN_OPCODE16 ();
}
}
 
 
INSTR_T
INSTR_T
bfin_gen_ldstiifp (REG_T sreg, Expr_Node * poffset, int W)
bfin_gen_ldstiifp (REG_T sreg, Expr_Node * poffset, int W)
{
{
  /* Set bit 4 if it's a Preg.  */
  /* Set bit 4 if it's a Preg.  */
  int reg = (sreg->regno & CODE_MASK) | (IS_PREG (*sreg) ? 0x8 : 0x0);
  int reg = (sreg->regno & CODE_MASK) | (IS_PREG (*sreg) ? 0x8 : 0x0);
  int offset = ((~(EXPR_VALUE (poffset) >> 2)) & 0x1f) + 1;
  int offset = ((~(EXPR_VALUE (poffset) >> 2)) & 0x1f) + 1;
  INIT (LDSTiiFP);
  INIT (LDSTiiFP);
  ASSIGN (reg);
  ASSIGN (reg);
  ASSIGN (offset);
  ASSIGN (offset);
  ASSIGN (W);
  ASSIGN (W);
 
 
  return GEN_OPCODE16 ();
  return GEN_OPCODE16 ();
}
}
 
 
INSTR_T
INSTR_T
bfin_gen_ldstpmod (REG_T ptr, REG_T reg, int aop, int W, REG_T idx)
bfin_gen_ldstpmod (REG_T ptr, REG_T reg, int aop, int W, REG_T idx)
{
{
  INIT (LDSTpmod);
  INIT (LDSTpmod);
 
 
  ASSIGN_R (ptr);
  ASSIGN_R (ptr);
  ASSIGN_R (reg);
  ASSIGN_R (reg);
  ASSIGN (aop);
  ASSIGN (aop);
  ASSIGN (W);
  ASSIGN (W);
  ASSIGN_R (idx);
  ASSIGN_R (idx);
 
 
  return GEN_OPCODE16 ();
  return GEN_OPCODE16 ();
}
}
 
 
INSTR_T
INSTR_T
bfin_gen_dspldst (REG_T i, REG_T reg, int aop, int W, int m)
bfin_gen_dspldst (REG_T i, REG_T reg, int aop, int W, int m)
{
{
  INIT (DspLDST);
  INIT (DspLDST);
 
 
  ASSIGN_R (i);
  ASSIGN_R (i);
  ASSIGN_R (reg);
  ASSIGN_R (reg);
  ASSIGN (aop);
  ASSIGN (aop);
  ASSIGN (W);
  ASSIGN (W);
  ASSIGN (m);
  ASSIGN (m);
 
 
  return GEN_OPCODE16 ();
  return GEN_OPCODE16 ();
}
}
 
 
INSTR_T
INSTR_T
bfin_gen_logi2op (int opc, int src, int dst)
bfin_gen_logi2op (int opc, int src, int dst)
{
{
  INIT (LOGI2op);
  INIT (LOGI2op);
 
 
  ASSIGN (opc);
  ASSIGN (opc);
  ASSIGN (src);
  ASSIGN (src);
  ASSIGN (dst);
  ASSIGN (dst);
 
 
  return GEN_OPCODE16 ();
  return GEN_OPCODE16 ();
}
}
 
 
INSTR_T
INSTR_T
bfin_gen_brcc (int T, int B, Expr_Node * poffset)
bfin_gen_brcc (int T, int B, Expr_Node * poffset)
{
{
  int offset;
  int offset;
  INIT (BRCC);
  INIT (BRCC);
 
 
  ASSIGN (T);
  ASSIGN (T);
  ASSIGN (B);
  ASSIGN (B);
  offset = ((EXPR_VALUE (poffset) >> 1));
  offset = ((EXPR_VALUE (poffset) >> 1));
  ASSIGN (offset);
  ASSIGN (offset);
  return conscode (gencode (c_code.opcode), Expr_Node_Gen_Reloc (poffset, BFD_RELOC_BFIN_10_PCREL));
  return conscode (gencode (c_code.opcode), Expr_Node_Gen_Reloc (poffset, BFD_RELOC_BFIN_10_PCREL));
}
}
 
 
INSTR_T
INSTR_T
bfin_gen_ujump (Expr_Node * poffset)
bfin_gen_ujump (Expr_Node * poffset)
{
{
  int offset;
  int offset;
  INIT (UJump);
  INIT (UJump);
 
 
  offset = ((EXPR_VALUE (poffset) >> 1));
  offset = ((EXPR_VALUE (poffset) >> 1));
  ASSIGN (offset);
  ASSIGN (offset);
 
 
  return conscode (gencode (c_code.opcode),
  return conscode (gencode (c_code.opcode),
                   Expr_Node_Gen_Reloc (
                   Expr_Node_Gen_Reloc (
                       poffset, BFD_RELOC_BFIN_12_PCREL_JUMP_S));
                       poffset, BFD_RELOC_BFIN_12_PCREL_JUMP_S));
}
}
 
 
INSTR_T
INSTR_T
bfin_gen_alu2op (REG_T dst, REG_T src, int opc)
bfin_gen_alu2op (REG_T dst, REG_T src, int opc)
{
{
  INIT (ALU2op);
  INIT (ALU2op);
 
 
  ASSIGN_R (dst);
  ASSIGN_R (dst);
  ASSIGN_R (src);
  ASSIGN_R (src);
  ASSIGN (opc);
  ASSIGN (opc);
 
 
  return GEN_OPCODE16 ();
  return GEN_OPCODE16 ();
}
}
 
 
INSTR_T
INSTR_T
bfin_gen_compi2opd (REG_T dst, int src, int op)
bfin_gen_compi2opd (REG_T dst, int src, int op)
{
{
  INIT (COMPI2opD);
  INIT (COMPI2opD);
 
 
  ASSIGN_R (dst);
  ASSIGN_R (dst);
  ASSIGN (src);
  ASSIGN (src);
  ASSIGN (op);
  ASSIGN (op);
 
 
  return GEN_OPCODE16 ();
  return GEN_OPCODE16 ();
}
}
 
 
INSTR_T
INSTR_T
bfin_gen_compi2opp (REG_T dst, int src, int op)
bfin_gen_compi2opp (REG_T dst, int src, int op)
{
{
  INIT (COMPI2opP);
  INIT (COMPI2opP);
 
 
  ASSIGN_R (dst);
  ASSIGN_R (dst);
  ASSIGN (src);
  ASSIGN (src);
  ASSIGN (op);
  ASSIGN (op);
 
 
  return GEN_OPCODE16 ();
  return GEN_OPCODE16 ();
}
}
 
 
INSTR_T
INSTR_T
bfin_gen_dagmodik (REG_T i, int op)
bfin_gen_dagmodik (REG_T i, int op)
{
{
  INIT (DagMODik);
  INIT (DagMODik);
 
 
  ASSIGN_R (i);
  ASSIGN_R (i);
  ASSIGN (op);
  ASSIGN (op);
 
 
  return GEN_OPCODE16 ();
  return GEN_OPCODE16 ();
}
}
 
 
INSTR_T
INSTR_T
bfin_gen_dagmodim (REG_T i, REG_T m, int op, int br)
bfin_gen_dagmodim (REG_T i, REG_T m, int op, int br)
{
{
  INIT (DagMODim);
  INIT (DagMODim);
 
 
  ASSIGN_R (i);
  ASSIGN_R (i);
  ASSIGN_R (m);
  ASSIGN_R (m);
  ASSIGN (op);
  ASSIGN (op);
  ASSIGN (br);
  ASSIGN (br);
 
 
  return GEN_OPCODE16 ();
  return GEN_OPCODE16 ();
}
}
 
 
INSTR_T
INSTR_T
bfin_gen_ptr2op (REG_T dst, REG_T src, int opc)
bfin_gen_ptr2op (REG_T dst, REG_T src, int opc)
{
{
  INIT (PTR2op);
  INIT (PTR2op);
 
 
  ASSIGN_R (dst);
  ASSIGN_R (dst);
  ASSIGN_R (src);
  ASSIGN_R (src);
  ASSIGN (opc);
  ASSIGN (opc);
 
 
  return GEN_OPCODE16 ();
  return GEN_OPCODE16 ();
}
}
 
 
INSTR_T
INSTR_T
bfin_gen_comp3op (REG_T src0, REG_T src1, REG_T dst, int opc)
bfin_gen_comp3op (REG_T src0, REG_T src1, REG_T dst, int opc)
{
{
  INIT (COMP3op);
  INIT (COMP3op);
 
 
  ASSIGN_R (src0);
  ASSIGN_R (src0);
  ASSIGN_R (src1);
  ASSIGN_R (src1);
  ASSIGN_R (dst);
  ASSIGN_R (dst);
  ASSIGN (opc);
  ASSIGN (opc);
 
 
  return GEN_OPCODE16 ();
  return GEN_OPCODE16 ();
}
}
 
 
INSTR_T
INSTR_T
bfin_gen_ccflag (REG_T x, int y, int opc, int I, int G)
bfin_gen_ccflag (REG_T x, int y, int opc, int I, int G)
{
{
  INIT (CCflag);
  INIT (CCflag);
 
 
  ASSIGN_R (x);
  ASSIGN_R (x);
  ASSIGN (y);
  ASSIGN (y);
  ASSIGN (opc);
  ASSIGN (opc);
  ASSIGN (I);
  ASSIGN (I);
  ASSIGN (G);
  ASSIGN (G);
 
 
  return GEN_OPCODE16 ();
  return GEN_OPCODE16 ();
}
}
 
 
INSTR_T
INSTR_T
bfin_gen_ccmv (REG_T src, REG_T dst, int T)
bfin_gen_ccmv (REG_T src, REG_T dst, int T)
{
{
  int s, d;
  int s, d;
  INIT (CCmv);
  INIT (CCmv);
 
 
  ASSIGN_R (src);
  ASSIGN_R (src);
  ASSIGN_R (dst);
  ASSIGN_R (dst);
  s = (GROUP (src));
  s = (GROUP (src));
  ASSIGN (s);
  ASSIGN (s);
  d = (GROUP (dst));
  d = (GROUP (dst));
  ASSIGN (d);
  ASSIGN (d);
  ASSIGN (T);
  ASSIGN (T);
 
 
  return GEN_OPCODE16 ();
  return GEN_OPCODE16 ();
}
}
 
 
INSTR_T
INSTR_T
bfin_gen_cc2stat (int cbit, int op, int D)
bfin_gen_cc2stat (int cbit, int op, int D)
{
{
  INIT (CC2stat);
  INIT (CC2stat);
 
 
  ASSIGN (cbit);
  ASSIGN (cbit);
  ASSIGN (op);
  ASSIGN (op);
  ASSIGN (D);
  ASSIGN (D);
 
 
  return GEN_OPCODE16 ();
  return GEN_OPCODE16 ();
}
}
 
 
INSTR_T
INSTR_T
bfin_gen_regmv (REG_T src, REG_T dst)
bfin_gen_regmv (REG_T src, REG_T dst)
{
{
  int gs, gd;
  int gs, gd;
  INIT (RegMv);
  INIT (RegMv);
 
 
  ASSIGN_R (src);
  ASSIGN_R (src);
  ASSIGN_R (dst);
  ASSIGN_R (dst);
 
 
  gs = (GROUP (src));
  gs = (GROUP (src));
  ASSIGN (gs);
  ASSIGN (gs);
  gd = (GROUP (dst));
  gd = (GROUP (dst));
  ASSIGN (gd);
  ASSIGN (gd);
 
 
  return GEN_OPCODE16 ();
  return GEN_OPCODE16 ();
}
}
 
 
INSTR_T
INSTR_T
bfin_gen_cc2dreg (int op, REG_T reg)
bfin_gen_cc2dreg (int op, REG_T reg)
{
{
  INIT (CC2dreg);
  INIT (CC2dreg);
 
 
  ASSIGN (op);
  ASSIGN (op);
  ASSIGN_R (reg);
  ASSIGN_R (reg);
 
 
  return GEN_OPCODE16 ();
  return GEN_OPCODE16 ();
}
}
 
 
INSTR_T
INSTR_T
bfin_gen_progctrl (int prgfunc, int poprnd)
bfin_gen_progctrl (int prgfunc, int poprnd)
{
{
  INIT (ProgCtrl);
  INIT (ProgCtrl);
 
 
  ASSIGN (prgfunc);
  ASSIGN (prgfunc);
  ASSIGN (poprnd);
  ASSIGN (poprnd);
 
 
  return GEN_OPCODE16 ();
  return GEN_OPCODE16 ();
}
}
 
 
INSTR_T
INSTR_T
bfin_gen_cactrl (REG_T reg, int a, int op)
bfin_gen_cactrl (REG_T reg, int a, int op)
{
{
  INIT (CaCTRL);
  INIT (CaCTRL);
 
 
  ASSIGN_R (reg);
  ASSIGN_R (reg);
  ASSIGN (a);
  ASSIGN (a);
  ASSIGN (op);
  ASSIGN (op);
 
 
  return GEN_OPCODE16 ();
  return GEN_OPCODE16 ();
}
}
 
 
INSTR_T
INSTR_T
bfin_gen_pushpopmultiple (int dr, int pr, int d, int p, int W)
bfin_gen_pushpopmultiple (int dr, int pr, int d, int p, int W)
{
{
  INIT (PushPopMultiple);
  INIT (PushPopMultiple);
 
 
  ASSIGN (dr);
  ASSIGN (dr);
  ASSIGN (pr);
  ASSIGN (pr);
  ASSIGN (d);
  ASSIGN (d);
  ASSIGN (p);
  ASSIGN (p);
  ASSIGN (W);
  ASSIGN (W);
 
 
  return GEN_OPCODE16 ();
  return GEN_OPCODE16 ();
}
}
 
 
INSTR_T
INSTR_T
bfin_gen_pushpopreg (REG_T reg, int W)
bfin_gen_pushpopreg (REG_T reg, int W)
{
{
  int grp;
  int grp;
  INIT (PushPopReg);
  INIT (PushPopReg);
 
 
  ASSIGN_R (reg);
  ASSIGN_R (reg);
  grp = (GROUP (reg));
  grp = (GROUP (reg));
  ASSIGN (grp);
  ASSIGN (grp);
  ASSIGN (W);
  ASSIGN (W);
 
 
  return GEN_OPCODE16 ();
  return GEN_OPCODE16 ();
}
}
 
 
/* Pseudo Debugging Support.  */
/* Pseudo Debugging Support.  */
 
 
INSTR_T
INSTR_T
bfin_gen_pseudodbg (int fn, int reg, int grp)
bfin_gen_pseudodbg (int fn, int reg, int grp)
{
{
  INIT (PseudoDbg);
  INIT (PseudoDbg);
 
 
  ASSIGN (fn);
  ASSIGN (fn);
  ASSIGN (reg);
  ASSIGN (reg);
  ASSIGN (grp);
  ASSIGN (grp);
 
 
  return GEN_OPCODE16 ();
  return GEN_OPCODE16 ();
}
}
 
 
INSTR_T
INSTR_T
bfin_gen_pseudodbg_assert (int dbgop, REG_T regtest, int expected)
bfin_gen_pseudodbg_assert (int dbgop, REG_T regtest, int expected)
{
{
  INIT (PseudoDbg_Assert);
  INIT (PseudoDbg_Assert);
 
 
  ASSIGN (dbgop);
  ASSIGN (dbgop);
  ASSIGN_R (regtest);
  ASSIGN_R (regtest);
  ASSIGN (expected);
  ASSIGN (expected);
 
 
  return GEN_OPCODE32 ();
  return GEN_OPCODE32 ();
}
}
 
 
/* Multiple instruction generation.  */
/* Multiple instruction generation.  */
 
 
INSTR_T
INSTR_T
bfin_gen_multi_instr (INSTR_T dsp32, INSTR_T dsp16_grp1, INSTR_T dsp16_grp2)
bfin_gen_multi_instr (INSTR_T dsp32, INSTR_T dsp16_grp1, INSTR_T dsp16_grp2)
{
{
  INSTR_T walk;
  INSTR_T walk;
 
 
  /* If it's a 0, convert into MNOP. */
  /* If it's a 0, convert into MNOP. */
  if (dsp32)
  if (dsp32)
    {
    {
      walk = dsp32->next;
      walk = dsp32->next;
      SET_MULTI_INSTRUCTION_BIT (dsp32);
      SET_MULTI_INSTRUCTION_BIT (dsp32);
    }
    }
  else
  else
    {
    {
      dsp32 = gencode (0xc803);
      dsp32 = gencode (0xc803);
      walk = gencode (0x1800);
      walk = gencode (0x1800);
      dsp32->next = walk;
      dsp32->next = walk;
    }
    }
 
 
  if (!dsp16_grp1)
  if (!dsp16_grp1)
    {
    {
      dsp16_grp1 = gencode (0x0000);
      dsp16_grp1 = gencode (0x0000);
    }
    }
 
 
  if (!dsp16_grp2)
  if (!dsp16_grp2)
    {
    {
      dsp16_grp2 = gencode (0x0000);
      dsp16_grp2 = gencode (0x0000);
    }
    }
 
 
  walk->next = dsp16_grp1;
  walk->next = dsp16_grp1;
  dsp16_grp1->next = dsp16_grp2;
  dsp16_grp1->next = dsp16_grp2;
  dsp16_grp2->next = NULL_CODE;
  dsp16_grp2->next = NULL_CODE;
 
 
  return dsp32;
  return dsp32;
}
}
 
 
INSTR_T
INSTR_T
bfin_gen_loop (Expr_Node *expr, REG_T reg, int rop, REG_T preg)
bfin_gen_loop (Expr_Node *expr, REG_T reg, int rop, REG_T preg)
{
{
  const char *loopsym;
  const char *loopsym;
  char *lbeginsym, *lendsym;
  char *lbeginsym, *lendsym;
  Expr_Node_Value lbeginval, lendval;
  Expr_Node_Value lbeginval, lendval;
  Expr_Node *lbegin, *lend;
  Expr_Node *lbegin, *lend;
 
 
  loopsym = expr->value.s_value;
  loopsym = expr->value.s_value;
  lbeginsym = (char *) xmalloc (strlen (loopsym) + strlen ("__BEGIN") + 5);
  lbeginsym = (char *) xmalloc (strlen (loopsym) + strlen ("__BEGIN") + 5);
  lendsym = (char *) xmalloc (strlen (loopsym) + strlen ("__END") + 5);
  lendsym = (char *) xmalloc (strlen (loopsym) + strlen ("__END") + 5);
 
 
  lbeginsym[0] = 0;
  lbeginsym[0] = 0;
  lendsym[0] = 0;
  lendsym[0] = 0;
 
 
  strcat (lbeginsym, "L$L$");
  strcat (lbeginsym, "L$L$");
  strcat (lbeginsym, loopsym);
  strcat (lbeginsym, loopsym);
  strcat (lbeginsym, "__BEGIN");
  strcat (lbeginsym, "__BEGIN");
 
 
  strcat (lendsym, "L$L$");
  strcat (lendsym, "L$L$");
  strcat (lendsym, loopsym);
  strcat (lendsym, loopsym);
  strcat (lendsym, "__END");
  strcat (lendsym, "__END");
 
 
  lbeginval.s_value = lbeginsym;
  lbeginval.s_value = lbeginsym;
  lendval.s_value = lendsym;
  lendval.s_value = lendsym;
 
 
  lbegin = Expr_Node_Create (Expr_Node_Reloc, lbeginval, NULL, NULL);
  lbegin = Expr_Node_Create (Expr_Node_Reloc, lbeginval, NULL, NULL);
  lend   = Expr_Node_Create (Expr_Node_Reloc, lendval, NULL, NULL);
  lend   = Expr_Node_Create (Expr_Node_Reloc, lendval, NULL, NULL);
  return bfin_gen_loopsetup(lbegin, reg, rop, lend, preg);
  return bfin_gen_loopsetup(lbegin, reg, rop, lend, preg);
}
}
 
 
bfd_boolean
bfd_boolean
bfin_eol_in_insn (char *line)
bfin_eol_in_insn (char *line)
{
{
   /* Allow a new-line to appear in the middle of a multi-issue instruction.  */
   /* Allow a new-line to appear in the middle of a multi-issue instruction.  */
 
 
   char *temp = line;
   char *temp = line;
 
 
  if (*line != '\n')
  if (*line != '\n')
    return FALSE;
    return FALSE;
 
 
  /* A semi-colon followed by a newline is always the end of a line.  */
  /* A semi-colon followed by a newline is always the end of a line.  */
  if (line[-1] == ';')
  if (line[-1] == ';')
    return FALSE;
    return FALSE;
 
 
  if (line[-1] == '|')
  if (line[-1] == '|')
    return TRUE;
    return TRUE;
 
 
  /* If the || is on the next line, there might be leading whitespace.  */
  /* If the || is on the next line, there might be leading whitespace.  */
  temp++;
  temp++;
  while (*temp == ' ' || *temp == '\t') temp++;
  while (*temp == ' ' || *temp == '\t') temp++;
 
 
  if (*temp == '|')
  if (*temp == '|')
    return TRUE;
    return TRUE;
 
 
  return FALSE;
  return FALSE;
}
}
 
 
bfd_boolean
bfd_boolean
bfin_start_label (char *ptr)
bfin_start_label (char *ptr)
{
{
  ptr--;
  ptr--;
  while (!ISSPACE (*ptr) && !is_end_of_line[(unsigned char) *ptr])
  while (!ISSPACE (*ptr) && !is_end_of_line[(unsigned char) *ptr])
    ptr--;
    ptr--;
 
 
  ptr++;
  ptr++;
  if (*ptr == '(' || *ptr == '[')
  if (*ptr == '(' || *ptr == '[')
    return FALSE;
    return FALSE;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
int
int
bfin_force_relocation (struct fix *fixp)
bfin_force_relocation (struct fix *fixp)
{
{
  if (fixp->fx_r_type ==BFD_RELOC_BFIN_16_LOW
  if (fixp->fx_r_type ==BFD_RELOC_BFIN_16_LOW
      || fixp->fx_r_type == BFD_RELOC_BFIN_16_HIGH)
      || fixp->fx_r_type == BFD_RELOC_BFIN_16_HIGH)
    return TRUE;
    return TRUE;
 
 
  return generic_force_reloc (fixp);
  return generic_force_reloc (fixp);
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.