Home | History | Annotate | Line # | Download | only in config
tc-arc.c revision 1.4.8.1
      1      1.1  christos /* tc-arc.c -- Assembler for the ARC
      2  1.4.8.1  pgoyette    Copyright (C) 1994-2016 Free Software Foundation, Inc.
      3      1.3  christos 
      4      1.3  christos    Contributor: Claudiu Zissulescu <claziss (at) synopsys.com>
      5      1.1  christos 
      6      1.1  christos    This file is part of GAS, the GNU Assembler.
      7      1.1  christos 
      8      1.1  christos    GAS is free software; you can redistribute it and/or modify
      9      1.1  christos    it under the terms of the GNU General Public License as published by
     10      1.1  christos    the Free Software Foundation; either version 3, or (at your option)
     11      1.1  christos    any later version.
     12      1.1  christos 
     13      1.1  christos    GAS is distributed in the hope that it will be useful,
     14      1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     15      1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16      1.1  christos    GNU General Public License for more details.
     17      1.1  christos 
     18      1.1  christos    You should have received a copy of the GNU General Public License
     19      1.1  christos    along with GAS; see the file COPYING.  If not, write to the Free
     20      1.1  christos    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
     21      1.1  christos    02110-1301, USA.  */
     22      1.1  christos 
     23      1.1  christos #include "as.h"
     24      1.3  christos #include "subsegs.h"
     25      1.1  christos #include "struc-symbol.h"
     26      1.3  christos #include "dwarf2dbg.h"
     27  1.4.8.1  pgoyette #include "dw2gencfi.h"
     28      1.1  christos #include "safe-ctype.h"
     29      1.3  christos 
     30      1.1  christos #include "opcode/arc.h"
     31      1.1  christos #include "elf/arc.h"
     32  1.4.8.1  pgoyette #include "../opcodes/arc-ext.h"
     33      1.1  christos 
     34      1.3  christos /* Defines section.  */
     35      1.1  christos 
     36      1.3  christos #define MAX_INSN_FIXUPS      2
     37      1.3  christos #define MAX_CONSTR_STR       20
     38  1.4.8.1  pgoyette #define FRAG_MAX_GROWTH      8
     39      1.3  christos 
     40      1.3  christos #ifdef DEBUG
     41      1.3  christos # define pr_debug(fmt, args...) fprintf (stderr, fmt, ##args)
     42      1.3  christos #else
     43      1.3  christos # define pr_debug(fmt, args...)
     44      1.3  christos #endif
     45      1.3  christos 
     46      1.3  christos #define MAJOR_OPCODE(x)  (((x) & 0xF8000000) >> 27)
     47      1.3  christos #define SUB_OPCODE(x)	 (((x) & 0x003F0000) >> 16)
     48  1.4.8.1  pgoyette #define LP_INSN(x)	 ((MAJOR_OPCODE (x) == 0x4) && \
     49      1.3  christos 			  (SUB_OPCODE (x) == 0x28))
     50      1.3  christos 
     51      1.3  christos /* Equal to MAX_PRECISION in atof-ieee.c.  */
     52      1.3  christos #define MAX_LITTLENUMS 6
     53      1.3  christos 
     54  1.4.8.1  pgoyette #ifndef TARGET_WITH_CPU
     55  1.4.8.1  pgoyette #define TARGET_WITH_CPU "arc700"
     56  1.4.8.1  pgoyette #endif /* TARGET_WITH_CPU */
     57  1.4.8.1  pgoyette 
     58  1.4.8.1  pgoyette /* Enum used to enumerate the relaxable ins operands.  */
     59  1.4.8.1  pgoyette enum rlx_operand_type
     60  1.4.8.1  pgoyette {
     61  1.4.8.1  pgoyette   EMPTY = 0,
     62  1.4.8.1  pgoyette   REGISTER,
     63  1.4.8.1  pgoyette   REGISTER_S,     /* Register for short instruction(s).  */
     64  1.4.8.1  pgoyette   REGISTER_NO_GP, /* Is a register but not gp register specifically.  */
     65  1.4.8.1  pgoyette   REGISTER_DUP,   /* Duplication of previous operand of type register.  */
     66  1.4.8.1  pgoyette   IMMEDIATE,
     67  1.4.8.1  pgoyette   BRACKET
     68  1.4.8.1  pgoyette };
     69  1.4.8.1  pgoyette 
     70  1.4.8.1  pgoyette enum arc_rlx_types
     71  1.4.8.1  pgoyette {
     72  1.4.8.1  pgoyette   ARC_RLX_NONE = 0,
     73  1.4.8.1  pgoyette   ARC_RLX_BL_S,
     74  1.4.8.1  pgoyette   ARC_RLX_BL,
     75  1.4.8.1  pgoyette   ARC_RLX_B_S,
     76  1.4.8.1  pgoyette   ARC_RLX_B,
     77  1.4.8.1  pgoyette   ARC_RLX_ADD_U3,
     78  1.4.8.1  pgoyette   ARC_RLX_ADD_U6,
     79  1.4.8.1  pgoyette   ARC_RLX_ADD_LIMM,
     80  1.4.8.1  pgoyette   ARC_RLX_LD_U7,
     81  1.4.8.1  pgoyette   ARC_RLX_LD_S9,
     82  1.4.8.1  pgoyette   ARC_RLX_LD_LIMM,
     83  1.4.8.1  pgoyette   ARC_RLX_MOV_U8,
     84  1.4.8.1  pgoyette   ARC_RLX_MOV_S12,
     85  1.4.8.1  pgoyette   ARC_RLX_MOV_LIMM,
     86  1.4.8.1  pgoyette   ARC_RLX_SUB_U3,
     87  1.4.8.1  pgoyette   ARC_RLX_SUB_U6,
     88  1.4.8.1  pgoyette   ARC_RLX_SUB_LIMM,
     89  1.4.8.1  pgoyette   ARC_RLX_MPY_U6,
     90  1.4.8.1  pgoyette   ARC_RLX_MPY_LIMM,
     91  1.4.8.1  pgoyette   ARC_RLX_MOV_RU6,
     92  1.4.8.1  pgoyette   ARC_RLX_MOV_RLIMM,
     93  1.4.8.1  pgoyette   ARC_RLX_ADD_RRU6,
     94  1.4.8.1  pgoyette   ARC_RLX_ADD_RRLIMM,
     95  1.4.8.1  pgoyette };
     96  1.4.8.1  pgoyette 
     97      1.3  christos /* Macros section.  */
     98      1.3  christos 
     99      1.3  christos #define regno(x)		((x) & 0x3F)
    100      1.3  christos #define is_ir_num(x)		(((x) & ~0x3F) == 0)
    101  1.4.8.1  pgoyette #define is_code_density_p(sc)   (((sc) == CD1 || (sc) == CD2))
    102  1.4.8.1  pgoyette #define is_spfp_p(op)           (((sc) == SPX))
    103  1.4.8.1  pgoyette #define is_dpfp_p(op)           (((sc) == DPX))
    104  1.4.8.1  pgoyette #define is_fpuda_p(op)          (((sc) == DPA))
    105  1.4.8.1  pgoyette #define is_br_jmp_insn_p(op)    (((op)->insn_class == BRANCH || (op)->insn_class == JUMP))
    106  1.4.8.1  pgoyette #define is_kernel_insn_p(op)    (((op)->insn_class == KERNEL))
    107  1.4.8.1  pgoyette #define is_nps400_p(op)         (((sc) == NPS400))
    108      1.1  christos 
    109      1.3  christos /* Generic assembler global variables which must be defined by all
    110      1.3  christos    targets.  */
    111      1.1  christos 
    112      1.3  christos /* Characters which always start a comment.  */
    113      1.1  christos const char comment_chars[] = "#;";
    114      1.1  christos 
    115      1.3  christos /* Characters which start a comment at the beginning of a line.  */
    116      1.1  christos const char line_comment_chars[] = "#";
    117      1.1  christos 
    118      1.3  christos /* Characters which may be used to separate multiple commands on a
    119      1.3  christos    single line.  */
    120      1.3  christos const char line_separator_chars[] = "`";
    121      1.1  christos 
    122      1.3  christos /* Characters which are used to indicate an exponent in a floating
    123      1.3  christos    point number.  */
    124      1.1  christos const char EXP_CHARS[] = "eE";
    125      1.1  christos 
    126      1.1  christos /* Chars that mean this number is a floating point constant
    127      1.1  christos    As in 0f12.456 or 0d1.2345e12.  */
    128      1.1  christos const char FLT_CHARS[] = "rRsSfFdD";
    129      1.1  christos 
    130      1.1  christos /* Byte order.  */
    131      1.1  christos extern int target_big_endian;
    132      1.1  christos const char *arc_target_format = DEFAULT_TARGET_FORMAT;
    133      1.1  christos static int byte_order = DEFAULT_BYTE_ORDER;
    134      1.1  christos 
    135  1.4.8.1  pgoyette /* Arc extension section.  */
    136  1.4.8.1  pgoyette static segT arcext_section;
    137  1.4.8.1  pgoyette 
    138  1.4.8.1  pgoyette /* By default relaxation is disabled.  */
    139  1.4.8.1  pgoyette static int relaxation_state = 0;
    140  1.4.8.1  pgoyette 
    141      1.3  christos extern int arc_get_mach (char *);
    142      1.3  christos 
    143  1.4.8.1  pgoyette /* Forward declarations.  */
    144      1.3  christos static void arc_lcomm (int);
    145      1.3  christos static void arc_option (int);
    146      1.3  christos static void arc_extra_reloc (int);
    147  1.4.8.1  pgoyette static void arc_extinsn (int);
    148  1.4.8.1  pgoyette static void arc_extcorereg (int);
    149      1.3  christos 
    150      1.3  christos const pseudo_typeS md_pseudo_table[] =
    151      1.3  christos {
    152      1.3  christos   /* Make sure that .word is 32 bits.  */
    153      1.3  christos   { "word", cons, 4 },
    154      1.1  christos 
    155      1.3  christos   { "align",   s_align_bytes, 0 }, /* Defaulting is invalid (0).  */
    156      1.3  christos   { "lcomm",   arc_lcomm, 0 },
    157      1.3  christos   { "lcommon", arc_lcomm, 0 },
    158      1.3  christos   { "cpu",     arc_option, 0 },
    159      1.1  christos 
    160  1.4.8.1  pgoyette   { "extinstruction",  arc_extinsn, 0 },
    161  1.4.8.1  pgoyette   { "extcoreregister", arc_extcorereg, EXT_CORE_REGISTER },
    162  1.4.8.1  pgoyette   { "extauxregister",  arc_extcorereg, EXT_AUX_REGISTER },
    163  1.4.8.1  pgoyette   { "extcondcode",     arc_extcorereg, EXT_COND_CODE },
    164  1.4.8.1  pgoyette 
    165      1.3  christos   { "tls_gd_ld",   arc_extra_reloc, BFD_RELOC_ARC_TLS_GD_LD },
    166      1.3  christos   { "tls_gd_call", arc_extra_reloc, BFD_RELOC_ARC_TLS_GD_CALL },
    167      1.1  christos 
    168      1.3  christos   { NULL, NULL, 0 }
    169      1.3  christos };
    170      1.1  christos 
    171      1.1  christos const char *md_shortopts = "";
    172      1.1  christos 
    173      1.1  christos enum options
    174      1.1  christos {
    175      1.1  christos   OPTION_EB = OPTION_MD_BASE,
    176      1.1  christos   OPTION_EL,
    177      1.3  christos 
    178      1.3  christos   OPTION_ARC600,
    179      1.3  christos   OPTION_ARC601,
    180      1.3  christos   OPTION_ARC700,
    181      1.3  christos   OPTION_ARCEM,
    182      1.3  christos   OPTION_ARCHS,
    183      1.3  christos 
    184      1.3  christos   OPTION_MCPU,
    185      1.3  christos   OPTION_CD,
    186  1.4.8.1  pgoyette   OPTION_RELAX,
    187  1.4.8.1  pgoyette   OPTION_NPS400,
    188  1.4.8.1  pgoyette 
    189  1.4.8.1  pgoyette   OPTION_SPFP,
    190  1.4.8.1  pgoyette   OPTION_DPFP,
    191  1.4.8.1  pgoyette   OPTION_FPUDA,
    192      1.3  christos 
    193      1.3  christos   /* The following options are deprecated and provided here only for
    194      1.3  christos      compatibility reasons.  */
    195      1.3  christos   OPTION_USER_MODE,
    196      1.3  christos   OPTION_LD_EXT_MASK,
    197      1.3  christos   OPTION_SWAP,
    198      1.3  christos   OPTION_NORM,
    199      1.3  christos   OPTION_BARREL_SHIFT,
    200      1.3  christos   OPTION_MIN_MAX,
    201      1.3  christos   OPTION_NO_MPY,
    202      1.3  christos   OPTION_EA,
    203      1.3  christos   OPTION_MUL64,
    204      1.3  christos   OPTION_SIMD,
    205      1.3  christos   OPTION_XMAC_D16,
    206      1.3  christos   OPTION_XMAC_24,
    207      1.3  christos   OPTION_DSP_PACKA,
    208      1.3  christos   OPTION_CRC,
    209      1.3  christos   OPTION_DVBF,
    210      1.3  christos   OPTION_TELEPHONY,
    211      1.3  christos   OPTION_XYMEMORY,
    212      1.3  christos   OPTION_LOCK,
    213      1.3  christos   OPTION_SWAPE,
    214  1.4.8.1  pgoyette   OPTION_RTSC
    215      1.1  christos };
    216      1.1  christos 
    217      1.1  christos struct option md_longopts[] =
    218      1.1  christos {
    219      1.3  christos   { "EB",		no_argument,	   NULL, OPTION_EB },
    220      1.3  christos   { "EL",		no_argument,	   NULL, OPTION_EL },
    221      1.3  christos   { "mcpu",		required_argument, NULL, OPTION_MCPU },
    222      1.3  christos   { "mA6",		no_argument,	   NULL, OPTION_ARC600 },
    223  1.4.8.1  pgoyette   { "mARC600",		no_argument,	   NULL, OPTION_ARC600 },
    224  1.4.8.1  pgoyette   { "mARC601",		no_argument,	   NULL, OPTION_ARC601 },
    225  1.4.8.1  pgoyette   { "mARC700",		no_argument,	   NULL, OPTION_ARC700 },
    226      1.3  christos   { "mA7",		no_argument,	   NULL, OPTION_ARC700 },
    227      1.3  christos   { "mEM",		no_argument,	   NULL, OPTION_ARCEM },
    228      1.3  christos   { "mHS",		no_argument,	   NULL, OPTION_ARCHS },
    229      1.3  christos   { "mcode-density",	no_argument,	   NULL, OPTION_CD },
    230  1.4.8.1  pgoyette   { "mrelax",           no_argument,       NULL, OPTION_RELAX },
    231  1.4.8.1  pgoyette   { "mnps400",          no_argument,       NULL, OPTION_NPS400 },
    232  1.4.8.1  pgoyette 
    233  1.4.8.1  pgoyette   /* Floating point options */
    234  1.4.8.1  pgoyette   { "mspfp", no_argument, NULL, OPTION_SPFP},
    235  1.4.8.1  pgoyette   { "mspfp-compact", no_argument, NULL, OPTION_SPFP},
    236  1.4.8.1  pgoyette   { "mspfp_compact", no_argument, NULL, OPTION_SPFP},
    237  1.4.8.1  pgoyette   { "mspfp-fast", no_argument, NULL, OPTION_SPFP},
    238  1.4.8.1  pgoyette   { "mspfp_fast", no_argument, NULL, OPTION_SPFP},
    239  1.4.8.1  pgoyette   { "mdpfp", no_argument, NULL, OPTION_DPFP},
    240  1.4.8.1  pgoyette   { "mdpfp-compact", no_argument, NULL, OPTION_DPFP},
    241  1.4.8.1  pgoyette   { "mdpfp_compact", no_argument, NULL, OPTION_DPFP},
    242  1.4.8.1  pgoyette   { "mdpfp-fast", no_argument, NULL, OPTION_DPFP},
    243  1.4.8.1  pgoyette   { "mdpfp_fast", no_argument, NULL, OPTION_DPFP},
    244  1.4.8.1  pgoyette   { "mfpuda", no_argument, NULL, OPTION_FPUDA},
    245      1.3  christos 
    246      1.3  christos   /* The following options are deprecated and provided here only for
    247      1.3  christos      compatibility reasons.  */
    248      1.3  christos   { "mav2em", no_argument, NULL, OPTION_ARCEM },
    249      1.3  christos   { "mav2hs", no_argument, NULL, OPTION_ARCHS },
    250      1.3  christos   { "muser-mode-only", no_argument, NULL, OPTION_USER_MODE },
    251      1.3  christos   { "mld-extension-reg-mask", required_argument, NULL, OPTION_LD_EXT_MASK },
    252      1.3  christos   { "mswap", no_argument, NULL, OPTION_SWAP },
    253      1.3  christos   { "mnorm", no_argument, NULL, OPTION_NORM },
    254      1.3  christos   { "mbarrel-shifter", no_argument, NULL, OPTION_BARREL_SHIFT },
    255      1.3  christos   { "mbarrel_shifter", no_argument, NULL, OPTION_BARREL_SHIFT },
    256      1.3  christos   { "mmin-max", no_argument, NULL, OPTION_MIN_MAX },
    257      1.3  christos   { "mmin_max", no_argument, NULL, OPTION_MIN_MAX },
    258      1.3  christos   { "mno-mpy", no_argument, NULL, OPTION_NO_MPY },
    259      1.3  christos   { "mea", no_argument, NULL, OPTION_EA },
    260      1.3  christos   { "mEA", no_argument, NULL, OPTION_EA },
    261      1.3  christos   { "mmul64", no_argument, NULL, OPTION_MUL64 },
    262      1.3  christos   { "msimd", no_argument, NULL, OPTION_SIMD},
    263      1.3  christos   { "mmac-d16", no_argument, NULL, OPTION_XMAC_D16},
    264      1.3  christos   { "mmac_d16", no_argument, NULL, OPTION_XMAC_D16},
    265      1.3  christos   { "mmac-24", no_argument, NULL, OPTION_XMAC_24},
    266      1.3  christos   { "mmac_24", no_argument, NULL, OPTION_XMAC_24},
    267      1.3  christos   { "mdsp-packa", no_argument, NULL, OPTION_DSP_PACKA},
    268      1.3  christos   { "mdsp_packa", no_argument, NULL, OPTION_DSP_PACKA},
    269      1.3  christos   { "mcrc", no_argument, NULL, OPTION_CRC},
    270      1.3  christos   { "mdvbf", no_argument, NULL, OPTION_DVBF},
    271      1.3  christos   { "mtelephony", no_argument, NULL, OPTION_TELEPHONY},
    272      1.3  christos   { "mxy", no_argument, NULL, OPTION_XYMEMORY},
    273      1.3  christos   { "mlock", no_argument, NULL, OPTION_LOCK},
    274      1.3  christos   { "mswape", no_argument, NULL, OPTION_SWAPE},
    275      1.3  christos   { "mrtsc", no_argument, NULL, OPTION_RTSC},
    276      1.3  christos 
    277      1.3  christos   { NULL,		no_argument, NULL, 0 }
    278      1.1  christos };
    279      1.3  christos 
    280      1.1  christos size_t md_longopts_size = sizeof (md_longopts);
    281      1.1  christos 
    282      1.3  christos /* Local data and data types.  */
    283      1.3  christos 
    284      1.3  christos /* Used since new relocation types are introduced in this
    285      1.3  christos    file (DUMMY_RELOC_LITUSE_*).  */
    286      1.3  christos typedef int extended_bfd_reloc_code_real_type;
    287      1.3  christos 
    288      1.3  christos struct arc_fixup
    289      1.3  christos {
    290      1.3  christos   expressionS exp;
    291      1.3  christos 
    292      1.3  christos   extended_bfd_reloc_code_real_type reloc;
    293      1.1  christos 
    294      1.3  christos   /* index into arc_operands.  */
    295      1.3  christos   unsigned int opindex;
    296      1.1  christos 
    297      1.3  christos   /* PC-relative, used by internals fixups.  */
    298      1.3  christos   unsigned char pcrel;
    299      1.1  christos 
    300      1.3  christos   /* TRUE if this fixup is for LIMM operand.  */
    301      1.3  christos   bfd_boolean islong;
    302      1.3  christos };
    303      1.3  christos 
    304      1.3  christos struct arc_insn
    305      1.1  christos {
    306      1.3  christos   unsigned int insn;
    307      1.3  christos   int nfixups;
    308      1.3  christos   struct arc_fixup fixups[MAX_INSN_FIXUPS];
    309      1.3  christos   long limm;
    310      1.3  christos   bfd_boolean short_insn; /* Boolean value: TRUE if current insn is
    311      1.3  christos 			     short.  */
    312      1.3  christos   bfd_boolean has_limm;   /* Boolean value: TRUE if limm field is
    313      1.3  christos 			     valid.  */
    314  1.4.8.1  pgoyette   bfd_boolean relax;	  /* Boolean value: TRUE if needs
    315  1.4.8.1  pgoyette 			     relaxation.  */
    316      1.3  christos };
    317      1.1  christos 
    318      1.3  christos /* Structure to hold any last two instructions.  */
    319      1.3  christos static struct arc_last_insn
    320      1.1  christos {
    321      1.3  christos   /* Saved instruction opcode.  */
    322      1.3  christos   const struct arc_opcode *opcode;
    323      1.3  christos 
    324      1.3  christos   /* Boolean value: TRUE if current insn is short.  */
    325      1.3  christos   bfd_boolean has_limm;
    326      1.3  christos 
    327      1.3  christos   /* Boolean value: TRUE if current insn has delay slot.  */
    328      1.3  christos   bfd_boolean has_delay_slot;
    329      1.3  christos } arc_last_insns[2];
    330      1.3  christos 
    331  1.4.8.1  pgoyette /* Extension instruction suffix classes.  */
    332  1.4.8.1  pgoyette typedef struct
    333  1.4.8.1  pgoyette {
    334  1.4.8.1  pgoyette   const char *name;
    335  1.4.8.1  pgoyette   int  len;
    336  1.4.8.1  pgoyette   int  attr_class;
    337  1.4.8.1  pgoyette } attributes_t;
    338  1.4.8.1  pgoyette 
    339  1.4.8.1  pgoyette static const attributes_t suffixclass[] =
    340  1.4.8.1  pgoyette {
    341  1.4.8.1  pgoyette   { "SUFFIX_FLAG", 11, ARC_SUFFIX_FLAG },
    342  1.4.8.1  pgoyette   { "SUFFIX_COND", 11, ARC_SUFFIX_COND },
    343  1.4.8.1  pgoyette   { "SUFFIX_NONE", 11, ARC_SUFFIX_NONE }
    344  1.4.8.1  pgoyette };
    345  1.4.8.1  pgoyette 
    346  1.4.8.1  pgoyette /* Extension instruction syntax classes.  */
    347  1.4.8.1  pgoyette static const attributes_t syntaxclass[] =
    348  1.4.8.1  pgoyette {
    349  1.4.8.1  pgoyette   { "SYNTAX_3OP", 10, ARC_SYNTAX_3OP },
    350  1.4.8.1  pgoyette   { "SYNTAX_2OP", 10, ARC_SYNTAX_2OP },
    351  1.4.8.1  pgoyette   { "SYNTAX_1OP", 10, ARC_SYNTAX_1OP },
    352  1.4.8.1  pgoyette   { "SYNTAX_NOP", 10, ARC_SYNTAX_NOP }
    353  1.4.8.1  pgoyette };
    354  1.4.8.1  pgoyette 
    355  1.4.8.1  pgoyette /* Extension instruction syntax classes modifiers.  */
    356  1.4.8.1  pgoyette static const attributes_t syntaxclassmod[] =
    357  1.4.8.1  pgoyette {
    358  1.4.8.1  pgoyette   { "OP1_IMM_IMPLIED" , 15, ARC_OP1_IMM_IMPLIED },
    359  1.4.8.1  pgoyette   { "OP1_MUST_BE_IMM" , 15, ARC_OP1_MUST_BE_IMM }
    360  1.4.8.1  pgoyette };
    361  1.4.8.1  pgoyette 
    362  1.4.8.1  pgoyette /* Extension register type.  */
    363  1.4.8.1  pgoyette typedef struct
    364  1.4.8.1  pgoyette {
    365  1.4.8.1  pgoyette   char *name;
    366  1.4.8.1  pgoyette   int  number;
    367  1.4.8.1  pgoyette   int  imode;
    368  1.4.8.1  pgoyette } extRegister_t;
    369  1.4.8.1  pgoyette 
    370  1.4.8.1  pgoyette /* A structure to hold the additional conditional codes.  */
    371  1.4.8.1  pgoyette static struct
    372  1.4.8.1  pgoyette {
    373  1.4.8.1  pgoyette   struct arc_flag_operand *arc_ext_condcode;
    374  1.4.8.1  pgoyette   int size;
    375  1.4.8.1  pgoyette } ext_condcode = { NULL, 0 };
    376  1.4.8.1  pgoyette 
    377  1.4.8.1  pgoyette /* Structure to hold an entry in ARC_OPCODE_HASH.  */
    378  1.4.8.1  pgoyette struct arc_opcode_hash_entry
    379  1.4.8.1  pgoyette {
    380  1.4.8.1  pgoyette   /* The number of pointers in the OPCODE list.  */
    381  1.4.8.1  pgoyette   size_t count;
    382  1.4.8.1  pgoyette 
    383  1.4.8.1  pgoyette   /* Points to a list of opcode pointers.  */
    384  1.4.8.1  pgoyette   const struct arc_opcode **opcode;
    385  1.4.8.1  pgoyette };
    386  1.4.8.1  pgoyette 
    387  1.4.8.1  pgoyette /* Structure used for iterating through an arc_opcode_hash_entry.  */
    388  1.4.8.1  pgoyette struct arc_opcode_hash_entry_iterator
    389  1.4.8.1  pgoyette {
    390  1.4.8.1  pgoyette   /* Index into the OPCODE element of the arc_opcode_hash_entry.  */
    391  1.4.8.1  pgoyette   size_t index;
    392  1.4.8.1  pgoyette 
    393  1.4.8.1  pgoyette   /* The specific ARC_OPCODE from the ARC_OPCODES table that was last
    394  1.4.8.1  pgoyette      returned by this iterator.  */
    395  1.4.8.1  pgoyette   const struct arc_opcode *opcode;
    396  1.4.8.1  pgoyette };
    397  1.4.8.1  pgoyette 
    398  1.4.8.1  pgoyette /* Forward declaration.  */
    399  1.4.8.1  pgoyette static void assemble_insn
    400  1.4.8.1  pgoyette   (const struct arc_opcode *, const expressionS *, int,
    401  1.4.8.1  pgoyette    const struct arc_flags *, int, struct arc_insn *);
    402  1.4.8.1  pgoyette 
    403      1.3  christos /* The cpu for which we are generating code.  */
    404  1.4.8.1  pgoyette static unsigned arc_target;
    405  1.4.8.1  pgoyette static const char *arc_target_name;
    406  1.4.8.1  pgoyette static unsigned arc_features;
    407      1.3  christos 
    408      1.3  christos /* The default architecture.  */
    409  1.4.8.1  pgoyette static int arc_mach_type;
    410      1.1  christos 
    411  1.4.8.1  pgoyette /* TRUE if the cpu type has been explicitly specified.  */
    412  1.4.8.1  pgoyette static bfd_boolean mach_type_specified_p = FALSE;
    413      1.1  christos 
    414      1.3  christos /* The hash table of instruction opcodes.  */
    415      1.3  christos static struct hash_control *arc_opcode_hash;
    416      1.1  christos 
    417      1.3  christos /* The hash table of register symbols.  */
    418      1.3  christos static struct hash_control *arc_reg_hash;
    419      1.1  christos 
    420  1.4.8.1  pgoyette /* The hash table of aux register symbols.  */
    421  1.4.8.1  pgoyette static struct hash_control *arc_aux_hash;
    422  1.4.8.1  pgoyette 
    423      1.3  christos /* A table of CPU names and opcode sets.  */
    424      1.3  christos static const struct cpu_type
    425      1.3  christos {
    426      1.3  christos   const char *name;
    427      1.3  christos   unsigned flags;
    428      1.3  christos   int mach;
    429      1.3  christos   unsigned eflags;
    430      1.3  christos   unsigned features;
    431      1.1  christos }
    432      1.3  christos   cpu_types[] =
    433      1.3  christos {
    434      1.3  christos   { "arc600", ARC_OPCODE_ARC600,  bfd_mach_arc_arc600,
    435      1.3  christos     E_ARC_MACH_ARC600,  0x00},
    436      1.3  christos   { "arc700", ARC_OPCODE_ARC700,  bfd_mach_arc_arc700,
    437      1.3  christos     E_ARC_MACH_ARC700,  0x00},
    438  1.4.8.1  pgoyette   { "nps400", ARC_OPCODE_ARC700 , bfd_mach_arc_arc700,
    439  1.4.8.1  pgoyette     E_ARC_MACH_ARC700,  ARC_NPS400},
    440      1.3  christos   { "arcem",  ARC_OPCODE_ARCv2EM, bfd_mach_arc_arcv2,
    441      1.3  christos     EF_ARC_CPU_ARCV2EM, 0x00},
    442      1.3  christos   { "archs",  ARC_OPCODE_ARCv2HS, bfd_mach_arc_arcv2,
    443      1.3  christos     EF_ARC_CPU_ARCV2HS, ARC_CD},
    444      1.3  christos   { 0, 0, 0, 0, 0 }
    445      1.3  christos };
    446      1.1  christos 
    447      1.3  christos /* Used by the arc_reloc_op table.  Order is important.  */
    448      1.3  christos #define O_gotoff  O_md1     /* @gotoff relocation.  */
    449      1.3  christos #define O_gotpc   O_md2     /* @gotpc relocation.  */
    450      1.3  christos #define O_plt     O_md3     /* @plt relocation.  */
    451      1.3  christos #define O_sda     O_md4     /* @sda relocation.  */
    452      1.3  christos #define O_pcl     O_md5     /* @pcl relocation.  */
    453      1.3  christos #define O_tlsgd   O_md6     /* @tlsgd relocation.  */
    454      1.3  christos #define O_tlsie   O_md7     /* @tlsie relocation.  */
    455      1.3  christos #define O_tpoff9  O_md8     /* @tpoff9 relocation.  */
    456      1.3  christos #define O_tpoff   O_md9     /* @tpoff relocation.  */
    457      1.3  christos #define O_dtpoff9 O_md10    /* @dtpoff9 relocation.  */
    458      1.3  christos #define O_dtpoff  O_md11    /* @dtpoff relocation.  */
    459      1.3  christos #define O_last    O_dtpoff
    460      1.3  christos 
    461      1.3  christos /* Used to define a bracket as operand in tokens.  */
    462      1.3  christos #define O_bracket O_md32
    463      1.3  christos 
    464      1.3  christos /* Dummy relocation, to be sorted out.  */
    465      1.3  christos #define DUMMY_RELOC_ARC_ENTRY     (BFD_RELOC_UNUSED + 1)
    466      1.3  christos 
    467      1.3  christos #define USER_RELOC_P(R) ((R) >= O_gotoff && (R) <= O_last)
    468      1.3  christos 
    469      1.3  christos /* A table to map the spelling of a relocation operand into an appropriate
    470      1.3  christos    bfd_reloc_code_real_type type.  The table is assumed to be ordered such
    471      1.3  christos    that op-O_literal indexes into it.  */
    472      1.3  christos #define ARC_RELOC_TABLE(op)				\
    473      1.3  christos   (&arc_reloc_op[ ((!USER_RELOC_P (op))			\
    474      1.3  christos 		   ? (abort (), 0)			\
    475      1.3  christos 		   : (int) (op) - (int) O_gotoff) ])
    476      1.3  christos 
    477      1.3  christos #define DEF(NAME, RELOC, REQ)				\
    478      1.3  christos   { #NAME, sizeof (#NAME)-1, O_##NAME, RELOC, REQ}
    479      1.3  christos 
    480      1.3  christos static const struct arc_reloc_op_tag
    481      1.3  christos {
    482      1.3  christos   /* String to lookup.  */
    483      1.3  christos   const char *name;
    484      1.3  christos   /* Size of the string.  */
    485      1.3  christos   size_t length;
    486      1.3  christos   /* Which operator to use.  */
    487      1.3  christos   operatorT op;
    488      1.3  christos   extended_bfd_reloc_code_real_type reloc;
    489      1.3  christos   /* Allows complex relocation expression like identifier@reloc +
    490      1.3  christos      const.  */
    491      1.3  christos   unsigned int complex_expr : 1;
    492      1.3  christos }
    493      1.3  christos   arc_reloc_op[] =
    494      1.3  christos {
    495      1.3  christos   DEF (gotoff,  BFD_RELOC_ARC_GOTOFF,		1),
    496      1.3  christos   DEF (gotpc,   BFD_RELOC_ARC_GOTPC32,		0),
    497      1.3  christos   DEF (plt,	BFD_RELOC_ARC_PLT32,		0),
    498      1.3  christos   DEF (sda,	DUMMY_RELOC_ARC_ENTRY,		1),
    499      1.3  christos   DEF (pcl,	BFD_RELOC_ARC_PC32,		1),
    500      1.3  christos   DEF (tlsgd,   BFD_RELOC_ARC_TLS_GD_GOT,	0),
    501      1.3  christos   DEF (tlsie,   BFD_RELOC_ARC_TLS_IE_GOT,	0),
    502      1.3  christos   DEF (tpoff9,  BFD_RELOC_ARC_TLS_LE_S9,	0),
    503  1.4.8.1  pgoyette   DEF (tpoff,   BFD_RELOC_ARC_TLS_LE_32,	1),
    504      1.3  christos   DEF (dtpoff9, BFD_RELOC_ARC_TLS_DTPOFF_S9,	0),
    505      1.3  christos   DEF (dtpoff,  BFD_RELOC_ARC_TLS_DTPOFF,	0),
    506      1.3  christos };
    507      1.1  christos 
    508      1.3  christos static const int arc_num_reloc_op
    509      1.3  christos = sizeof (arc_reloc_op) / sizeof (*arc_reloc_op);
    510      1.1  christos 
    511  1.4.8.1  pgoyette /* Structure for relaxable instruction that have to be swapped with a
    512  1.4.8.1  pgoyette    smaller alternative instruction.  */
    513  1.4.8.1  pgoyette struct arc_relaxable_ins
    514  1.4.8.1  pgoyette {
    515  1.4.8.1  pgoyette   /* Mnemonic that should be checked.  */
    516  1.4.8.1  pgoyette   const char *mnemonic_r;
    517  1.4.8.1  pgoyette 
    518  1.4.8.1  pgoyette   /* Operands that should be checked.
    519  1.4.8.1  pgoyette      Indexes of operands from operand array.  */
    520  1.4.8.1  pgoyette   enum rlx_operand_type operands[6];
    521  1.4.8.1  pgoyette 
    522  1.4.8.1  pgoyette   /* Flags that should be checked.  */
    523  1.4.8.1  pgoyette   unsigned flag_classes[5];
    524  1.4.8.1  pgoyette 
    525  1.4.8.1  pgoyette   /* Mnemonic (smaller) alternative to be used later for relaxation.  */
    526  1.4.8.1  pgoyette   const char *mnemonic_alt;
    527  1.4.8.1  pgoyette 
    528  1.4.8.1  pgoyette   /* Index of operand that generic relaxation has to check.  */
    529  1.4.8.1  pgoyette   unsigned opcheckidx;
    530  1.4.8.1  pgoyette 
    531  1.4.8.1  pgoyette   /* Base subtype index used.  */
    532  1.4.8.1  pgoyette   enum arc_rlx_types subtype;
    533  1.4.8.1  pgoyette };
    534  1.4.8.1  pgoyette 
    535  1.4.8.1  pgoyette #define RELAX_TABLE_ENTRY(BITS, ISSIGNED, SIZE, NEXT)			\
    536  1.4.8.1  pgoyette   { (ISSIGNED) ? ((1 << ((BITS) - 1)) - 1) : ((1 << (BITS)) - 1),	\
    537  1.4.8.1  pgoyette       (ISSIGNED) ? -(1 << ((BITS) - 1)) : 0,				\
    538  1.4.8.1  pgoyette       (SIZE),								\
    539  1.4.8.1  pgoyette       (NEXT) }								\
    540  1.4.8.1  pgoyette 
    541  1.4.8.1  pgoyette #define RELAX_TABLE_ENTRY_MAX(ISSIGNED, SIZE, NEXT)	\
    542  1.4.8.1  pgoyette   { (ISSIGNED) ? 0x7FFFFFFF : 0xFFFFFFFF,		\
    543  1.4.8.1  pgoyette       (ISSIGNED) ? -(0x7FFFFFFF) : 0,                   \
    544  1.4.8.1  pgoyette       (SIZE),                                           \
    545  1.4.8.1  pgoyette       (NEXT) }                                          \
    546  1.4.8.1  pgoyette 
    547  1.4.8.1  pgoyette 
    548  1.4.8.1  pgoyette /* ARC relaxation table.  */
    549  1.4.8.1  pgoyette const relax_typeS md_relax_table[] =
    550  1.4.8.1  pgoyette {
    551  1.4.8.1  pgoyette   /* Fake entry.  */
    552  1.4.8.1  pgoyette   {0, 0, 0, 0},
    553  1.4.8.1  pgoyette 
    554  1.4.8.1  pgoyette   /* BL_S s13 ->
    555  1.4.8.1  pgoyette      BL s25.  */
    556  1.4.8.1  pgoyette   RELAX_TABLE_ENTRY(13, 1, 2, ARC_RLX_BL),
    557  1.4.8.1  pgoyette   RELAX_TABLE_ENTRY(25, 1, 4, ARC_RLX_NONE),
    558  1.4.8.1  pgoyette 
    559  1.4.8.1  pgoyette   /* B_S s10 ->
    560  1.4.8.1  pgoyette      B s25.  */
    561  1.4.8.1  pgoyette   RELAX_TABLE_ENTRY(10, 1, 2, ARC_RLX_B),
    562  1.4.8.1  pgoyette   RELAX_TABLE_ENTRY(25, 1, 4, ARC_RLX_NONE),
    563  1.4.8.1  pgoyette 
    564  1.4.8.1  pgoyette   /* ADD_S c,b, u3 ->
    565  1.4.8.1  pgoyette      ADD<.f> a,b,u6 ->
    566  1.4.8.1  pgoyette      ADD<.f> a,b,limm.  */
    567  1.4.8.1  pgoyette   RELAX_TABLE_ENTRY(3, 0, 2, ARC_RLX_ADD_U6),
    568  1.4.8.1  pgoyette   RELAX_TABLE_ENTRY(6, 0, 4, ARC_RLX_ADD_LIMM),
    569  1.4.8.1  pgoyette   RELAX_TABLE_ENTRY_MAX(0, 8, ARC_RLX_NONE),
    570  1.4.8.1  pgoyette 
    571  1.4.8.1  pgoyette   /* LD_S a, [b, u7] ->
    572  1.4.8.1  pgoyette      LD<zz><.x><.aa><.di> a, [b, s9] ->
    573  1.4.8.1  pgoyette      LD<zz><.x><.aa><.di> a, [b, limm] */
    574  1.4.8.1  pgoyette   RELAX_TABLE_ENTRY(7, 0, 2, ARC_RLX_LD_S9),
    575  1.4.8.1  pgoyette   RELAX_TABLE_ENTRY(9, 1, 4, ARC_RLX_LD_LIMM),
    576  1.4.8.1  pgoyette   RELAX_TABLE_ENTRY_MAX(1, 8, ARC_RLX_NONE),
    577  1.4.8.1  pgoyette 
    578  1.4.8.1  pgoyette   /* MOV_S b, u8 ->
    579  1.4.8.1  pgoyette      MOV<.f> b, s12 ->
    580  1.4.8.1  pgoyette      MOV<.f> b, limm.  */
    581  1.4.8.1  pgoyette   RELAX_TABLE_ENTRY(8, 0, 2, ARC_RLX_MOV_S12),
    582  1.4.8.1  pgoyette   RELAX_TABLE_ENTRY(8, 0, 4, ARC_RLX_MOV_LIMM),
    583  1.4.8.1  pgoyette   RELAX_TABLE_ENTRY_MAX(0, 8, ARC_RLX_NONE),
    584  1.4.8.1  pgoyette 
    585  1.4.8.1  pgoyette   /* SUB_S c, b, u3 ->
    586  1.4.8.1  pgoyette      SUB<.f> a, b, u6 ->
    587  1.4.8.1  pgoyette      SUB<.f> a, b, limm.  */
    588  1.4.8.1  pgoyette   RELAX_TABLE_ENTRY(3, 0, 2, ARC_RLX_SUB_U6),
    589  1.4.8.1  pgoyette   RELAX_TABLE_ENTRY(6, 0, 4, ARC_RLX_SUB_LIMM),
    590  1.4.8.1  pgoyette   RELAX_TABLE_ENTRY_MAX(0, 8, ARC_RLX_NONE),
    591  1.4.8.1  pgoyette 
    592  1.4.8.1  pgoyette   /* MPY<.f> a, b, u6 ->
    593  1.4.8.1  pgoyette      MPY<.f> a, b, limm.  */
    594  1.4.8.1  pgoyette   RELAX_TABLE_ENTRY(6, 0, 4, ARC_RLX_MPY_LIMM),
    595  1.4.8.1  pgoyette   RELAX_TABLE_ENTRY_MAX(0, 8, ARC_RLX_NONE),
    596  1.4.8.1  pgoyette 
    597  1.4.8.1  pgoyette   /* MOV<.f><.cc> b, u6 ->
    598  1.4.8.1  pgoyette      MOV<.f><.cc> b, limm.  */
    599  1.4.8.1  pgoyette   RELAX_TABLE_ENTRY(6, 0, 4, ARC_RLX_MOV_RLIMM),
    600  1.4.8.1  pgoyette   RELAX_TABLE_ENTRY_MAX(0, 8, ARC_RLX_NONE),
    601  1.4.8.1  pgoyette 
    602  1.4.8.1  pgoyette   /* ADD<.f><.cc> b, b, u6 ->
    603  1.4.8.1  pgoyette      ADD<.f><.cc> b, b, limm.  */
    604  1.4.8.1  pgoyette   RELAX_TABLE_ENTRY(6, 0, 4, ARC_RLX_ADD_RRLIMM),
    605  1.4.8.1  pgoyette   RELAX_TABLE_ENTRY_MAX(0, 8, ARC_RLX_NONE),
    606  1.4.8.1  pgoyette };
    607  1.4.8.1  pgoyette 
    608  1.4.8.1  pgoyette /* Order of this table's entries matters!  */
    609  1.4.8.1  pgoyette const struct arc_relaxable_ins arc_relaxable_insns[] =
    610  1.4.8.1  pgoyette {
    611  1.4.8.1  pgoyette   { "bl", { IMMEDIATE }, { 0 }, "bl_s", 0, ARC_RLX_BL_S },
    612  1.4.8.1  pgoyette   { "b", { IMMEDIATE }, { 0 }, "b_s", 0, ARC_RLX_B_S },
    613  1.4.8.1  pgoyette   { "add", { REGISTER, REGISTER_DUP, IMMEDIATE }, { 5, 1, 0 }, "add",
    614  1.4.8.1  pgoyette     2, ARC_RLX_ADD_RRU6},
    615  1.4.8.1  pgoyette   { "add", { REGISTER_S, REGISTER_S, IMMEDIATE }, { 0 }, "add_s", 2,
    616  1.4.8.1  pgoyette     ARC_RLX_ADD_U3 },
    617  1.4.8.1  pgoyette   { "add", { REGISTER, REGISTER, IMMEDIATE }, { 5, 0 }, "add", 2,
    618  1.4.8.1  pgoyette     ARC_RLX_ADD_U6 },
    619  1.4.8.1  pgoyette   { "ld", { REGISTER_S, BRACKET, REGISTER_S, IMMEDIATE, BRACKET },
    620  1.4.8.1  pgoyette     { 0 }, "ld_s", 3, ARC_RLX_LD_U7 },
    621  1.4.8.1  pgoyette   { "ld", { REGISTER, BRACKET, REGISTER_NO_GP, IMMEDIATE, BRACKET },
    622  1.4.8.1  pgoyette     { 11, 4, 14, 17, 0 }, "ld", 3, ARC_RLX_LD_S9 },
    623  1.4.8.1  pgoyette   { "mov", { REGISTER_S, IMMEDIATE }, { 0 }, "mov_s", 1, ARC_RLX_MOV_U8 },
    624  1.4.8.1  pgoyette   { "mov", { REGISTER, IMMEDIATE }, { 5, 0 }, "mov", 1, ARC_RLX_MOV_S12 },
    625  1.4.8.1  pgoyette   { "mov", { REGISTER, IMMEDIATE }, { 5, 1, 0 },"mov", 1, ARC_RLX_MOV_RU6 },
    626  1.4.8.1  pgoyette   { "sub", { REGISTER_S, REGISTER_S, IMMEDIATE }, { 0 }, "sub_s", 2,
    627  1.4.8.1  pgoyette     ARC_RLX_SUB_U3 },
    628  1.4.8.1  pgoyette   { "sub", { REGISTER, REGISTER, IMMEDIATE }, { 5, 0 }, "sub", 2,
    629  1.4.8.1  pgoyette     ARC_RLX_SUB_U6 },
    630  1.4.8.1  pgoyette   { "mpy", { REGISTER, REGISTER, IMMEDIATE }, { 5, 0 }, "mpy", 2,
    631  1.4.8.1  pgoyette     ARC_RLX_MPY_U6 },
    632  1.4.8.1  pgoyette };
    633  1.4.8.1  pgoyette 
    634  1.4.8.1  pgoyette const unsigned arc_num_relaxable_ins = ARRAY_SIZE (arc_relaxable_insns);
    635  1.4.8.1  pgoyette 
    636      1.3  christos /* Flags to set in the elf header.  */
    637      1.3  christos static flagword arc_eflag = 0x00;
    638      1.1  christos 
    639      1.3  christos /* Pre-defined "_GLOBAL_OFFSET_TABLE_".  */
    640      1.3  christos symbolS * GOT_symbol = 0;
    641      1.1  christos 
    642      1.3  christos /* Set to TRUE when we assemble instructions.  */
    643      1.3  christos static bfd_boolean assembling_insn = FALSE;
    644      1.3  christos 
    645  1.4.8.1  pgoyette /* Functions implementation.  */
    646      1.3  christos 
    647  1.4.8.1  pgoyette /* Return a pointer to ARC_OPCODE_HASH_ENTRY that identifies all
    648  1.4.8.1  pgoyette    ARC_OPCODE entries in ARC_OPCODE_HASH that match NAME, or NULL if there
    649  1.4.8.1  pgoyette    are no matching entries in ARC_OPCODE_HASH.  */
    650  1.4.8.1  pgoyette 
    651  1.4.8.1  pgoyette static const struct arc_opcode_hash_entry *
    652  1.4.8.1  pgoyette arc_find_opcode (const char *name)
    653  1.4.8.1  pgoyette {
    654  1.4.8.1  pgoyette   const struct arc_opcode_hash_entry *entry;
    655  1.4.8.1  pgoyette 
    656  1.4.8.1  pgoyette   entry = hash_find (arc_opcode_hash, name);
    657  1.4.8.1  pgoyette   return entry;
    658  1.4.8.1  pgoyette }
    659  1.4.8.1  pgoyette 
    660  1.4.8.1  pgoyette /* Initialise the iterator ITER.  */
    661  1.4.8.1  pgoyette 
    662  1.4.8.1  pgoyette static void
    663  1.4.8.1  pgoyette arc_opcode_hash_entry_iterator_init (struct arc_opcode_hash_entry_iterator *iter)
    664  1.4.8.1  pgoyette {
    665  1.4.8.1  pgoyette   iter->index = 0;
    666  1.4.8.1  pgoyette   iter->opcode = NULL;
    667  1.4.8.1  pgoyette }
    668  1.4.8.1  pgoyette 
    669  1.4.8.1  pgoyette /* Return the next ARC_OPCODE from ENTRY, using ITER to hold state between
    670  1.4.8.1  pgoyette    calls to this function.  Return NULL when all ARC_OPCODE entries have
    671  1.4.8.1  pgoyette    been returned.  */
    672  1.4.8.1  pgoyette 
    673  1.4.8.1  pgoyette static const struct arc_opcode *
    674  1.4.8.1  pgoyette arc_opcode_hash_entry_iterator_next (const struct arc_opcode_hash_entry *entry,
    675  1.4.8.1  pgoyette 				     struct arc_opcode_hash_entry_iterator *iter)
    676  1.4.8.1  pgoyette {
    677  1.4.8.1  pgoyette   if (iter->opcode == NULL && iter->index == 0)
    678  1.4.8.1  pgoyette     {
    679  1.4.8.1  pgoyette       gas_assert (entry->count > 0);
    680  1.4.8.1  pgoyette       iter->opcode = entry->opcode[iter->index];
    681  1.4.8.1  pgoyette     }
    682  1.4.8.1  pgoyette   else if (iter->opcode != NULL)
    683  1.4.8.1  pgoyette     {
    684  1.4.8.1  pgoyette       const char *old_name = iter->opcode->name;
    685  1.4.8.1  pgoyette 
    686  1.4.8.1  pgoyette       iter->opcode++;
    687  1.4.8.1  pgoyette       if (iter->opcode->name == NULL
    688  1.4.8.1  pgoyette 	  || strcmp (old_name, iter->opcode->name) != 0)
    689  1.4.8.1  pgoyette 	{
    690  1.4.8.1  pgoyette 	  iter->index++;
    691  1.4.8.1  pgoyette 	  if (iter->index == entry->count)
    692  1.4.8.1  pgoyette 	    iter->opcode = NULL;
    693  1.4.8.1  pgoyette 	  else
    694  1.4.8.1  pgoyette 	    iter->opcode = entry->opcode[iter->index];
    695  1.4.8.1  pgoyette 	}
    696  1.4.8.1  pgoyette     }
    697  1.4.8.1  pgoyette 
    698  1.4.8.1  pgoyette   return iter->opcode;
    699  1.4.8.1  pgoyette }
    700  1.4.8.1  pgoyette 
    701  1.4.8.1  pgoyette /* Insert an opcode into opcode hash structure.  */
    702  1.4.8.1  pgoyette 
    703  1.4.8.1  pgoyette static void
    704  1.4.8.1  pgoyette arc_insert_opcode (const struct arc_opcode *opcode)
    705  1.4.8.1  pgoyette {
    706  1.4.8.1  pgoyette   const char *name, *retval;
    707  1.4.8.1  pgoyette   struct arc_opcode_hash_entry *entry;
    708  1.4.8.1  pgoyette   name = opcode->name;
    709  1.4.8.1  pgoyette 
    710  1.4.8.1  pgoyette   entry = hash_find (arc_opcode_hash, name);
    711  1.4.8.1  pgoyette   if (entry == NULL)
    712  1.4.8.1  pgoyette     {
    713  1.4.8.1  pgoyette       entry = XNEW (struct arc_opcode_hash_entry);
    714  1.4.8.1  pgoyette       entry->count = 0;
    715  1.4.8.1  pgoyette       entry->opcode = NULL;
    716  1.4.8.1  pgoyette 
    717  1.4.8.1  pgoyette       retval = hash_insert (arc_opcode_hash, name, (void *) entry);
    718  1.4.8.1  pgoyette       if (retval)
    719  1.4.8.1  pgoyette 	as_fatal (_("internal error: can't hash opcode '%s': %s"),
    720  1.4.8.1  pgoyette 		  name, retval);
    721  1.4.8.1  pgoyette     }
    722  1.4.8.1  pgoyette 
    723  1.4.8.1  pgoyette   entry->opcode = XRESIZEVEC (const struct arc_opcode *, entry->opcode,
    724  1.4.8.1  pgoyette 			      entry->count + 1);
    725  1.4.8.1  pgoyette 
    726  1.4.8.1  pgoyette   if (entry->opcode == NULL)
    727  1.4.8.1  pgoyette     as_fatal (_("Virtual memory exhausted"));
    728  1.4.8.1  pgoyette 
    729  1.4.8.1  pgoyette   entry->opcode[entry->count] = opcode;
    730  1.4.8.1  pgoyette   entry->count++;
    731  1.4.8.1  pgoyette }
    732      1.3  christos 
    733      1.3  christos 
    734      1.3  christos /* Like md_number_to_chars but used for limms.  The 4-byte limm value,
    735      1.3  christos    is encoded as 'middle-endian' for a little-endian target.  FIXME!
    736      1.3  christos    this function is used for regular 4 byte instructions as well.  */
    737      1.1  christos 
    738      1.3  christos static void
    739      1.3  christos md_number_to_chars_midend (char *buf, valueT val, int n)
    740      1.3  christos {
    741      1.3  christos   if (n == 4)
    742      1.1  christos     {
    743      1.3  christos       md_number_to_chars (buf,     (val & 0xffff0000) >> 16, 2);
    744      1.3  christos       md_number_to_chars (buf + 2, (val & 0xffff), 2);
    745      1.3  christos     }
    746      1.3  christos   else
    747      1.1  christos     {
    748      1.3  christos       md_number_to_chars (buf, val, n);
    749      1.3  christos     }
    750      1.3  christos }
    751      1.1  christos 
    752  1.4.8.1  pgoyette /* Select an appropriate entry from CPU_TYPES based on ARG and initialise
    753  1.4.8.1  pgoyette    the relevant static global variables.  */
    754  1.4.8.1  pgoyette 
    755  1.4.8.1  pgoyette static void
    756  1.4.8.1  pgoyette arc_select_cpu (const char *arg)
    757  1.4.8.1  pgoyette {
    758  1.4.8.1  pgoyette   int cpu_flags = 0;
    759  1.4.8.1  pgoyette   int i;
    760  1.4.8.1  pgoyette 
    761  1.4.8.1  pgoyette   for (i = 0; cpu_types[i].name; ++i)
    762  1.4.8.1  pgoyette     {
    763  1.4.8.1  pgoyette       if (!strcasecmp (cpu_types[i].name, arg))
    764  1.4.8.1  pgoyette         {
    765  1.4.8.1  pgoyette           arc_target = cpu_types[i].flags;
    766  1.4.8.1  pgoyette           arc_target_name = cpu_types[i].name;
    767  1.4.8.1  pgoyette           arc_features = cpu_types[i].features;
    768  1.4.8.1  pgoyette           arc_mach_type = cpu_types[i].mach;
    769  1.4.8.1  pgoyette           cpu_flags = cpu_types[i].eflags;
    770  1.4.8.1  pgoyette           break;
    771  1.4.8.1  pgoyette         }
    772  1.4.8.1  pgoyette     }
    773  1.4.8.1  pgoyette 
    774  1.4.8.1  pgoyette   if (!cpu_types[i].name)
    775  1.4.8.1  pgoyette     as_fatal (_("unknown architecture: %s\n"), arg);
    776  1.4.8.1  pgoyette   gas_assert (cpu_flags != 0);
    777  1.4.8.1  pgoyette   arc_eflag = (arc_eflag & ~EF_ARC_MACH_MSK) | cpu_flags;
    778  1.4.8.1  pgoyette }
    779  1.4.8.1  pgoyette 
    780      1.3  christos /* Here ends all the ARCompact extension instruction assembling
    781      1.3  christos    stuff.  */
    782      1.1  christos 
    783      1.3  christos static void
    784      1.3  christos arc_extra_reloc (int r_type)
    785      1.3  christos {
    786      1.3  christos   char *sym_name, c;
    787      1.3  christos   symbolS *sym, *lab = NULL;
    788      1.1  christos 
    789      1.3  christos   if (*input_line_pointer == '@')
    790      1.3  christos     input_line_pointer++;
    791      1.3  christos   c = get_symbol_name (&sym_name);
    792      1.3  christos   sym = symbol_find_or_make (sym_name);
    793      1.3  christos   restore_line_pointer (c);
    794      1.3  christos   if (c == ',' && r_type == BFD_RELOC_ARC_TLS_GD_LD)
    795      1.3  christos     {
    796      1.3  christos       ++input_line_pointer;
    797      1.3  christos       char *lab_name;
    798      1.3  christos       c = get_symbol_name (&lab_name);
    799      1.3  christos       lab = symbol_find_or_make (lab_name);
    800      1.3  christos       restore_line_pointer (c);
    801      1.3  christos     }
    802  1.4.8.1  pgoyette 
    803  1.4.8.1  pgoyette   /* These relocations exist as a mechanism for the compiler to tell the
    804  1.4.8.1  pgoyette      linker how to patch the code if the tls model is optimised.  However,
    805  1.4.8.1  pgoyette      the relocation itself does not require any space within the assembler
    806  1.4.8.1  pgoyette      fragment, and so we pass a size of 0.
    807  1.4.8.1  pgoyette 
    808  1.4.8.1  pgoyette      The lines that generate these relocations look like this:
    809  1.4.8.1  pgoyette 
    810  1.4.8.1  pgoyette          .tls_gd_ld @.tdata`bl __tls_get_addr@plt
    811  1.4.8.1  pgoyette 
    812  1.4.8.1  pgoyette      The '.tls_gd_ld @.tdata' is processed first and generates the
    813  1.4.8.1  pgoyette      additional relocation, while the 'bl __tls_get_addr@plt' is processed
    814  1.4.8.1  pgoyette      second and generates the additional branch.
    815  1.4.8.1  pgoyette 
    816  1.4.8.1  pgoyette      It is possible that the additional relocation generated by the
    817  1.4.8.1  pgoyette      '.tls_gd_ld @.tdata' will be attached at the very end of one fragment,
    818  1.4.8.1  pgoyette      while the 'bl __tls_get_addr@plt' will be generated as the first thing
    819  1.4.8.1  pgoyette      in the next fragment.  This will be fine; both relocations will still
    820  1.4.8.1  pgoyette      appear to be at the same address in the generated object file.
    821  1.4.8.1  pgoyette      However, this only works as the additional relocation is generated
    822  1.4.8.1  pgoyette      with size of 0 bytes.  */
    823      1.3  christos   fixS *fixP
    824      1.3  christos     = fix_new (frag_now,	/* Which frag?  */
    825      1.3  christos 	       frag_now_fix (),	/* Where in that frag?  */
    826  1.4.8.1  pgoyette 	       0,		/* size: 1, 2, or 4 usually.  */
    827      1.3  christos 	       sym,		/* X_add_symbol.  */
    828      1.3  christos 	       0,		/* X_add_number.  */
    829      1.3  christos 	       FALSE,		/* TRUE if PC-relative relocation.  */
    830      1.3  christos 	       r_type		/* Relocation type.  */);
    831      1.3  christos   fixP->fx_subsy = lab;
    832      1.3  christos }
    833      1.3  christos 
    834      1.3  christos static symbolS *
    835      1.3  christos arc_lcomm_internal (int ignore ATTRIBUTE_UNUSED,
    836      1.3  christos 		    symbolS *symbolP, addressT size)
    837      1.3  christos {
    838      1.3  christos   addressT align = 0;
    839      1.3  christos   SKIP_WHITESPACE ();
    840      1.1  christos 
    841      1.3  christos   if (*input_line_pointer == ',')
    842      1.1  christos     {
    843      1.3  christos       align = parse_align (1);
    844      1.1  christos 
    845      1.3  christos       if (align == (addressT) -1)
    846      1.3  christos 	return NULL;
    847      1.1  christos     }
    848      1.1  christos   else
    849      1.3  christos     {
    850      1.3  christos       if (size >= 8)
    851      1.3  christos 	align = 3;
    852      1.3  christos       else if (size >= 4)
    853      1.3  christos 	align = 2;
    854      1.3  christos       else if (size >= 2)
    855      1.3  christos 	align = 1;
    856      1.3  christos       else
    857      1.3  christos 	align = 0;
    858      1.3  christos     }
    859      1.1  christos 
    860      1.3  christos   bss_alloc (symbolP, size, align);
    861      1.3  christos   S_CLEAR_EXTERNAL (symbolP);
    862      1.3  christos 
    863      1.3  christos   return symbolP;
    864      1.1  christos }
    865      1.1  christos 
    866      1.3  christos static void
    867      1.3  christos arc_lcomm (int ignore)
    868      1.1  christos {
    869      1.3  christos   symbolS *symbolP = s_comm_internal (ignore, arc_lcomm_internal);
    870      1.1  christos 
    871      1.3  christos   if (symbolP)
    872      1.3  christos     symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT;
    873      1.3  christos }
    874      1.1  christos 
    875      1.3  christos /* Select the cpu we're assembling for.  */
    876      1.1  christos 
    877      1.3  christos static void
    878      1.3  christos arc_option (int ignore ATTRIBUTE_UNUSED)
    879      1.3  christos {
    880      1.3  christos   int mach = -1;
    881      1.3  christos   char c;
    882      1.3  christos   char *cpu;
    883      1.1  christos 
    884      1.3  christos   c = get_symbol_name (&cpu);
    885      1.3  christos   mach = arc_get_mach (cpu);
    886      1.1  christos 
    887      1.3  christos   if (mach == -1)
    888      1.3  christos     goto bad_cpu;
    889      1.1  christos 
    890      1.3  christos   if (!mach_type_specified_p)
    891      1.3  christos     {
    892  1.4.8.1  pgoyette       if ((!strcmp ("ARC600", cpu))
    893  1.4.8.1  pgoyette 	  || (!strcmp ("ARC601", cpu))
    894  1.4.8.1  pgoyette 	  || (!strcmp ("A6", cpu)))
    895  1.4.8.1  pgoyette 	{
    896  1.4.8.1  pgoyette 	  md_parse_option (OPTION_MCPU, "arc600");
    897  1.4.8.1  pgoyette 	}
    898  1.4.8.1  pgoyette       else if ((!strcmp ("ARC700", cpu))
    899  1.4.8.1  pgoyette 	       || (!strcmp ("A7", cpu)))
    900  1.4.8.1  pgoyette 	{
    901  1.4.8.1  pgoyette 	  md_parse_option (OPTION_MCPU, "arc700");
    902  1.4.8.1  pgoyette 	}
    903  1.4.8.1  pgoyette       else if (!strcmp ("EM", cpu))
    904  1.4.8.1  pgoyette 	{
    905  1.4.8.1  pgoyette 	  md_parse_option (OPTION_MCPU, "arcem");
    906  1.4.8.1  pgoyette 	}
    907  1.4.8.1  pgoyette       else if (!strcmp ("HS", cpu))
    908  1.4.8.1  pgoyette 	{
    909  1.4.8.1  pgoyette 	  md_parse_option (OPTION_MCPU, "archs");
    910  1.4.8.1  pgoyette 	}
    911  1.4.8.1  pgoyette       else if (!strcmp ("NPS400", cpu))
    912  1.4.8.1  pgoyette 	{
    913  1.4.8.1  pgoyette 	  md_parse_option (OPTION_MCPU, "nps400");
    914  1.4.8.1  pgoyette 	}
    915  1.4.8.1  pgoyette       else
    916  1.4.8.1  pgoyette 	as_fatal (_("could not find the architecture"));
    917  1.4.8.1  pgoyette 
    918      1.3  christos       if (!bfd_set_arch_mach (stdoutput, bfd_arch_arc, mach))
    919  1.4.8.1  pgoyette 	as_fatal (_("could not set architecture and machine"));
    920      1.1  christos 
    921  1.4.8.1  pgoyette       /* Set elf header flags.  */
    922  1.4.8.1  pgoyette       bfd_set_private_flags (stdoutput, arc_eflag);
    923      1.3  christos     }
    924      1.3  christos   else
    925      1.3  christos     if (arc_mach_type != mach)
    926  1.4.8.1  pgoyette       as_warn (_("Command-line value overrides \".cpu\" directive"));
    927      1.1  christos 
    928  1.4.8.1  pgoyette   restore_line_pointer (c);
    929      1.3  christos   demand_empty_rest_of_line ();
    930      1.3  christos   return;
    931      1.1  christos 
    932      1.3  christos  bad_cpu:
    933  1.4.8.1  pgoyette   restore_line_pointer (c);
    934  1.4.8.1  pgoyette   as_bad (_("invalid identifier for \".cpu\""));
    935      1.3  christos   ignore_rest_of_line ();
    936      1.3  christos }
    937      1.1  christos 
    938      1.3  christos /* Smartly print an expression.  */
    939      1.1  christos 
    940      1.1  christos static void
    941      1.3  christos debug_exp (expressionS *t)
    942      1.1  christos {
    943      1.3  christos   const char *name ATTRIBUTE_UNUSED;
    944      1.3  christos   const char *namemd ATTRIBUTE_UNUSED;
    945      1.1  christos 
    946      1.3  christos   pr_debug ("debug_exp: ");
    947      1.1  christos 
    948      1.3  christos   switch (t->X_op)
    949      1.3  christos     {
    950      1.3  christos     default:			name = "unknown";		break;
    951      1.3  christos     case O_illegal:		name = "O_illegal";		break;
    952      1.3  christos     case O_absent:		name = "O_absent";		break;
    953      1.3  christos     case O_constant:		name = "O_constant";		break;
    954      1.3  christos     case O_symbol:		name = "O_symbol";		break;
    955      1.3  christos     case O_symbol_rva:		name = "O_symbol_rva";		break;
    956      1.3  christos     case O_register:		name = "O_register";		break;
    957      1.3  christos     case O_big:			name = "O_big";			break;
    958      1.3  christos     case O_uminus:		name = "O_uminus";		break;
    959      1.3  christos     case O_bit_not:		name = "O_bit_not";		break;
    960      1.3  christos     case O_logical_not:		name = "O_logical_not";		break;
    961      1.3  christos     case O_multiply:		name = "O_multiply";		break;
    962      1.3  christos     case O_divide:		name = "O_divide";		break;
    963      1.3  christos     case O_modulus:		name = "O_modulus";		break;
    964      1.3  christos     case O_left_shift:		name = "O_left_shift";		break;
    965      1.3  christos     case O_right_shift:		name = "O_right_shift";		break;
    966      1.3  christos     case O_bit_inclusive_or:	name = "O_bit_inclusive_or";	break;
    967      1.3  christos     case O_bit_or_not:		name = "O_bit_or_not";		break;
    968      1.3  christos     case O_bit_exclusive_or:	name = "O_bit_exclusive_or";	break;
    969      1.3  christos     case O_bit_and:		name = "O_bit_and";		break;
    970      1.3  christos     case O_add:			name = "O_add";			break;
    971      1.3  christos     case O_subtract:		name = "O_subtract";		break;
    972      1.3  christos     case O_eq:			name = "O_eq";			break;
    973      1.3  christos     case O_ne:			name = "O_ne";			break;
    974      1.3  christos     case O_lt:			name = "O_lt";			break;
    975      1.3  christos     case O_le:			name = "O_le";			break;
    976      1.3  christos     case O_ge:			name = "O_ge";			break;
    977      1.3  christos     case O_gt:			name = "O_gt";			break;
    978      1.3  christos     case O_logical_and:		name = "O_logical_and";		break;
    979      1.3  christos     case O_logical_or:		name = "O_logical_or";		break;
    980      1.3  christos     case O_index:		name = "O_index";		break;
    981      1.3  christos     case O_bracket:		name = "O_bracket";		break;
    982      1.3  christos     }
    983      1.3  christos 
    984      1.3  christos   switch (t->X_md)
    985      1.3  christos     {
    986      1.3  christos     default:			namemd = "unknown";		break;
    987      1.3  christos     case O_gotoff:		namemd = "O_gotoff";		break;
    988      1.3  christos     case O_gotpc:		namemd = "O_gotpc";		break;
    989      1.3  christos     case O_plt:			namemd = "O_plt";		break;
    990      1.3  christos     case O_sda:			namemd = "O_sda";		break;
    991      1.3  christos     case O_pcl:			namemd = "O_pcl";		break;
    992      1.3  christos     case O_tlsgd:		namemd = "O_tlsgd";		break;
    993      1.3  christos     case O_tlsie:		namemd = "O_tlsie";		break;
    994      1.3  christos     case O_tpoff9:		namemd = "O_tpoff9";		break;
    995      1.3  christos     case O_tpoff:		namemd = "O_tpoff";		break;
    996      1.3  christos     case O_dtpoff9:		namemd = "O_dtpoff9";		break;
    997      1.3  christos     case O_dtpoff:		namemd = "O_dtpoff";		break;
    998      1.3  christos     }
    999      1.3  christos 
   1000      1.3  christos   pr_debug ("%s (%s, %s, %d, %s)", name,
   1001      1.3  christos 	    (t->X_add_symbol) ? S_GET_NAME (t->X_add_symbol) : "--",
   1002      1.3  christos 	    (t->X_op_symbol) ? S_GET_NAME (t->X_op_symbol) : "--",
   1003      1.3  christos 	    (int) t->X_add_number,
   1004      1.3  christos 	    (t->X_md) ? namemd : "--");
   1005      1.3  christos   pr_debug ("\n");
   1006      1.3  christos   fflush (stderr);
   1007      1.3  christos }
   1008      1.1  christos 
   1009      1.3  christos /* Parse the arguments to an opcode.  */
   1010      1.1  christos 
   1011      1.3  christos static int
   1012      1.3  christos tokenize_arguments (char *str,
   1013      1.3  christos 		    expressionS *tok,
   1014      1.3  christos 		    int ntok)
   1015      1.3  christos {
   1016      1.3  christos   char *old_input_line_pointer;
   1017      1.3  christos   bfd_boolean saw_comma = FALSE;
   1018      1.3  christos   bfd_boolean saw_arg = FALSE;
   1019      1.3  christos   int brk_lvl = 0;
   1020      1.3  christos   int num_args = 0;
   1021      1.3  christos   int i;
   1022      1.3  christos   size_t len;
   1023      1.3  christos   const struct arc_reloc_op_tag *r;
   1024      1.3  christos   expressionS tmpE;
   1025      1.3  christos   char *reloc_name, c;
   1026      1.3  christos 
   1027      1.3  christos   memset (tok, 0, sizeof (*tok) * ntok);
   1028      1.3  christos 
   1029      1.3  christos   /* Save and restore input_line_pointer around this function.  */
   1030      1.3  christos   old_input_line_pointer = input_line_pointer;
   1031      1.3  christos   input_line_pointer = str;
   1032      1.1  christos 
   1033      1.3  christos   while (*input_line_pointer)
   1034      1.1  christos     {
   1035      1.3  christos       SKIP_WHITESPACE ();
   1036      1.3  christos       switch (*input_line_pointer)
   1037      1.3  christos 	{
   1038      1.3  christos 	case '\0':
   1039      1.3  christos 	  goto fini;
   1040      1.1  christos 
   1041      1.3  christos 	case ',':
   1042      1.3  christos 	  input_line_pointer++;
   1043      1.3  christos 	  if (saw_comma || !saw_arg)
   1044      1.3  christos 	    goto err;
   1045      1.3  christos 	  saw_comma = TRUE;
   1046      1.3  christos 	  break;
   1047      1.1  christos 
   1048      1.3  christos 	case '}':
   1049      1.3  christos 	case ']':
   1050      1.3  christos 	  ++input_line_pointer;
   1051      1.3  christos 	  --brk_lvl;
   1052  1.4.8.1  pgoyette 	  if (!saw_arg || num_args == ntok)
   1053      1.3  christos 	    goto err;
   1054      1.3  christos 	  tok->X_op = O_bracket;
   1055      1.3  christos 	  ++tok;
   1056      1.3  christos 	  ++num_args;
   1057      1.3  christos 	  break;
   1058      1.1  christos 
   1059      1.3  christos 	case '{':
   1060      1.3  christos 	case '[':
   1061      1.3  christos 	  input_line_pointer++;
   1062  1.4.8.1  pgoyette 	  if (brk_lvl || num_args == ntok)
   1063      1.3  christos 	    goto err;
   1064      1.3  christos 	  ++brk_lvl;
   1065      1.3  christos 	  tok->X_op = O_bracket;
   1066      1.3  christos 	  ++tok;
   1067      1.3  christos 	  ++num_args;
   1068      1.3  christos 	  break;
   1069      1.1  christos 
   1070      1.3  christos 	case '@':
   1071      1.3  christos 	  /* We have labels, function names and relocations, all
   1072      1.3  christos 	     starting with @ symbol.  Sort them out.  */
   1073  1.4.8.1  pgoyette 	  if ((saw_arg && !saw_comma) || num_args == ntok)
   1074      1.3  christos 	    goto err;
   1075      1.3  christos 
   1076      1.3  christos 	  /* Parse @label.  */
   1077      1.3  christos 	  tok->X_op = O_symbol;
   1078      1.3  christos 	  tok->X_md = O_absent;
   1079      1.3  christos 	  expression (tok);
   1080      1.3  christos 	  if (*input_line_pointer != '@')
   1081      1.3  christos 	    goto normalsymbol; /* This is not a relocation.  */
   1082      1.3  christos 
   1083      1.3  christos 	relocationsym:
   1084      1.3  christos 
   1085      1.3  christos 	  /* A relocation opernad has the following form
   1086      1.3  christos 	     @identifier@relocation_type.  The identifier is already
   1087      1.3  christos 	     in tok!  */
   1088      1.3  christos 	  if (tok->X_op != O_symbol)
   1089      1.3  christos 	    {
   1090      1.3  christos 	      as_bad (_("No valid label relocation operand"));
   1091      1.3  christos 	      goto err;
   1092      1.3  christos 	    }
   1093      1.1  christos 
   1094      1.3  christos 	  /* Parse @relocation_type.  */
   1095      1.3  christos 	  input_line_pointer++;
   1096      1.3  christos 	  c = get_symbol_name (&reloc_name);
   1097      1.3  christos 	  len = input_line_pointer - reloc_name;
   1098      1.3  christos 	  if (len == 0)
   1099      1.3  christos 	    {
   1100      1.3  christos 	      as_bad (_("No relocation operand"));
   1101      1.3  christos 	      goto err;
   1102      1.3  christos 	    }
   1103      1.1  christos 
   1104      1.3  christos 	  /* Go through known relocation and try to find a match.  */
   1105      1.3  christos 	  r = &arc_reloc_op[0];
   1106      1.3  christos 	  for (i = arc_num_reloc_op - 1; i >= 0; i--, r++)
   1107      1.3  christos 	    if (len == r->length
   1108      1.3  christos 		&& memcmp (reloc_name, r->name, len) == 0)
   1109      1.3  christos 	      break;
   1110      1.3  christos 	  if (i < 0)
   1111      1.1  christos 	    {
   1112      1.3  christos 	      as_bad (_("Unknown relocation operand: @%s"), reloc_name);
   1113      1.3  christos 	      goto err;
   1114      1.1  christos 	    }
   1115      1.3  christos 
   1116      1.3  christos 	  *input_line_pointer = c;
   1117      1.3  christos 	  SKIP_WHITESPACE_AFTER_NAME ();
   1118      1.3  christos 	  /* Extra check for TLS: base.  */
   1119      1.3  christos 	  if (*input_line_pointer == '@')
   1120      1.1  christos 	    {
   1121      1.3  christos 	      symbolS *base;
   1122      1.3  christos 	      if (tok->X_op_symbol != NULL
   1123      1.3  christos 		  || tok->X_op != O_symbol)
   1124      1.1  christos 		{
   1125      1.3  christos 		  as_bad (_("Unable to parse TLS base: %s"),
   1126      1.3  christos 			  input_line_pointer);
   1127      1.3  christos 		  goto err;
   1128      1.1  christos 		}
   1129      1.3  christos 	      input_line_pointer++;
   1130      1.3  christos 	      char *sym_name;
   1131      1.3  christos 	      c = get_symbol_name (&sym_name);
   1132      1.3  christos 	      base = symbol_find_or_make (sym_name);
   1133      1.3  christos 	      tok->X_op = O_subtract;
   1134      1.3  christos 	      tok->X_op_symbol = base;
   1135      1.3  christos 	      restore_line_pointer (c);
   1136      1.3  christos 	      tmpE.X_add_number = 0;
   1137      1.1  christos 	    }
   1138      1.3  christos 	  else if ((*input_line_pointer != '+')
   1139      1.3  christos 		   && (*input_line_pointer != '-'))
   1140      1.1  christos 	    {
   1141      1.3  christos 	      tmpE.X_add_number = 0;
   1142      1.1  christos 	    }
   1143      1.1  christos 	  else
   1144      1.1  christos 	    {
   1145      1.3  christos 	      /* Parse the constant of a complex relocation expression
   1146      1.3  christos 		 like @identifier@reloc +/- const.  */
   1147      1.3  christos 	      if (! r->complex_expr)
   1148      1.1  christos 		{
   1149      1.3  christos 		  as_bad (_("@%s is not a complex relocation."), r->name);
   1150      1.3  christos 		  goto err;
   1151      1.1  christos 		}
   1152      1.3  christos 	      expression (&tmpE);
   1153      1.3  christos 	      if (tmpE.X_op != O_constant)
   1154      1.1  christos 		{
   1155      1.3  christos 		  as_bad (_("Bad expression: @%s + %s."),
   1156      1.3  christos 			  r->name, input_line_pointer);
   1157      1.3  christos 		  goto err;
   1158      1.1  christos 		}
   1159      1.1  christos 	    }
   1160      1.1  christos 
   1161      1.3  christos 	  tok->X_md = r->op;
   1162      1.3  christos 	  tok->X_add_number = tmpE.X_add_number;
   1163      1.3  christos 
   1164      1.3  christos 	  debug_exp (tok);
   1165      1.3  christos 
   1166      1.3  christos 	  saw_comma = FALSE;
   1167      1.3  christos 	  saw_arg = TRUE;
   1168      1.3  christos 	  tok++;
   1169      1.3  christos 	  num_args++;
   1170      1.3  christos 	  break;
   1171      1.1  christos 
   1172      1.3  christos 	case '%':
   1173      1.3  christos 	  /* Can be a register.  */
   1174      1.3  christos 	  ++input_line_pointer;
   1175      1.3  christos 	  /* Fall through.  */
   1176      1.3  christos 	default:
   1177      1.1  christos 
   1178  1.4.8.1  pgoyette 	  if ((saw_arg && !saw_comma) || num_args == ntok)
   1179      1.3  christos 	    goto err;
   1180      1.1  christos 
   1181      1.3  christos 	  tok->X_op = O_absent;
   1182      1.3  christos 	  tok->X_md = O_absent;
   1183      1.3  christos 	  expression (tok);
   1184      1.3  christos 
   1185      1.3  christos 	  /* Legacy: There are cases when we have
   1186      1.3  christos 	     identifier@relocation_type, if it is the case parse the
   1187      1.3  christos 	     relocation type as well.  */
   1188      1.3  christos 	  if (*input_line_pointer == '@')
   1189      1.3  christos 	    goto relocationsym;
   1190      1.3  christos 
   1191      1.3  christos 	normalsymbol:
   1192      1.3  christos 	  debug_exp (tok);
   1193      1.3  christos 
   1194  1.4.8.1  pgoyette 	  if (tok->X_op == O_illegal
   1195  1.4.8.1  pgoyette               || tok->X_op == O_absent
   1196  1.4.8.1  pgoyette               || num_args == ntok)
   1197      1.3  christos 	    goto err;
   1198      1.3  christos 
   1199      1.3  christos 	  saw_comma = FALSE;
   1200      1.3  christos 	  saw_arg = TRUE;
   1201      1.3  christos 	  tok++;
   1202      1.3  christos 	  num_args++;
   1203      1.3  christos 	  break;
   1204      1.1  christos 	}
   1205      1.1  christos     }
   1206      1.1  christos 
   1207      1.3  christos  fini:
   1208      1.3  christos   if (saw_comma || brk_lvl)
   1209      1.3  christos     goto err;
   1210      1.3  christos   input_line_pointer = old_input_line_pointer;
   1211      1.3  christos 
   1212      1.3  christos   return num_args;
   1213      1.3  christos 
   1214      1.3  christos  err:
   1215      1.3  christos   if (brk_lvl)
   1216      1.3  christos     as_bad (_("Brackets in operand field incorrect"));
   1217      1.3  christos   else if (saw_comma)
   1218      1.3  christos     as_bad (_("extra comma"));
   1219      1.3  christos   else if (!saw_arg)
   1220      1.3  christos     as_bad (_("missing argument"));
   1221      1.3  christos   else
   1222      1.3  christos     as_bad (_("missing comma or colon"));
   1223      1.3  christos   input_line_pointer = old_input_line_pointer;
   1224      1.3  christos   return -1;
   1225      1.3  christos }
   1226      1.1  christos 
   1227      1.3  christos /* Parse the flags to a structure.  */
   1228      1.1  christos 
   1229      1.3  christos static int
   1230      1.3  christos tokenize_flags (const char *str,
   1231      1.3  christos 		struct arc_flags flags[],
   1232      1.3  christos 		int nflg)
   1233      1.3  christos {
   1234      1.3  christos   char *old_input_line_pointer;
   1235      1.3  christos   bfd_boolean saw_flg = FALSE;
   1236      1.3  christos   bfd_boolean saw_dot = FALSE;
   1237      1.3  christos   int num_flags  = 0;
   1238      1.3  christos   size_t flgnamelen;
   1239      1.3  christos 
   1240      1.3  christos   memset (flags, 0, sizeof (*flags) * nflg);
   1241      1.3  christos 
   1242      1.3  christos   /* Save and restore input_line_pointer around this function.  */
   1243      1.3  christos   old_input_line_pointer = input_line_pointer;
   1244      1.3  christos   input_line_pointer = (char *) str;
   1245      1.3  christos 
   1246      1.3  christos   while (*input_line_pointer)
   1247      1.3  christos     {
   1248      1.3  christos       switch (*input_line_pointer)
   1249      1.3  christos 	{
   1250      1.3  christos 	case ' ':
   1251      1.3  christos 	case '\0':
   1252      1.3  christos 	  goto fini;
   1253      1.3  christos 
   1254      1.3  christos 	case '.':
   1255      1.3  christos 	  input_line_pointer++;
   1256      1.3  christos 	  if (saw_dot)
   1257      1.3  christos 	    goto err;
   1258      1.3  christos 	  saw_dot = TRUE;
   1259      1.3  christos 	  saw_flg = FALSE;
   1260      1.3  christos 	  break;
   1261      1.1  christos 
   1262      1.3  christos 	default:
   1263      1.3  christos 	  if (saw_flg && !saw_dot)
   1264      1.3  christos 	    goto err;
   1265      1.1  christos 
   1266      1.3  christos 	  if (num_flags >= nflg)
   1267      1.3  christos 	    goto err;
   1268      1.1  christos 
   1269  1.4.8.1  pgoyette 	  flgnamelen = strspn (input_line_pointer,
   1270  1.4.8.1  pgoyette 			       "abcdefghijklmnopqrstuvwxyz0123456789");
   1271  1.4.8.1  pgoyette 	  if (flgnamelen > MAX_FLAG_NAME_LENGTH)
   1272      1.3  christos 	    goto err;
   1273      1.3  christos 
   1274      1.3  christos 	  memcpy (flags->name, input_line_pointer, flgnamelen);
   1275      1.3  christos 
   1276      1.3  christos 	  input_line_pointer += flgnamelen;
   1277      1.3  christos 	  flags++;
   1278      1.3  christos 	  saw_dot = FALSE;
   1279      1.3  christos 	  saw_flg = TRUE;
   1280      1.3  christos 	  num_flags++;
   1281      1.3  christos 	  break;
   1282      1.3  christos 	}
   1283      1.1  christos     }
   1284      1.1  christos 
   1285      1.3  christos  fini:
   1286      1.3  christos   input_line_pointer = old_input_line_pointer;
   1287      1.3  christos   return num_flags;
   1288      1.3  christos 
   1289      1.3  christos  err:
   1290      1.3  christos   if (saw_dot)
   1291      1.3  christos     as_bad (_("extra dot"));
   1292      1.3  christos   else if (!saw_flg)
   1293      1.3  christos     as_bad (_("unrecognized flag"));
   1294      1.3  christos   else
   1295      1.3  christos     as_bad (_("failed to parse flags"));
   1296      1.3  christos   input_line_pointer = old_input_line_pointer;
   1297      1.3  christos   return -1;
   1298      1.3  christos }
   1299      1.1  christos 
   1300  1.4.8.1  pgoyette /* Apply the fixups in order.  */
   1301      1.1  christos 
   1302  1.4.8.1  pgoyette static void
   1303  1.4.8.1  pgoyette apply_fixups (struct arc_insn *insn, fragS *fragP, int fix)
   1304      1.1  christos {
   1305  1.4.8.1  pgoyette   int i;
   1306      1.1  christos 
   1307  1.4.8.1  pgoyette   for (i = 0; i < insn->nfixups; i++)
   1308      1.1  christos     {
   1309  1.4.8.1  pgoyette       struct arc_fixup *fixup = &insn->fixups[i];
   1310  1.4.8.1  pgoyette       int size, pcrel, offset = 0;
   1311      1.1  christos 
   1312  1.4.8.1  pgoyette       /* FIXME! the reloc size is wrong in the BFD file.
   1313  1.4.8.1  pgoyette 	 When it is fixed please delete me.  */
   1314  1.4.8.1  pgoyette       size = (insn->short_insn && !fixup->islong) ? 2 : 4;
   1315      1.3  christos 
   1316  1.4.8.1  pgoyette       if (fixup->islong)
   1317  1.4.8.1  pgoyette 	offset = (insn->short_insn) ? 2 : 4;
   1318      1.1  christos 
   1319  1.4.8.1  pgoyette       /* Some fixups are only used internally, thus no howto.  */
   1320  1.4.8.1  pgoyette       if ((int) fixup->reloc == 0)
   1321  1.4.8.1  pgoyette 	as_fatal (_("Unhandled reloc type"));
   1322      1.1  christos 
   1323  1.4.8.1  pgoyette       if ((int) fixup->reloc < 0)
   1324  1.4.8.1  pgoyette 	{
   1325  1.4.8.1  pgoyette 	  /* FIXME! the reloc size is wrong in the BFD file.
   1326  1.4.8.1  pgoyette 	     When it is fixed please enable me.
   1327  1.4.8.1  pgoyette 	     size = (insn->short_insn && !fixup->islong) ? 2 : 4; */
   1328  1.4.8.1  pgoyette 	  pcrel = fixup->pcrel;
   1329  1.4.8.1  pgoyette 	}
   1330  1.4.8.1  pgoyette       else
   1331  1.4.8.1  pgoyette 	{
   1332  1.4.8.1  pgoyette 	  reloc_howto_type *reloc_howto =
   1333  1.4.8.1  pgoyette 	    bfd_reloc_type_lookup (stdoutput,
   1334  1.4.8.1  pgoyette 				   (bfd_reloc_code_real_type) fixup->reloc);
   1335  1.4.8.1  pgoyette 	  gas_assert (reloc_howto);
   1336      1.3  christos 
   1337  1.4.8.1  pgoyette 	  /* FIXME! the reloc size is wrong in the BFD file.
   1338  1.4.8.1  pgoyette 	     When it is fixed please enable me.
   1339  1.4.8.1  pgoyette 	     size = bfd_get_reloc_size (reloc_howto); */
   1340  1.4.8.1  pgoyette 	  pcrel = reloc_howto->pc_relative;
   1341  1.4.8.1  pgoyette 	}
   1342      1.3  christos 
   1343  1.4.8.1  pgoyette       pr_debug ("%s:%d: apply_fixups: new %s fixup (PCrel:%s) of size %d @ \
   1344  1.4.8.1  pgoyette offset %d + %d\n",
   1345  1.4.8.1  pgoyette 		fragP->fr_file, fragP->fr_line,
   1346  1.4.8.1  pgoyette 		(fixup->reloc < 0) ? "Internal" :
   1347  1.4.8.1  pgoyette 		bfd_get_reloc_code_name (fixup->reloc),
   1348  1.4.8.1  pgoyette 		pcrel ? "Y" : "N",
   1349  1.4.8.1  pgoyette 		size, fix, offset);
   1350  1.4.8.1  pgoyette       fix_new_exp (fragP, fix + offset,
   1351  1.4.8.1  pgoyette 		   size, &fixup->exp, pcrel, fixup->reloc);
   1352      1.3  christos 
   1353  1.4.8.1  pgoyette       /* Check for ZOLs, and update symbol info if any.  */
   1354  1.4.8.1  pgoyette       if (LP_INSN (insn->insn))
   1355      1.1  christos 	{
   1356  1.4.8.1  pgoyette 	  gas_assert (fixup->exp.X_add_symbol);
   1357  1.4.8.1  pgoyette 	  ARC_SET_FLAG (fixup->exp.X_add_symbol, ARC_FLAG_ZOL);
   1358      1.1  christos 	}
   1359      1.1  christos     }
   1360      1.3  christos }
   1361      1.3  christos 
   1362  1.4.8.1  pgoyette /* Actually output an instruction with its fixup.  */
   1363      1.3  christos 
   1364  1.4.8.1  pgoyette static void
   1365  1.4.8.1  pgoyette emit_insn0 (struct arc_insn *insn, char *where, bfd_boolean relax)
   1366      1.3  christos {
   1367  1.4.8.1  pgoyette   char *f = where;
   1368      1.3  christos 
   1369  1.4.8.1  pgoyette   pr_debug ("Emit insn : 0x%x\n", insn->insn);
   1370  1.4.8.1  pgoyette   pr_debug ("\tShort   : 0x%d\n", insn->short_insn);
   1371  1.4.8.1  pgoyette   pr_debug ("\tLong imm: 0x%lx\n", insn->limm);
   1372      1.3  christos 
   1373  1.4.8.1  pgoyette   /* Write out the instruction.  */
   1374  1.4.8.1  pgoyette   if (insn->short_insn)
   1375      1.3  christos     {
   1376  1.4.8.1  pgoyette       if (insn->has_limm)
   1377  1.4.8.1  pgoyette 	{
   1378  1.4.8.1  pgoyette 	  if (!relax)
   1379  1.4.8.1  pgoyette 	    f = frag_more (6);
   1380  1.4.8.1  pgoyette 	  md_number_to_chars (f, insn->insn, 2);
   1381  1.4.8.1  pgoyette 	  md_number_to_chars_midend (f + 2, insn->limm, 4);
   1382  1.4.8.1  pgoyette 	  dwarf2_emit_insn (6);
   1383  1.4.8.1  pgoyette 	}
   1384  1.4.8.1  pgoyette       else
   1385  1.4.8.1  pgoyette 	{
   1386  1.4.8.1  pgoyette 	  if (!relax)
   1387  1.4.8.1  pgoyette 	    f = frag_more (2);
   1388  1.4.8.1  pgoyette 	  md_number_to_chars (f, insn->insn, 2);
   1389  1.4.8.1  pgoyette 	  dwarf2_emit_insn (2);
   1390  1.4.8.1  pgoyette 	}
   1391  1.4.8.1  pgoyette     }
   1392  1.4.8.1  pgoyette   else
   1393  1.4.8.1  pgoyette     {
   1394  1.4.8.1  pgoyette       if (insn->has_limm)
   1395  1.4.8.1  pgoyette 	{
   1396  1.4.8.1  pgoyette 	  if (!relax)
   1397  1.4.8.1  pgoyette 	    f = frag_more (8);
   1398  1.4.8.1  pgoyette 	  md_number_to_chars_midend (f, insn->insn, 4);
   1399  1.4.8.1  pgoyette 	  md_number_to_chars_midend (f + 4, insn->limm, 4);
   1400  1.4.8.1  pgoyette 	  dwarf2_emit_insn (8);
   1401  1.4.8.1  pgoyette 	}
   1402  1.4.8.1  pgoyette       else
   1403  1.4.8.1  pgoyette 	{
   1404  1.4.8.1  pgoyette 	  if (!relax)
   1405  1.4.8.1  pgoyette 	    f = frag_more (4);
   1406  1.4.8.1  pgoyette 	  md_number_to_chars_midend (f, insn->insn, 4);
   1407  1.4.8.1  pgoyette 	  dwarf2_emit_insn (4);
   1408  1.4.8.1  pgoyette 	}
   1409      1.3  christos     }
   1410      1.3  christos 
   1411  1.4.8.1  pgoyette   if (!relax)
   1412  1.4.8.1  pgoyette     apply_fixups (insn, frag_now, (f - frag_now->fr_literal));
   1413  1.4.8.1  pgoyette }
   1414      1.3  christos 
   1415  1.4.8.1  pgoyette static void
   1416  1.4.8.1  pgoyette emit_insn1 (struct arc_insn *insn)
   1417  1.4.8.1  pgoyette {
   1418  1.4.8.1  pgoyette   /* How frag_var's args are currently configured:
   1419  1.4.8.1  pgoyette      - rs_machine_dependent, to dictate it's a relaxation frag.
   1420  1.4.8.1  pgoyette      - FRAG_MAX_GROWTH, maximum size of instruction
   1421  1.4.8.1  pgoyette      - 0, variable size that might grow...unused by generic relaxation.
   1422  1.4.8.1  pgoyette      - frag_now->fr_subtype, fr_subtype starting value, set previously.
   1423  1.4.8.1  pgoyette      - s, opand expression.
   1424  1.4.8.1  pgoyette      - 0, offset but it's unused.
   1425  1.4.8.1  pgoyette      - 0, opcode but it's unused.  */
   1426  1.4.8.1  pgoyette   symbolS *s = make_expr_symbol (&insn->fixups[0].exp);
   1427  1.4.8.1  pgoyette   frag_now->tc_frag_data.pcrel = insn->fixups[0].pcrel;
   1428  1.4.8.1  pgoyette 
   1429  1.4.8.1  pgoyette   if (frag_room () < FRAG_MAX_GROWTH)
   1430  1.4.8.1  pgoyette     {
   1431  1.4.8.1  pgoyette       /* Handle differently when frag literal memory is exhausted.
   1432  1.4.8.1  pgoyette 	 This is used because when there's not enough memory left in
   1433  1.4.8.1  pgoyette 	 the current frag, a new frag is created and the information
   1434  1.4.8.1  pgoyette 	 we put into frag_now->tc_frag_data is disregarded.  */
   1435  1.4.8.1  pgoyette 
   1436  1.4.8.1  pgoyette       struct arc_relax_type relax_info_copy;
   1437  1.4.8.1  pgoyette       relax_substateT subtype = frag_now->fr_subtype;
   1438  1.4.8.1  pgoyette 
   1439  1.4.8.1  pgoyette       memcpy (&relax_info_copy, &frag_now->tc_frag_data,
   1440  1.4.8.1  pgoyette 	      sizeof (struct arc_relax_type));
   1441      1.3  christos 
   1442  1.4.8.1  pgoyette       frag_wane (frag_now);
   1443  1.4.8.1  pgoyette       frag_grow (FRAG_MAX_GROWTH);
   1444      1.3  christos 
   1445  1.4.8.1  pgoyette       memcpy (&frag_now->tc_frag_data, &relax_info_copy,
   1446  1.4.8.1  pgoyette 	      sizeof (struct arc_relax_type));
   1447      1.3  christos 
   1448  1.4.8.1  pgoyette       frag_var (rs_machine_dependent, FRAG_MAX_GROWTH, 0,
   1449  1.4.8.1  pgoyette 		subtype, s, 0, 0);
   1450  1.4.8.1  pgoyette     }
   1451  1.4.8.1  pgoyette   else
   1452  1.4.8.1  pgoyette     frag_var (rs_machine_dependent, FRAG_MAX_GROWTH, 0,
   1453  1.4.8.1  pgoyette 	      frag_now->fr_subtype, s, 0, 0);
   1454      1.3  christos }
   1455      1.3  christos 
   1456  1.4.8.1  pgoyette static void
   1457  1.4.8.1  pgoyette emit_insn (struct arc_insn *insn)
   1458      1.3  christos {
   1459  1.4.8.1  pgoyette   if (insn->relax)
   1460  1.4.8.1  pgoyette     emit_insn1 (insn);
   1461      1.3  christos   else
   1462  1.4.8.1  pgoyette     emit_insn0 (insn, NULL, FALSE);
   1463      1.3  christos }
   1464      1.3  christos 
   1465  1.4.8.1  pgoyette /* Check whether a symbol involves a register.  */
   1466      1.3  christos 
   1467  1.4.8.1  pgoyette static bfd_boolean
   1468  1.4.8.1  pgoyette contains_register (symbolS *sym)
   1469      1.3  christos {
   1470  1.4.8.1  pgoyette   if (sym)
   1471  1.4.8.1  pgoyette     {
   1472  1.4.8.1  pgoyette       expressionS *ex = symbol_get_value_expression (sym);
   1473  1.4.8.1  pgoyette 
   1474  1.4.8.1  pgoyette       return ((O_register == ex->X_op)
   1475  1.4.8.1  pgoyette 	      && !contains_register (ex->X_add_symbol)
   1476  1.4.8.1  pgoyette 	      && !contains_register (ex->X_op_symbol));
   1477  1.4.8.1  pgoyette     }
   1478      1.3  christos 
   1479  1.4.8.1  pgoyette   return FALSE;
   1480      1.3  christos }
   1481      1.3  christos 
   1482  1.4.8.1  pgoyette /* Returns the register number within a symbol.  */
   1483      1.3  christos 
   1484  1.4.8.1  pgoyette static int
   1485  1.4.8.1  pgoyette get_register (symbolS *sym)
   1486      1.3  christos {
   1487  1.4.8.1  pgoyette   if (!contains_register (sym))
   1488  1.4.8.1  pgoyette     return -1;
   1489      1.1  christos 
   1490  1.4.8.1  pgoyette   expressionS *ex = symbol_get_value_expression (sym);
   1491  1.4.8.1  pgoyette   return regno (ex->X_add_number);
   1492  1.4.8.1  pgoyette }
   1493      1.1  christos 
   1494  1.4.8.1  pgoyette /* Return true if a RELOC is generic.  A generic reloc is PC-rel of a
   1495  1.4.8.1  pgoyette    simple ME relocation (e.g. RELOC_ARC_32_ME, BFD_RELOC_ARC_PC32.  */
   1496      1.3  christos 
   1497  1.4.8.1  pgoyette static bfd_boolean
   1498  1.4.8.1  pgoyette generic_reloc_p (extended_bfd_reloc_code_real_type reloc)
   1499  1.4.8.1  pgoyette {
   1500  1.4.8.1  pgoyette   if (!reloc)
   1501  1.4.8.1  pgoyette     return FALSE;
   1502      1.1  christos 
   1503  1.4.8.1  pgoyette   switch (reloc)
   1504      1.1  christos     {
   1505  1.4.8.1  pgoyette     case BFD_RELOC_ARC_SDA_LDST:
   1506  1.4.8.1  pgoyette     case BFD_RELOC_ARC_SDA_LDST1:
   1507  1.4.8.1  pgoyette     case BFD_RELOC_ARC_SDA_LDST2:
   1508  1.4.8.1  pgoyette     case BFD_RELOC_ARC_SDA16_LD:
   1509  1.4.8.1  pgoyette     case BFD_RELOC_ARC_SDA16_LD1:
   1510  1.4.8.1  pgoyette     case BFD_RELOC_ARC_SDA16_LD2:
   1511  1.4.8.1  pgoyette     case BFD_RELOC_ARC_SDA16_ST2:
   1512  1.4.8.1  pgoyette     case BFD_RELOC_ARC_SDA32_ME:
   1513  1.4.8.1  pgoyette       return FALSE;
   1514  1.4.8.1  pgoyette     default:
   1515  1.4.8.1  pgoyette       return TRUE;
   1516      1.1  christos     }
   1517      1.3  christos }
   1518      1.3  christos 
   1519  1.4.8.1  pgoyette /* Allocates a tok entry.  */
   1520      1.1  christos 
   1521  1.4.8.1  pgoyette static int
   1522  1.4.8.1  pgoyette allocate_tok (expressionS *tok, int ntok, int cidx)
   1523      1.3  christos {
   1524  1.4.8.1  pgoyette   if (ntok > MAX_INSN_ARGS - 2)
   1525  1.4.8.1  pgoyette     return 0; /* No space left.  */
   1526      1.1  christos 
   1527  1.4.8.1  pgoyette   if (cidx > ntok)
   1528  1.4.8.1  pgoyette     return 0; /* Incorect args.  */
   1529  1.4.8.1  pgoyette 
   1530  1.4.8.1  pgoyette   memcpy (&tok[ntok+1], &tok[ntok], sizeof (*tok));
   1531  1.4.8.1  pgoyette 
   1532  1.4.8.1  pgoyette   if (cidx == ntok)
   1533  1.4.8.1  pgoyette     return 1; /* Success.  */
   1534  1.4.8.1  pgoyette   return allocate_tok (tok, ntok - 1, cidx);
   1535      1.3  christos }
   1536      1.1  christos 
   1537  1.4.8.1  pgoyette /* Check if an particular ARC feature is enabled.  */
   1538      1.1  christos 
   1539  1.4.8.1  pgoyette static bfd_boolean
   1540  1.4.8.1  pgoyette check_cpu_feature (insn_subclass_t sc)
   1541      1.3  christos {
   1542  1.4.8.1  pgoyette   if (is_code_density_p (sc) && !(arc_features & ARC_CD))
   1543  1.4.8.1  pgoyette     return FALSE;
   1544      1.3  christos 
   1545  1.4.8.1  pgoyette   if (is_spfp_p (sc) && !(arc_features & ARC_SPFP))
   1546  1.4.8.1  pgoyette     return FALSE;
   1547      1.3  christos 
   1548  1.4.8.1  pgoyette   if (is_dpfp_p (sc) && !(arc_features & ARC_DPFP))
   1549  1.4.8.1  pgoyette     return FALSE;
   1550      1.3  christos 
   1551  1.4.8.1  pgoyette   if (is_fpuda_p (sc) && !(arc_features & ARC_FPUDA))
   1552  1.4.8.1  pgoyette     return FALSE;
   1553      1.3  christos 
   1554  1.4.8.1  pgoyette   if (is_nps400_p (sc) && !(arc_features & ARC_NPS400))
   1555  1.4.8.1  pgoyette     return FALSE;
   1556      1.3  christos 
   1557  1.4.8.1  pgoyette   return TRUE;
   1558  1.4.8.1  pgoyette }
   1559  1.4.8.1  pgoyette 
   1560  1.4.8.1  pgoyette /* Parse the flags described by FIRST_PFLAG and NFLGS against the flag
   1561  1.4.8.1  pgoyette    operands in OPCODE.  Stores the matching OPCODES into the FIRST_PFLAG
   1562  1.4.8.1  pgoyette    array and returns TRUE if the flag operands all match, otherwise,
   1563  1.4.8.1  pgoyette    returns FALSE, in which case the FIRST_PFLAG array may have been
   1564  1.4.8.1  pgoyette    modified.  */
   1565  1.4.8.1  pgoyette 
   1566  1.4.8.1  pgoyette static bfd_boolean
   1567  1.4.8.1  pgoyette parse_opcode_flags (const struct arc_opcode *opcode,
   1568  1.4.8.1  pgoyette                     int nflgs,
   1569  1.4.8.1  pgoyette                     struct arc_flags *first_pflag)
   1570  1.4.8.1  pgoyette {
   1571  1.4.8.1  pgoyette   int lnflg, i;
   1572  1.4.8.1  pgoyette   const unsigned char *flgidx;
   1573  1.4.8.1  pgoyette 
   1574  1.4.8.1  pgoyette   lnflg = nflgs;
   1575  1.4.8.1  pgoyette   for (i = 0; i < nflgs; i++)
   1576  1.4.8.1  pgoyette     first_pflag[i].flgp = NULL;
   1577  1.4.8.1  pgoyette 
   1578  1.4.8.1  pgoyette   /* Check the flags.  Iterate over the valid flag classes.  */
   1579  1.4.8.1  pgoyette   for (flgidx = opcode->flags; *flgidx; ++flgidx)
   1580  1.4.8.1  pgoyette     {
   1581  1.4.8.1  pgoyette       /* Get a valid flag class.  */
   1582  1.4.8.1  pgoyette       const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
   1583  1.4.8.1  pgoyette       const unsigned *flgopridx;
   1584  1.4.8.1  pgoyette       int cl_matches = 0;
   1585  1.4.8.1  pgoyette       struct arc_flags *pflag = NULL;
   1586  1.4.8.1  pgoyette 
   1587  1.4.8.1  pgoyette       /* Check for extension conditional codes.  */
   1588  1.4.8.1  pgoyette       if (ext_condcode.arc_ext_condcode
   1589  1.4.8.1  pgoyette           && cl_flags->flag_class & F_CLASS_EXTEND)
   1590  1.4.8.1  pgoyette         {
   1591  1.4.8.1  pgoyette           struct arc_flag_operand *pf = ext_condcode.arc_ext_condcode;
   1592  1.4.8.1  pgoyette           while (pf->name)
   1593  1.4.8.1  pgoyette             {
   1594  1.4.8.1  pgoyette               pflag = first_pflag;
   1595  1.4.8.1  pgoyette               for (i = 0; i < nflgs; i++, pflag++)
   1596  1.4.8.1  pgoyette                 {
   1597  1.4.8.1  pgoyette                   if (!strcmp (pf->name, pflag->name))
   1598  1.4.8.1  pgoyette                     {
   1599  1.4.8.1  pgoyette                       if (pflag->flgp != NULL)
   1600  1.4.8.1  pgoyette                         return FALSE;
   1601  1.4.8.1  pgoyette                       /* Found it.  */
   1602  1.4.8.1  pgoyette                       cl_matches++;
   1603  1.4.8.1  pgoyette                       pflag->flgp = pf;
   1604  1.4.8.1  pgoyette                       lnflg--;
   1605  1.4.8.1  pgoyette                       break;
   1606  1.4.8.1  pgoyette                     }
   1607  1.4.8.1  pgoyette                 }
   1608  1.4.8.1  pgoyette               pf++;
   1609  1.4.8.1  pgoyette             }
   1610  1.4.8.1  pgoyette         }
   1611  1.4.8.1  pgoyette 
   1612  1.4.8.1  pgoyette       for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
   1613  1.4.8.1  pgoyette         {
   1614  1.4.8.1  pgoyette           const struct arc_flag_operand *flg_operand;
   1615  1.4.8.1  pgoyette 
   1616  1.4.8.1  pgoyette           pflag = first_pflag;
   1617  1.4.8.1  pgoyette           flg_operand = &arc_flag_operands[*flgopridx];
   1618  1.4.8.1  pgoyette           for (i = 0; i < nflgs; i++, pflag++)
   1619  1.4.8.1  pgoyette             {
   1620  1.4.8.1  pgoyette               /* Match against the parsed flags.  */
   1621  1.4.8.1  pgoyette               if (!strcmp (flg_operand->name, pflag->name))
   1622  1.4.8.1  pgoyette                 {
   1623  1.4.8.1  pgoyette                   if (pflag->flgp != NULL)
   1624  1.4.8.1  pgoyette                     return FALSE;
   1625  1.4.8.1  pgoyette                   cl_matches++;
   1626  1.4.8.1  pgoyette                   pflag->flgp = flg_operand;
   1627  1.4.8.1  pgoyette                   lnflg--;
   1628  1.4.8.1  pgoyette                   break; /* goto next flag class and parsed flag.  */
   1629  1.4.8.1  pgoyette                 }
   1630  1.4.8.1  pgoyette             }
   1631  1.4.8.1  pgoyette         }
   1632  1.4.8.1  pgoyette 
   1633  1.4.8.1  pgoyette       if ((cl_flags->flag_class & F_CLASS_REQUIRED) && cl_matches == 0)
   1634  1.4.8.1  pgoyette         return FALSE;
   1635  1.4.8.1  pgoyette       if ((cl_flags->flag_class & F_CLASS_OPTIONAL) && cl_matches > 1)
   1636  1.4.8.1  pgoyette         return FALSE;
   1637      1.1  christos     }
   1638      1.1  christos 
   1639  1.4.8.1  pgoyette   /* Did I check all the parsed flags?  */
   1640  1.4.8.1  pgoyette   return lnflg ? FALSE : TRUE;
   1641  1.4.8.1  pgoyette }
   1642  1.4.8.1  pgoyette 
   1643  1.4.8.1  pgoyette 
   1644  1.4.8.1  pgoyette /* Search forward through all variants of an opcode looking for a
   1645  1.4.8.1  pgoyette    syntax match.  */
   1646  1.4.8.1  pgoyette 
   1647  1.4.8.1  pgoyette static const struct arc_opcode *
   1648  1.4.8.1  pgoyette find_opcode_match (const struct arc_opcode_hash_entry *entry,
   1649  1.4.8.1  pgoyette 		   expressionS *tok,
   1650  1.4.8.1  pgoyette 		   int *pntok,
   1651  1.4.8.1  pgoyette 		   struct arc_flags *first_pflag,
   1652  1.4.8.1  pgoyette 		   int nflgs,
   1653  1.4.8.1  pgoyette 		   int *pcpumatch)
   1654  1.4.8.1  pgoyette {
   1655  1.4.8.1  pgoyette   const struct arc_opcode *opcode;
   1656  1.4.8.1  pgoyette   struct arc_opcode_hash_entry_iterator iter;
   1657  1.4.8.1  pgoyette   int ntok = *pntok;
   1658  1.4.8.1  pgoyette   int got_cpu_match = 0;
   1659  1.4.8.1  pgoyette   expressionS bktok[MAX_INSN_ARGS];
   1660  1.4.8.1  pgoyette   int bkntok;
   1661  1.4.8.1  pgoyette   expressionS emptyE;
   1662  1.4.8.1  pgoyette 
   1663  1.4.8.1  pgoyette   arc_opcode_hash_entry_iterator_init (&iter);
   1664  1.4.8.1  pgoyette   memset (&emptyE, 0, sizeof (emptyE));
   1665  1.4.8.1  pgoyette   memcpy (bktok, tok, MAX_INSN_ARGS * sizeof (*tok));
   1666  1.4.8.1  pgoyette   bkntok = ntok;
   1667  1.4.8.1  pgoyette 
   1668  1.4.8.1  pgoyette   for (opcode = arc_opcode_hash_entry_iterator_next (entry, &iter);
   1669  1.4.8.1  pgoyette        opcode != NULL;
   1670  1.4.8.1  pgoyette        opcode = arc_opcode_hash_entry_iterator_next (entry, &iter))
   1671      1.1  christos     {
   1672  1.4.8.1  pgoyette       const unsigned char *opidx;
   1673  1.4.8.1  pgoyette       int tokidx = 0;
   1674  1.4.8.1  pgoyette       const expressionS *t = &emptyE;
   1675  1.4.8.1  pgoyette 
   1676  1.4.8.1  pgoyette       pr_debug ("%s:%d: find_opcode_match: trying opcode 0x%08X ",
   1677  1.4.8.1  pgoyette 		frag_now->fr_file, frag_now->fr_line, opcode->opcode);
   1678  1.4.8.1  pgoyette 
   1679  1.4.8.1  pgoyette       /* Don't match opcodes that don't exist on this
   1680  1.4.8.1  pgoyette 	 architecture.  */
   1681  1.4.8.1  pgoyette       if (!(opcode->cpu & arc_target))
   1682  1.4.8.1  pgoyette 	goto match_failed;
   1683  1.4.8.1  pgoyette 
   1684  1.4.8.1  pgoyette       if (!check_cpu_feature (opcode->subclass))
   1685  1.4.8.1  pgoyette 	goto match_failed;
   1686  1.4.8.1  pgoyette 
   1687  1.4.8.1  pgoyette       got_cpu_match = 1;
   1688  1.4.8.1  pgoyette       pr_debug ("cpu ");
   1689  1.4.8.1  pgoyette 
   1690  1.4.8.1  pgoyette       /* Check the operands.  */
   1691  1.4.8.1  pgoyette       for (opidx = opcode->operands; *opidx; ++opidx)
   1692      1.3  christos 	{
   1693  1.4.8.1  pgoyette 	  const struct arc_operand *operand = &arc_operands[*opidx];
   1694  1.4.8.1  pgoyette 
   1695  1.4.8.1  pgoyette 	  /* Only take input from real operands.  */
   1696  1.4.8.1  pgoyette 	  if ((operand->flags & ARC_OPERAND_FAKE)
   1697  1.4.8.1  pgoyette 	      && !(operand->flags & ARC_OPERAND_BRAKET))
   1698  1.4.8.1  pgoyette 	    continue;
   1699  1.4.8.1  pgoyette 
   1700  1.4.8.1  pgoyette 	  /* When we expect input, make sure we have it.  */
   1701  1.4.8.1  pgoyette 	  if (tokidx >= ntok)
   1702  1.4.8.1  pgoyette 	    goto match_failed;
   1703  1.4.8.1  pgoyette 
   1704  1.4.8.1  pgoyette 	  /* Match operand type with expression type.  */
   1705  1.4.8.1  pgoyette 	  switch (operand->flags & ARC_OPERAND_TYPECHECK_MASK)
   1706  1.4.8.1  pgoyette 	    {
   1707  1.4.8.1  pgoyette 	    case ARC_OPERAND_IR:
   1708  1.4.8.1  pgoyette 	      /* Check to be a register.  */
   1709  1.4.8.1  pgoyette 	      if ((tok[tokidx].X_op != O_register
   1710  1.4.8.1  pgoyette 		   || !is_ir_num (tok[tokidx].X_add_number))
   1711  1.4.8.1  pgoyette 		  && !(operand->flags & ARC_OPERAND_IGNORE))
   1712  1.4.8.1  pgoyette 		goto match_failed;
   1713  1.4.8.1  pgoyette 
   1714  1.4.8.1  pgoyette 	      /* If expect duplicate, make sure it is duplicate.  */
   1715  1.4.8.1  pgoyette 	      if (operand->flags & ARC_OPERAND_DUPLICATE)
   1716  1.4.8.1  pgoyette 		{
   1717  1.4.8.1  pgoyette 		  /* Check for duplicate.  */
   1718  1.4.8.1  pgoyette 		  if (t->X_op != O_register
   1719  1.4.8.1  pgoyette 		      || !is_ir_num (t->X_add_number)
   1720  1.4.8.1  pgoyette 		      || (regno (t->X_add_number) !=
   1721  1.4.8.1  pgoyette 			  regno (tok[tokidx].X_add_number)))
   1722  1.4.8.1  pgoyette 		    goto match_failed;
   1723  1.4.8.1  pgoyette 		}
   1724  1.4.8.1  pgoyette 
   1725  1.4.8.1  pgoyette 	      /* Special handling?  */
   1726  1.4.8.1  pgoyette 	      if (operand->insert)
   1727  1.4.8.1  pgoyette 		{
   1728  1.4.8.1  pgoyette 		  const char *errmsg = NULL;
   1729  1.4.8.1  pgoyette 		  (*operand->insert)(0,
   1730  1.4.8.1  pgoyette 				     regno (tok[tokidx].X_add_number),
   1731  1.4.8.1  pgoyette 				     &errmsg);
   1732  1.4.8.1  pgoyette 		  if (errmsg)
   1733  1.4.8.1  pgoyette 		    {
   1734  1.4.8.1  pgoyette 		      if (operand->flags & ARC_OPERAND_IGNORE)
   1735  1.4.8.1  pgoyette 			{
   1736  1.4.8.1  pgoyette 			  /* Missing argument, create one.  */
   1737  1.4.8.1  pgoyette 			  if (!allocate_tok (tok, ntok - 1, tokidx))
   1738  1.4.8.1  pgoyette 			    goto match_failed;
   1739  1.4.8.1  pgoyette 
   1740  1.4.8.1  pgoyette 			  tok[tokidx].X_op = O_absent;
   1741  1.4.8.1  pgoyette 			  ++ntok;
   1742  1.4.8.1  pgoyette 			}
   1743  1.4.8.1  pgoyette 		      else
   1744  1.4.8.1  pgoyette 			goto match_failed;
   1745  1.4.8.1  pgoyette 		    }
   1746  1.4.8.1  pgoyette 		}
   1747  1.4.8.1  pgoyette 
   1748  1.4.8.1  pgoyette 	      t = &tok[tokidx];
   1749  1.4.8.1  pgoyette 	      break;
   1750  1.4.8.1  pgoyette 
   1751  1.4.8.1  pgoyette 	    case ARC_OPERAND_BRAKET:
   1752  1.4.8.1  pgoyette 	      /* Check if bracket is also in opcode table as
   1753  1.4.8.1  pgoyette 		 operand.  */
   1754  1.4.8.1  pgoyette 	      if (tok[tokidx].X_op != O_bracket)
   1755  1.4.8.1  pgoyette 		goto match_failed;
   1756  1.4.8.1  pgoyette 	      break;
   1757  1.4.8.1  pgoyette 
   1758  1.4.8.1  pgoyette 	    case ARC_OPERAND_LIMM:
   1759  1.4.8.1  pgoyette 	    case ARC_OPERAND_SIGNED:
   1760  1.4.8.1  pgoyette 	    case ARC_OPERAND_UNSIGNED:
   1761  1.4.8.1  pgoyette 	      switch (tok[tokidx].X_op)
   1762  1.4.8.1  pgoyette 		{
   1763  1.4.8.1  pgoyette 		case O_illegal:
   1764  1.4.8.1  pgoyette 		case O_absent:
   1765  1.4.8.1  pgoyette 		case O_register:
   1766  1.4.8.1  pgoyette 		  goto match_failed;
   1767  1.4.8.1  pgoyette 
   1768  1.4.8.1  pgoyette 		case O_bracket:
   1769  1.4.8.1  pgoyette 		  /* Got an (too) early bracket, check if it is an
   1770  1.4.8.1  pgoyette 		     ignored operand.  N.B. This procedure works only
   1771  1.4.8.1  pgoyette 		     when bracket is the last operand!  */
   1772  1.4.8.1  pgoyette 		  if (!(operand->flags & ARC_OPERAND_IGNORE))
   1773  1.4.8.1  pgoyette 		    goto match_failed;
   1774  1.4.8.1  pgoyette 		  /* Insert the missing operand.  */
   1775  1.4.8.1  pgoyette 		  if (!allocate_tok (tok, ntok - 1, tokidx))
   1776  1.4.8.1  pgoyette 		    goto match_failed;
   1777  1.4.8.1  pgoyette 
   1778  1.4.8.1  pgoyette 		  tok[tokidx].X_op = O_absent;
   1779  1.4.8.1  pgoyette 		  ++ntok;
   1780  1.4.8.1  pgoyette 		  break;
   1781  1.4.8.1  pgoyette 
   1782  1.4.8.1  pgoyette 		case O_symbol:
   1783  1.4.8.1  pgoyette 		  {
   1784  1.4.8.1  pgoyette 		    const char *p;
   1785  1.4.8.1  pgoyette 		    const struct arc_aux_reg *auxr;
   1786  1.4.8.1  pgoyette 
   1787  1.4.8.1  pgoyette 		    if (opcode->insn_class != AUXREG)
   1788  1.4.8.1  pgoyette 		      goto de_fault;
   1789  1.4.8.1  pgoyette 		    p = S_GET_NAME (tok[tokidx].X_add_symbol);
   1790  1.4.8.1  pgoyette 
   1791  1.4.8.1  pgoyette 		    auxr = hash_find (arc_aux_hash, p);
   1792  1.4.8.1  pgoyette 		    if (auxr)
   1793  1.4.8.1  pgoyette 		      {
   1794  1.4.8.1  pgoyette 			/* We modify the token array here, safe in the
   1795  1.4.8.1  pgoyette 			   knowledge, that if this was the wrong
   1796  1.4.8.1  pgoyette 			   choice then the original contents will be
   1797  1.4.8.1  pgoyette 			   restored from BKTOK.  */
   1798  1.4.8.1  pgoyette 			tok[tokidx].X_op = O_constant;
   1799  1.4.8.1  pgoyette 			tok[tokidx].X_add_number = auxr->address;
   1800  1.4.8.1  pgoyette 			ARC_SET_FLAG (tok[tokidx].X_add_symbol, ARC_FLAG_AUX);
   1801  1.4.8.1  pgoyette 		      }
   1802  1.4.8.1  pgoyette 
   1803  1.4.8.1  pgoyette 		    if (tok[tokidx].X_op != O_constant)
   1804  1.4.8.1  pgoyette 		      goto de_fault;
   1805  1.4.8.1  pgoyette 		  }
   1806  1.4.8.1  pgoyette 		  /* Fall-through */
   1807  1.4.8.1  pgoyette 		case O_constant:
   1808  1.4.8.1  pgoyette 		  /* Check the range.  */
   1809  1.4.8.1  pgoyette 		  if (operand->bits != 32
   1810  1.4.8.1  pgoyette 		      && !(operand->flags & ARC_OPERAND_NCHK))
   1811  1.4.8.1  pgoyette 		    {
   1812  1.4.8.1  pgoyette 		      offsetT min, max, val;
   1813  1.4.8.1  pgoyette 		      val = tok[tokidx].X_add_number;
   1814  1.4.8.1  pgoyette 
   1815  1.4.8.1  pgoyette 		      if (operand->flags & ARC_OPERAND_SIGNED)
   1816  1.4.8.1  pgoyette 			{
   1817  1.4.8.1  pgoyette 			  max = (1 << (operand->bits - 1)) - 1;
   1818  1.4.8.1  pgoyette 			  min = -(1 << (operand->bits - 1));
   1819  1.4.8.1  pgoyette 			}
   1820  1.4.8.1  pgoyette 		      else
   1821  1.4.8.1  pgoyette 			{
   1822  1.4.8.1  pgoyette 			  max = (1 << operand->bits) - 1;
   1823  1.4.8.1  pgoyette 			  min = 0;
   1824  1.4.8.1  pgoyette 			}
   1825  1.4.8.1  pgoyette 
   1826  1.4.8.1  pgoyette 		      if (val < min || val > max)
   1827  1.4.8.1  pgoyette 			goto match_failed;
   1828  1.4.8.1  pgoyette 
   1829  1.4.8.1  pgoyette 		      /* Check alignmets.  */
   1830  1.4.8.1  pgoyette 		      if ((operand->flags & ARC_OPERAND_ALIGNED32)
   1831  1.4.8.1  pgoyette 			  && (val & 0x03))
   1832  1.4.8.1  pgoyette 			goto match_failed;
   1833  1.4.8.1  pgoyette 
   1834  1.4.8.1  pgoyette 		      if ((operand->flags & ARC_OPERAND_ALIGNED16)
   1835  1.4.8.1  pgoyette 			  && (val & 0x01))
   1836  1.4.8.1  pgoyette 			goto match_failed;
   1837  1.4.8.1  pgoyette 		    }
   1838  1.4.8.1  pgoyette 		  else if (operand->flags & ARC_OPERAND_NCHK)
   1839  1.4.8.1  pgoyette 		    {
   1840  1.4.8.1  pgoyette 		      if (operand->insert)
   1841  1.4.8.1  pgoyette 			{
   1842  1.4.8.1  pgoyette 			  const char *errmsg = NULL;
   1843  1.4.8.1  pgoyette 			  (*operand->insert)(0,
   1844  1.4.8.1  pgoyette 					     tok[tokidx].X_add_number,
   1845  1.4.8.1  pgoyette 					     &errmsg);
   1846  1.4.8.1  pgoyette 			  if (errmsg)
   1847  1.4.8.1  pgoyette 			    goto match_failed;
   1848  1.4.8.1  pgoyette 			}
   1849  1.4.8.1  pgoyette 		      else if (!(operand->flags & ARC_OPERAND_IGNORE))
   1850  1.4.8.1  pgoyette 			goto match_failed;
   1851  1.4.8.1  pgoyette 		    }
   1852  1.4.8.1  pgoyette 		  break;
   1853  1.4.8.1  pgoyette 
   1854  1.4.8.1  pgoyette 		case O_subtract:
   1855  1.4.8.1  pgoyette 		  /* Check if it is register range.  */
   1856  1.4.8.1  pgoyette 		  if ((tok[tokidx].X_add_number == 0)
   1857  1.4.8.1  pgoyette 		      && contains_register (tok[tokidx].X_add_symbol)
   1858  1.4.8.1  pgoyette 		      && contains_register (tok[tokidx].X_op_symbol))
   1859  1.4.8.1  pgoyette 		    {
   1860  1.4.8.1  pgoyette 		      int regs;
   1861  1.4.8.1  pgoyette 
   1862  1.4.8.1  pgoyette 		      regs = get_register (tok[tokidx].X_add_symbol);
   1863  1.4.8.1  pgoyette 		      regs <<= 16;
   1864  1.4.8.1  pgoyette 		      regs |= get_register (tok[tokidx].X_op_symbol);
   1865  1.4.8.1  pgoyette 		      if (operand->insert)
   1866  1.4.8.1  pgoyette 			{
   1867  1.4.8.1  pgoyette 			  const char *errmsg = NULL;
   1868  1.4.8.1  pgoyette 			  (*operand->insert)(0,
   1869  1.4.8.1  pgoyette 					     regs,
   1870  1.4.8.1  pgoyette 					     &errmsg);
   1871  1.4.8.1  pgoyette 			  if (errmsg)
   1872  1.4.8.1  pgoyette 			    goto match_failed;
   1873  1.4.8.1  pgoyette 			}
   1874  1.4.8.1  pgoyette 		      else
   1875  1.4.8.1  pgoyette 			goto match_failed;
   1876  1.4.8.1  pgoyette 		      break;
   1877  1.4.8.1  pgoyette 		    }
   1878  1.4.8.1  pgoyette 		default:
   1879  1.4.8.1  pgoyette 		de_fault:
   1880  1.4.8.1  pgoyette 		  if (operand->default_reloc == 0)
   1881  1.4.8.1  pgoyette 		    goto match_failed; /* The operand needs relocation.  */
   1882  1.4.8.1  pgoyette 
   1883  1.4.8.1  pgoyette 		  /* Relocs requiring long immediate.  FIXME! make it
   1884  1.4.8.1  pgoyette 		     generic and move it to a function.  */
   1885  1.4.8.1  pgoyette 		  switch (tok[tokidx].X_md)
   1886  1.4.8.1  pgoyette 		    {
   1887  1.4.8.1  pgoyette 		    case O_gotoff:
   1888  1.4.8.1  pgoyette 		    case O_gotpc:
   1889  1.4.8.1  pgoyette 		    case O_pcl:
   1890  1.4.8.1  pgoyette 		    case O_tpoff:
   1891  1.4.8.1  pgoyette 		    case O_dtpoff:
   1892  1.4.8.1  pgoyette 		    case O_tlsgd:
   1893  1.4.8.1  pgoyette 		    case O_tlsie:
   1894  1.4.8.1  pgoyette 		      if (!(operand->flags & ARC_OPERAND_LIMM))
   1895  1.4.8.1  pgoyette 			goto match_failed;
   1896  1.4.8.1  pgoyette 		    case O_absent:
   1897  1.4.8.1  pgoyette 		      if (!generic_reloc_p (operand->default_reloc))
   1898  1.4.8.1  pgoyette 			goto match_failed;
   1899  1.4.8.1  pgoyette 		    default:
   1900  1.4.8.1  pgoyette 		      break;
   1901  1.4.8.1  pgoyette 		    }
   1902  1.4.8.1  pgoyette 		  break;
   1903  1.4.8.1  pgoyette 		}
   1904  1.4.8.1  pgoyette 	      /* If expect duplicate, make sure it is duplicate.  */
   1905  1.4.8.1  pgoyette 	      if (operand->flags & ARC_OPERAND_DUPLICATE)
   1906  1.4.8.1  pgoyette 		{
   1907  1.4.8.1  pgoyette 		  if (t->X_op == O_illegal
   1908  1.4.8.1  pgoyette 		      || t->X_op == O_absent
   1909  1.4.8.1  pgoyette 		      || t->X_op == O_register
   1910  1.4.8.1  pgoyette 		      || (t->X_add_number != tok[tokidx].X_add_number))
   1911  1.4.8.1  pgoyette 		    goto match_failed;
   1912  1.4.8.1  pgoyette 		}
   1913  1.4.8.1  pgoyette 	      t = &tok[tokidx];
   1914  1.4.8.1  pgoyette 	      break;
   1915  1.4.8.1  pgoyette 
   1916  1.4.8.1  pgoyette 	    default:
   1917  1.4.8.1  pgoyette 	      /* Everything else should have been fake.  */
   1918  1.4.8.1  pgoyette 	      abort ();
   1919  1.4.8.1  pgoyette 	    }
   1920  1.4.8.1  pgoyette 
   1921  1.4.8.1  pgoyette 	  ++tokidx;
   1922      1.3  christos 	}
   1923  1.4.8.1  pgoyette       pr_debug ("opr ");
   1924  1.4.8.1  pgoyette 
   1925  1.4.8.1  pgoyette       /* Setup ready for flag parsing.  */
   1926  1.4.8.1  pgoyette       if (!parse_opcode_flags (opcode, nflgs, first_pflag))
   1927  1.4.8.1  pgoyette 	goto match_failed;
   1928  1.4.8.1  pgoyette 
   1929  1.4.8.1  pgoyette       pr_debug ("flg");
   1930  1.4.8.1  pgoyette       /* Possible match -- did we use all of our input?  */
   1931  1.4.8.1  pgoyette       if (tokidx == ntok)
   1932      1.3  christos 	{
   1933  1.4.8.1  pgoyette 	  *pntok = ntok;
   1934  1.4.8.1  pgoyette 	  pr_debug ("\n");
   1935  1.4.8.1  pgoyette 	  return opcode;
   1936      1.3  christos 	}
   1937  1.4.8.1  pgoyette 
   1938  1.4.8.1  pgoyette     match_failed:;
   1939  1.4.8.1  pgoyette       pr_debug ("\n");
   1940  1.4.8.1  pgoyette       /* Restore the original parameters.  */
   1941  1.4.8.1  pgoyette       memcpy (tok, bktok, MAX_INSN_ARGS * sizeof (*tok));
   1942  1.4.8.1  pgoyette       ntok = bkntok;
   1943      1.1  christos     }
   1944      1.1  christos 
   1945  1.4.8.1  pgoyette   if (*pcpumatch)
   1946  1.4.8.1  pgoyette     *pcpumatch = got_cpu_match;
   1947      1.3  christos 
   1948  1.4.8.1  pgoyette   return NULL;
   1949  1.4.8.1  pgoyette }
   1950      1.3  christos 
   1951  1.4.8.1  pgoyette /* Swap operand tokens.  */
   1952      1.1  christos 
   1953  1.4.8.1  pgoyette static void
   1954  1.4.8.1  pgoyette swap_operand (expressionS *operand_array,
   1955  1.4.8.1  pgoyette 	      unsigned source,
   1956  1.4.8.1  pgoyette 	      unsigned destination)
   1957  1.4.8.1  pgoyette {
   1958  1.4.8.1  pgoyette   expressionS cpy_operand;
   1959  1.4.8.1  pgoyette   expressionS *src_operand;
   1960  1.4.8.1  pgoyette   expressionS *dst_operand;
   1961  1.4.8.1  pgoyette   size_t size;
   1962      1.3  christos 
   1963  1.4.8.1  pgoyette   if (source == destination)
   1964  1.4.8.1  pgoyette     return;
   1965      1.3  christos 
   1966  1.4.8.1  pgoyette   src_operand = &operand_array[source];
   1967  1.4.8.1  pgoyette   dst_operand = &operand_array[destination];
   1968  1.4.8.1  pgoyette   size = sizeof (expressionS);
   1969  1.4.8.1  pgoyette 
   1970  1.4.8.1  pgoyette   /* Make copy of operand to swap with and swap.  */
   1971  1.4.8.1  pgoyette   memcpy (&cpy_operand, dst_operand, size);
   1972  1.4.8.1  pgoyette   memcpy (dst_operand, src_operand, size);
   1973  1.4.8.1  pgoyette   memcpy (src_operand, &cpy_operand, size);
   1974  1.4.8.1  pgoyette }
   1975  1.4.8.1  pgoyette 
   1976  1.4.8.1  pgoyette /* Check if *op matches *tok type.
   1977  1.4.8.1  pgoyette    Returns FALSE if they don't match, TRUE if they match.  */
   1978  1.4.8.1  pgoyette 
   1979  1.4.8.1  pgoyette static bfd_boolean
   1980  1.4.8.1  pgoyette pseudo_operand_match (const expressionS *tok,
   1981  1.4.8.1  pgoyette 		      const struct arc_operand_operation *op)
   1982  1.4.8.1  pgoyette {
   1983  1.4.8.1  pgoyette   offsetT min, max, val;
   1984  1.4.8.1  pgoyette   bfd_boolean ret;
   1985  1.4.8.1  pgoyette   const struct arc_operand *operand_real = &arc_operands[op->operand_idx];
   1986  1.4.8.1  pgoyette 
   1987  1.4.8.1  pgoyette   ret = FALSE;
   1988  1.4.8.1  pgoyette   switch (tok->X_op)
   1989      1.3  christos     {
   1990  1.4.8.1  pgoyette     case O_constant:
   1991  1.4.8.1  pgoyette       if (operand_real->bits == 32 && (operand_real->flags & ARC_OPERAND_LIMM))
   1992  1.4.8.1  pgoyette 	ret = 1;
   1993  1.4.8.1  pgoyette       else if (!(operand_real->flags & ARC_OPERAND_IR))
   1994  1.4.8.1  pgoyette 	{
   1995  1.4.8.1  pgoyette 	  val = tok->X_add_number + op->count;
   1996  1.4.8.1  pgoyette 	  if (operand_real->flags & ARC_OPERAND_SIGNED)
   1997  1.4.8.1  pgoyette 	    {
   1998  1.4.8.1  pgoyette 	      max = (1 << (operand_real->bits - 1)) - 1;
   1999  1.4.8.1  pgoyette 	      min = -(1 << (operand_real->bits - 1));
   2000  1.4.8.1  pgoyette 	    }
   2001  1.4.8.1  pgoyette 	  else
   2002  1.4.8.1  pgoyette 	    {
   2003  1.4.8.1  pgoyette 	      max = (1 << operand_real->bits) - 1;
   2004  1.4.8.1  pgoyette 	      min = 0;
   2005  1.4.8.1  pgoyette 	    }
   2006  1.4.8.1  pgoyette 	  if (min <= val && val <= max)
   2007  1.4.8.1  pgoyette 	    ret = TRUE;
   2008  1.4.8.1  pgoyette 	}
   2009  1.4.8.1  pgoyette       break;
   2010  1.4.8.1  pgoyette 
   2011  1.4.8.1  pgoyette     case O_symbol:
   2012  1.4.8.1  pgoyette       /* Handle all symbols as long immediates or signed 9.  */
   2013  1.4.8.1  pgoyette       if (operand_real->flags & ARC_OPERAND_LIMM ||
   2014  1.4.8.1  pgoyette 	  ((operand_real->flags & ARC_OPERAND_SIGNED) && operand_real->bits == 9))
   2015  1.4.8.1  pgoyette 	ret = TRUE;
   2016      1.1  christos       break;
   2017      1.3  christos 
   2018  1.4.8.1  pgoyette     case O_register:
   2019  1.4.8.1  pgoyette       if (operand_real->flags & ARC_OPERAND_IR)
   2020  1.4.8.1  pgoyette 	ret = TRUE;
   2021      1.1  christos       break;
   2022      1.3  christos 
   2023  1.4.8.1  pgoyette     case O_bracket:
   2024  1.4.8.1  pgoyette       if (operand_real->flags & ARC_OPERAND_BRAKET)
   2025  1.4.8.1  pgoyette 	ret = TRUE;
   2026      1.1  christos       break;
   2027      1.3  christos 
   2028      1.1  christos     default:
   2029  1.4.8.1  pgoyette       /* Unknown.  */
   2030      1.1  christos       break;
   2031      1.3  christos     }
   2032  1.4.8.1  pgoyette   return ret;
   2033  1.4.8.1  pgoyette }
   2034      1.1  christos 
   2035  1.4.8.1  pgoyette /* Find pseudo instruction in array.  */
   2036  1.4.8.1  pgoyette 
   2037  1.4.8.1  pgoyette static const struct arc_pseudo_insn *
   2038  1.4.8.1  pgoyette find_pseudo_insn (const char *opname,
   2039  1.4.8.1  pgoyette 		  int ntok,
   2040  1.4.8.1  pgoyette 		  const expressionS *tok)
   2041  1.4.8.1  pgoyette {
   2042  1.4.8.1  pgoyette   const struct arc_pseudo_insn *pseudo_insn = NULL;
   2043  1.4.8.1  pgoyette   const struct arc_operand_operation *op;
   2044  1.4.8.1  pgoyette   unsigned int i;
   2045  1.4.8.1  pgoyette   int j;
   2046  1.4.8.1  pgoyette 
   2047  1.4.8.1  pgoyette   for (i = 0; i < arc_num_pseudo_insn; ++i)
   2048      1.3  christos     {
   2049  1.4.8.1  pgoyette       pseudo_insn = &arc_pseudo_insns[i];
   2050  1.4.8.1  pgoyette       if (strcmp (pseudo_insn->mnemonic_p, opname) == 0)
   2051  1.4.8.1  pgoyette 	{
   2052  1.4.8.1  pgoyette 	  op = pseudo_insn->operand;
   2053  1.4.8.1  pgoyette 	  for (j = 0; j < ntok; ++j)
   2054  1.4.8.1  pgoyette 	    if (!pseudo_operand_match (&tok[j], &op[j]))
   2055  1.4.8.1  pgoyette 	      break;
   2056  1.4.8.1  pgoyette 
   2057  1.4.8.1  pgoyette 	  /* Found the right instruction.  */
   2058  1.4.8.1  pgoyette 	  if (j == ntok)
   2059  1.4.8.1  pgoyette 	    return pseudo_insn;
   2060  1.4.8.1  pgoyette 	}
   2061      1.3  christos     }
   2062  1.4.8.1  pgoyette   return NULL;
   2063  1.4.8.1  pgoyette }
   2064      1.1  christos 
   2065  1.4.8.1  pgoyette /* Assumes the expressionS *tok is of sufficient size.  */
   2066      1.1  christos 
   2067  1.4.8.1  pgoyette static const struct arc_opcode_hash_entry *
   2068  1.4.8.1  pgoyette find_special_case_pseudo (const char *opname,
   2069  1.4.8.1  pgoyette 			  int *ntok,
   2070  1.4.8.1  pgoyette 			  expressionS *tok,
   2071  1.4.8.1  pgoyette 			  int *nflgs,
   2072  1.4.8.1  pgoyette 			  struct arc_flags *pflags)
   2073  1.4.8.1  pgoyette {
   2074  1.4.8.1  pgoyette   const struct arc_pseudo_insn *pseudo_insn = NULL;
   2075  1.4.8.1  pgoyette   const struct arc_operand_operation *operand_pseudo;
   2076  1.4.8.1  pgoyette   const struct arc_operand *operand_real;
   2077  1.4.8.1  pgoyette   unsigned i;
   2078  1.4.8.1  pgoyette   char construct_operand[MAX_CONSTR_STR];
   2079      1.3  christos 
   2080  1.4.8.1  pgoyette   /* Find whether opname is in pseudo instruction array.  */
   2081  1.4.8.1  pgoyette   pseudo_insn = find_pseudo_insn (opname, *ntok, tok);
   2082      1.1  christos 
   2083  1.4.8.1  pgoyette   if (pseudo_insn == NULL)
   2084  1.4.8.1  pgoyette     return NULL;
   2085      1.1  christos 
   2086  1.4.8.1  pgoyette   /* Handle flag, Limited to one flag at the moment.  */
   2087  1.4.8.1  pgoyette   if (pseudo_insn->flag_r != NULL)
   2088  1.4.8.1  pgoyette     *nflgs += tokenize_flags (pseudo_insn->flag_r, &pflags[*nflgs],
   2089  1.4.8.1  pgoyette 			      MAX_INSN_FLGS - *nflgs);
   2090      1.1  christos 
   2091  1.4.8.1  pgoyette   /* Handle operand operations.  */
   2092  1.4.8.1  pgoyette   for (i = 0; i < pseudo_insn->operand_cnt; ++i)
   2093  1.4.8.1  pgoyette     {
   2094  1.4.8.1  pgoyette       operand_pseudo = &pseudo_insn->operand[i];
   2095  1.4.8.1  pgoyette       operand_real = &arc_operands[operand_pseudo->operand_idx];
   2096      1.3  christos 
   2097  1.4.8.1  pgoyette       if (operand_real->flags & ARC_OPERAND_BRAKET &&
   2098  1.4.8.1  pgoyette 	  !operand_pseudo->needs_insert)
   2099  1.4.8.1  pgoyette 	continue;
   2100      1.3  christos 
   2101  1.4.8.1  pgoyette       /* Has to be inserted (i.e. this token does not exist yet).  */
   2102  1.4.8.1  pgoyette       if (operand_pseudo->needs_insert)
   2103  1.4.8.1  pgoyette 	{
   2104  1.4.8.1  pgoyette 	  if (operand_real->flags & ARC_OPERAND_BRAKET)
   2105  1.4.8.1  pgoyette 	    {
   2106  1.4.8.1  pgoyette 	      tok[i].X_op = O_bracket;
   2107  1.4.8.1  pgoyette 	      ++(*ntok);
   2108  1.4.8.1  pgoyette 	      continue;
   2109  1.4.8.1  pgoyette 	    }
   2110      1.3  christos 
   2111  1.4.8.1  pgoyette 	  /* Check if operand is a register or constant and handle it
   2112  1.4.8.1  pgoyette 	     by type.  */
   2113  1.4.8.1  pgoyette 	  if (operand_real->flags & ARC_OPERAND_IR)
   2114  1.4.8.1  pgoyette 	    snprintf (construct_operand, MAX_CONSTR_STR, "r%d",
   2115  1.4.8.1  pgoyette 		      operand_pseudo->count);
   2116  1.4.8.1  pgoyette 	  else
   2117  1.4.8.1  pgoyette 	    snprintf (construct_operand, MAX_CONSTR_STR, "%d",
   2118  1.4.8.1  pgoyette 		      operand_pseudo->count);
   2119      1.3  christos 
   2120  1.4.8.1  pgoyette 	  tokenize_arguments (construct_operand, &tok[i], 1);
   2121  1.4.8.1  pgoyette 	  ++(*ntok);
   2122  1.4.8.1  pgoyette 	}
   2123      1.1  christos 
   2124  1.4.8.1  pgoyette       else if (operand_pseudo->count)
   2125  1.4.8.1  pgoyette 	{
   2126  1.4.8.1  pgoyette 	  /* Operand number has to be adjusted accordingly (by operand
   2127  1.4.8.1  pgoyette 	     type).  */
   2128  1.4.8.1  pgoyette 	  switch (tok[i].X_op)
   2129  1.4.8.1  pgoyette 	    {
   2130  1.4.8.1  pgoyette 	    case O_constant:
   2131  1.4.8.1  pgoyette 	      tok[i].X_add_number += operand_pseudo->count;
   2132  1.4.8.1  pgoyette 	      break;
   2133      1.1  christos 
   2134  1.4.8.1  pgoyette 	    case O_symbol:
   2135  1.4.8.1  pgoyette 	      break;
   2136      1.1  christos 
   2137  1.4.8.1  pgoyette 	    default:
   2138  1.4.8.1  pgoyette 	      /* Ignored.  */
   2139  1.4.8.1  pgoyette 	      break;
   2140  1.4.8.1  pgoyette 	    }
   2141  1.4.8.1  pgoyette 	}
   2142      1.1  christos     }
   2143      1.1  christos 
   2144  1.4.8.1  pgoyette   /* Swap operands if necessary.  Only supports one swap at the
   2145  1.4.8.1  pgoyette      moment.  */
   2146  1.4.8.1  pgoyette   for (i = 0; i < pseudo_insn->operand_cnt; ++i)
   2147      1.1  christos     {
   2148  1.4.8.1  pgoyette       operand_pseudo = &pseudo_insn->operand[i];
   2149  1.4.8.1  pgoyette 
   2150  1.4.8.1  pgoyette       if (operand_pseudo->swap_operand_idx == i)
   2151  1.4.8.1  pgoyette 	continue;
   2152  1.4.8.1  pgoyette 
   2153  1.4.8.1  pgoyette       swap_operand (tok, i, operand_pseudo->swap_operand_idx);
   2154  1.4.8.1  pgoyette 
   2155  1.4.8.1  pgoyette       /* Prevent a swap back later by breaking out.  */
   2156  1.4.8.1  pgoyette       break;
   2157      1.1  christos     }
   2158  1.4.8.1  pgoyette 
   2159  1.4.8.1  pgoyette   return arc_find_opcode (pseudo_insn->mnemonic_r);
   2160  1.4.8.1  pgoyette }
   2161  1.4.8.1  pgoyette 
   2162  1.4.8.1  pgoyette static const struct arc_opcode_hash_entry *
   2163  1.4.8.1  pgoyette find_special_case_flag (const char *opname,
   2164  1.4.8.1  pgoyette 			int *nflgs,
   2165  1.4.8.1  pgoyette 			struct arc_flags *pflags)
   2166  1.4.8.1  pgoyette {
   2167  1.4.8.1  pgoyette   unsigned int i;
   2168  1.4.8.1  pgoyette   const char *flagnm;
   2169  1.4.8.1  pgoyette   unsigned flag_idx, flag_arr_idx;
   2170  1.4.8.1  pgoyette   size_t flaglen, oplen;
   2171  1.4.8.1  pgoyette   const struct arc_flag_special *arc_flag_special_opcode;
   2172  1.4.8.1  pgoyette   const struct arc_opcode_hash_entry *entry;
   2173  1.4.8.1  pgoyette 
   2174  1.4.8.1  pgoyette   /* Search for special case instruction.  */
   2175  1.4.8.1  pgoyette   for (i = 0; i < arc_num_flag_special; i++)
   2176      1.1  christos     {
   2177  1.4.8.1  pgoyette       arc_flag_special_opcode = &arc_flag_special_cases[i];
   2178  1.4.8.1  pgoyette       oplen = strlen (arc_flag_special_opcode->name);
   2179  1.4.8.1  pgoyette 
   2180  1.4.8.1  pgoyette       if (strncmp (opname, arc_flag_special_opcode->name, oplen) != 0)
   2181  1.4.8.1  pgoyette 	continue;
   2182  1.4.8.1  pgoyette 
   2183  1.4.8.1  pgoyette       /* Found a potential special case instruction, now test for
   2184  1.4.8.1  pgoyette 	 flags.  */
   2185  1.4.8.1  pgoyette       for (flag_arr_idx = 0;; ++flag_arr_idx)
   2186      1.3  christos 	{
   2187  1.4.8.1  pgoyette 	  flag_idx = arc_flag_special_opcode->flags[flag_arr_idx];
   2188  1.4.8.1  pgoyette 	  if (flag_idx == 0)
   2189  1.4.8.1  pgoyette 	    break;  /* End of array, nothing found.  */
   2190  1.4.8.1  pgoyette 
   2191  1.4.8.1  pgoyette 	  flagnm = arc_flag_operands[flag_idx].name;
   2192  1.4.8.1  pgoyette 	  flaglen = strlen (flagnm);
   2193  1.4.8.1  pgoyette 	  if (strcmp (opname + oplen, flagnm) == 0)
   2194  1.4.8.1  pgoyette 	    {
   2195  1.4.8.1  pgoyette               entry = arc_find_opcode (arc_flag_special_opcode->name);
   2196  1.4.8.1  pgoyette 
   2197  1.4.8.1  pgoyette 	      if (*nflgs + 1 > MAX_INSN_FLGS)
   2198  1.4.8.1  pgoyette 		break;
   2199  1.4.8.1  pgoyette 	      memcpy (pflags[*nflgs].name, flagnm, flaglen);
   2200  1.4.8.1  pgoyette 	      pflags[*nflgs].name[flaglen] = '\0';
   2201  1.4.8.1  pgoyette 	      (*nflgs)++;
   2202  1.4.8.1  pgoyette 	      return entry;
   2203  1.4.8.1  pgoyette 	    }
   2204      1.3  christos 	}
   2205      1.1  christos     }
   2206  1.4.8.1  pgoyette   return NULL;
   2207  1.4.8.1  pgoyette }
   2208      1.1  christos 
   2209  1.4.8.1  pgoyette /* The long instructions are not stored in a hash (there's not many of
   2210  1.4.8.1  pgoyette    them) and so there's no arc_opcode_hash_entry structure to return.  This
   2211  1.4.8.1  pgoyette    helper function for find_special_case_long_opcode takes an arc_opcode
   2212  1.4.8.1  pgoyette    result and places it into a fake arc_opcode_hash_entry that points to
   2213  1.4.8.1  pgoyette    the single arc_opcode OPCODE, which is then returned.  */
   2214  1.4.8.1  pgoyette 
   2215  1.4.8.1  pgoyette static const struct arc_opcode_hash_entry *
   2216  1.4.8.1  pgoyette build_fake_opcode_hash_entry (const struct arc_opcode *opcode)
   2217  1.4.8.1  pgoyette {
   2218  1.4.8.1  pgoyette   static struct arc_opcode_hash_entry entry;
   2219  1.4.8.1  pgoyette   static struct arc_opcode tmp[2];
   2220  1.4.8.1  pgoyette   static const struct arc_opcode *ptr[2];
   2221  1.4.8.1  pgoyette 
   2222  1.4.8.1  pgoyette   memcpy (&tmp[0], opcode, sizeof (struct arc_opcode));
   2223  1.4.8.1  pgoyette   memset (&tmp[1], 0, sizeof (struct arc_opcode));
   2224  1.4.8.1  pgoyette   entry.count = 1;
   2225  1.4.8.1  pgoyette   entry.opcode = ptr;
   2226  1.4.8.1  pgoyette   ptr[0] = tmp;
   2227  1.4.8.1  pgoyette   ptr[1] = NULL;
   2228  1.4.8.1  pgoyette   return &entry;
   2229      1.3  christos }
   2230      1.3  christos 
   2231      1.3  christos 
   2232  1.4.8.1  pgoyette /* Used by the assembler to match the list of tokens against a long (48 or
   2233  1.4.8.1  pgoyette    64 bits) instruction.  If a matching long instruction is found, then
   2234  1.4.8.1  pgoyette    some of the tokens are consumed in this function and converted into a
   2235  1.4.8.1  pgoyette    single LIMM value, which is then added to the end of the token list,
   2236  1.4.8.1  pgoyette    where it will be consumed by a LIMM operand that exists in the base
   2237  1.4.8.1  pgoyette    opcode of the long instruction.  */
   2238  1.4.8.1  pgoyette 
   2239  1.4.8.1  pgoyette static const struct arc_opcode_hash_entry *
   2240  1.4.8.1  pgoyette find_special_case_long_opcode (const char *opname,
   2241  1.4.8.1  pgoyette                                int *ntok ATTRIBUTE_UNUSED,
   2242  1.4.8.1  pgoyette                                expressionS *tok ATTRIBUTE_UNUSED,
   2243  1.4.8.1  pgoyette                                int *nflgs,
   2244  1.4.8.1  pgoyette                                struct arc_flags *pflags)
   2245  1.4.8.1  pgoyette {
   2246  1.4.8.1  pgoyette   unsigned i;
   2247      1.3  christos 
   2248  1.4.8.1  pgoyette   if (*ntok == MAX_INSN_ARGS)
   2249  1.4.8.1  pgoyette     return NULL;
   2250      1.3  christos 
   2251  1.4.8.1  pgoyette   for (i = 0; i < arc_num_long_opcodes; ++i)
   2252  1.4.8.1  pgoyette     {
   2253  1.4.8.1  pgoyette       struct arc_opcode fake_opcode;
   2254  1.4.8.1  pgoyette       const struct arc_opcode *opcode;
   2255  1.4.8.1  pgoyette       struct arc_insn insn;
   2256  1.4.8.1  pgoyette       expressionS *limm_token;
   2257      1.3  christos 
   2258  1.4.8.1  pgoyette       opcode = &arc_long_opcodes[i].base_opcode;
   2259      1.3  christos 
   2260  1.4.8.1  pgoyette       if (!(opcode->cpu & arc_target))
   2261  1.4.8.1  pgoyette         continue;
   2262      1.3  christos 
   2263  1.4.8.1  pgoyette       if (!check_cpu_feature (opcode->subclass))
   2264  1.4.8.1  pgoyette         continue;
   2265      1.1  christos 
   2266  1.4.8.1  pgoyette       if (strcmp (opname, opcode->name) != 0)
   2267  1.4.8.1  pgoyette         continue;
   2268  1.4.8.1  pgoyette 
   2269  1.4.8.1  pgoyette       /* Check that the flags are a match.  */
   2270  1.4.8.1  pgoyette       if (!parse_opcode_flags (opcode, *nflgs, pflags))
   2271  1.4.8.1  pgoyette         continue;
   2272  1.4.8.1  pgoyette 
   2273  1.4.8.1  pgoyette       /* Parse the LIMM operands into the LIMM template.  */
   2274  1.4.8.1  pgoyette       memset (&fake_opcode, 0, sizeof (fake_opcode));
   2275  1.4.8.1  pgoyette       fake_opcode.name = "fake limm";
   2276  1.4.8.1  pgoyette       fake_opcode.opcode = arc_long_opcodes[i].limm_template;
   2277  1.4.8.1  pgoyette       fake_opcode.mask = arc_long_opcodes[i].limm_mask;
   2278  1.4.8.1  pgoyette       fake_opcode.cpu = opcode->cpu;
   2279  1.4.8.1  pgoyette       fake_opcode.insn_class = opcode->insn_class;
   2280  1.4.8.1  pgoyette       fake_opcode.subclass = opcode->subclass;
   2281  1.4.8.1  pgoyette       memcpy (&fake_opcode.operands[0],
   2282  1.4.8.1  pgoyette               &arc_long_opcodes[i].operands,
   2283  1.4.8.1  pgoyette               MAX_INSN_ARGS);
   2284  1.4.8.1  pgoyette       /* Leave fake_opcode.flags as zero.  */
   2285  1.4.8.1  pgoyette 
   2286  1.4.8.1  pgoyette       pr_debug ("Calling assemble_insn to build fake limm value\n");
   2287  1.4.8.1  pgoyette       assemble_insn (&fake_opcode, tok, *ntok,
   2288  1.4.8.1  pgoyette                      NULL, 0, &insn);
   2289  1.4.8.1  pgoyette       pr_debug ("   got limm value: 0x%x\n", insn.insn);
   2290  1.4.8.1  pgoyette 
   2291  1.4.8.1  pgoyette       /* Now create a new token at the end of the token array (We know this
   2292  1.4.8.1  pgoyette          is safe as the token array is always created with enough space for
   2293  1.4.8.1  pgoyette          MAX_INSN_ARGS, and we check at the start at the start of this
   2294  1.4.8.1  pgoyette          function that we're not there yet).  This new token will
   2295  1.4.8.1  pgoyette          correspond to a LIMM operand that will be contained in the
   2296  1.4.8.1  pgoyette          base_opcode of the arc_long_opcode.  */
   2297  1.4.8.1  pgoyette       limm_token = &tok[(*ntok)];
   2298  1.4.8.1  pgoyette       (*ntok)++;
   2299  1.4.8.1  pgoyette 
   2300  1.4.8.1  pgoyette       /* Modify the LIMM token to hold the constant.  */
   2301  1.4.8.1  pgoyette       limm_token->X_op = O_constant;
   2302  1.4.8.1  pgoyette       limm_token->X_add_number = insn.insn;
   2303  1.4.8.1  pgoyette 
   2304  1.4.8.1  pgoyette       /* Return the base opcode.  */
   2305  1.4.8.1  pgoyette       return build_fake_opcode_hash_entry (opcode);
   2306  1.4.8.1  pgoyette     }
   2307  1.4.8.1  pgoyette 
   2308  1.4.8.1  pgoyette     return NULL;
   2309      1.1  christos }
   2310      1.1  christos 
   2311  1.4.8.1  pgoyette /* Used to find special case opcode.  */
   2312      1.3  christos 
   2313  1.4.8.1  pgoyette static const struct arc_opcode_hash_entry *
   2314  1.4.8.1  pgoyette find_special_case (const char *opname,
   2315  1.4.8.1  pgoyette 		   int *nflgs,
   2316  1.4.8.1  pgoyette 		   struct arc_flags *pflags,
   2317  1.4.8.1  pgoyette 		   expressionS *tok,
   2318  1.4.8.1  pgoyette 		   int *ntok)
   2319      1.1  christos {
   2320  1.4.8.1  pgoyette   const struct arc_opcode_hash_entry *entry;
   2321      1.3  christos 
   2322  1.4.8.1  pgoyette   entry = find_special_case_pseudo (opname, ntok, tok, nflgs, pflags);
   2323      1.1  christos 
   2324  1.4.8.1  pgoyette   if (entry == NULL)
   2325  1.4.8.1  pgoyette     entry = find_special_case_flag (opname, nflgs, pflags);
   2326      1.3  christos 
   2327  1.4.8.1  pgoyette   if (entry == NULL)
   2328  1.4.8.1  pgoyette     entry = find_special_case_long_opcode (opname, ntok, tok, nflgs, pflags);
   2329      1.3  christos 
   2330  1.4.8.1  pgoyette   return entry;
   2331  1.4.8.1  pgoyette }
   2332      1.1  christos 
   2333  1.4.8.1  pgoyette /* Given an opcode name, pre-tockenized set of argumenst and the
   2334  1.4.8.1  pgoyette    opcode flags, take it all the way through emission.  */
   2335      1.1  christos 
   2336  1.4.8.1  pgoyette static void
   2337  1.4.8.1  pgoyette assemble_tokens (const char *opname,
   2338  1.4.8.1  pgoyette 		 expressionS *tok,
   2339  1.4.8.1  pgoyette 		 int ntok,
   2340  1.4.8.1  pgoyette 		 struct arc_flags *pflags,
   2341  1.4.8.1  pgoyette 		 int nflgs)
   2342  1.4.8.1  pgoyette {
   2343  1.4.8.1  pgoyette   bfd_boolean found_something = FALSE;
   2344  1.4.8.1  pgoyette   const struct arc_opcode_hash_entry *entry;
   2345  1.4.8.1  pgoyette   int cpumatch = 1;
   2346      1.3  christos 
   2347  1.4.8.1  pgoyette   /* Search opcodes.  */
   2348  1.4.8.1  pgoyette   entry = arc_find_opcode (opname);
   2349      1.1  christos 
   2350  1.4.8.1  pgoyette   /* Couldn't find opcode conventional way, try special cases.  */
   2351  1.4.8.1  pgoyette   if (entry == NULL)
   2352  1.4.8.1  pgoyette     entry = find_special_case (opname, &nflgs, pflags, tok, &ntok);
   2353  1.4.8.1  pgoyette 
   2354  1.4.8.1  pgoyette   if (entry != NULL)
   2355      1.1  christos     {
   2356  1.4.8.1  pgoyette       const struct arc_opcode *opcode;
   2357  1.4.8.1  pgoyette 
   2358  1.4.8.1  pgoyette       pr_debug ("%s:%d: assemble_tokens: %s\n",
   2359  1.4.8.1  pgoyette 		frag_now->fr_file, frag_now->fr_line, opname);
   2360  1.4.8.1  pgoyette       found_something = TRUE;
   2361  1.4.8.1  pgoyette       opcode = find_opcode_match (entry, tok, &ntok, pflags,
   2362  1.4.8.1  pgoyette 				  nflgs, &cpumatch);
   2363  1.4.8.1  pgoyette       if (opcode != NULL)
   2364      1.3  christos 	{
   2365  1.4.8.1  pgoyette 	  struct arc_insn insn;
   2366  1.4.8.1  pgoyette 
   2367  1.4.8.1  pgoyette 	  assemble_insn (opcode, tok, ntok, pflags, nflgs, &insn);
   2368  1.4.8.1  pgoyette 	  emit_insn (&insn);
   2369  1.4.8.1  pgoyette 	  return;
   2370      1.3  christos 	}
   2371      1.1  christos     }
   2372      1.1  christos 
   2373  1.4.8.1  pgoyette   if (found_something)
   2374  1.4.8.1  pgoyette     {
   2375  1.4.8.1  pgoyette       if (cpumatch)
   2376  1.4.8.1  pgoyette 	as_bad (_("inappropriate arguments for opcode '%s'"), opname);
   2377  1.4.8.1  pgoyette       else
   2378  1.4.8.1  pgoyette 	as_bad (_("opcode '%s' not supported for target %s"), opname,
   2379  1.4.8.1  pgoyette 		arc_target_name);
   2380  1.4.8.1  pgoyette     }
   2381  1.4.8.1  pgoyette   else
   2382  1.4.8.1  pgoyette     as_bad (_("unknown opcode '%s'"), opname);
   2383      1.1  christos }
   2384      1.1  christos 
   2385  1.4.8.1  pgoyette /* The public interface to the instruction assembler.  */
   2386      1.1  christos 
   2387      1.1  christos void
   2388  1.4.8.1  pgoyette md_assemble (char *str)
   2389      1.1  christos {
   2390  1.4.8.1  pgoyette   char *opname;
   2391  1.4.8.1  pgoyette   expressionS tok[MAX_INSN_ARGS];
   2392  1.4.8.1  pgoyette   int ntok, nflg;
   2393  1.4.8.1  pgoyette   size_t opnamelen;
   2394  1.4.8.1  pgoyette   struct arc_flags flags[MAX_INSN_FLGS];
   2395      1.1  christos 
   2396  1.4.8.1  pgoyette   /* Split off the opcode.  */
   2397  1.4.8.1  pgoyette   opnamelen = strspn (str, "abcdefghijklmnopqrstuvwxyz_0123468");
   2398  1.4.8.1  pgoyette   opname = xmemdup0 (str, opnamelen);
   2399      1.1  christos 
   2400  1.4.8.1  pgoyette   /* Signalize we are assmbling the instructions.  */
   2401  1.4.8.1  pgoyette   assembling_insn = TRUE;
   2402      1.3  christos 
   2403  1.4.8.1  pgoyette   /* Tokenize the flags.  */
   2404  1.4.8.1  pgoyette   if ((nflg = tokenize_flags (str + opnamelen, flags, MAX_INSN_FLGS)) == -1)
   2405  1.4.8.1  pgoyette     {
   2406  1.4.8.1  pgoyette       as_bad (_("syntax error"));
   2407  1.4.8.1  pgoyette       return;
   2408      1.3  christos     }
   2409      1.1  christos 
   2410  1.4.8.1  pgoyette   /* Scan up to the end of the mnemonic which must end in space or end
   2411  1.4.8.1  pgoyette      of string.  */
   2412  1.4.8.1  pgoyette   str += opnamelen;
   2413  1.4.8.1  pgoyette   for (; *str != '\0'; str++)
   2414  1.4.8.1  pgoyette     if (*str == ' ')
   2415  1.4.8.1  pgoyette       break;
   2416      1.1  christos 
   2417  1.4.8.1  pgoyette   /* Tokenize the rest of the line.  */
   2418  1.4.8.1  pgoyette   if ((ntok = tokenize_arguments (str, tok, MAX_INSN_ARGS)) < 0)
   2419      1.3  christos     {
   2420  1.4.8.1  pgoyette       as_bad (_("syntax error"));
   2421  1.4.8.1  pgoyette       return;
   2422      1.3  christos     }
   2423  1.4.8.1  pgoyette 
   2424  1.4.8.1  pgoyette   /* Finish it off.  */
   2425  1.4.8.1  pgoyette   assemble_tokens (opname, tok, ntok, flags, nflg);
   2426  1.4.8.1  pgoyette   assembling_insn = FALSE;
   2427      1.1  christos }
   2428      1.1  christos 
   2429  1.4.8.1  pgoyette /* Callback to insert a register into the hash table.  */
   2430      1.1  christos 
   2431  1.4.8.1  pgoyette static void
   2432  1.4.8.1  pgoyette declare_register (const char *name, int number)
   2433      1.1  christos {
   2434  1.4.8.1  pgoyette   const char *err;
   2435  1.4.8.1  pgoyette   symbolS *regS = symbol_create (name, reg_section,
   2436  1.4.8.1  pgoyette 				 number, &zero_address_frag);
   2437      1.3  christos 
   2438  1.4.8.1  pgoyette   err = hash_insert (arc_reg_hash, S_GET_NAME (regS), (void *) regS);
   2439  1.4.8.1  pgoyette   if (err)
   2440  1.4.8.1  pgoyette     as_fatal (_("Inserting \"%s\" into register table failed: %s"),
   2441  1.4.8.1  pgoyette 	      name, err);
   2442  1.4.8.1  pgoyette }
   2443      1.3  christos 
   2444  1.4.8.1  pgoyette /* Construct symbols for each of the general registers.  */
   2445      1.1  christos 
   2446  1.4.8.1  pgoyette static void
   2447  1.4.8.1  pgoyette declare_register_set (void)
   2448  1.4.8.1  pgoyette {
   2449  1.4.8.1  pgoyette   int i;
   2450  1.4.8.1  pgoyette   for (i = 0; i < 64; ++i)
   2451      1.1  christos     {
   2452  1.4.8.1  pgoyette       char name[7];
   2453  1.4.8.1  pgoyette 
   2454  1.4.8.1  pgoyette       sprintf (name, "r%d", i);
   2455  1.4.8.1  pgoyette       declare_register (name, i);
   2456  1.4.8.1  pgoyette       if ((i & 0x01) == 0)
   2457  1.4.8.1  pgoyette 	{
   2458  1.4.8.1  pgoyette 	  sprintf (name, "r%dr%d", i, i+1);
   2459  1.4.8.1  pgoyette 	  declare_register (name, i);
   2460  1.4.8.1  pgoyette 	}
   2461      1.1  christos     }
   2462      1.1  christos }
   2463      1.1  christos 
   2464  1.4.8.1  pgoyette /* Port-specific assembler initialization.  This function is called
   2465  1.4.8.1  pgoyette    once, at assembler startup time.  */
   2466  1.4.8.1  pgoyette 
   2467  1.4.8.1  pgoyette void
   2468  1.4.8.1  pgoyette md_begin (void)
   2469  1.4.8.1  pgoyette {
   2470  1.4.8.1  pgoyette   const struct arc_opcode *opcode = arc_opcodes;
   2471  1.4.8.1  pgoyette 
   2472  1.4.8.1  pgoyette   if (!mach_type_specified_p)
   2473  1.4.8.1  pgoyette     arc_select_cpu (TARGET_WITH_CPU);
   2474      1.1  christos 
   2475  1.4.8.1  pgoyette   /* The endianness can be chosen "at the factory".  */
   2476  1.4.8.1  pgoyette   target_big_endian = byte_order == BIG_ENDIAN;
   2477      1.1  christos 
   2478  1.4.8.1  pgoyette   if (!bfd_set_arch_mach (stdoutput, bfd_arch_arc, arc_mach_type))
   2479  1.4.8.1  pgoyette     as_warn (_("could not set architecture and machine"));
   2480      1.1  christos 
   2481  1.4.8.1  pgoyette   /* Set elf header flags.  */
   2482  1.4.8.1  pgoyette   bfd_set_private_flags (stdoutput, arc_eflag);
   2483      1.3  christos 
   2484  1.4.8.1  pgoyette   /* Set up a hash table for the instructions.  */
   2485  1.4.8.1  pgoyette   arc_opcode_hash = hash_new ();
   2486  1.4.8.1  pgoyette   if (arc_opcode_hash == NULL)
   2487  1.4.8.1  pgoyette     as_fatal (_("Virtual memory exhausted"));
   2488      1.3  christos 
   2489  1.4.8.1  pgoyette   /* Initialize the hash table with the insns.  */
   2490  1.4.8.1  pgoyette   do
   2491      1.3  christos     {
   2492  1.4.8.1  pgoyette       const char *name = opcode->name;
   2493      1.3  christos 
   2494  1.4.8.1  pgoyette       arc_insert_opcode (opcode);
   2495      1.1  christos 
   2496  1.4.8.1  pgoyette       while (++opcode && opcode->name
   2497  1.4.8.1  pgoyette 	     && (opcode->name == name
   2498  1.4.8.1  pgoyette 		 || !strcmp (opcode->name, name)))
   2499  1.4.8.1  pgoyette 	continue;
   2500  1.4.8.1  pgoyette     }while (opcode->name);
   2501      1.3  christos 
   2502  1.4.8.1  pgoyette   /* Register declaration.  */
   2503  1.4.8.1  pgoyette   arc_reg_hash = hash_new ();
   2504  1.4.8.1  pgoyette   if (arc_reg_hash == NULL)
   2505  1.4.8.1  pgoyette     as_fatal (_("Virtual memory exhausted"));
   2506      1.3  christos 
   2507  1.4.8.1  pgoyette   declare_register_set ();
   2508  1.4.8.1  pgoyette   declare_register ("gp", 26);
   2509  1.4.8.1  pgoyette   declare_register ("fp", 27);
   2510  1.4.8.1  pgoyette   declare_register ("sp", 28);
   2511  1.4.8.1  pgoyette   declare_register ("ilink", 29);
   2512  1.4.8.1  pgoyette   declare_register ("ilink1", 29);
   2513  1.4.8.1  pgoyette   declare_register ("ilink2", 30);
   2514  1.4.8.1  pgoyette   declare_register ("blink", 31);
   2515      1.1  christos 
   2516  1.4.8.1  pgoyette   /* XY memory registers.  */
   2517  1.4.8.1  pgoyette   declare_register ("x0_u0", 32);
   2518  1.4.8.1  pgoyette   declare_register ("x0_u1", 33);
   2519  1.4.8.1  pgoyette   declare_register ("x1_u0", 34);
   2520  1.4.8.1  pgoyette   declare_register ("x1_u1", 35);
   2521  1.4.8.1  pgoyette   declare_register ("x2_u0", 36);
   2522  1.4.8.1  pgoyette   declare_register ("x2_u1", 37);
   2523  1.4.8.1  pgoyette   declare_register ("x3_u0", 38);
   2524  1.4.8.1  pgoyette   declare_register ("x3_u1", 39);
   2525  1.4.8.1  pgoyette   declare_register ("y0_u0", 40);
   2526  1.4.8.1  pgoyette   declare_register ("y0_u1", 41);
   2527  1.4.8.1  pgoyette   declare_register ("y1_u0", 42);
   2528  1.4.8.1  pgoyette   declare_register ("y1_u1", 43);
   2529  1.4.8.1  pgoyette   declare_register ("y2_u0", 44);
   2530  1.4.8.1  pgoyette   declare_register ("y2_u1", 45);
   2531  1.4.8.1  pgoyette   declare_register ("y3_u0", 46);
   2532  1.4.8.1  pgoyette   declare_register ("y3_u1", 47);
   2533  1.4.8.1  pgoyette   declare_register ("x0_nu", 48);
   2534  1.4.8.1  pgoyette   declare_register ("x1_nu", 49);
   2535  1.4.8.1  pgoyette   declare_register ("x2_nu", 50);
   2536  1.4.8.1  pgoyette   declare_register ("x3_nu", 51);
   2537  1.4.8.1  pgoyette   declare_register ("y0_nu", 52);
   2538  1.4.8.1  pgoyette   declare_register ("y1_nu", 53);
   2539  1.4.8.1  pgoyette   declare_register ("y2_nu", 54);
   2540  1.4.8.1  pgoyette   declare_register ("y3_nu", 55);
   2541      1.1  christos 
   2542  1.4.8.1  pgoyette   declare_register ("mlo", 57);
   2543  1.4.8.1  pgoyette   declare_register ("mmid", 58);
   2544  1.4.8.1  pgoyette   declare_register ("mhi", 59);
   2545      1.1  christos 
   2546  1.4.8.1  pgoyette   declare_register ("acc1", 56);
   2547  1.4.8.1  pgoyette   declare_register ("acc2", 57);
   2548      1.1  christos 
   2549  1.4.8.1  pgoyette   declare_register ("lp_count", 60);
   2550  1.4.8.1  pgoyette   declare_register ("pcl", 63);
   2551      1.1  christos 
   2552  1.4.8.1  pgoyette   /* Initialize the last instructions.  */
   2553  1.4.8.1  pgoyette   memset (&arc_last_insns[0], 0, sizeof (arc_last_insns));
   2554      1.1  christos 
   2555  1.4.8.1  pgoyette   /* Aux register declaration.  */
   2556  1.4.8.1  pgoyette   arc_aux_hash = hash_new ();
   2557  1.4.8.1  pgoyette   if (arc_aux_hash == NULL)
   2558  1.4.8.1  pgoyette     as_fatal (_("Virtual memory exhausted"));
   2559      1.1  christos 
   2560  1.4.8.1  pgoyette   const struct arc_aux_reg *auxr = &arc_aux_regs[0];
   2561  1.4.8.1  pgoyette   unsigned int i;
   2562  1.4.8.1  pgoyette   for (i = 0; i < arc_num_aux_regs; i++, auxr++)
   2563  1.4.8.1  pgoyette     {
   2564  1.4.8.1  pgoyette       const char *retval;
   2565      1.1  christos 
   2566  1.4.8.1  pgoyette       if (!(auxr->cpu & arc_target))
   2567  1.4.8.1  pgoyette 	continue;
   2568      1.1  christos 
   2569  1.4.8.1  pgoyette       if ((auxr->subclass != NONE)
   2570  1.4.8.1  pgoyette 	  && !check_cpu_feature (auxr->subclass))
   2571  1.4.8.1  pgoyette 	continue;
   2572      1.1  christos 
   2573  1.4.8.1  pgoyette       retval = hash_insert (arc_aux_hash, auxr->name, (void *) auxr);
   2574  1.4.8.1  pgoyette       if (retval)
   2575  1.4.8.1  pgoyette 	as_fatal (_("internal error: can't hash aux register '%s': %s"),
   2576  1.4.8.1  pgoyette 		  auxr->name, retval);
   2577      1.1  christos     }
   2578      1.1  christos }
   2579      1.1  christos 
   2580  1.4.8.1  pgoyette /* Write a value out to the object file, using the appropriate
   2581  1.4.8.1  pgoyette    endianness.  */
   2582  1.4.8.1  pgoyette 
   2583      1.1  christos void
   2584  1.4.8.1  pgoyette md_number_to_chars (char *buf,
   2585  1.4.8.1  pgoyette 		    valueT val,
   2586  1.4.8.1  pgoyette 		    int n)
   2587      1.1  christos {
   2588  1.4.8.1  pgoyette   if (target_big_endian)
   2589  1.4.8.1  pgoyette     number_to_chars_bigendian (buf, val, n);
   2590  1.4.8.1  pgoyette   else
   2591  1.4.8.1  pgoyette     number_to_chars_littleendian (buf, val, n);
   2592  1.4.8.1  pgoyette }
   2593      1.1  christos 
   2594  1.4.8.1  pgoyette /* Round up a section size to the appropriate boundary.  */
   2595      1.3  christos 
   2596  1.4.8.1  pgoyette valueT
   2597  1.4.8.1  pgoyette md_section_align (segT segment,
   2598  1.4.8.1  pgoyette 		  valueT size)
   2599  1.4.8.1  pgoyette {
   2600  1.4.8.1  pgoyette   int align = bfd_get_section_alignment (stdoutput, segment);
   2601  1.4.8.1  pgoyette 
   2602  1.4.8.1  pgoyette   return ((size + (1 << align) - 1) & (-((valueT) 1 << align)));
   2603      1.3  christos }
   2604      1.1  christos 
   2605  1.4.8.1  pgoyette /* The location from which a PC relative jump should be calculated,
   2606  1.4.8.1  pgoyette    given a PC relative reloc.  */
   2607  1.4.8.1  pgoyette 
   2608  1.4.8.1  pgoyette long
   2609  1.4.8.1  pgoyette md_pcrel_from_section (fixS *fixP,
   2610  1.4.8.1  pgoyette 		       segT sec)
   2611      1.3  christos {
   2612  1.4.8.1  pgoyette   offsetT base = fixP->fx_where + fixP->fx_frag->fr_address;
   2613  1.4.8.1  pgoyette 
   2614  1.4.8.1  pgoyette   pr_debug ("pcrel_from_section, fx_offset = %d\n", (int) fixP->fx_offset);
   2615  1.4.8.1  pgoyette 
   2616  1.4.8.1  pgoyette   if (fixP->fx_addsy != (symbolS *) NULL
   2617  1.4.8.1  pgoyette       && (!S_IS_DEFINED (fixP->fx_addsy)
   2618  1.4.8.1  pgoyette 	  || S_GET_SEGMENT (fixP->fx_addsy) != sec))
   2619  1.4.8.1  pgoyette     {
   2620  1.4.8.1  pgoyette       pr_debug ("Unknown pcrel symbol: %s\n", S_GET_NAME (fixP->fx_addsy));
   2621  1.4.8.1  pgoyette 
   2622  1.4.8.1  pgoyette       /* The symbol is undefined (or is defined but not in this section).
   2623  1.4.8.1  pgoyette 	 Let the linker figure it out.  */
   2624  1.4.8.1  pgoyette       return 0;
   2625  1.4.8.1  pgoyette     }
   2626      1.3  christos 
   2627  1.4.8.1  pgoyette   if ((int) fixP->fx_r_type < 0)
   2628  1.4.8.1  pgoyette     {
   2629  1.4.8.1  pgoyette       /* These are the "internal" relocations.  Align them to
   2630  1.4.8.1  pgoyette 	 32 bit boundary (PCL), for the moment.  */
   2631  1.4.8.1  pgoyette       base &= ~3;
   2632  1.4.8.1  pgoyette     }
   2633  1.4.8.1  pgoyette   else
   2634      1.3  christos     {
   2635  1.4.8.1  pgoyette       switch (fixP->fx_r_type)
   2636      1.3  christos 	{
   2637  1.4.8.1  pgoyette 	case BFD_RELOC_ARC_PC32:
   2638  1.4.8.1  pgoyette 	  /* The hardware calculates relative to the start of the
   2639  1.4.8.1  pgoyette 	     insn, but this relocation is relative to location of the
   2640  1.4.8.1  pgoyette 	     LIMM, compensate.  The base always needs to be
   2641  1.4.8.1  pgoyette 	     substracted by 4 as we do not support this type of PCrel
   2642  1.4.8.1  pgoyette 	     relocation for short instructions.  */
   2643  1.4.8.1  pgoyette 	  base -= 4;
   2644  1.4.8.1  pgoyette 	  /* Fall through.  */
   2645  1.4.8.1  pgoyette 	case BFD_RELOC_ARC_PLT32:
   2646  1.4.8.1  pgoyette 	case BFD_RELOC_ARC_S25H_PCREL_PLT:
   2647  1.4.8.1  pgoyette 	case BFD_RELOC_ARC_S21H_PCREL_PLT:
   2648  1.4.8.1  pgoyette 	case BFD_RELOC_ARC_S25W_PCREL_PLT:
   2649  1.4.8.1  pgoyette 	case BFD_RELOC_ARC_S21W_PCREL_PLT:
   2650      1.3  christos 
   2651  1.4.8.1  pgoyette 	case BFD_RELOC_ARC_S21H_PCREL:
   2652  1.4.8.1  pgoyette 	case BFD_RELOC_ARC_S25H_PCREL:
   2653  1.4.8.1  pgoyette 	case BFD_RELOC_ARC_S13_PCREL:
   2654  1.4.8.1  pgoyette 	case BFD_RELOC_ARC_S21W_PCREL:
   2655  1.4.8.1  pgoyette 	case BFD_RELOC_ARC_S25W_PCREL:
   2656  1.4.8.1  pgoyette 	  base &= ~3;
   2657      1.3  christos 	  break;
   2658      1.3  christos 	default:
   2659  1.4.8.1  pgoyette 	  as_bad_where (fixP->fx_file, fixP->fx_line,
   2660  1.4.8.1  pgoyette 			_("unhandled reloc %s in md_pcrel_from_section"),
   2661  1.4.8.1  pgoyette 		  bfd_get_reloc_code_name (fixP->fx_r_type));
   2662      1.3  christos 	  break;
   2663      1.3  christos 	}
   2664      1.1  christos     }
   2665  1.4.8.1  pgoyette 
   2666  1.4.8.1  pgoyette   pr_debug ("pcrel from %"BFD_VMA_FMT"x + %lx = %"BFD_VMA_FMT"x, "
   2667  1.4.8.1  pgoyette 	    "symbol: %s (%"BFD_VMA_FMT"x)\n",
   2668  1.4.8.1  pgoyette 	    fixP->fx_frag->fr_address, fixP->fx_where, base,
   2669  1.4.8.1  pgoyette 	    fixP->fx_addsy ? S_GET_NAME (fixP->fx_addsy) : "(null)",
   2670  1.4.8.1  pgoyette 	    fixP->fx_addsy ? S_GET_VALUE (fixP->fx_addsy) : 0);
   2671  1.4.8.1  pgoyette 
   2672  1.4.8.1  pgoyette   return base;
   2673      1.3  christos }
   2674      1.1  christos 
   2675  1.4.8.1  pgoyette /* Given a BFD relocation find the coresponding operand.  */
   2676      1.1  christos 
   2677  1.4.8.1  pgoyette static const struct arc_operand *
   2678  1.4.8.1  pgoyette find_operand_for_reloc (extended_bfd_reloc_code_real_type reloc)
   2679      1.3  christos {
   2680  1.4.8.1  pgoyette   unsigned i;
   2681      1.1  christos 
   2682  1.4.8.1  pgoyette   for (i = 0; i < arc_num_operands; i++)
   2683  1.4.8.1  pgoyette     if (arc_operands[i].default_reloc == reloc)
   2684  1.4.8.1  pgoyette       return  &arc_operands[i];
   2685  1.4.8.1  pgoyette   return NULL;
   2686  1.4.8.1  pgoyette }
   2687      1.1  christos 
   2688  1.4.8.1  pgoyette /* Insert an operand value into an instruction.  */
   2689      1.1  christos 
   2690  1.4.8.1  pgoyette static unsigned
   2691  1.4.8.1  pgoyette insert_operand (unsigned insn,
   2692  1.4.8.1  pgoyette 		const struct arc_operand *operand,
   2693  1.4.8.1  pgoyette 		offsetT val,
   2694  1.4.8.1  pgoyette 		const char *file,
   2695  1.4.8.1  pgoyette 		unsigned line)
   2696  1.4.8.1  pgoyette {
   2697  1.4.8.1  pgoyette   offsetT min = 0, max = 0;
   2698      1.1  christos 
   2699  1.4.8.1  pgoyette   if (operand->bits != 32
   2700  1.4.8.1  pgoyette       && !(operand->flags & ARC_OPERAND_NCHK)
   2701  1.4.8.1  pgoyette       && !(operand->flags & ARC_OPERAND_FAKE))
   2702  1.4.8.1  pgoyette     {
   2703  1.4.8.1  pgoyette       if (operand->flags & ARC_OPERAND_SIGNED)
   2704      1.1  christos 	{
   2705  1.4.8.1  pgoyette 	  max = (1 << (operand->bits - 1)) - 1;
   2706  1.4.8.1  pgoyette 	  min = -(1 << (operand->bits - 1));
   2707      1.1  christos 	}
   2708      1.3  christos       else
   2709  1.4.8.1  pgoyette 	{
   2710  1.4.8.1  pgoyette 	  max = (1 << operand->bits) - 1;
   2711  1.4.8.1  pgoyette 	  min = 0;
   2712  1.4.8.1  pgoyette 	}
   2713  1.4.8.1  pgoyette 
   2714  1.4.8.1  pgoyette       if (val < min || val > max)
   2715  1.4.8.1  pgoyette 	as_bad_value_out_of_range (_("operand"),
   2716  1.4.8.1  pgoyette 				   val, min, max, file, line);
   2717      1.1  christos     }
   2718      1.1  christos 
   2719  1.4.8.1  pgoyette   pr_debug ("insert field: %ld <= %ld <= %ld in 0x%08x\n",
   2720  1.4.8.1  pgoyette 	    min, val, max, insn);
   2721      1.1  christos 
   2722  1.4.8.1  pgoyette   if ((operand->flags & ARC_OPERAND_ALIGNED32)
   2723  1.4.8.1  pgoyette       && (val & 0x03))
   2724  1.4.8.1  pgoyette     as_bad_where (file, line,
   2725  1.4.8.1  pgoyette 		  _("Unaligned operand. Needs to be 32bit aligned"));
   2726      1.3  christos 
   2727  1.4.8.1  pgoyette   if ((operand->flags & ARC_OPERAND_ALIGNED16)
   2728  1.4.8.1  pgoyette       && (val & 0x01))
   2729  1.4.8.1  pgoyette     as_bad_where (file, line,
   2730  1.4.8.1  pgoyette 		  _("Unaligned operand. Needs to be 16bit aligned"));
   2731      1.3  christos 
   2732  1.4.8.1  pgoyette   if (operand->insert)
   2733  1.4.8.1  pgoyette     {
   2734  1.4.8.1  pgoyette       const char *errmsg = NULL;
   2735      1.1  christos 
   2736  1.4.8.1  pgoyette       insn = (*operand->insert) (insn, val, &errmsg);
   2737  1.4.8.1  pgoyette       if (errmsg)
   2738  1.4.8.1  pgoyette 	as_warn_where (file, line, "%s", errmsg);
   2739  1.4.8.1  pgoyette     }
   2740  1.4.8.1  pgoyette   else
   2741  1.4.8.1  pgoyette     {
   2742  1.4.8.1  pgoyette       if (operand->flags & ARC_OPERAND_TRUNCATE)
   2743  1.4.8.1  pgoyette 	{
   2744  1.4.8.1  pgoyette 	  if (operand->flags & ARC_OPERAND_ALIGNED32)
   2745  1.4.8.1  pgoyette 	    val >>= 2;
   2746  1.4.8.1  pgoyette 	  if (operand->flags & ARC_OPERAND_ALIGNED16)
   2747  1.4.8.1  pgoyette 	    val >>= 1;
   2748  1.4.8.1  pgoyette 	}
   2749  1.4.8.1  pgoyette       insn |= ((val & ((1 << operand->bits) - 1)) << operand->shift);
   2750  1.4.8.1  pgoyette     }
   2751  1.4.8.1  pgoyette   return insn;
   2752      1.3  christos }
   2753      1.1  christos 
   2754  1.4.8.1  pgoyette /* Apply a fixup to the object code.  At this point all symbol values
   2755  1.4.8.1  pgoyette    should be fully resolved, and we attempt to completely resolve the
   2756  1.4.8.1  pgoyette    reloc.  If we can not do that, we determine the correct reloc code
   2757  1.4.8.1  pgoyette    and put it back in the fixup.  To indicate that a fixup has been
   2758  1.4.8.1  pgoyette    eliminated, set fixP->fx_done.  */
   2759      1.1  christos 
   2760  1.4.8.1  pgoyette void
   2761  1.4.8.1  pgoyette md_apply_fix (fixS *fixP,
   2762  1.4.8.1  pgoyette 	      valueT *valP,
   2763  1.4.8.1  pgoyette 	      segT seg)
   2764      1.3  christos {
   2765  1.4.8.1  pgoyette   char * const fixpos = fixP->fx_frag->fr_literal + fixP->fx_where;
   2766  1.4.8.1  pgoyette   valueT value = *valP;
   2767  1.4.8.1  pgoyette   unsigned insn = 0;
   2768  1.4.8.1  pgoyette   symbolS *fx_addsy, *fx_subsy;
   2769  1.4.8.1  pgoyette   offsetT fx_offset;
   2770  1.4.8.1  pgoyette   segT add_symbol_segment = absolute_section;
   2771  1.4.8.1  pgoyette   segT sub_symbol_segment = absolute_section;
   2772  1.4.8.1  pgoyette   const struct arc_operand *operand = NULL;
   2773  1.4.8.1  pgoyette   extended_bfd_reloc_code_real_type reloc;
   2774      1.1  christos 
   2775  1.4.8.1  pgoyette   pr_debug ("%s:%u: apply_fix: r_type=%d (%s) value=0x%lX offset=0x%lX\n",
   2776  1.4.8.1  pgoyette 	    fixP->fx_file, fixP->fx_line, fixP->fx_r_type,
   2777  1.4.8.1  pgoyette 	    ((int) fixP->fx_r_type < 0) ? "Internal":
   2778  1.4.8.1  pgoyette 	    bfd_get_reloc_code_name (fixP->fx_r_type), value,
   2779  1.4.8.1  pgoyette 	    fixP->fx_offset);
   2780      1.1  christos 
   2781  1.4.8.1  pgoyette   fx_addsy = fixP->fx_addsy;
   2782  1.4.8.1  pgoyette   fx_subsy = fixP->fx_subsy;
   2783  1.4.8.1  pgoyette   fx_offset = 0;
   2784      1.1  christos 
   2785  1.4.8.1  pgoyette   if (fx_addsy)
   2786  1.4.8.1  pgoyette     {
   2787  1.4.8.1  pgoyette       add_symbol_segment = S_GET_SEGMENT (fx_addsy);
   2788  1.4.8.1  pgoyette     }
   2789      1.1  christos 
   2790  1.4.8.1  pgoyette   if (fx_subsy
   2791  1.4.8.1  pgoyette       && fixP->fx_r_type != BFD_RELOC_ARC_TLS_DTPOFF
   2792  1.4.8.1  pgoyette       && fixP->fx_r_type != BFD_RELOC_ARC_TLS_DTPOFF_S9
   2793  1.4.8.1  pgoyette       && fixP->fx_r_type != BFD_RELOC_ARC_TLS_GD_LD)
   2794  1.4.8.1  pgoyette     {
   2795  1.4.8.1  pgoyette       resolve_symbol_value (fx_subsy);
   2796  1.4.8.1  pgoyette       sub_symbol_segment = S_GET_SEGMENT (fx_subsy);
   2797      1.1  christos 
   2798  1.4.8.1  pgoyette       if (sub_symbol_segment == absolute_section)
   2799  1.4.8.1  pgoyette 	{
   2800  1.4.8.1  pgoyette 	  /* The symbol is really a constant.  */
   2801  1.4.8.1  pgoyette 	  fx_offset -= S_GET_VALUE (fx_subsy);
   2802  1.4.8.1  pgoyette 	  fx_subsy = NULL;
   2803  1.4.8.1  pgoyette 	}
   2804  1.4.8.1  pgoyette       else
   2805  1.4.8.1  pgoyette 	{
   2806  1.4.8.1  pgoyette 	  as_bad_where (fixP->fx_file, fixP->fx_line,
   2807  1.4.8.1  pgoyette 			_("can't resolve `%s' {%s section} - `%s' {%s section}"),
   2808  1.4.8.1  pgoyette 			fx_addsy ? S_GET_NAME (fx_addsy) : "0",
   2809  1.4.8.1  pgoyette 			segment_name (add_symbol_segment),
   2810  1.4.8.1  pgoyette 			S_GET_NAME (fx_subsy),
   2811  1.4.8.1  pgoyette 			segment_name (sub_symbol_segment));
   2812  1.4.8.1  pgoyette 	  return;
   2813  1.4.8.1  pgoyette 	}
   2814  1.4.8.1  pgoyette     }
   2815      1.1  christos 
   2816  1.4.8.1  pgoyette   if (fx_addsy
   2817  1.4.8.1  pgoyette       && !S_IS_WEAK (fx_addsy))
   2818      1.3  christos     {
   2819  1.4.8.1  pgoyette       if (add_symbol_segment == seg
   2820  1.4.8.1  pgoyette 	  && fixP->fx_pcrel)
   2821      1.1  christos 	{
   2822  1.4.8.1  pgoyette 	  value += S_GET_VALUE (fx_addsy);
   2823  1.4.8.1  pgoyette 	  value -= md_pcrel_from_section (fixP, seg);
   2824  1.4.8.1  pgoyette 	  fx_addsy = NULL;
   2825  1.4.8.1  pgoyette 	  fixP->fx_pcrel = FALSE;
   2826      1.3  christos 	}
   2827  1.4.8.1  pgoyette       else if (add_symbol_segment == absolute_section)
   2828  1.4.8.1  pgoyette 	{
   2829  1.4.8.1  pgoyette 	  value = fixP->fx_offset;
   2830  1.4.8.1  pgoyette 	  fx_offset += S_GET_VALUE (fixP->fx_addsy);
   2831  1.4.8.1  pgoyette 	  fx_addsy = NULL;
   2832  1.4.8.1  pgoyette 	  fixP->fx_pcrel = FALSE;
   2833  1.4.8.1  pgoyette 	}
   2834  1.4.8.1  pgoyette     }
   2835      1.1  christos 
   2836  1.4.8.1  pgoyette   if (!fx_addsy)
   2837  1.4.8.1  pgoyette     fixP->fx_done = TRUE;
   2838      1.1  christos 
   2839  1.4.8.1  pgoyette   if (fixP->fx_pcrel)
   2840  1.4.8.1  pgoyette     {
   2841  1.4.8.1  pgoyette       if (fx_addsy
   2842  1.4.8.1  pgoyette 	  && ((S_IS_DEFINED (fx_addsy)
   2843  1.4.8.1  pgoyette 	       && S_GET_SEGMENT (fx_addsy) != seg)
   2844  1.4.8.1  pgoyette 	      || S_IS_WEAK (fx_addsy)))
   2845  1.4.8.1  pgoyette 	value += md_pcrel_from_section (fixP, seg);
   2846      1.1  christos 
   2847  1.4.8.1  pgoyette       switch (fixP->fx_r_type)
   2848  1.4.8.1  pgoyette 	{
   2849  1.4.8.1  pgoyette 	case BFD_RELOC_ARC_32_ME:
   2850  1.4.8.1  pgoyette 	  /* This is a pc-relative value in a LIMM.  Adjust it to the
   2851  1.4.8.1  pgoyette 	     address of the instruction not to the address of the
   2852  1.4.8.1  pgoyette 	     LIMM.  Note: it is not anylonger valid this afirmation as
   2853  1.4.8.1  pgoyette 	     the linker consider ARC_PC32 a fixup to entire 64 bit
   2854  1.4.8.1  pgoyette 	     insn.  */
   2855  1.4.8.1  pgoyette 	  fixP->fx_offset += fixP->fx_frag->fr_address;
   2856  1.4.8.1  pgoyette 	  /* Fall through.  */
   2857  1.4.8.1  pgoyette 	case BFD_RELOC_32:
   2858  1.4.8.1  pgoyette 	  fixP->fx_r_type = BFD_RELOC_ARC_PC32;
   2859  1.4.8.1  pgoyette 	  /* Fall through.  */
   2860  1.4.8.1  pgoyette 	case BFD_RELOC_ARC_PC32:
   2861  1.4.8.1  pgoyette 	  /* fixP->fx_offset += fixP->fx_where - fixP->fx_dot_value; */
   2862  1.4.8.1  pgoyette 	  break;
   2863  1.4.8.1  pgoyette 	default:
   2864  1.4.8.1  pgoyette 	  if ((int) fixP->fx_r_type < 0)
   2865  1.4.8.1  pgoyette 	    as_fatal (_("PC relative relocation not allowed for (internal) type %d"),
   2866  1.4.8.1  pgoyette 		      fixP->fx_r_type);
   2867  1.4.8.1  pgoyette 	  break;
   2868  1.4.8.1  pgoyette 	}
   2869      1.3  christos     }
   2870      1.1  christos 
   2871  1.4.8.1  pgoyette   pr_debug ("%s:%u: apply_fix: r_type=%d (%s) value=0x%lX offset=0x%lX\n",
   2872  1.4.8.1  pgoyette 	    fixP->fx_file, fixP->fx_line, fixP->fx_r_type,
   2873  1.4.8.1  pgoyette 	    ((int) fixP->fx_r_type < 0) ? "Internal":
   2874  1.4.8.1  pgoyette 	    bfd_get_reloc_code_name (fixP->fx_r_type), value,
   2875  1.4.8.1  pgoyette 	    fixP->fx_offset);
   2876      1.1  christos 
   2877      1.1  christos 
   2878  1.4.8.1  pgoyette   /* Now check for TLS relocations.  */
   2879  1.4.8.1  pgoyette   reloc = fixP->fx_r_type;
   2880  1.4.8.1  pgoyette   switch (reloc)
   2881      1.3  christos     {
   2882  1.4.8.1  pgoyette     case BFD_RELOC_ARC_TLS_DTPOFF:
   2883  1.4.8.1  pgoyette     case BFD_RELOC_ARC_TLS_LE_32:
   2884  1.4.8.1  pgoyette       if (fixP->fx_done)
   2885  1.4.8.1  pgoyette 	break;
   2886  1.4.8.1  pgoyette       /* Fall through.  */
   2887  1.4.8.1  pgoyette     case BFD_RELOC_ARC_TLS_GD_GOT:
   2888  1.4.8.1  pgoyette     case BFD_RELOC_ARC_TLS_IE_GOT:
   2889  1.4.8.1  pgoyette       S_SET_THREAD_LOCAL (fixP->fx_addsy);
   2890  1.4.8.1  pgoyette       break;
   2891      1.1  christos 
   2892  1.4.8.1  pgoyette     case BFD_RELOC_ARC_TLS_GD_LD:
   2893  1.4.8.1  pgoyette       gas_assert (!fixP->fx_offset);
   2894  1.4.8.1  pgoyette       if (fixP->fx_subsy)
   2895  1.4.8.1  pgoyette 	fixP->fx_offset
   2896  1.4.8.1  pgoyette 	  = (S_GET_VALUE (fixP->fx_subsy)
   2897  1.4.8.1  pgoyette 	     - fixP->fx_frag->fr_address- fixP->fx_where);
   2898  1.4.8.1  pgoyette       fixP->fx_subsy = NULL;
   2899  1.4.8.1  pgoyette       /* Fall through.  */
   2900  1.4.8.1  pgoyette     case BFD_RELOC_ARC_TLS_GD_CALL:
   2901  1.4.8.1  pgoyette       /* These two relocs are there just to allow ld to change the tls
   2902  1.4.8.1  pgoyette 	 model for this symbol, by patching the code.  The offset -
   2903  1.4.8.1  pgoyette 	 and scale, if any - will be installed by the linker.  */
   2904  1.4.8.1  pgoyette       S_SET_THREAD_LOCAL (fixP->fx_addsy);
   2905  1.4.8.1  pgoyette       break;
   2906      1.1  christos 
   2907  1.4.8.1  pgoyette     case BFD_RELOC_ARC_TLS_LE_S9:
   2908  1.4.8.1  pgoyette     case BFD_RELOC_ARC_TLS_DTPOFF_S9:
   2909  1.4.8.1  pgoyette       as_bad (_("TLS_*_S9 relocs are not supported yet"));
   2910  1.4.8.1  pgoyette       break;
   2911      1.1  christos 
   2912  1.4.8.1  pgoyette     default:
   2913  1.4.8.1  pgoyette       break;
   2914  1.4.8.1  pgoyette     }
   2915      1.1  christos 
   2916  1.4.8.1  pgoyette   if (!fixP->fx_done)
   2917  1.4.8.1  pgoyette     {
   2918  1.4.8.1  pgoyette       return;
   2919  1.4.8.1  pgoyette     }
   2920      1.1  christos 
   2921  1.4.8.1  pgoyette   /* Addjust the value if we have a constant.  */
   2922  1.4.8.1  pgoyette   value += fx_offset;
   2923      1.1  christos 
   2924  1.4.8.1  pgoyette   /* For hosts with longs bigger than 32-bits make sure that the top
   2925  1.4.8.1  pgoyette      bits of a 32-bit negative value read in by the parser are set,
   2926  1.4.8.1  pgoyette      so that the correct comparisons are made.  */
   2927  1.4.8.1  pgoyette   if (value & 0x80000000)
   2928  1.4.8.1  pgoyette     value |= (-1UL << 31);
   2929      1.1  christos 
   2930  1.4.8.1  pgoyette   reloc = fixP->fx_r_type;
   2931  1.4.8.1  pgoyette   switch (reloc)
   2932      1.3  christos     {
   2933  1.4.8.1  pgoyette     case BFD_RELOC_8:
   2934  1.4.8.1  pgoyette     case BFD_RELOC_16:
   2935  1.4.8.1  pgoyette     case BFD_RELOC_24:
   2936  1.4.8.1  pgoyette     case BFD_RELOC_32:
   2937  1.4.8.1  pgoyette     case BFD_RELOC_64:
   2938  1.4.8.1  pgoyette     case BFD_RELOC_ARC_32_PCREL:
   2939  1.4.8.1  pgoyette       md_number_to_chars (fixpos, value, fixP->fx_size);
   2940  1.4.8.1  pgoyette       return;
   2941      1.1  christos 
   2942  1.4.8.1  pgoyette     case BFD_RELOC_ARC_GOTPC32:
   2943  1.4.8.1  pgoyette       /* I cannot fix an GOTPC relocation because I need to relax it
   2944  1.4.8.1  pgoyette 	 from ld rx,[pcl,@sym@gotpc] to add rx,pcl,@sym@gotpc.  */
   2945  1.4.8.1  pgoyette       as_bad (_("Unsupported operation on reloc"));
   2946  1.4.8.1  pgoyette       return;
   2947      1.1  christos 
   2948  1.4.8.1  pgoyette     case BFD_RELOC_ARC_TLS_DTPOFF:
   2949  1.4.8.1  pgoyette     case BFD_RELOC_ARC_TLS_LE_32:
   2950  1.4.8.1  pgoyette       gas_assert (!fixP->fx_addsy);
   2951  1.4.8.1  pgoyette       gas_assert (!fixP->fx_subsy);
   2952      1.3  christos 
   2953  1.4.8.1  pgoyette     case BFD_RELOC_ARC_GOTOFF:
   2954  1.4.8.1  pgoyette     case BFD_RELOC_ARC_32_ME:
   2955  1.4.8.1  pgoyette     case BFD_RELOC_ARC_PC32:
   2956  1.4.8.1  pgoyette       md_number_to_chars_midend (fixpos, value, fixP->fx_size);
   2957  1.4.8.1  pgoyette       return;
   2958      1.3  christos 
   2959  1.4.8.1  pgoyette     case BFD_RELOC_ARC_PLT32:
   2960  1.4.8.1  pgoyette       md_number_to_chars_midend (fixpos, value, fixP->fx_size);
   2961  1.4.8.1  pgoyette       return;
   2962      1.3  christos 
   2963  1.4.8.1  pgoyette     case BFD_RELOC_ARC_S25H_PCREL_PLT:
   2964  1.4.8.1  pgoyette       reloc = BFD_RELOC_ARC_S25W_PCREL;
   2965  1.4.8.1  pgoyette       goto solve_plt;
   2966      1.3  christos 
   2967  1.4.8.1  pgoyette     case BFD_RELOC_ARC_S21H_PCREL_PLT:
   2968  1.4.8.1  pgoyette       reloc = BFD_RELOC_ARC_S21H_PCREL;
   2969  1.4.8.1  pgoyette       goto solve_plt;
   2970      1.3  christos 
   2971  1.4.8.1  pgoyette     case BFD_RELOC_ARC_S25W_PCREL_PLT:
   2972  1.4.8.1  pgoyette       reloc = BFD_RELOC_ARC_S25W_PCREL;
   2973  1.4.8.1  pgoyette       goto solve_plt;
   2974      1.3  christos 
   2975  1.4.8.1  pgoyette     case BFD_RELOC_ARC_S21W_PCREL_PLT:
   2976  1.4.8.1  pgoyette       reloc = BFD_RELOC_ARC_S21W_PCREL;
   2977      1.3  christos 
   2978  1.4.8.1  pgoyette     case BFD_RELOC_ARC_S25W_PCREL:
   2979  1.4.8.1  pgoyette     case BFD_RELOC_ARC_S21W_PCREL:
   2980  1.4.8.1  pgoyette     case BFD_RELOC_ARC_S21H_PCREL:
   2981  1.4.8.1  pgoyette     case BFD_RELOC_ARC_S25H_PCREL:
   2982  1.4.8.1  pgoyette     case BFD_RELOC_ARC_S13_PCREL:
   2983  1.4.8.1  pgoyette     solve_plt:
   2984  1.4.8.1  pgoyette       operand = find_operand_for_reloc (reloc);
   2985  1.4.8.1  pgoyette       gas_assert (operand);
   2986  1.4.8.1  pgoyette       break;
   2987      1.3  christos 
   2988  1.4.8.1  pgoyette     default:
   2989  1.4.8.1  pgoyette       {
   2990  1.4.8.1  pgoyette 	if ((int) fixP->fx_r_type >= 0)
   2991  1.4.8.1  pgoyette 	  as_fatal (_("unhandled relocation type %s"),
   2992  1.4.8.1  pgoyette 		    bfd_get_reloc_code_name (fixP->fx_r_type));
   2993      1.3  christos 
   2994  1.4.8.1  pgoyette 	/* The rest of these fixups needs to be completely resolved as
   2995  1.4.8.1  pgoyette 	   constants.  */
   2996  1.4.8.1  pgoyette 	if (fixP->fx_addsy != 0
   2997  1.4.8.1  pgoyette 	    && S_GET_SEGMENT (fixP->fx_addsy) != absolute_section)
   2998  1.4.8.1  pgoyette 	  as_bad_where (fixP->fx_file, fixP->fx_line,
   2999  1.4.8.1  pgoyette 			_("non-absolute expression in constant field"));
   3000  1.4.8.1  pgoyette 
   3001  1.4.8.1  pgoyette 	gas_assert (-(int) fixP->fx_r_type < (int) arc_num_operands);
   3002  1.4.8.1  pgoyette 	operand = &arc_operands[-(int) fixP->fx_r_type];
   3003  1.4.8.1  pgoyette 	break;
   3004  1.4.8.1  pgoyette       }
   3005      1.3  christos     }
   3006      1.3  christos 
   3007  1.4.8.1  pgoyette   if (target_big_endian)
   3008  1.4.8.1  pgoyette     {
   3009  1.4.8.1  pgoyette       switch (fixP->fx_size)
   3010  1.4.8.1  pgoyette 	{
   3011  1.4.8.1  pgoyette 	case 4:
   3012  1.4.8.1  pgoyette 	  insn = bfd_getb32 (fixpos);
   3013  1.4.8.1  pgoyette 	  break;
   3014  1.4.8.1  pgoyette 	case 2:
   3015  1.4.8.1  pgoyette 	  insn = bfd_getb16 (fixpos);
   3016  1.4.8.1  pgoyette 	  break;
   3017  1.4.8.1  pgoyette 	default:
   3018  1.4.8.1  pgoyette 	  as_bad_where (fixP->fx_file, fixP->fx_line,
   3019  1.4.8.1  pgoyette 			_("unknown fixup size"));
   3020  1.4.8.1  pgoyette 	}
   3021  1.4.8.1  pgoyette     }
   3022  1.4.8.1  pgoyette   else
   3023  1.4.8.1  pgoyette     {
   3024  1.4.8.1  pgoyette       insn = 0;
   3025  1.4.8.1  pgoyette       switch (fixP->fx_size)
   3026  1.4.8.1  pgoyette 	{
   3027  1.4.8.1  pgoyette 	case 4:
   3028  1.4.8.1  pgoyette 	  insn = bfd_getl16 (fixpos) << 16 | bfd_getl16 (fixpos + 2);
   3029  1.4.8.1  pgoyette 	  break;
   3030  1.4.8.1  pgoyette 	case 2:
   3031  1.4.8.1  pgoyette 	  insn = bfd_getl16 (fixpos);
   3032  1.4.8.1  pgoyette 	  break;
   3033  1.4.8.1  pgoyette 	default:
   3034  1.4.8.1  pgoyette 	  as_bad_where (fixP->fx_file, fixP->fx_line,
   3035  1.4.8.1  pgoyette 			_("unknown fixup size"));
   3036  1.4.8.1  pgoyette 	}
   3037  1.4.8.1  pgoyette     }
   3038      1.3  christos 
   3039  1.4.8.1  pgoyette   insn = insert_operand (insn, operand, (offsetT) value,
   3040  1.4.8.1  pgoyette 			 fixP->fx_file, fixP->fx_line);
   3041      1.3  christos 
   3042  1.4.8.1  pgoyette   md_number_to_chars_midend (fixpos, insn, fixP->fx_size);
   3043  1.4.8.1  pgoyette }
   3044      1.1  christos 
   3045  1.4.8.1  pgoyette /* Prepare machine-dependent frags for relaxation.
   3046      1.3  christos 
   3047  1.4.8.1  pgoyette    Called just before relaxation starts.  Any symbol that is now undefined
   3048  1.4.8.1  pgoyette    will not become defined.
   3049      1.3  christos 
   3050  1.4.8.1  pgoyette    Return the correct fr_subtype in the frag.
   3051      1.1  christos 
   3052  1.4.8.1  pgoyette    Return the initial "guess for fr_var" to caller.  The guess for fr_var
   3053  1.4.8.1  pgoyette    is *actually* the growth beyond fr_fix.  Whatever we do to grow fr_fix
   3054  1.4.8.1  pgoyette    or fr_var contributes to our returned value.
   3055      1.3  christos 
   3056  1.4.8.1  pgoyette    Although it may not be explicit in the frag, pretend
   3057  1.4.8.1  pgoyette    fr_var starts with a value.  */
   3058      1.3  christos 
   3059  1.4.8.1  pgoyette int
   3060  1.4.8.1  pgoyette md_estimate_size_before_relax (fragS *fragP,
   3061  1.4.8.1  pgoyette 			       segT segment)
   3062      1.3  christos {
   3063  1.4.8.1  pgoyette   int growth;
   3064  1.4.8.1  pgoyette 
   3065  1.4.8.1  pgoyette   /* If the symbol is not located within the same section AND it's not
   3066  1.4.8.1  pgoyette      an absolute section, use the maximum.  OR if the symbol is a
   3067  1.4.8.1  pgoyette      constant AND the insn is by nature not pc-rel, use the maximum.
   3068  1.4.8.1  pgoyette      OR if the symbol is being equated against another symbol, use the
   3069  1.4.8.1  pgoyette      maximum.  OR if the symbol is weak use the maximum.  */
   3070  1.4.8.1  pgoyette   if ((S_GET_SEGMENT (fragP->fr_symbol) != segment
   3071  1.4.8.1  pgoyette        && S_GET_SEGMENT (fragP->fr_symbol) != absolute_section)
   3072  1.4.8.1  pgoyette       || (symbol_constant_p (fragP->fr_symbol)
   3073  1.4.8.1  pgoyette 	  && !fragP->tc_frag_data.pcrel)
   3074  1.4.8.1  pgoyette       || symbol_equated_p (fragP->fr_symbol)
   3075  1.4.8.1  pgoyette       || S_IS_WEAK (fragP->fr_symbol))
   3076  1.4.8.1  pgoyette     {
   3077  1.4.8.1  pgoyette       while (md_relax_table[fragP->fr_subtype].rlx_more != ARC_RLX_NONE)
   3078  1.4.8.1  pgoyette 	++fragP->fr_subtype;
   3079  1.4.8.1  pgoyette     }
   3080      1.3  christos 
   3081  1.4.8.1  pgoyette   growth = md_relax_table[fragP->fr_subtype].rlx_length;
   3082  1.4.8.1  pgoyette   fragP->fr_var = growth;
   3083      1.3  christos 
   3084  1.4.8.1  pgoyette   pr_debug ("%s:%d: md_estimate_size_before_relax: %d\n",
   3085  1.4.8.1  pgoyette 	   fragP->fr_file, fragP->fr_line, growth);
   3086      1.3  christos 
   3087  1.4.8.1  pgoyette   return growth;
   3088      1.3  christos }
   3089      1.3  christos 
   3090  1.4.8.1  pgoyette /* Translate internal representation of relocation info to BFD target
   3091  1.4.8.1  pgoyette    format.  */
   3092      1.3  christos 
   3093  1.4.8.1  pgoyette arelent *
   3094  1.4.8.1  pgoyette tc_gen_reloc (asection *section ATTRIBUTE_UNUSED,
   3095  1.4.8.1  pgoyette 	      fixS *fixP)
   3096      1.3  christos {
   3097  1.4.8.1  pgoyette   arelent *reloc;
   3098  1.4.8.1  pgoyette   bfd_reloc_code_real_type code;
   3099      1.3  christos 
   3100  1.4.8.1  pgoyette   reloc = XNEW (arelent);
   3101  1.4.8.1  pgoyette   reloc->sym_ptr_ptr = XNEW (asymbol *);
   3102  1.4.8.1  pgoyette   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
   3103  1.4.8.1  pgoyette   reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
   3104      1.3  christos 
   3105  1.4.8.1  pgoyette   /* Make sure none of our internal relocations make it this far.
   3106  1.4.8.1  pgoyette      They'd better have been fully resolved by this point.  */
   3107  1.4.8.1  pgoyette   gas_assert ((int) fixP->fx_r_type > 0);
   3108      1.3  christos 
   3109  1.4.8.1  pgoyette   code = fixP->fx_r_type;
   3110      1.3  christos 
   3111  1.4.8.1  pgoyette   /* if we have something like add gp, pcl,
   3112  1.4.8.1  pgoyette      _GLOBAL_OFFSET_TABLE_@gotpc.  */
   3113  1.4.8.1  pgoyette   if (code == BFD_RELOC_ARC_GOTPC32
   3114  1.4.8.1  pgoyette       && GOT_symbol
   3115  1.4.8.1  pgoyette       && fixP->fx_addsy == GOT_symbol)
   3116  1.4.8.1  pgoyette     code = BFD_RELOC_ARC_GOTPC;
   3117      1.3  christos 
   3118  1.4.8.1  pgoyette   reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
   3119  1.4.8.1  pgoyette   if (reloc->howto == NULL)
   3120  1.4.8.1  pgoyette     {
   3121  1.4.8.1  pgoyette       as_bad_where (fixP->fx_file, fixP->fx_line,
   3122  1.4.8.1  pgoyette 		    _("cannot represent `%s' relocation in object file"),
   3123  1.4.8.1  pgoyette 		    bfd_get_reloc_code_name (code));
   3124  1.4.8.1  pgoyette       return NULL;
   3125  1.4.8.1  pgoyette     }
   3126      1.3  christos 
   3127  1.4.8.1  pgoyette   if (!fixP->fx_pcrel != !reloc->howto->pc_relative)
   3128  1.4.8.1  pgoyette     as_fatal (_("internal error? cannot generate `%s' relocation"),
   3129  1.4.8.1  pgoyette 	      bfd_get_reloc_code_name (code));
   3130  1.4.8.1  pgoyette 
   3131  1.4.8.1  pgoyette   gas_assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
   3132  1.4.8.1  pgoyette 
   3133  1.4.8.1  pgoyette   if (code == BFD_RELOC_ARC_TLS_DTPOFF
   3134  1.4.8.1  pgoyette       || code ==  BFD_RELOC_ARC_TLS_DTPOFF_S9)
   3135      1.3  christos     {
   3136  1.4.8.1  pgoyette       asymbol *sym
   3137  1.4.8.1  pgoyette 	= fixP->fx_subsy ? symbol_get_bfdsym (fixP->fx_subsy) : NULL;
   3138  1.4.8.1  pgoyette       /* We just want to store a 24 bit index, but we have to wait
   3139  1.4.8.1  pgoyette 	 till after write_contents has been called via
   3140  1.4.8.1  pgoyette 	 bfd_map_over_sections before we can get the index from
   3141  1.4.8.1  pgoyette 	 _bfd_elf_symbol_from_bfd_symbol.  Thus, the write_relocs
   3142  1.4.8.1  pgoyette 	 function is elf32-arc.c has to pick up the slack.
   3143  1.4.8.1  pgoyette 	 Unfortunately, this leads to problems with hosts that have
   3144  1.4.8.1  pgoyette 	 pointers wider than long (bfd_vma).  There would be various
   3145  1.4.8.1  pgoyette 	 ways to handle this, all error-prone :-(  */
   3146  1.4.8.1  pgoyette       reloc->addend = (bfd_vma) sym;
   3147  1.4.8.1  pgoyette       if ((asymbol *) reloc->addend != sym)
   3148  1.4.8.1  pgoyette 	{
   3149  1.4.8.1  pgoyette 	  as_bad ("Can't store pointer\n");
   3150  1.4.8.1  pgoyette 	  return NULL;
   3151  1.4.8.1  pgoyette 	}
   3152      1.3  christos     }
   3153  1.4.8.1  pgoyette   else
   3154  1.4.8.1  pgoyette     reloc->addend = fixP->fx_offset;
   3155  1.4.8.1  pgoyette 
   3156  1.4.8.1  pgoyette   return reloc;
   3157      1.3  christos }
   3158      1.3  christos 
   3159  1.4.8.1  pgoyette /* Perform post-processing of machine-dependent frags after relaxation.
   3160  1.4.8.1  pgoyette    Called after relaxation is finished.
   3161  1.4.8.1  pgoyette    In:	Address of frag.
   3162  1.4.8.1  pgoyette    fr_type == rs_machine_dependent.
   3163  1.4.8.1  pgoyette    fr_subtype is what the address relaxed to.
   3164      1.3  christos 
   3165  1.4.8.1  pgoyette    Out: Any fixS:s and constants are set up.  */
   3166  1.4.8.1  pgoyette 
   3167  1.4.8.1  pgoyette void
   3168  1.4.8.1  pgoyette md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
   3169  1.4.8.1  pgoyette 		 segT segment ATTRIBUTE_UNUSED,
   3170  1.4.8.1  pgoyette 		 fragS *fragP)
   3171      1.3  christos {
   3172  1.4.8.1  pgoyette   const relax_typeS *table_entry;
   3173  1.4.8.1  pgoyette   char *dest;
   3174  1.4.8.1  pgoyette   const struct arc_opcode *opcode;
   3175  1.4.8.1  pgoyette   struct arc_insn insn;
   3176  1.4.8.1  pgoyette   int size, fix;
   3177  1.4.8.1  pgoyette   struct arc_relax_type *relax_arg = &fragP->tc_frag_data;
   3178  1.4.8.1  pgoyette 
   3179  1.4.8.1  pgoyette   fix = (fragP->fr_fix < 0 ? 0 : fragP->fr_fix);
   3180  1.4.8.1  pgoyette   dest = fragP->fr_literal + fix;
   3181  1.4.8.1  pgoyette   table_entry = TC_GENERIC_RELAX_TABLE + fragP->fr_subtype;
   3182      1.3  christos 
   3183  1.4.8.1  pgoyette   pr_debug ("%s:%d: md_convert_frag, subtype: %d, fix: %d, "
   3184  1.4.8.1  pgoyette 	    "var: %"BFD_VMA_FMT"d\n",
   3185  1.4.8.1  pgoyette 	    fragP->fr_file, fragP->fr_line,
   3186  1.4.8.1  pgoyette 	    fragP->fr_subtype, fix, fragP->fr_var);
   3187      1.3  christos 
   3188  1.4.8.1  pgoyette   if (fragP->fr_subtype <= 0
   3189  1.4.8.1  pgoyette       && fragP->fr_subtype >= arc_num_relax_opcodes)
   3190  1.4.8.1  pgoyette     as_fatal (_("no relaxation found for this instruction."));
   3191      1.3  christos 
   3192  1.4.8.1  pgoyette   opcode = &arc_relax_opcodes[fragP->fr_subtype];
   3193      1.3  christos 
   3194  1.4.8.1  pgoyette   assemble_insn (opcode, relax_arg->tok, relax_arg->ntok, relax_arg->pflags,
   3195  1.4.8.1  pgoyette 	relax_arg->nflg, &insn);
   3196      1.3  christos 
   3197  1.4.8.1  pgoyette   apply_fixups (&insn, fragP, fix);
   3198      1.3  christos 
   3199  1.4.8.1  pgoyette   size = insn.short_insn ? (insn.has_limm ? 6 : 2) : (insn.has_limm ? 8 : 4);
   3200  1.4.8.1  pgoyette   gas_assert (table_entry->rlx_length == size);
   3201  1.4.8.1  pgoyette   emit_insn0 (&insn, dest, TRUE);
   3202      1.3  christos 
   3203  1.4.8.1  pgoyette   fragP->fr_fix += table_entry->rlx_length;
   3204  1.4.8.1  pgoyette   fragP->fr_var = 0;
   3205  1.4.8.1  pgoyette }
   3206  1.4.8.1  pgoyette 
   3207  1.4.8.1  pgoyette /* We have no need to default values of symbols.  We could catch
   3208  1.4.8.1  pgoyette    register names here, but that is handled by inserting them all in
   3209  1.4.8.1  pgoyette    the symbol table to begin with.  */
   3210  1.4.8.1  pgoyette 
   3211  1.4.8.1  pgoyette symbolS *
   3212  1.4.8.1  pgoyette md_undefined_symbol (char *name)
   3213  1.4.8.1  pgoyette {
   3214  1.4.8.1  pgoyette   /* The arc abi demands that a GOT[0] should be referencible as
   3215  1.4.8.1  pgoyette      [pc+_DYNAMIC@gotpc].  Hence we convert a _DYNAMIC@gotpc to a
   3216  1.4.8.1  pgoyette      GOTPC reference to _GLOBAL_OFFSET_TABLE_.  */
   3217  1.4.8.1  pgoyette   if (((*name == '_')
   3218  1.4.8.1  pgoyette        && (*(name+1) == 'G')
   3219  1.4.8.1  pgoyette        && (strcmp (name, GLOBAL_OFFSET_TABLE_NAME) == 0))
   3220  1.4.8.1  pgoyette       || ((*name == '_')
   3221  1.4.8.1  pgoyette 	  && (*(name+1) == 'D')
   3222  1.4.8.1  pgoyette 	  && (strcmp (name, DYNAMIC_STRUCT_NAME) == 0)))
   3223  1.4.8.1  pgoyette     {
   3224  1.4.8.1  pgoyette       if (!GOT_symbol)
   3225      1.3  christos 	{
   3226  1.4.8.1  pgoyette 	  if (symbol_find (name))
   3227  1.4.8.1  pgoyette 	    as_bad ("GOT already in symbol table");
   3228      1.3  christos 
   3229  1.4.8.1  pgoyette 	  GOT_symbol = symbol_new (GLOBAL_OFFSET_TABLE_NAME, undefined_section,
   3230  1.4.8.1  pgoyette 				   (valueT) 0, &zero_address_frag);
   3231  1.4.8.1  pgoyette 	};
   3232  1.4.8.1  pgoyette       return GOT_symbol;
   3233  1.4.8.1  pgoyette     }
   3234  1.4.8.1  pgoyette   return NULL;
   3235  1.4.8.1  pgoyette }
   3236      1.3  christos 
   3237  1.4.8.1  pgoyette /* Turn a string in input_line_pointer into a floating point constant
   3238  1.4.8.1  pgoyette    of type type, and store the appropriate bytes in *litP.  The number
   3239  1.4.8.1  pgoyette    of LITTLENUMS emitted is stored in *sizeP.  An error message is
   3240  1.4.8.1  pgoyette    returned, or NULL on OK.  */
   3241      1.3  christos 
   3242  1.4.8.1  pgoyette const char *
   3243  1.4.8.1  pgoyette md_atof (int type, char *litP, int *sizeP)
   3244  1.4.8.1  pgoyette {
   3245  1.4.8.1  pgoyette   return ieee_md_atof (type, litP, sizeP, target_big_endian);
   3246  1.4.8.1  pgoyette }
   3247      1.3  christos 
   3248  1.4.8.1  pgoyette /* Called for any expression that can not be recognized.  When the
   3249  1.4.8.1  pgoyette    function is called, `input_line_pointer' will point to the start of
   3250  1.4.8.1  pgoyette    the expression.  */
   3251      1.3  christos 
   3252  1.4.8.1  pgoyette void
   3253  1.4.8.1  pgoyette md_operand (expressionS *expressionP ATTRIBUTE_UNUSED)
   3254  1.4.8.1  pgoyette {
   3255  1.4.8.1  pgoyette   char *p = input_line_pointer;
   3256  1.4.8.1  pgoyette   if (*p == '@')
   3257  1.4.8.1  pgoyette     {
   3258  1.4.8.1  pgoyette       input_line_pointer++;
   3259  1.4.8.1  pgoyette       expressionP->X_op = O_symbol;
   3260  1.4.8.1  pgoyette       expression (expressionP);
   3261  1.4.8.1  pgoyette     }
   3262  1.4.8.1  pgoyette }
   3263      1.3  christos 
   3264  1.4.8.1  pgoyette /* This function is called from the function 'expression', it attempts
   3265  1.4.8.1  pgoyette    to parse special names (in our case register names).  It fills in
   3266  1.4.8.1  pgoyette    the expression with the identified register.  It returns TRUE if
   3267  1.4.8.1  pgoyette    it is a register and FALSE otherwise.  */
   3268  1.4.8.1  pgoyette 
   3269  1.4.8.1  pgoyette bfd_boolean
   3270  1.4.8.1  pgoyette arc_parse_name (const char *name,
   3271  1.4.8.1  pgoyette 		struct expressionS *e)
   3272  1.4.8.1  pgoyette {
   3273  1.4.8.1  pgoyette   struct symbol *sym;
   3274  1.4.8.1  pgoyette 
   3275  1.4.8.1  pgoyette   if (!assembling_insn)
   3276  1.4.8.1  pgoyette     return FALSE;
   3277      1.3  christos 
   3278  1.4.8.1  pgoyette   /* Handle only registers.  */
   3279  1.4.8.1  pgoyette   if (e->X_op != O_absent)
   3280  1.4.8.1  pgoyette     return FALSE;
   3281      1.3  christos 
   3282  1.4.8.1  pgoyette   sym = hash_find (arc_reg_hash, name);
   3283  1.4.8.1  pgoyette   if (sym)
   3284  1.4.8.1  pgoyette     {
   3285  1.4.8.1  pgoyette       e->X_op = O_register;
   3286  1.4.8.1  pgoyette       e->X_add_number = S_GET_VALUE (sym);
   3287  1.4.8.1  pgoyette       return TRUE;
   3288  1.4.8.1  pgoyette     }
   3289  1.4.8.1  pgoyette   return FALSE;
   3290  1.4.8.1  pgoyette }
   3291      1.3  christos 
   3292  1.4.8.1  pgoyette /* md_parse_option
   3293  1.4.8.1  pgoyette    Invocation line includes a switch not recognized by the base assembler.
   3294  1.4.8.1  pgoyette    See if it's a processor-specific option.
   3295      1.3  christos 
   3296  1.4.8.1  pgoyette    New options (supported) are:
   3297      1.3  christos 
   3298  1.4.8.1  pgoyette    -mcpu=<cpu name>		 Assemble for selected processor
   3299  1.4.8.1  pgoyette    -EB/-mbig-endian		 Big-endian
   3300  1.4.8.1  pgoyette    -EL/-mlittle-endian		 Little-endian
   3301  1.4.8.1  pgoyette    -mrelax                       Enable relaxation
   3302      1.3  christos 
   3303  1.4.8.1  pgoyette    The following CPU names are recognized:
   3304  1.4.8.1  pgoyette    arc600, arc700, arcem, archs, nps400.  */
   3305      1.3  christos 
   3306  1.4.8.1  pgoyette int
   3307  1.4.8.1  pgoyette md_parse_option (int c, const char *arg ATTRIBUTE_UNUSED)
   3308  1.4.8.1  pgoyette {
   3309  1.4.8.1  pgoyette   switch (c)
   3310  1.4.8.1  pgoyette     {
   3311  1.4.8.1  pgoyette     case OPTION_ARC600:
   3312  1.4.8.1  pgoyette     case OPTION_ARC601:
   3313  1.4.8.1  pgoyette       return md_parse_option (OPTION_MCPU, "arc600");
   3314      1.3  christos 
   3315  1.4.8.1  pgoyette     case OPTION_ARC700:
   3316  1.4.8.1  pgoyette       return md_parse_option (OPTION_MCPU, "arc700");
   3317      1.3  christos 
   3318  1.4.8.1  pgoyette     case OPTION_ARCEM:
   3319  1.4.8.1  pgoyette       return md_parse_option (OPTION_MCPU, "arcem");
   3320      1.3  christos 
   3321  1.4.8.1  pgoyette     case OPTION_ARCHS:
   3322  1.4.8.1  pgoyette       return md_parse_option (OPTION_MCPU, "archs");
   3323      1.3  christos 
   3324  1.4.8.1  pgoyette     case OPTION_MCPU:
   3325  1.4.8.1  pgoyette       {
   3326  1.4.8.1  pgoyette         arc_select_cpu (arg);
   3327  1.4.8.1  pgoyette         mach_type_specified_p = TRUE;
   3328  1.4.8.1  pgoyette 	break;
   3329  1.4.8.1  pgoyette       }
   3330      1.3  christos 
   3331  1.4.8.1  pgoyette     case OPTION_EB:
   3332  1.4.8.1  pgoyette       arc_target_format = "elf32-bigarc";
   3333  1.4.8.1  pgoyette       byte_order = BIG_ENDIAN;
   3334  1.4.8.1  pgoyette       break;
   3335      1.3  christos 
   3336  1.4.8.1  pgoyette     case OPTION_EL:
   3337  1.4.8.1  pgoyette       arc_target_format = "elf32-littlearc";
   3338  1.4.8.1  pgoyette       byte_order = LITTLE_ENDIAN;
   3339  1.4.8.1  pgoyette       break;
   3340      1.3  christos 
   3341  1.4.8.1  pgoyette     case OPTION_CD:
   3342  1.4.8.1  pgoyette       /* This option has an effect only on ARC EM.  */
   3343  1.4.8.1  pgoyette       if (arc_target & ARC_OPCODE_ARCv2EM)
   3344  1.4.8.1  pgoyette 	arc_features |= ARC_CD;
   3345  1.4.8.1  pgoyette       else
   3346  1.4.8.1  pgoyette 	as_warn (_("Code density option invalid for selected CPU"));
   3347  1.4.8.1  pgoyette       break;
   3348      1.3  christos 
   3349  1.4.8.1  pgoyette     case OPTION_RELAX:
   3350  1.4.8.1  pgoyette       relaxation_state = 1;
   3351  1.4.8.1  pgoyette       break;
   3352      1.3  christos 
   3353  1.4.8.1  pgoyette     case OPTION_NPS400:
   3354  1.4.8.1  pgoyette       arc_features |= ARC_NPS400;
   3355  1.4.8.1  pgoyette       break;
   3356      1.3  christos 
   3357  1.4.8.1  pgoyette     case OPTION_SPFP:
   3358  1.4.8.1  pgoyette       arc_features |= ARC_SPFP;
   3359  1.4.8.1  pgoyette       break;
   3360      1.3  christos 
   3361  1.4.8.1  pgoyette     case OPTION_DPFP:
   3362  1.4.8.1  pgoyette       arc_features |= ARC_DPFP;
   3363  1.4.8.1  pgoyette       break;
   3364      1.3  christos 
   3365  1.4.8.1  pgoyette     case OPTION_FPUDA:
   3366  1.4.8.1  pgoyette       /* This option has an effect only on ARC EM.  */
   3367  1.4.8.1  pgoyette       if (arc_target & ARC_OPCODE_ARCv2EM)
   3368  1.4.8.1  pgoyette 	arc_features |= ARC_FPUDA;
   3369  1.4.8.1  pgoyette       else
   3370  1.4.8.1  pgoyette 	as_warn (_("FPUDA invalid for selected CPU"));
   3371  1.4.8.1  pgoyette       break;
   3372      1.3  christos 
   3373  1.4.8.1  pgoyette     /* Dummy options are accepted but have no effect.  */
   3374  1.4.8.1  pgoyette     case OPTION_USER_MODE:
   3375  1.4.8.1  pgoyette     case OPTION_LD_EXT_MASK:
   3376  1.4.8.1  pgoyette     case OPTION_SWAP:
   3377  1.4.8.1  pgoyette     case OPTION_NORM:
   3378  1.4.8.1  pgoyette     case OPTION_BARREL_SHIFT:
   3379  1.4.8.1  pgoyette     case OPTION_MIN_MAX:
   3380  1.4.8.1  pgoyette     case OPTION_NO_MPY:
   3381  1.4.8.1  pgoyette     case OPTION_EA:
   3382  1.4.8.1  pgoyette     case OPTION_MUL64:
   3383  1.4.8.1  pgoyette     case OPTION_SIMD:
   3384  1.4.8.1  pgoyette     case OPTION_XMAC_D16:
   3385  1.4.8.1  pgoyette     case OPTION_XMAC_24:
   3386  1.4.8.1  pgoyette     case OPTION_DSP_PACKA:
   3387  1.4.8.1  pgoyette     case OPTION_CRC:
   3388  1.4.8.1  pgoyette     case OPTION_DVBF:
   3389  1.4.8.1  pgoyette     case OPTION_TELEPHONY:
   3390  1.4.8.1  pgoyette     case OPTION_XYMEMORY:
   3391  1.4.8.1  pgoyette     case OPTION_LOCK:
   3392  1.4.8.1  pgoyette     case OPTION_SWAPE:
   3393  1.4.8.1  pgoyette     case OPTION_RTSC:
   3394  1.4.8.1  pgoyette       break;
   3395      1.3  christos 
   3396  1.4.8.1  pgoyette     default:
   3397  1.4.8.1  pgoyette       return 0;
   3398      1.3  christos     }
   3399      1.3  christos 
   3400  1.4.8.1  pgoyette   return 1;
   3401  1.4.8.1  pgoyette }
   3402  1.4.8.1  pgoyette 
   3403  1.4.8.1  pgoyette void
   3404  1.4.8.1  pgoyette md_show_usage (FILE *stream)
   3405  1.4.8.1  pgoyette {
   3406  1.4.8.1  pgoyette   fprintf (stream, _("ARC-specific assembler options:\n"));
   3407  1.4.8.1  pgoyette 
   3408  1.4.8.1  pgoyette   fprintf (stream, "  -mcpu=<cpu name>\t  assemble for CPU <cpu name> "
   3409  1.4.8.1  pgoyette            "(default: %s)\n", TARGET_WITH_CPU);
   3410  1.4.8.1  pgoyette   fprintf (stream, "  -mcpu=nps400\t\t  same as -mcpu=arc700 -mnps400\n");
   3411  1.4.8.1  pgoyette   fprintf (stream, "  -mA6/-mARC600/-mARC601  same as -mcpu=arc600\n");
   3412  1.4.8.1  pgoyette   fprintf (stream, "  -mA7/-mARC700\t\t  same as -mcpu=arc700\n");
   3413  1.4.8.1  pgoyette   fprintf (stream, "  -mEM\t\t\t  same as -mcpu=arcem\n");
   3414  1.4.8.1  pgoyette   fprintf (stream, "  -mHS\t\t\t  same as -mcpu=archs\n");
   3415  1.4.8.1  pgoyette 
   3416  1.4.8.1  pgoyette   fprintf (stream, "  -mnps400\t\t  enable NPS-400 extended instructions\n");
   3417  1.4.8.1  pgoyette   fprintf (stream, "  -mspfp\t\t  enable single-precision floating point instructions\n");
   3418  1.4.8.1  pgoyette   fprintf (stream, "  -mdpfp\t\t  enable double-precision floating point instructions\n");
   3419  1.4.8.1  pgoyette   fprintf (stream, "  -mfpuda\t\t  enable double-precision assist floating "
   3420  1.4.8.1  pgoyette                    "point\n\t\t\t  instructions for ARC EM\n");
   3421  1.4.8.1  pgoyette 
   3422  1.4.8.1  pgoyette   fprintf (stream,
   3423  1.4.8.1  pgoyette 	   "  -mcode-density\t  enable code density option for ARC EM\n");
   3424  1.4.8.1  pgoyette 
   3425  1.4.8.1  pgoyette   fprintf (stream, _("\
   3426  1.4.8.1  pgoyette   -EB                     assemble code for a big-endian cpu\n"));
   3427  1.4.8.1  pgoyette   fprintf (stream, _("\
   3428  1.4.8.1  pgoyette   -EL                     assemble code for a little-endian cpu\n"));
   3429  1.4.8.1  pgoyette   fprintf (stream, _("\
   3430  1.4.8.1  pgoyette   -mrelax                 enable relaxation\n"));
   3431  1.4.8.1  pgoyette 
   3432  1.4.8.1  pgoyette   fprintf (stream, _("The following ARC-specific assembler options are "
   3433  1.4.8.1  pgoyette                      "deprecated and are accepted\nfor compatibility only:\n"));
   3434      1.3  christos 
   3435  1.4.8.1  pgoyette   fprintf (stream, _("  -mEA\n"
   3436  1.4.8.1  pgoyette                      "  -mbarrel-shifter\n"
   3437  1.4.8.1  pgoyette                      "  -mbarrel_shifter\n"
   3438  1.4.8.1  pgoyette                      "  -mcrc\n"
   3439  1.4.8.1  pgoyette                      "  -mdsp-packa\n"
   3440  1.4.8.1  pgoyette                      "  -mdsp_packa\n"
   3441  1.4.8.1  pgoyette                      "  -mdvbf\n"
   3442  1.4.8.1  pgoyette                      "  -mld-extension-reg-mask\n"
   3443  1.4.8.1  pgoyette                      "  -mlock\n"
   3444  1.4.8.1  pgoyette                      "  -mmac-24\n"
   3445  1.4.8.1  pgoyette                      "  -mmac-d16\n"
   3446  1.4.8.1  pgoyette                      "  -mmac_24\n"
   3447  1.4.8.1  pgoyette                      "  -mmac_d16\n"
   3448  1.4.8.1  pgoyette                      "  -mmin-max\n"
   3449  1.4.8.1  pgoyette                      "  -mmin_max\n"
   3450  1.4.8.1  pgoyette                      "  -mmul64\n"
   3451  1.4.8.1  pgoyette                      "  -mno-mpy\n"
   3452  1.4.8.1  pgoyette                      "  -mnorm\n"
   3453  1.4.8.1  pgoyette                      "  -mrtsc\n"
   3454  1.4.8.1  pgoyette                      "  -msimd\n"
   3455  1.4.8.1  pgoyette                      "  -mswap\n"
   3456  1.4.8.1  pgoyette                      "  -mswape\n"
   3457  1.4.8.1  pgoyette                      "  -mtelephony\n"
   3458  1.4.8.1  pgoyette 		     "  -muser-mode-only\n"
   3459  1.4.8.1  pgoyette                      "  -mxy\n"));
   3460      1.3  christos }
   3461      1.3  christos 
   3462      1.3  christos /* Find the proper relocation for the given opcode.  */
   3463      1.3  christos 
   3464      1.3  christos static extended_bfd_reloc_code_real_type
   3465      1.3  christos find_reloc (const char *name,
   3466      1.3  christos 	    const char *opcodename,
   3467      1.3  christos 	    const struct arc_flags *pflags,
   3468      1.3  christos 	    int nflg,
   3469      1.3  christos 	    extended_bfd_reloc_code_real_type reloc)
   3470      1.3  christos {
   3471      1.3  christos   unsigned int i;
   3472      1.3  christos   int j;
   3473  1.4.8.1  pgoyette   bfd_boolean found_flag, tmp;
   3474      1.3  christos   extended_bfd_reloc_code_real_type ret = BFD_RELOC_UNUSED;
   3475      1.3  christos 
   3476      1.3  christos   for (i = 0; i < arc_num_equiv_tab; i++)
   3477      1.3  christos     {
   3478      1.3  christos       const struct arc_reloc_equiv_tab *r = &arc_reloc_equiv[i];
   3479      1.3  christos 
   3480      1.3  christos       /* Find the entry.  */
   3481      1.3  christos       if (strcmp (name, r->name))
   3482      1.3  christos 	continue;
   3483      1.3  christos       if (r->mnemonic && (strcmp (r->mnemonic, opcodename)))
   3484      1.3  christos 	continue;
   3485  1.4.8.1  pgoyette       if (r->flags[0])
   3486      1.3  christos 	{
   3487      1.3  christos 	  if (!nflg)
   3488      1.3  christos 	    continue;
   3489      1.3  christos 	  found_flag = FALSE;
   3490  1.4.8.1  pgoyette 	  unsigned * psflg = (unsigned *)r->flags;
   3491  1.4.8.1  pgoyette 	  do
   3492  1.4.8.1  pgoyette 	    {
   3493  1.4.8.1  pgoyette 	      tmp = FALSE;
   3494  1.4.8.1  pgoyette 	      for (j = 0; j < nflg; j++)
   3495  1.4.8.1  pgoyette 		if (!strcmp (pflags[j].name,
   3496  1.4.8.1  pgoyette 			     arc_flag_operands[*psflg].name))
   3497  1.4.8.1  pgoyette 		  {
   3498  1.4.8.1  pgoyette 		    tmp = TRUE;
   3499  1.4.8.1  pgoyette 		    break;
   3500  1.4.8.1  pgoyette 		  }
   3501  1.4.8.1  pgoyette 	      if (!tmp)
   3502  1.4.8.1  pgoyette 		{
   3503  1.4.8.1  pgoyette 		  found_flag = FALSE;
   3504  1.4.8.1  pgoyette 		  break;
   3505  1.4.8.1  pgoyette 		}
   3506  1.4.8.1  pgoyette 	      else
   3507  1.4.8.1  pgoyette 		{
   3508  1.4.8.1  pgoyette 		  found_flag = TRUE;
   3509  1.4.8.1  pgoyette 		}
   3510  1.4.8.1  pgoyette 	      ++ psflg;
   3511  1.4.8.1  pgoyette 	    } while (*psflg);
   3512  1.4.8.1  pgoyette 
   3513      1.3  christos 	  if (!found_flag)
   3514      1.3  christos 	    continue;
   3515      1.3  christos 	}
   3516      1.3  christos 
   3517      1.3  christos       if (reloc != r->oldreloc)
   3518      1.3  christos 	continue;
   3519      1.3  christos       /* Found it.  */
   3520      1.3  christos       ret = r->newreloc;
   3521      1.3  christos       break;
   3522      1.3  christos     }
   3523      1.3  christos 
   3524      1.3  christos   if (ret == BFD_RELOC_UNUSED)
   3525      1.3  christos     as_bad (_("Unable to find %s relocation for instruction %s"),
   3526      1.3  christos 	    name, opcodename);
   3527      1.3  christos   return ret;
   3528      1.3  christos }
   3529      1.3  christos 
   3530  1.4.8.1  pgoyette /* All the symbol types that are allowed to be used for
   3531  1.4.8.1  pgoyette    relaxation.  */
   3532  1.4.8.1  pgoyette 
   3533  1.4.8.1  pgoyette static bfd_boolean
   3534  1.4.8.1  pgoyette may_relax_expr (expressionS tok)
   3535  1.4.8.1  pgoyette {
   3536  1.4.8.1  pgoyette   /* Check if we have unrelaxable relocs.  */
   3537  1.4.8.1  pgoyette   switch (tok.X_md)
   3538  1.4.8.1  pgoyette     {
   3539  1.4.8.1  pgoyette     default:
   3540  1.4.8.1  pgoyette       break;
   3541  1.4.8.1  pgoyette     case O_plt:
   3542  1.4.8.1  pgoyette       return FALSE;
   3543  1.4.8.1  pgoyette     }
   3544  1.4.8.1  pgoyette 
   3545  1.4.8.1  pgoyette   switch (tok.X_op)
   3546  1.4.8.1  pgoyette     {
   3547  1.4.8.1  pgoyette     case O_symbol:
   3548  1.4.8.1  pgoyette     case O_multiply:
   3549  1.4.8.1  pgoyette     case O_divide:
   3550  1.4.8.1  pgoyette     case O_modulus:
   3551  1.4.8.1  pgoyette     case O_add:
   3552  1.4.8.1  pgoyette     case O_subtract:
   3553  1.4.8.1  pgoyette       break;
   3554  1.4.8.1  pgoyette 
   3555  1.4.8.1  pgoyette     default:
   3556  1.4.8.1  pgoyette       return FALSE;
   3557  1.4.8.1  pgoyette     }
   3558  1.4.8.1  pgoyette   return TRUE;
   3559  1.4.8.1  pgoyette }
   3560  1.4.8.1  pgoyette 
   3561  1.4.8.1  pgoyette /* Checks if flags are in line with relaxable insn.  */
   3562  1.4.8.1  pgoyette 
   3563  1.4.8.1  pgoyette static bfd_boolean
   3564  1.4.8.1  pgoyette relaxable_flag (const struct arc_relaxable_ins *ins,
   3565  1.4.8.1  pgoyette 		const struct arc_flags *pflags,
   3566  1.4.8.1  pgoyette 		int nflgs)
   3567  1.4.8.1  pgoyette {
   3568  1.4.8.1  pgoyette   unsigned flag_class,
   3569  1.4.8.1  pgoyette     flag,
   3570  1.4.8.1  pgoyette     flag_class_idx = 0,
   3571  1.4.8.1  pgoyette     flag_idx = 0;
   3572  1.4.8.1  pgoyette 
   3573  1.4.8.1  pgoyette   const struct arc_flag_operand *flag_opand;
   3574  1.4.8.1  pgoyette   int i, counttrue = 0;
   3575  1.4.8.1  pgoyette 
   3576  1.4.8.1  pgoyette   /* Iterate through flags classes.  */
   3577  1.4.8.1  pgoyette   while ((flag_class = ins->flag_classes[flag_class_idx]) != 0)
   3578  1.4.8.1  pgoyette     {
   3579  1.4.8.1  pgoyette       /* Iterate through flags in flag class.  */
   3580  1.4.8.1  pgoyette       while ((flag = arc_flag_classes[flag_class].flags[flag_idx])
   3581  1.4.8.1  pgoyette 	     != 0)
   3582  1.4.8.1  pgoyette 	{
   3583  1.4.8.1  pgoyette 	  flag_opand = &arc_flag_operands[flag];
   3584  1.4.8.1  pgoyette 	  /* Iterate through flags in ins to compare.  */
   3585  1.4.8.1  pgoyette 	  for (i = 0; i < nflgs; ++i)
   3586  1.4.8.1  pgoyette 	    {
   3587  1.4.8.1  pgoyette 	      if (strcmp (flag_opand->name, pflags[i].name) == 0)
   3588  1.4.8.1  pgoyette 		++counttrue;
   3589  1.4.8.1  pgoyette 	    }
   3590  1.4.8.1  pgoyette 
   3591  1.4.8.1  pgoyette 	  ++flag_idx;
   3592  1.4.8.1  pgoyette 	}
   3593  1.4.8.1  pgoyette 
   3594  1.4.8.1  pgoyette       ++flag_class_idx;
   3595  1.4.8.1  pgoyette       flag_idx = 0;
   3596  1.4.8.1  pgoyette     }
   3597  1.4.8.1  pgoyette 
   3598  1.4.8.1  pgoyette   /* If counttrue == nflgs, then all flags have been found.  */
   3599  1.4.8.1  pgoyette   return (counttrue == nflgs ? TRUE : FALSE);
   3600  1.4.8.1  pgoyette }
   3601  1.4.8.1  pgoyette 
   3602  1.4.8.1  pgoyette /* Checks if operands are in line with relaxable insn.  */
   3603  1.4.8.1  pgoyette 
   3604  1.4.8.1  pgoyette static bfd_boolean
   3605  1.4.8.1  pgoyette relaxable_operand (const struct arc_relaxable_ins *ins,
   3606  1.4.8.1  pgoyette 		   const expressionS *tok,
   3607  1.4.8.1  pgoyette 		   int ntok)
   3608  1.4.8.1  pgoyette {
   3609  1.4.8.1  pgoyette   const enum rlx_operand_type *operand = &ins->operands[0];
   3610  1.4.8.1  pgoyette   int i = 0;
   3611  1.4.8.1  pgoyette 
   3612  1.4.8.1  pgoyette   while (*operand != EMPTY)
   3613  1.4.8.1  pgoyette     {
   3614  1.4.8.1  pgoyette       const expressionS *epr = &tok[i];
   3615  1.4.8.1  pgoyette 
   3616  1.4.8.1  pgoyette       if (i != 0 && i >= ntok)
   3617  1.4.8.1  pgoyette 	return FALSE;
   3618  1.4.8.1  pgoyette 
   3619  1.4.8.1  pgoyette       switch (*operand)
   3620  1.4.8.1  pgoyette 	{
   3621  1.4.8.1  pgoyette 	case IMMEDIATE:
   3622  1.4.8.1  pgoyette 	  if (!(epr->X_op == O_multiply
   3623  1.4.8.1  pgoyette 		|| epr->X_op == O_divide
   3624  1.4.8.1  pgoyette 		|| epr->X_op == O_modulus
   3625  1.4.8.1  pgoyette 		|| epr->X_op == O_add
   3626  1.4.8.1  pgoyette 		|| epr->X_op == O_subtract
   3627  1.4.8.1  pgoyette 		|| epr->X_op == O_symbol))
   3628  1.4.8.1  pgoyette 	    return FALSE;
   3629  1.4.8.1  pgoyette 	  break;
   3630  1.4.8.1  pgoyette 
   3631  1.4.8.1  pgoyette 	case REGISTER_DUP:
   3632  1.4.8.1  pgoyette 	  if ((i <= 0)
   3633  1.4.8.1  pgoyette 	      || (epr->X_add_number != tok[i - 1].X_add_number))
   3634  1.4.8.1  pgoyette 	    return FALSE;
   3635  1.4.8.1  pgoyette 	  /* Fall through.  */
   3636  1.4.8.1  pgoyette 	case REGISTER:
   3637  1.4.8.1  pgoyette 	  if (epr->X_op != O_register)
   3638  1.4.8.1  pgoyette 	    return FALSE;
   3639  1.4.8.1  pgoyette 	  break;
   3640  1.4.8.1  pgoyette 
   3641  1.4.8.1  pgoyette 	case REGISTER_S:
   3642  1.4.8.1  pgoyette 	  if (epr->X_op != O_register)
   3643  1.4.8.1  pgoyette 	    return FALSE;
   3644  1.4.8.1  pgoyette 
   3645  1.4.8.1  pgoyette 	  switch (epr->X_add_number)
   3646  1.4.8.1  pgoyette 	    {
   3647  1.4.8.1  pgoyette 	    case 0: case 1: case 2: case 3:
   3648  1.4.8.1  pgoyette 	    case 12: case 13: case 14: case 15:
   3649  1.4.8.1  pgoyette 	      break;
   3650  1.4.8.1  pgoyette 	    default:
   3651  1.4.8.1  pgoyette 	      return FALSE;
   3652  1.4.8.1  pgoyette 	    }
   3653  1.4.8.1  pgoyette 	  break;
   3654  1.4.8.1  pgoyette 
   3655  1.4.8.1  pgoyette 	case REGISTER_NO_GP:
   3656  1.4.8.1  pgoyette 	  if ((epr->X_op != O_register)
   3657  1.4.8.1  pgoyette 	      || (epr->X_add_number == 26)) /* 26 is the gp register.  */
   3658  1.4.8.1  pgoyette 	    return FALSE;
   3659  1.4.8.1  pgoyette 	  break;
   3660  1.4.8.1  pgoyette 
   3661  1.4.8.1  pgoyette 	case BRACKET:
   3662  1.4.8.1  pgoyette 	  if (epr->X_op != O_bracket)
   3663  1.4.8.1  pgoyette 	    return FALSE;
   3664  1.4.8.1  pgoyette 	  break;
   3665  1.4.8.1  pgoyette 
   3666  1.4.8.1  pgoyette 	default:
   3667  1.4.8.1  pgoyette 	  /* Don't understand, bail out.  */
   3668  1.4.8.1  pgoyette 	  return FALSE;
   3669  1.4.8.1  pgoyette 	  break;
   3670  1.4.8.1  pgoyette 	}
   3671  1.4.8.1  pgoyette 
   3672  1.4.8.1  pgoyette       ++i;
   3673  1.4.8.1  pgoyette       operand = &ins->operands[i];
   3674  1.4.8.1  pgoyette     }
   3675  1.4.8.1  pgoyette 
   3676  1.4.8.1  pgoyette   return (i == ntok ? TRUE : FALSE);
   3677  1.4.8.1  pgoyette }
   3678  1.4.8.1  pgoyette 
   3679  1.4.8.1  pgoyette /* Return TRUE if this OPDCODE is a candidate for relaxation.  */
   3680  1.4.8.1  pgoyette 
   3681  1.4.8.1  pgoyette static bfd_boolean
   3682  1.4.8.1  pgoyette relax_insn_p (const struct arc_opcode *opcode,
   3683  1.4.8.1  pgoyette 	      const expressionS *tok,
   3684  1.4.8.1  pgoyette 	      int ntok,
   3685  1.4.8.1  pgoyette 	      const struct arc_flags *pflags,
   3686  1.4.8.1  pgoyette 	      int nflg)
   3687  1.4.8.1  pgoyette {
   3688  1.4.8.1  pgoyette   unsigned i;
   3689  1.4.8.1  pgoyette   bfd_boolean rv = FALSE;
   3690  1.4.8.1  pgoyette 
   3691  1.4.8.1  pgoyette   /* Check the relaxation table.  */
   3692  1.4.8.1  pgoyette   for (i = 0; i < arc_num_relaxable_ins && relaxation_state; ++i)
   3693  1.4.8.1  pgoyette     {
   3694  1.4.8.1  pgoyette       const struct arc_relaxable_ins *arc_rlx_ins = &arc_relaxable_insns[i];
   3695  1.4.8.1  pgoyette 
   3696  1.4.8.1  pgoyette       if ((strcmp (opcode->name, arc_rlx_ins->mnemonic_r) == 0)
   3697  1.4.8.1  pgoyette 	  && may_relax_expr (tok[arc_rlx_ins->opcheckidx])
   3698  1.4.8.1  pgoyette 	  && relaxable_operand (arc_rlx_ins, tok, ntok)
   3699  1.4.8.1  pgoyette 	  && relaxable_flag (arc_rlx_ins, pflags, nflg))
   3700  1.4.8.1  pgoyette 	{
   3701  1.4.8.1  pgoyette 	  rv = TRUE;
   3702  1.4.8.1  pgoyette 	  frag_now->fr_subtype = arc_relaxable_insns[i].subtype;
   3703  1.4.8.1  pgoyette 	  memcpy (&frag_now->tc_frag_data.tok, tok,
   3704  1.4.8.1  pgoyette 		sizeof (expressionS) * ntok);
   3705  1.4.8.1  pgoyette 	  memcpy (&frag_now->tc_frag_data.pflags, pflags,
   3706  1.4.8.1  pgoyette 		sizeof (struct arc_flags) * nflg);
   3707  1.4.8.1  pgoyette 	  frag_now->tc_frag_data.nflg = nflg;
   3708  1.4.8.1  pgoyette 	  frag_now->tc_frag_data.ntok = ntok;
   3709  1.4.8.1  pgoyette 	  break;
   3710  1.4.8.1  pgoyette 	}
   3711  1.4.8.1  pgoyette     }
   3712  1.4.8.1  pgoyette 
   3713  1.4.8.1  pgoyette   return rv;
   3714  1.4.8.1  pgoyette }
   3715  1.4.8.1  pgoyette 
   3716      1.3  christos /* Turn an opcode description and a set of arguments into
   3717      1.3  christos    an instruction and a fixup.  */
   3718      1.3  christos 
   3719      1.3  christos static void
   3720      1.3  christos assemble_insn (const struct arc_opcode *opcode,
   3721      1.3  christos 	       const expressionS *tok,
   3722      1.3  christos 	       int ntok,
   3723      1.3  christos 	       const struct arc_flags *pflags,
   3724      1.3  christos 	       int nflg,
   3725      1.3  christos 	       struct arc_insn *insn)
   3726      1.3  christos {
   3727      1.3  christos   const expressionS *reloc_exp = NULL;
   3728      1.3  christos   unsigned image;
   3729      1.3  christos   const unsigned char *argidx;
   3730      1.3  christos   int i;
   3731      1.3  christos   int tokidx = 0;
   3732      1.3  christos   unsigned char pcrel = 0;
   3733      1.3  christos   bfd_boolean needGOTSymbol;
   3734      1.3  christos   bfd_boolean has_delay_slot = FALSE;
   3735      1.3  christos   extended_bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED;
   3736      1.3  christos 
   3737      1.3  christos   memset (insn, 0, sizeof (*insn));
   3738      1.3  christos   image = opcode->opcode;
   3739      1.3  christos 
   3740      1.3  christos   pr_debug ("%s:%d: assemble_insn: %s using opcode %x\n",
   3741      1.3  christos 	    frag_now->fr_file, frag_now->fr_line, opcode->name,
   3742      1.3  christos 	    opcode->opcode);
   3743      1.3  christos 
   3744      1.3  christos   /* Handle operands.  */
   3745      1.3  christos   for (argidx = opcode->operands; *argidx; ++argidx)
   3746      1.3  christos     {
   3747      1.3  christos       const struct arc_operand *operand = &arc_operands[*argidx];
   3748      1.3  christos       const expressionS *t = (const expressionS *) 0;
   3749      1.3  christos 
   3750      1.3  christos       if ((operand->flags & ARC_OPERAND_FAKE)
   3751      1.3  christos 	  && !(operand->flags & ARC_OPERAND_BRAKET))
   3752      1.3  christos 	continue;
   3753      1.3  christos 
   3754      1.3  christos       if (operand->flags & ARC_OPERAND_DUPLICATE)
   3755      1.3  christos 	{
   3756      1.3  christos 	  /* Duplicate operand, already inserted.  */
   3757      1.3  christos 	  tokidx ++;
   3758      1.3  christos 	  continue;
   3759      1.3  christos 	}
   3760      1.3  christos 
   3761      1.3  christos       if (tokidx >= ntok)
   3762      1.3  christos 	{
   3763      1.3  christos 	  abort ();
   3764      1.3  christos 	}
   3765      1.3  christos       else
   3766      1.3  christos 	t = &tok[tokidx++];
   3767      1.3  christos 
   3768      1.3  christos       /* Regardless if we have a reloc or not mark the instruction
   3769      1.3  christos 	 limm if it is the case.  */
   3770      1.3  christos       if (operand->flags & ARC_OPERAND_LIMM)
   3771      1.3  christos 	insn->has_limm = TRUE;
   3772      1.3  christos 
   3773      1.3  christos       switch (t->X_op)
   3774      1.3  christos 	{
   3775      1.3  christos 	case O_register:
   3776      1.3  christos 	  image = insert_operand (image, operand, regno (t->X_add_number),
   3777      1.3  christos 				  NULL, 0);
   3778      1.3  christos 	  break;
   3779      1.3  christos 
   3780      1.3  christos 	case O_constant:
   3781      1.3  christos 	  image = insert_operand (image, operand, t->X_add_number, NULL, 0);
   3782      1.3  christos 	  reloc_exp = t;
   3783      1.3  christos 	  if (operand->flags & ARC_OPERAND_LIMM)
   3784      1.3  christos 	    insn->limm = t->X_add_number;
   3785      1.3  christos 	  break;
   3786      1.3  christos 
   3787      1.3  christos 	case O_bracket:
   3788      1.3  christos 	  /* Ignore brackets.  */
   3789      1.3  christos 	  break;
   3790      1.3  christos 
   3791      1.3  christos 	case O_absent:
   3792      1.3  christos 	  gas_assert (operand->flags & ARC_OPERAND_IGNORE);
   3793      1.3  christos 	  break;
   3794      1.3  christos 
   3795      1.3  christos 	case O_subtract:
   3796      1.3  christos 	  /* Maybe register range.  */
   3797      1.3  christos 	  if ((t->X_add_number == 0)
   3798      1.3  christos 	      && contains_register (t->X_add_symbol)
   3799      1.3  christos 	      && contains_register (t->X_op_symbol))
   3800      1.3  christos 	    {
   3801      1.3  christos 	      int regs;
   3802      1.3  christos 
   3803      1.3  christos 	      regs = get_register (t->X_add_symbol);
   3804      1.3  christos 	      regs <<= 16;
   3805      1.3  christos 	      regs |= get_register (t->X_op_symbol);
   3806      1.3  christos 	      image = insert_operand (image, operand, regs, NULL, 0);
   3807      1.3  christos 	      break;
   3808      1.3  christos 	    }
   3809      1.3  christos 
   3810      1.3  christos 	default:
   3811      1.3  christos 	  /* This operand needs a relocation.  */
   3812      1.3  christos 	  needGOTSymbol = FALSE;
   3813      1.3  christos 
   3814      1.3  christos 	  switch (t->X_md)
   3815      1.3  christos 	    {
   3816      1.3  christos 	    case O_plt:
   3817  1.4.8.1  pgoyette 	      if (opcode->insn_class == JUMP)
   3818  1.4.8.1  pgoyette 		as_bad_where (frag_now->fr_file, frag_now->fr_line,
   3819  1.4.8.1  pgoyette 			      _("Unable to use @plt relocatio for insn %s"),
   3820  1.4.8.1  pgoyette 			      opcode->name);
   3821      1.3  christos 	      needGOTSymbol = TRUE;
   3822      1.3  christos 	      reloc = find_reloc ("plt", opcode->name,
   3823      1.3  christos 				  pflags, nflg,
   3824      1.3  christos 				  operand->default_reloc);
   3825      1.3  christos 	      break;
   3826      1.3  christos 
   3827      1.3  christos 	    case O_gotoff:
   3828      1.3  christos 	    case O_gotpc:
   3829      1.3  christos 	      needGOTSymbol = TRUE;
   3830      1.3  christos 	      reloc = ARC_RELOC_TABLE (t->X_md)->reloc;
   3831      1.3  christos 	      break;
   3832      1.3  christos 	    case O_pcl:
   3833      1.3  christos 	      reloc = ARC_RELOC_TABLE (t->X_md)->reloc;
   3834  1.4.8.1  pgoyette 	      if (ARC_SHORT (opcode->mask) || opcode->insn_class == JUMP)
   3835      1.3  christos 		as_bad_where (frag_now->fr_file, frag_now->fr_line,
   3836      1.3  christos 			      _("Unable to use @pcl relocation for insn %s"),
   3837      1.3  christos 			      opcode->name);
   3838      1.3  christos 	      break;
   3839      1.3  christos 	    case O_sda:
   3840      1.3  christos 	      reloc = find_reloc ("sda", opcode->name,
   3841      1.3  christos 				  pflags, nflg,
   3842      1.3  christos 				  operand->default_reloc);
   3843      1.3  christos 	      break;
   3844      1.3  christos 	    case O_tlsgd:
   3845      1.3  christos 	    case O_tlsie:
   3846      1.3  christos 	      needGOTSymbol = TRUE;
   3847      1.3  christos 	      /* Fall-through.  */
   3848      1.3  christos 
   3849      1.3  christos 	    case O_tpoff:
   3850      1.3  christos 	    case O_dtpoff:
   3851      1.3  christos 	      reloc = ARC_RELOC_TABLE (t->X_md)->reloc;
   3852      1.3  christos 	      break;
   3853      1.3  christos 
   3854      1.3  christos 	    case O_tpoff9: /*FIXME! Check for the conditionality of
   3855      1.3  christos 			     the insn.  */
   3856      1.3  christos 	    case O_dtpoff9: /*FIXME! Check for the conditionality of
   3857      1.3  christos 			      the insn.  */
   3858      1.3  christos 	      as_bad (_("TLS_*_S9 relocs are not supported yet"));
   3859      1.3  christos 	      break;
   3860      1.3  christos 
   3861      1.3  christos 	    default:
   3862      1.3  christos 	      /* Just consider the default relocation.  */
   3863      1.3  christos 	      reloc = operand->default_reloc;
   3864      1.3  christos 	      break;
   3865      1.3  christos 	    }
   3866      1.3  christos 
   3867      1.3  christos 	  if (needGOTSymbol && (GOT_symbol == NULL))
   3868      1.3  christos 	    GOT_symbol = symbol_find_or_make (GLOBAL_OFFSET_TABLE_NAME);
   3869      1.3  christos 
   3870      1.3  christos 	  reloc_exp = t;
   3871      1.3  christos 
   3872      1.3  christos #if 0
   3873      1.3  christos 	  if (reloc > 0)
   3874      1.3  christos 	    {
   3875      1.3  christos 	      /* sanity checks.  */
   3876      1.3  christos 	      reloc_howto_type *reloc_howto
   3877      1.3  christos 		= bfd_reloc_type_lookup (stdoutput,
   3878      1.3  christos 					 (bfd_reloc_code_real_type) reloc);
   3879      1.3  christos 	      unsigned reloc_bitsize = reloc_howto->bitsize;
   3880      1.3  christos 	      if (reloc_howto->rightshift)
   3881      1.3  christos 		reloc_bitsize -= reloc_howto->rightshift;
   3882      1.3  christos 	      if (reloc_bitsize != operand->bits)
   3883      1.3  christos 		{
   3884      1.3  christos 		  as_bad (_("invalid relocation %s for field"),
   3885      1.3  christos 			  bfd_get_reloc_code_name (reloc));
   3886      1.3  christos 		  return;
   3887      1.3  christos 		}
   3888      1.3  christos 	    }
   3889      1.3  christos #endif
   3890      1.3  christos 	  if (insn->nfixups >= MAX_INSN_FIXUPS)
   3891      1.3  christos 	    as_fatal (_("too many fixups"));
   3892      1.3  christos 
   3893      1.3  christos 	  struct arc_fixup *fixup;
   3894      1.3  christos 	  fixup = &insn->fixups[insn->nfixups++];
   3895      1.3  christos 	  fixup->exp = *t;
   3896      1.3  christos 	  fixup->reloc = reloc;
   3897      1.3  christos 	  pcrel = (operand->flags & ARC_OPERAND_PCREL) ? 1 : 0;
   3898      1.3  christos 	  fixup->pcrel = pcrel;
   3899      1.3  christos 	  fixup->islong = (operand->flags & ARC_OPERAND_LIMM) ?
   3900      1.3  christos 	    TRUE : FALSE;
   3901      1.3  christos 	  break;
   3902      1.1  christos 	}
   3903      1.1  christos     }
   3904      1.1  christos 
   3905      1.3  christos   /* Handle flags.  */
   3906      1.3  christos   for (i = 0; i < nflg; i++)
   3907      1.3  christos     {
   3908  1.4.8.1  pgoyette       const struct arc_flag_operand *flg_operand = pflags[i].flgp;
   3909      1.3  christos 
   3910      1.3  christos       /* Check if the instruction has a delay slot.  */
   3911      1.3  christos       if (!strcmp (flg_operand->name, "d"))
   3912      1.3  christos 	has_delay_slot = TRUE;
   3913      1.3  christos 
   3914      1.3  christos       /* There is an exceptional case when we cannot insert a flag
   3915      1.3  christos 	 just as it is.  The .T flag must be handled in relation with
   3916      1.3  christos 	 the relative address.  */
   3917      1.3  christos       if (!strcmp (flg_operand->name, "t")
   3918      1.3  christos 	  || !strcmp (flg_operand->name, "nt"))
   3919      1.3  christos 	{
   3920      1.3  christos 	  unsigned bitYoperand = 0;
   3921      1.3  christos 	  /* FIXME! move selection bbit/brcc in arc-opc.c.  */
   3922      1.3  christos 	  if (!strcmp (flg_operand->name, "t"))
   3923      1.3  christos 	    if (!strcmp (opcode->name, "bbit0")
   3924      1.3  christos 		|| !strcmp (opcode->name, "bbit1"))
   3925      1.3  christos 	      bitYoperand = arc_NToperand;
   3926      1.3  christos 	    else
   3927      1.3  christos 	      bitYoperand = arc_Toperand;
   3928      1.3  christos 	  else
   3929      1.3  christos 	    if (!strcmp (opcode->name, "bbit0")
   3930      1.3  christos 		|| !strcmp (opcode->name, "bbit1"))
   3931      1.3  christos 	      bitYoperand = arc_Toperand;
   3932      1.3  christos 	    else
   3933      1.3  christos 	      bitYoperand = arc_NToperand;
   3934      1.3  christos 
   3935      1.3  christos 	  gas_assert (reloc_exp != NULL);
   3936      1.3  christos 	  if (reloc_exp->X_op == O_constant)
   3937      1.3  christos 	    {
   3938      1.3  christos 	      /* Check if we have a constant and solved it
   3939      1.3  christos 		 immediately.  */
   3940      1.3  christos 	      offsetT val = reloc_exp->X_add_number;
   3941      1.3  christos 	      image |= insert_operand (image, &arc_operands[bitYoperand],
   3942      1.3  christos 				       val, NULL, 0);
   3943      1.3  christos 	    }
   3944      1.3  christos 	  else
   3945      1.3  christos 	    {
   3946      1.3  christos 	      struct arc_fixup *fixup;
   3947      1.3  christos 
   3948      1.3  christos 	      if (insn->nfixups >= MAX_INSN_FIXUPS)
   3949      1.3  christos 		as_fatal (_("too many fixups"));
   3950      1.3  christos 
   3951      1.3  christos 	      fixup = &insn->fixups[insn->nfixups++];
   3952      1.3  christos 	      fixup->exp = *reloc_exp;
   3953      1.3  christos 	      fixup->reloc = -bitYoperand;
   3954      1.3  christos 	      fixup->pcrel = pcrel;
   3955      1.3  christos 	      fixup->islong = FALSE;
   3956      1.3  christos 	    }
   3957      1.3  christos 	}
   3958      1.3  christos       else
   3959      1.3  christos 	image |= (flg_operand->code & ((1 << flg_operand->bits) - 1))
   3960      1.3  christos 	  << flg_operand->shift;
   3961      1.3  christos     }
   3962      1.3  christos 
   3963  1.4.8.1  pgoyette   insn->relax = relax_insn_p (opcode, tok, ntok, pflags, nflg);
   3964  1.4.8.1  pgoyette 
   3965  1.4.8.1  pgoyette   /* Short instruction?  */
   3966  1.4.8.1  pgoyette   insn->short_insn = ARC_SHORT (opcode->mask) ? TRUE : FALSE;
   3967  1.4.8.1  pgoyette 
   3968  1.4.8.1  pgoyette   insn->insn = image;
   3969  1.4.8.1  pgoyette 
   3970  1.4.8.1  pgoyette   /* Update last insn status.  */
   3971  1.4.8.1  pgoyette   arc_last_insns[1]		   = arc_last_insns[0];
   3972  1.4.8.1  pgoyette   arc_last_insns[0].opcode	   = opcode;
   3973  1.4.8.1  pgoyette   arc_last_insns[0].has_limm	   = insn->has_limm;
   3974  1.4.8.1  pgoyette   arc_last_insns[0].has_delay_slot = has_delay_slot;
   3975  1.4.8.1  pgoyette 
   3976  1.4.8.1  pgoyette   /* Check if the current instruction is legally used.  */
   3977  1.4.8.1  pgoyette   if (arc_last_insns[1].has_delay_slot
   3978  1.4.8.1  pgoyette       && is_br_jmp_insn_p (arc_last_insns[0].opcode))
   3979  1.4.8.1  pgoyette     as_bad_where (frag_now->fr_file, frag_now->fr_line,
   3980  1.4.8.1  pgoyette 		  _("A jump/branch instruction in delay slot."));
   3981      1.3  christos }
   3982      1.3  christos 
   3983      1.3  christos void
   3984      1.3  christos arc_handle_align (fragS* fragP)
   3985      1.3  christos {
   3986      1.3  christos   if ((fragP)->fr_type == rs_align_code)
   3987      1.3  christos     {
   3988      1.3  christos       char *dest = (fragP)->fr_literal + (fragP)->fr_fix;
   3989      1.3  christos       valueT count = ((fragP)->fr_next->fr_address
   3990      1.3  christos 		      - (fragP)->fr_address - (fragP)->fr_fix);
   3991      1.3  christos 
   3992      1.3  christos       (fragP)->fr_var = 2;
   3993      1.3  christos 
   3994      1.3  christos       if (count & 1)/* Padding in the gap till the next 2-byte
   3995      1.3  christos 		       boundary with 0s.  */
   3996      1.3  christos 	{
   3997      1.3  christos 	  (fragP)->fr_fix++;
   3998      1.3  christos 	  *dest++ = 0;
   3999      1.3  christos 	}
   4000      1.3  christos       /* Writing nop_s.  */
   4001      1.3  christos       md_number_to_chars (dest, NOP_OPCODE_S, 2);
   4002      1.3  christos     }
   4003      1.3  christos }
   4004      1.3  christos 
   4005      1.3  christos /* Here we decide which fixups can be adjusted to make them relative
   4006      1.3  christos    to the beginning of the section instead of the symbol.  Basically
   4007      1.3  christos    we need to make sure that the dynamic relocations are done
   4008      1.3  christos    correctly, so in some cases we force the original symbol to be
   4009      1.3  christos    used.  */
   4010      1.3  christos 
   4011      1.3  christos int
   4012      1.3  christos tc_arc_fix_adjustable (fixS *fixP)
   4013      1.3  christos {
   4014      1.3  christos 
   4015      1.3  christos   /* Prevent all adjustments to global symbols.  */
   4016      1.3  christos   if (S_IS_EXTERNAL (fixP->fx_addsy))
   4017      1.3  christos     return 0;
   4018      1.3  christos   if (S_IS_WEAK (fixP->fx_addsy))
   4019      1.3  christos     return 0;
   4020      1.3  christos 
   4021      1.3  christos   /* Adjust_reloc_syms doesn't know about the GOT.  */
   4022      1.3  christos   switch (fixP->fx_r_type)
   4023      1.3  christos     {
   4024      1.3  christos     case BFD_RELOC_ARC_GOTPC32:
   4025      1.3  christos     case BFD_RELOC_ARC_PLT32:
   4026      1.3  christos     case BFD_RELOC_ARC_S25H_PCREL_PLT:
   4027      1.3  christos     case BFD_RELOC_ARC_S21H_PCREL_PLT:
   4028      1.3  christos     case BFD_RELOC_ARC_S25W_PCREL_PLT:
   4029      1.3  christos     case BFD_RELOC_ARC_S21W_PCREL_PLT:
   4030      1.3  christos       return 0;
   4031      1.3  christos 
   4032      1.3  christos     default:
   4033      1.3  christos       break;
   4034      1.3  christos     }
   4035      1.3  christos 
   4036  1.4.8.1  pgoyette   return 1;
   4037      1.3  christos }
   4038      1.3  christos 
   4039      1.3  christos /* Compute the reloc type of an expression EXP.  */
   4040      1.3  christos 
   4041      1.3  christos static void
   4042      1.3  christos arc_check_reloc (expressionS *exp,
   4043      1.3  christos 		 bfd_reloc_code_real_type *r_type_p)
   4044      1.3  christos {
   4045      1.3  christos   if (*r_type_p == BFD_RELOC_32
   4046      1.3  christos       && exp->X_op == O_subtract
   4047      1.3  christos       && exp->X_op_symbol != NULL
   4048      1.3  christos       && exp->X_op_symbol->bsym->section == now_seg)
   4049      1.3  christos     *r_type_p = BFD_RELOC_ARC_32_PCREL;
   4050      1.3  christos }
   4051      1.3  christos 
   4052      1.3  christos 
   4053      1.3  christos /* Add expression EXP of SIZE bytes to offset OFF of fragment FRAG.  */
   4054      1.3  christos 
   4055      1.3  christos void
   4056      1.3  christos arc_cons_fix_new (fragS *frag,
   4057      1.3  christos 		  int off,
   4058      1.3  christos 		  int size,
   4059      1.3  christos 		  expressionS *exp,
   4060      1.3  christos 		  bfd_reloc_code_real_type r_type)
   4061      1.3  christos {
   4062      1.3  christos   r_type = BFD_RELOC_UNUSED;
   4063      1.3  christos 
   4064      1.3  christos   switch (size)
   4065      1.3  christos     {
   4066      1.3  christos     case 1:
   4067      1.3  christos       r_type = BFD_RELOC_8;
   4068      1.3  christos       break;
   4069      1.3  christos 
   4070      1.3  christos     case 2:
   4071      1.3  christos       r_type = BFD_RELOC_16;
   4072      1.3  christos       break;
   4073      1.3  christos 
   4074      1.3  christos     case 3:
   4075      1.3  christos       r_type = BFD_RELOC_24;
   4076      1.3  christos       break;
   4077      1.3  christos 
   4078      1.3  christos     case 4:
   4079      1.3  christos       r_type = BFD_RELOC_32;
   4080      1.3  christos       arc_check_reloc (exp, &r_type);
   4081      1.3  christos       break;
   4082      1.3  christos 
   4083      1.3  christos     case 8:
   4084      1.3  christos       r_type = BFD_RELOC_64;
   4085      1.3  christos       break;
   4086      1.3  christos 
   4087      1.3  christos     default:
   4088      1.3  christos       as_bad (_("unsupported BFD relocation size %u"), size);
   4089      1.3  christos       r_type = BFD_RELOC_UNUSED;
   4090      1.3  christos     }
   4091      1.3  christos 
   4092      1.3  christos   fix_new_exp (frag, off, size, exp, 0, r_type);
   4093      1.3  christos }
   4094      1.3  christos 
   4095      1.3  christos /* The actual routine that checks the ZOL conditions.  */
   4096      1.3  christos 
   4097      1.3  christos static void
   4098      1.3  christos check_zol (symbolS *s)
   4099      1.3  christos {
   4100      1.3  christos   switch (arc_mach_type)
   4101      1.3  christos     {
   4102      1.3  christos     case bfd_mach_arc_arcv2:
   4103      1.3  christos       if (arc_target & ARC_OPCODE_ARCv2EM)
   4104      1.3  christos 	return;
   4105      1.3  christos 
   4106      1.3  christos       if (is_br_jmp_insn_p (arc_last_insns[0].opcode)
   4107      1.3  christos 	  || arc_last_insns[1].has_delay_slot)
   4108      1.3  christos 	as_bad (_("Jump/Branch instruction detected at the end of the ZOL label @%s"),
   4109      1.3  christos 		S_GET_NAME (s));
   4110      1.3  christos 
   4111      1.3  christos       break;
   4112      1.3  christos     case bfd_mach_arc_arc600:
   4113      1.3  christos 
   4114      1.3  christos       if (is_kernel_insn_p (arc_last_insns[0].opcode))
   4115      1.3  christos 	as_bad (_("Kernel instruction detected at the end of the ZOL label @%s"),
   4116      1.3  christos 		S_GET_NAME (s));
   4117      1.3  christos 
   4118      1.3  christos       if (arc_last_insns[0].has_limm
   4119      1.3  christos 	  && is_br_jmp_insn_p (arc_last_insns[0].opcode))
   4120      1.3  christos 	as_bad (_("A jump instruction with long immediate detected at the \
   4121      1.3  christos end of the ZOL label @%s"), S_GET_NAME (s));
   4122      1.3  christos 
   4123      1.3  christos       /* Fall through.  */
   4124      1.3  christos     case bfd_mach_arc_arc700:
   4125      1.3  christos       if (arc_last_insns[0].has_delay_slot)
   4126      1.3  christos 	as_bad (_("An illegal use of delay slot detected at the end of the ZOL label @%s"),
   4127      1.3  christos 		S_GET_NAME (s));
   4128      1.3  christos 
   4129      1.3  christos       break;
   4130      1.3  christos     default:
   4131      1.3  christos       break;
   4132      1.3  christos     }
   4133      1.3  christos }
   4134      1.3  christos 
   4135      1.3  christos /* If ZOL end check the last two instruction for illegals.  */
   4136      1.3  christos void
   4137      1.3  christos arc_frob_label (symbolS * sym)
   4138      1.3  christos {
   4139      1.3  christos   if (ARC_GET_FLAG (sym) & ARC_FLAG_ZOL)
   4140      1.3  christos     check_zol (sym);
   4141      1.3  christos 
   4142      1.3  christos   dwarf2_emit_label (sym);
   4143      1.1  christos }
   4144  1.4.8.1  pgoyette 
   4145  1.4.8.1  pgoyette /* Used because generic relaxation assumes a pc-rel value whilst we
   4146  1.4.8.1  pgoyette    also relax instructions that use an absolute value resolved out of
   4147  1.4.8.1  pgoyette    relative values (if that makes any sense).  An example: 'add r1,
   4148  1.4.8.1  pgoyette    r2, @.L2 - .'  The symbols . and @.L2 are relative to the section
   4149  1.4.8.1  pgoyette    but if they're in the same section we can subtract the section
   4150  1.4.8.1  pgoyette    offset relocation which ends up in a resolved value.  So if @.L2 is
   4151  1.4.8.1  pgoyette    .text + 0x50 and . is .text + 0x10, we can say that .text + 0x50 -
   4152  1.4.8.1  pgoyette    .text + 0x40 = 0x10.  */
   4153  1.4.8.1  pgoyette int
   4154  1.4.8.1  pgoyette arc_pcrel_adjust (fragS *fragP)
   4155  1.4.8.1  pgoyette {
   4156  1.4.8.1  pgoyette   if (!fragP->tc_frag_data.pcrel)
   4157  1.4.8.1  pgoyette     return fragP->fr_address + fragP->fr_fix;
   4158  1.4.8.1  pgoyette 
   4159  1.4.8.1  pgoyette   return 0;
   4160  1.4.8.1  pgoyette }
   4161  1.4.8.1  pgoyette 
   4162  1.4.8.1  pgoyette /* Initialize the DWARF-2 unwind information for this procedure.  */
   4163  1.4.8.1  pgoyette 
   4164  1.4.8.1  pgoyette void
   4165  1.4.8.1  pgoyette tc_arc_frame_initial_instructions (void)
   4166  1.4.8.1  pgoyette {
   4167  1.4.8.1  pgoyette   /* Stack pointer is register 28.  */
   4168  1.4.8.1  pgoyette   cfi_add_CFA_def_cfa (28, 0);
   4169  1.4.8.1  pgoyette }
   4170  1.4.8.1  pgoyette 
   4171  1.4.8.1  pgoyette int
   4172  1.4.8.1  pgoyette tc_arc_regname_to_dw2regnum (char *regname)
   4173  1.4.8.1  pgoyette {
   4174  1.4.8.1  pgoyette   struct symbol *sym;
   4175  1.4.8.1  pgoyette 
   4176  1.4.8.1  pgoyette   sym = hash_find (arc_reg_hash, regname);
   4177  1.4.8.1  pgoyette   if (sym)
   4178  1.4.8.1  pgoyette     return S_GET_VALUE (sym);
   4179  1.4.8.1  pgoyette 
   4180  1.4.8.1  pgoyette   return -1;
   4181  1.4.8.1  pgoyette }
   4182  1.4.8.1  pgoyette 
   4183  1.4.8.1  pgoyette /* Adjust the symbol table.  Delete found AUX register symbols.  */
   4184  1.4.8.1  pgoyette 
   4185  1.4.8.1  pgoyette void
   4186  1.4.8.1  pgoyette arc_adjust_symtab (void)
   4187  1.4.8.1  pgoyette {
   4188  1.4.8.1  pgoyette   symbolS * sym;
   4189  1.4.8.1  pgoyette 
   4190  1.4.8.1  pgoyette   for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
   4191  1.4.8.1  pgoyette     {
   4192  1.4.8.1  pgoyette       /* I've created a symbol during parsing process.  Now, remove
   4193  1.4.8.1  pgoyette 	 the symbol as it is found to be an AUX register.  */
   4194  1.4.8.1  pgoyette       if (ARC_GET_FLAG (sym) & ARC_FLAG_AUX)
   4195  1.4.8.1  pgoyette 	symbol_remove (sym, &symbol_rootP, &symbol_lastP);
   4196  1.4.8.1  pgoyette     }
   4197  1.4.8.1  pgoyette 
   4198  1.4.8.1  pgoyette   /* Now do generic ELF adjustments.  */
   4199  1.4.8.1  pgoyette   elf_adjust_symtab ();
   4200  1.4.8.1  pgoyette }
   4201  1.4.8.1  pgoyette 
   4202  1.4.8.1  pgoyette static void
   4203  1.4.8.1  pgoyette tokenize_extinsn (extInstruction_t *einsn)
   4204  1.4.8.1  pgoyette {
   4205  1.4.8.1  pgoyette   char *p, c;
   4206  1.4.8.1  pgoyette   char *insn_name;
   4207  1.4.8.1  pgoyette   unsigned char major_opcode;
   4208  1.4.8.1  pgoyette   unsigned char sub_opcode;
   4209  1.4.8.1  pgoyette   unsigned char syntax_class = 0;
   4210  1.4.8.1  pgoyette   unsigned char syntax_class_modifiers = 0;
   4211  1.4.8.1  pgoyette   unsigned char suffix_class = 0;
   4212  1.4.8.1  pgoyette   unsigned int i;
   4213  1.4.8.1  pgoyette 
   4214  1.4.8.1  pgoyette   SKIP_WHITESPACE ();
   4215  1.4.8.1  pgoyette 
   4216  1.4.8.1  pgoyette   /* 1st: get instruction name.  */
   4217  1.4.8.1  pgoyette   p = input_line_pointer;
   4218  1.4.8.1  pgoyette   c = get_symbol_name (&p);
   4219  1.4.8.1  pgoyette 
   4220  1.4.8.1  pgoyette   insn_name = xstrdup (p);
   4221  1.4.8.1  pgoyette   restore_line_pointer (c);
   4222  1.4.8.1  pgoyette 
   4223  1.4.8.1  pgoyette   /* 2nd: get major opcode.  */
   4224  1.4.8.1  pgoyette   if (*input_line_pointer != ',')
   4225  1.4.8.1  pgoyette     {
   4226  1.4.8.1  pgoyette       as_bad (_("expected comma after instruction name"));
   4227  1.4.8.1  pgoyette       ignore_rest_of_line ();
   4228  1.4.8.1  pgoyette       return;
   4229  1.4.8.1  pgoyette     }
   4230  1.4.8.1  pgoyette   input_line_pointer++;
   4231  1.4.8.1  pgoyette   major_opcode = get_absolute_expression ();
   4232  1.4.8.1  pgoyette 
   4233  1.4.8.1  pgoyette   /* 3rd: get sub-opcode.  */
   4234  1.4.8.1  pgoyette   SKIP_WHITESPACE ();
   4235  1.4.8.1  pgoyette 
   4236  1.4.8.1  pgoyette   if (*input_line_pointer != ',')
   4237  1.4.8.1  pgoyette     {
   4238  1.4.8.1  pgoyette       as_bad (_("expected comma after major opcode"));
   4239  1.4.8.1  pgoyette       ignore_rest_of_line ();
   4240  1.4.8.1  pgoyette       return;
   4241  1.4.8.1  pgoyette     }
   4242  1.4.8.1  pgoyette   input_line_pointer++;
   4243  1.4.8.1  pgoyette   sub_opcode = get_absolute_expression ();
   4244  1.4.8.1  pgoyette 
   4245  1.4.8.1  pgoyette   /* 4th: get suffix class.  */
   4246  1.4.8.1  pgoyette   SKIP_WHITESPACE ();
   4247  1.4.8.1  pgoyette 
   4248  1.4.8.1  pgoyette   if (*input_line_pointer != ',')
   4249  1.4.8.1  pgoyette     {
   4250  1.4.8.1  pgoyette       as_bad ("expected comma after sub opcode");
   4251  1.4.8.1  pgoyette       ignore_rest_of_line ();
   4252  1.4.8.1  pgoyette       return;
   4253  1.4.8.1  pgoyette     }
   4254  1.4.8.1  pgoyette   input_line_pointer++;
   4255  1.4.8.1  pgoyette 
   4256  1.4.8.1  pgoyette   while (1)
   4257  1.4.8.1  pgoyette     {
   4258  1.4.8.1  pgoyette       SKIP_WHITESPACE ();
   4259  1.4.8.1  pgoyette 
   4260  1.4.8.1  pgoyette       for (i = 0; i < ARRAY_SIZE (suffixclass); i++)
   4261  1.4.8.1  pgoyette 	{
   4262  1.4.8.1  pgoyette 	  if (!strncmp (suffixclass[i].name, input_line_pointer,
   4263  1.4.8.1  pgoyette 			suffixclass[i].len))
   4264  1.4.8.1  pgoyette 	    {
   4265  1.4.8.1  pgoyette 	      suffix_class |= suffixclass[i].attr_class;
   4266  1.4.8.1  pgoyette 	      input_line_pointer += suffixclass[i].len;
   4267  1.4.8.1  pgoyette 	      break;
   4268  1.4.8.1  pgoyette 	    }
   4269  1.4.8.1  pgoyette 	}
   4270  1.4.8.1  pgoyette 
   4271  1.4.8.1  pgoyette       if (i == ARRAY_SIZE (suffixclass))
   4272  1.4.8.1  pgoyette 	{
   4273  1.4.8.1  pgoyette 	  as_bad ("invalid suffix class");
   4274  1.4.8.1  pgoyette 	  ignore_rest_of_line ();
   4275  1.4.8.1  pgoyette 	  return;
   4276  1.4.8.1  pgoyette 	}
   4277  1.4.8.1  pgoyette 
   4278  1.4.8.1  pgoyette       SKIP_WHITESPACE ();
   4279  1.4.8.1  pgoyette 
   4280  1.4.8.1  pgoyette       if (*input_line_pointer == '|')
   4281  1.4.8.1  pgoyette 	input_line_pointer++;
   4282  1.4.8.1  pgoyette       else
   4283  1.4.8.1  pgoyette 	break;
   4284  1.4.8.1  pgoyette     }
   4285  1.4.8.1  pgoyette 
   4286  1.4.8.1  pgoyette   /* 5th: get syntax class and syntax class modifiers.  */
   4287  1.4.8.1  pgoyette   if (*input_line_pointer != ',')
   4288  1.4.8.1  pgoyette     {
   4289  1.4.8.1  pgoyette       as_bad ("expected comma after suffix class");
   4290  1.4.8.1  pgoyette       ignore_rest_of_line ();
   4291  1.4.8.1  pgoyette       return;
   4292  1.4.8.1  pgoyette     }
   4293  1.4.8.1  pgoyette   input_line_pointer++;
   4294  1.4.8.1  pgoyette 
   4295  1.4.8.1  pgoyette   while (1)
   4296  1.4.8.1  pgoyette     {
   4297  1.4.8.1  pgoyette       SKIP_WHITESPACE ();
   4298  1.4.8.1  pgoyette 
   4299  1.4.8.1  pgoyette       for (i = 0; i < ARRAY_SIZE (syntaxclassmod); i++)
   4300  1.4.8.1  pgoyette 	{
   4301  1.4.8.1  pgoyette 	  if (!strncmp (syntaxclassmod[i].name,
   4302  1.4.8.1  pgoyette 			input_line_pointer,
   4303  1.4.8.1  pgoyette 			syntaxclassmod[i].len))
   4304  1.4.8.1  pgoyette 	    {
   4305  1.4.8.1  pgoyette 	      syntax_class_modifiers |= syntaxclassmod[i].attr_class;
   4306  1.4.8.1  pgoyette 	      input_line_pointer += syntaxclassmod[i].len;
   4307  1.4.8.1  pgoyette 	      break;
   4308  1.4.8.1  pgoyette 	    }
   4309  1.4.8.1  pgoyette 	}
   4310  1.4.8.1  pgoyette 
   4311  1.4.8.1  pgoyette       if (i == ARRAY_SIZE (syntaxclassmod))
   4312  1.4.8.1  pgoyette 	{
   4313  1.4.8.1  pgoyette 	  for (i = 0; i < ARRAY_SIZE (syntaxclass); i++)
   4314  1.4.8.1  pgoyette 	    {
   4315  1.4.8.1  pgoyette 	      if (!strncmp (syntaxclass[i].name,
   4316  1.4.8.1  pgoyette 			    input_line_pointer,
   4317  1.4.8.1  pgoyette 			    syntaxclass[i].len))
   4318  1.4.8.1  pgoyette 		{
   4319  1.4.8.1  pgoyette 		  syntax_class |= syntaxclass[i].attr_class;
   4320  1.4.8.1  pgoyette 		  input_line_pointer += syntaxclass[i].len;
   4321  1.4.8.1  pgoyette 		  break;
   4322  1.4.8.1  pgoyette 		}
   4323  1.4.8.1  pgoyette 	    }
   4324  1.4.8.1  pgoyette 
   4325  1.4.8.1  pgoyette 	  if (i == ARRAY_SIZE (syntaxclass))
   4326  1.4.8.1  pgoyette 	    {
   4327  1.4.8.1  pgoyette 	      as_bad ("missing syntax class");
   4328  1.4.8.1  pgoyette 	      ignore_rest_of_line ();
   4329  1.4.8.1  pgoyette 	      return;
   4330  1.4.8.1  pgoyette 	    }
   4331  1.4.8.1  pgoyette 	}
   4332  1.4.8.1  pgoyette 
   4333  1.4.8.1  pgoyette       SKIP_WHITESPACE ();
   4334  1.4.8.1  pgoyette 
   4335  1.4.8.1  pgoyette       if (*input_line_pointer == '|')
   4336  1.4.8.1  pgoyette 	input_line_pointer++;
   4337  1.4.8.1  pgoyette       else
   4338  1.4.8.1  pgoyette 	break;
   4339  1.4.8.1  pgoyette     }
   4340  1.4.8.1  pgoyette 
   4341  1.4.8.1  pgoyette   demand_empty_rest_of_line ();
   4342  1.4.8.1  pgoyette 
   4343  1.4.8.1  pgoyette   einsn->name   = insn_name;
   4344  1.4.8.1  pgoyette   einsn->major  = major_opcode;
   4345  1.4.8.1  pgoyette   einsn->minor  = sub_opcode;
   4346  1.4.8.1  pgoyette   einsn->syntax = syntax_class;
   4347  1.4.8.1  pgoyette   einsn->modsyn = syntax_class_modifiers;
   4348  1.4.8.1  pgoyette   einsn->suffix = suffix_class;
   4349  1.4.8.1  pgoyette   einsn->flags  = syntax_class
   4350  1.4.8.1  pgoyette     | (syntax_class_modifiers & ARC_OP1_IMM_IMPLIED ? 0x10 : 0);
   4351  1.4.8.1  pgoyette }
   4352  1.4.8.1  pgoyette 
   4353  1.4.8.1  pgoyette /* Generate an extension section.  */
   4354  1.4.8.1  pgoyette 
   4355  1.4.8.1  pgoyette static int
   4356  1.4.8.1  pgoyette arc_set_ext_seg (void)
   4357  1.4.8.1  pgoyette {
   4358  1.4.8.1  pgoyette   if (!arcext_section)
   4359  1.4.8.1  pgoyette     {
   4360  1.4.8.1  pgoyette       arcext_section = subseg_new (".arcextmap", 0);
   4361  1.4.8.1  pgoyette       bfd_set_section_flags (stdoutput, arcext_section,
   4362  1.4.8.1  pgoyette 			     SEC_READONLY | SEC_HAS_CONTENTS);
   4363  1.4.8.1  pgoyette     }
   4364  1.4.8.1  pgoyette   else
   4365  1.4.8.1  pgoyette     subseg_set (arcext_section, 0);
   4366  1.4.8.1  pgoyette   return 1;
   4367  1.4.8.1  pgoyette }
   4368  1.4.8.1  pgoyette 
   4369  1.4.8.1  pgoyette /* Create an extension instruction description in the arc extension
   4370  1.4.8.1  pgoyette    section of the output file.
   4371  1.4.8.1  pgoyette    The structure for an instruction is like this:
   4372  1.4.8.1  pgoyette    [0]: Length of the record.
   4373  1.4.8.1  pgoyette    [1]: Type of the record.
   4374  1.4.8.1  pgoyette 
   4375  1.4.8.1  pgoyette    [2]: Major opcode.
   4376  1.4.8.1  pgoyette    [3]: Sub-opcode.
   4377  1.4.8.1  pgoyette    [4]: Syntax (flags).
   4378  1.4.8.1  pgoyette    [5]+ Name instruction.
   4379  1.4.8.1  pgoyette 
   4380  1.4.8.1  pgoyette    The sequence is terminated by an empty entry.  */
   4381  1.4.8.1  pgoyette 
   4382  1.4.8.1  pgoyette static void
   4383  1.4.8.1  pgoyette create_extinst_section (extInstruction_t *einsn)
   4384  1.4.8.1  pgoyette {
   4385  1.4.8.1  pgoyette 
   4386  1.4.8.1  pgoyette   segT old_sec    = now_seg;
   4387  1.4.8.1  pgoyette   int old_subsec  = now_subseg;
   4388  1.4.8.1  pgoyette   char *p;
   4389  1.4.8.1  pgoyette   int name_len    = strlen (einsn->name);
   4390  1.4.8.1  pgoyette 
   4391  1.4.8.1  pgoyette   arc_set_ext_seg ();
   4392  1.4.8.1  pgoyette 
   4393  1.4.8.1  pgoyette   p = frag_more (1);
   4394  1.4.8.1  pgoyette   *p = 5 + name_len + 1;
   4395  1.4.8.1  pgoyette   p = frag_more (1);
   4396  1.4.8.1  pgoyette   *p = EXT_INSTRUCTION;
   4397  1.4.8.1  pgoyette   p = frag_more (1);
   4398  1.4.8.1  pgoyette   *p = einsn->major;
   4399  1.4.8.1  pgoyette   p = frag_more (1);
   4400  1.4.8.1  pgoyette   *p = einsn->minor;
   4401  1.4.8.1  pgoyette   p = frag_more (1);
   4402  1.4.8.1  pgoyette   *p = einsn->flags;
   4403  1.4.8.1  pgoyette   p = frag_more (name_len + 1);
   4404  1.4.8.1  pgoyette   strcpy (p, einsn->name);
   4405  1.4.8.1  pgoyette 
   4406  1.4.8.1  pgoyette   subseg_set (old_sec, old_subsec);
   4407  1.4.8.1  pgoyette }
   4408  1.4.8.1  pgoyette 
   4409  1.4.8.1  pgoyette /* Handler .extinstruction pseudo-op.  */
   4410  1.4.8.1  pgoyette 
   4411  1.4.8.1  pgoyette static void
   4412  1.4.8.1  pgoyette arc_extinsn (int ignore ATTRIBUTE_UNUSED)
   4413  1.4.8.1  pgoyette {
   4414  1.4.8.1  pgoyette   extInstruction_t einsn;
   4415  1.4.8.1  pgoyette   struct arc_opcode *arc_ext_opcodes;
   4416  1.4.8.1  pgoyette   const char *errmsg = NULL;
   4417  1.4.8.1  pgoyette   unsigned char moplow, mophigh;
   4418  1.4.8.1  pgoyette 
   4419  1.4.8.1  pgoyette   memset (&einsn, 0, sizeof (einsn));
   4420  1.4.8.1  pgoyette   tokenize_extinsn (&einsn);
   4421  1.4.8.1  pgoyette 
   4422  1.4.8.1  pgoyette   /* Check if the name is already used.  */
   4423  1.4.8.1  pgoyette   if (arc_find_opcode (einsn.name))
   4424  1.4.8.1  pgoyette     as_warn (_("Pseudocode already used %s"), einsn.name);
   4425  1.4.8.1  pgoyette 
   4426  1.4.8.1  pgoyette   /* Check the opcode ranges.  */
   4427  1.4.8.1  pgoyette   moplow = 0x05;
   4428  1.4.8.1  pgoyette   mophigh = (arc_target & (ARC_OPCODE_ARCv2EM
   4429  1.4.8.1  pgoyette 			   | ARC_OPCODE_ARCv2HS)) ? 0x07 : 0x0a;
   4430  1.4.8.1  pgoyette 
   4431  1.4.8.1  pgoyette   if ((einsn.major > mophigh) || (einsn.major < moplow))
   4432  1.4.8.1  pgoyette     as_fatal (_("major opcode not in range [0x%02x - 0x%02x]"), moplow, mophigh);
   4433  1.4.8.1  pgoyette 
   4434  1.4.8.1  pgoyette   if ((einsn.minor > 0x3f) && (einsn.major != 0x0a)
   4435  1.4.8.1  pgoyette       && (einsn.major != 5) && (einsn.major != 9))
   4436  1.4.8.1  pgoyette     as_fatal (_("minor opcode not in range [0x00 - 0x3f]"));
   4437  1.4.8.1  pgoyette 
   4438  1.4.8.1  pgoyette   switch (einsn.syntax & ARC_SYNTAX_MASK)
   4439  1.4.8.1  pgoyette     {
   4440  1.4.8.1  pgoyette     case ARC_SYNTAX_3OP:
   4441  1.4.8.1  pgoyette       if (einsn.modsyn & ARC_OP1_IMM_IMPLIED)
   4442  1.4.8.1  pgoyette 	as_fatal (_("Improper use of OP1_IMM_IMPLIED"));
   4443  1.4.8.1  pgoyette       break;
   4444  1.4.8.1  pgoyette     case ARC_SYNTAX_2OP:
   4445  1.4.8.1  pgoyette     case ARC_SYNTAX_1OP:
   4446  1.4.8.1  pgoyette     case ARC_SYNTAX_NOP:
   4447  1.4.8.1  pgoyette       if (einsn.modsyn & ARC_OP1_MUST_BE_IMM)
   4448  1.4.8.1  pgoyette 	as_fatal (_("Improper use of OP1_MUST_BE_IMM"));
   4449  1.4.8.1  pgoyette       break;
   4450  1.4.8.1  pgoyette     default:
   4451  1.4.8.1  pgoyette       break;
   4452  1.4.8.1  pgoyette     }
   4453  1.4.8.1  pgoyette 
   4454  1.4.8.1  pgoyette   arc_ext_opcodes = arcExtMap_genOpcode (&einsn, arc_target, &errmsg);
   4455  1.4.8.1  pgoyette   if (arc_ext_opcodes == NULL)
   4456  1.4.8.1  pgoyette     {
   4457  1.4.8.1  pgoyette       if (errmsg)
   4458  1.4.8.1  pgoyette 	as_fatal ("%s", errmsg);
   4459  1.4.8.1  pgoyette       else
   4460  1.4.8.1  pgoyette 	as_fatal (_("Couldn't generate extension instruction opcodes"));
   4461  1.4.8.1  pgoyette     }
   4462  1.4.8.1  pgoyette   else if (errmsg)
   4463  1.4.8.1  pgoyette     as_warn ("%s", errmsg);
   4464  1.4.8.1  pgoyette 
   4465  1.4.8.1  pgoyette   /* Insert the extension instruction.  */
   4466  1.4.8.1  pgoyette   arc_insert_opcode ((const struct arc_opcode *) arc_ext_opcodes);
   4467  1.4.8.1  pgoyette 
   4468  1.4.8.1  pgoyette   create_extinst_section (&einsn);
   4469  1.4.8.1  pgoyette }
   4470  1.4.8.1  pgoyette 
   4471  1.4.8.1  pgoyette static void
   4472  1.4.8.1  pgoyette tokenize_extregister (extRegister_t *ereg, int opertype)
   4473  1.4.8.1  pgoyette {
   4474  1.4.8.1  pgoyette   char *name;
   4475  1.4.8.1  pgoyette   char *mode;
   4476  1.4.8.1  pgoyette   char c;
   4477  1.4.8.1  pgoyette   char *p;
   4478  1.4.8.1  pgoyette   int number, imode = 0;
   4479  1.4.8.1  pgoyette   bfd_boolean isCore_p = (opertype == EXT_CORE_REGISTER) ? TRUE : FALSE;
   4480  1.4.8.1  pgoyette   bfd_boolean isReg_p  = (opertype == EXT_CORE_REGISTER
   4481  1.4.8.1  pgoyette 			  || opertype == EXT_AUX_REGISTER) ? TRUE : FALSE;
   4482  1.4.8.1  pgoyette 
   4483  1.4.8.1  pgoyette   /* 1st: get register name.  */
   4484  1.4.8.1  pgoyette   SKIP_WHITESPACE ();
   4485  1.4.8.1  pgoyette   p = input_line_pointer;
   4486  1.4.8.1  pgoyette   c = get_symbol_name (&p);
   4487  1.4.8.1  pgoyette 
   4488  1.4.8.1  pgoyette   name = xstrdup (p);
   4489  1.4.8.1  pgoyette   restore_line_pointer (c);
   4490  1.4.8.1  pgoyette 
   4491  1.4.8.1  pgoyette   /* 2nd: get register number.  */
   4492  1.4.8.1  pgoyette   SKIP_WHITESPACE ();
   4493  1.4.8.1  pgoyette 
   4494  1.4.8.1  pgoyette   if (*input_line_pointer != ',')
   4495  1.4.8.1  pgoyette     {
   4496  1.4.8.1  pgoyette       as_bad (_("expected comma after register name"));
   4497  1.4.8.1  pgoyette       ignore_rest_of_line ();
   4498  1.4.8.1  pgoyette       free (name);
   4499  1.4.8.1  pgoyette       return;
   4500  1.4.8.1  pgoyette     }
   4501  1.4.8.1  pgoyette   input_line_pointer++;
   4502  1.4.8.1  pgoyette   number = get_absolute_expression ();
   4503  1.4.8.1  pgoyette 
   4504  1.4.8.1  pgoyette   if (number < 0)
   4505  1.4.8.1  pgoyette     {
   4506  1.4.8.1  pgoyette       as_bad (_("negative operand number %d"), number);
   4507  1.4.8.1  pgoyette       ignore_rest_of_line ();
   4508  1.4.8.1  pgoyette       free (name);
   4509  1.4.8.1  pgoyette       return;
   4510  1.4.8.1  pgoyette     }
   4511  1.4.8.1  pgoyette 
   4512  1.4.8.1  pgoyette   if (isReg_p)
   4513  1.4.8.1  pgoyette     {
   4514  1.4.8.1  pgoyette       /* 3rd: get register mode.  */
   4515  1.4.8.1  pgoyette       SKIP_WHITESPACE ();
   4516  1.4.8.1  pgoyette 
   4517  1.4.8.1  pgoyette       if (*input_line_pointer != ',')
   4518  1.4.8.1  pgoyette 	{
   4519  1.4.8.1  pgoyette 	  as_bad (_("expected comma after register number"));
   4520  1.4.8.1  pgoyette 	  ignore_rest_of_line ();
   4521  1.4.8.1  pgoyette 	  free (name);
   4522  1.4.8.1  pgoyette 	  return;
   4523  1.4.8.1  pgoyette 	}
   4524  1.4.8.1  pgoyette 
   4525  1.4.8.1  pgoyette       input_line_pointer++;
   4526  1.4.8.1  pgoyette       mode = input_line_pointer;
   4527  1.4.8.1  pgoyette 
   4528  1.4.8.1  pgoyette       if (!strncmp (mode, "r|w", 3))
   4529  1.4.8.1  pgoyette 	{
   4530  1.4.8.1  pgoyette 	  imode = 0;
   4531  1.4.8.1  pgoyette 	  input_line_pointer += 3;
   4532  1.4.8.1  pgoyette 	}
   4533  1.4.8.1  pgoyette       else if (!strncmp (mode, "r", 1))
   4534  1.4.8.1  pgoyette 	{
   4535  1.4.8.1  pgoyette 	  imode = ARC_REGISTER_READONLY;
   4536  1.4.8.1  pgoyette 	  input_line_pointer += 1;
   4537  1.4.8.1  pgoyette 	}
   4538  1.4.8.1  pgoyette       else if (strncmp (mode, "w", 1))
   4539  1.4.8.1  pgoyette 	{
   4540  1.4.8.1  pgoyette 	  as_bad (_("invalid mode"));
   4541  1.4.8.1  pgoyette 	  ignore_rest_of_line ();
   4542  1.4.8.1  pgoyette 	  free (name);
   4543  1.4.8.1  pgoyette 	  return;
   4544  1.4.8.1  pgoyette 	}
   4545  1.4.8.1  pgoyette       else
   4546  1.4.8.1  pgoyette 	{
   4547  1.4.8.1  pgoyette 	  imode = ARC_REGISTER_WRITEONLY;
   4548  1.4.8.1  pgoyette 	  input_line_pointer += 1;
   4549  1.4.8.1  pgoyette 	}
   4550  1.4.8.1  pgoyette     }
   4551  1.4.8.1  pgoyette 
   4552  1.4.8.1  pgoyette   if (isCore_p)
   4553  1.4.8.1  pgoyette     {
   4554  1.4.8.1  pgoyette       /* 4th: get core register shortcut.  */
   4555  1.4.8.1  pgoyette       SKIP_WHITESPACE ();
   4556  1.4.8.1  pgoyette       if (*input_line_pointer != ',')
   4557  1.4.8.1  pgoyette 	{
   4558  1.4.8.1  pgoyette 	  as_bad (_("expected comma after register mode"));
   4559  1.4.8.1  pgoyette 	  ignore_rest_of_line ();
   4560  1.4.8.1  pgoyette 	  free (name);
   4561  1.4.8.1  pgoyette 	  return;
   4562  1.4.8.1  pgoyette 	}
   4563  1.4.8.1  pgoyette 
   4564  1.4.8.1  pgoyette       input_line_pointer++;
   4565  1.4.8.1  pgoyette 
   4566  1.4.8.1  pgoyette       if (!strncmp (input_line_pointer, "cannot_shortcut", 15))
   4567  1.4.8.1  pgoyette 	{
   4568  1.4.8.1  pgoyette 	  imode |= ARC_REGISTER_NOSHORT_CUT;
   4569  1.4.8.1  pgoyette 	  input_line_pointer += 15;
   4570  1.4.8.1  pgoyette 	}
   4571  1.4.8.1  pgoyette       else if (strncmp (input_line_pointer, "can_shortcut", 12))
   4572  1.4.8.1  pgoyette 	{
   4573  1.4.8.1  pgoyette 	  as_bad (_("shortcut designator invalid"));
   4574  1.4.8.1  pgoyette 	  ignore_rest_of_line ();
   4575  1.4.8.1  pgoyette 	  free (name);
   4576  1.4.8.1  pgoyette 	  return;
   4577  1.4.8.1  pgoyette 	}
   4578  1.4.8.1  pgoyette       else
   4579  1.4.8.1  pgoyette 	{
   4580  1.4.8.1  pgoyette 	  input_line_pointer += 12;
   4581  1.4.8.1  pgoyette 	}
   4582  1.4.8.1  pgoyette     }
   4583  1.4.8.1  pgoyette   demand_empty_rest_of_line ();
   4584  1.4.8.1  pgoyette 
   4585  1.4.8.1  pgoyette   ereg->name = name;
   4586  1.4.8.1  pgoyette   ereg->number = number;
   4587  1.4.8.1  pgoyette   ereg->imode  = imode;
   4588  1.4.8.1  pgoyette }
   4589  1.4.8.1  pgoyette 
   4590  1.4.8.1  pgoyette /* Create an extension register/condition description in the arc
   4591  1.4.8.1  pgoyette    extension section of the output file.
   4592  1.4.8.1  pgoyette 
   4593  1.4.8.1  pgoyette    The structure for an instruction is like this:
   4594  1.4.8.1  pgoyette    [0]: Length of the record.
   4595  1.4.8.1  pgoyette    [1]: Type of the record.
   4596  1.4.8.1  pgoyette 
   4597  1.4.8.1  pgoyette    For core regs and condition codes:
   4598  1.4.8.1  pgoyette    [2]: Value.
   4599  1.4.8.1  pgoyette    [3]+ Name.
   4600  1.4.8.1  pgoyette 
   4601  1.4.8.1  pgoyette    For auxilirary registers:
   4602  1.4.8.1  pgoyette    [2..5]: Value.
   4603  1.4.8.1  pgoyette    [6]+ Name
   4604  1.4.8.1  pgoyette 
   4605  1.4.8.1  pgoyette    The sequence is terminated by an empty entry.  */
   4606  1.4.8.1  pgoyette 
   4607  1.4.8.1  pgoyette static void
   4608  1.4.8.1  pgoyette create_extcore_section (extRegister_t *ereg, int opertype)
   4609  1.4.8.1  pgoyette {
   4610  1.4.8.1  pgoyette   segT old_sec   = now_seg;
   4611  1.4.8.1  pgoyette   int old_subsec = now_subseg;
   4612  1.4.8.1  pgoyette   char *p;
   4613  1.4.8.1  pgoyette   int name_len   = strlen (ereg->name);
   4614  1.4.8.1  pgoyette 
   4615  1.4.8.1  pgoyette   arc_set_ext_seg ();
   4616  1.4.8.1  pgoyette 
   4617  1.4.8.1  pgoyette   switch (opertype)
   4618  1.4.8.1  pgoyette     {
   4619  1.4.8.1  pgoyette     case EXT_COND_CODE:
   4620  1.4.8.1  pgoyette     case EXT_CORE_REGISTER:
   4621  1.4.8.1  pgoyette       p = frag_more (1);
   4622  1.4.8.1  pgoyette       *p = 3 + name_len + 1;
   4623  1.4.8.1  pgoyette       p = frag_more (1);
   4624  1.4.8.1  pgoyette       *p = opertype;
   4625  1.4.8.1  pgoyette       p = frag_more (1);
   4626  1.4.8.1  pgoyette       *p = ereg->number;
   4627  1.4.8.1  pgoyette       break;
   4628  1.4.8.1  pgoyette     case EXT_AUX_REGISTER:
   4629  1.4.8.1  pgoyette       p = frag_more (1);
   4630  1.4.8.1  pgoyette       *p = 6 + name_len + 1;
   4631  1.4.8.1  pgoyette       p = frag_more (1);
   4632  1.4.8.1  pgoyette       *p = EXT_AUX_REGISTER;
   4633  1.4.8.1  pgoyette       p = frag_more (1);
   4634  1.4.8.1  pgoyette       *p = (ereg->number >> 24) & 0xff;
   4635  1.4.8.1  pgoyette       p = frag_more (1);
   4636  1.4.8.1  pgoyette       *p = (ereg->number >> 16) & 0xff;
   4637  1.4.8.1  pgoyette       p = frag_more (1);
   4638  1.4.8.1  pgoyette       *p = (ereg->number >>  8) & 0xff;
   4639  1.4.8.1  pgoyette       p = frag_more (1);
   4640  1.4.8.1  pgoyette       *p = (ereg->number)       & 0xff;
   4641  1.4.8.1  pgoyette       break;
   4642  1.4.8.1  pgoyette     default:
   4643  1.4.8.1  pgoyette       break;
   4644  1.4.8.1  pgoyette     }
   4645  1.4.8.1  pgoyette 
   4646  1.4.8.1  pgoyette   p = frag_more (name_len + 1);
   4647  1.4.8.1  pgoyette   strcpy (p, ereg->name);
   4648  1.4.8.1  pgoyette 
   4649  1.4.8.1  pgoyette   subseg_set (old_sec, old_subsec);
   4650  1.4.8.1  pgoyette }
   4651  1.4.8.1  pgoyette 
   4652  1.4.8.1  pgoyette /* Handler .extCoreRegister pseudo-op.  */
   4653  1.4.8.1  pgoyette 
   4654  1.4.8.1  pgoyette static void
   4655  1.4.8.1  pgoyette arc_extcorereg (int opertype)
   4656  1.4.8.1  pgoyette {
   4657  1.4.8.1  pgoyette   extRegister_t ereg;
   4658  1.4.8.1  pgoyette   struct arc_aux_reg *auxr;
   4659  1.4.8.1  pgoyette   const char *retval;
   4660  1.4.8.1  pgoyette   struct arc_flag_operand *ccode;
   4661  1.4.8.1  pgoyette 
   4662  1.4.8.1  pgoyette   memset (&ereg, 0, sizeof (ereg));
   4663  1.4.8.1  pgoyette   tokenize_extregister (&ereg, opertype);
   4664  1.4.8.1  pgoyette 
   4665  1.4.8.1  pgoyette   switch (opertype)
   4666  1.4.8.1  pgoyette     {
   4667  1.4.8.1  pgoyette     case EXT_CORE_REGISTER:
   4668  1.4.8.1  pgoyette       /* Core register.  */
   4669  1.4.8.1  pgoyette       if (ereg.number > 60)
   4670  1.4.8.1  pgoyette 	as_bad (_("core register %s value (%d) too large"), ereg.name,
   4671  1.4.8.1  pgoyette 		ereg.number);
   4672  1.4.8.1  pgoyette       declare_register (ereg.name, ereg.number);
   4673  1.4.8.1  pgoyette       break;
   4674  1.4.8.1  pgoyette     case EXT_AUX_REGISTER:
   4675  1.4.8.1  pgoyette       /* Auxiliary register.  */
   4676  1.4.8.1  pgoyette       auxr = XNEW (struct arc_aux_reg);
   4677  1.4.8.1  pgoyette       auxr->name = ereg.name;
   4678  1.4.8.1  pgoyette       auxr->cpu = arc_target;
   4679  1.4.8.1  pgoyette       auxr->subclass = NONE;
   4680  1.4.8.1  pgoyette       auxr->address = ereg.number;
   4681  1.4.8.1  pgoyette       retval = hash_insert (arc_aux_hash, auxr->name, (void *) auxr);
   4682  1.4.8.1  pgoyette       if (retval)
   4683  1.4.8.1  pgoyette 	as_fatal (_("internal error: can't hash aux register '%s': %s"),
   4684  1.4.8.1  pgoyette 		  auxr->name, retval);
   4685  1.4.8.1  pgoyette       break;
   4686  1.4.8.1  pgoyette     case EXT_COND_CODE:
   4687  1.4.8.1  pgoyette       /* Condition code.  */
   4688  1.4.8.1  pgoyette       if (ereg.number > 31)
   4689  1.4.8.1  pgoyette 	as_bad (_("condition code %s value (%d) too large"), ereg.name,
   4690  1.4.8.1  pgoyette 		ereg.number);
   4691  1.4.8.1  pgoyette       ext_condcode.size ++;
   4692  1.4.8.1  pgoyette       ext_condcode.arc_ext_condcode =
   4693  1.4.8.1  pgoyette 	XRESIZEVEC (struct arc_flag_operand, ext_condcode.arc_ext_condcode,
   4694  1.4.8.1  pgoyette 		    ext_condcode.size + 1);
   4695  1.4.8.1  pgoyette       if (ext_condcode.arc_ext_condcode == NULL)
   4696  1.4.8.1  pgoyette 	as_fatal (_("Virtual memory exhausted"));
   4697  1.4.8.1  pgoyette 
   4698  1.4.8.1  pgoyette       ccode = ext_condcode.arc_ext_condcode + ext_condcode.size - 1;
   4699  1.4.8.1  pgoyette       ccode->name   = ereg.name;
   4700  1.4.8.1  pgoyette       ccode->code   = ereg.number;
   4701  1.4.8.1  pgoyette       ccode->bits   = 5;
   4702  1.4.8.1  pgoyette       ccode->shift  = 0;
   4703  1.4.8.1  pgoyette       ccode->favail = 0; /* not used.  */
   4704  1.4.8.1  pgoyette       ccode++;
   4705  1.4.8.1  pgoyette       memset (ccode, 0, sizeof (struct arc_flag_operand));
   4706  1.4.8.1  pgoyette       break;
   4707  1.4.8.1  pgoyette     default:
   4708  1.4.8.1  pgoyette       as_bad (_("Unknown extension"));
   4709  1.4.8.1  pgoyette       break;
   4710  1.4.8.1  pgoyette     }
   4711  1.4.8.1  pgoyette   create_extcore_section (&ereg, opertype);
   4712  1.4.8.1  pgoyette }
   4713  1.4.8.1  pgoyette 
   4714  1.4.8.1  pgoyette /* Local variables:
   4715  1.4.8.1  pgoyette    eval: (c-set-style "gnu")
   4716  1.4.8.1  pgoyette    indent-tabs-mode: t
   4717  1.4.8.1  pgoyette    End:  */
   4718