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