| 1 | /* tc-xtensa.c -- Assemble Xtensa instructions.
 | 
|---|
| 2 |    Copyright 2003 Free Software Foundation, Inc.
 | 
|---|
| 3 | 
 | 
|---|
| 4 |    This file is part of GAS, the GNU Assembler.
 | 
|---|
| 5 | 
 | 
|---|
| 6 |    GAS is free software; you can redistribute it and/or modify
 | 
|---|
| 7 |    it under the terms of the GNU General Public License as published by
 | 
|---|
| 8 |    the Free Software Foundation; either version 2, or (at your option)
 | 
|---|
| 9 |    any later version.
 | 
|---|
| 10 | 
 | 
|---|
| 11 |    GAS is distributed in the hope that it will be useful,
 | 
|---|
| 12 |    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|---|
| 13 |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|---|
| 14 |    GNU General Public License for more details.
 | 
|---|
| 15 | 
 | 
|---|
| 16 |    You should have received a copy of the GNU General Public License
 | 
|---|
| 17 |    along with GAS; see the file COPYING.  If not, write to
 | 
|---|
| 18 |    the Free Software Foundation, 59 Temple Place - Suite 330, Boston, 
 | 
|---|
| 19 |    MA 02111-1307, USA.  */
 | 
|---|
| 20 | 
 | 
|---|
| 21 | #include <string.h>
 | 
|---|
| 22 | #include "as.h"
 | 
|---|
| 23 | #include "sb.h"
 | 
|---|
| 24 | #include "safe-ctype.h"
 | 
|---|
| 25 | #include "tc-xtensa.h"
 | 
|---|
| 26 | #include "frags.h"
 | 
|---|
| 27 | #include "subsegs.h"
 | 
|---|
| 28 | #include "xtensa-relax.h"
 | 
|---|
| 29 | #include "xtensa-istack.h"
 | 
|---|
| 30 | #include "dwarf2dbg.h"
 | 
|---|
| 31 | #include "struc-symbol.h"
 | 
|---|
| 32 | #include "xtensa-config.h"
 | 
|---|
| 33 | 
 | 
|---|
| 34 | #ifndef uint32
 | 
|---|
| 35 | #define uint32 unsigned int
 | 
|---|
| 36 | #endif
 | 
|---|
| 37 | #ifndef int32
 | 
|---|
| 38 | #define int32 signed int
 | 
|---|
| 39 | #endif
 | 
|---|
| 40 | 
 | 
|---|
| 41 | /* Notes:
 | 
|---|
| 42 | 
 | 
|---|
| 43 |    There are 3 forms for instructions,
 | 
|---|
| 44 |    1) the MEMORY format -- this is the encoding 2 or 3 byte instruction
 | 
|---|
| 45 |    2) the TInsn -- handles instructions/labels and literals;
 | 
|---|
| 46 |       all operands are assumed to be expressions
 | 
|---|
| 47 |    3) the IStack -- a stack of TInsn.  this allows us to 
 | 
|---|
| 48 |       reason about the generated expansion instructions
 | 
|---|
| 49 |   
 | 
|---|
| 50 |    Naming conventions (used somewhat inconsistently):
 | 
|---|
| 51 |       The xtensa_ functions are exported
 | 
|---|
| 52 |       The xg_ functions are internal
 | 
|---|
| 53 | 
 | 
|---|
| 54 |    We also have a couple of different extensibility mechanisms.
 | 
|---|
| 55 |    1) The idiom replacement:
 | 
|---|
| 56 |       This is used when a line is first parsed to
 | 
|---|
| 57 |       replace an instruction pattern with another instruction
 | 
|---|
| 58 |       It is currently limited to replacements of instructions
 | 
|---|
| 59 |       with constant operands.
 | 
|---|
| 60 |    2) The xtensa-relax.c mechanism that has stronger instruction
 | 
|---|
| 61 |       replacement patterns.  When an instruction's immediate field
 | 
|---|
| 62 |       does not fit the next instruction sequence is attempted.
 | 
|---|
| 63 |       In addition, "narrow" opcodes are supported this way.  */
 | 
|---|
| 64 | 
 | 
|---|
| 65 | 
 | 
|---|
| 66 | /* Define characters with special meanings to GAS.  */
 | 
|---|
| 67 | const char comment_chars[] = "#";
 | 
|---|
| 68 | const char line_comment_chars[] = "#";
 | 
|---|
| 69 | const char line_separator_chars[] = ";";
 | 
|---|
| 70 | const char EXP_CHARS[] = "eE";
 | 
|---|
| 71 | const char FLT_CHARS[] = "rRsSfFdDxXpP";
 | 
|---|
| 72 | 
 | 
|---|
| 73 | 
 | 
|---|
| 74 | /* Flag to indicate whether the hardware supports the density option.
 | 
|---|
| 75 |    If not, enabling density instructions (via directives or --density flag)
 | 
|---|
| 76 |    is illegal.  */
 | 
|---|
| 77 | 
 | 
|---|
| 78 | #if STATIC_LIBISA
 | 
|---|
| 79 | bfd_boolean density_supported = XCHAL_HAVE_DENSITY;
 | 
|---|
| 80 | #else
 | 
|---|
| 81 | bfd_boolean density_supported = TRUE;
 | 
|---|
| 82 | #endif
 | 
|---|
| 83 | 
 | 
|---|
| 84 | #define XTENSA_FETCH_WIDTH 4
 | 
|---|
| 85 | 
 | 
|---|
| 86 | /* Flags for properties of the last instruction in a segment.  */
 | 
|---|
| 87 | #define FLAG_IS_A0_WRITER       0x1
 | 
|---|
| 88 | #define FLAG_IS_BAD_LOOPEND     0x2
 | 
|---|
| 89 | 
 | 
|---|
| 90 | 
 | 
|---|
| 91 | /* We define a special segment names ".literal" to place literals
 | 
|---|
| 92 |    into.  The .fini and .init sections are special because they
 | 
|---|
| 93 |    contain code that is moved together by the linker.  We give them
 | 
|---|
| 94 |    their own special .fini.literal and .init.literal sections.  */
 | 
|---|
| 95 | 
 | 
|---|
| 96 | #define LITERAL_SECTION_NAME            xtensa_section_rename (".literal")
 | 
|---|
| 97 | #define FINI_SECTION_NAME               xtensa_section_rename (".fini")
 | 
|---|
| 98 | #define INIT_SECTION_NAME               xtensa_section_rename (".init")
 | 
|---|
| 99 | #define FINI_LITERAL_SECTION_NAME       xtensa_section_rename (".fini.literal")
 | 
|---|
| 100 | #define INIT_LITERAL_SECTION_NAME       xtensa_section_rename (".init.literal")
 | 
|---|
| 101 | 
 | 
|---|
| 102 | 
 | 
|---|
| 103 | /* This type is used for the directive_stack to keep track of the 
 | 
|---|
| 104 |    state of the literal collection pools.  */
 | 
|---|
| 105 | 
 | 
|---|
| 106 | typedef struct lit_state_struct
 | 
|---|
| 107 | {
 | 
|---|
| 108 |   const char *lit_seg_name;
 | 
|---|
| 109 |   const char *init_lit_seg_name;
 | 
|---|
| 110 |   const char *fini_lit_seg_name;
 | 
|---|
| 111 |   segT lit_seg;
 | 
|---|
| 112 |   segT init_lit_seg;
 | 
|---|
| 113 |   segT fini_lit_seg;
 | 
|---|
| 114 | } lit_state;
 | 
|---|
| 115 | 
 | 
|---|
| 116 | static lit_state default_lit_sections;
 | 
|---|
| 117 | 
 | 
|---|
| 118 | 
 | 
|---|
| 119 | /* We keep lists of literal segments.  The seg_list type is the node
 | 
|---|
| 120 |    for such a list.  The *_literal_head locals are the heads of the
 | 
|---|
| 121 |    various lists.  All of these lists have a dummy node at the start.  */
 | 
|---|
| 122 | 
 | 
|---|
| 123 | typedef struct seg_list_struct
 | 
|---|
| 124 | {
 | 
|---|
| 125 |   struct seg_list_struct *next;
 | 
|---|
| 126 |   segT seg;
 | 
|---|
| 127 | } seg_list;
 | 
|---|
| 128 | 
 | 
|---|
| 129 | static seg_list literal_head_h;
 | 
|---|
| 130 | static seg_list *literal_head = &literal_head_h;
 | 
|---|
| 131 | static seg_list init_literal_head_h;
 | 
|---|
| 132 | static seg_list *init_literal_head = &init_literal_head_h;
 | 
|---|
| 133 | static seg_list fini_literal_head_h;
 | 
|---|
| 134 | static seg_list *fini_literal_head = &fini_literal_head_h;
 | 
|---|
| 135 | 
 | 
|---|
| 136 | 
 | 
|---|
| 137 | /* Global flag to indicate when we are emitting literals.  */
 | 
|---|
| 138 | int generating_literals = 0;
 | 
|---|
| 139 | 
 | 
|---|
| 140 | 
 | 
|---|
| 141 | /* Structure for saving the current state before emitting literals.  */
 | 
|---|
| 142 | typedef struct emit_state_struct
 | 
|---|
| 143 | {
 | 
|---|
| 144 |   const char *name;
 | 
|---|
| 145 |   segT now_seg;
 | 
|---|
| 146 |   subsegT now_subseg;
 | 
|---|
| 147 |   int generating_literals;
 | 
|---|
| 148 | } emit_state;
 | 
|---|
| 149 | 
 | 
|---|
| 150 | 
 | 
|---|
| 151 | /* Directives.  */
 | 
|---|
| 152 | 
 | 
|---|
| 153 | typedef enum
 | 
|---|
| 154 | {
 | 
|---|
| 155 |   directive_none = 0,
 | 
|---|
| 156 |   directive_literal,
 | 
|---|
| 157 |   directive_density,
 | 
|---|
| 158 |   directive_generics,
 | 
|---|
| 159 |   directive_relax,
 | 
|---|
| 160 |   directive_freeregs,
 | 
|---|
| 161 |   directive_longcalls,
 | 
|---|
| 162 |   directive_literal_prefix
 | 
|---|
| 163 | } directiveE;
 | 
|---|
| 164 | 
 | 
|---|
| 165 | typedef struct
 | 
|---|
| 166 | {
 | 
|---|
| 167 |   const char *name;
 | 
|---|
| 168 |   bfd_boolean can_be_negated;
 | 
|---|
| 169 | } directive_infoS;
 | 
|---|
| 170 | 
 | 
|---|
| 171 | const directive_infoS directive_info[] =
 | 
|---|
| 172 | {
 | 
|---|
| 173 |   {"none",      FALSE},
 | 
|---|
| 174 |   {"literal",   FALSE},
 | 
|---|
| 175 |   {"density",   TRUE},
 | 
|---|
| 176 |   {"generics",  TRUE},
 | 
|---|
| 177 |   {"relax",     TRUE},
 | 
|---|
| 178 |   {"freeregs",  FALSE},
 | 
|---|
| 179 |   {"longcalls", TRUE},
 | 
|---|
| 180 |   {"literal_prefix", FALSE}
 | 
|---|
| 181 | };
 | 
|---|
| 182 | 
 | 
|---|
| 183 | bfd_boolean directive_state[] =
 | 
|---|
| 184 | {
 | 
|---|
| 185 |   FALSE,                        /* none */
 | 
|---|
| 186 |   FALSE,                        /* literal */
 | 
|---|
| 187 | #if STATIC_LIBISA && !XCHAL_HAVE_DENSITY
 | 
|---|
| 188 |   FALSE,                        /* density */
 | 
|---|
| 189 | #else
 | 
|---|
| 190 |   TRUE,                         /* density */
 | 
|---|
| 191 | #endif
 | 
|---|
| 192 |   TRUE,                         /* generics */
 | 
|---|
| 193 |   TRUE,                         /* relax */
 | 
|---|
| 194 |   FALSE,                        /* freeregs */
 | 
|---|
| 195 |   FALSE,                        /* longcalls */
 | 
|---|
| 196 |   FALSE                         /* literal_prefix */
 | 
|---|
| 197 | };
 | 
|---|
| 198 | 
 | 
|---|
| 199 | 
 | 
|---|
| 200 | enum xtensa_relax_statesE
 | 
|---|
| 201 | {
 | 
|---|
| 202 |   RELAX_ALIGN_NEXT_OPCODE,
 | 
|---|
| 203 |   /* Use the first opcode of the next fragment to determine the
 | 
|---|
| 204 |      alignment requirements.  This is ONLY used for LOOPS
 | 
|---|
| 205 |      currently.  */
 | 
|---|
| 206 | 
 | 
|---|
| 207 |   RELAX_DESIRE_ALIGN_IF_TARGET,
 | 
|---|
| 208 |   /* These are placed in front of labels.  They will all be converted
 | 
|---|
| 209 |      to RELAX_DESIRE_ALIGN / RELAX_LOOP_END or rs_fill of 0 before
 | 
|---|
| 210 |      relaxation begins.  */
 | 
|---|
| 211 | 
 | 
|---|
| 212 |   RELAX_ADD_NOP_IF_A0_B_RETW,
 | 
|---|
| 213 |   /* These are placed in front of conditional branches.  It will be
 | 
|---|
| 214 |      turned into a NOP (using a1) if the branch is immediately
 | 
|---|
| 215 |      followed by a RETW or RETW.N.  Otherwise it will be turned into
 | 
|---|
| 216 |      an rs_fill of 0 before relaxation begins.  */
 | 
|---|
| 217 | 
 | 
|---|
| 218 |   RELAX_ADD_NOP_IF_PRE_LOOP_END,
 | 
|---|
| 219 |   /* These are placed after JX instructions.  It will be turned into a
 | 
|---|
| 220 |      NOP if there is one instruction before a loop end label.
 | 
|---|
| 221 |      Otherwise it will be turned into an rs_fill of 0 before
 | 
|---|
| 222 |      relaxation begins.  This is used to avoid a hardware TIE
 | 
|---|
| 223 |      interlock issue prior to T1040.  */
 | 
|---|
| 224 | 
 | 
|---|
| 225 |   RELAX_ADD_NOP_IF_SHORT_LOOP,
 | 
|---|
| 226 |   /* These are placed after LOOP instructions.  It will be turned into
 | 
|---|
| 227 |      a NOP when: (1) there are less than 3 instructions in the loop;
 | 
|---|
| 228 |      we place 2 of these in a row to add up to 2 NOPS in short loops;
 | 
|---|
| 229 |      or (2) The instructions in the loop do not include a branch or
 | 
|---|
| 230 |      jump.  Otherwise it will be turned into an rs_fill of 0 before
 | 
|---|
| 231 |      relaxation begins.  This is used to avoid hardware bug
 | 
|---|
| 232 |      PR3830.  */
 | 
|---|
| 233 | 
 | 
|---|
| 234 |   RELAX_ADD_NOP_IF_CLOSE_LOOP_END,
 | 
|---|
| 235 |   /* These are placed after LOOP instructions.  It will be turned into
 | 
|---|
| 236 |      a NOP if there are less than 12 bytes to the end of some other
 | 
|---|
| 237 |      loop's end.  Otherwise it will be turned into an rs_fill of 0
 | 
|---|
| 238 |      before relaxation begins.  This is used to avoid hardware bug
 | 
|---|
| 239 |      PR3830.  */
 | 
|---|
| 240 | 
 | 
|---|
| 241 |   RELAX_DESIRE_ALIGN,
 | 
|---|
| 242 |   /* The next fragment like its first instruction to NOT cross a
 | 
|---|
| 243 |      4-byte boundary.  */
 | 
|---|
| 244 | 
 | 
|---|
| 245 |   RELAX_LOOP_END,
 | 
|---|
| 246 |   /* This will be turned into a NOP or NOP.N if the previous
 | 
|---|
| 247 |      instruction is expanded to negate a loop.  */
 | 
|---|
| 248 | 
 | 
|---|
| 249 |   RELAX_LOOP_END_ADD_NOP,
 | 
|---|
| 250 |   /* When the code density option is available, this will generate a
 | 
|---|
| 251 |      NOP.N marked RELAX_NARROW.  Otherwise, it will create an rs_fill
 | 
|---|
| 252 |      fragment with a NOP in it.  */
 | 
|---|
| 253 | 
 | 
|---|
| 254 |   RELAX_LITERAL,
 | 
|---|
| 255 |   /* Another fragment could generate an expansion here but has not yet.  */
 | 
|---|
| 256 | 
 | 
|---|
| 257 |   RELAX_LITERAL_NR,
 | 
|---|
| 258 |   /* Expansion has been generated by an instruction that generates a
 | 
|---|
| 259 |      literal.  However, the stretch has NOT been reported yet in this
 | 
|---|
| 260 |      fragment.  */
 | 
|---|
| 261 | 
 | 
|---|
| 262 |   RELAX_LITERAL_FINAL,
 | 
|---|
| 263 |   /* Expansion has been generated by an instruction that generates a
 | 
|---|
| 264 |      literal.  */
 | 
|---|
| 265 | 
 | 
|---|
| 266 |   RELAX_LITERAL_POOL_BEGIN,
 | 
|---|
| 267 |   RELAX_LITERAL_POOL_END,
 | 
|---|
| 268 |   /* Technically these are not relaxations at all, but mark a location
 | 
|---|
| 269 |      to store literals later.  Note that fr_var stores the frchain for
 | 
|---|
| 270 |      BEGIN frags and fr_var stores now_seg for END frags.  */
 | 
|---|
| 271 | 
 | 
|---|
| 272 |   RELAX_NARROW,
 | 
|---|
| 273 |   /* The last instruction in this fragment (at->fr_opcode) can be
 | 
|---|
| 274 |      freely replaced with a single wider instruction if a future
 | 
|---|
| 275 |      alignment desires or needs it.  */
 | 
|---|
| 276 | 
 | 
|---|
| 277 |   RELAX_IMMED,
 | 
|---|
| 278 |   /* The last instruction in this fragment (at->fr_opcode) contains
 | 
|---|
| 279 |      the value defined by fr_symbol (fr_offset = 0).  If the value
 | 
|---|
| 280 |      does not fit, use the specified expansion.  This is similar to
 | 
|---|
| 281 |      "NARROW", except that these may not be expanded in order to align
 | 
|---|
| 282 |      code.  */
 | 
|---|
| 283 |   
 | 
|---|
| 284 |   RELAX_IMMED_STEP1,
 | 
|---|
| 285 |   /* The last instruction in this fragment (at->fr_opcode) contains a
 | 
|---|
| 286 |      literal.  It has already been expanded at least 1 step.  */
 | 
|---|
| 287 | 
 | 
|---|
| 288 |   RELAX_IMMED_STEP2
 | 
|---|
| 289 |   /* The last instruction in this fragment (at->fr_opcode) contains a
 | 
|---|
| 290 |      literal.  It has already been expanded at least 2 steps.  */
 | 
|---|
| 291 | };
 | 
|---|
| 292 | 
 | 
|---|
| 293 | /* This is used as a stopper to bound the number of steps that
 | 
|---|
| 294 |    can be taken.  */
 | 
|---|
| 295 | #define RELAX_IMMED_MAXSTEPS (RELAX_IMMED_STEP2 - RELAX_IMMED)
 | 
|---|
| 296 | 
 | 
|---|
| 297 | 
 | 
|---|
| 298 | typedef bfd_boolean (*frag_predicate) (const fragS *);
 | 
|---|
| 299 | 
 | 
|---|
| 300 | 
 | 
|---|
| 301 | /* Directive functions.  */
 | 
|---|
| 302 | 
 | 
|---|
| 303 | static bfd_boolean use_generics
 | 
|---|
| 304 |   PARAMS ((void));
 | 
|---|
| 305 | static bfd_boolean use_longcalls
 | 
|---|
| 306 |   PARAMS ((void));
 | 
|---|
| 307 | static bfd_boolean code_density_available
 | 
|---|
| 308 |   PARAMS ((void));
 | 
|---|
| 309 | static bfd_boolean can_relax
 | 
|---|
| 310 |   PARAMS ((void));
 | 
|---|
| 311 | static void directive_push
 | 
|---|
| 312 |   PARAMS ((directiveE, bfd_boolean, const void *));
 | 
|---|
| 313 | static void directive_pop
 | 
|---|
| 314 |   PARAMS ((directiveE *, bfd_boolean *, const char **,
 | 
|---|
| 315 |            unsigned int *, const void **));
 | 
|---|
| 316 | static void directive_balance
 | 
|---|
| 317 |   PARAMS ((void));
 | 
|---|
| 318 | static bfd_boolean inside_directive
 | 
|---|
| 319 |   PARAMS ((directiveE));
 | 
|---|
| 320 | static void get_directive
 | 
|---|
| 321 |   PARAMS ((directiveE *, bfd_boolean *));
 | 
|---|
| 322 | static void xtensa_begin_directive
 | 
|---|
| 323 |   PARAMS ((int));
 | 
|---|
| 324 | static void xtensa_end_directive
 | 
|---|
| 325 |   PARAMS ((int));
 | 
|---|
| 326 | static void xtensa_literal_prefix
 | 
|---|
| 327 |   PARAMS ((char const *, int));
 | 
|---|
| 328 | static void xtensa_literal_position
 | 
|---|
| 329 |   PARAMS ((int));
 | 
|---|
| 330 | static void xtensa_literal_pseudo
 | 
|---|
| 331 |   PARAMS ((int));
 | 
|---|
| 332 | 
 | 
|---|
| 333 | /* Parsing and Idiom Translation Functions.  */
 | 
|---|
| 334 | 
 | 
|---|
| 335 | static const char *expression_end
 | 
|---|
| 336 |   PARAMS ((const char *));
 | 
|---|
| 337 | static unsigned tc_get_register
 | 
|---|
| 338 |   PARAMS ((const char *));
 | 
|---|
| 339 | static void expression_maybe_register
 | 
|---|
| 340 |   PARAMS ((xtensa_operand, expressionS *));
 | 
|---|
| 341 | static int tokenize_arguments
 | 
|---|
| 342 |   PARAMS ((char **, char *));
 | 
|---|
| 343 | static bfd_boolean parse_arguments
 | 
|---|
| 344 |   PARAMS ((TInsn *, int, char **));
 | 
|---|
| 345 | static int xg_translate_idioms
 | 
|---|
| 346 |   PARAMS ((char **, int *, char **));
 | 
|---|
| 347 | static int xg_translate_sysreg_op
 | 
|---|
| 348 |   PARAMS ((char **, int *, char **));
 | 
|---|
| 349 | static void xg_reverse_shift_count
 | 
|---|
| 350 |   PARAMS ((char **));
 | 
|---|
| 351 | static int xg_arg_is_constant
 | 
|---|
| 352 |   PARAMS ((char *, offsetT *));
 | 
|---|
| 353 | static void xg_replace_opname
 | 
|---|
| 354 |   PARAMS ((char **, char *));
 | 
|---|
| 355 | static int xg_check_num_args
 | 
|---|
| 356 |   PARAMS ((int *, int, char *, char **));
 | 
|---|
| 357 | 
 | 
|---|
| 358 | /* Functions for dealing with the Xtensa ISA.  */
 | 
|---|
| 359 | 
 | 
|---|
| 360 | static bfd_boolean operand_is_immed
 | 
|---|
| 361 |   PARAMS ((xtensa_operand));
 | 
|---|
| 362 | static bfd_boolean operand_is_pcrel_label
 | 
|---|
| 363 |   PARAMS ((xtensa_operand));
 | 
|---|
| 364 | static int get_relaxable_immed
 | 
|---|
| 365 |   PARAMS ((xtensa_opcode));
 | 
|---|
| 366 | static xtensa_opcode get_opcode_from_buf
 | 
|---|
| 367 |   PARAMS ((const char *));
 | 
|---|
| 368 | static bfd_boolean is_direct_call_opcode
 | 
|---|
| 369 |   PARAMS ((xtensa_opcode));
 | 
|---|
| 370 | static bfd_boolean is_call_opcode
 | 
|---|
| 371 |   PARAMS ((xtensa_opcode));
 | 
|---|
| 372 | static bfd_boolean is_entry_opcode
 | 
|---|
| 373 |   PARAMS ((xtensa_opcode));
 | 
|---|
| 374 | static bfd_boolean is_loop_opcode
 | 
|---|
| 375 |   PARAMS ((xtensa_opcode));
 | 
|---|
| 376 | static bfd_boolean is_the_loop_opcode
 | 
|---|
| 377 |   PARAMS ((xtensa_opcode));
 | 
|---|
| 378 | static bfd_boolean is_jx_opcode
 | 
|---|
| 379 |   PARAMS ((xtensa_opcode));
 | 
|---|
| 380 | static bfd_boolean is_windowed_return_opcode
 | 
|---|
| 381 |   PARAMS ((xtensa_opcode));
 | 
|---|
| 382 | static bfd_boolean is_conditional_branch_opcode
 | 
|---|
| 383 |   PARAMS ((xtensa_opcode));
 | 
|---|
| 384 | static bfd_boolean is_branch_or_jump_opcode
 | 
|---|
| 385 |   PARAMS ((xtensa_opcode));
 | 
|---|
| 386 | static bfd_reloc_code_real_type opnum_to_reloc
 | 
|---|
| 387 |   PARAMS ((int));
 | 
|---|
| 388 | static int reloc_to_opnum
 | 
|---|
| 389 |   PARAMS ((bfd_reloc_code_real_type));
 | 
|---|
| 390 | static void xtensa_insnbuf_set_operand
 | 
|---|
| 391 |   PARAMS ((xtensa_insnbuf, xtensa_opcode, xtensa_operand, int32,
 | 
|---|
| 392 |            const char *, unsigned int));
 | 
|---|
| 393 | static uint32 xtensa_insnbuf_get_operand
 | 
|---|
| 394 |   PARAMS ((xtensa_insnbuf, xtensa_opcode, int));
 | 
|---|
| 395 | static void xtensa_insnbuf_set_immediate_field
 | 
|---|
| 396 |   PARAMS ((xtensa_opcode, xtensa_insnbuf, int32, const char *,
 | 
|---|
| 397 |            unsigned int));
 | 
|---|
| 398 | static bfd_boolean is_negatable_branch
 | 
|---|
| 399 |   PARAMS ((TInsn *));
 | 
|---|
| 400 | 
 | 
|---|
| 401 | /* Functions for Internal Lists of Symbols.  */
 | 
|---|
| 402 | static void xtensa_define_label
 | 
|---|
| 403 |   PARAMS ((symbolS *));
 | 
|---|
| 404 | static void add_target_symbol
 | 
|---|
| 405 |   PARAMS ((symbolS *, bfd_boolean));
 | 
|---|
| 406 | static symbolS *xtensa_find_label
 | 
|---|
| 407 |   PARAMS ((fragS *, offsetT, bfd_boolean));
 | 
|---|
| 408 | static void map_over_defined_symbols
 | 
|---|
| 409 |   PARAMS ((void (*fn) (symbolS *)));
 | 
|---|
| 410 | static bfd_boolean is_loop_target_label
 | 
|---|
| 411 |   PARAMS ((symbolS *));
 | 
|---|
| 412 | static void xtensa_mark_target_fragments
 | 
|---|
| 413 |   PARAMS ((void));
 | 
|---|
| 414 | 
 | 
|---|
| 415 | /* Various Other Internal Functions.  */
 | 
|---|
| 416 | 
 | 
|---|
| 417 | static bfd_boolean is_unique_insn_expansion
 | 
|---|
| 418 |   PARAMS ((TransitionRule *));
 | 
|---|
| 419 | static int xg_get_insn_size
 | 
|---|
| 420 |   PARAMS ((TInsn *));
 | 
|---|
| 421 | static int xg_get_build_instr_size
 | 
|---|
| 422 |   PARAMS ((BuildInstr *));
 | 
|---|
| 423 | static bfd_boolean xg_is_narrow_insn
 | 
|---|
| 424 |   PARAMS ((TInsn *));
 | 
|---|
| 425 | static bfd_boolean xg_is_single_relaxable_insn
 | 
|---|
| 426 |   PARAMS ((TInsn *));
 | 
|---|
| 427 | static int xg_get_max_narrow_insn_size
 | 
|---|
| 428 |   PARAMS ((xtensa_opcode));
 | 
|---|
| 429 | static int xg_get_max_insn_widen_size
 | 
|---|
| 430 |   PARAMS ((xtensa_opcode));
 | 
|---|
| 431 | static int xg_get_max_insn_widen_literal_size
 | 
|---|
| 432 |   PARAMS ((xtensa_opcode));
 | 
|---|
| 433 | static bfd_boolean xg_is_relaxable_insn
 | 
|---|
| 434 |   PARAMS ((TInsn *, int));
 | 
|---|
| 435 | static symbolS *get_special_literal_symbol
 | 
|---|
| 436 |   PARAMS ((void));
 | 
|---|
| 437 | static symbolS *get_special_label_symbol
 | 
|---|
| 438 |   PARAMS ((void));
 | 
|---|
| 439 | static bfd_boolean xg_build_to_insn
 | 
|---|
| 440 |   PARAMS ((TInsn *, TInsn *, BuildInstr *));
 | 
|---|
| 441 | static bfd_boolean xg_build_to_stack
 | 
|---|
| 442 |   PARAMS ((IStack *, TInsn *, BuildInstr *));
 | 
|---|
| 443 | static bfd_boolean xg_expand_to_stack
 | 
|---|
| 444 |   PARAMS ((IStack *, TInsn *, int));
 | 
|---|
| 445 | static bfd_boolean xg_expand_narrow
 | 
|---|
| 446 |   PARAMS ((TInsn *, TInsn *));
 | 
|---|
| 447 | static bfd_boolean xg_immeds_fit
 | 
|---|
| 448 |   PARAMS ((const TInsn *));
 | 
|---|
| 449 | static bfd_boolean xg_symbolic_immeds_fit
 | 
|---|
| 450 |   PARAMS ((const TInsn *, segT, fragS *, offsetT, long));
 | 
|---|
| 451 | static bfd_boolean xg_check_operand
 | 
|---|
| 452 |   PARAMS ((int32, xtensa_operand));
 | 
|---|
| 453 | static int is_dnrange
 | 
|---|
| 454 |   PARAMS ((fragS *, symbolS *, long));
 | 
|---|
| 455 | static int xg_assembly_relax
 | 
|---|
| 456 |   PARAMS ((IStack *, TInsn *, segT, fragS *, offsetT, int, long));
 | 
|---|
| 457 | static void xg_force_frag_space
 | 
|---|
| 458 |   PARAMS ((int));
 | 
|---|
| 459 | static void xg_finish_frag
 | 
|---|
| 460 |   PARAMS ((char *, enum xtensa_relax_statesE, int, bfd_boolean));
 | 
|---|
| 461 | static bfd_boolean is_branch_jmp_to_next
 | 
|---|
| 462 |   PARAMS ((TInsn *, fragS *));
 | 
|---|
| 463 | static void xg_add_branch_and_loop_targets
 | 
|---|
| 464 |   PARAMS ((TInsn *));
 | 
|---|
| 465 | static bfd_boolean xg_instruction_matches_rule
 | 
|---|
| 466 |   PARAMS ((TInsn *, TransitionRule *));
 | 
|---|
| 467 | static TransitionRule *xg_instruction_match
 | 
|---|
| 468 |   PARAMS ((TInsn *));
 | 
|---|
| 469 | static bfd_boolean xg_build_token_insn
 | 
|---|
| 470 |   PARAMS ((BuildInstr *, TInsn *, TInsn *));
 | 
|---|
| 471 | static bfd_boolean xg_simplify_insn
 | 
|---|
| 472 |   PARAMS ((TInsn *, TInsn *));
 | 
|---|
| 473 | static bfd_boolean xg_expand_assembly_insn
 | 
|---|
| 474 |   PARAMS ((IStack *, TInsn *));
 | 
|---|
| 475 | static symbolS *xg_assemble_literal
 | 
|---|
| 476 |   PARAMS ((TInsn *));
 | 
|---|
| 477 | static void xg_assemble_literal_space
 | 
|---|
| 478 |   PARAMS ((int));
 | 
|---|
| 479 | static symbolS *xtensa_create_literal_symbol
 | 
|---|
| 480 |   PARAMS ((segT, fragS *));
 | 
|---|
| 481 | static symbolS *xtensa_create_local_symbol
 | 
|---|
| 482 |   PARAMS ((bfd *, const char *, segT, valueT, fragS *));
 | 
|---|
| 483 | static bfd_boolean get_is_linkonce_section
 | 
|---|
| 484 |   PARAMS ((bfd *, segT));
 | 
|---|
| 485 | static bfd_boolean xg_emit_insn
 | 
|---|
| 486 |   PARAMS ((TInsn *, bfd_boolean));
 | 
|---|
| 487 | static bfd_boolean xg_emit_insn_to_buf
 | 
|---|
| 488 |   PARAMS ((TInsn *, char *, fragS *, offsetT, bfd_boolean));
 | 
|---|
| 489 | static bfd_boolean xg_add_opcode_fix
 | 
|---|
| 490 |   PARAMS ((xtensa_opcode, int, expressionS *, fragS *, offsetT));
 | 
|---|
| 491 | static void xg_resolve_literals
 | 
|---|
| 492 |   PARAMS ((TInsn *, symbolS *));
 | 
|---|
| 493 | static void xg_resolve_labels
 | 
|---|
| 494 |   PARAMS ((TInsn *, symbolS *));
 | 
|---|
| 495 | static void xg_assemble_tokens
 | 
|---|
| 496 |   PARAMS ((TInsn *));
 | 
|---|
| 497 | static bfd_boolean is_register_writer
 | 
|---|
| 498 |   PARAMS ((const TInsn *, const char *, int));
 | 
|---|
| 499 | static bfd_boolean is_bad_loopend_opcode
 | 
|---|
| 500 |   PARAMS ((const TInsn *));
 | 
|---|
| 501 | static bfd_boolean is_unaligned_label
 | 
|---|
| 502 |   PARAMS ((symbolS *));
 | 
|---|
| 503 | static fragS *next_non_empty_frag
 | 
|---|
| 504 |   PARAMS ((const fragS *));
 | 
|---|
| 505 | static xtensa_opcode next_frag_opcode
 | 
|---|
| 506 |   PARAMS ((const fragS *));
 | 
|---|
| 507 | static void update_next_frag_nop_state
 | 
|---|
| 508 |   PARAMS ((fragS *));
 | 
|---|
| 509 | static bfd_boolean next_frag_is_branch_target
 | 
|---|
| 510 |   PARAMS ((const fragS *));
 | 
|---|
| 511 | static bfd_boolean next_frag_is_loop_target
 | 
|---|
| 512 |   PARAMS ((const fragS *));
 | 
|---|
| 513 | static addressT next_frag_pre_opcode_bytes
 | 
|---|
| 514 |   PARAMS ((const fragS *));
 | 
|---|
| 515 | static bfd_boolean is_next_frag_target
 | 
|---|
| 516 |   PARAMS ((const fragS *, const fragS *));
 | 
|---|
| 517 | static void xtensa_mark_literal_pool_location
 | 
|---|
| 518 |   PARAMS ((bfd_boolean));
 | 
|---|
| 519 | static void xtensa_move_labels
 | 
|---|
| 520 |   PARAMS ((fragS *, valueT, fragS *, valueT));
 | 
|---|
| 521 | static void assemble_nop
 | 
|---|
| 522 |   PARAMS ((size_t, char *));
 | 
|---|
| 523 | static addressT get_expanded_loop_offset
 | 
|---|
| 524 |   PARAMS ((xtensa_opcode));
 | 
|---|
| 525 | static fragS *get_literal_pool_location
 | 
|---|
| 526 |   PARAMS ((segT));
 | 
|---|
| 527 | static void set_literal_pool_location
 | 
|---|
| 528 |   PARAMS ((segT, fragS *));
 | 
|---|
| 529 | 
 | 
|---|
| 530 | /* Helpers for xtensa_end().  */
 | 
|---|
| 531 | 
 | 
|---|
| 532 | static void xtensa_cleanup_align_frags
 | 
|---|
| 533 |   PARAMS ((void));
 | 
|---|
| 534 | static void xtensa_fix_target_frags
 | 
|---|
| 535 |   PARAMS ((void));
 | 
|---|
| 536 | static bfd_boolean frag_can_negate_branch
 | 
|---|
| 537 |   PARAMS ((fragS *));
 | 
|---|
| 538 | static void xtensa_fix_a0_b_retw_frags
 | 
|---|
| 539 |   PARAMS ((void));
 | 
|---|
| 540 | static bfd_boolean next_instrs_are_b_retw
 | 
|---|
| 541 |   PARAMS ((fragS *));
 | 
|---|
| 542 | static void xtensa_fix_b_j_loop_end_frags
 | 
|---|
| 543 |   PARAMS ((void));
 | 
|---|
| 544 | static bfd_boolean next_instr_is_loop_end
 | 
|---|
| 545 |   PARAMS ((fragS *));
 | 
|---|
| 546 | static void xtensa_fix_close_loop_end_frags
 | 
|---|
| 547 |   PARAMS ((void));
 | 
|---|
| 548 | static size_t min_bytes_to_other_loop_end
 | 
|---|
| 549 |   PARAMS ((fragS *, fragS *, offsetT, size_t));
 | 
|---|
| 550 | static size_t unrelaxed_frag_min_size
 | 
|---|
| 551 |   PARAMS ((fragS *));
 | 
|---|
| 552 | static void xtensa_fix_short_loop_frags
 | 
|---|
| 553 |   PARAMS ((void));
 | 
|---|
| 554 | static size_t count_insns_to_loop_end
 | 
|---|
| 555 |   PARAMS ((fragS *, bfd_boolean, size_t));
 | 
|---|
| 556 | static size_t unrelaxed_frag_min_insn_count
 | 
|---|
| 557 |   PARAMS ((fragS *));
 | 
|---|
| 558 | static bfd_boolean branch_before_loop_end
 | 
|---|
| 559 |   PARAMS ((fragS *));
 | 
|---|
| 560 | static bfd_boolean unrelaxed_frag_has_b_j
 | 
|---|
| 561 |   PARAMS ((fragS *));
 | 
|---|
| 562 | static void xtensa_sanity_check
 | 
|---|
| 563 |   PARAMS ((void));
 | 
|---|
| 564 | static bfd_boolean is_empty_loop
 | 
|---|
| 565 |   PARAMS ((const TInsn *, fragS *));
 | 
|---|
| 566 | static bfd_boolean is_local_forward_loop
 | 
|---|
| 567 |   PARAMS ((const TInsn *, fragS *));
 | 
|---|
| 568 | 
 | 
|---|
| 569 | /* Alignment Functions.  */
 | 
|---|
| 570 | 
 | 
|---|
| 571 | static size_t get_text_align_power
 | 
|---|
| 572 |   PARAMS ((int));
 | 
|---|
| 573 | static addressT get_text_align_max_fill_size
 | 
|---|
| 574 |   PARAMS ((int, bfd_boolean, bfd_boolean));
 | 
|---|
| 575 | static addressT get_text_align_fill_size
 | 
|---|
| 576 |   PARAMS ((addressT, int, int, bfd_boolean, bfd_boolean));
 | 
|---|
| 577 | static size_t get_text_align_nop_count
 | 
|---|
| 578 |   PARAMS ((size_t, bfd_boolean));
 | 
|---|
| 579 | static size_t get_text_align_nth_nop_size
 | 
|---|
| 580 |   PARAMS ((size_t, size_t, bfd_boolean));
 | 
|---|
| 581 | static addressT get_noop_aligned_address
 | 
|---|
| 582 |   PARAMS ((fragS *, addressT));
 | 
|---|
| 583 | static addressT get_widen_aligned_address
 | 
|---|
| 584 |   PARAMS ((fragS *, addressT));
 | 
|---|
| 585 | 
 | 
|---|
| 586 | /* Helpers for xtensa_relax_frag().  */
 | 
|---|
| 587 | 
 | 
|---|
| 588 | static long relax_frag_text_align
 | 
|---|
| 589 |   PARAMS ((fragS *, long));
 | 
|---|
| 590 | static long relax_frag_add_nop
 | 
|---|
| 591 |   PARAMS ((fragS *));
 | 
|---|
| 592 | static long relax_frag_narrow
 | 
|---|
| 593 |   PARAMS ((fragS *, long));
 | 
|---|
| 594 | static bfd_boolean future_alignment_required
 | 
|---|
| 595 |   PARAMS ((fragS *, long));
 | 
|---|
| 596 | static long relax_frag_immed
 | 
|---|
| 597 |   PARAMS ((segT, fragS *, long, int, int *));
 | 
|---|
| 598 | 
 | 
|---|
| 599 | /* Helpers for md_convert_frag().  */
 | 
|---|
| 600 | 
 | 
|---|
| 601 | static void convert_frag_align_next_opcode
 | 
|---|
| 602 |   PARAMS ((fragS *));
 | 
|---|
| 603 | static void convert_frag_narrow
 | 
|---|
| 604 |   PARAMS ((fragS *));
 | 
|---|
| 605 | static void convert_frag_immed
 | 
|---|
| 606 |   PARAMS ((segT, fragS *, int));
 | 
|---|
| 607 | static fixS *fix_new_exp_in_seg
 | 
|---|
| 608 |   PARAMS ((segT, subsegT, fragS *, int, int, expressionS *, int,
 | 
|---|
| 609 |            bfd_reloc_code_real_type));
 | 
|---|
| 610 | static void convert_frag_immed_finish_loop
 | 
|---|
| 611 |   PARAMS ((segT, fragS *, TInsn *));
 | 
|---|
| 612 | static offsetT get_expression_value
 | 
|---|
| 613 |   PARAMS ((segT, expressionS *));
 | 
|---|
| 614 | 
 | 
|---|
| 615 | /* Flags for the Last Instruction in Each Subsegment.  */
 | 
|---|
| 616 | 
 | 
|---|
| 617 | static unsigned get_last_insn_flags
 | 
|---|
| 618 |   PARAMS ((segT, subsegT));
 | 
|---|
| 619 | static void set_last_insn_flags
 | 
|---|
| 620 |   PARAMS ((segT, subsegT, unsigned, bfd_boolean));
 | 
|---|
| 621 | 
 | 
|---|
| 622 | /* Segment list functions.  */
 | 
|---|
| 623 | 
 | 
|---|
| 624 | static void xtensa_remove_section
 | 
|---|
| 625 |   PARAMS ((segT));
 | 
|---|
| 626 | static void xtensa_insert_section
 | 
|---|
| 627 |   PARAMS ((segT, segT));
 | 
|---|
| 628 | static void xtensa_move_seg_list_to_beginning
 | 
|---|
| 629 |   PARAMS ((seg_list *));
 | 
|---|
| 630 | static void xtensa_move_literals
 | 
|---|
| 631 |   PARAMS ((void));
 | 
|---|
| 632 | static void xtensa_move_frag_symbol
 | 
|---|
| 633 |   PARAMS ((symbolS *));
 | 
|---|
| 634 | static void xtensa_move_frag_symbols
 | 
|---|
| 635 |   PARAMS ((void));
 | 
|---|
| 636 | static void xtensa_reorder_seg_list
 | 
|---|
| 637 |   PARAMS ((seg_list *, segT));
 | 
|---|
| 638 | static void xtensa_reorder_segments
 | 
|---|
| 639 |   PARAMS ((void));
 | 
|---|
| 640 | static segT get_last_sec
 | 
|---|
| 641 |   PARAMS ((void));
 | 
|---|
| 642 | static void xtensa_switch_to_literal_fragment
 | 
|---|
| 643 |   PARAMS ((emit_state *));
 | 
|---|
| 644 | static void xtensa_switch_section_emit_state
 | 
|---|
| 645 |   PARAMS ((emit_state *, segT, subsegT));
 | 
|---|
| 646 | static void xtensa_restore_emit_state
 | 
|---|
| 647 |   PARAMS ((emit_state *));
 | 
|---|
| 648 | static void cache_literal_section
 | 
|---|
| 649 |   PARAMS ((seg_list *, const char *, segT *));
 | 
|---|
| 650 | static segT retrieve_literal_seg
 | 
|---|
| 651 |   PARAMS ((seg_list *, const char *));
 | 
|---|
| 652 | static segT seg_present
 | 
|---|
| 653 |   PARAMS ((const char *));
 | 
|---|
| 654 | static void add_seg_list
 | 
|---|
| 655 |   PARAMS ((seg_list *, segT));
 | 
|---|
| 656 | 
 | 
|---|
| 657 | /* Property Table (e.g., ".xt.insn" and ".xt.lit") Functions.  */
 | 
|---|
| 658 | 
 | 
|---|
| 659 | static void xtensa_create_property_segments
 | 
|---|
| 660 |   PARAMS ((frag_predicate, const char *, xt_section_type));
 | 
|---|
| 661 | static segment_info_type *retrieve_segment_info
 | 
|---|
| 662 |   PARAMS ((segT));
 | 
|---|
| 663 | static segT retrieve_xtensa_section
 | 
|---|
| 664 |   PARAMS ((char *));
 | 
|---|
| 665 | static bfd_boolean section_has_property
 | 
|---|
| 666 |   PARAMS ((segT sec, frag_predicate));
 | 
|---|
| 667 | static void add_xt_block_frags
 | 
|---|
| 668 |   PARAMS ((segT, segT, xtensa_block_info **, frag_predicate));
 | 
|---|
| 669 | static bfd_boolean get_frag_is_literal
 | 
|---|
| 670 |   PARAMS ((const fragS *));
 | 
|---|
| 671 | static bfd_boolean get_frag_is_insn
 | 
|---|
| 672 |   PARAMS ((const fragS *));
 | 
|---|
| 673 | 
 | 
|---|
| 674 | /* Import from elf32-xtensa.c in BFD library.  */
 | 
|---|
| 675 | extern char *xtensa_get_property_section_name
 | 
|---|
| 676 |   PARAMS ((bfd *, asection *, const char *));
 | 
|---|
| 677 | 
 | 
|---|
| 678 | /* TInsn and IStack functions.  */
 | 
|---|
| 679 | static bfd_boolean tinsn_has_symbolic_operands
 | 
|---|
| 680 |   PARAMS ((const TInsn *));
 | 
|---|
| 681 | static bfd_boolean tinsn_has_invalid_symbolic_operands
 | 
|---|
| 682 |   PARAMS ((const TInsn *));
 | 
|---|
| 683 | static bfd_boolean tinsn_has_complex_operands
 | 
|---|
| 684 |   PARAMS ((const TInsn *));
 | 
|---|
| 685 | static bfd_boolean tinsn_to_insnbuf
 | 
|---|
| 686 |   PARAMS ((TInsn *, xtensa_insnbuf));
 | 
|---|
| 687 | static bfd_boolean tinsn_check_arguments
 | 
|---|
| 688 |   PARAMS ((const TInsn *));
 | 
|---|
| 689 | static void tinsn_from_chars
 | 
|---|
| 690 |   PARAMS ((TInsn *, char *));
 | 
|---|
| 691 | static void tinsn_immed_from_frag
 | 
|---|
| 692 |   PARAMS ((TInsn *, fragS *));
 | 
|---|
| 693 | static int get_num_stack_text_bytes
 | 
|---|
| 694 |   PARAMS ((IStack *));
 | 
|---|
| 695 | static int get_num_stack_literal_bytes
 | 
|---|
| 696 |   PARAMS ((IStack *));
 | 
|---|
| 697 | 
 | 
|---|
| 698 | /* Expression Utilities.  */
 | 
|---|
| 699 | bfd_boolean expr_is_const
 | 
|---|
| 700 |   PARAMS ((const expressionS *));
 | 
|---|
| 701 | offsetT get_expr_const
 | 
|---|
| 702 |   PARAMS ((const expressionS *));
 | 
|---|
| 703 | void set_expr_const
 | 
|---|
| 704 |   PARAMS ((expressionS *, offsetT));
 | 
|---|
| 705 | void set_expr_symbol_offset
 | 
|---|
| 706 |   PARAMS ((expressionS *, symbolS *, offsetT));
 | 
|---|
| 707 | bfd_boolean expr_is_equal
 | 
|---|
| 708 |   PARAMS ((expressionS *, expressionS *));
 | 
|---|
| 709 | static void copy_expr
 | 
|---|
| 710 |   PARAMS ((expressionS *, const expressionS *));
 | 
|---|
| 711 | 
 | 
|---|
| 712 | #ifdef XTENSA_SECTION_RENAME
 | 
|---|
| 713 | static void build_section_rename
 | 
|---|
| 714 |   PARAMS ((const char *));
 | 
|---|
| 715 | static void add_section_rename
 | 
|---|
| 716 |   PARAMS ((char *, char *));
 | 
|---|
| 717 | #endif
 | 
|---|
| 718 | 
 | 
|---|
| 719 | #ifdef XTENSA_COMBINE_LITERALS
 | 
|---|
| 720 | static void find_lit_sym_translation
 | 
|---|
| 721 |   PARAMS ((expressionS *));
 | 
|---|
| 722 | static void add_lit_sym_translation
 | 
|---|
| 723 |   PARAMS ((char *, offsetT, symbolS *));
 | 
|---|
| 724 | #endif
 | 
|---|
| 725 | 
 | 
|---|
| 726 | 
 | 
|---|
| 727 | /* ISA imported from bfd.  */
 | 
|---|
| 728 | extern xtensa_isa xtensa_default_isa;
 | 
|---|
| 729 | 
 | 
|---|
| 730 | extern int target_big_endian;
 | 
|---|
| 731 | 
 | 
|---|
| 732 | static xtensa_opcode xtensa_addi_opcode;
 | 
|---|
| 733 | static xtensa_opcode xtensa_addmi_opcode;
 | 
|---|
| 734 | static xtensa_opcode xtensa_call0_opcode;
 | 
|---|
| 735 | static xtensa_opcode xtensa_call4_opcode;
 | 
|---|
| 736 | static xtensa_opcode xtensa_call8_opcode;
 | 
|---|
| 737 | static xtensa_opcode xtensa_call12_opcode;
 | 
|---|
| 738 | static xtensa_opcode xtensa_callx0_opcode;
 | 
|---|
| 739 | static xtensa_opcode xtensa_callx4_opcode;
 | 
|---|
| 740 | static xtensa_opcode xtensa_callx8_opcode;
 | 
|---|
| 741 | static xtensa_opcode xtensa_callx12_opcode;
 | 
|---|
| 742 | static xtensa_opcode xtensa_entry_opcode;
 | 
|---|
| 743 | static xtensa_opcode xtensa_isync_opcode;
 | 
|---|
| 744 | static xtensa_opcode xtensa_j_opcode;
 | 
|---|
| 745 | static xtensa_opcode xtensa_jx_opcode;
 | 
|---|
| 746 | static xtensa_opcode xtensa_loop_opcode;
 | 
|---|
| 747 | static xtensa_opcode xtensa_loopnez_opcode;
 | 
|---|
| 748 | static xtensa_opcode xtensa_loopgtz_opcode;
 | 
|---|
| 749 | static xtensa_opcode xtensa_nop_n_opcode;
 | 
|---|
| 750 | static xtensa_opcode xtensa_or_opcode;
 | 
|---|
| 751 | static xtensa_opcode xtensa_ret_opcode;
 | 
|---|
| 752 | static xtensa_opcode xtensa_ret_n_opcode;
 | 
|---|
| 753 | static xtensa_opcode xtensa_retw_opcode;
 | 
|---|
| 754 | static xtensa_opcode xtensa_retw_n_opcode;
 | 
|---|
| 755 | static xtensa_opcode xtensa_rsr_opcode;
 | 
|---|
| 756 | static xtensa_opcode xtensa_waiti_opcode;
 | 
|---|
| 757 | 
 | 
|---|
| 758 |  | 
|---|
| 759 | 
 | 
|---|
| 760 | /* Command-line Options.  */
 | 
|---|
| 761 | 
 | 
|---|
| 762 | bfd_boolean use_literal_section = TRUE;
 | 
|---|
| 763 | static bfd_boolean align_targets = TRUE;
 | 
|---|
| 764 | static bfd_boolean align_only_targets = FALSE;
 | 
|---|
| 765 | static bfd_boolean software_a0_b_retw_interlock = TRUE;
 | 
|---|
| 766 | static bfd_boolean has_a0_b_retw = FALSE;
 | 
|---|
| 767 | static bfd_boolean workaround_a0_b_retw = TRUE;
 | 
|---|
| 768 | 
 | 
|---|
| 769 | static bfd_boolean software_avoid_b_j_loop_end = TRUE;
 | 
|---|
| 770 | static bfd_boolean workaround_b_j_loop_end = TRUE;
 | 
|---|
| 771 | static bfd_boolean maybe_has_b_j_loop_end = FALSE;
 | 
|---|
| 772 | 
 | 
|---|
| 773 | static bfd_boolean software_avoid_short_loop = TRUE;
 | 
|---|
| 774 | static bfd_boolean workaround_short_loop = TRUE;
 | 
|---|
| 775 | static bfd_boolean maybe_has_short_loop = FALSE;
 | 
|---|
| 776 | 
 | 
|---|
| 777 | static bfd_boolean software_avoid_close_loop_end = TRUE;
 | 
|---|
| 778 | static bfd_boolean workaround_close_loop_end = TRUE;
 | 
|---|
| 779 | static bfd_boolean maybe_has_close_loop_end = FALSE;
 | 
|---|
| 780 | 
 | 
|---|
| 781 | /* When avoid_short_loops is true, all loops with early exits must
 | 
|---|
| 782 |    have at least 3 instructions.  avoid_all_short_loops is a modifier
 | 
|---|
| 783 |    to the avoid_short_loop flag.  In addition to the avoid_short_loop
 | 
|---|
| 784 |    actions, all straightline loopgtz and loopnez must have at least 3
 | 
|---|
| 785 |    instructions.  */
 | 
|---|
| 786 | 
 | 
|---|
| 787 | static bfd_boolean software_avoid_all_short_loops = TRUE;
 | 
|---|
| 788 | static bfd_boolean workaround_all_short_loops = TRUE;
 | 
|---|
| 789 | 
 | 
|---|
| 790 | /* This is on a per-instruction basis.  */
 | 
|---|
| 791 | static bfd_boolean specific_opcode = FALSE;
 | 
|---|
| 792 | 
 | 
|---|
| 793 | enum
 | 
|---|
| 794 | {
 | 
|---|
| 795 |   option_density = OPTION_MD_BASE,
 | 
|---|
| 796 |   option_no_density,
 | 
|---|
| 797 | 
 | 
|---|
| 798 |   option_relax,
 | 
|---|
| 799 |   option_no_relax,
 | 
|---|
| 800 | 
 | 
|---|
| 801 |   option_generics,
 | 
|---|
| 802 |   option_no_generics,
 | 
|---|
| 803 | 
 | 
|---|
| 804 |   option_text_section_literals,
 | 
|---|
| 805 |   option_no_text_section_literals,
 | 
|---|
| 806 | 
 | 
|---|
| 807 |   option_align_targets,
 | 
|---|
| 808 |   option_no_align_targets,
 | 
|---|
| 809 | 
 | 
|---|
| 810 |   option_align_only_targets,
 | 
|---|
| 811 |   option_no_align_only_targets,
 | 
|---|
| 812 | 
 | 
|---|
| 813 |   option_longcalls,
 | 
|---|
| 814 |   option_no_longcalls,
 | 
|---|
| 815 | 
 | 
|---|
| 816 |   option_workaround_a0_b_retw,
 | 
|---|
| 817 |   option_no_workaround_a0_b_retw,
 | 
|---|
| 818 | 
 | 
|---|
| 819 |   option_workaround_b_j_loop_end,
 | 
|---|
| 820 |   option_no_workaround_b_j_loop_end,
 | 
|---|
| 821 | 
 | 
|---|
| 822 |   option_workaround_short_loop,
 | 
|---|
| 823 |   option_no_workaround_short_loop,
 | 
|---|
| 824 | 
 | 
|---|
| 825 |   option_workaround_all_short_loops,
 | 
|---|
| 826 |   option_no_workaround_all_short_loops,
 | 
|---|
| 827 | 
 | 
|---|
| 828 |   option_workaround_close_loop_end,
 | 
|---|
| 829 |   option_no_workaround_close_loop_end,
 | 
|---|
| 830 | 
 | 
|---|
| 831 |   option_no_workarounds,
 | 
|---|
| 832 | 
 | 
|---|
| 833 | #ifdef XTENSA_SECTION_RENAME
 | 
|---|
| 834 |   option_literal_section_name,
 | 
|---|
| 835 |   option_text_section_name,
 | 
|---|
| 836 |   option_data_section_name,
 | 
|---|
| 837 |   option_bss_section_name,
 | 
|---|
| 838 |   option_rename_section_name,
 | 
|---|
| 839 | #endif
 | 
|---|
| 840 | 
 | 
|---|
| 841 |   option_eb,
 | 
|---|
| 842 |   option_el
 | 
|---|
| 843 | };
 | 
|---|
| 844 | 
 | 
|---|
| 845 | const char *md_shortopts = "";
 | 
|---|
| 846 | 
 | 
|---|
| 847 | struct option md_longopts[] =
 | 
|---|
| 848 | {
 | 
|---|
| 849 |   {"density", no_argument, NULL, option_density},
 | 
|---|
| 850 |   {"no-density", no_argument, NULL, option_no_density},
 | 
|---|
| 851 |   /* At least as early as alameda, --[no-]relax didn't work as
 | 
|---|
| 852 |      documented, so as of albany, --[no-]relax is equivalent to
 | 
|---|
| 853 |      --[no-]generics.  Both of these will be deprecated in
 | 
|---|
| 854 |      BearValley.  */
 | 
|---|
| 855 |   {"relax", no_argument, NULL, option_generics},
 | 
|---|
| 856 |   {"no-relax", no_argument, NULL, option_no_generics},
 | 
|---|
| 857 |   {"generics", no_argument, NULL, option_generics},
 | 
|---|
| 858 |   {"no-generics", no_argument, NULL, option_no_generics},
 | 
|---|
| 859 |   {"text-section-literals", no_argument, NULL, option_text_section_literals},
 | 
|---|
| 860 |   {"no-text-section-literals", no_argument, NULL,
 | 
|---|
| 861 |    option_no_text_section_literals},
 | 
|---|
| 862 |   /* This option was changed from -align-target to -target-align
 | 
|---|
| 863 |      because it conflicted with the "-al" option.  */
 | 
|---|
| 864 |   {"target-align", no_argument, NULL, option_align_targets},
 | 
|---|
| 865 |   {"no-target-align", no_argument, NULL,
 | 
|---|
| 866 |    option_no_align_targets},
 | 
|---|
| 867 | #if 0
 | 
|---|
| 868 |   /* This option  should do a better job aligning targets because
 | 
|---|
| 869 |      it will only attempt to align targets that are the target of a 
 | 
|---|
| 870 |      branch.  */
 | 
|---|
| 871 |    { "target-align-only", no_argument, NULL, option_align_only_targets },
 | 
|---|
| 872 |    { "no-target-align-only", no_argument, NULL, option_no_align_only_targets },
 | 
|---|
| 873 | #endif /* 0 */
 | 
|---|
| 874 |   {"longcalls", no_argument, NULL, option_longcalls},
 | 
|---|
| 875 |   {"no-longcalls", no_argument, NULL, option_no_longcalls},
 | 
|---|
| 876 | 
 | 
|---|
| 877 |   {"no-workaround-a0-b-retw", no_argument, NULL,
 | 
|---|
| 878 |    option_no_workaround_a0_b_retw},
 | 
|---|
| 879 |   {"workaround-a0-b-retw", no_argument, NULL, option_workaround_a0_b_retw},
 | 
|---|
| 880 |   
 | 
|---|
| 881 |   {"no-workaround-b-j-loop-end", no_argument, NULL,
 | 
|---|
| 882 |    option_no_workaround_b_j_loop_end},
 | 
|---|
| 883 |   {"workaround-b-j-loop-end", no_argument, NULL,
 | 
|---|
| 884 |    option_workaround_b_j_loop_end},
 | 
|---|
| 885 |   
 | 
|---|
| 886 |   {"no-workaround-short-loops", no_argument, NULL,
 | 
|---|
| 887 |    option_no_workaround_short_loop},
 | 
|---|
| 888 |   {"workaround-short-loops", no_argument, NULL, option_workaround_short_loop},
 | 
|---|
| 889 | 
 | 
|---|
| 890 |   {"no-workaround-all-short-loops", no_argument, NULL,
 | 
|---|
| 891 |    option_no_workaround_all_short_loops},
 | 
|---|
| 892 |   {"workaround-all-short-loop", no_argument, NULL,
 | 
|---|
| 893 |    option_workaround_all_short_loops},
 | 
|---|
| 894 | 
 | 
|---|
| 895 |   {"no-workaround-close-loop-end", no_argument, NULL,
 | 
|---|
| 896 |    option_no_workaround_close_loop_end},
 | 
|---|
| 897 |   {"workaround-close-loop-end", no_argument, NULL,
 | 
|---|
| 898 |    option_workaround_close_loop_end},
 | 
|---|
| 899 | 
 | 
|---|
| 900 |   {"no-workarounds", no_argument, NULL, option_no_workarounds},
 | 
|---|
| 901 | 
 | 
|---|
| 902 | #ifdef XTENSA_SECTION_RENAME
 | 
|---|
| 903 |   {"literal-section-name", required_argument, NULL,
 | 
|---|
| 904 |    option_literal_section_name},
 | 
|---|
| 905 |   {"text-section-name", required_argument, NULL,
 | 
|---|
| 906 |    option_text_section_name},
 | 
|---|
| 907 |   {"data-section-name", required_argument, NULL,
 | 
|---|
| 908 |    option_data_section_name},
 | 
|---|
| 909 |   {"rename-section", required_argument, NULL,
 | 
|---|
| 910 |    option_rename_section_name},
 | 
|---|
| 911 |   {"bss-section-name", required_argument, NULL,
 | 
|---|
| 912 |    option_bss_section_name},
 | 
|---|
| 913 | #endif /* XTENSA_SECTION_RENAME */
 | 
|---|
| 914 | 
 | 
|---|
| 915 |   {NULL, no_argument, NULL, 0}
 | 
|---|
| 916 | };
 | 
|---|
| 917 | 
 | 
|---|
| 918 | size_t md_longopts_size = sizeof md_longopts;
 | 
|---|
| 919 | 
 | 
|---|
| 920 | 
 | 
|---|
| 921 | int
 | 
|---|
| 922 | md_parse_option (c, arg)
 | 
|---|
| 923 |      int c;
 | 
|---|
| 924 |      char *arg;
 | 
|---|
| 925 | {
 | 
|---|
| 926 |   switch (c)
 | 
|---|
| 927 |     {
 | 
|---|
| 928 |     case option_density:
 | 
|---|
| 929 |       if (!density_supported)
 | 
|---|
| 930 |         {
 | 
|---|
| 931 |           as_bad (_("'--density' option not supported in this Xtensa "
 | 
|---|
| 932 |                   "configuration"));
 | 
|---|
| 933 |           return 0;
 | 
|---|
| 934 |         }
 | 
|---|
| 935 |       directive_state[directive_density] = TRUE;
 | 
|---|
| 936 |       return 1;
 | 
|---|
| 937 |     case option_no_density:
 | 
|---|
| 938 |       directive_state[directive_density] = FALSE;
 | 
|---|
| 939 |       return 1;
 | 
|---|
| 940 |     case option_generics:
 | 
|---|
| 941 |       directive_state[directive_generics] = TRUE;
 | 
|---|
| 942 |       return 1;
 | 
|---|
| 943 |     case option_no_generics:
 | 
|---|
| 944 |       directive_state[directive_generics] = FALSE;
 | 
|---|
| 945 |       return 1;
 | 
|---|
| 946 |     case option_longcalls:
 | 
|---|
| 947 |       directive_state[directive_longcalls] = TRUE;
 | 
|---|
| 948 |       return 1;
 | 
|---|
| 949 |     case option_no_longcalls:
 | 
|---|
| 950 |       directive_state[directive_longcalls] = FALSE;
 | 
|---|
| 951 |       return 1;
 | 
|---|
| 952 |     case option_text_section_literals:
 | 
|---|
| 953 |       use_literal_section = FALSE;
 | 
|---|
| 954 |       return 1;
 | 
|---|
| 955 |     case option_no_text_section_literals:
 | 
|---|
| 956 |       use_literal_section = TRUE;
 | 
|---|
| 957 |       return 1;
 | 
|---|
| 958 |     case option_workaround_a0_b_retw:
 | 
|---|
| 959 |       workaround_a0_b_retw = TRUE;
 | 
|---|
| 960 |       software_a0_b_retw_interlock = TRUE;
 | 
|---|
| 961 |       return 1;
 | 
|---|
| 962 |     case option_no_workaround_a0_b_retw:
 | 
|---|
| 963 |       workaround_a0_b_retw = FALSE;
 | 
|---|
| 964 |       software_a0_b_retw_interlock = FALSE;
 | 
|---|
| 965 |       return 1;
 | 
|---|
| 966 |     case option_workaround_b_j_loop_end:
 | 
|---|
| 967 |       workaround_b_j_loop_end = TRUE;
 | 
|---|
| 968 |       software_avoid_b_j_loop_end = TRUE;
 | 
|---|
| 969 |       return 1;
 | 
|---|
| 970 |     case option_no_workaround_b_j_loop_end:
 | 
|---|
| 971 |       workaround_b_j_loop_end = FALSE;
 | 
|---|
| 972 |       software_avoid_b_j_loop_end = FALSE;
 | 
|---|
| 973 |       return 1;
 | 
|---|
| 974 | 
 | 
|---|
| 975 |     case option_workaround_short_loop:
 | 
|---|
| 976 |       workaround_short_loop = TRUE;
 | 
|---|
| 977 |       software_avoid_short_loop = TRUE;
 | 
|---|
| 978 |       return 1;
 | 
|---|
| 979 |     case option_no_workaround_short_loop:
 | 
|---|
| 980 |       workaround_short_loop = FALSE;
 | 
|---|
| 981 |       software_avoid_short_loop = FALSE;
 | 
|---|
| 982 |       return 1;
 | 
|---|
| 983 | 
 | 
|---|
| 984 |     case option_workaround_all_short_loops:
 | 
|---|
| 985 |       workaround_all_short_loops = TRUE;
 | 
|---|
| 986 |       software_avoid_all_short_loops = TRUE;
 | 
|---|
| 987 |       return 1;
 | 
|---|
| 988 |     case option_no_workaround_all_short_loops:
 | 
|---|
| 989 |       workaround_all_short_loops = FALSE;
 | 
|---|
| 990 |       software_avoid_all_short_loops = FALSE;
 | 
|---|
| 991 |       return 1;
 | 
|---|
| 992 | 
 | 
|---|
| 993 |     case option_workaround_close_loop_end:
 | 
|---|
| 994 |       workaround_close_loop_end = TRUE;
 | 
|---|
| 995 |       software_avoid_close_loop_end = TRUE;
 | 
|---|
| 996 |       return 1;
 | 
|---|
| 997 |     case option_no_workaround_close_loop_end:
 | 
|---|
| 998 |       workaround_close_loop_end = FALSE;
 | 
|---|
| 999 |       software_avoid_close_loop_end = FALSE;
 | 
|---|
| 1000 |       return 1;
 | 
|---|
| 1001 | 
 | 
|---|
| 1002 |     case option_no_workarounds:
 | 
|---|
| 1003 |       workaround_a0_b_retw = FALSE;
 | 
|---|
| 1004 |       software_a0_b_retw_interlock = FALSE;
 | 
|---|
| 1005 |       workaround_b_j_loop_end = FALSE;
 | 
|---|
| 1006 |       software_avoid_b_j_loop_end = FALSE;
 | 
|---|
| 1007 |       workaround_short_loop = FALSE;
 | 
|---|
| 1008 |       software_avoid_short_loop = FALSE;
 | 
|---|
| 1009 |       workaround_all_short_loops = FALSE;
 | 
|---|
| 1010 |       software_avoid_all_short_loops = FALSE;
 | 
|---|
| 1011 |       workaround_close_loop_end = FALSE;
 | 
|---|
| 1012 |       software_avoid_close_loop_end = FALSE;
 | 
|---|
| 1013 |       return 1;
 | 
|---|
| 1014 |       
 | 
|---|
| 1015 |     case option_align_targets:
 | 
|---|
| 1016 |       align_targets = TRUE;
 | 
|---|
| 1017 |       return 1;
 | 
|---|
| 1018 |     case option_no_align_targets:
 | 
|---|
| 1019 |       align_targets = FALSE;
 | 
|---|
| 1020 |       return 1;
 | 
|---|
| 1021 | 
 | 
|---|
| 1022 |     case option_align_only_targets:
 | 
|---|
| 1023 |       align_only_targets = TRUE;
 | 
|---|
| 1024 |       return 1;
 | 
|---|
| 1025 |     case option_no_align_only_targets:
 | 
|---|
| 1026 |       align_only_targets = FALSE;
 | 
|---|
| 1027 |       return 1;
 | 
|---|
| 1028 | 
 | 
|---|
| 1029 | #ifdef XTENSA_SECTION_RENAME
 | 
|---|
| 1030 |     case option_literal_section_name:
 | 
|---|
| 1031 |       add_section_rename (".literal", arg);
 | 
|---|
| 1032 |       as_warn (_("'--literal-section-name' is deprecated; "
 | 
|---|
| 1033 |                  "use '--rename-section .literal=NEWNAME'"));
 | 
|---|
| 1034 |       return 1;
 | 
|---|
| 1035 | 
 | 
|---|
| 1036 |     case option_text_section_name:
 | 
|---|
| 1037 |       add_section_rename (".text", arg);
 | 
|---|
| 1038 |       as_warn (_("'--text-section-name' is deprecated; "
 | 
|---|
| 1039 |                  "use '--rename-section .text=NEWNAME'"));
 | 
|---|
| 1040 |       return 1;
 | 
|---|
| 1041 | 
 | 
|---|
| 1042 |     case option_data_section_name:
 | 
|---|
| 1043 |       add_section_rename (".data", arg);
 | 
|---|
| 1044 |       as_warn (_("'--data-section-name' is deprecated; "
 | 
|---|
| 1045 |                  "use '--rename-section .data=NEWNAME'"));
 | 
|---|
| 1046 |       return 1;
 | 
|---|
| 1047 | 
 | 
|---|
| 1048 |     case option_bss_section_name:
 | 
|---|
| 1049 |       add_section_rename (".bss", arg);
 | 
|---|
| 1050 |       as_warn (_("'--bss-section-name' is deprecated; "
 | 
|---|
| 1051 |                  "use '--rename-section .bss=NEWNAME'"));
 | 
|---|
| 1052 |       return 1;
 | 
|---|
| 1053 | 
 | 
|---|
| 1054 |     case option_rename_section_name:
 | 
|---|
| 1055 |       build_section_rename (arg);
 | 
|---|
| 1056 |       return 1;
 | 
|---|
| 1057 | #endif /* XTENSA_SECTION_RENAME */
 | 
|---|
| 1058 | 
 | 
|---|
| 1059 |     case 'Q':
 | 
|---|
| 1060 |       /* -Qy, -Qn: SVR4 arguments controlling whether a .comment section
 | 
|---|
| 1061 |          should be emitted or not.  FIXME: Not implemented.  */
 | 
|---|
| 1062 |       return 1;
 | 
|---|
| 1063 |       
 | 
|---|
| 1064 |     default:
 | 
|---|
| 1065 |       return 0;
 | 
|---|
| 1066 |     }
 | 
|---|
| 1067 | }
 | 
|---|
| 1068 | 
 | 
|---|
| 1069 | 
 | 
|---|
| 1070 | void
 | 
|---|
| 1071 | md_show_usage (stream)
 | 
|---|
| 1072 |      FILE *stream;
 | 
|---|
| 1073 | {
 | 
|---|
| 1074 |   fputs ("\nXtensa options:\n"
 | 
|---|
| 1075 |          "--[no-]density          [Do not] emit density instructions\n"
 | 
|---|
| 1076 |          "--[no-]relax            [Do not] perform branch relaxation\n"
 | 
|---|
| 1077 |          "--[no-]generics         [Do not] transform instructions\n"
 | 
|---|
| 1078 |          "--[no-]longcalls        [Do not] emit 32-bit call sequences\n"
 | 
|---|
| 1079 |          "--[no-]target-align     [Do not] try to align branch targets\n"
 | 
|---|
| 1080 |          "--[no-]text-section-literals\n"
 | 
|---|
| 1081 |          "                        [Do not] put literals in the text section\n"
 | 
|---|
| 1082 |          "--no-workarounds        Do not use any Xtensa workarounds\n"
 | 
|---|
| 1083 | #ifdef XTENSA_SECTION_RENAME
 | 
|---|
| 1084 |          "--rename-section old=new(:old1=new1)*\n"
 | 
|---|
| 1085 |          "                        Rename section 'old' to 'new'\n"
 | 
|---|
| 1086 |          "\nThe following Xtensa options are deprecated\n"
 | 
|---|
| 1087 |          "--literal-section-name  Name of literal section (default .literal)\n"
 | 
|---|
| 1088 |          "--text-section-name     Name of text section (default .text)\n"
 | 
|---|
| 1089 |          "--data-section-name     Name of data section (default .data)\n"
 | 
|---|
| 1090 |          "--bss-section-name      Name of bss section (default .bss)\n"
 | 
|---|
| 1091 | #endif
 | 
|---|
| 1092 |          , stream);
 | 
|---|
| 1093 | }
 | 
|---|
| 1094 | 
 | 
|---|
| 1095 |  | 
|---|
| 1096 | 
 | 
|---|
| 1097 | /* Directive data and functions.  */
 | 
|---|
| 1098 | 
 | 
|---|
| 1099 | typedef struct state_stackS_struct
 | 
|---|
| 1100 | {
 | 
|---|
| 1101 |   directiveE directive;
 | 
|---|
| 1102 |   bfd_boolean negated;
 | 
|---|
| 1103 |   bfd_boolean old_state;
 | 
|---|
| 1104 |   const char *file;
 | 
|---|
| 1105 |   unsigned int line;
 | 
|---|
| 1106 |   const void *datum;
 | 
|---|
| 1107 |   struct state_stackS_struct *prev;
 | 
|---|
| 1108 | } state_stackS;
 | 
|---|
| 1109 | 
 | 
|---|
| 1110 | state_stackS *directive_state_stack;
 | 
|---|
| 1111 | 
 | 
|---|
| 1112 | const pseudo_typeS md_pseudo_table[] =
 | 
|---|
| 1113 | {
 | 
|---|
| 1114 |   {"align", s_align_bytes, 0},  /* Defaulting is invalid (0) */
 | 
|---|
| 1115 |   {"literal_position", xtensa_literal_position, 0},
 | 
|---|
| 1116 |   {"frame", s_ignore, 0},       /* formerly used for STABS debugging */
 | 
|---|
| 1117 |   {"word", cons, 4},
 | 
|---|
| 1118 |   {"begin", xtensa_begin_directive, 0},
 | 
|---|
| 1119 |   {"end", xtensa_end_directive, 0},
 | 
|---|
| 1120 |   {"file", (void (*) PARAMS ((int))) dwarf2_directive_file, 0},
 | 
|---|
| 1121 |   {"loc", dwarf2_directive_loc, 0},
 | 
|---|
| 1122 |   {"literal", xtensa_literal_pseudo, 0},
 | 
|---|
| 1123 |   {NULL, 0, 0},
 | 
|---|
| 1124 | };
 | 
|---|
| 1125 | 
 | 
|---|
| 1126 | 
 | 
|---|
| 1127 | bfd_boolean
 | 
|---|
| 1128 | use_generics ()
 | 
|---|
| 1129 | {
 | 
|---|
| 1130 |   return directive_state[directive_generics];
 | 
|---|
| 1131 | }
 | 
|---|
| 1132 | 
 | 
|---|
| 1133 | 
 | 
|---|
| 1134 | bfd_boolean
 | 
|---|
| 1135 | use_longcalls ()
 | 
|---|
| 1136 | {
 | 
|---|
| 1137 |   return directive_state[directive_longcalls];
 | 
|---|
| 1138 | }
 | 
|---|
| 1139 | 
 | 
|---|
| 1140 | 
 | 
|---|
| 1141 | bfd_boolean
 | 
|---|
| 1142 | code_density_available ()
 | 
|---|
| 1143 | {
 | 
|---|
| 1144 |   return directive_state[directive_density];
 | 
|---|
| 1145 | }
 | 
|---|
| 1146 | 
 | 
|---|
| 1147 | 
 | 
|---|
| 1148 | bfd_boolean
 | 
|---|
| 1149 | can_relax ()
 | 
|---|
| 1150 | {
 | 
|---|
| 1151 |   return use_generics ();
 | 
|---|
| 1152 | }
 | 
|---|
| 1153 | 
 | 
|---|
| 1154 | 
 | 
|---|
| 1155 | static void
 | 
|---|
| 1156 | directive_push (directive, negated, datum)
 | 
|---|
| 1157 |      directiveE directive;
 | 
|---|
| 1158 |      bfd_boolean negated;
 | 
|---|
| 1159 |      const void *datum;
 | 
|---|
| 1160 | {
 | 
|---|
| 1161 |   char *file;
 | 
|---|
| 1162 |   unsigned int line;
 | 
|---|
| 1163 |   state_stackS *stack = (state_stackS *) xmalloc (sizeof (state_stackS));
 | 
|---|
| 1164 | 
 | 
|---|
| 1165 |   as_where (&file, &line);
 | 
|---|
| 1166 | 
 | 
|---|
| 1167 |   stack->directive = directive;
 | 
|---|
| 1168 |   stack->negated = negated;
 | 
|---|
| 1169 |   stack->old_state = directive_state[directive];
 | 
|---|
| 1170 |   stack->file = file;
 | 
|---|
| 1171 |   stack->line = line;
 | 
|---|
| 1172 |   stack->datum = datum;
 | 
|---|
| 1173 |   stack->prev = directive_state_stack;
 | 
|---|
| 1174 |   directive_state_stack = stack;
 | 
|---|
| 1175 | 
 | 
|---|
| 1176 |   directive_state[directive] = !negated;
 | 
|---|
| 1177 | }
 | 
|---|
| 1178 | 
 | 
|---|
| 1179 | static void
 | 
|---|
| 1180 | directive_pop (directive, negated, file, line, datum)
 | 
|---|
| 1181 |      directiveE *directive;
 | 
|---|
| 1182 |      bfd_boolean *negated;
 | 
|---|
| 1183 |      const char **file;
 | 
|---|
| 1184 |      unsigned int *line;
 | 
|---|
| 1185 |      const void **datum;
 | 
|---|
| 1186 | {
 | 
|---|
| 1187 |   state_stackS *top = directive_state_stack;
 | 
|---|
| 1188 | 
 | 
|---|
| 1189 |   if (!directive_state_stack)
 | 
|---|
| 1190 |     {
 | 
|---|
| 1191 |       as_bad (_("unmatched end directive"));
 | 
|---|
| 1192 |       *directive = directive_none;
 | 
|---|
| 1193 |       return;
 | 
|---|
| 1194 |     }
 | 
|---|
| 1195 | 
 | 
|---|
| 1196 |   directive_state[directive_state_stack->directive] = top->old_state;
 | 
|---|
| 1197 |   *directive = top->directive;
 | 
|---|
| 1198 |   *negated = top->negated;
 | 
|---|
| 1199 |   *file = top->file;
 | 
|---|
| 1200 |   *line = top->line;
 | 
|---|
| 1201 |   *datum = top->datum;
 | 
|---|
| 1202 |   directive_state_stack = top->prev;
 | 
|---|
| 1203 |   free (top);
 | 
|---|
| 1204 | }
 | 
|---|
| 1205 | 
 | 
|---|
| 1206 | 
 | 
|---|
| 1207 | static void
 | 
|---|
| 1208 | directive_balance ()
 | 
|---|
| 1209 | {
 | 
|---|
| 1210 |   while (directive_state_stack)
 | 
|---|
| 1211 |     {
 | 
|---|
| 1212 |       directiveE directive;
 | 
|---|
| 1213 |       bfd_boolean negated;
 | 
|---|
| 1214 |       const char *file;
 | 
|---|
| 1215 |       unsigned int line;
 | 
|---|
| 1216 |       const void *datum;
 | 
|---|
| 1217 | 
 | 
|---|
| 1218 |       directive_pop (&directive, &negated, &file, &line, &datum);
 | 
|---|
| 1219 |       as_warn_where ((char *) file, line,
 | 
|---|
| 1220 |                      _(".begin directive with no matching .end directive"));
 | 
|---|
| 1221 |     }
 | 
|---|
| 1222 | }
 | 
|---|
| 1223 | 
 | 
|---|
| 1224 | 
 | 
|---|
| 1225 | static bfd_boolean
 | 
|---|
| 1226 | inside_directive (dir)
 | 
|---|
| 1227 |      directiveE dir;
 | 
|---|
| 1228 | {
 | 
|---|
| 1229 |   state_stackS *top = directive_state_stack;
 | 
|---|
| 1230 | 
 | 
|---|
| 1231 |   while (top && top->directive != dir)
 | 
|---|
| 1232 |     top = top->prev;
 | 
|---|
| 1233 | 
 | 
|---|
| 1234 |   return (top != NULL);
 | 
|---|
| 1235 | }
 | 
|---|
| 1236 | 
 | 
|---|
| 1237 | 
 | 
|---|
| 1238 | static void
 | 
|---|
| 1239 | get_directive (directive, negated)
 | 
|---|
| 1240 |      directiveE *directive;
 | 
|---|
| 1241 |      bfd_boolean *negated;
 | 
|---|
| 1242 | {
 | 
|---|
| 1243 |   int len;
 | 
|---|
| 1244 |   unsigned i;
 | 
|---|
| 1245 | 
 | 
|---|
| 1246 |   if (strncmp (input_line_pointer, "no-", 3) != 0)
 | 
|---|
| 1247 |     *negated = FALSE;
 | 
|---|
| 1248 |   else
 | 
|---|
| 1249 |     {
 | 
|---|
| 1250 |       *negated = TRUE;
 | 
|---|
| 1251 |       input_line_pointer += 3;
 | 
|---|
| 1252 |     }
 | 
|---|
| 1253 | 
 | 
|---|
| 1254 |   len = strspn (input_line_pointer,
 | 
|---|
| 1255 |                 "abcdefghijklmnopqrstuvwxyz_/0123456789.");
 | 
|---|
| 1256 | 
 | 
|---|
| 1257 |   for (i = 0; i < sizeof (directive_info) / sizeof (*directive_info); ++i)
 | 
|---|
| 1258 |     {
 | 
|---|
| 1259 |       if (strncmp (input_line_pointer, directive_info[i].name, len) == 0)
 | 
|---|
| 1260 |         {
 | 
|---|
| 1261 |           input_line_pointer += len;
 | 
|---|
| 1262 |           *directive = (directiveE) i;
 | 
|---|
| 1263 |           if (*negated && !directive_info[i].can_be_negated)
 | 
|---|
| 1264 |             as_bad (_("directive %s can't be negated"),
 | 
|---|
| 1265 |                     directive_info[i].name);
 | 
|---|
| 1266 |           return;
 | 
|---|
| 1267 |         }
 | 
|---|
| 1268 |     }
 | 
|---|
| 1269 | 
 | 
|---|
| 1270 |   as_bad (_("unknown directive"));
 | 
|---|
| 1271 |   *directive = (directiveE) XTENSA_UNDEFINED;
 | 
|---|
| 1272 | }
 | 
|---|
| 1273 | 
 | 
|---|
| 1274 | 
 | 
|---|
| 1275 | static void
 | 
|---|
| 1276 | xtensa_begin_directive (ignore)
 | 
|---|
| 1277 |      int ignore ATTRIBUTE_UNUSED;
 | 
|---|
| 1278 | {
 | 
|---|
| 1279 |   directiveE directive;
 | 
|---|
| 1280 |   bfd_boolean negated;
 | 
|---|
| 1281 |   emit_state *state;
 | 
|---|
| 1282 |   int len;
 | 
|---|
| 1283 |   lit_state *ls;
 | 
|---|
| 1284 | 
 | 
|---|
| 1285 |   get_directive (&directive, &negated);
 | 
|---|
| 1286 |   if (directive == (directiveE) XTENSA_UNDEFINED)
 | 
|---|
| 1287 |     {
 | 
|---|
| 1288 |       discard_rest_of_line ();
 | 
|---|
| 1289 |       return;
 | 
|---|
| 1290 |     }
 | 
|---|
| 1291 | 
 | 
|---|
| 1292 |   switch (directive)
 | 
|---|
| 1293 |     {
 | 
|---|
| 1294 |     case directive_literal:
 | 
|---|
| 1295 |       state = (emit_state *) xmalloc (sizeof (emit_state));
 | 
|---|
| 1296 |       xtensa_switch_to_literal_fragment (state);
 | 
|---|
| 1297 |       directive_push (directive_literal, negated, state);
 | 
|---|
| 1298 |       break;
 | 
|---|
| 1299 | 
 | 
|---|
| 1300 |     case directive_literal_prefix:
 | 
|---|
| 1301 |       /* Check to see if the current fragment is a literal
 | 
|---|
| 1302 |          fragment.  If it is, then this operation is not allowed.  */
 | 
|---|
| 1303 |       if (frag_now->tc_frag_data.is_literal)
 | 
|---|
| 1304 |         {
 | 
|---|
| 1305 |           as_bad (_("cannot set literal_prefix inside literal fragment"));
 | 
|---|
| 1306 |           return;
 | 
|---|
| 1307 |         }
 | 
|---|
| 1308 | 
 | 
|---|
| 1309 |       /* Allocate the literal state for this section and push
 | 
|---|
| 1310 |          onto the directive stack.  */
 | 
|---|
| 1311 |       ls = xmalloc (sizeof (lit_state));
 | 
|---|
| 1312 |       assert (ls);
 | 
|---|
| 1313 | 
 | 
|---|
| 1314 |       *ls = default_lit_sections;
 | 
|---|
| 1315 | 
 | 
|---|
| 1316 |       directive_push (directive_literal_prefix, negated, ls);
 | 
|---|
| 1317 | 
 | 
|---|
| 1318 |       /* Parse the new prefix from the input_line_pointer.  */
 | 
|---|
| 1319 |       SKIP_WHITESPACE ();
 | 
|---|
| 1320 |       len = strspn (input_line_pointer,
 | 
|---|
| 1321 |                     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 | 
|---|
| 1322 |                     "abcdefghijklmnopqrstuvwxyz_/0123456789.$");
 | 
|---|
| 1323 | 
 | 
|---|
| 1324 |       /* Process the new prefix.  */
 | 
|---|
| 1325 |       xtensa_literal_prefix (input_line_pointer, len);
 | 
|---|
| 1326 | 
 | 
|---|
| 1327 |       /* Skip the name in the input line.  */
 | 
|---|
| 1328 |       input_line_pointer += len;
 | 
|---|
| 1329 |       break;
 | 
|---|
| 1330 | 
 | 
|---|
| 1331 |     case directive_freeregs:
 | 
|---|
| 1332 |       /* This information is currently unused, but we'll accept the statement
 | 
|---|
| 1333 |          and just discard the rest of the line.  This won't check the syntax,
 | 
|---|
| 1334 |          but it will accept every correct freeregs directive.  */
 | 
|---|
| 1335 |       input_line_pointer += strcspn (input_line_pointer, "\n");
 | 
|---|
| 1336 |       directive_push (directive_freeregs, negated, 0);
 | 
|---|
| 1337 |       break;
 | 
|---|
| 1338 | 
 | 
|---|
| 1339 |     case directive_density:
 | 
|---|
| 1340 |       if (!density_supported && !negated)
 | 
|---|
| 1341 |         {
 | 
|---|
| 1342 |           as_warn (_("Xtensa density option not supported; ignored"));
 | 
|---|
| 1343 |           break;
 | 
|---|
| 1344 |         }
 | 
|---|
| 1345 |       /* fall through */
 | 
|---|
| 1346 | 
 | 
|---|
| 1347 |     default:
 | 
|---|
| 1348 |       directive_push (directive, negated, 0);
 | 
|---|
| 1349 |       break;
 | 
|---|
| 1350 |     }
 | 
|---|
| 1351 | 
 | 
|---|
| 1352 |   demand_empty_rest_of_line ();
 | 
|---|
| 1353 | }
 | 
|---|
| 1354 | 
 | 
|---|
| 1355 | 
 | 
|---|
| 1356 | static void
 | 
|---|
| 1357 | xtensa_end_directive (ignore)
 | 
|---|
| 1358 |      int ignore ATTRIBUTE_UNUSED;
 | 
|---|
| 1359 | {
 | 
|---|
| 1360 |   directiveE begin_directive, end_directive;
 | 
|---|
| 1361 |   bfd_boolean begin_negated, end_negated;
 | 
|---|
| 1362 |   const char *file;
 | 
|---|
| 1363 |   unsigned int line;
 | 
|---|
| 1364 |   emit_state *state;
 | 
|---|
| 1365 |   lit_state *s;
 | 
|---|
| 1366 | 
 | 
|---|
| 1367 |   get_directive (&end_directive, &end_negated);
 | 
|---|
| 1368 |   if (end_directive == (directiveE) XTENSA_UNDEFINED)
 | 
|---|
| 1369 |     {
 | 
|---|
| 1370 |       discard_rest_of_line ();
 | 
|---|
| 1371 |       return;
 | 
|---|
| 1372 |     }
 | 
|---|
| 1373 | 
 | 
|---|
| 1374 |   if (end_directive == directive_density && !density_supported && !end_negated)
 | 
|---|
| 1375 |     {
 | 
|---|
| 1376 |       as_warn (_("Xtensa density option not supported; ignored"));
 | 
|---|
| 1377 |       demand_empty_rest_of_line ();
 | 
|---|
| 1378 |       return;
 | 
|---|
| 1379 |     }
 | 
|---|
| 1380 | 
 | 
|---|
| 1381 |   directive_pop (&begin_directive, &begin_negated, &file, &line,
 | 
|---|
| 1382 |                  (const void **) &state);
 | 
|---|
| 1383 | 
 | 
|---|
| 1384 |   if (begin_directive != directive_none)
 | 
|---|
| 1385 |     {
 | 
|---|
| 1386 |       if (begin_directive != end_directive || begin_negated != end_negated)
 | 
|---|
| 1387 |         {
 | 
|---|
| 1388 |           as_bad (_("does not match begin %s%s at %s:%d"),
 | 
|---|
| 1389 |                   begin_negated ? "no-" : "",
 | 
|---|
| 1390 |                   directive_info[begin_directive].name, file, line);
 | 
|---|
| 1391 |         }
 | 
|---|
| 1392 |       else
 | 
|---|
| 1393 |         {
 | 
|---|
| 1394 |           switch (end_directive)
 | 
|---|
| 1395 |             {
 | 
|---|
| 1396 |             case directive_literal:
 | 
|---|
| 1397 |               frag_var (rs_fill, 0, 0, 0, NULL, 0, NULL);
 | 
|---|
| 1398 |               xtensa_restore_emit_state (state);
 | 
|---|
| 1399 |               free (state);
 | 
|---|
| 1400 |               break;
 | 
|---|
| 1401 | 
 | 
|---|
| 1402 |             case directive_freeregs:
 | 
|---|
| 1403 |               break;
 | 
|---|
| 1404 | 
 | 
|---|
| 1405 |             case directive_literal_prefix:
 | 
|---|
| 1406 |               /* Restore the default collection sections from saved state.  */
 | 
|---|
| 1407 |               s = (lit_state *) state;
 | 
|---|
| 1408 |               assert (s);
 | 
|---|
| 1409 | 
 | 
|---|
| 1410 |               if (use_literal_section)
 | 
|---|
| 1411 |                 default_lit_sections = *s;
 | 
|---|
| 1412 | 
 | 
|---|
| 1413 |               /* free the state storage */
 | 
|---|
| 1414 |               free (s);
 | 
|---|
| 1415 |               break;
 | 
|---|
| 1416 | 
 | 
|---|
| 1417 |             default:
 | 
|---|
| 1418 |               break;
 | 
|---|
| 1419 |             }
 | 
|---|
| 1420 |         }
 | 
|---|
| 1421 |     }
 | 
|---|
| 1422 | 
 | 
|---|
| 1423 |   demand_empty_rest_of_line ();
 | 
|---|
| 1424 | }
 | 
|---|
| 1425 | 
 | 
|---|
| 1426 | 
 | 
|---|
| 1427 | /* Place an aligned literal fragment at the current location.  */
 | 
|---|
| 1428 | 
 | 
|---|
| 1429 | static void
 | 
|---|
| 1430 | xtensa_literal_position (ignore)
 | 
|---|
| 1431 |      int ignore ATTRIBUTE_UNUSED;
 | 
|---|
| 1432 | {
 | 
|---|
| 1433 |   if (inside_directive (directive_literal))
 | 
|---|
| 1434 |     as_warn (_(".literal_position inside literal directive; ignoring"));
 | 
|---|
| 1435 |   else if (!use_literal_section)
 | 
|---|
| 1436 |     xtensa_mark_literal_pool_location (FALSE);
 | 
|---|
| 1437 | 
 | 
|---|
| 1438 |   demand_empty_rest_of_line ();
 | 
|---|
| 1439 | }
 | 
|---|
| 1440 | 
 | 
|---|
| 1441 | 
 | 
|---|
| 1442 | /* Support .literal label, value@plt + offset.  */
 | 
|---|
| 1443 | 
 | 
|---|
| 1444 | static void
 | 
|---|
| 1445 | xtensa_literal_pseudo (ignored)
 | 
|---|
| 1446 |      int ignored ATTRIBUTE_UNUSED;
 | 
|---|
| 1447 | {
 | 
|---|
| 1448 |   emit_state state;
 | 
|---|
| 1449 |   char *base_name;
 | 
|---|
| 1450 | #ifdef XTENSA_COMBINE_LITERALS
 | 
|---|
| 1451 |   char *next_name;
 | 
|---|
| 1452 |   symbolS *duplicate;
 | 
|---|
| 1453 |   bfd_boolean used_name = FALSE;
 | 
|---|
| 1454 |   int offset = 0;
 | 
|---|
| 1455 | #endif
 | 
|---|
| 1456 |   char c;
 | 
|---|
| 1457 |   char *p;
 | 
|---|
| 1458 |   expressionS expP;
 | 
|---|
| 1459 |   segT dest_seg;
 | 
|---|
| 1460 | 
 | 
|---|
| 1461 |   /* If we are using text-section literals, then this is the right value... */
 | 
|---|
| 1462 |   dest_seg = now_seg;
 | 
|---|
| 1463 | 
 | 
|---|
| 1464 |   base_name = input_line_pointer;
 | 
|---|
| 1465 | 
 | 
|---|
| 1466 |   xtensa_switch_to_literal_fragment (&state);
 | 
|---|
| 1467 | 
 | 
|---|
| 1468 |   /* ...but if we aren't using text-section-literals, then we 
 | 
|---|
| 1469 |      need to put them in the section we just switched to.  */
 | 
|---|
| 1470 |   if (use_literal_section)
 | 
|---|
| 1471 |     dest_seg = now_seg;
 | 
|---|
| 1472 | 
 | 
|---|
| 1473 |   /* All literals are aligned to four-byte boundaries
 | 
|---|
| 1474 |      which is handled by switch to literal fragment.  */
 | 
|---|
| 1475 |   /* frag_align (2, 0, 0);  */
 | 
|---|
| 1476 | 
 | 
|---|
| 1477 |   c = get_symbol_end ();
 | 
|---|
| 1478 |   /* Just after name is now '\0'.  */
 | 
|---|
| 1479 |   p = input_line_pointer;
 | 
|---|
| 1480 |   *p = c;
 | 
|---|
| 1481 |   SKIP_WHITESPACE ();
 | 
|---|
| 1482 | 
 | 
|---|
| 1483 |   if (*input_line_pointer != ',' && *input_line_pointer != ':')
 | 
|---|
| 1484 |     {
 | 
|---|
| 1485 |       as_bad (_("expected comma or colon after symbol name; "
 | 
|---|
| 1486 |                 "rest of line ignored"));
 | 
|---|
| 1487 |       ignore_rest_of_line ();
 | 
|---|
| 1488 |       xtensa_restore_emit_state (&state);
 | 
|---|
| 1489 |       return;
 | 
|---|
| 1490 |     }
 | 
|---|
| 1491 |   *p = 0;
 | 
|---|
| 1492 | 
 | 
|---|
| 1493 | #ifdef XTENSA_COMBINE_LITERALS
 | 
|---|
| 1494 |   /* We need next name to start out equal to base_name,
 | 
|---|
| 1495 |      but we modify it later to refer to a symbol and an offset.  */
 | 
|---|
| 1496 |   next_name = xmalloc (strlen (base_name) + 1);
 | 
|---|
| 1497 |   strcpy (next_name, base_name);
 | 
|---|
| 1498 | 
 | 
|---|
| 1499 |   /* We need a copy of base_name because we refer to it in the 
 | 
|---|
| 1500 |      lit_sym_translations and the source is somewhere in the input stream.  */
 | 
|---|
| 1501 |   base_name = xmalloc (strlen (base_name) + 1);
 | 
|---|
| 1502 |   strcpy (base_name, next_name);
 | 
|---|
| 1503 | 
 | 
|---|
| 1504 | #else
 | 
|---|
| 1505 | 
 | 
|---|
| 1506 |   colon (base_name);
 | 
|---|
| 1507 | #endif
 | 
|---|
| 1508 | 
 | 
|---|
| 1509 |   do 
 | 
|---|
| 1510 |     {
 | 
|---|
| 1511 |       input_line_pointer++;             /* skip ',' or ':' */
 | 
|---|
| 1512 |       
 | 
|---|
| 1513 |       expr (0, &expP);
 | 
|---|
| 1514 | 
 | 
|---|
| 1515 | #ifdef XTENSA_COMBINE_LITERALS
 | 
|---|
| 1516 |       duplicate = is_duplicate_literal (&expP, dest_seg);
 | 
|---|
| 1517 |       if (duplicate)
 | 
|---|
| 1518 |         {
 | 
|---|
| 1519 |           add_lit_sym_translation (base_name, offset, duplicate);
 | 
|---|
| 1520 |           used_name = TRUE;
 | 
|---|
| 1521 |           continue;
 | 
|---|
| 1522 |         }
 | 
|---|
| 1523 |       colon (next_name);
 | 
|---|
| 1524 | #endif
 | 
|---|
| 1525 | 
 | 
|---|
| 1526 |       /* We only support 4-byte literals with .literal.  */
 | 
|---|
| 1527 |       emit_expr (&expP, 4);
 | 
|---|
| 1528 | 
 | 
|---|
| 1529 | #ifdef XTENSA_COMBINE_LITERALS
 | 
|---|
| 1530 |       cache_literal (next_name, &expP, dest_seg);
 | 
|---|
| 1531 |       free (next_name);
 | 
|---|
| 1532 | 
 | 
|---|
| 1533 |       if (*input_line_pointer == ',') 
 | 
|---|
| 1534 |         {
 | 
|---|
| 1535 |           offset += 4;
 | 
|---|
| 1536 |           next_name = xmalloc (strlen (base_name) + 
 | 
|---|
| 1537 |                                strlen (XTENSA_LIT_PLUS_OFFSET) + 10);
 | 
|---|
| 1538 |           sprintf (next_name, "%s%s%d", 
 | 
|---|
| 1539 |                    XTENSA_LIT_PLUS_OFFSET, base_name, offset);
 | 
|---|
| 1540 |         }
 | 
|---|
| 1541 | #endif
 | 
|---|
| 1542 |     }
 | 
|---|
| 1543 |   while (*input_line_pointer == ',');
 | 
|---|
| 1544 | 
 | 
|---|
| 1545 |   *p = c;
 | 
|---|
| 1546 | #ifdef XTENSA_COMBINE_LITERALS
 | 
|---|
| 1547 |   if (!used_name)
 | 
|---|
| 1548 |     free (base_name);
 | 
|---|
| 1549 | #endif
 | 
|---|
| 1550 | 
 | 
|---|
| 1551 |   demand_empty_rest_of_line ();
 | 
|---|
| 1552 | 
 | 
|---|
| 1553 |   xtensa_restore_emit_state (&state);
 | 
|---|
| 1554 | }
 | 
|---|
| 1555 | 
 | 
|---|
| 1556 | 
 | 
|---|
| 1557 | static void
 | 
|---|
| 1558 | xtensa_literal_prefix (start, len)
 | 
|---|
| 1559 |      char const *start;
 | 
|---|
| 1560 |      int len;
 | 
|---|
| 1561 | {
 | 
|---|
| 1562 |   segT s_now;                   /* Storage for the current seg and subseg.  */
 | 
|---|
| 1563 |   subsegT ss_now;
 | 
|---|
| 1564 |   char *name;                   /* Pointer to the name itself.  */
 | 
|---|
| 1565 |   char *newname;
 | 
|---|
| 1566 | 
 | 
|---|
| 1567 |   if (!use_literal_section)
 | 
|---|
| 1568 |     return;
 | 
|---|
| 1569 | 
 | 
|---|
| 1570 |   /* Store away the current section and subsection.  */
 | 
|---|
| 1571 |   s_now = now_seg;
 | 
|---|
| 1572 |   ss_now = now_subseg;
 | 
|---|
| 1573 | 
 | 
|---|
| 1574 |   /* Get a null-terminated copy of the name.  */
 | 
|---|
| 1575 |   name = xmalloc (len + 1);
 | 
|---|
| 1576 |   assert (name);
 | 
|---|
| 1577 | 
 | 
|---|
| 1578 |   strncpy (name, start, len);
 | 
|---|
| 1579 |   name[len] = 0;
 | 
|---|
| 1580 | 
 | 
|---|
| 1581 |   /* Allocate the sections (interesting note: the memory pointing to
 | 
|---|
| 1582 |      the name is actually used for the name by the new section). */
 | 
|---|
| 1583 |   newname = xmalloc (len + strlen (".literal") + 1);
 | 
|---|
| 1584 |   strcpy (newname, name);
 | 
|---|
| 1585 |   strcpy (newname + len, ".literal");
 | 
|---|
| 1586 | 
 | 
|---|
| 1587 |   /* Note that retrieve_literal_seg does not create a segment if 
 | 
|---|
| 1588 |      it already exists.  */
 | 
|---|
| 1589 |   default_lit_sections.lit_seg = NULL;  /* retrieved on demand */
 | 
|---|
| 1590 | 
 | 
|---|
| 1591 |   /* Canonicalizing section names allows renaming literal
 | 
|---|
| 1592 |      sections to occur correctly.  */
 | 
|---|
| 1593 |   default_lit_sections.lit_seg_name =
 | 
|---|
| 1594 |     tc_canonicalize_symbol_name (newname);
 | 
|---|
| 1595 | 
 | 
|---|
| 1596 |   free (name);
 | 
|---|
| 1597 | 
 | 
|---|
| 1598 |   /* Restore the current section and subsection and set the 
 | 
|---|
| 1599 |      generation into the old segment.  */
 | 
|---|
| 1600 |   subseg_set (s_now, ss_now);
 | 
|---|
| 1601 | }
 | 
|---|
| 1602 | 
 | 
|---|
| 1603 |  | 
|---|
| 1604 | 
 | 
|---|
| 1605 | /* Parsing and Idiom Translation.  */
 | 
|---|
| 1606 | 
 | 
|---|
| 1607 | static const char *
 | 
|---|
| 1608 | expression_end (name)
 | 
|---|
| 1609 |      const char *name;
 | 
|---|
| 1610 | {
 | 
|---|
| 1611 |   while (1)
 | 
|---|
| 1612 |     {
 | 
|---|
| 1613 |       switch (*name)
 | 
|---|
| 1614 |         {
 | 
|---|
| 1615 |         case ';':
 | 
|---|
| 1616 |         case '\0':
 | 
|---|
| 1617 |         case ',':
 | 
|---|
| 1618 |           return name;
 | 
|---|
| 1619 |         case ' ':
 | 
|---|
| 1620 |         case '\t':
 | 
|---|
| 1621 |           ++name;
 | 
|---|
| 1622 |           continue;
 | 
|---|
| 1623 |         default:
 | 
|---|
| 1624 |           return 0;
 | 
|---|
| 1625 |         }
 | 
|---|
| 1626 |     }
 | 
|---|
| 1627 | }
 | 
|---|
| 1628 | 
 | 
|---|
| 1629 | 
 | 
|---|
| 1630 | #define ERROR_REG_NUM ((unsigned) -1)
 | 
|---|
| 1631 | 
 | 
|---|
| 1632 | static unsigned
 | 
|---|
| 1633 | tc_get_register (prefix)
 | 
|---|
| 1634 |      const char *prefix;
 | 
|---|
| 1635 | {
 | 
|---|
| 1636 |   unsigned reg;
 | 
|---|
| 1637 |   const char *next_expr;
 | 
|---|
| 1638 |   const char *old_line_pointer;
 | 
|---|
| 1639 | 
 | 
|---|
| 1640 |   SKIP_WHITESPACE ();
 | 
|---|
| 1641 |   old_line_pointer = input_line_pointer;
 | 
|---|
| 1642 | 
 | 
|---|
| 1643 |   if (*input_line_pointer == '$')
 | 
|---|
| 1644 |     ++input_line_pointer;
 | 
|---|
| 1645 | 
 | 
|---|
| 1646 |   /* Accept "sp" as a synonym for "a1".  */
 | 
|---|
| 1647 |   if (input_line_pointer[0] == 's' && input_line_pointer[1] == 'p'
 | 
|---|
| 1648 |       && expression_end (input_line_pointer + 2))
 | 
|---|
| 1649 |     {
 | 
|---|
| 1650 |       input_line_pointer += 2;
 | 
|---|
| 1651 |       return 1;  /* AR[1] */
 | 
|---|
| 1652 |     }
 | 
|---|
| 1653 | 
 | 
|---|
| 1654 |   while (*input_line_pointer++ == *prefix++)
 | 
|---|
| 1655 |     ;
 | 
|---|
| 1656 |   --input_line_pointer;
 | 
|---|
| 1657 |   --prefix;
 | 
|---|
| 1658 | 
 | 
|---|
| 1659 |   if (*prefix)
 | 
|---|
| 1660 |     {
 | 
|---|
| 1661 |       as_bad (_("bad register name: %s"), old_line_pointer);
 | 
|---|
| 1662 |       return ERROR_REG_NUM;
 | 
|---|
| 1663 |     }
 | 
|---|
| 1664 | 
 | 
|---|
| 1665 |   if (!ISDIGIT ((unsigned char) *input_line_pointer))
 | 
|---|
| 1666 |     {
 | 
|---|
| 1667 |       as_bad (_("bad register number: %s"), input_line_pointer);
 | 
|---|
| 1668 |       return ERROR_REG_NUM;
 | 
|---|
| 1669 |     }
 | 
|---|
| 1670 | 
 | 
|---|
| 1671 |   reg = 0;
 | 
|---|
| 1672 | 
 | 
|---|
| 1673 |   while (ISDIGIT ((int) *input_line_pointer))
 | 
|---|
| 1674 |     reg = reg * 10 + *input_line_pointer++ - '0';
 | 
|---|
| 1675 | 
 | 
|---|
| 1676 |   if (!(next_expr = expression_end (input_line_pointer)))
 | 
|---|
| 1677 |     {
 | 
|---|
| 1678 |       as_bad (_("bad register name: %s"), old_line_pointer);
 | 
|---|
| 1679 |       return ERROR_REG_NUM;
 | 
|---|
| 1680 |     }
 | 
|---|
| 1681 | 
 | 
|---|
| 1682 |   input_line_pointer = (char *) next_expr;
 | 
|---|
| 1683 | 
 | 
|---|
| 1684 |   return reg;
 | 
|---|
| 1685 | }
 | 
|---|
| 1686 | 
 | 
|---|
| 1687 | 
 | 
|---|
| 1688 | #define PLT_SUFFIX "@PLT"
 | 
|---|
| 1689 | #define plt_suffix "@plt"
 | 
|---|
| 1690 | 
 | 
|---|
| 1691 | static void
 | 
|---|
| 1692 | expression_maybe_register (opnd, tok)
 | 
|---|
| 1693 |      xtensa_operand opnd;
 | 
|---|
| 1694 |      expressionS *tok;
 | 
|---|
| 1695 | {
 | 
|---|
| 1696 |   char *kind = xtensa_operand_kind (opnd);
 | 
|---|
| 1697 | 
 | 
|---|
| 1698 |   if ((strlen (kind) == 1)
 | 
|---|
| 1699 |       && (*kind == 'l' || *kind == 'L' || *kind == 'i' || *kind == 'r'))
 | 
|---|
| 1700 |     {
 | 
|---|
| 1701 |       segT t = expression (tok);
 | 
|---|
| 1702 |       if (t == absolute_section && operand_is_pcrel_label (opnd))
 | 
|---|
| 1703 |         {
 | 
|---|
| 1704 |           assert (tok->X_op == O_constant);
 | 
|---|
| 1705 |           tok->X_op = O_symbol;
 | 
|---|
| 1706 |           tok->X_add_symbol = &abs_symbol;
 | 
|---|
| 1707 |         }
 | 
|---|
| 1708 |       if (tok->X_op == O_symbol 
 | 
|---|
| 1709 |           && (!strncmp (input_line_pointer, PLT_SUFFIX,
 | 
|---|
| 1710 |                         strlen (PLT_SUFFIX) - 1)
 | 
|---|
| 1711 |               || !strncmp (input_line_pointer, plt_suffix,
 | 
|---|
| 1712 |                            strlen (plt_suffix) - 1)))
 | 
|---|
| 1713 |         {
 | 
|---|
| 1714 |           tok->X_add_symbol->sy_tc.plt = 1;
 | 
|---|
| 1715 |           input_line_pointer += strlen (plt_suffix);
 | 
|---|
| 1716 |         }
 | 
|---|
| 1717 | #ifdef XTENSA_COMBINE_LITERALS
 | 
|---|
| 1718 |       find_lit_sym_translation (tok);
 | 
|---|
| 1719 | #endif
 | 
|---|
| 1720 |     }
 | 
|---|
| 1721 |   else
 | 
|---|
| 1722 |     {
 | 
|---|
| 1723 |       unsigned reg = tc_get_register (kind);
 | 
|---|
| 1724 | 
 | 
|---|
| 1725 |       if (reg != ERROR_REG_NUM) /* Already errored */
 | 
|---|
| 1726 |         {
 | 
|---|
| 1727 |           uint32 buf = reg;
 | 
|---|
| 1728 |           if ((xtensa_operand_encode (opnd, &buf) != xtensa_encode_result_ok)
 | 
|---|
| 1729 |               || (reg != xtensa_operand_decode (opnd, buf)))
 | 
|---|
| 1730 |             as_bad (_("register number out of range"));
 | 
|---|
| 1731 |         }
 | 
|---|
| 1732 | 
 | 
|---|
| 1733 |       tok->X_op = O_register;
 | 
|---|
| 1734 |       tok->X_add_symbol = 0;
 | 
|---|
| 1735 |       tok->X_add_number = reg;
 | 
|---|
| 1736 |     }
 | 
|---|
| 1737 | }
 | 
|---|
| 1738 | 
 | 
|---|
| 1739 | 
 | 
|---|
| 1740 | /* Split up the arguments for an opcode or pseudo-op.  */
 | 
|---|
| 1741 | 
 | 
|---|
| 1742 | static int
 | 
|---|
| 1743 | tokenize_arguments (args, str)
 | 
|---|
| 1744 |      char **args;
 | 
|---|
| 1745 |      char *str;
 | 
|---|
| 1746 | {
 | 
|---|
| 1747 |   char *old_input_line_pointer;
 | 
|---|
| 1748 |   bfd_boolean saw_comma = FALSE;
 | 
|---|
| 1749 |   bfd_boolean saw_arg = FALSE;
 | 
|---|
| 1750 |   int num_args = 0;
 | 
|---|
| 1751 |   char *arg_end, *arg;
 | 
|---|
| 1752 |   int arg_len;
 | 
|---|
| 1753 |   
 | 
|---|
| 1754 |   /* Save and restore input_line_pointer around this function.  */ 
 | 
|---|
| 1755 |   old_input_line_pointer = input_line_pointer;
 | 
|---|
| 1756 |   input_line_pointer = str;
 | 
|---|
| 1757 | 
 | 
|---|
| 1758 |   while (*input_line_pointer)
 | 
|---|
| 1759 |     {
 | 
|---|
| 1760 |       SKIP_WHITESPACE ();
 | 
|---|
| 1761 |       switch (*input_line_pointer)
 | 
|---|
| 1762 |         {
 | 
|---|
| 1763 |         case '\0':
 | 
|---|
| 1764 |           goto fini;
 | 
|---|
| 1765 | 
 | 
|---|
| 1766 |         case ',':
 | 
|---|
| 1767 |           input_line_pointer++;
 | 
|---|
| 1768 |           if (saw_comma || !saw_arg)
 | 
|---|
| 1769 |             goto err;
 | 
|---|
| 1770 |           saw_comma = TRUE;
 | 
|---|
| 1771 |           break;
 | 
|---|
| 1772 | 
 | 
|---|
| 1773 |         default:
 | 
|---|
| 1774 |           if (!saw_comma && saw_arg)
 | 
|---|
| 1775 |             goto err;
 | 
|---|
| 1776 | 
 | 
|---|
| 1777 |           arg_end = input_line_pointer + 1;
 | 
|---|
| 1778 |           while (!expression_end (arg_end))
 | 
|---|
| 1779 |             arg_end += 1;
 | 
|---|
| 1780 |  
 | 
|---|
| 1781 |           arg_len = arg_end - input_line_pointer;
 | 
|---|
| 1782 |           arg = (char *) xmalloc (arg_len + 1);
 | 
|---|
| 1783 |           args[num_args] = arg;
 | 
|---|
| 1784 | 
 | 
|---|
| 1785 |           strncpy (arg, input_line_pointer, arg_len);
 | 
|---|
| 1786 |           arg[arg_len] = '\0';
 | 
|---|
| 1787 |  
 | 
|---|
| 1788 |           input_line_pointer = arg_end;
 | 
|---|
| 1789 |           num_args += 1;
 | 
|---|
| 1790 |           saw_comma = FALSE; 
 | 
|---|
| 1791 |           saw_arg = TRUE; 
 | 
|---|
| 1792 |           break;
 | 
|---|
| 1793 |         }
 | 
|---|
| 1794 |     }
 | 
|---|
| 1795 | 
 | 
|---|
| 1796 | fini:
 | 
|---|
| 1797 |   if (saw_comma)
 | 
|---|
| 1798 |     goto err;
 | 
|---|
| 1799 |   input_line_pointer = old_input_line_pointer;
 | 
|---|
| 1800 |   return num_args;
 | 
|---|
| 1801 | 
 | 
|---|
| 1802 | err:
 | 
|---|
| 1803 |   input_line_pointer = old_input_line_pointer;
 | 
|---|
| 1804 |   return -1;
 | 
|---|
| 1805 | }
 | 
|---|
| 1806 | 
 | 
|---|
| 1807 | 
 | 
|---|
| 1808 | /* Parse the arguments to an opcode.  Return true on error.  */
 | 
|---|
| 1809 | 
 | 
|---|
| 1810 | static bfd_boolean
 | 
|---|
| 1811 | parse_arguments (insn, num_args, arg_strings)
 | 
|---|
| 1812 |      TInsn *insn;
 | 
|---|
| 1813 |      int num_args;
 | 
|---|
| 1814 |      char **arg_strings;
 | 
|---|
| 1815 | {
 | 
|---|
| 1816 |   expressionS *tok = insn->tok;
 | 
|---|
| 1817 |   xtensa_opcode opcode = insn->opcode;
 | 
|---|
| 1818 |   bfd_boolean had_error = TRUE;
 | 
|---|
| 1819 |   xtensa_isa isa = xtensa_default_isa; 
 | 
|---|
| 1820 |   int n;
 | 
|---|
| 1821 |   int opcode_operand_count;
 | 
|---|
| 1822 |   int actual_operand_count = 0;
 | 
|---|
| 1823 |   xtensa_operand opnd = NULL; 
 | 
|---|
| 1824 |   char *old_input_line_pointer;
 | 
|---|
| 1825 | 
 | 
|---|
| 1826 |   if (insn->insn_type == ITYPE_LITERAL)
 | 
|---|
| 1827 |     opcode_operand_count = 1;
 | 
|---|
| 1828 |   else
 | 
|---|
| 1829 |     opcode_operand_count = xtensa_num_operands (isa, opcode);
 | 
|---|
| 1830 | 
 | 
|---|
| 1831 |   memset (tok, 0, sizeof (*tok) * MAX_INSN_ARGS);
 | 
|---|
| 1832 | 
 | 
|---|
| 1833 |   /* Save and restore input_line_pointer around this function.  */
 | 
|---|
| 1834 |   old_input_line_pointer = input_line_pointer; 
 | 
|---|
| 1835 | 
 | 
|---|
| 1836 |   for (n = 0; n < num_args; n++)
 | 
|---|
| 1837 |     { 
 | 
|---|
| 1838 |       input_line_pointer = arg_strings[n];
 | 
|---|
| 1839 | 
 | 
|---|
| 1840 |       if (actual_operand_count >= opcode_operand_count)
 | 
|---|
| 1841 |         { 
 | 
|---|
| 1842 |           as_warn (_("too many arguments")); 
 | 
|---|
| 1843 |           goto err;
 | 
|---|
| 1844 |         } 
 | 
|---|
| 1845 |       assert (actual_operand_count < MAX_INSN_ARGS);
 | 
|---|
| 1846 | 
 | 
|---|
| 1847 |       opnd = xtensa_get_operand (isa, opcode, actual_operand_count); 
 | 
|---|
| 1848 |       expression_maybe_register (opnd, tok);
 | 
|---|
| 1849 | 
 | 
|---|
| 1850 |       if (tok->X_op == O_illegal || tok->X_op == O_absent) 
 | 
|---|
| 1851 |         goto err; 
 | 
|---|
| 1852 |       actual_operand_count++;
 | 
|---|
| 1853 |       tok++; 
 | 
|---|
| 1854 |     } 
 | 
|---|
| 1855 | 
 | 
|---|
| 1856 |   insn->ntok = tok - insn->tok;
 | 
|---|
| 1857 |   had_error = FALSE; 
 | 
|---|
| 1858 | 
 | 
|---|
| 1859 |  err:
 | 
|---|
| 1860 |   input_line_pointer = old_input_line_pointer; 
 | 
|---|
| 1861 |   return had_error;
 | 
|---|
| 1862 | }
 | 
|---|
| 1863 | 
 | 
|---|
| 1864 | 
 | 
|---|
| 1865 | static void
 | 
|---|
| 1866 | xg_reverse_shift_count (cnt_argp)
 | 
|---|
| 1867 |      char **cnt_argp;
 | 
|---|
| 1868 | {
 | 
|---|
| 1869 |   char *cnt_arg, *new_arg;
 | 
|---|
| 1870 |   cnt_arg = *cnt_argp;
 | 
|---|
| 1871 | 
 | 
|---|
| 1872 |   /* replace the argument with "31-(argument)" */
 | 
|---|
| 1873 |   new_arg = (char *) xmalloc (strlen (cnt_arg) + 6);
 | 
|---|
| 1874 |   sprintf (new_arg, "31-(%s)", cnt_arg);
 | 
|---|
| 1875 | 
 | 
|---|
| 1876 |   free (cnt_arg);
 | 
|---|
| 1877 |   *cnt_argp = new_arg;
 | 
|---|
| 1878 | }
 | 
|---|
| 1879 | 
 | 
|---|
| 1880 | 
 | 
|---|
| 1881 | /* If "arg" is a constant expression, return non-zero with the value
 | 
|---|
| 1882 |    in *valp.  */
 | 
|---|
| 1883 | 
 | 
|---|
| 1884 | static int
 | 
|---|
| 1885 | xg_arg_is_constant (arg, valp)
 | 
|---|
| 1886 |      char *arg;
 | 
|---|
| 1887 |      offsetT *valp;
 | 
|---|
| 1888 | {
 | 
|---|
| 1889 |   expressionS exp;
 | 
|---|
| 1890 |   char *save_ptr = input_line_pointer;
 | 
|---|
| 1891 | 
 | 
|---|
| 1892 |   input_line_pointer = arg;
 | 
|---|
| 1893 |   expression (&exp);
 | 
|---|
| 1894 |   input_line_pointer = save_ptr;
 | 
|---|
| 1895 | 
 | 
|---|
| 1896 |   if (exp.X_op == O_constant)
 | 
|---|
| 1897 |     {
 | 
|---|
| 1898 |       *valp = exp.X_add_number;
 | 
|---|
| 1899 |       return 1;
 | 
|---|
| 1900 |     }
 | 
|---|
| 1901 | 
 | 
|---|
| 1902 |   return 0;
 | 
|---|
| 1903 | }
 | 
|---|
| 1904 | 
 | 
|---|
| 1905 | 
 | 
|---|
| 1906 | static void
 | 
|---|
| 1907 | xg_replace_opname (popname, newop)
 | 
|---|
| 1908 |      char **popname;
 | 
|---|
| 1909 |      char *newop;
 | 
|---|
| 1910 | {
 | 
|---|
| 1911 |   free (*popname);
 | 
|---|
| 1912 |   *popname = (char *) xmalloc (strlen (newop) + 1);
 | 
|---|
| 1913 |   strcpy (*popname, newop);
 | 
|---|
| 1914 | }
 | 
|---|
| 1915 | 
 | 
|---|
| 1916 | 
 | 
|---|
| 1917 | static int
 | 
|---|
| 1918 | xg_check_num_args (pnum_args, expected_num, opname, arg_strings)
 | 
|---|
| 1919 |      int *pnum_args;
 | 
|---|
| 1920 |      int expected_num; 
 | 
|---|
| 1921 |      char *opname;
 | 
|---|
| 1922 |      char **arg_strings;
 | 
|---|
| 1923 | {
 | 
|---|
| 1924 |   int num_args = *pnum_args;
 | 
|---|
| 1925 | 
 | 
|---|
| 1926 |   if (num_args < expected_num) 
 | 
|---|
| 1927 |     {
 | 
|---|
| 1928 |       as_bad (_("not enough operands (%d) for '%s'; expected %d"),
 | 
|---|
| 1929 |               num_args, opname, expected_num);
 | 
|---|
| 1930 |       return -1;
 | 
|---|
| 1931 |     }
 | 
|---|
| 1932 | 
 | 
|---|
| 1933 |   if (num_args > expected_num)
 | 
|---|
| 1934 |     {
 | 
|---|
| 1935 |       as_warn (_("too many operands (%d) for '%s'; expected %d"),
 | 
|---|
| 1936 |                num_args, opname, expected_num);
 | 
|---|
| 1937 |       while (num_args-- > expected_num)
 | 
|---|
| 1938 |         {
 | 
|---|
| 1939 |           free (arg_strings[num_args]);
 | 
|---|
| 1940 |           arg_strings[num_args] = 0;
 | 
|---|
| 1941 |         }
 | 
|---|
| 1942 |       *pnum_args = expected_num;
 | 
|---|
| 1943 |       return -1;
 | 
|---|
| 1944 |     }
 | 
|---|
| 1945 | 
 | 
|---|
| 1946 |   return 0;
 | 
|---|
| 1947 | }
 | 
|---|
| 1948 | 
 | 
|---|
| 1949 | 
 | 
|---|
| 1950 | static int
 | 
|---|
| 1951 | xg_translate_sysreg_op (popname, pnum_args, arg_strings)
 | 
|---|
| 1952 |      char **popname;
 | 
|---|
| 1953 |      int *pnum_args;
 | 
|---|
| 1954 |      char **arg_strings;
 | 
|---|
| 1955 | {
 | 
|---|
| 1956 |   char *opname, *new_opname;
 | 
|---|
| 1957 |   offsetT val;
 | 
|---|
| 1958 |   bfd_boolean has_underbar = FALSE;
 | 
|---|
| 1959 | 
 | 
|---|
| 1960 |   opname = *popname;
 | 
|---|
| 1961 |   if (*opname == '_')
 | 
|---|
| 1962 |     {
 | 
|---|
| 1963 |       has_underbar = TRUE;
 | 
|---|
| 1964 |       opname += 1;
 | 
|---|
| 1965 |     }
 | 
|---|
| 1966 | 
 | 
|---|
| 1967 |   /* Opname == [rw]ur... */
 | 
|---|
| 1968 | 
 | 
|---|
| 1969 |   if (opname[3] == '\0')
 | 
|---|
| 1970 |     {
 | 
|---|
| 1971 |       /* If the register is not specified as part of the opcode,
 | 
|---|
| 1972 |          then get it from the operand and move it to the opcode.  */
 | 
|---|
| 1973 | 
 | 
|---|
| 1974 |       if (xg_check_num_args (pnum_args, 2, opname, arg_strings))
 | 
|---|
| 1975 |         return -1;
 | 
|---|
| 1976 | 
 | 
|---|
| 1977 |       if (!xg_arg_is_constant (arg_strings[1], &val))
 | 
|---|
| 1978 |         {
 | 
|---|
| 1979 |           as_bad (_("register number for `%s' is not a constant"), opname);
 | 
|---|
| 1980 |           return -1;
 | 
|---|
| 1981 |         }
 | 
|---|
| 1982 |       if ((unsigned) val > 255)
 | 
|---|
| 1983 |         {
 | 
|---|
| 1984 |           as_bad (_("register number (%ld) for `%s' is out of range"),
 | 
|---|
| 1985 |                   val, opname);
 | 
|---|
| 1986 |           return -1;
 | 
|---|
| 1987 |         }
 | 
|---|
| 1988 | 
 | 
|---|
| 1989 |       /* Remove the last argument, which is now part of the opcode.  */
 | 
|---|
| 1990 |       free (arg_strings[1]);
 | 
|---|
| 1991 |       arg_strings[1] = 0;
 | 
|---|
| 1992 |       *pnum_args = 1;
 | 
|---|
| 1993 | 
 | 
|---|
| 1994 |       /* Translate the opcode.  */
 | 
|---|
| 1995 |       new_opname = (char *) xmalloc (8);
 | 
|---|
| 1996 |       sprintf (new_opname, "%s%cur%u", (has_underbar ? "_" : ""),
 | 
|---|
| 1997 |                opname[0], (unsigned) val);
 | 
|---|
| 1998 |       free (*popname);
 | 
|---|
| 1999 |       *popname = new_opname;
 | 
|---|
| 2000 |     }
 | 
|---|
| 2001 | 
 | 
|---|
| 2002 |   return 0;
 | 
|---|
| 2003 | }
 | 
|---|
| 2004 | 
 | 
|---|
| 2005 | 
 | 
|---|
| 2006 | /* If the instruction is an idiom (i.e., a built-in macro), translate it.
 | 
|---|
| 2007 |    Returns non-zero if an error was found.  */
 | 
|---|
| 2008 | 
 | 
|---|
| 2009 | static int
 | 
|---|
| 2010 | xg_translate_idioms (popname, pnum_args, arg_strings)
 | 
|---|
| 2011 |      char **popname;
 | 
|---|
| 2012 |      int *pnum_args;
 | 
|---|
| 2013 |      char **arg_strings;
 | 
|---|
| 2014 | {
 | 
|---|
| 2015 |   char *opname = *popname;
 | 
|---|
| 2016 |   bfd_boolean has_underbar = FALSE;
 | 
|---|
| 2017 | 
 | 
|---|
| 2018 |   if (*opname == '_')
 | 
|---|
| 2019 |     {
 | 
|---|
| 2020 |       has_underbar = TRUE;
 | 
|---|
| 2021 |       opname += 1;
 | 
|---|
| 2022 |     }
 | 
|---|
| 2023 | 
 | 
|---|
| 2024 |   if (strcmp (opname, "mov") == 0)
 | 
|---|
| 2025 |     {
 | 
|---|
| 2026 |       if (!has_underbar && code_density_available ())
 | 
|---|
| 2027 |         xg_replace_opname (popname, "mov.n");
 | 
|---|
| 2028 |       else
 | 
|---|
| 2029 |         {
 | 
|---|
| 2030 |           if (xg_check_num_args (pnum_args, 2, opname, arg_strings))
 | 
|---|
| 2031 |             return -1;
 | 
|---|
| 2032 |           xg_replace_opname (popname, (has_underbar ? "_or" : "or"));
 | 
|---|
| 2033 |           arg_strings[2] = (char *) xmalloc (strlen (arg_strings[1]) + 1);
 | 
|---|
| 2034 |           strcpy (arg_strings[2], arg_strings[1]);
 | 
|---|
| 2035 |           *pnum_args = 3;
 | 
|---|
| 2036 |         }
 | 
|---|
| 2037 |       return 0;
 | 
|---|
| 2038 |     }
 | 
|---|
| 2039 | 
 | 
|---|
| 2040 |   if (strcmp (opname, "bbsi.l") == 0)
 | 
|---|
| 2041 |     {
 | 
|---|
| 2042 |       if (xg_check_num_args (pnum_args, 3, opname, arg_strings))
 | 
|---|
| 2043 |         return -1;
 | 
|---|
| 2044 |       xg_replace_opname (popname, (has_underbar ? "_bbsi" : "bbsi"));
 | 
|---|
| 2045 |       if (target_big_endian)
 | 
|---|
| 2046 |         xg_reverse_shift_count (&arg_strings[1]);
 | 
|---|
| 2047 |       return 0;
 | 
|---|
| 2048 |     }
 | 
|---|
| 2049 | 
 | 
|---|
| 2050 |   if (strcmp (opname, "bbci.l") == 0)
 | 
|---|
| 2051 |     {
 | 
|---|
| 2052 |       if (xg_check_num_args (pnum_args, 3, opname, arg_strings))
 | 
|---|
| 2053 |         return -1;
 | 
|---|
| 2054 |       xg_replace_opname (popname, (has_underbar ? "_bbci" : "bbci"));
 | 
|---|
| 2055 |       if (target_big_endian)
 | 
|---|
| 2056 |         xg_reverse_shift_count (&arg_strings[1]);
 | 
|---|
| 2057 |       return 0;
 | 
|---|
| 2058 |     }
 | 
|---|
| 2059 | 
 | 
|---|
| 2060 |   if (strcmp (opname, "nop") == 0)
 | 
|---|
| 2061 |     {
 | 
|---|
| 2062 |       if (!has_underbar && code_density_available ())
 | 
|---|
| 2063 |         xg_replace_opname (popname, "nop.n");
 | 
|---|
| 2064 |       else
 | 
|---|
| 2065 |         {
 | 
|---|
| 2066 |           if (xg_check_num_args (pnum_args, 0, opname, arg_strings))
 | 
|---|
| 2067 |             return -1;
 | 
|---|
| 2068 |           xg_replace_opname (popname, (has_underbar ? "_or" : "or"));
 | 
|---|
| 2069 |           arg_strings[0] = (char *) xmalloc (3);
 | 
|---|
| 2070 |           arg_strings[1] = (char *) xmalloc (3);
 | 
|---|
| 2071 |           arg_strings[2] = (char *) xmalloc (3);
 | 
|---|
| 2072 |           strcpy (arg_strings[0], "a1");
 | 
|---|
| 2073 |           strcpy (arg_strings[1], "a1");
 | 
|---|
| 2074 |           strcpy (arg_strings[2], "a1");
 | 
|---|
| 2075 |           *pnum_args = 3;
 | 
|---|
| 2076 |         }
 | 
|---|
| 2077 |       return 0;
 | 
|---|
| 2078 |     }
 | 
|---|
| 2079 | 
 | 
|---|
| 2080 |   if ((opname[0] == 'r' || opname[0] == 'w')
 | 
|---|
| 2081 |       && opname[1] == 'u'
 | 
|---|
| 2082 |       && opname[2] == 'r')
 | 
|---|
| 2083 |     return xg_translate_sysreg_op (popname, pnum_args, arg_strings);
 | 
|---|
| 2084 | 
 | 
|---|
| 2085 | 
 | 
|---|
| 2086 |   /* WIDENING DENSITY OPCODES
 | 
|---|
| 2087 | 
 | 
|---|
| 2088 |      questionable relaxations (widening) from old "tai" idioms:
 | 
|---|
| 2089 | 
 | 
|---|
| 2090 |        ADD.N --> ADD
 | 
|---|
| 2091 |        BEQZ.N --> BEQZ
 | 
|---|
| 2092 |        RET.N --> RET
 | 
|---|
| 2093 |        RETW.N --> RETW
 | 
|---|
| 2094 |        MOVI.N --> MOVI
 | 
|---|
| 2095 |        MOV.N --> MOV
 | 
|---|
| 2096 |        NOP.N --> NOP
 | 
|---|
| 2097 | 
 | 
|---|
| 2098 |      Note: this incomplete list was imported to match the "tai"
 | 
|---|
| 2099 |      behavior; other density opcodes are not handled.
 | 
|---|
| 2100 | 
 | 
|---|
| 2101 |      The xtensa-relax code may know how to do these but it doesn't do
 | 
|---|
| 2102 |      anything when these density opcodes appear inside a no-density
 | 
|---|
| 2103 |      region.  Somehow GAS should either print an error when that happens
 | 
|---|
| 2104 |      or do the widening.  The old "tai" behavior was to do the widening.
 | 
|---|
| 2105 |      For now, I'll make it widen but print a warning.
 | 
|---|
| 2106 | 
 | 
|---|
| 2107 |      FIXME: GAS needs to detect density opcodes inside no-density
 | 
|---|
| 2108 |      regions and treat them as errors.  This code should be removed
 | 
|---|
| 2109 |      when that is done.  */
 | 
|---|
| 2110 | 
 | 
|---|
| 2111 |   if (use_generics ()
 | 
|---|
| 2112 |       && !has_underbar
 | 
|---|
| 2113 |       && density_supported
 | 
|---|
| 2114 |       && !code_density_available ())
 | 
|---|
| 2115 |     {
 | 
|---|
| 2116 |       if (strcmp (opname, "add.n") == 0)
 | 
|---|
| 2117 |         xg_replace_opname (popname, "add");
 | 
|---|
| 2118 | 
 | 
|---|
| 2119 |       else if (strcmp (opname, "beqz.n") == 0)
 | 
|---|
| 2120 |         xg_replace_opname (popname, "beqz");
 | 
|---|
| 2121 | 
 | 
|---|
| 2122 |       else if (strcmp (opname, "ret.n") == 0)
 | 
|---|
| 2123 |         xg_replace_opname (popname, "ret");
 | 
|---|
| 2124 | 
 | 
|---|
| 2125 |       else if (strcmp (opname, "retw.n") == 0)
 | 
|---|
| 2126 |         xg_replace_opname (popname, "retw");
 | 
|---|
| 2127 | 
 | 
|---|
| 2128 |       else if (strcmp (opname, "movi.n") == 0)
 | 
|---|
| 2129 |         xg_replace_opname (popname, "movi");
 | 
|---|
| 2130 | 
 | 
|---|
| 2131 |       else if (strcmp (opname, "mov.n") == 0)
 | 
|---|
| 2132 |         {
 | 
|---|
| 2133 |           if (xg_check_num_args (pnum_args, 2, opname, arg_strings))
 | 
|---|
| 2134 |             return -1;
 | 
|---|
| 2135 |           xg_replace_opname (popname, "or");
 | 
|---|
| 2136 |           arg_strings[2] = (char *) xmalloc (strlen (arg_strings[1]) + 1);
 | 
|---|
| 2137 |           strcpy (arg_strings[2], arg_strings[1]);
 | 
|---|
| 2138 |           *pnum_args = 3;
 | 
|---|
| 2139 |         }
 | 
|---|
| 2140 | 
 | 
|---|
| 2141 |       else if (strcmp (opname, "nop.n") == 0)
 | 
|---|
| 2142 |         {
 | 
|---|
| 2143 |           if (xg_check_num_args (pnum_args, 0, opname, arg_strings))
 | 
|---|
| 2144 |             return -1;
 | 
|---|
| 2145 |           xg_replace_opname (popname, "or");
 | 
|---|
| 2146 |           arg_strings[0] = (char *) xmalloc (3);
 | 
|---|
| 2147 |           arg_strings[1] = (char *) xmalloc (3);
 | 
|---|
| 2148 |           arg_strings[2] = (char *) xmalloc (3);
 | 
|---|
| 2149 |           strcpy (arg_strings[0], "a1");
 | 
|---|
| 2150 |           strcpy (arg_strings[1], "a1");
 | 
|---|
| 2151 |           strcpy (arg_strings[2], "a1");
 | 
|---|
| 2152 |           *pnum_args = 3;
 | 
|---|
| 2153 |         }
 | 
|---|
| 2154 |     }
 | 
|---|
| 2155 | 
 | 
|---|
| 2156 |   return 0;
 | 
|---|
| 2157 | }
 | 
|---|
| 2158 | 
 | 
|---|
| 2159 |  | 
|---|
| 2160 | 
 | 
|---|
| 2161 | /* Functions for dealing with the Xtensa ISA.  */
 | 
|---|
| 2162 | 
 | 
|---|
| 2163 | /* Return true if the given operand is an immed or target instruction,
 | 
|---|
| 2164 |    i.e., has a reloc associated with it.  Currently, this is only true
 | 
|---|
| 2165 |    if the operand kind is "i, "l" or "L".  */
 | 
|---|
| 2166 | 
 | 
|---|
| 2167 | static bfd_boolean
 | 
|---|
| 2168 | operand_is_immed (opnd)
 | 
|---|
| 2169 |      xtensa_operand opnd;
 | 
|---|
| 2170 | {
 | 
|---|
| 2171 |   const char *opkind = xtensa_operand_kind (opnd);
 | 
|---|
| 2172 |   if (opkind[0] == '\0' || opkind[1] != '\0')
 | 
|---|
| 2173 |     return FALSE;
 | 
|---|
| 2174 |   switch (opkind[0])
 | 
|---|
| 2175 |     {
 | 
|---|
| 2176 |     case 'i':
 | 
|---|
| 2177 |     case 'l':
 | 
|---|
| 2178 |     case 'L':
 | 
|---|
| 2179 |       return TRUE;
 | 
|---|
| 2180 |     }
 | 
|---|
| 2181 |   return FALSE;
 | 
|---|
| 2182 | }
 | 
|---|
| 2183 | 
 | 
|---|
| 2184 | 
 | 
|---|
| 2185 | /* Return true if the given operand is a pc-relative label.  This is
 | 
|---|
| 2186 |    true for "l", "L", and "r" operand kinds.  */
 | 
|---|
| 2187 | 
 | 
|---|
| 2188 | bfd_boolean
 | 
|---|
| 2189 | operand_is_pcrel_label (opnd)
 | 
|---|
| 2190 |      xtensa_operand opnd;
 | 
|---|
| 2191 | {
 | 
|---|
| 2192 |   const char *opkind = xtensa_operand_kind (opnd);
 | 
|---|
| 2193 |   if (opkind[0] == '\0' || opkind[1] != '\0')
 | 
|---|
| 2194 |     return FALSE;
 | 
|---|
| 2195 |   switch (opkind[0])
 | 
|---|
| 2196 |     {
 | 
|---|
| 2197 |     case 'r':
 | 
|---|
| 2198 |     case 'l':
 | 
|---|
| 2199 |     case 'L':
 | 
|---|
| 2200 |       return TRUE;
 | 
|---|
| 2201 |     }
 | 
|---|
| 2202 |   return FALSE;
 | 
|---|
| 2203 | }
 | 
|---|
| 2204 | 
 | 
|---|
| 2205 | 
 | 
|---|
| 2206 | /* Currently the assembler only allows us to use a single target per
 | 
|---|
| 2207 |    fragment.  Because of this, only one operand for a given
 | 
|---|
| 2208 |    instruction may be symbolic.  If there is an operand of kind "lrL",
 | 
|---|
| 2209 |    the last one is chosen.  Otherwise, the result is the number of the
 | 
|---|
| 2210 |    last operand of type "i", and if there are none of those, we fail
 | 
|---|
| 2211 |    and return -1.  */
 | 
|---|
| 2212 | 
 | 
|---|
| 2213 | int
 | 
|---|
| 2214 | get_relaxable_immed (opcode)
 | 
|---|
| 2215 |      xtensa_opcode opcode;
 | 
|---|
| 2216 | {
 | 
|---|
| 2217 |   int last_immed = -1;
 | 
|---|
| 2218 |   int noperands, opi;
 | 
|---|
| 2219 |   xtensa_operand operand;
 | 
|---|
| 2220 | 
 | 
|---|
| 2221 |   if (opcode == XTENSA_UNDEFINED)
 | 
|---|
| 2222 |     return -1;
 | 
|---|
| 2223 | 
 | 
|---|
| 2224 |   noperands = xtensa_num_operands (xtensa_default_isa, opcode);
 | 
|---|
| 2225 |   for (opi = noperands - 1; opi >= 0; opi--)
 | 
|---|
| 2226 |     {
 | 
|---|
| 2227 |       operand = xtensa_get_operand (xtensa_default_isa, opcode, opi);
 | 
|---|
| 2228 |       if (operand_is_pcrel_label (operand))
 | 
|---|
| 2229 |         return opi;
 | 
|---|
| 2230 |       if (last_immed == -1 && operand_is_immed (operand))
 | 
|---|
| 2231 |         last_immed = opi;
 | 
|---|
| 2232 |     }
 | 
|---|
| 2233 |   return last_immed;
 | 
|---|
| 2234 | }
 | 
|---|
| 2235 | 
 | 
|---|
| 2236 | 
 | 
|---|
| 2237 | xtensa_opcode
 | 
|---|
| 2238 | get_opcode_from_buf (buf)
 | 
|---|
| 2239 |      const char *buf;
 | 
|---|
| 2240 | {
 | 
|---|
| 2241 |   static xtensa_insnbuf insnbuf = NULL;
 | 
|---|
| 2242 |   xtensa_opcode opcode;
 | 
|---|
| 2243 |   xtensa_isa isa = xtensa_default_isa;
 | 
|---|
| 2244 |   if (!insnbuf)
 | 
|---|
| 2245 |     insnbuf = xtensa_insnbuf_alloc (isa);
 | 
|---|
| 2246 | 
 | 
|---|
| 2247 |   xtensa_insnbuf_from_chars (isa, insnbuf, buf);
 | 
|---|
| 2248 |   opcode = xtensa_decode_insn (isa, insnbuf);
 | 
|---|
| 2249 |   return opcode;
 | 
|---|
| 2250 | }
 | 
|---|
| 2251 | 
 | 
|---|
| 2252 | 
 | 
|---|
| 2253 | static bfd_boolean
 | 
|---|
| 2254 | is_direct_call_opcode (opcode)
 | 
|---|
| 2255 |      xtensa_opcode opcode;
 | 
|---|
| 2256 | {
 | 
|---|
| 2257 |   if (opcode == XTENSA_UNDEFINED)
 | 
|---|
| 2258 |     return FALSE;
 | 
|---|
| 2259 | 
 | 
|---|
| 2260 |   return (opcode == xtensa_call0_opcode
 | 
|---|
| 2261 |           || opcode == xtensa_call4_opcode
 | 
|---|
| 2262 |           || opcode == xtensa_call8_opcode
 | 
|---|
| 2263 |           || opcode == xtensa_call12_opcode);
 | 
|---|
| 2264 | }
 | 
|---|
| 2265 | 
 | 
|---|
| 2266 | 
 | 
|---|
| 2267 | static bfd_boolean
 | 
|---|
| 2268 | is_call_opcode (opcode)
 | 
|---|
| 2269 |      xtensa_opcode opcode;
 | 
|---|
| 2270 | {
 | 
|---|
| 2271 |   if (is_direct_call_opcode (opcode))
 | 
|---|
| 2272 |     return TRUE;
 | 
|---|
| 2273 | 
 | 
|---|
| 2274 |   if (opcode == XTENSA_UNDEFINED)
 | 
|---|
| 2275 |     return FALSE;
 | 
|---|
| 2276 | 
 | 
|---|
| 2277 |   return (opcode == xtensa_callx0_opcode
 | 
|---|
| 2278 |           || opcode == xtensa_callx4_opcode
 | 
|---|
| 2279 |           || opcode == xtensa_callx8_opcode
 | 
|---|
| 2280 |           || opcode == xtensa_callx12_opcode);
 | 
|---|
| 2281 | }
 | 
|---|
| 2282 | 
 | 
|---|
| 2283 | 
 | 
|---|
| 2284 | /* Return true if the opcode is an entry opcode.  This is used because
 | 
|---|
| 2285 |    "entry" adds an implicit ".align 4" and also the entry instruction
 | 
|---|
| 2286 |    has an extra check for an operand value.  */
 | 
|---|
| 2287 | 
 | 
|---|
| 2288 | static bfd_boolean
 | 
|---|
| 2289 | is_entry_opcode (opcode)
 | 
|---|
| 2290 |      xtensa_opcode opcode;
 | 
|---|
| 2291 | {
 | 
|---|
| 2292 |   if (opcode == XTENSA_UNDEFINED)
 | 
|---|
| 2293 |     return FALSE;
 | 
|---|
| 2294 | 
 | 
|---|
| 2295 |   return (opcode == xtensa_entry_opcode);
 | 
|---|
| 2296 | }
 | 
|---|
| 2297 | 
 | 
|---|
| 2298 | 
 | 
|---|
| 2299 | /* Return true if it is one of the loop opcodes.  Loops are special
 | 
|---|
| 2300 |    because they need automatic alignment and they have a relaxation so
 | 
|---|
| 2301 |    complex that we hard-coded it.  */
 | 
|---|
| 2302 | 
 | 
|---|
| 2303 | static bfd_boolean
 | 
|---|
| 2304 | is_loop_opcode (opcode)
 | 
|---|
| 2305 |      xtensa_opcode opcode;
 | 
|---|
| 2306 | {
 | 
|---|
| 2307 |   if (opcode == XTENSA_UNDEFINED)
 | 
|---|
| 2308 |     return FALSE;
 | 
|---|
| 2309 | 
 | 
|---|
| 2310 |   return (opcode == xtensa_loop_opcode
 | 
|---|
| 2311 |           || opcode == xtensa_loopnez_opcode
 | 
|---|
| 2312 |           || opcode == xtensa_loopgtz_opcode);
 | 
|---|
| 2313 | }
 | 
|---|
| 2314 | 
 | 
|---|
| 2315 | 
 | 
|---|
| 2316 | static bfd_boolean
 | 
|---|
| 2317 | is_the_loop_opcode (opcode)
 | 
|---|
| 2318 |      xtensa_opcode opcode;
 | 
|---|
| 2319 | {
 | 
|---|
| 2320 |   if (opcode == XTENSA_UNDEFINED)
 | 
|---|
| 2321 |     return FALSE;
 | 
|---|
| 2322 | 
 | 
|---|
| 2323 |   return (opcode == xtensa_loop_opcode);
 | 
|---|
| 2324 | }
 | 
|---|
| 2325 | 
 | 
|---|
| 2326 | 
 | 
|---|
| 2327 | static bfd_boolean
 | 
|---|
| 2328 | is_jx_opcode (opcode)
 | 
|---|
| 2329 |      xtensa_opcode opcode;
 | 
|---|
| 2330 | {
 | 
|---|
| 2331 |   if (opcode == XTENSA_UNDEFINED)
 | 
|---|
| 2332 |     return FALSE;
 | 
|---|
| 2333 | 
 | 
|---|
| 2334 |   return (opcode == xtensa_jx_opcode);
 | 
|---|
| 2335 | }
 | 
|---|
| 2336 | 
 | 
|---|
| 2337 | 
 | 
|---|
| 2338 | /* Return true if the opcode is a retw or retw.n.
 | 
|---|
| 2339 |    Needed to add nops to avoid a hardware interlock issue.  */
 | 
|---|
| 2340 | 
 | 
|---|
| 2341 | static bfd_boolean
 | 
|---|
| 2342 | is_windowed_return_opcode (opcode)
 | 
|---|
| 2343 |      xtensa_opcode opcode;
 | 
|---|
| 2344 | {
 | 
|---|
| 2345 |   if (opcode == XTENSA_UNDEFINED)
 | 
|---|
| 2346 |     return FALSE;
 | 
|---|
| 2347 | 
 | 
|---|
| 2348 |   return (opcode == xtensa_retw_opcode || opcode == xtensa_retw_n_opcode);
 | 
|---|
| 2349 | }
 | 
|---|
| 2350 | 
 | 
|---|
| 2351 | 
 | 
|---|
| 2352 | /* Return true if the opcode type is "l" and the opcode is NOT a jump.  */
 | 
|---|
| 2353 | 
 | 
|---|
| 2354 | static bfd_boolean
 | 
|---|
| 2355 | is_conditional_branch_opcode (opcode)
 | 
|---|
| 2356 |      xtensa_opcode opcode;
 | 
|---|
| 2357 | {
 | 
|---|
| 2358 |   xtensa_isa isa = xtensa_default_isa;
 | 
|---|
| 2359 |   int num_ops, i;
 | 
|---|
| 2360 | 
 | 
|---|
| 2361 |   if (opcode == xtensa_j_opcode && opcode != XTENSA_UNDEFINED)
 | 
|---|
| 2362 |     return FALSE;
 | 
|---|
| 2363 | 
 | 
|---|
| 2364 |   num_ops = xtensa_num_operands (isa, opcode);
 | 
|---|
| 2365 |   for (i = 0; i < num_ops; i++)
 | 
|---|
| 2366 |     {
 | 
|---|
| 2367 |       xtensa_operand operand = xtensa_get_operand (isa, opcode, i);
 | 
|---|
| 2368 |       if (strcmp (xtensa_operand_kind (operand), "l") == 0)
 | 
|---|
| 2369 |         return TRUE;
 | 
|---|
| 2370 |     }
 | 
|---|
| 2371 |   return FALSE;
 | 
|---|
| 2372 | }
 | 
|---|
| 2373 | 
 | 
|---|
| 2374 | 
 | 
|---|
| 2375 | /* Return true if the given opcode is a conditional branch
 | 
|---|
| 2376 |    instruction, i.e., currently this is true if the instruction 
 | 
|---|
| 2377 |    is a jx or has an operand with 'l' type and is not a loop.  */
 | 
|---|
| 2378 | 
 | 
|---|
| 2379 | bfd_boolean
 | 
|---|
| 2380 | is_branch_or_jump_opcode (opcode)
 | 
|---|
| 2381 |      xtensa_opcode opcode;
 | 
|---|
| 2382 | {
 | 
|---|
| 2383 |   int opn, op_count;
 | 
|---|
| 2384 | 
 | 
|---|
| 2385 |   if (opcode == XTENSA_UNDEFINED)
 | 
|---|
| 2386 |     return FALSE;
 | 
|---|
| 2387 | 
 | 
|---|
| 2388 |   if (is_loop_opcode (opcode))
 | 
|---|
| 2389 |     return FALSE;
 | 
|---|
| 2390 | 
 | 
|---|
| 2391 |   if (is_jx_opcode (opcode))
 | 
|---|
| 2392 |     return TRUE;
 | 
|---|
| 2393 | 
 | 
|---|
| 2394 |   op_count = xtensa_num_operands (xtensa_default_isa, opcode);
 | 
|---|
| 2395 |   for (opn = 0; opn < op_count; opn++)
 | 
|---|
| 2396 |     {
 | 
|---|
| 2397 |       xtensa_operand opnd =
 | 
|---|
| 2398 |         xtensa_get_operand (xtensa_default_isa, opcode, opn);
 | 
|---|
| 2399 |       const char *opkind = xtensa_operand_kind (opnd);
 | 
|---|
| 2400 |       if (opkind && opkind[0] == 'l' && opkind[1] == '\0')
 | 
|---|
| 2401 |         return TRUE;
 | 
|---|
| 2402 |     }
 | 
|---|
| 2403 |   return FALSE;
 | 
|---|
| 2404 | }
 | 
|---|
| 2405 | 
 | 
|---|
| 2406 | 
 | 
|---|
| 2407 | /* Convert from operand numbers to BFD relocation type code.
 | 
|---|
| 2408 |    Return BFD_RELOC_NONE on failure.  */
 | 
|---|
| 2409 | 
 | 
|---|
| 2410 | bfd_reloc_code_real_type
 | 
|---|
| 2411 | opnum_to_reloc (opnum)
 | 
|---|
| 2412 |      int opnum;
 | 
|---|
| 2413 | {
 | 
|---|
| 2414 |   switch (opnum)
 | 
|---|
| 2415 |     {
 | 
|---|
| 2416 |     case 0:
 | 
|---|
| 2417 |       return BFD_RELOC_XTENSA_OP0;
 | 
|---|
| 2418 |     case 1:
 | 
|---|
| 2419 |       return BFD_RELOC_XTENSA_OP1;
 | 
|---|
| 2420 |     case 2:
 | 
|---|
| 2421 |       return BFD_RELOC_XTENSA_OP2;
 | 
|---|
| 2422 |     default:
 | 
|---|
| 2423 |       break;
 | 
|---|
| 2424 |     }
 | 
|---|
| 2425 |   return BFD_RELOC_NONE;
 | 
|---|
| 2426 | }
 | 
|---|
| 2427 | 
 | 
|---|
| 2428 | 
 | 
|---|
| 2429 | /* Convert from BFD relocation type code to operand number.
 | 
|---|
| 2430 |    Return -1 on failure.  */
 | 
|---|
| 2431 | 
 | 
|---|
| 2432 | int
 | 
|---|
| 2433 | reloc_to_opnum (reloc)
 | 
|---|
| 2434 |      bfd_reloc_code_real_type reloc;
 | 
|---|
| 2435 | {
 | 
|---|
| 2436 |   switch (reloc)
 | 
|---|
| 2437 |     {
 | 
|---|
| 2438 |     case BFD_RELOC_XTENSA_OP0:
 | 
|---|
| 2439 |       return 0;
 | 
|---|
| 2440 |     case BFD_RELOC_XTENSA_OP1:
 | 
|---|
| 2441 |       return 1;
 | 
|---|
| 2442 |     case BFD_RELOC_XTENSA_OP2:
 | 
|---|
| 2443 |       return 2;
 | 
|---|
| 2444 |     default:
 | 
|---|
| 2445 |       break;
 | 
|---|
| 2446 |     }
 | 
|---|
| 2447 |   return -1;
 | 
|---|
| 2448 | }
 | 
|---|
| 2449 | 
 | 
|---|
| 2450 | 
 | 
|---|
| 2451 | static void
 | 
|---|
| 2452 | xtensa_insnbuf_set_operand (insnbuf, opcode, operand, value, file, line)
 | 
|---|
| 2453 |      xtensa_insnbuf insnbuf;
 | 
|---|
| 2454 |      xtensa_opcode opcode;
 | 
|---|
| 2455 |      xtensa_operand operand;
 | 
|---|
| 2456 |      int32 value;
 | 
|---|
| 2457 |      const char *file;
 | 
|---|
| 2458 |      unsigned int line;
 | 
|---|
| 2459 | {
 | 
|---|
| 2460 |   xtensa_encode_result encode_result;
 | 
|---|
| 2461 |   uint32 valbuf = value;
 | 
|---|
| 2462 | 
 | 
|---|
| 2463 |   encode_result = xtensa_operand_encode (operand, &valbuf);
 | 
|---|
| 2464 | 
 | 
|---|
| 2465 |   switch (encode_result)
 | 
|---|
| 2466 |     {
 | 
|---|
| 2467 |     case xtensa_encode_result_ok:
 | 
|---|
| 2468 |       break;
 | 
|---|
| 2469 |     case xtensa_encode_result_align:
 | 
|---|
| 2470 |       as_bad_where ((char *) file, line,
 | 
|---|
| 2471 |                     _("operand %d not properly aligned for '%s'"),
 | 
|---|
| 2472 |                     value, xtensa_opcode_name (xtensa_default_isa, opcode));
 | 
|---|
| 2473 |       break;
 | 
|---|
| 2474 |     case xtensa_encode_result_not_in_table:
 | 
|---|
| 2475 |       as_bad_where ((char *) file, line,
 | 
|---|
| 2476 |                     _("operand %d not in immediate table for '%s'"),
 | 
|---|
| 2477 |                     value, xtensa_opcode_name (xtensa_default_isa, opcode));
 | 
|---|
| 2478 |       break;
 | 
|---|
| 2479 |     case xtensa_encode_result_too_high:
 | 
|---|
| 2480 |       as_bad_where ((char *) file, line,
 | 
|---|
| 2481 |                     _("operand %d too large for '%s'"), value,
 | 
|---|
| 2482 |                     xtensa_opcode_name (xtensa_default_isa, opcode));
 | 
|---|
| 2483 |       break;
 | 
|---|
| 2484 |     case xtensa_encode_result_too_low:
 | 
|---|
| 2485 |       as_bad_where ((char *) file, line,
 | 
|---|
| 2486 |                     _("operand %d too small for '%s'"), value,
 | 
|---|
| 2487 |                     xtensa_opcode_name (xtensa_default_isa, opcode));
 | 
|---|
| 2488 |       break;
 | 
|---|
| 2489 |     case xtensa_encode_result_not_ok:
 | 
|---|
| 2490 |       as_bad_where ((char *) file, line,
 | 
|---|
| 2491 |                     _("operand %d is invalid for '%s'"), value,
 | 
|---|
| 2492 |                     xtensa_opcode_name (xtensa_default_isa, opcode));
 | 
|---|
| 2493 |       break;
 | 
|---|
| 2494 |     default:
 | 
|---|
| 2495 |       abort ();
 | 
|---|
| 2496 |     }
 | 
|---|
| 2497 | 
 | 
|---|
| 2498 |   xtensa_operand_set_field (operand, insnbuf, valbuf);
 | 
|---|
| 2499 | }
 | 
|---|
| 2500 | 
 | 
|---|
| 2501 | 
 | 
|---|
| 2502 | static uint32
 | 
|---|
| 2503 | xtensa_insnbuf_get_operand (insnbuf, opcode, opnum)
 | 
|---|
| 2504 |      xtensa_insnbuf insnbuf;
 | 
|---|
| 2505 |      xtensa_opcode opcode;
 | 
|---|
| 2506 |      int opnum;
 | 
|---|
| 2507 | {
 | 
|---|
| 2508 |   xtensa_operand op = xtensa_get_operand (xtensa_default_isa, opcode, opnum);
 | 
|---|
| 2509 |   return xtensa_operand_decode (op, xtensa_operand_get_field (op, insnbuf));
 | 
|---|
| 2510 | }
 | 
|---|
| 2511 | 
 | 
|---|
| 2512 | 
 | 
|---|
| 2513 | static void
 | 
|---|
| 2514 | xtensa_insnbuf_set_immediate_field (opcode, insnbuf, value, file, line)
 | 
|---|
| 2515 |      xtensa_opcode opcode;
 | 
|---|
| 2516 |      xtensa_insnbuf insnbuf;
 | 
|---|
| 2517 |      int32 value;
 | 
|---|
| 2518 |      const char *file;
 | 
|---|
| 2519 |      unsigned int line;
 | 
|---|
| 2520 | {
 | 
|---|
| 2521 |   xtensa_isa isa = xtensa_default_isa;
 | 
|---|
| 2522 |   int last_opnd = xtensa_num_operands (isa, opcode) - 1;
 | 
|---|
| 2523 |   xtensa_operand operand = xtensa_get_operand (isa, opcode, last_opnd);
 | 
|---|
| 2524 |   xtensa_insnbuf_set_operand (insnbuf, opcode, operand, value, file, line);
 | 
|---|
| 2525 | }
 | 
|---|
| 2526 | 
 | 
|---|
| 2527 | 
 | 
|---|
| 2528 | static bfd_boolean
 | 
|---|
| 2529 | is_negatable_branch (insn)
 | 
|---|
| 2530 |      TInsn *insn;
 | 
|---|
| 2531 | {
 | 
|---|
| 2532 |   xtensa_isa isa = xtensa_default_isa;
 | 
|---|
| 2533 |   int i;
 | 
|---|
| 2534 |   int num_ops = xtensa_num_operands (isa, insn->opcode);
 | 
|---|
| 2535 | 
 | 
|---|
| 2536 |   for (i = 0; i < num_ops; i++)
 | 
|---|
| 2537 |     {
 | 
|---|
| 2538 |       xtensa_operand opnd = xtensa_get_operand (isa, insn->opcode, i);
 | 
|---|
| 2539 |       char *kind = xtensa_operand_kind (opnd);
 | 
|---|
| 2540 |       if (strlen (kind) == 1 && *kind == 'l')
 | 
|---|
| 2541 |         return TRUE;
 | 
|---|
| 2542 |     }
 | 
|---|
| 2543 |   return FALSE;
 | 
|---|
| 2544 | }
 | 
|---|
| 2545 | 
 | 
|---|
| 2546 |  | 
|---|
| 2547 | 
 | 
|---|
| 2548 | /* Lists for recording various properties of symbols.  */
 | 
|---|
| 2549 | 
 | 
|---|
| 2550 | typedef struct symbol_consS_struct
 | 
|---|
| 2551 | {
 | 
|---|
| 2552 |   symbolS *first;
 | 
|---|
| 2553 |   /* These are used for the target taken.  */
 | 
|---|
| 2554 |   int is_loop_target:1;
 | 
|---|
| 2555 |   int is_branch_target:1;
 | 
|---|
| 2556 |   int is_literal:1;
 | 
|---|
| 2557 |   int is_moved:1;
 | 
|---|
| 2558 |   struct symbol_consS_struct *rest;
 | 
|---|
| 2559 | } symbol_consS;
 | 
|---|
| 2560 | 
 | 
|---|
| 2561 | symbol_consS *defined_symbols = 0;
 | 
|---|
| 2562 | symbol_consS *branch_targets = 0;
 | 
|---|
| 2563 | 
 | 
|---|
| 2564 | 
 | 
|---|
| 2565 | static void
 | 
|---|
| 2566 | xtensa_define_label (sym)
 | 
|---|
| 2567 |      symbolS *sym;
 | 
|---|
| 2568 | {
 | 
|---|
| 2569 |   symbol_consS *cons = (symbol_consS *) xmalloc (sizeof (symbol_consS));
 | 
|---|
| 2570 | 
 | 
|---|
| 2571 |   cons->first = sym;
 | 
|---|
| 2572 |   cons->is_branch_target = 0;
 | 
|---|
| 2573 |   cons->is_loop_target = 0;
 | 
|---|
| 2574 |   cons->is_literal = generating_literals ? 1 : 0;
 | 
|---|
| 2575 |   cons->is_moved = 0;
 | 
|---|
| 2576 |   cons->rest = defined_symbols;
 | 
|---|
| 2577 |   defined_symbols = cons;
 | 
|---|
| 2578 | }
 | 
|---|
| 2579 | 
 | 
|---|
| 2580 | 
 | 
|---|
| 2581 | void
 | 
|---|
| 2582 | add_target_symbol (sym, is_loop)
 | 
|---|
| 2583 |      symbolS *sym;
 | 
|---|
| 2584 |      bfd_boolean is_loop;
 | 
|---|
| 2585 | {
 | 
|---|
| 2586 |   symbol_consS *cons, *sym_e;
 | 
|---|
| 2587 | 
 | 
|---|
| 2588 |   for (sym_e = branch_targets; sym_e; sym_e = sym_e->rest)
 | 
|---|
| 2589 |     {
 | 
|---|
| 2590 |       if (sym_e->first == sym)
 | 
|---|
| 2591 |         {
 | 
|---|
| 2592 |           if (is_loop)
 | 
|---|
| 2593 |             sym_e->is_loop_target = 1;
 | 
|---|
| 2594 |           else
 | 
|---|
| 2595 |             sym_e->is_branch_target = 1;
 | 
|---|
| 2596 |           return;
 | 
|---|
| 2597 |         }
 | 
|---|
| 2598 |     }
 | 
|---|
| 2599 | 
 | 
|---|
| 2600 |   cons = (symbol_consS *) xmalloc (sizeof (symbol_consS));
 | 
|---|
| 2601 |   cons->first = sym;
 | 
|---|
| 2602 |   cons->is_branch_target = (is_loop ? 0 : 1);
 | 
|---|
| 2603 |   cons->is_loop_target = (is_loop ? 1 : 0);
 | 
|---|
| 2604 |   cons->rest = branch_targets;
 | 
|---|
| 2605 |   branch_targets = cons;
 | 
|---|
| 2606 | }
 | 
|---|
| 2607 | 
 | 
|---|
| 2608 | 
 | 
|---|
| 2609 | /* Find the symbol at a given position.  (Note: the "loops_ok"
 | 
|---|
| 2610 |    argument is provided to allow ignoring labels that define loop
 | 
|---|
| 2611 |    ends.  This fixes a bug where the NOPs to align a loop opcode were
 | 
|---|
| 2612 |    included in a previous zero-cost loop:
 | 
|---|
| 2613 | 
 | 
|---|
| 2614 |    loop a0, loopend
 | 
|---|
| 2615 |      <loop1 body>
 | 
|---|
| 2616 |    loopend:
 | 
|---|
| 2617 | 
 | 
|---|
| 2618 |    loop a2, loopend2
 | 
|---|
| 2619 |      <loop2 body>
 | 
|---|
| 2620 |              
 | 
|---|
| 2621 |    would become:
 | 
|---|
| 2622 | 
 | 
|---|
| 2623 |    loop a0, loopend
 | 
|---|
| 2624 |      <loop1 body>
 | 
|---|
| 2625 |      nop.n <===== bad!
 | 
|---|
| 2626 |    loopend:
 | 
|---|
| 2627 | 
 | 
|---|
| 2628 |    loop a2, loopend2
 | 
|---|
| 2629 |      <loop2 body>
 | 
|---|
| 2630 | 
 | 
|---|
| 2631 |    This argument is used to prevent moving the NOP to before the
 | 
|---|
| 2632 |    loop-end label, which is what you want in this special case.)  */
 | 
|---|
| 2633 | 
 | 
|---|
| 2634 | static symbolS *
 | 
|---|
| 2635 | xtensa_find_label (fragP, offset, loops_ok)
 | 
|---|
| 2636 |      fragS *fragP;
 | 
|---|
| 2637 |      offsetT offset;
 | 
|---|
| 2638 |      bfd_boolean loops_ok;
 | 
|---|
| 2639 | {
 | 
|---|
| 2640 |   symbol_consS *consP;
 | 
|---|
| 2641 | 
 | 
|---|
| 2642 |   for (consP = defined_symbols; consP; consP = consP->rest)
 | 
|---|
| 2643 |     {
 | 
|---|
| 2644 |       symbolS *symP = consP->first;
 | 
|---|
| 2645 | 
 | 
|---|
| 2646 |       if (S_GET_SEGMENT (symP) == now_seg
 | 
|---|
| 2647 |           && symbol_get_frag (symP) == fragP
 | 
|---|
| 2648 |           && symbol_constant_p (symP)
 | 
|---|
| 2649 |           && S_GET_VALUE (symP) == fragP->fr_address + (unsigned) offset
 | 
|---|
| 2650 |           && (loops_ok || !is_loop_target_label (symP)))
 | 
|---|
| 2651 |         return symP;
 | 
|---|
| 2652 |     }
 | 
|---|
| 2653 |   return NULL;
 | 
|---|
| 2654 | }
 | 
|---|
| 2655 | 
 | 
|---|
| 2656 | 
 | 
|---|
| 2657 | static void
 | 
|---|
| 2658 | map_over_defined_symbols (fn)
 | 
|---|
| 2659 |      void (*fn) PARAMS ((symbolS *));
 | 
|---|
| 2660 | {
 | 
|---|
| 2661 |   symbol_consS *sym_cons;
 | 
|---|
| 2662 | 
 | 
|---|
| 2663 |   for (sym_cons = defined_symbols; sym_cons; sym_cons = sym_cons->rest)
 | 
|---|
| 2664 |     fn (sym_cons->first);
 | 
|---|
| 2665 | }
 | 
|---|
| 2666 | 
 | 
|---|
| 2667 | 
 | 
|---|
| 2668 | static bfd_boolean
 | 
|---|
| 2669 | is_loop_target_label (sym)
 | 
|---|
| 2670 |      symbolS *sym;
 | 
|---|
| 2671 | {
 | 
|---|
| 2672 |   symbol_consS *sym_e;
 | 
|---|
| 2673 | 
 | 
|---|
| 2674 |   for (sym_e = branch_targets; sym_e; sym_e = sym_e->rest)
 | 
|---|
| 2675 |     {
 | 
|---|
| 2676 |       if (sym_e->first == sym)
 | 
|---|
| 2677 |         return sym_e->is_loop_target;
 | 
|---|
| 2678 |     }
 | 
|---|
| 2679 |   return FALSE;
 | 
|---|
| 2680 | } 
 | 
|---|
| 2681 | 
 | 
|---|
| 2682 | 
 | 
|---|
| 2683 | /* Walk over all of the symbols that are branch target labels and
 | 
|---|
| 2684 |    loop target labels.  Mark the associated fragments for these with
 | 
|---|
| 2685 |    the appropriate flags.  */
 | 
|---|
| 2686 | 
 | 
|---|
| 2687 | static void
 | 
|---|
| 2688 | xtensa_mark_target_fragments ()
 | 
|---|
| 2689 | {
 | 
|---|
| 2690 |   symbol_consS *sym_e;
 | 
|---|
| 2691 | 
 | 
|---|
| 2692 |   for (sym_e = branch_targets; sym_e; sym_e = sym_e->rest)
 | 
|---|
| 2693 |     {
 | 
|---|
| 2694 |       symbolS *sym = sym_e->first;
 | 
|---|
| 2695 | 
 | 
|---|
| 2696 |       if (symbol_get_frag (sym)
 | 
|---|
| 2697 |           && symbol_constant_p (sym)
 | 
|---|
| 2698 |           && S_GET_VALUE (sym) == 0)
 | 
|---|
| 2699 |         {
 | 
|---|
| 2700 |           if (sym_e->is_branch_target)
 | 
|---|
| 2701 |             symbol_get_frag (sym)->tc_frag_data.is_branch_target = TRUE;
 | 
|---|
| 2702 |           if (sym_e->is_loop_target)
 | 
|---|
| 2703 |             symbol_get_frag (sym)->tc_frag_data.is_loop_target = TRUE;
 | 
|---|
| 2704 |         }
 | 
|---|
| 2705 |     }
 | 
|---|
| 2706 | }
 | 
|---|
| 2707 | 
 | 
|---|
| 2708 |  | 
|---|
| 2709 | 
 | 
|---|
| 2710 | /* Various Other Internal Functions.  */
 | 
|---|
| 2711 | 
 | 
|---|
| 2712 | static bfd_boolean
 | 
|---|
| 2713 | is_unique_insn_expansion (r)
 | 
|---|
| 2714 |      TransitionRule *r;
 | 
|---|
| 2715 | {
 | 
|---|
| 2716 |   if (!r->to_instr || r->to_instr->next != NULL)
 | 
|---|
| 2717 |     return FALSE;
 | 
|---|
| 2718 |   if (r->to_instr->typ != INSTR_INSTR)
 | 
|---|
| 2719 |     return FALSE;
 | 
|---|
| 2720 |   return TRUE;
 | 
|---|
| 2721 | }
 | 
|---|
| 2722 | 
 | 
|---|
| 2723 | 
 | 
|---|
| 2724 | static int
 | 
|---|
| 2725 | xg_get_insn_size (insn)
 | 
|---|
| 2726 |      TInsn *insn;
 | 
|---|
| 2727 | {
 | 
|---|
| 2728 |   assert (insn->insn_type == ITYPE_INSN);
 | 
|---|
| 2729 |   return xtensa_insn_length (xtensa_default_isa, insn->opcode);
 | 
|---|
| 2730 | }
 | 
|---|
| 2731 | 
 | 
|---|
| 2732 | 
 | 
|---|
| 2733 | static int
 | 
|---|
| 2734 | xg_get_build_instr_size (insn)
 | 
|---|
| 2735 |      BuildInstr *insn;
 | 
|---|
| 2736 | {
 | 
|---|
| 2737 |   assert (insn->typ == INSTR_INSTR);
 | 
|---|
| 2738 |   return xtensa_insn_length (xtensa_default_isa, insn->opcode);
 | 
|---|
| 2739 | }
 | 
|---|
| 2740 | 
 | 
|---|
| 2741 | 
 | 
|---|
| 2742 | bfd_boolean
 | 
|---|
| 2743 | xg_is_narrow_insn (insn)
 | 
|---|
| 2744 |      TInsn *insn;
 | 
|---|
| 2745 | {
 | 
|---|
| 2746 |   TransitionTable *table = xg_build_widen_table ();
 | 
|---|
| 2747 |   TransitionList *l;
 | 
|---|
| 2748 |   int num_match = 0;
 | 
|---|
| 2749 |   assert (insn->insn_type == ITYPE_INSN);
 | 
|---|
| 2750 |   assert (insn->opcode < table->num_opcodes);
 | 
|---|
| 2751 | 
 | 
|---|
| 2752 |   for (l = table->table[insn->opcode]; l != NULL; l = l->next)
 | 
|---|
| 2753 |     {
 | 
|---|
| 2754 |       TransitionRule *rule = l->rule;
 | 
|---|
| 2755 | 
 | 
|---|
| 2756 |       if (xg_instruction_matches_rule (insn, rule)
 | 
|---|
| 2757 |           && is_unique_insn_expansion (rule))
 | 
|---|
| 2758 |         {
 | 
|---|
| 2759 |           /* It only generates one instruction... */
 | 
|---|
| 2760 |           assert (insn->insn_type == ITYPE_INSN);
 | 
|---|
| 2761 |           /* ...and it is a larger instruction.  */
 | 
|---|
| 2762 |           if (xg_get_insn_size (insn)
 | 
|---|
| 2763 |               < xg_get_build_instr_size (rule->to_instr))
 | 
|---|
| 2764 |             {
 | 
|---|
| 2765 |               num_match++;
 | 
|---|
| 2766 |               if (num_match > 1)
 | 
|---|
| 2767 |                 return FALSE;
 | 
|---|
| 2768 |             }
 | 
|---|
| 2769 |         }
 | 
|---|
| 2770 |     }
 | 
|---|
| 2771 |   return (num_match == 1);
 | 
|---|
| 2772 | }
 | 
|---|
| 2773 | 
 | 
|---|
| 2774 | 
 | 
|---|
| 2775 | bfd_boolean
 | 
|---|
| 2776 | xg_is_single_relaxable_insn (insn)
 | 
|---|
| 2777 |      TInsn *insn;
 | 
|---|
| 2778 | {
 | 
|---|
| 2779 |   TransitionTable *table = xg_build_widen_table ();
 | 
|---|
| 2780 |   TransitionList *l;
 | 
|---|
| 2781 |   int num_match = 0;
 | 
|---|
| 2782 |   assert (insn->insn_type == ITYPE_INSN);
 | 
|---|
| 2783 |   assert (insn->opcode < table->num_opcodes);
 | 
|---|
| 2784 | 
 | 
|---|
| 2785 |   for (l = table->table[insn->opcode]; l != NULL; l = l->next)
 | 
|---|
| 2786 |     {
 | 
|---|
| 2787 |       TransitionRule *rule = l->rule;
 | 
|---|
| 2788 | 
 | 
|---|
| 2789 |       if (xg_instruction_matches_rule (insn, rule)
 | 
|---|
| 2790 |           && is_unique_insn_expansion (rule))
 | 
|---|
| 2791 |         {
 | 
|---|
| 2792 |           assert (insn->insn_type == ITYPE_INSN);
 | 
|---|
| 2793 |           /* ... and it is a larger instruction.  */
 | 
|---|
| 2794 |           if (xg_get_insn_size (insn)
 | 
|---|
| 2795 |               <= xg_get_build_instr_size (rule->to_instr))
 | 
|---|
| 2796 |             {
 | 
|---|
| 2797 |               num_match++;
 | 
|---|
| 2798 |               if (num_match > 1)
 | 
|---|
| 2799 |                 return FALSE;
 | 
|---|
| 2800 |             }
 | 
|---|
| 2801 |         }
 | 
|---|
| 2802 |     }
 | 
|---|
| 2803 |   return (num_match == 1);
 | 
|---|
| 2804 | }
 | 
|---|
| 2805 | 
 | 
|---|
| 2806 | 
 | 
|---|
| 2807 | /* Return the largest size instruction that this instruction can
 | 
|---|
| 2808 |    expand to.  Currently, in all cases, this is 3 bytes.  Of course we
 | 
|---|
| 2809 |    could just calculate this once and generate a table.  */
 | 
|---|
| 2810 | 
 | 
|---|
| 2811 | int
 | 
|---|
| 2812 | xg_get_max_narrow_insn_size (opcode)
 | 
|---|
| 2813 |      xtensa_opcode opcode;
 | 
|---|
| 2814 | {
 | 
|---|
| 2815 |   /* Go ahead and compute it, but it better be 3.  */
 | 
|---|
| 2816 |   TransitionTable *table = xg_build_widen_table ();
 | 
|---|
| 2817 |   TransitionList *l;
 | 
|---|
| 2818 |   int old_size = xtensa_insn_length (xtensa_default_isa, opcode);
 | 
|---|
| 2819 |   assert (opcode < table->num_opcodes);
 | 
|---|
| 2820 | 
 | 
|---|
| 2821 |   /* Actually we can do better. Check to see of Only one applies.  */
 | 
|---|
| 2822 |   for (l = table->table[opcode]; l != NULL; l = l->next)
 | 
|---|
| 2823 |     {
 | 
|---|
| 2824 |       TransitionRule *rule = l->rule;
 | 
|---|
| 2825 | 
 | 
|---|
| 2826 |       /* If it only generates one instruction.  */
 | 
|---|
| 2827 |       if (is_unique_insn_expansion (rule))
 | 
|---|
| 2828 |         {
 | 
|---|
| 2829 |           int new_size = xtensa_insn_length (xtensa_default_isa,
 | 
|---|
| 2830 |                                              rule->to_instr->opcode);
 | 
|---|
| 2831 |           if (new_size > old_size)
 | 
|---|
| 2832 |             {
 | 
|---|
| 2833 |               assert (new_size == 3);
 | 
|---|
| 2834 |               return 3;
 | 
|---|
| 2835 |             }
 | 
|---|
| 2836 |         }
 | 
|---|
| 2837 |     }
 | 
|---|
| 2838 |   return old_size;
 | 
|---|
| 2839 | }
 | 
|---|
| 2840 | 
 | 
|---|
| 2841 | 
 | 
|---|
| 2842 | /* Return the maximum number of bytes this opcode can expand to.  */
 | 
|---|
| 2843 | 
 | 
|---|
| 2844 | int
 | 
|---|
| 2845 | xg_get_max_insn_widen_size (opcode)
 | 
|---|
| 2846 |      xtensa_opcode opcode;
 | 
|---|
| 2847 | {
 | 
|---|
| 2848 |   TransitionTable *table = xg_build_widen_table ();
 | 
|---|
| 2849 |   TransitionList *l;
 | 
|---|
| 2850 |   int max_size = xtensa_insn_length (xtensa_default_isa, opcode);
 | 
|---|
| 2851 | 
 | 
|---|
| 2852 |   assert (opcode < table->num_opcodes);
 | 
|---|
| 2853 | 
 | 
|---|
| 2854 |   for (l = table->table[opcode]; l != NULL; l = l->next)
 | 
|---|
| 2855 |     {
 | 
|---|
| 2856 |       TransitionRule *rule = l->rule;
 | 
|---|
| 2857 |       BuildInstr *build_list;
 | 
|---|
| 2858 |       int this_size = 0;
 | 
|---|
| 2859 | 
 | 
|---|
| 2860 |       if (!rule)
 | 
|---|
| 2861 |         continue;
 | 
|---|
| 2862 |       build_list = rule->to_instr;
 | 
|---|
| 2863 |       if (is_unique_insn_expansion (rule))
 | 
|---|
| 2864 |         {
 | 
|---|
| 2865 |           assert (build_list->typ == INSTR_INSTR);
 | 
|---|
| 2866 |           this_size = xg_get_max_insn_widen_size (build_list->opcode);
 | 
|---|
| 2867 |         }
 | 
|---|
| 2868 |       else
 | 
|---|
| 2869 |         for (; build_list != NULL; build_list = build_list->next)
 | 
|---|
| 2870 |           {
 | 
|---|
| 2871 |             switch (build_list->typ)
 | 
|---|
| 2872 |               {
 | 
|---|
| 2873 |               case INSTR_INSTR:
 | 
|---|
| 2874 |                 this_size += xtensa_insn_length (xtensa_default_isa,
 | 
|---|
| 2875 |                                                  build_list->opcode);
 | 
|---|
| 2876 | 
 | 
|---|
| 2877 |                 break;
 | 
|---|
| 2878 |               case INSTR_LITERAL_DEF:
 | 
|---|
| 2879 |               case INSTR_LABEL_DEF:
 | 
|---|
| 2880 |               default:
 | 
|---|
| 2881 |                 break;
 | 
|---|
| 2882 |               }
 | 
|---|
| 2883 |           }
 | 
|---|
| 2884 |       if (this_size > max_size)
 | 
|---|
| 2885 |         max_size = this_size;
 | 
|---|
| 2886 |     }
 | 
|---|
| 2887 |   return max_size;
 | 
|---|
| 2888 | }
 | 
|---|
| 2889 | 
 | 
|---|
| 2890 | 
 | 
|---|
| 2891 | /* Return the maximum number of literal bytes this opcode can generate.  */
 | 
|---|
| 2892 | 
 | 
|---|
| 2893 | int
 | 
|---|
| 2894 | xg_get_max_insn_widen_literal_size (opcode)
 | 
|---|
| 2895 |      xtensa_opcode opcode;
 | 
|---|
| 2896 | {
 | 
|---|
| 2897 |   TransitionTable *table = xg_build_widen_table ();
 | 
|---|
| 2898 |   TransitionList *l;
 | 
|---|
| 2899 |   int max_size = 0;
 | 
|---|
| 2900 | 
 | 
|---|
| 2901 |   assert (opcode < table->num_opcodes);
 | 
|---|
| 2902 | 
 | 
|---|
| 2903 |   for (l = table->table[opcode]; l != NULL; l = l->next)
 | 
|---|
| 2904 |     {
 | 
|---|
| 2905 |       TransitionRule *rule = l->rule;
 | 
|---|
| 2906 |       BuildInstr *build_list;
 | 
|---|
| 2907 |       int this_size = 0;
 | 
|---|
| 2908 | 
 | 
|---|
| 2909 |       if (!rule)
 | 
|---|
| 2910 |         continue;
 | 
|---|
| 2911 |       build_list = rule->to_instr;
 | 
|---|
| 2912 |       if (is_unique_insn_expansion (rule))
 | 
|---|
| 2913 |         {
 | 
|---|
| 2914 |           assert (build_list->typ == INSTR_INSTR);
 | 
|---|
| 2915 |           this_size = xg_get_max_insn_widen_literal_size (build_list->opcode);
 | 
|---|
| 2916 |         }
 | 
|---|
| 2917 |       else
 | 
|---|
| 2918 |         for (; build_list != NULL; build_list = build_list->next)
 | 
|---|
| 2919 |           {
 | 
|---|
| 2920 |             switch (build_list->typ)
 | 
|---|
| 2921 |               {
 | 
|---|
| 2922 |               case INSTR_LITERAL_DEF:
 | 
|---|
| 2923 |                 /* hard coded 4-byte literal.  */
 | 
|---|
| 2924 |                 this_size += 4;
 | 
|---|
| 2925 |                 break;
 | 
|---|
| 2926 |               case INSTR_INSTR:
 | 
|---|
| 2927 |               case INSTR_LABEL_DEF:
 | 
|---|
| 2928 |               default:
 | 
|---|
| 2929 |                 break;
 | 
|---|
| 2930 |               }
 | 
|---|
| 2931 |           }
 | 
|---|
| 2932 |       if (this_size > max_size)
 | 
|---|
| 2933 |         max_size = this_size;
 | 
|---|
| 2934 |     }
 | 
|---|
| 2935 |   return max_size;
 | 
|---|
| 2936 | }
 | 
|---|
| 2937 | 
 | 
|---|
| 2938 | 
 | 
|---|
| 2939 | bfd_boolean
 | 
|---|
| 2940 | xg_is_relaxable_insn (insn, lateral_steps)
 | 
|---|
| 2941 |      TInsn *insn;
 | 
|---|
| 2942 |      int lateral_steps;
 | 
|---|
| 2943 | {
 | 
|---|
| 2944 |   int steps_taken = 0;
 | 
|---|
| 2945 |   TransitionTable *table = xg_build_widen_table ();
 | 
|---|
| 2946 |   TransitionList *l;
 | 
|---|
| 2947 | 
 | 
|---|
| 2948 |   assert (insn->insn_type == ITYPE_INSN);
 | 
|---|
| 2949 |   assert (insn->opcode < table->num_opcodes);
 | 
|---|
| 2950 | 
 | 
|---|
| 2951 |   for (l = table->table[insn->opcode]; l != NULL; l = l->next)
 | 
|---|
| 2952 |     {
 | 
|---|
| 2953 |       TransitionRule *rule = l->rule;
 | 
|---|
| 2954 | 
 | 
|---|
| 2955 |       if (xg_instruction_matches_rule (insn, rule))
 | 
|---|
| 2956 |         {
 | 
|---|
| 2957 |           if (steps_taken == lateral_steps)
 | 
|---|
| 2958 |             return TRUE;
 | 
|---|
| 2959 |           steps_taken++;
 | 
|---|
| 2960 |         }
 | 
|---|
| 2961 |     }
 | 
|---|
| 2962 |   return FALSE;
 | 
|---|
| 2963 | }
 | 
|---|
| 2964 | 
 | 
|---|
| 2965 | 
 | 
|---|
| 2966 | static symbolS *
 | 
|---|
| 2967 | get_special_literal_symbol ()
 | 
|---|
| 2968 | {
 | 
|---|
| 2969 |   static symbolS *sym = NULL;
 | 
|---|
| 2970 | 
 | 
|---|
| 2971 |   if (sym == NULL)
 | 
|---|
| 2972 |     sym = symbol_find_or_make ("SPECIAL_LITERAL0\001");
 | 
|---|
| 2973 |   return sym;
 | 
|---|
| 2974 | }
 | 
|---|
| 2975 | 
 | 
|---|
| 2976 | 
 | 
|---|
| 2977 | static symbolS *
 | 
|---|
| 2978 | get_special_label_symbol ()
 | 
|---|
| 2979 | {
 | 
|---|
| 2980 |   static symbolS *sym = NULL;
 | 
|---|
| 2981 | 
 | 
|---|
| 2982 |   if (sym == NULL)
 | 
|---|
| 2983 |     sym = symbol_find_or_make ("SPECIAL_LABEL0\001");
 | 
|---|
| 2984 |   return sym;
 | 
|---|
| 2985 | }
 | 
|---|
| 2986 | 
 | 
|---|
| 2987 | 
 | 
|---|
| 2988 | /* Return true on success.  */
 | 
|---|
| 2989 | 
 | 
|---|
| 2990 | bfd_boolean
 | 
|---|
| 2991 | xg_build_to_insn (targ, insn, bi)
 | 
|---|
| 2992 |      TInsn *targ;
 | 
|---|
| 2993 |      TInsn *insn;
 | 
|---|
| 2994 |      BuildInstr *bi;
 | 
|---|
| 2995 | {
 | 
|---|
| 2996 |   BuildOp *op;
 | 
|---|
| 2997 |   symbolS *sym;
 | 
|---|
| 2998 | 
 | 
|---|
| 2999 |   memset (targ, 0, sizeof (TInsn));
 | 
|---|
| 3000 |   switch (bi->typ)
 | 
|---|
| 3001 |     {
 | 
|---|
| 3002 |     case INSTR_INSTR:
 | 
|---|
| 3003 |       op = bi->ops;
 | 
|---|
| 3004 |       targ->opcode = bi->opcode;
 | 
|---|
| 3005 |       targ->insn_type = ITYPE_INSN;
 | 
|---|
| 3006 |       targ->is_specific_opcode = FALSE;
 | 
|---|
| 3007 | 
 | 
|---|
| 3008 |       for (; op != NULL; op = op->next)
 | 
|---|
| 3009 |         {
 | 
|---|
| 3010 |           int op_num = op->op_num;
 | 
|---|
| 3011 |           int op_data = op->op_data;
 | 
|---|
| 3012 | 
 | 
|---|
| 3013 |           assert (op->op_num < MAX_INSN_ARGS);
 | 
|---|
| 3014 | 
 | 
|---|
| 3015 |           if (targ->ntok <= op_num)
 | 
|---|
| 3016 |             targ->ntok = op_num + 1;
 | 
|---|
| 3017 | 
 | 
|---|
| 3018 |           switch (op->typ)
 | 
|---|
| 3019 |             {
 | 
|---|
| 3020 |             case OP_CONSTANT:
 | 
|---|
| 3021 |               set_expr_const (&targ->tok[op_num], op_data);
 | 
|---|
| 3022 |               break;
 | 
|---|
| 3023 |             case OP_OPERAND:
 | 
|---|
| 3024 |               assert (op_data < insn->ntok);
 | 
|---|
| 3025 |               copy_expr (&targ->tok[op_num], &insn->tok[op_data]);
 | 
|---|
| 3026 |               break;
 | 
|---|
| 3027 |             case OP_LITERAL:
 | 
|---|
| 3028 |               sym = get_special_literal_symbol ();
 | 
|---|
| 3029 |               set_expr_symbol_offset (&targ->tok[op_num], sym, 0);
 | 
|---|
| 3030 |               break;
 | 
|---|
| 3031 |             case OP_LABEL:
 | 
|---|
| 3032 |               sym = get_special_label_symbol ();
 | 
|---|
| 3033 |               set_expr_symbol_offset (&targ->tok[op_num], sym, 0);
 | 
|---|
| 3034 |               break;
 | 
|---|
| 3035 |             default:
 | 
|---|
| 3036 |               /* currently handles:
 | 
|---|
| 3037 |                  OP_OPERAND_LOW8
 | 
|---|
| 3038 |                  OP_OPERAND_HI24S
 | 
|---|
| 3039 |                  OP_OPERAND_F32MINUS */
 | 
|---|
| 3040 |               if (xg_has_userdef_op_fn (op->typ))
 | 
|---|
| 3041 |                 {
 | 
|---|
| 3042 |                   assert (op_data < insn->ntok);
 | 
|---|
| 3043 |                   if (expr_is_const (&insn->tok[op_data]))
 | 
|---|
| 3044 |                     {
 | 
|---|
| 3045 |                       long val;
 | 
|---|
| 3046 |                       copy_expr (&targ->tok[op_num], &insn->tok[op_data]);
 | 
|---|
| 3047 |                       val = xg_apply_userdef_op_fn (op->typ,
 | 
|---|
| 3048 |                                                     targ->tok[op_num].
 | 
|---|
| 3049 |                                                     X_add_number);
 | 
|---|
| 3050 |                       targ->tok[op_num].X_add_number = val;
 | 
|---|
| 3051 |                     }
 | 
|---|
| 3052 |                   else
 | 
|---|
| 3053 |                     return FALSE; /* We cannot use a relocation for this.  */
 | 
|---|
| 3054 |                   break;
 | 
|---|
| 3055 |                 }
 | 
|---|
| 3056 |               assert (0);
 | 
|---|
| 3057 |               break;
 | 
|---|
| 3058 |             }
 | 
|---|
| 3059 |         }
 | 
|---|
| 3060 |       break;
 | 
|---|
| 3061 | 
 | 
|---|
| 3062 |     case INSTR_LITERAL_DEF:
 | 
|---|
| 3063 |       op = bi->ops;
 | 
|---|
| 3064 |       targ->opcode = XTENSA_UNDEFINED;
 | 
|---|
| 3065 |       targ->insn_type = ITYPE_LITERAL;
 | 
|---|
| 3066 |       targ->is_specific_opcode = FALSE;
 | 
|---|
| 3067 |       for (; op != NULL; op = op->next)
 | 
|---|
| 3068 |         {
 | 
|---|
| 3069 |           int op_num = op->op_num;
 | 
|---|
| 3070 |           int op_data = op->op_data;
 | 
|---|
| 3071 |           assert (op->op_num < MAX_INSN_ARGS);
 | 
|---|
| 3072 | 
 | 
|---|
| 3073 |           if (targ->ntok <= op_num)
 | 
|---|
| 3074 |             targ->ntok = op_num + 1;
 | 
|---|
| 3075 | 
 | 
|---|
| 3076 |           switch (op->typ)
 | 
|---|
| 3077 |             {
 | 
|---|
| 3078 |             case OP_OPERAND:
 | 
|---|
| 3079 |               assert (op_data < insn->ntok);
 | 
|---|
| 3080 |               copy_expr (&targ->tok[op_num], &insn->tok[op_data]);
 | 
|---|
| 3081 |               break;
 | 
|---|
| 3082 |             case OP_LITERAL:
 | 
|---|
| 3083 |             case OP_CONSTANT:
 | 
|---|
| 3084 |             case OP_LABEL:
 | 
|---|
| 3085 |             default:
 | 
|---|
| 3086 |               assert (0);
 | 
|---|
| 3087 |               break;
 | 
|---|
| 3088 |             }
 | 
|---|
| 3089 |         }
 | 
|---|
| 3090 |       break;
 | 
|---|
| 3091 | 
 | 
|---|
| 3092 |     case INSTR_LABEL_DEF:
 | 
|---|
| 3093 |       op = bi->ops;
 | 
|---|
| 3094 |       targ->opcode = XTENSA_UNDEFINED;
 | 
|---|
| 3095 |       targ->insn_type = ITYPE_LABEL;
 | 
|---|
| 3096 |       targ->is_specific_opcode = FALSE;
 | 
|---|
| 3097 |       /* Literal with no ops. is a label?  */
 | 
|---|
| 3098 |       assert (op == NULL);
 | 
|---|
| 3099 |       break;
 | 
|---|
| 3100 | 
 | 
|---|
| 3101 |     default:
 | 
|---|
| 3102 |       assert (0);
 | 
|---|
| 3103 |     }
 | 
|---|
| 3104 | 
 | 
|---|
| 3105 |   return TRUE;
 | 
|---|
| 3106 | }
 | 
|---|
| 3107 | 
 | 
|---|
| 3108 | 
 | 
|---|
| 3109 | /* Return true on success.  */
 | 
|---|
| 3110 | 
 | 
|---|
| 3111 | bfd_boolean
 | 
|---|
| 3112 | xg_build_to_stack (istack, insn, bi)
 | 
|---|
| 3113 |      IStack *istack;
 | 
|---|
| 3114 |      TInsn *insn;
 | 
|---|
| 3115 |      BuildInstr *bi;
 | 
|---|
| 3116 | {
 | 
|---|
| 3117 |   for (; bi != NULL; bi = bi->next)
 | 
|---|
| 3118 |     {
 | 
|---|
| 3119 |       TInsn *next_insn = istack_push_space (istack);
 | 
|---|
| 3120 | 
 | 
|---|
| 3121 |       if (!xg_build_to_insn (next_insn, insn, bi))
 | 
|---|
| 3122 |         return FALSE;
 | 
|---|
| 3123 |     }
 | 
|---|
| 3124 |   return TRUE;
 | 
|---|
| 3125 | }
 | 
|---|
| 3126 | 
 | 
|---|
| 3127 | 
 | 
|---|
| 3128 | /* Return true on valid expansion.  */
 | 
|---|
| 3129 | 
 | 
|---|
| 3130 | bfd_boolean
 | 
|---|
| 3131 | xg_expand_to_stack (istack, insn, lateral_steps)
 | 
|---|
| 3132 |      IStack *istack;
 | 
|---|
| 3133 |      TInsn *insn;
 | 
|---|
| 3134 |      int lateral_steps;
 | 
|---|
| 3135 | {
 | 
|---|
| 3136 |   int stack_size = istack->ninsn;
 | 
|---|
| 3137 |   int steps_taken = 0;
 | 
|---|
| 3138 |   TransitionTable *table = xg_build_widen_table ();
 | 
|---|
| 3139 |   TransitionList *l;
 | 
|---|
| 3140 | 
 | 
|---|
| 3141 |   assert (insn->insn_type == ITYPE_INSN);
 | 
|---|
| 3142 |   assert (insn->opcode < table->num_opcodes);
 | 
|---|
| 3143 | 
 | 
|---|
| 3144 |   for (l = table->table[insn->opcode]; l != NULL; l = l->next)
 | 
|---|
| 3145 |     {
 | 
|---|
| 3146 |       TransitionRule *rule = l->rule;
 | 
|---|
| 3147 | 
 | 
|---|
| 3148 |       if (xg_instruction_matches_rule (insn, rule))
 | 
|---|
| 3149 |         {
 | 
|---|
| 3150 |           if (lateral_steps == steps_taken)
 | 
|---|
| 3151 |             {
 | 
|---|
| 3152 |               int i;
 | 
|---|
| 3153 | 
 | 
|---|
| 3154 |               /* This is it.  Expand the rule to the stack.  */
 | 
|---|
| 3155 |               if (!xg_build_to_stack (istack, insn, rule->to_instr))
 | 
|---|
| 3156 |                 return FALSE;
 | 
|---|
| 3157 | 
 | 
|---|
| 3158 |               /* Check to see if it fits.  */
 | 
|---|
| 3159 |               for (i = stack_size; i < istack->ninsn; i++)
 | 
|---|
| 3160 |                 {
 | 
|---|
| 3161 |                   TInsn *insn = &istack->insn[i];
 | 
|---|
| 3162 | 
 | 
|---|
| 3163 |                   if (insn->insn_type == ITYPE_INSN
 | 
|---|
| 3164 |                       && !tinsn_has_symbolic_operands (insn)
 | 
|---|
| 3165 |                       && !xg_immeds_fit (insn))
 | 
|---|
| 3166 |                     {
 | 
|---|
| 3167 |                       istack->ninsn = stack_size;
 | 
|---|
| 3168 |                       return FALSE;
 | 
|---|
| 3169 |                     }
 | 
|---|
| 3170 |                 }
 | 
|---|
| 3171 |               return TRUE;
 | 
|---|
| 3172 |             }
 | 
|---|
| 3173 |           steps_taken++;
 | 
|---|
| 3174 |         }
 | 
|---|
| 3175 |     }
 | 
|---|
| 3176 |   return FALSE;
 | 
|---|
| 3177 | }
 | 
|---|
| 3178 | 
 | 
|---|
| 3179 | 
 | 
|---|
| 3180 | bfd_boolean
 | 
|---|
| 3181 | xg_expand_narrow (targ, insn)
 | 
|---|
| 3182 |      TInsn *targ;
 | 
|---|
| 3183 |      TInsn *insn;
 | 
|---|
| 3184 | {
 | 
|---|
| 3185 |   TransitionTable *table = xg_build_widen_table ();
 | 
|---|
| 3186 |   TransitionList *l;
 | 
|---|
| 3187 | 
 | 
|---|
| 3188 |   assert (insn->insn_type == ITYPE_INSN);
 | 
|---|
| 3189 |   assert (insn->opcode < table->num_opcodes);
 | 
|---|
| 3190 | 
 | 
|---|
| 3191 |   for (l = table->table[insn->opcode]; l != NULL; l = l->next)
 | 
|---|
| 3192 |     {
 | 
|---|
| 3193 |       TransitionRule *rule = l->rule;
 | 
|---|
| 3194 |       if (xg_instruction_matches_rule (insn, rule)
 | 
|---|
| 3195 |           && is_unique_insn_expansion (rule))
 | 
|---|
| 3196 |         {
 | 
|---|
| 3197 |           /* Is it a larger instruction?  */
 | 
|---|
| 3198 |           if (xg_get_insn_size (insn)
 | 
|---|
| 3199 |               <= xg_get_build_instr_size (rule->to_instr))
 | 
|---|
| 3200 |             {
 | 
|---|
| 3201 |               xg_build_to_insn (targ, insn, rule->to_instr);
 | 
|---|
| 3202 |               return FALSE;
 | 
|---|
| 3203 |             }
 | 
|---|
| 3204 |         }
 | 
|---|
| 3205 |     }
 | 
|---|
| 3206 |   return TRUE;
 | 
|---|
| 3207 | }
 | 
|---|
| 3208 | 
 | 
|---|
| 3209 | 
 | 
|---|
| 3210 | /* Assumes: All immeds are constants.  Check that all constants fit
 | 
|---|
| 3211 |    into their immeds; return false if not.  */
 | 
|---|
| 3212 | 
 | 
|---|
| 3213 | static bfd_boolean
 | 
|---|
| 3214 | xg_immeds_fit (insn)
 | 
|---|
| 3215 |      const TInsn *insn;
 | 
|---|
| 3216 | {
 | 
|---|
| 3217 |   int i;
 | 
|---|
| 3218 | 
 | 
|---|
| 3219 |   int n = insn->ntok;
 | 
|---|
| 3220 |   assert (insn->insn_type == ITYPE_INSN);
 | 
|---|
| 3221 |   for (i = 0; i < n; ++i)
 | 
|---|
| 3222 |     {
 | 
|---|
| 3223 |       const expressionS *expr = &insn->tok[i];
 | 
|---|
| 3224 |       xtensa_operand opnd = xtensa_get_operand (xtensa_default_isa,
 | 
|---|
| 3225 |                                                 insn->opcode, i);
 | 
|---|
| 3226 |       if (!operand_is_immed (opnd))
 | 
|---|
| 3227 |         continue;
 | 
|---|
| 3228 | 
 | 
|---|
| 3229 |       switch (expr->X_op)
 | 
|---|
| 3230 |         {
 | 
|---|
| 3231 |         case O_register:
 | 
|---|
| 3232 |         case O_constant:
 | 
|---|
| 3233 |           {
 | 
|---|
| 3234 |             if (xg_check_operand (expr->X_add_number, opnd))
 | 
|---|
| 3235 |               return FALSE;
 | 
|---|
| 3236 |           }
 | 
|---|
| 3237 |           break;
 | 
|---|
| 3238 |         default:
 | 
|---|
| 3239 |           /* The symbol should have a fixup associated with it.  */
 | 
|---|
| 3240 |           assert (FALSE);
 | 
|---|
| 3241 |           break;
 | 
|---|
| 3242 |         }
 | 
|---|
| 3243 |     }
 | 
|---|
| 3244 |   return TRUE;
 | 
|---|
| 3245 | }
 | 
|---|
| 3246 | 
 | 
|---|
| 3247 | 
 | 
|---|
| 3248 | /* This should only be called after we have an initial
 | 
|---|
| 3249 |    estimate of the addresses.  */
 | 
|---|
| 3250 | 
 | 
|---|
| 3251 | static bfd_boolean
 | 
|---|
| 3252 | xg_symbolic_immeds_fit (insn, pc_seg, pc_frag, pc_offset, stretch)
 | 
|---|
| 3253 |      const TInsn *insn;
 | 
|---|
| 3254 |      segT pc_seg;
 | 
|---|
| 3255 |      fragS *pc_frag;
 | 
|---|
| 3256 |      offsetT pc_offset;
 | 
|---|
| 3257 |      long stretch;
 | 
|---|
| 3258 | {
 | 
|---|
| 3259 |   symbolS *symbolP;
 | 
|---|
| 3260 |   offsetT target, pc, new_offset;
 | 
|---|
| 3261 |   int i;
 | 
|---|
| 3262 |   int n = insn->ntok;
 | 
|---|
| 3263 | 
 | 
|---|
| 3264 |   assert (insn->insn_type == ITYPE_INSN);
 | 
|---|
| 3265 | 
 | 
|---|
| 3266 |   for (i = 0; i < n; ++i)
 | 
|---|
| 3267 |     {
 | 
|---|
| 3268 |       const expressionS *expr = &insn->tok[i];
 | 
|---|
| 3269 |       xtensa_operand opnd = xtensa_get_operand (xtensa_default_isa,
 | 
|---|
| 3270 |                                                 insn->opcode, i);
 | 
|---|
| 3271 |       if (!operand_is_immed (opnd))
 | 
|---|
| 3272 |         continue;
 | 
|---|
| 3273 | 
 | 
|---|
| 3274 |       switch (expr->X_op)
 | 
|---|
| 3275 |         {
 | 
|---|
| 3276 |         case O_register:
 | 
|---|
| 3277 |         case O_constant:
 | 
|---|
| 3278 |           if (xg_check_operand (expr->X_add_number, opnd))
 | 
|---|
| 3279 |             return FALSE;
 | 
|---|
| 3280 |           break;
 | 
|---|
| 3281 | 
 | 
|---|
| 3282 |         case O_symbol:
 | 
|---|
| 3283 |           /* We only allow symbols for pc-relative stuff.
 | 
|---|
| 3284 |              If pc_frag == 0, then we don't have frag locations yet.  */
 | 
|---|
| 3285 |           if (pc_frag == 0)
 | 
|---|
| 3286 |             return FALSE;
 | 
|---|
| 3287 | 
 | 
|---|
| 3288 |           /* If it is PC-relative and the symbol is in the same segment as
 | 
|---|
| 3289 |              the PC.... */
 | 
|---|
| 3290 |           if (!xtensa_operand_isPCRelative (opnd)
 | 
|---|
| 3291 |               || S_GET_SEGMENT (expr->X_add_symbol) != pc_seg)
 | 
|---|
| 3292 |             return FALSE;
 | 
|---|
| 3293 | 
 | 
|---|
| 3294 |           symbolP = expr->X_add_symbol;
 | 
|---|
| 3295 |           target = S_GET_VALUE (symbolP) + expr->X_add_number;
 | 
|---|
| 3296 |           pc = pc_frag->fr_address + pc_offset;
 | 
|---|
| 3297 | 
 | 
|---|
| 3298 |           /* If frag has yet to be reached on this pass, assume it
 | 
|---|
| 3299 |              will move by STRETCH just as we did.  If this is not so,
 | 
|---|
| 3300 |              it will be because some frag between grows, and that will
 | 
|---|
| 3301 |              force another pass.  Beware zero-length frags.  There
 | 
|---|
| 3302 |              should be a faster way to do this.  */
 | 
|---|
| 3303 | 
 | 
|---|
| 3304 |           if (stretch && is_dnrange (pc_frag, symbolP, stretch))
 | 
|---|
| 3305 |             target += stretch;
 | 
|---|
| 3306 | 
 | 
|---|
| 3307 |           new_offset = xtensa_operand_do_reloc (opnd, target, pc);
 | 
|---|
| 3308 |           if (xg_check_operand (new_offset, opnd))
 | 
|---|
| 3309 |             return FALSE;
 | 
|---|
| 3310 |           break;
 | 
|---|
| 3311 | 
 | 
|---|
| 3312 |         default:
 | 
|---|
| 3313 |           /* The symbol should have a fixup associated with it.  */
 | 
|---|
| 3314 |           return FALSE;
 | 
|---|
| 3315 |         }
 | 
|---|
| 3316 |     }
 | 
|---|
| 3317 | 
 | 
|---|
| 3318 |   return TRUE;
 | 
|---|
| 3319 | }
 | 
|---|
| 3320 | 
 | 
|---|
| 3321 | 
 | 
|---|
| 3322 | /* This will check to see if the value can be converted into the
 | 
|---|
| 3323 |    operand type.  It will return true if it does not fit.  */
 | 
|---|
| 3324 | 
 | 
|---|
| 3325 | static bfd_boolean
 | 
|---|
| 3326 | xg_check_operand (value, operand)
 | 
|---|
| 3327 |      int32 value;
 | 
|---|
| 3328 |      xtensa_operand operand;
 | 
|---|
| 3329 | {
 | 
|---|
| 3330 |   uint32 valbuf = value;
 | 
|---|
| 3331 |   return (xtensa_operand_encode (operand, &valbuf) != xtensa_encode_result_ok);
 | 
|---|
| 3332 | }
 | 
|---|
| 3333 | 
 | 
|---|
| 3334 | 
 | 
|---|
| 3335 | /* Check if a symbol is pointing to somewhere after
 | 
|---|
| 3336 |    the start frag, given that the segment has stretched 
 | 
|---|
| 3337 |    by stretch during relaxation.
 | 
|---|
| 3338 | 
 | 
|---|
| 3339 |    This is more complicated than it might appear at first blush
 | 
|---|
| 3340 |    because of the stretching that goes on. Here is how the check
 | 
|---|
| 3341 |    works:
 | 
|---|
| 3342 | 
 | 
|---|
| 3343 |    If the symbol and the frag are in the same segment, then
 | 
|---|
| 3344 |    the symbol could be down range. Note that this function 
 | 
|---|
| 3345 |    assumes that start_frag is in now_seg.
 | 
|---|
| 3346 | 
 | 
|---|
| 3347 |    If the symbol is pointing to a frag with an address greater than 
 | 
|---|
| 3348 |    than the start_frag's address, then it _could_ be down range. 
 | 
|---|
| 3349 | 
 | 
|---|
| 3350 |    The problem comes because target_frag may or may not have had
 | 
|---|
| 3351 |    stretch bytes added to its address already, depending on if it is 
 | 
|---|
| 3352 |    before or after start frag. (And if we knew that, then we wouldn't
 | 
|---|
| 3353 |    need this function.) start_frag has definitely already had stretch
 | 
|---|
| 3354 |    bytes added to its address.
 | 
|---|
| 3355 |    
 | 
|---|
| 3356 |    If target_frag's address hasn't been adjusted yet, then to 
 | 
|---|
| 3357 |    determine if it comes after start_frag, we need to subtract
 | 
|---|
| 3358 |    stretch from start_frag's address.
 | 
|---|
| 3359 | 
 | 
|---|
| 3360 |    If target_frag's address has been adjusted, then it might have
 | 
|---|
| 3361 |    been adjusted such that it comes after start_frag's address minus
 | 
|---|
| 3362 |    stretch bytes.
 | 
|---|
| 3363 | 
 | 
|---|
| 3364 |    So, in that case, we scan for it down stream to within 
 | 
|---|
| 3365 |    stretch bytes. We could search to the end of the fr_chain, but
 | 
|---|
| 3366 |    that ends up taking too much time (over a minute on some gnu 
 | 
|---|
| 3367 |    tests).  */
 | 
|---|
| 3368 | 
 | 
|---|
| 3369 | int
 | 
|---|
| 3370 | is_dnrange (start_frag, sym, stretch)
 | 
|---|
| 3371 |      fragS *start_frag;
 | 
|---|
| 3372 |      symbolS *sym;
 | 
|---|
| 3373 |      long stretch;
 | 
|---|
| 3374 | {
 | 
|---|
| 3375 |   if (S_GET_SEGMENT (sym) == now_seg)
 | 
|---|
| 3376 |     {
 | 
|---|
| 3377 |       fragS *cur_frag = symbol_get_frag (sym);
 | 
|---|
| 3378 | 
 | 
|---|
| 3379 |       if (cur_frag->fr_address >= start_frag->fr_address - stretch)
 | 
|---|
| 3380 |         {
 | 
|---|
| 3381 |           int distance = stretch;
 | 
|---|
| 3382 | 
 | 
|---|
| 3383 |           while (cur_frag && distance >= 0) 
 | 
|---|
| 3384 |             {
 | 
|---|
| 3385 |               distance -= cur_frag->fr_fix;
 | 
|---|
| 3386 |               if (cur_frag == start_frag)
 | 
|---|
| 3387 |                 return 0;
 | 
|---|
| 3388 |               cur_frag = cur_frag->fr_next;
 | 
|---|
| 3389 |             }
 | 
|---|
| 3390 |           return 1;
 | 
|---|
| 3391 |         }
 | 
|---|
| 3392 |     }
 | 
|---|
| 3393 |   return 0;
 | 
|---|
| 3394 | }
 | 
|---|
| 3395 | 
 | 
|---|
| 3396 |  | 
|---|
| 3397 | 
 | 
|---|
| 3398 | /* Relax the assembly instruction at least "min_steps".
 | 
|---|
| 3399 |    Return the number of steps taken.  */
 | 
|---|
| 3400 | 
 | 
|---|
| 3401 | int
 | 
|---|
| 3402 | xg_assembly_relax (istack, insn, pc_seg, pc_frag, pc_offset, min_steps,
 | 
|---|
| 3403 |                    stretch)
 | 
|---|
| 3404 |      IStack *istack;
 | 
|---|
| 3405 |      TInsn *insn;
 | 
|---|
| 3406 |      segT pc_seg;
 | 
|---|
| 3407 |      fragS *pc_frag;            /* If pc_frag == 0, then no pc-relative.  */
 | 
|---|
| 3408 |      offsetT pc_offset;         /* Offset in fragment.  */
 | 
|---|
| 3409 |      int min_steps;             /* Minimum number of conversion steps.  */
 | 
|---|
| 3410 |      long stretch;              /* Number of bytes stretched so far.  */
 | 
|---|
| 3411 | {
 | 
|---|
| 3412 |   int steps_taken = 0;
 | 
|---|
| 3413 | 
 | 
|---|
| 3414 |   /* assert (has no symbolic operands)
 | 
|---|
| 3415 |      Some of its immeds don't fit.
 | 
|---|
| 3416 |      Try to build a relaxed version.
 | 
|---|
| 3417 |      This may go through a couple of stages
 | 
|---|
| 3418 |      of single instruction transformations before
 | 
|---|
| 3419 |      we get there.  */
 | 
|---|
| 3420 | 
 | 
|---|
| 3421 |   TInsn single_target;
 | 
|---|
| 3422 |   TInsn current_insn;
 | 
|---|
| 3423 |   int lateral_steps = 0;
 | 
|---|
| 3424 |   int istack_size = istack->ninsn;
 | 
|---|
| 3425 | 
 | 
|---|
| 3426 |   if (xg_symbolic_immeds_fit (insn, pc_seg, pc_frag, pc_offset, stretch)
 | 
|---|
| 3427 |       && steps_taken >= min_steps)
 | 
|---|
| 3428 |     {
 | 
|---|
| 3429 |       istack_push (istack, insn);
 | 
|---|
| 3430 |       return steps_taken;
 | 
|---|
| 3431 |     }
 | 
|---|
| 3432 |   tinsn_copy (¤t_insn, insn);
 | 
|---|
| 3433 | 
 | 
|---|
| 3434 |   /* Walk through all of the single instruction expansions. */
 | 
|---|
| 3435 |   while (xg_is_single_relaxable_insn (¤t_insn))
 | 
|---|
| 3436 |     {
 | 
|---|
| 3437 |       int error_val = xg_expand_narrow (&single_target, ¤t_insn);
 | 
|---|
| 3438 | 
 | 
|---|
| 3439 |       assert (!error_val);
 | 
|---|
| 3440 | 
 | 
|---|
| 3441 |       if (xg_symbolic_immeds_fit (&single_target, pc_seg, pc_frag, pc_offset,
 | 
|---|
| 3442 |                                   stretch))
 | 
|---|
| 3443 |         {
 | 
|---|
| 3444 |           steps_taken++;
 | 
|---|
| 3445 |           if (steps_taken >= min_steps)
 | 
|---|
| 3446 |             {
 | 
|---|
| 3447 |               istack_push (istack, &single_target);
 | 
|---|
| 3448 |               return steps_taken;
 | 
|---|
| 3449 |             }
 | 
|---|
| 3450 |         }
 | 
|---|
| 3451 |       tinsn_copy (¤t_insn, &single_target);
 | 
|---|
| 3452 |     }
 | 
|---|
| 3453 | 
 | 
|---|
| 3454 |   /* Now check for a multi-instruction expansion.  */
 | 
|---|
| 3455 |   while (xg_is_relaxable_insn (¤t_insn, lateral_steps))
 | 
|---|
| 3456 |     {
 | 
|---|
| 3457 |       if (xg_symbolic_immeds_fit (¤t_insn, pc_seg, pc_frag, pc_offset,
 | 
|---|
| 3458 |                                   stretch))
 | 
|---|
| 3459 |         {
 | 
|---|
| 3460 |           if (steps_taken >= min_steps)
 | 
|---|
| 3461 |             {
 | 
|---|
| 3462 |               istack_push (istack, ¤t_insn);
 | 
|---|
| 3463 |               return steps_taken;
 | 
|---|
| 3464 |             }
 | 
|---|
| 3465 |         }
 | 
|---|
| 3466 |       steps_taken++;
 | 
|---|
| 3467 |       if (xg_expand_to_stack (istack, ¤t_insn, lateral_steps))
 | 
|---|
| 3468 |         {
 | 
|---|
| 3469 |           if (steps_taken >= min_steps)
 | 
|---|
| 3470 |             return steps_taken;
 | 
|---|
| 3471 |         }
 | 
|---|
| 3472 |       lateral_steps++;
 | 
|---|
| 3473 |       istack->ninsn = istack_size;
 | 
|---|
| 3474 |     }
 | 
|---|
| 3475 | 
 | 
|---|
| 3476 |   /* It's not going to work -- use the original.  */
 | 
|---|
| 3477 |   istack_push (istack, insn);
 | 
|---|
| 3478 |   return steps_taken;
 | 
|---|
| 3479 | }
 | 
|---|
| 3480 | 
 | 
|---|
| 3481 | 
 | 
|---|
| 3482 | static void
 | 
|---|
| 3483 | xg_force_frag_space (size)
 | 
|---|
| 3484 |      int size;
 | 
|---|
| 3485 | {
 | 
|---|
| 3486 |   /* This may have the side effect of creating a new fragment for the
 | 
|---|
| 3487 |      space to go into.  I just do not like the name of the "frag"
 | 
|---|
| 3488 |      functions.  */
 | 
|---|
| 3489 |   frag_grow (size);
 | 
|---|
| 3490 | }
 | 
|---|
| 3491 | 
 | 
|---|
| 3492 | 
 | 
|---|
| 3493 | void
 | 
|---|
| 3494 | xg_finish_frag (last_insn, state, max_growth, is_insn)
 | 
|---|
| 3495 |      char *last_insn;
 | 
|---|
| 3496 |      enum xtensa_relax_statesE state;
 | 
|---|
| 3497 |      int max_growth;
 | 
|---|
| 3498 |      bfd_boolean is_insn;
 | 
|---|
| 3499 | {
 | 
|---|
| 3500 |   /* Finish off this fragment so that it has at LEAST the desired
 | 
|---|
| 3501 |      max_growth.  If it doesn't fit in this fragment, close this one
 | 
|---|
| 3502 |      and start a new one.  In either case, return a pointer to the
 | 
|---|
| 3503 |      beginning of the growth area.  */
 | 
|---|
| 3504 | 
 | 
|---|
| 3505 |   fragS *old_frag;
 | 
|---|
| 3506 |   xg_force_frag_space (max_growth);
 | 
|---|
| 3507 | 
 | 
|---|
| 3508 |   old_frag = frag_now;
 | 
|---|
| 3509 | 
 | 
|---|
| 3510 |   frag_now->fr_opcode = last_insn;
 | 
|---|
| 3511 |   if (is_insn)
 | 
|---|
| 3512 |     frag_now->tc_frag_data.is_insn = TRUE;
 | 
|---|
| 3513 | 
 | 
|---|
| 3514 |   frag_var (rs_machine_dependent, max_growth, max_growth,
 | 
|---|
| 3515 |             state, frag_now->fr_symbol, frag_now->fr_offset, last_insn);
 | 
|---|
| 3516 | 
 | 
|---|
| 3517 |   /* Just to make sure that we did not split it up.  */
 | 
|---|
| 3518 |   assert (old_frag->fr_next == frag_now);
 | 
|---|
| 3519 | }
 | 
|---|
| 3520 | 
 | 
|---|
| 3521 | 
 | 
|---|
| 3522 | static bfd_boolean
 | 
|---|
| 3523 | is_branch_jmp_to_next (insn, fragP)
 | 
|---|
| 3524 |      TInsn *insn;
 | 
|---|
| 3525 |      fragS *fragP;
 | 
|---|
| 3526 | {
 | 
|---|
| 3527 |   xtensa_isa isa = xtensa_default_isa;
 | 
|---|
| 3528 |   int i;
 | 
|---|
| 3529 |   int num_ops = xtensa_num_operands (isa, insn->opcode);
 | 
|---|
| 3530 |   int target_op = -1;
 | 
|---|
| 3531 |   symbolS *sym;
 | 
|---|
| 3532 |   fragS *target_frag;
 | 
|---|
| 3533 | 
 | 
|---|
| 3534 |   if (is_loop_opcode (insn->opcode))
 | 
|---|
| 3535 |     return FALSE;
 | 
|---|
| 3536 | 
 | 
|---|
| 3537 |   for (i = 0; i < num_ops; i++)
 | 
|---|
| 3538 |     {
 | 
|---|
| 3539 |       xtensa_operand opnd = xtensa_get_operand (isa, insn->opcode, i);
 | 
|---|
| 3540 |       char *kind = xtensa_operand_kind (opnd);
 | 
|---|
| 3541 |       if (strlen (kind) == 1 && *kind == 'l')
 | 
|---|
| 3542 |         {
 | 
|---|
| 3543 |           target_op = i;
 | 
|---|
| 3544 |           break;
 | 
|---|
| 3545 |         }
 | 
|---|
| 3546 |     }
 | 
|---|
| 3547 |   if (target_op == -1)
 | 
|---|
| 3548 |     return FALSE;
 | 
|---|
| 3549 | 
 | 
|---|
| 3550 |   if (insn->ntok <= target_op)
 | 
|---|
| 3551 |     return FALSE;
 | 
|---|
| 3552 | 
 | 
|---|
| 3553 |   if (insn->tok[target_op].X_op != O_symbol)
 | 
|---|
| 3554 |     return FALSE;
 | 
|---|
| 3555 | 
 | 
|---|
| 3556 |   sym = insn->tok[target_op].X_add_symbol;
 | 
|---|
| 3557 |   if (sym == NULL)
 | 
|---|
| 3558 |     return FALSE;
 | 
|---|
| 3559 | 
 | 
|---|
| 3560 |   if (insn->tok[target_op].X_add_number != 0)
 | 
|---|
| 3561 |     return FALSE;
 | 
|---|
| 3562 | 
 | 
|---|
| 3563 |   target_frag = symbol_get_frag (sym);
 | 
|---|
| 3564 |   if (target_frag == NULL)
 | 
|---|
| 3565 |     return FALSE;
 | 
|---|
| 3566 | 
 | 
|---|
| 3567 |   if (is_next_frag_target (fragP->fr_next, target_frag) 
 | 
|---|
| 3568 |       && S_GET_VALUE (sym) == target_frag->fr_address)
 | 
|---|
| 3569 |     return TRUE;
 | 
|---|
| 3570 | 
 | 
|---|
| 3571 |   return FALSE;
 | 
|---|
| 3572 | }
 | 
|---|
| 3573 | 
 | 
|---|
| 3574 | 
 | 
|---|
| 3575 | static void
 | 
|---|
| 3576 | xg_add_branch_and_loop_targets (insn)
 | 
|---|
| 3577 |      TInsn *insn;
 | 
|---|
| 3578 | {
 | 
|---|
| 3579 |   xtensa_isa isa = xtensa_default_isa;
 | 
|---|
| 3580 |   int num_ops = xtensa_num_operands (isa, insn->opcode);
 | 
|---|
| 3581 | 
 | 
|---|
| 3582 |   if (is_loop_opcode (insn->opcode))
 | 
|---|
| 3583 |     {
 | 
|---|
| 3584 |       int i = 1;
 | 
|---|
| 3585 |       xtensa_operand opnd = xtensa_get_operand (isa, insn->opcode, i);
 | 
|---|
| 3586 |       char *kind = xtensa_operand_kind (opnd);
 | 
|---|
| 3587 |       if (strlen (kind) == 1 && *kind == 'l')
 | 
|---|
| 3588 |         if (insn->tok[i].X_op == O_symbol)
 | 
|---|
| 3589 |           add_target_symbol (insn->tok[i].X_add_symbol, TRUE);
 | 
|---|
| 3590 |       return;
 | 
|---|
| 3591 |     }
 | 
|---|
| 3592 | 
 | 
|---|
| 3593 |   /* Currently, we do not add branch targets.  This is an optimization
 | 
|---|
| 3594 |      for later that tries to align only branch targets, not just any
 | 
|---|
| 3595 |      label in a text section.  */
 | 
|---|
| 3596 | 
 | 
|---|
| 3597 |   if (align_only_targets)
 | 
|---|
| 3598 |     {
 | 
|---|
| 3599 |       int i;
 | 
|---|
| 3600 | 
 | 
|---|
| 3601 |       for (i = 0; i < insn->ntok && i < num_ops; i++)
 | 
|---|
| 3602 |         {
 | 
|---|
| 3603 |           xtensa_operand opnd = xtensa_get_operand (isa, insn->opcode, i);
 | 
|---|
| 3604 |           char *kind = xtensa_operand_kind (opnd);
 | 
|---|
| 3605 |           if (strlen (kind) == 1 && *kind == 'l'
 | 
|---|
| 3606 |               && insn->tok[i].X_op == O_symbol)
 | 
|---|
| 3607 |             add_target_symbol (insn->tok[i].X_add_symbol, FALSE);
 | 
|---|
| 3608 |         }
 | 
|---|
| 3609 |     }
 | 
|---|
| 3610 | }
 | 
|---|
| 3611 | 
 | 
|---|
| 3612 | 
 | 
|---|
| 3613 | /* Return the transition rule that matches or NULL if none matches.  */
 | 
|---|
| 3614 | 
 | 
|---|
| 3615 | bfd_boolean
 | 
|---|
| 3616 | xg_instruction_matches_rule (insn, rule)
 | 
|---|
| 3617 |      TInsn *insn;
 | 
|---|
| 3618 |      TransitionRule *rule;
 | 
|---|
| 3619 | {
 | 
|---|
| 3620 |   PreconditionList *condition_l;
 | 
|---|
| 3621 | 
 | 
|---|
| 3622 |   if (rule->opcode != insn->opcode)
 | 
|---|
| 3623 |     return FALSE;
 | 
|---|
| 3624 | 
 | 
|---|
| 3625 |   for (condition_l = rule->conditions;
 | 
|---|
| 3626 |        condition_l != NULL;
 | 
|---|
| 3627 |        condition_l = condition_l->next)
 | 
|---|
| 3628 |     {
 | 
|---|
| 3629 |       expressionS *exp1;
 | 
|---|
| 3630 |       expressionS *exp2;
 | 
|---|
| 3631 |       Precondition *cond = condition_l->precond;
 | 
|---|
| 3632 | 
 | 
|---|
| 3633 |       switch (cond->typ)
 | 
|---|
| 3634 |         {
 | 
|---|
| 3635 |         case OP_CONSTANT:
 | 
|---|
| 3636 |           /* The expression must be the constant.  */
 | 
|---|
| 3637 |           assert (cond->op_num < insn->ntok);
 | 
|---|
| 3638 |           exp1 = &insn->tok[cond->op_num];
 | 
|---|
| 3639 |           if (!expr_is_const (exp1))
 | 
|---|
| 3640 |             return FALSE;
 | 
|---|
| 3641 |           switch (cond->cmp)
 | 
|---|
| 3642 |             {
 | 
|---|
| 3643 |             case OP_EQUAL:
 | 
|---|
| 3644 |               if (get_expr_const (exp1) != cond->op_data)
 | 
|---|
| 3645 |                 return FALSE;
 | 
|---|
| 3646 |               break;
 | 
|---|
| 3647 |             case OP_NOTEQUAL:
 | 
|---|
| 3648 |               if (get_expr_const (exp1) == cond->op_data)
 | 
|---|
| 3649 |                 return FALSE;
 | 
|---|
| 3650 |               break;
 | 
|---|
| 3651 |             }
 | 
|---|
| 3652 |           break;
 | 
|---|
| 3653 | 
 | 
|---|
| 3654 |         case OP_OPERAND:
 | 
|---|
| 3655 |           assert (cond->op_num < insn->ntok);
 | 
|---|
| 3656 |           assert (cond->op_data < insn->ntok);
 | 
|---|
| 3657 |           exp1 = &insn->tok[cond->op_num];
 | 
|---|
| 3658 |           exp2 = &insn->tok[cond->op_data];
 | 
|---|
| 3659 | 
 | 
|---|
| 3660 |           switch (cond->cmp)
 | 
|---|
| 3661 |             {
 | 
|---|
| 3662 |             case OP_EQUAL:
 | 
|---|
| 3663 |               if (!expr_is_equal (exp1, exp2))
 | 
|---|
| 3664 |                 return FALSE;
 | 
|---|
| 3665 |               break;
 | 
|---|
| 3666 |             case OP_NOTEQUAL:
 | 
|---|
| 3667 |               if (expr_is_equal (exp1, exp2))
 | 
|---|
| 3668 |                 return FALSE;
 | 
|---|
| 3669 |               break;
 | 
|---|
| 3670 |             }
 | 
|---|
| 3671 |           break;
 | 
|---|
| 3672 | 
 | 
|---|
| 3673 |         case OP_LITERAL:
 | 
|---|
| 3674 |         case OP_LABEL:
 | 
|---|
| 3675 |         default:
 | 
|---|
| 3676 |           return FALSE;
 | 
|---|
| 3677 |         }
 | 
|---|
| 3678 |     }
 | 
|---|
| 3679 |   return TRUE;
 | 
|---|
| 3680 | }
 | 
|---|
| 3681 | 
 | 
|---|
| 3682 | 
 | 
|---|
| 3683 | TransitionRule *
 | 
|---|
| 3684 | xg_instruction_match (insn)
 | 
|---|
| 3685 |      TInsn *insn;
 | 
|---|
| 3686 | {
 | 
|---|
| 3687 |   TransitionTable *table = xg_build_simplify_table ();
 | 
|---|
| 3688 |   TransitionList *l;
 | 
|---|
| 3689 |   assert (insn->opcode < table->num_opcodes);
 | 
|---|
| 3690 | 
 | 
|---|
| 3691 |   /* Walk through all of the possible transitions.  */
 | 
|---|
| 3692 |   for (l = table->table[insn->opcode]; l != NULL; l = l->next)
 | 
|---|
| 3693 |     {
 | 
|---|
| 3694 |       TransitionRule *rule = l->rule;
 | 
|---|
| 3695 |       if (xg_instruction_matches_rule (insn, rule))
 | 
|---|
| 3696 |         return rule;
 | 
|---|
| 3697 |     }
 | 
|---|
| 3698 |   return NULL;
 | 
|---|
| 3699 | }
 | 
|---|
| 3700 | 
 | 
|---|
| 3701 | 
 | 
|---|
| 3702 | /* Return false if no error.  */
 | 
|---|
| 3703 | 
 | 
|---|
| 3704 | bfd_boolean
 | 
|---|
| 3705 | xg_build_token_insn (instr_spec, old_insn, new_insn)
 | 
|---|
| 3706 |      BuildInstr *instr_spec;
 | 
|---|
| 3707 |      TInsn *old_insn;
 | 
|---|
| 3708 |      TInsn *new_insn;
 | 
|---|
| 3709 | {
 | 
|---|
| 3710 |   int num_ops = 0;
 | 
|---|
| 3711 |   BuildOp *b_op;
 | 
|---|
| 3712 | 
 | 
|---|
| 3713 |   switch (instr_spec->typ)
 | 
|---|
| 3714 |     {
 | 
|---|
| 3715 |     case INSTR_INSTR:
 | 
|---|
| 3716 |       new_insn->insn_type = ITYPE_INSN;
 | 
|---|
| 3717 |       new_insn->opcode = instr_spec->opcode;
 | 
|---|
| 3718 |       new_insn->is_specific_opcode = FALSE;
 | 
|---|
| 3719 |       break;
 | 
|---|
| 3720 |     case INSTR_LITERAL_DEF:
 | 
|---|
| 3721 |       new_insn->insn_type = ITYPE_LITERAL;
 | 
|---|
| 3722 |       new_insn->opcode = XTENSA_UNDEFINED;
 | 
|---|
| 3723 |       new_insn->is_specific_opcode = FALSE;
 | 
|---|
| 3724 |       break;
 | 
|---|
| 3725 |     case INSTR_LABEL_DEF:
 | 
|---|
| 3726 |       as_bad (_("INSTR_LABEL_DEF not supported yet"));
 | 
|---|
| 3727 |       break;
 | 
|---|
| 3728 |     }
 | 
|---|
| 3729 | 
 | 
|---|
| 3730 |   for (b_op = instr_spec->ops; b_op != NULL; b_op = b_op->next)
 | 
|---|
| 3731 |     {
 | 
|---|
| 3732 |       expressionS *exp;
 | 
|---|
| 3733 |       const expressionS *src_exp;
 | 
|---|
| 3734 | 
 | 
|---|
| 3735 |       num_ops++;
 | 
|---|
| 3736 |       switch (b_op->typ)
 | 
|---|
| 3737 |         {
 | 
|---|
| 3738 |         case OP_CONSTANT:
 | 
|---|
| 3739 |           /* The expression must be the constant.  */
 | 
|---|
| 3740 |           assert (b_op->op_num < MAX_INSN_ARGS);
 | 
|---|
| 3741 |           exp = &new_insn->tok[b_op->op_num];
 | 
|---|
| 3742 |           set_expr_const (exp, b_op->op_data);
 | 
|---|
| 3743 |           break;
 | 
|---|
| 3744 | 
 | 
|---|
| 3745 |         case OP_OPERAND:
 | 
|---|
| 3746 |           assert (b_op->op_num < MAX_INSN_ARGS);
 | 
|---|
| 3747 |           assert (b_op->op_data < (unsigned) old_insn->ntok);
 | 
|---|
| 3748 |           src_exp = &old_insn->tok[b_op->op_data];
 | 
|---|
| 3749 |           exp = &new_insn->tok[b_op->op_num];
 | 
|---|
| 3750 |           copy_expr (exp, src_exp);
 | 
|---|
| 3751 |           break;
 | 
|---|
| 3752 | 
 | 
|---|
| 3753 |         case OP_LITERAL:
 | 
|---|
| 3754 |         case OP_LABEL:
 | 
|---|
| 3755 |           as_bad (_("can't handle generation of literal/labels yet"));
 | 
|---|
| 3756 |           assert (0);
 | 
|---|
| 3757 | 
 | 
|---|
| 3758 |         default:
 | 
|---|
| 3759 |           as_bad (_("can't handle undefined OP TYPE"));
 | 
|---|
| 3760 |           assert (0);
 | 
|---|
| 3761 |         }
 | 
|---|
| 3762 |     }
 | 
|---|
| 3763 | 
 | 
|---|
| 3764 |   new_insn->ntok = num_ops;
 | 
|---|
| 3765 |   return FALSE;
 | 
|---|
| 3766 | }
 | 
|---|
| 3767 | 
 | 
|---|
| 3768 | 
 | 
|---|
| 3769 | /* Return true if it was simplified.  */
 | 
|---|
| 3770 | 
 | 
|---|
| 3771 | bfd_boolean
 | 
|---|
| 3772 | xg_simplify_insn (old_insn, new_insn)
 | 
|---|
| 3773 |      TInsn *old_insn;
 | 
|---|
| 3774 |      TInsn *new_insn;
 | 
|---|
| 3775 | {
 | 
|---|
| 3776 |   TransitionRule *rule = xg_instruction_match (old_insn);
 | 
|---|
| 3777 |   BuildInstr *insn_spec;
 | 
|---|
| 3778 |   if (rule == NULL)
 | 
|---|
| 3779 |     return FALSE;
 | 
|---|
| 3780 | 
 | 
|---|
| 3781 |   insn_spec = rule->to_instr;
 | 
|---|
| 3782 |   /* There should only be one.  */
 | 
|---|
| 3783 |   assert (insn_spec != NULL);
 | 
|---|
| 3784 |   assert (insn_spec->next == NULL);
 | 
|---|
| 3785 |   if (insn_spec->next != NULL)
 | 
|---|
| 3786 |     return FALSE;
 | 
|---|
| 3787 | 
 | 
|---|
| 3788 |   xg_build_token_insn (insn_spec, old_insn, new_insn);
 | 
|---|
| 3789 | 
 | 
|---|
| 3790 |   return TRUE;
 | 
|---|
| 3791 | }
 | 
|---|
| 3792 | 
 | 
|---|
| 3793 | 
 | 
|---|
| 3794 | /* xg_expand_assembly_insn: (1) Simplify the instruction, i.e., l32i ->
 | 
|---|
| 3795 |    l32i.n. (2) Check the number of operands.  (3) Place the instruction
 | 
|---|
| 3796 |    tokens into the stack or if we can relax it at assembly time, place
 | 
|---|
| 3797 |    multiple instructions/literals onto the stack.  Return false if no
 | 
|---|
| 3798 |    error.  */
 | 
|---|
| 3799 | 
 | 
|---|
| 3800 | static bfd_boolean
 | 
|---|
| 3801 | xg_expand_assembly_insn (istack, orig_insn)
 | 
|---|
| 3802 |      IStack *istack;
 | 
|---|
| 3803 |      TInsn *orig_insn;
 | 
|---|
| 3804 | {
 | 
|---|
| 3805 |   int noperands;
 | 
|---|
| 3806 |   TInsn new_insn;
 | 
|---|
| 3807 |   memset (&new_insn, 0, sizeof (TInsn));
 | 
|---|
| 3808 | 
 | 
|---|
| 3809 |   /* On return, we will be using the "use_tokens" with "use_ntok".
 | 
|---|
| 3810 |      This will reduce things like addi to addi.n.  */
 | 
|---|
| 3811 |   if (code_density_available () && !orig_insn->is_specific_opcode)
 | 
|---|
| 3812 |     {
 | 
|---|
| 3813 |       if (xg_simplify_insn (orig_insn, &new_insn))
 | 
|---|
| 3814 |         orig_insn = &new_insn;
 | 
|---|
| 3815 |     }
 | 
|---|
| 3816 | 
 | 
|---|
| 3817 |   noperands = xtensa_num_operands (xtensa_default_isa, orig_insn->opcode);
 | 
|---|
| 3818 |   if (orig_insn->ntok < noperands)
 | 
|---|
| 3819 |     {
 | 
|---|
| 3820 |       as_bad (_("found %d operands for '%s':  Expected %d"),
 | 
|---|
| 3821 |               orig_insn->ntok,
 | 
|---|
| 3822 |               xtensa_opcode_name (xtensa_default_isa, orig_insn->opcode),
 | 
|---|
| 3823 |               noperands);
 | 
|---|
| 3824 |       return TRUE;
 | 
|---|
| 3825 |     }
 | 
|---|
| 3826 |   if (orig_insn->ntok > noperands)
 | 
|---|
| 3827 |     as_warn (_("found too many (%d) operands for '%s':  Expected %d"),
 | 
|---|
| 3828 |              orig_insn->ntok,
 | 
|---|
| 3829 |              xtensa_opcode_name (xtensa_default_isa, orig_insn->opcode),
 | 
|---|
| 3830 |              noperands);
 | 
|---|
| 3831 | 
 | 
|---|
| 3832 |   /* If there are not enough operands, we will assert above. If there
 | 
|---|
| 3833 |      are too many, just cut out the extras here.  */
 | 
|---|
| 3834 | 
 | 
|---|
| 3835 |   orig_insn->ntok = noperands;
 | 
|---|
| 3836 | 
 | 
|---|
| 3837 |   /* Cases: 
 | 
|---|
| 3838 | 
 | 
|---|
| 3839 |      Instructions with all constant immeds:
 | 
|---|
| 3840 |      Assemble them and relax the instruction if possible.
 | 
|---|
| 3841 |      Give error if not possible; no fixup needed.
 | 
|---|
| 3842 | 
 | 
|---|
| 3843 |      Instructions with symbolic immeds:
 | 
|---|
| 3844 |      Assemble them with a Fix up (that may cause instruction expansion).
 | 
|---|
| 3845 |      Also close out the fragment if the fixup may cause instruction expansion. 
 | 
|---|
| 3846 |      
 | 
|---|
| 3847 |      There are some other special cases where we need alignment.
 | 
|---|
| 3848 |      1) before certain instructions with required alignment (OPCODE_ALIGN)
 | 
|---|
| 3849 |      2) before labels that have jumps (LABEL_ALIGN)
 | 
|---|
| 3850 |      3) after call instructions (RETURN_ALIGN)
 | 
|---|
| 3851 |         Multiple of these may be possible on the same fragment. 
 | 
|---|
| 3852 |         If so, make sure to satisfy the required alignment. 
 | 
|---|
| 3853 |         Then try to get the desired alignment.  */
 | 
|---|
| 3854 | 
 | 
|---|
| 3855 |   if (tinsn_has_invalid_symbolic_operands (orig_insn))
 | 
|---|
| 3856 |     return TRUE;
 | 
|---|
| 3857 | 
 | 
|---|
| 3858 |   if (orig_insn->is_specific_opcode || !can_relax ())
 | 
|---|
| 3859 |     {
 | 
|---|
| 3860 |       istack_push (istack, orig_insn);
 | 
|---|
| 3861 |       return FALSE;
 | 
|---|
| 3862 |     }
 | 
|---|
| 3863 | 
 | 
|---|
| 3864 |   if (tinsn_has_symbolic_operands (orig_insn))
 | 
|---|
| 3865 |     {
 | 
|---|
| 3866 |       if (tinsn_has_complex_operands (orig_insn))
 | 
|---|
| 3867 |         xg_assembly_relax (istack, orig_insn, 0, 0, 0, 0, 0);
 | 
|---|
| 3868 |       else
 | 
|---|
| 3869 |         istack_push (istack, orig_insn);
 | 
|---|
| 3870 |     }
 | 
|---|
| 3871 |   else
 | 
|---|
| 3872 |     {
 | 
|---|
| 3873 |       if (xg_immeds_fit (orig_insn))
 | 
|---|
| 3874 |         istack_push (istack, orig_insn);
 | 
|---|
| 3875 |       else
 | 
|---|
| 3876 |         xg_assembly_relax (istack, orig_insn, 0, 0, 0, 0, 0);
 | 
|---|
| 3877 |     }
 | 
|---|
| 3878 | 
 | 
|---|
| 3879 | #if 0
 | 
|---|
| 3880 |   for (i = 0; i < istack->ninsn; i++)
 | 
|---|
| 3881 |     {
 | 
|---|
| 3882 |       if (xg_simplify_insn (&new_insn, &istack->insn[i]))
 | 
|---|
| 3883 |         istack->insn[i] = new_insn;
 | 
|---|
| 3884 |     }
 | 
|---|
| 3885 | #endif
 | 
|---|
| 3886 | 
 | 
|---|
| 3887 |   return FALSE;
 | 
|---|
| 3888 | }
 | 
|---|
| 3889 | 
 | 
|---|
| 3890 | 
 | 
|---|
| 3891 | /* Currently all literals that are generated here are 32-bit L32R targets.  */
 | 
|---|
| 3892 | 
 | 
|---|
| 3893 | symbolS *
 | 
|---|
| 3894 | xg_assemble_literal (insn)
 | 
|---|
| 3895 |      /* const */ TInsn *insn;
 | 
|---|
| 3896 | {
 | 
|---|
| 3897 |   emit_state state;
 | 
|---|
| 3898 |   symbolS *lit_sym = NULL;
 | 
|---|
| 3899 | 
 | 
|---|
| 3900 |   /* size = 4 for L32R.  It could easily be larger when we move to
 | 
|---|
| 3901 |      larger constants.  Add a parameter later.  */
 | 
|---|
| 3902 |   offsetT litsize = 4;
 | 
|---|
| 3903 |   offsetT litalign = 2;         /* 2^2 = 4 */
 | 
|---|
| 3904 |   expressionS saved_loc;
 | 
|---|
| 3905 |   set_expr_symbol_offset (&saved_loc, frag_now->fr_symbol, frag_now_fix ());
 | 
|---|
| 3906 | 
 | 
|---|
| 3907 |   assert (insn->insn_type == ITYPE_LITERAL);
 | 
|---|
| 3908 |   assert (insn->ntok = 1);      /* must be only one token here */
 | 
|---|
| 3909 | 
 | 
|---|
| 3910 |   xtensa_switch_to_literal_fragment (&state);
 | 
|---|
| 3911 | 
 | 
|---|
| 3912 |   /* Force a 4-byte align here.  Note that this opens a new frag, so all
 | 
|---|
| 3913 |      literals done with this function have a frag to themselves.  That's
 | 
|---|
| 3914 |      important for the way text section literals work.  */
 | 
|---|
| 3915 |   frag_align (litalign, 0, 0);
 | 
|---|
| 3916 | 
 | 
|---|
| 3917 |   emit_expr (&insn->tok[0], litsize);
 | 
|---|
| 3918 | 
 | 
|---|
| 3919 |   assert (frag_now->tc_frag_data.literal_frag == NULL);
 | 
|---|
| 3920 |   frag_now->tc_frag_data.literal_frag = get_literal_pool_location (now_seg);
 | 
|---|
| 3921 |   frag_now->fr_symbol = xtensa_create_literal_symbol (now_seg, frag_now);
 | 
|---|
| 3922 |   lit_sym = frag_now->fr_symbol;
 | 
|---|
| 3923 |   frag_now->tc_frag_data.is_literal = TRUE;
 | 
|---|
| 3924 | 
 | 
|---|
| 3925 |   /* Go back.  */
 | 
|---|
| 3926 |   xtensa_restore_emit_state (&state);
 | 
|---|
| 3927 |   return lit_sym;
 | 
|---|
| 3928 | }
 | 
|---|
| 3929 | 
 | 
|---|
| 3930 | 
 | 
|---|
| 3931 | static void
 | 
|---|
| 3932 | xg_assemble_literal_space (size)
 | 
|---|
| 3933 |      /* const */ int size;
 | 
|---|
| 3934 | {
 | 
|---|
| 3935 |   emit_state state;
 | 
|---|
| 3936 |   /* We might have to do something about this alignment.  It only  
 | 
|---|
| 3937 |      takes effect if something is placed here.  */
 | 
|---|
| 3938 |   offsetT litalign = 2;         /* 2^2 = 4 */
 | 
|---|
| 3939 |   fragS *lit_saved_frag;
 | 
|---|
| 3940 | 
 | 
|---|
| 3941 |   expressionS saved_loc;
 | 
|---|
| 3942 | 
 | 
|---|
| 3943 |   assert (size % 4 == 0);
 | 
|---|
| 3944 |   set_expr_symbol_offset (&saved_loc, frag_now->fr_symbol, frag_now_fix ());
 | 
|---|
| 3945 | 
 | 
|---|
| 3946 |   xtensa_switch_to_literal_fragment (&state);
 | 
|---|
| 3947 | 
 | 
|---|
| 3948 |   /* Force a 4-byte align here.  */
 | 
|---|
| 3949 |   frag_align (litalign, 0, 0);
 | 
|---|
| 3950 | 
 | 
|---|
| 3951 |   xg_force_frag_space (size);
 | 
|---|
| 3952 | 
 | 
|---|
| 3953 |   lit_saved_frag = frag_now;
 | 
|---|
| 3954 |   frag_now->tc_frag_data.literal_frag = get_literal_pool_location (now_seg);
 | 
|---|
| 3955 |   frag_now->tc_frag_data.is_literal = TRUE;
 | 
|---|
| 3956 |   frag_now->fr_symbol = xtensa_create_literal_symbol (now_seg, frag_now);
 | 
|---|
| 3957 |   xg_finish_frag (0, RELAX_LITERAL, size, FALSE);
 | 
|---|
| 3958 | 
 | 
|---|
| 3959 |   /* Go back.  */
 | 
|---|
| 3960 |   xtensa_restore_emit_state (&state);
 | 
|---|
| 3961 |   frag_now->tc_frag_data.literal_frag = lit_saved_frag;
 | 
|---|
| 3962 | }
 | 
|---|
| 3963 | 
 | 
|---|
| 3964 | 
 | 
|---|
| 3965 | symbolS *
 | 
|---|
| 3966 | xtensa_create_literal_symbol (sec, frag)
 | 
|---|
| 3967 |      segT sec;
 | 
|---|
| 3968 |      fragS *frag;
 | 
|---|
| 3969 | {
 | 
|---|
| 3970 |   static int lit_num = 0;
 | 
|---|
| 3971 |   static char name[256];
 | 
|---|
| 3972 |   symbolS *fragSym;
 | 
|---|
| 3973 | 
 | 
|---|
| 3974 |   sprintf (name, ".L_lit_sym%d", lit_num);
 | 
|---|
| 3975 |   fragSym = xtensa_create_local_symbol (stdoutput, name, sec, 0, frag_now);
 | 
|---|
| 3976 | 
 | 
|---|
| 3977 |   frag->tc_frag_data.is_literal = TRUE;
 | 
|---|
| 3978 |   lit_num++;
 | 
|---|
| 3979 |   return fragSym;
 | 
|---|
| 3980 | }
 | 
|---|
| 3981 | 
 | 
|---|
| 3982 | 
 | 
|---|
| 3983 | /* Create a local symbol.  If it is in a linkonce section, we have to
 | 
|---|
| 3984 |    be careful to make sure that if it is used in a relocation that the
 | 
|---|
| 3985 |    symbol will be in the output file.  */
 | 
|---|
| 3986 | 
 | 
|---|
| 3987 | symbolS *
 | 
|---|
| 3988 | xtensa_create_local_symbol (abfd, name, sec, value, frag)
 | 
|---|
| 3989 |      bfd *abfd;
 | 
|---|
| 3990 |      const char *name;
 | 
|---|
| 3991 |      segT sec;
 | 
|---|
| 3992 |      valueT value;
 | 
|---|
| 3993 |      fragS *frag;
 | 
|---|
| 3994 | {
 | 
|---|
| 3995 |   symbolS *symbolP;
 | 
|---|
| 3996 | 
 | 
|---|
| 3997 |   if (get_is_linkonce_section (abfd, sec))
 | 
|---|
| 3998 |     {
 | 
|---|
| 3999 |       symbolP = symbol_new (name, sec, value, frag);
 | 
|---|
| 4000 |       S_CLEAR_EXTERNAL (symbolP);
 | 
|---|
| 4001 |       /* symbolP->local = 1; */
 | 
|---|
| 4002 |     }
 | 
|---|
| 4003 |   else
 | 
|---|
| 4004 |     symbolP = symbol_new (name, sec, value, frag);
 | 
|---|
| 4005 | 
 | 
|---|
| 4006 |   return symbolP;
 | 
|---|
| 4007 | }
 | 
|---|
| 4008 | 
 | 
|---|
| 4009 | 
 | 
|---|
| 4010 | /* Return true if the section flags are marked linkonce
 | 
|---|
| 4011 |    or the name is .gnu.linkonce*.  */
 | 
|---|
| 4012 | 
 | 
|---|
| 4013 | bfd_boolean
 | 
|---|
| 4014 | get_is_linkonce_section (abfd, sec)
 | 
|---|
| 4015 |      bfd *abfd ATTRIBUTE_UNUSED;
 | 
|---|
| 4016 |      segT sec;
 | 
|---|
| 4017 | {
 | 
|---|
| 4018 |   flagword flags, link_once_flags;
 | 
|---|
| 4019 | 
 | 
|---|
| 4020 |   flags = bfd_get_section_flags (abfd, sec);
 | 
|---|
| 4021 |   link_once_flags = (flags & SEC_LINK_ONCE);
 | 
|---|
| 4022 | 
 | 
|---|
| 4023 |   /* Flags might not be set yet.  */
 | 
|---|
| 4024 |   if (!link_once_flags)
 | 
|---|
| 4025 |     {
 | 
|---|
| 4026 |       static size_t len = sizeof ".gnu.linkonce.t.";
 | 
|---|
| 4027 | 
 | 
|---|
| 4028 |       if (strncmp (segment_name (sec), ".gnu.linkonce.t.", len - 1) == 0)
 | 
|---|
| 4029 |         link_once_flags = SEC_LINK_ONCE;
 | 
|---|
| 4030 |     }
 | 
|---|
| 4031 |   return (link_once_flags != 0);
 | 
|---|
| 4032 | }
 | 
|---|
| 4033 | 
 | 
|---|
| 4034 | 
 | 
|---|
| 4035 | /* Emit an instruction to the current fragment.  If record_fix is true,
 | 
|---|
| 4036 |    then this instruction will not change and we can go ahead and record
 | 
|---|
| 4037 |    the fixup.  If record_fix is false, then the instruction may change
 | 
|---|
| 4038 |    and we are going to close out this fragment.  Go ahead and set the
 | 
|---|
| 4039 |    fr_symbol and fr_offset instead of adding a fixup.  */
 | 
|---|
| 4040 | 
 | 
|---|
| 4041 | static bfd_boolean
 | 
|---|
| 4042 | xg_emit_insn (t_insn, record_fix)
 | 
|---|
| 4043 |      TInsn *t_insn;
 | 
|---|
| 4044 |      bfd_boolean record_fix;
 | 
|---|
| 4045 | {
 | 
|---|
| 4046 |   bfd_boolean ok = TRUE;
 | 
|---|
| 4047 |   xtensa_isa isa = xtensa_default_isa;
 | 
|---|
| 4048 |   xtensa_opcode opcode = t_insn->opcode;
 | 
|---|
| 4049 |   bfd_boolean has_fixup = FALSE;
 | 
|---|
| 4050 |   int noperands;
 | 
|---|
| 4051 |   int i, byte_count;
 | 
|---|
| 4052 |   fragS *oldfrag;
 | 
|---|
| 4053 |   size_t old_size;
 | 
|---|
| 4054 |   char *f;
 | 
|---|
| 4055 |   static xtensa_insnbuf insnbuf = NULL;
 | 
|---|
| 4056 |   
 | 
|---|
| 4057 |   /* Use a static pointer to the insn buffer so we don't have to call 
 | 
|---|
| 4058 |      malloc each time through.  */
 | 
|---|
| 4059 |   if (!insnbuf)
 | 
|---|
| 4060 |     insnbuf = xtensa_insnbuf_alloc (xtensa_default_isa);
 | 
|---|
| 4061 | 
 | 
|---|
| 4062 |   has_fixup = tinsn_to_insnbuf (t_insn, insnbuf);
 | 
|---|
| 4063 | 
 | 
|---|
| 4064 |   noperands = xtensa_num_operands (isa, opcode);
 | 
|---|
| 4065 |   assert (noperands == t_insn->ntok);
 | 
|---|
| 4066 | 
 | 
|---|
| 4067 |   byte_count = xtensa_insn_length (isa, opcode);
 | 
|---|
| 4068 |   oldfrag = frag_now;
 | 
|---|
| 4069 |   /* This should NEVER cause us to jump into a new frag;
 | 
|---|
| 4070 |      we've already reserved space.  */
 | 
|---|
| 4071 |   old_size = frag_now_fix ();
 | 
|---|
| 4072 |   f = frag_more (byte_count);
 | 
|---|
| 4073 |   assert (oldfrag == frag_now);
 | 
|---|
| 4074 | 
 | 
|---|
| 4075 |   /* This needs to generate a record that lists the parts that are
 | 
|---|
| 4076 |      instructions.  */
 | 
|---|
| 4077 |   if (!frag_now->tc_frag_data.is_insn)
 | 
|---|
| 4078 |     {
 | 
|---|
| 4079 |       /* If we are at the beginning of a fragment, switch this
 | 
|---|
| 4080 |          fragment to an instruction fragment.  */
 | 
|---|
| 4081 |       if (now_seg != absolute_section && old_size != 0)
 | 
|---|
| 4082 |         as_warn (_("instruction fragment may contain data"));
 | 
|---|
| 4083 |       frag_now->tc_frag_data.is_insn = TRUE;
 | 
|---|
| 4084 |     }
 | 
|---|
| 4085 | 
 | 
|---|
| 4086 |   xtensa_insnbuf_to_chars (isa, insnbuf, f);
 | 
|---|
| 4087 | 
 | 
|---|
| 4088 |   /* dwarf2_emit_insn (byte_count); */
 | 
|---|
| 4089 | 
 | 
|---|
| 4090 |   /* Now spit out the opcode fixup.... */
 | 
|---|
| 4091 |   if (!has_fixup)
 | 
|---|
| 4092 |     return !ok;
 | 
|---|
| 4093 | 
 | 
|---|
| 4094 |   for (i = 0; i < noperands; ++i)
 | 
|---|
| 4095 |     {
 | 
|---|
| 4096 |       expressionS *expr = &t_insn->tok[i];
 | 
|---|
| 4097 |       switch (expr->X_op)
 | 
|---|
| 4098 |         {
 | 
|---|
| 4099 |         case O_symbol:
 | 
|---|
| 4100 |           if (get_relaxable_immed (opcode) == i)
 | 
|---|
| 4101 |             {
 | 
|---|
| 4102 |               if (record_fix)
 | 
|---|
| 4103 |                 {
 | 
|---|
| 4104 |                   if (!xg_add_opcode_fix (opcode, i, expr, frag_now,
 | 
|---|
| 4105 |                                           f - frag_now->fr_literal))
 | 
|---|
| 4106 |                     ok = FALSE;
 | 
|---|
| 4107 |                 }
 | 
|---|
| 4108 |               else
 | 
|---|
| 4109 |                 {
 | 
|---|
| 4110 |                   /* Write it to the fr_offset, fr_symbol.  */
 | 
|---|
| 4111 |                   frag_now->fr_symbol = expr->X_add_symbol;
 | 
|---|
| 4112 |                   frag_now->fr_offset = expr->X_add_number;
 | 
|---|
| 4113 |                 }
 | 
|---|
| 4114 |             }
 | 
|---|
| 4115 |           else
 | 
|---|
| 4116 |             {
 | 
|---|
| 4117 |               as_bad (_("invalid operand %d on '%s'"),
 | 
|---|
| 4118 |                       i, xtensa_opcode_name (isa, opcode));
 | 
|---|
| 4119 |               ok = FALSE;
 | 
|---|
| 4120 |             }
 | 
|---|
| 4121 |           break;
 | 
|---|
| 4122 | 
 | 
|---|
| 4123 |         case O_constant:
 | 
|---|
| 4124 |         case O_register:
 | 
|---|
| 4125 |           break;
 | 
|---|
| 4126 | 
 | 
|---|
| 4127 |         default:
 | 
|---|
| 4128 |           as_bad (_("invalid expression for operand %d on '%s'"),
 | 
|---|
| 4129 |                   i, xtensa_opcode_name (isa, opcode));
 | 
|---|
| 4130 |           ok = FALSE;
 | 
|---|
| 4131 |           break;
 | 
|---|
| 4132 |         }
 | 
|---|
| 4133 |     }
 | 
|---|
| 4134 | 
 | 
|---|
| 4135 |   return !ok;
 | 
|---|
| 4136 | }
 | 
|---|
| 4137 | 
 | 
|---|
| 4138 | 
 | 
|---|
| 4139 | static bfd_boolean
 | 
|---|
| 4140 | xg_emit_insn_to_buf (t_insn, buf, fragP, offset, build_fix)
 | 
|---|
| 4141 |      TInsn *t_insn;
 | 
|---|
| 4142 |      char *buf;
 | 
|---|
| 4143 |      fragS *fragP;
 | 
|---|
| 4144 |      offsetT offset;
 | 
|---|
| 4145 |      bfd_boolean build_fix;
 | 
|---|
| 4146 | {
 | 
|---|
| 4147 |   static xtensa_insnbuf insnbuf = NULL;
 | 
|---|
| 4148 |   bfd_boolean has_symbolic_immed = FALSE;
 | 
|---|
| 4149 |   bfd_boolean ok = TRUE;
 | 
|---|
| 4150 |   if (!insnbuf)
 | 
|---|
| 4151 |     insnbuf = xtensa_insnbuf_alloc (xtensa_default_isa);
 | 
|---|
| 4152 | 
 | 
|---|
| 4153 |   has_symbolic_immed = tinsn_to_insnbuf (t_insn, insnbuf);
 | 
|---|
| 4154 |   if (has_symbolic_immed && build_fix)
 | 
|---|
| 4155 |     {
 | 
|---|
| 4156 |       /* Add a fixup.  */
 | 
|---|
| 4157 |       int opnum = get_relaxable_immed (t_insn->opcode);
 | 
|---|
| 4158 |       expressionS *exp = &t_insn->tok[opnum];
 | 
|---|
| 4159 | 
 | 
|---|
| 4160 |       if (!xg_add_opcode_fix (t_insn->opcode, 
 | 
|---|
| 4161 |                               opnum, exp, fragP, offset))
 | 
|---|
| 4162 |         ok = FALSE;
 | 
|---|
| 4163 |     }
 | 
|---|
| 4164 |   fragP->tc_frag_data.is_insn = TRUE;
 | 
|---|
| 4165 |   xtensa_insnbuf_to_chars (xtensa_default_isa, insnbuf, buf);
 | 
|---|
| 4166 |   return ok;
 | 
|---|
| 4167 | }
 | 
|---|
| 4168 | 
 | 
|---|
| 4169 | 
 | 
|---|
| 4170 | /* Put in a fixup record based on the opcode.
 | 
|---|
| 4171 |    Return true on success.  */
 | 
|---|
| 4172 | 
 | 
|---|
| 4173 | bfd_boolean
 | 
|---|
| 4174 | xg_add_opcode_fix (opcode, opnum, expr, fragP, offset)
 | 
|---|
| 4175 |      xtensa_opcode opcode;
 | 
|---|
| 4176 |      int opnum;
 | 
|---|
| 4177 |      expressionS *expr;
 | 
|---|
| 4178 |      fragS *fragP;
 | 
|---|
| 4179 |      offsetT offset;
 | 
|---|
| 4180 | { 
 | 
|---|
| 4181 |   bfd_reloc_code_real_type reloc; 
 | 
|---|
| 4182 |   reloc_howto_type *howto; 
 | 
|---|
| 4183 |   int insn_length;
 | 
|---|
| 4184 |   fixS *the_fix;
 | 
|---|
| 4185 | 
 | 
|---|
| 4186 |   reloc = opnum_to_reloc (opnum);
 | 
|---|
| 4187 |   if (reloc == BFD_RELOC_NONE)
 | 
|---|
| 4188 |     {
 | 
|---|
| 4189 |       as_bad (_("invalid relocation operand %i on '%s'"),
 | 
|---|
| 4190 |               opnum, xtensa_opcode_name (xtensa_default_isa, opcode));
 | 
|---|
| 4191 |       return FALSE;
 | 
|---|
| 4192 |     }
 | 
|---|
| 4193 | 
 | 
|---|
| 4194 |   howto = bfd_reloc_type_lookup (stdoutput, reloc);
 | 
|---|
| 4195 | 
 | 
|---|
| 4196 |   if (!howto)
 | 
|---|
| 4197 |     {
 | 
|---|
| 4198 |       as_bad (_("undefined symbol for opcode \"%s\"."),
 | 
|---|
| 4199 |               xtensa_opcode_name (xtensa_default_isa, opcode));
 | 
|---|
| 4200 |       return FALSE;
 | 
|---|
| 4201 |     }
 | 
|---|
| 4202 | 
 | 
|---|
| 4203 |   insn_length = xtensa_insn_length (xtensa_default_isa, opcode);
 | 
|---|
| 4204 |   the_fix = fix_new_exp (fragP, offset, insn_length, expr,
 | 
|---|
| 4205 |                          howto->pc_relative, reloc);
 | 
|---|
| 4206 | 
 | 
|---|
| 4207 |   if (expr->X_add_symbol && 
 | 
|---|
| 4208 |       (S_IS_EXTERNAL (expr->X_add_symbol) || S_IS_WEAK (expr->X_add_symbol)))
 | 
|---|
| 4209 |     the_fix->fx_plt = TRUE;
 | 
|---|
| 4210 |   
 | 
|---|
| 4211 |   return TRUE;
 | 
|---|
| 4212 | }
 | 
|---|
| 4213 | 
 | 
|---|
| 4214 | 
 | 
|---|
| 4215 | void
 | 
|---|
| 4216 | xg_resolve_literals (insn, lit_sym)
 | 
|---|
| 4217 |      TInsn *insn;
 | 
|---|
| 4218 |      symbolS *lit_sym;
 | 
|---|
| 4219 | {
 | 
|---|
| 4220 |   symbolS *sym = get_special_literal_symbol ();
 | 
|---|
| 4221 |   int i;
 | 
|---|
| 4222 |   if (lit_sym == 0)
 | 
|---|
| 4223 |     return;
 | 
|---|
| 4224 |   assert (insn->insn_type == ITYPE_INSN);
 | 
|---|
| 4225 |   for (i = 0; i < insn->ntok; i++)
 | 
|---|
| 4226 |     if (insn->tok[i].X_add_symbol == sym)
 | 
|---|
| 4227 |       insn->tok[i].X_add_symbol = lit_sym;
 | 
|---|
| 4228 | 
 | 
|---|
| 4229 | }
 | 
|---|
| 4230 | 
 | 
|---|
| 4231 | 
 | 
|---|
| 4232 | void
 | 
|---|
| 4233 | xg_resolve_labels (insn, label_sym)
 | 
|---|
| 4234 |      TInsn *insn;
 | 
|---|
| 4235 |      symbolS *label_sym;
 | 
|---|
| 4236 | {
 | 
|---|
| 4237 |   symbolS *sym = get_special_label_symbol ();
 | 
|---|
| 4238 |   int i;
 | 
|---|
| 4239 |   /* assert(!insn->is_literal); */
 | 
|---|
| 4240 |   for (i = 0; i < insn->ntok; i++)
 | 
|---|
| 4241 |     if (insn->tok[i].X_add_symbol == sym)
 | 
|---|
| 4242 |       insn->tok[i].X_add_symbol = label_sym;
 | 
|---|
| 4243 | 
 | 
|---|
| 4244 | }
 | 
|---|
| 4245 | 
 | 
|---|
| 4246 | 
 | 
|---|
| 4247 | static void
 | 
|---|
| 4248 | xg_assemble_tokens (insn)
 | 
|---|
| 4249 |      /*const */ TInsn *insn;
 | 
|---|
| 4250 | {
 | 
|---|
| 4251 |   /* By the time we get here, there's not too much left to do. 
 | 
|---|
| 4252 |      1) Check our assumptions. 
 | 
|---|
| 4253 |      2) Check if the current instruction is "narrow". 
 | 
|---|
| 4254 |         If so, then finish the frag, create another one.
 | 
|---|
| 4255 |         We could also go back to change some previous
 | 
|---|
| 4256 |         "narrow" frags into no-change ones if we have more than
 | 
|---|
| 4257 |         MAX_NARROW_ALIGNMENT of them without alignment restrictions
 | 
|---|
| 4258 |         between them.
 | 
|---|
| 4259 | 
 | 
|---|
| 4260 |      Cases:
 | 
|---|
| 4261 |         1) It has constant operands and doesn't fit.
 | 
|---|
| 4262 |            Go ahead and assemble it so it will fail.
 | 
|---|
| 4263 |         2) It has constant operands that fit.
 | 
|---|
| 4264 |            If narrow and !is_specific_opcode,
 | 
|---|
| 4265 |               assemble it and put in a relocation
 | 
|---|
| 4266 |            else
 | 
|---|
| 4267 |               assemble it.
 | 
|---|
| 4268 |         3) It has a symbolic immediate operand
 | 
|---|
| 4269 |            a) Find the worst-case relaxation required
 | 
|---|
| 4270 |            b) Find the worst-case literal pool space required.
 | 
|---|
| 4271 |               Insert appropriate alignment & space in the literal.
 | 
|---|
| 4272 |               Assemble it.
 | 
|---|
| 4273 |               Add the relocation.  */
 | 
|---|
| 4274 | 
 | 
|---|
| 4275 |   assert (insn->insn_type == ITYPE_INSN);
 | 
|---|
| 4276 | 
 | 
|---|
| 4277 |   if (!tinsn_has_symbolic_operands (insn))
 | 
|---|
| 4278 |     {
 | 
|---|
| 4279 |       if (xg_is_narrow_insn (insn) && !insn->is_specific_opcode)
 | 
|---|
| 4280 |         {
 | 
|---|
| 4281 |           /* assemble it but add max required space */
 | 
|---|
| 4282 |           int max_size = xg_get_max_narrow_insn_size (insn->opcode);
 | 
|---|
| 4283 |           int min_size = xg_get_insn_size (insn);
 | 
|---|
| 4284 |           char *last_insn;
 | 
|---|
| 4285 |           assert (max_size == 3);
 | 
|---|
| 4286 |           /* make sure we have enough space to widen it */
 | 
|---|
| 4287 |           xg_force_frag_space (max_size);
 | 
|---|
| 4288 |           /* Output the instruction.  It may cause an error if some 
 | 
|---|
| 4289 |              operands do not fit.  */
 | 
|---|
| 4290 |           last_insn = frag_more (0);
 | 
|---|
| 4291 |           if (xg_emit_insn (insn, TRUE))
 | 
|---|
| 4292 |             as_warn (_("instruction with constant operands does not fit"));
 | 
|---|
| 4293 |           xg_finish_frag (last_insn, RELAX_NARROW, max_size - min_size, TRUE);
 | 
|---|
| 4294 |         }
 | 
|---|
| 4295 |       else
 | 
|---|
| 4296 |         {
 | 
|---|
| 4297 |           /* Assemble it.  No relocation needed.  */
 | 
|---|
| 4298 |           int max_size = xg_get_insn_size (insn);
 | 
|---|
| 4299 |           xg_force_frag_space (max_size);
 | 
|---|
| 4300 |           if (xg_emit_insn (insn, FALSE))
 | 
|---|
| 4301 |             as_warn (_("instruction with constant operands does not "
 | 
|---|
| 4302 |                        "fit without widening"));
 | 
|---|
| 4303 |           /* frag_more (max_size); */
 | 
|---|
| 4304 | 
 | 
|---|
| 4305 |           /* Special case for jx.  If the jx is the next to last
 | 
|---|
| 4306 |              instruction in a loop, we will add a NOP after it.  This
 | 
|---|
| 4307 |              avoids a hardware issue that could occur if the jx jumped
 | 
|---|
| 4308 |              to the next instruction.  */
 | 
|---|
| 4309 |           if (software_avoid_b_j_loop_end
 | 
|---|
| 4310 |               && is_jx_opcode (insn->opcode))
 | 
|---|
| 4311 |             {
 | 
|---|
| 4312 |               maybe_has_b_j_loop_end = TRUE;
 | 
|---|
| 4313 |               /* add 2 of these */
 | 
|---|
| 4314 |               frag_now->tc_frag_data.is_insn = TRUE;
 | 
|---|
| 4315 |               frag_var (rs_machine_dependent, 4, 4,
 | 
|---|
| 4316 |                         RELAX_ADD_NOP_IF_PRE_LOOP_END,
 | 
|---|
| 4317 |                         frag_now->fr_symbol, frag_now->fr_offset, NULL);
 | 
|---|
| 4318 |             }
 | 
|---|
| 4319 |         }
 | 
|---|
| 4320 |     }
 | 
|---|
| 4321 |   else
 | 
|---|
| 4322 |     {
 | 
|---|
| 4323 |       /* Need to assemble it with space for the relocation.  */
 | 
|---|
| 4324 |       if (!insn->is_specific_opcode)
 | 
|---|
| 4325 |         {
 | 
|---|
| 4326 |           /* Assemble it but add max required space.  */
 | 
|---|
| 4327 |           char *last_insn;
 | 
|---|
| 4328 |           int min_size = xg_get_insn_size (insn);
 | 
|---|
| 4329 |           int max_size = xg_get_max_insn_widen_size (insn->opcode);
 | 
|---|
| 4330 |           int max_literal_size =
 | 
|---|
| 4331 |             xg_get_max_insn_widen_literal_size (insn->opcode);
 | 
|---|
| 4332 | 
 | 
|---|
| 4333 | #if 0
 | 
|---|
| 4334 |           symbolS *immed_sym = xg_get_insn_immed_symbol (insn);
 | 
|---|
| 4335 |           set_frag_segment (frag_now, now_seg);
 | 
|---|
| 4336 | #endif /* 0 */
 | 
|---|
| 4337 | 
 | 
|---|
| 4338 |           /* Make sure we have enough space to widen the instruction. 
 | 
|---|
| 4339 |              This may open a new fragment.  */
 | 
|---|
| 4340 |           xg_force_frag_space (max_size);
 | 
|---|
| 4341 |           if (max_literal_size != 0)
 | 
|---|
| 4342 |             xg_assemble_literal_space (max_literal_size);
 | 
|---|
| 4343 | 
 | 
|---|
| 4344 |           /* Output the instruction.  It may cause an error if some 
 | 
|---|
| 4345 |              operands do not fit.  Emit the incomplete instruction.  */
 | 
|---|
| 4346 |           last_insn = frag_more (0);
 | 
|---|
| 4347 |           xg_emit_insn (insn, FALSE);
 | 
|---|
| 4348 | 
 | 
|---|
| 4349 |           xg_finish_frag (last_insn, RELAX_IMMED, max_size - min_size, TRUE);
 | 
|---|
| 4350 | 
 | 
|---|
| 4351 |           /* Special cases for loops:
 | 
|---|
| 4352 |              close_loop_end should be inserted AFTER short_loop.
 | 
|---|
| 4353 |              Make sure that CLOSE loops are processed BEFORE short_loops
 | 
|---|
| 4354 |              when converting them.  */
 | 
|---|
| 4355 | 
 | 
|---|
| 4356 |           /* "short_loop": add a NOP if the loop is < 4 bytes.  */
 | 
|---|
| 4357 |           if (software_avoid_short_loop
 | 
|---|
| 4358 |               && is_loop_opcode (insn->opcode))
 | 
|---|
| 4359 |             {
 | 
|---|
| 4360 |               maybe_has_short_loop = TRUE;
 | 
|---|
| 4361 |               frag_now->tc_frag_data.is_insn = TRUE;
 | 
|---|
| 4362 |               frag_var (rs_machine_dependent, 4, 4,
 | 
|---|
| 4363 |                         RELAX_ADD_NOP_IF_SHORT_LOOP,
 | 
|---|
| 4364 |                         frag_now->fr_symbol, frag_now->fr_offset, NULL);
 | 
|---|
| 4365 |               frag_now->tc_frag_data.is_insn = TRUE;
 | 
|---|
| 4366 |               frag_var (rs_machine_dependent, 4, 4,
 | 
|---|
| 4367 |                         RELAX_ADD_NOP_IF_SHORT_LOOP,
 | 
|---|
| 4368 |                         frag_now->fr_symbol, frag_now->fr_offset, NULL);
 | 
|---|
| 4369 |             }
 | 
|---|
| 4370 | 
 | 
|---|
| 4371 |           /* "close_loop_end": Add up to 12 bytes of NOPs to keep a
 | 
|---|
| 4372 |              loop at least 12 bytes away from another loop's loop
 | 
|---|
| 4373 |              end.  */
 | 
|---|
| 4374 |           if (software_avoid_close_loop_end
 | 
|---|
| 4375 |               && is_loop_opcode (insn->opcode))
 | 
|---|
| 4376 |             {
 | 
|---|
| 4377 |               maybe_has_close_loop_end = TRUE;
 | 
|---|
| 4378 |               frag_now->tc_frag_data.is_insn = TRUE;
 | 
|---|
| 4379 |               frag_var (rs_machine_dependent, 12, 12,
 | 
|---|
| 4380 |                         RELAX_ADD_NOP_IF_CLOSE_LOOP_END,
 | 
|---|
| 4381 |                         frag_now->fr_symbol, frag_now->fr_offset, NULL);
 | 
|---|
| 4382 |             }
 | 
|---|
| 4383 |         }
 | 
|---|
| 4384 |       else
 | 
|---|
| 4385 |         {
 | 
|---|
| 4386 |           /* Assemble it in place.  No expansion will be required, 
 | 
|---|
| 4387 |              but we'll still need a relocation record.  */
 | 
|---|
| 4388 |           int max_size = xg_get_insn_size (insn);
 | 
|---|
| 4389 |           xg_force_frag_space (max_size);
 | 
|---|
| 4390 |           if (xg_emit_insn (insn, TRUE))
 | 
|---|
| 4391 |             as_warn (_("instruction's constant operands do not fit"));
 | 
|---|
| 4392 |         }
 | 
|---|
| 4393 |     }
 | 
|---|
| 4394 | }
 | 
|---|
| 4395 | 
 | 
|---|
| 4396 | 
 | 
|---|
| 4397 | /* Return true if the instruction can write to the specified
 | 
|---|
| 4398 |    integer register.  */
 | 
|---|
| 4399 | 
 | 
|---|
| 4400 | static bfd_boolean
 | 
|---|
| 4401 | is_register_writer (insn, regset, regnum)
 | 
|---|
| 4402 |      const TInsn *insn;
 | 
|---|
| 4403 |      const char *regset;
 | 
|---|
| 4404 |      int regnum;
 | 
|---|
| 4405 | {
 | 
|---|
| 4406 |   int i;
 | 
|---|
| 4407 |   int num_ops;
 | 
|---|
| 4408 |   xtensa_isa isa = xtensa_default_isa;
 | 
|---|
| 4409 | 
 | 
|---|
| 4410 |   num_ops = xtensa_num_operands (isa, insn->opcode);
 | 
|---|
| 4411 | 
 | 
|---|
| 4412 |   for (i = 0; i < num_ops; i++)
 | 
|---|
| 4413 |     {
 | 
|---|
| 4414 |       xtensa_operand operand = xtensa_get_operand (isa, insn->opcode, i);
 | 
|---|
| 4415 |       char inout = xtensa_operand_inout (operand);
 | 
|---|
| 4416 | 
 | 
|---|
| 4417 |       if (inout == '>' || inout == '=')
 | 
|---|
| 4418 |         {
 | 
|---|
| 4419 |           if (strcmp (xtensa_operand_kind (operand), regset) == 0)
 | 
|---|
| 4420 |             {
 | 
|---|
| 4421 |               if ((insn->tok[i].X_op == O_register)
 | 
|---|
| 4422 |                   && (insn->tok[i].X_add_number == regnum))
 | 
|---|
| 4423 |                 return TRUE;
 | 
|---|
| 4424 |             }
 | 
|---|
| 4425 |         }
 | 
|---|
| 4426 |     }
 | 
|---|
| 4427 |   return FALSE;
 | 
|---|
| 4428 | }
 | 
|---|
| 4429 | 
 | 
|---|
| 4430 | 
 | 
|---|
| 4431 | static bfd_boolean
 | 
|---|
| 4432 | is_bad_loopend_opcode (tinsn)
 | 
|---|
| 4433 |      const TInsn * tinsn;
 | 
|---|
| 4434 | {
 | 
|---|
| 4435 |   xtensa_opcode opcode = tinsn->opcode;
 | 
|---|
| 4436 | 
 | 
|---|
| 4437 |   if (opcode == XTENSA_UNDEFINED)
 | 
|---|
| 4438 |     return FALSE;
 | 
|---|
| 4439 | 
 | 
|---|
| 4440 |   if (opcode == xtensa_call0_opcode
 | 
|---|
| 4441 |       || opcode == xtensa_callx0_opcode
 | 
|---|
| 4442 |       || opcode == xtensa_call4_opcode
 | 
|---|
| 4443 |       || opcode == xtensa_callx4_opcode
 | 
|---|
| 4444 |       || opcode == xtensa_call8_opcode
 | 
|---|
| 4445 |       || opcode == xtensa_callx8_opcode
 | 
|---|
| 4446 |       || opcode == xtensa_call12_opcode
 | 
|---|
| 4447 |       || opcode == xtensa_callx12_opcode
 | 
|---|
| 4448 |       || opcode == xtensa_isync_opcode
 | 
|---|
| 4449 |       || opcode == xtensa_ret_opcode
 | 
|---|
| 4450 |       || opcode == xtensa_ret_n_opcode
 | 
|---|
| 4451 |       || opcode == xtensa_retw_opcode
 | 
|---|
| 4452 |       || opcode == xtensa_retw_n_opcode
 | 
|---|
| 4453 |       || opcode == xtensa_waiti_opcode)
 | 
|---|
| 4454 |     return TRUE;
 | 
|---|
| 4455 |   
 | 
|---|
| 4456 |   /* An RSR of LCOUNT is illegal as the last opcode in a loop.  */
 | 
|---|
| 4457 |   if (opcode == xtensa_rsr_opcode
 | 
|---|
| 4458 |       && tinsn->ntok >= 2
 | 
|---|
| 4459 |       && tinsn->tok[1].X_op == O_constant
 | 
|---|
| 4460 |       && tinsn->tok[1].X_add_number == 2)
 | 
|---|
| 4461 |     return TRUE;
 | 
|---|
| 4462 | 
 | 
|---|
| 4463 |   return FALSE;
 | 
|---|
| 4464 | }
 | 
|---|
| 4465 | 
 | 
|---|
| 4466 | 
 | 
|---|
| 4467 | /* Labels that begin with ".Ln" or ".LM"  are unaligned.
 | 
|---|
| 4468 |    This allows the debugger to add unaligned labels.
 | 
|---|
| 4469 |    Also, the assembler generates stabs labels that need
 | 
|---|
| 4470 |    not be aligned:  FAKE_LABEL_NAME . {"F", "L", "endfunc"}.  */
 | 
|---|
| 4471 | 
 | 
|---|
| 4472 | bfd_boolean
 | 
|---|
| 4473 | is_unaligned_label (sym) 
 | 
|---|
| 4474 |      symbolS *sym; 
 | 
|---|
| 4475 | {
 | 
|---|
| 4476 |   const char *name = S_GET_NAME (sym);
 | 
|---|
| 4477 |   static size_t fake_size = 0;
 | 
|---|
| 4478 | 
 | 
|---|
| 4479 |   if (name
 | 
|---|
| 4480 |       && name[0] == '.'
 | 
|---|
| 4481 |       && name[1] == 'L' && (name[2] == 'n' || name[2] == 'M'))
 | 
|---|
| 4482 |     return TRUE;
 | 
|---|
| 4483 | 
 | 
|---|
| 4484 |   /* FAKE_LABEL_NAME followed by "F", "L" or "endfunc" */
 | 
|---|
| 4485 |   if (fake_size == 0)
 | 
|---|
| 4486 |     fake_size = strlen (FAKE_LABEL_NAME);
 | 
|---|
| 4487 | 
 | 
|---|
| 4488 |   if (name 
 | 
|---|
| 4489 |       && strncmp (FAKE_LABEL_NAME, name, fake_size) == 0
 | 
|---|
| 4490 |       && (name[fake_size] == 'F'
 | 
|---|
| 4491 |           || name[fake_size] == 'L'
 | 
|---|
| 4492 |           || (name[fake_size] == 'e'
 | 
|---|
| 4493 |               && strncmp ("endfunc", name+fake_size, 7) == 0)))
 | 
|---|
| 4494 |     return TRUE;
 | 
|---|
| 4495 | 
 | 
|---|
| 4496 |   return FALSE;
 | 
|---|
| 4497 | }
 | 
|---|
| 4498 | 
 | 
|---|
| 4499 | 
 | 
|---|
| 4500 | fragS *
 | 
|---|
| 4501 | next_non_empty_frag (fragP)
 | 
|---|
| 4502 |      const fragS *fragP;
 | 
|---|
| 4503 | {
 | 
|---|
| 4504 |   fragS *next_fragP = fragP->fr_next;
 | 
|---|
| 4505 | 
 | 
|---|
| 4506 |   /* Sometimes an empty will end up here due storage allocation issues. 
 | 
|---|
| 4507 |      So we have to skip until we find something legit.  */
 | 
|---|
| 4508 |   while (next_fragP && next_fragP->fr_fix == 0)
 | 
|---|
| 4509 |     next_fragP = next_fragP->fr_next;
 | 
|---|
| 4510 | 
 | 
|---|
| 4511 |   if (next_fragP == NULL || next_fragP->fr_fix == 0)
 | 
|---|
| 4512 |     return NULL;
 | 
|---|
| 4513 | 
 | 
|---|
| 4514 |   return next_fragP;
 | 
|---|
| 4515 | }
 | 
|---|
| 4516 | 
 | 
|---|
| 4517 | 
 | 
|---|
| 4518 | xtensa_opcode
 | 
|---|
| 4519 | next_frag_opcode (fragP)
 | 
|---|
| 4520 |      const fragS * fragP;
 | 
|---|
| 4521 | {
 | 
|---|
| 4522 |   const fragS *next_fragP = next_non_empty_frag (fragP);
 | 
|---|
| 4523 |   static xtensa_insnbuf insnbuf = NULL;
 | 
|---|
| 4524 |   xtensa_isa isa = xtensa_default_isa;
 | 
|---|
| 4525 | 
 | 
|---|
| 4526 |   if (!insnbuf)
 | 
|---|
| 4527 |     insnbuf = xtensa_insnbuf_alloc (isa);
 | 
|---|
| 4528 | 
 | 
|---|
| 4529 |   if (next_fragP == NULL)
 | 
|---|
| 4530 |     return XTENSA_UNDEFINED;
 | 
|---|
| 4531 | 
 | 
|---|
| 4532 |   xtensa_insnbuf_from_chars (isa, insnbuf, next_fragP->fr_literal);
 | 
|---|
| 4533 |   return xtensa_decode_insn (isa, insnbuf);
 | 
|---|
| 4534 | }
 | 
|---|
| 4535 | 
 | 
|---|
| 4536 | 
 | 
|---|
| 4537 | /* Return true if the target frag is one of the next non-empty frags.  */
 | 
|---|
| 4538 | 
 | 
|---|
| 4539 | bfd_boolean
 | 
|---|
| 4540 | is_next_frag_target (fragP, target)
 | 
|---|
| 4541 |      const fragS *fragP;
 | 
|---|
| 4542 |      const fragS *target;
 | 
|---|
| 4543 | {
 | 
|---|
| 4544 |   if (fragP == NULL)
 | 
|---|
| 4545 |     return FALSE;
 | 
|---|
| 4546 | 
 | 
|---|
| 4547 |   for (; fragP; fragP = fragP->fr_next)
 | 
|---|
| 4548 |     {
 | 
|---|
| 4549 |       if (fragP == target)
 | 
|---|
| 4550 |         return TRUE;
 | 
|---|
| 4551 |       if (fragP->fr_fix != 0)
 | 
|---|
| 4552 |         return FALSE;
 | 
|---|
| 4553 |       if (fragP->fr_type == rs_fill && fragP->fr_offset != 0)
 | 
|---|
| 4554 |         return FALSE;
 | 
|---|
| 4555 |       if ((fragP->fr_type == rs_align || fragP->fr_type == rs_align_code)
 | 
|---|
| 4556 |           && ((fragP->fr_address % (1 << fragP->fr_offset)) != 0))
 | 
|---|
| 4557 |         return FALSE;
 | 
|---|
| 4558 |       if (fragP->fr_type == rs_space)
 | 
|---|
| 4559 |         return FALSE;
 | 
|---|
| 4560 |     }
 | 
|---|
| 4561 |   return FALSE;
 | 
|---|
| 4562 | }
 | 
|---|
| 4563 | 
 | 
|---|
| 4564 | 
 | 
|---|
| 4565 | /* If the next legit fragment is an end-of-loop marker,
 | 
|---|
| 4566 |    switch its state so it will instantiate a NOP.  */
 | 
|---|
| 4567 | 
 | 
|---|
| 4568 | static void
 | 
|---|
| 4569 | update_next_frag_nop_state (fragP)
 | 
|---|
| 4570 |      fragS *fragP;
 | 
|---|
| 4571 | {
 | 
|---|
| 4572 |   fragS *next_fragP = fragP->fr_next;
 | 
|---|
| 4573 | 
 | 
|---|
| 4574 |   while (next_fragP && next_fragP->fr_fix == 0)
 | 
|---|
| 4575 |     {
 | 
|---|
| 4576 |       if (next_fragP->fr_type == rs_machine_dependent
 | 
|---|
| 4577 |           && next_fragP->fr_subtype == RELAX_LOOP_END)
 | 
|---|
| 4578 |         {
 | 
|---|
| 4579 |           next_fragP->fr_subtype = RELAX_LOOP_END_ADD_NOP;
 | 
|---|
| 4580 |           return;
 | 
|---|
| 4581 |         }
 | 
|---|
| 4582 |       next_fragP = next_fragP->fr_next;
 | 
|---|
| 4583 |     }
 | 
|---|
| 4584 | }
 | 
|---|
| 4585 | 
 | 
|---|
| 4586 | 
 | 
|---|
| 4587 | static bfd_boolean
 | 
|---|
| 4588 | next_frag_is_branch_target (fragP)
 | 
|---|
| 4589 |      const fragS *fragP;
 | 
|---|
| 4590 | {
 | 
|---|
| 4591 |   /* Sometimes an empty will end up here due storage allocation issues,
 | 
|---|
| 4592 |      so we have to skip until we find something legit.  */
 | 
|---|
| 4593 |   for (fragP = fragP->fr_next; fragP; fragP = fragP->fr_next)
 | 
|---|
| 4594 |     {
 | 
|---|
| 4595 |       if (fragP->tc_frag_data.is_branch_target)
 | 
|---|
| 4596 |         return TRUE;
 | 
|---|
| 4597 |       if (fragP->fr_fix != 0)
 | 
|---|
| 4598 |         break;
 | 
|---|
| 4599 |     }
 | 
|---|
| 4600 |   return FALSE;
 | 
|---|
| 4601 | }
 | 
|---|
| 4602 | 
 | 
|---|
| 4603 | 
 | 
|---|
| 4604 | static bfd_boolean
 | 
|---|
| 4605 | next_frag_is_loop_target (fragP)
 | 
|---|
| 4606 |      const fragS *fragP;
 | 
|---|
| 4607 | {
 | 
|---|
| 4608 |   /* Sometimes an empty will end up here due storage allocation issues. 
 | 
|---|
| 4609 |      So we have to skip until we find something legit. */
 | 
|---|
| 4610 |   for (fragP = fragP->fr_next; fragP; fragP = fragP->fr_next)
 | 
|---|
| 4611 |     {
 | 
|---|
| 4612 |       if (fragP->tc_frag_data.is_loop_target)
 | 
|---|
| 4613 |         return TRUE;
 | 
|---|
| 4614 |       if (fragP->fr_fix != 0)
 | 
|---|
| 4615 |         break;
 | 
|---|
| 4616 |     }
 | 
|---|
| 4617 |   return FALSE;
 | 
|---|
| 4618 | }
 | 
|---|
| 4619 | 
 | 
|---|
| 4620 | 
 | 
|---|
| 4621 | static addressT
 | 
|---|
| 4622 | next_frag_pre_opcode_bytes (fragp)
 | 
|---|
| 4623 |      const fragS *fragp;
 | 
|---|
| 4624 | {
 | 
|---|
| 4625 |   const fragS *next_fragp = fragp->fr_next;
 | 
|---|
| 4626 | 
 | 
|---|
| 4627 |   xtensa_opcode next_opcode = next_frag_opcode (fragp);
 | 
|---|
| 4628 |   if (!is_loop_opcode (next_opcode))
 | 
|---|
| 4629 |     return 0;
 | 
|---|
| 4630 | 
 | 
|---|
| 4631 |   /* Sometimes an empty will end up here due storage allocation issues.
 | 
|---|
| 4632 |      So we have to skip until we find something legit.  */
 | 
|---|
| 4633 |   while (next_fragp->fr_fix == 0)
 | 
|---|
| 4634 |     next_fragp = next_fragp->fr_next;
 | 
|---|
| 4635 | 
 | 
|---|
| 4636 |   if (next_fragp->fr_type != rs_machine_dependent)
 | 
|---|
| 4637 |     return 0;
 | 
|---|
| 4638 | 
 | 
|---|
| 4639 |   /* There is some implicit knowledge encoded in here.
 | 
|---|
| 4640 |      The LOOP instructions that are NOT RELAX_IMMED have
 | 
|---|
| 4641 |      been relaxed.  */
 | 
|---|
| 4642 |   if (next_fragp->fr_subtype > RELAX_IMMED)
 | 
|---|
| 4643 |       return get_expanded_loop_offset (next_opcode);
 | 
|---|
| 4644 | 
 | 
|---|
| 4645 |   return 0;
 | 
|---|
| 4646 | }
 | 
|---|
| 4647 | 
 | 
|---|
| 4648 | 
 | 
|---|
| 4649 | /* Mark a location where we can later insert literal frags.  Update
 | 
|---|
| 4650 |    the section's literal_pool_loc, so subsequent literals can be
 | 
|---|
| 4651 |    placed nearest to their use.  */
 | 
|---|
| 4652 | 
 | 
|---|
| 4653 | static void
 | 
|---|
| 4654 | xtensa_mark_literal_pool_location (move_labels)
 | 
|---|
| 4655 |      bfd_boolean move_labels;
 | 
|---|
| 4656 | {
 | 
|---|
| 4657 |   /* Any labels pointing to the current location need
 | 
|---|
| 4658 |      to be adjusted to after the literal pool.  */
 | 
|---|
| 4659 |   emit_state s;
 | 
|---|
| 4660 |   fragS *label_target = frag_now;
 | 
|---|
| 4661 |   fragS *pool_location;
 | 
|---|
| 4662 |   offsetT label_offset = frag_now_fix ();
 | 
|---|
| 4663 | 
 | 
|---|
| 4664 |   frag_align (2, 0, 0);
 | 
|---|
| 4665 | 
 | 
|---|
| 4666 |   /* We stash info in the fr_var of these frags
 | 
|---|
| 4667 |      so we can later move the literal's fixes into this 
 | 
|---|
| 4668 |      frchain's fix list.  We can use fr_var because fr_var's
 | 
|---|
| 4669 |      interpretation depends solely on the fr_type and subtype.  */
 | 
|---|
| 4670 |   pool_location = frag_now;
 | 
|---|
| 4671 |   frag_variant (rs_machine_dependent, 0, (int) frchain_now, 
 | 
|---|
| 4672 |                 RELAX_LITERAL_POOL_BEGIN, NULL, 0, NULL);
 | 
|---|
| 4673 |   frag_variant (rs_machine_dependent, 0, (int) now_seg, 
 | 
|---|
| 4674 |                 RELAX_LITERAL_POOL_END, NULL, 0, NULL);
 | 
|---|
| 4675 | 
 | 
|---|
| 4676 |   /* Now put a frag into the literal pool that points to this location.  */
 | 
|---|
| 4677 |   set_literal_pool_location (now_seg, pool_location);
 | 
|---|
| 4678 |   xtensa_switch_to_literal_fragment (&s);
 | 
|---|
| 4679 | 
 | 
|---|
| 4680 |   /* Close whatever frag is there.  */
 | 
|---|
| 4681 |   frag_variant (rs_fill, 0, 0, 0, NULL, 0, NULL);
 | 
|---|
| 4682 |   frag_now->tc_frag_data.literal_frag = pool_location;
 | 
|---|
| 4683 |   frag_variant (rs_fill, 0, 0, 0, NULL, 0, NULL);
 | 
|---|
| 4684 |   xtensa_restore_emit_state (&s);
 | 
|---|
| 4685 |   if (move_labels)
 | 
|---|
| 4686 |     xtensa_move_labels (label_target, label_offset, frag_now, 0);
 | 
|---|
| 4687 | }
 | 
|---|
| 4688 | 
 | 
|---|
| 4689 | 
 | 
|---|
| 4690 | static void
 | 
|---|
| 4691 | xtensa_move_labels (old_frag, old_offset, new_frag, new_offset)
 | 
|---|
| 4692 |      fragS *old_frag;
 | 
|---|
| 4693 |      valueT old_offset;
 | 
|---|
| 4694 |      fragS *new_frag ATTRIBUTE_UNUSED;
 | 
|---|
| 4695 |      valueT new_offset;
 | 
|---|
| 4696 | {
 | 
|---|
| 4697 |   symbolS *old_sym;
 | 
|---|
| 4698 | 
 | 
|---|
| 4699 |   /* Repeat until there are no more.... */
 | 
|---|
| 4700 |   for (old_sym = xtensa_find_label (old_frag, old_offset, TRUE);
 | 
|---|
| 4701 |        old_sym;
 | 
|---|
| 4702 |        old_sym = xtensa_find_label (old_frag, old_offset, TRUE))
 | 
|---|
| 4703 |     {
 | 
|---|
| 4704 |       S_SET_VALUE (old_sym, (valueT) new_offset);
 | 
|---|
| 4705 |       symbol_set_frag (old_sym, frag_now);
 | 
|---|
| 4706 |     }
 | 
|---|
| 4707 | }
 | 
|---|
| 4708 | 
 | 
|---|
| 4709 | 
 | 
|---|
| 4710 | /* Assemble a NOP of the requested size in the buffer.  User must have
 | 
|---|
| 4711 |    allocated "buf" with at least "size" bytes.  */
 | 
|---|
| 4712 | 
 | 
|---|
| 4713 | void
 | 
|---|
| 4714 | assemble_nop (size, buf)
 | 
|---|
| 4715 |      size_t size;
 | 
|---|
| 4716 |      char *buf;
 | 
|---|
| 4717 | {
 | 
|---|
| 4718 |   static xtensa_insnbuf insnbuf = NULL;
 | 
|---|
| 4719 |   TInsn t_insn;
 | 
|---|
| 4720 |   if (!insnbuf)
 | 
|---|
| 4721 |     insnbuf = xtensa_insnbuf_alloc (xtensa_default_isa);
 | 
|---|
| 4722 | 
 | 
|---|
| 4723 |   tinsn_init (&t_insn);
 | 
|---|
| 4724 |   switch (size)
 | 
|---|
| 4725 |     {
 | 
|---|
| 4726 |     case 2:
 | 
|---|
| 4727 |       t_insn.opcode = xtensa_nop_n_opcode;
 | 
|---|
| 4728 |       t_insn.ntok = 0;
 | 
|---|
| 4729 |       if (t_insn.opcode == XTENSA_UNDEFINED)
 | 
|---|
| 4730 |         as_fatal (_("opcode 'NOP.N' unavailable in this configuration"));
 | 
|---|
| 4731 |       tinsn_to_insnbuf (&t_insn, insnbuf);
 | 
|---|
| 4732 |       xtensa_insnbuf_to_chars (xtensa_default_isa, insnbuf, buf);
 | 
|---|
| 4733 |       break;
 | 
|---|
| 4734 | 
 | 
|---|
| 4735 |     case 3:
 | 
|---|
| 4736 |       t_insn.opcode = xtensa_or_opcode;
 | 
|---|
| 4737 |       assert (t_insn.opcode != XTENSA_UNDEFINED);
 | 
|---|
| 4738 |       if (t_insn.opcode == XTENSA_UNDEFINED)
 | 
|---|
| 4739 |         as_fatal (_("opcode 'OR' unavailable in this configuration"));
 | 
|---|
| 4740 |       set_expr_const (&t_insn.tok[0], 1);
 | 
|---|
| 4741 |       set_expr_const (&t_insn.tok[1], 1);
 | 
|---|
| 4742 |       set_expr_const (&t_insn.tok[2], 1);
 | 
|---|
| 4743 |       t_insn.ntok = 3;
 | 
|---|
| 4744 |       tinsn_to_insnbuf (&t_insn, insnbuf);
 | 
|---|
| 4745 |       xtensa_insnbuf_to_chars (xtensa_default_isa, insnbuf, buf);
 | 
|---|
| 4746 |       break;
 | 
|---|
| 4747 | 
 | 
|---|
| 4748 |     default:
 | 
|---|
| 4749 |       as_fatal (_("invalid %d-byte NOP requested"), size);
 | 
|---|
| 4750 |     }
 | 
|---|
| 4751 | }
 | 
|---|
| 4752 | 
 | 
|---|
| 4753 | 
 | 
|---|
| 4754 | /* Return the number of bytes for the offset of the expanded loop
 | 
|---|
| 4755 |    instruction.  This should be incorporated into the relaxation
 | 
|---|
| 4756 |    specification but is hard-coded here.  This is used to auto-align
 | 
|---|
| 4757 |    the loop instruction.  It is invalid to call this function if the
 | 
|---|
| 4758 |    configuration does not have loops or if the opcode is not a loop
 | 
|---|
| 4759 |    opcode.  */
 | 
|---|
| 4760 | 
 | 
|---|
| 4761 | static addressT
 | 
|---|
| 4762 | get_expanded_loop_offset (opcode)
 | 
|---|
| 4763 |      xtensa_opcode opcode;
 | 
|---|
| 4764 | {
 | 
|---|
| 4765 |   /* This is the OFFSET of the loop instruction in the expanded loop.
 | 
|---|
| 4766 |      This MUST correspond directly to the specification of the loop
 | 
|---|
| 4767 |      expansion.  It will be validated on fragment conversion.  */
 | 
|---|
| 4768 |   if (opcode == XTENSA_UNDEFINED)
 | 
|---|
| 4769 |     as_fatal (_("get_expanded_loop_offset: undefined opcode"));
 | 
|---|
| 4770 |   if (opcode == xtensa_loop_opcode)
 | 
|---|
| 4771 |     return 0;
 | 
|---|
| 4772 |   if (opcode == xtensa_loopnez_opcode)
 | 
|---|
| 4773 |     return 3;
 | 
|---|
| 4774 |   if (opcode == xtensa_loopgtz_opcode)
 | 
|---|
| 4775 |     return 6;
 | 
|---|
| 4776 |   as_fatal (_("get_expanded_loop_offset: invalid opcode"));
 | 
|---|
| 4777 |   return 0;
 | 
|---|
| 4778 | }
 | 
|---|
| 4779 | 
 | 
|---|
| 4780 | 
 | 
|---|
| 4781 | fragS *
 | 
|---|
| 4782 | get_literal_pool_location (seg)
 | 
|---|
| 4783 |      segT seg;
 | 
|---|
| 4784 | {
 | 
|---|
| 4785 |   return seg_info (seg)->tc_segment_info_data.literal_pool_loc;
 | 
|---|
| 4786 | }
 | 
|---|
| 4787 | 
 | 
|---|
| 4788 | 
 | 
|---|
| 4789 | static void
 | 
|---|
| 4790 | set_literal_pool_location (seg, literal_pool_loc)
 | 
|---|
| 4791 |      segT seg;
 | 
|---|
| 4792 |      fragS *literal_pool_loc;
 | 
|---|
| 4793 | {
 | 
|---|
| 4794 |   seg_info (seg)->tc_segment_info_data.literal_pool_loc = literal_pool_loc;
 | 
|---|
| 4795 | }
 | 
|---|
| 4796 | 
 | 
|---|
| 4797 |  | 
|---|
| 4798 | 
 | 
|---|
| 4799 | /* External Functions and Other GAS Hooks.  */
 | 
|---|
| 4800 | 
 | 
|---|
| 4801 | const char *
 | 
|---|
| 4802 | xtensa_target_format ()
 | 
|---|
| 4803 | {
 | 
|---|
| 4804 |   return (target_big_endian ? "elf32-xtensa-be" : "elf32-xtensa-le");
 | 
|---|
| 4805 | }
 | 
|---|
| 4806 | 
 | 
|---|
| 4807 | 
 | 
|---|
| 4808 | void
 | 
|---|
| 4809 | xtensa_file_arch_init (abfd)
 | 
|---|
| 4810 |      bfd *abfd;
 | 
|---|
| 4811 | {
 | 
|---|
| 4812 |   bfd_set_private_flags (abfd, 0x100 | 0x200);
 | 
|---|
| 4813 | }
 | 
|---|
| 4814 | 
 | 
|---|
| 4815 | 
 | 
|---|
| 4816 | void
 | 
|---|
| 4817 | md_number_to_chars (buf, val, n)
 | 
|---|
| 4818 |      char *buf;
 | 
|---|
| 4819 |      valueT val;
 | 
|---|
| 4820 |      int n;
 | 
|---|
| 4821 | {
 | 
|---|
| 4822 |   if (target_big_endian)
 | 
|---|
| 4823 |     number_to_chars_bigendian (buf, val, n);
 | 
|---|
| 4824 |   else
 | 
|---|
| 4825 |     number_to_chars_littleendian (buf, val, n);
 | 
|---|
| 4826 | }
 | 
|---|
| 4827 | 
 | 
|---|
| 4828 | 
 | 
|---|
| 4829 | /* This function is called once, at assembler startup time.  It should
 | 
|---|
| 4830 |    set up all the tables, etc. that the MD part of the assembler will
 | 
|---|
| 4831 |    need.  */
 | 
|---|
| 4832 | 
 | 
|---|
| 4833 | void
 | 
|---|
| 4834 | md_begin ()
 | 
|---|
| 4835 | {
 | 
|---|
| 4836 |   segT current_section = now_seg;
 | 
|---|
| 4837 |   int current_subsec = now_subseg;
 | 
|---|
| 4838 |   xtensa_isa isa;
 | 
|---|
| 4839 | 
 | 
|---|
| 4840 | #if STATIC_LIBISA
 | 
|---|
| 4841 |   isa = xtensa_isa_init ();
 | 
|---|
| 4842 | #else
 | 
|---|
| 4843 |   /* ISA was already initialized by xtensa_init().  */
 | 
|---|
| 4844 |   isa = xtensa_default_isa;
 | 
|---|
| 4845 | #endif
 | 
|---|
| 4846 | 
 | 
|---|
| 4847 |   /* Set  up the .literal, .fini.literal and .init.literal sections.  */
 | 
|---|
| 4848 |   memset (&default_lit_sections, 0, sizeof (default_lit_sections));
 | 
|---|
| 4849 |   default_lit_sections.init_lit_seg_name = INIT_LITERAL_SECTION_NAME;
 | 
|---|
| 4850 |   default_lit_sections.fini_lit_seg_name = FINI_LITERAL_SECTION_NAME;
 | 
|---|
| 4851 |   default_lit_sections.lit_seg_name = LITERAL_SECTION_NAME;
 | 
|---|
| 4852 | 
 | 
|---|
| 4853 |   subseg_set (current_section, current_subsec);
 | 
|---|
| 4854 | 
 | 
|---|
| 4855 |   xtensa_addi_opcode = xtensa_opcode_lookup (isa, "addi");
 | 
|---|
| 4856 |   xtensa_addmi_opcode = xtensa_opcode_lookup (isa, "addmi");
 | 
|---|
| 4857 |   xtensa_call0_opcode = xtensa_opcode_lookup (isa, "call0");
 | 
|---|
| 4858 |   xtensa_call4_opcode = xtensa_opcode_lookup (isa, "call4");
 | 
|---|
| 4859 |   xtensa_call8_opcode = xtensa_opcode_lookup (isa, "call8");
 | 
|---|
| 4860 |   xtensa_call12_opcode = xtensa_opcode_lookup (isa, "call12");
 | 
|---|
| 4861 |   xtensa_callx0_opcode = xtensa_opcode_lookup (isa, "callx0");
 | 
|---|
| 4862 |   xtensa_callx4_opcode = xtensa_opcode_lookup (isa, "callx4");
 | 
|---|
| 4863 |   xtensa_callx8_opcode = xtensa_opcode_lookup (isa, "callx8");
 | 
|---|
| 4864 |   xtensa_callx12_opcode = xtensa_opcode_lookup (isa, "callx12");
 | 
|---|
| 4865 |   xtensa_entry_opcode = xtensa_opcode_lookup (isa, "entry");
 | 
|---|
| 4866 |   xtensa_isync_opcode = xtensa_opcode_lookup (isa, "isync");
 | 
|---|
| 4867 |   xtensa_j_opcode = xtensa_opcode_lookup (isa, "j");
 | 
|---|
| 4868 |   xtensa_jx_opcode = xtensa_opcode_lookup (isa, "jx");
 | 
|---|
| 4869 |   xtensa_loop_opcode = xtensa_opcode_lookup (isa, "loop");
 | 
|---|
| 4870 |   xtensa_loopnez_opcode = xtensa_opcode_lookup (isa, "loopnez");
 | 
|---|
| 4871 |   xtensa_loopgtz_opcode = xtensa_opcode_lookup (isa, "loopgtz");
 | 
|---|
| 4872 |   xtensa_nop_n_opcode = xtensa_opcode_lookup (isa, "nop.n");
 | 
|---|
| 4873 |   xtensa_or_opcode = xtensa_opcode_lookup (isa, "or");
 | 
|---|
| 4874 |   xtensa_ret_opcode = xtensa_opcode_lookup (isa, "ret");
 | 
|---|
| 4875 |   xtensa_ret_n_opcode = xtensa_opcode_lookup (isa, "ret.n");
 | 
|---|
| 4876 |   xtensa_retw_opcode = xtensa_opcode_lookup (isa, "retw");
 | 
|---|
| 4877 |   xtensa_retw_n_opcode = xtensa_opcode_lookup (isa, "retw.n");
 | 
|---|
| 4878 |   xtensa_rsr_opcode = xtensa_opcode_lookup (isa, "rsr");
 | 
|---|
| 4879 |   xtensa_waiti_opcode = xtensa_opcode_lookup (isa, "waiti");
 | 
|---|
| 4880 | }
 | 
|---|
| 4881 | 
 | 
|---|
| 4882 | 
 | 
|---|
| 4883 | /* tc_frob_label hook */
 | 
|---|
| 4884 | 
 | 
|---|
| 4885 | void
 | 
|---|
| 4886 | xtensa_frob_label (sym)
 | 
|---|
| 4887 |      symbolS *sym;
 | 
|---|
| 4888 | {
 | 
|---|
| 4889 |   xtensa_define_label (sym);
 | 
|---|
| 4890 |   if (is_loop_target_label (sym) 
 | 
|---|
| 4891 |       && (get_last_insn_flags (now_seg, now_subseg)
 | 
|---|
| 4892 |           & FLAG_IS_BAD_LOOPEND) != 0)
 | 
|---|
| 4893 |     as_bad (_("invalid last instruction for a zero-overhead loop"));
 | 
|---|
| 4894 | 
 | 
|---|
| 4895 |   /* No target aligning in the absolute section.  */
 | 
|---|
| 4896 |   if (now_seg != absolute_section && align_targets
 | 
|---|
| 4897 |       && !is_unaligned_label (sym))
 | 
|---|
| 4898 |     {
 | 
|---|
| 4899 |       fragS *old_frag = frag_now;
 | 
|---|
| 4900 |       offsetT old_offset = frag_now_fix ();
 | 
|---|
| 4901 |       if (frag_now->tc_frag_data.is_literal)
 | 
|---|
| 4902 |         return;
 | 
|---|
| 4903 |       /* frag_now->tc_frag_data.is_insn = TRUE; */
 | 
|---|
| 4904 |       frag_var (rs_machine_dependent, 4, 4,
 | 
|---|
| 4905 |                 RELAX_DESIRE_ALIGN_IF_TARGET,
 | 
|---|
| 4906 |                 frag_now->fr_symbol, frag_now->fr_offset, NULL);
 | 
|---|
| 4907 |       xtensa_move_labels (old_frag, old_offset, frag_now, 0);
 | 
|---|
| 4908 |       /* Once we know whether or not the label is a branch target
 | 
|---|
| 4909 |          We will suppress some of these alignments.  */
 | 
|---|
| 4910 |     }
 | 
|---|
| 4911 | }
 | 
|---|
| 4912 | 
 | 
|---|
| 4913 | 
 | 
|---|
| 4914 | /* md_flush_pending_output hook */
 | 
|---|
| 4915 | 
 | 
|---|
| 4916 | void
 | 
|---|
| 4917 | xtensa_flush_pending_output ()
 | 
|---|
| 4918 | {
 | 
|---|
| 4919 |   /* If there is a non-zero instruction fragment, close it.  */
 | 
|---|
| 4920 |   if (frag_now_fix () != 0 && frag_now->tc_frag_data.is_insn)
 | 
|---|
| 4921 |     {
 | 
|---|
| 4922 |       frag_wane (frag_now);
 | 
|---|
| 4923 |       frag_new (0);
 | 
|---|
| 4924 |     }
 | 
|---|
| 4925 |   frag_now->tc_frag_data.is_insn = FALSE;
 | 
|---|
| 4926 | }
 | 
|---|
| 4927 | 
 | 
|---|
| 4928 | 
 | 
|---|
| 4929 | void
 | 
|---|
| 4930 | md_assemble (str)
 | 
|---|
| 4931 |      char *str;
 | 
|---|
| 4932 | {
 | 
|---|
| 4933 |   xtensa_isa isa = xtensa_default_isa;
 | 
|---|
| 4934 |   char *opname;
 | 
|---|
| 4935 |   unsigned opnamelen;
 | 
|---|
| 4936 |   bfd_boolean has_underbar = FALSE;
 | 
|---|
| 4937 |   char *arg_strings[MAX_INSN_ARGS]; 
 | 
|---|
| 4938 |   int num_args;
 | 
|---|
| 4939 |   IStack istack;                /* Put instructions into here.  */
 | 
|---|
| 4940 |   TInsn orig_insn;              /* Original instruction from the input.  */
 | 
|---|
| 4941 |   int i;
 | 
|---|
| 4942 |   symbolS *lit_sym = NULL;
 | 
|---|
| 4943 | 
 | 
|---|
| 4944 |   if (frag_now->tc_frag_data.is_literal)
 | 
|---|
| 4945 |     {
 | 
|---|
| 4946 |       static bfd_boolean reported = 0;
 | 
|---|
| 4947 |       if (reported < 4)
 | 
|---|
| 4948 |         as_bad (_("cannot assemble '%s' into a literal fragment"), str);
 | 
|---|
| 4949 |       if (reported == 3)
 | 
|---|
| 4950 |         as_bad (_("..."));
 | 
|---|
| 4951 |       reported++;
 | 
|---|
| 4952 |       return;
 | 
|---|
| 4953 |     }
 | 
|---|
| 4954 | 
 | 
|---|
| 4955 |   istack_init (&istack);
 | 
|---|
| 4956 |   tinsn_init (&orig_insn);
 | 
|---|
| 4957 | 
 | 
|---|
| 4958 |   /* Split off the opcode.  */
 | 
|---|
| 4959 |   opnamelen = strspn (str, "abcdefghijklmnopqrstuvwxyz_/0123456789.");
 | 
|---|
| 4960 |   opname = xmalloc (opnamelen + 1);
 | 
|---|
| 4961 |   memcpy (opname, str, opnamelen);
 | 
|---|
| 4962 |   opname[opnamelen] = '\0';
 | 
|---|
| 4963 | 
 | 
|---|
| 4964 |   num_args = tokenize_arguments (arg_strings, str + opnamelen);
 | 
|---|
| 4965 |   if (num_args == -1)
 | 
|---|
| 4966 |     {
 | 
|---|
| 4967 |       as_bad (_("syntax error"));
 | 
|---|
| 4968 |       return;
 | 
|---|
| 4969 |     }
 | 
|---|
| 4970 | 
 | 
|---|
| 4971 |   if (xg_translate_idioms (&opname, &num_args, arg_strings))
 | 
|---|
| 4972 |     return;
 | 
|---|
| 4973 | 
 | 
|---|
| 4974 |   /* Check for an underbar prefix.  */
 | 
|---|
| 4975 |   if (*opname == '_')
 | 
|---|
| 4976 |     {
 | 
|---|
| 4977 |       has_underbar = TRUE;
 | 
|---|
| 4978 |       opname += 1;
 | 
|---|
| 4979 |     }
 | 
|---|
| 4980 | 
 | 
|---|
| 4981 |   orig_insn.insn_type = ITYPE_INSN;
 | 
|---|
| 4982 |   orig_insn.ntok = 0;
 | 
|---|
| 4983 |   orig_insn.is_specific_opcode = (has_underbar || !use_generics ());
 | 
|---|
| 4984 |   specific_opcode = orig_insn.is_specific_opcode;
 | 
|---|
| 4985 | 
 | 
|---|
| 4986 |   orig_insn.opcode = xtensa_opcode_lookup (isa, opname);
 | 
|---|
| 4987 |   if (orig_insn.opcode == XTENSA_UNDEFINED)
 | 
|---|
| 4988 |     {
 | 
|---|
| 4989 |       as_bad (_("unknown opcode %s"), opname);
 | 
|---|
| 4990 |       return;
 | 
|---|
| 4991 |     }
 | 
|---|
| 4992 | 
 | 
|---|
| 4993 |   if (frag_now_fix () != 0 && !frag_now->tc_frag_data.is_insn)
 | 
|---|
| 4994 |     {
 | 
|---|
| 4995 |       frag_wane (frag_now);
 | 
|---|
| 4996 |       frag_new (0);
 | 
|---|
| 4997 |     }
 | 
|---|
| 4998 | 
 | 
|---|
| 4999 |   if (software_a0_b_retw_interlock)
 | 
|---|
| 5000 |     {
 | 
|---|
| 5001 |       if ((get_last_insn_flags (now_seg, now_subseg) & FLAG_IS_A0_WRITER) != 0
 | 
|---|
| 5002 |           && is_conditional_branch_opcode (orig_insn.opcode))
 | 
|---|
| 5003 |         {
 | 
|---|
| 5004 |           has_a0_b_retw = TRUE;
 | 
|---|
| 5005 | 
 | 
|---|
| 5006 |           /* Mark this fragment with the special RELAX_ADD_NOP_IF_A0_B_RETW.
 | 
|---|
| 5007 |              After the first assembly pass we will check all of them and
 | 
|---|
| 5008 |              add a nop if needed.  */
 | 
|---|
| 5009 |           frag_now->tc_frag_data.is_insn = TRUE;
 | 
|---|
| 5010 |           frag_var (rs_machine_dependent, 4, 4,
 | 
|---|
| 5011 |                     RELAX_ADD_NOP_IF_A0_B_RETW,
 | 
|---|
| 5012 |                     frag_now->fr_symbol, frag_now->fr_offset, NULL);
 | 
|---|
| 5013 |           frag_now->tc_frag_data.is_insn = TRUE;
 | 
|---|
| 5014 |           frag_var (rs_machine_dependent, 4, 4,
 | 
|---|
| 5015 |                     RELAX_ADD_NOP_IF_A0_B_RETW,
 | 
|---|
| 5016 |                     frag_now->fr_symbol, frag_now->fr_offset, NULL);
 | 
|---|
| 5017 |         }
 | 
|---|
| 5018 |     }
 | 
|---|
| 5019 | 
 | 
|---|
| 5020 |   /* Special case: The call instructions should be marked "specific opcode"
 | 
|---|
| 5021 |      to keep them from expanding.  */
 | 
|---|
| 5022 |   if (!use_longcalls () && is_direct_call_opcode (orig_insn.opcode))
 | 
|---|
| 5023 |     orig_insn.is_specific_opcode = TRUE;
 | 
|---|
| 5024 | 
 | 
|---|
| 5025 |   /* Parse the arguments.  */
 | 
|---|
| 5026 |   if (parse_arguments (&orig_insn, num_args, arg_strings))
 | 
|---|
| 5027 |     {
 | 
|---|
| 5028 |       as_bad (_("syntax error"));
 | 
|---|
| 5029 |       return;
 | 
|---|
| 5030 |     }
 | 
|---|
| 5031 | 
 | 
|---|
| 5032 |   /* Free the opcode and argument strings, now that they've been parsed.  */
 | 
|---|
| 5033 |   free (has_underbar ? opname - 1 : opname);
 | 
|---|
| 5034 |   opname = 0;
 | 
|---|
| 5035 |   while (num_args-- > 0)
 | 
|---|
| 5036 |     free (arg_strings[num_args]);
 | 
|---|
| 5037 | 
 | 
|---|
| 5038 |   /* Check for the right number and type of arguments.  */
 | 
|---|
| 5039 |   if (tinsn_check_arguments (&orig_insn))
 | 
|---|
| 5040 |     return;
 | 
|---|
| 5041 | 
 | 
|---|
| 5042 |   /* See if the instruction implies an aligned section.  */
 | 
|---|
| 5043 |   if (is_entry_opcode (orig_insn.opcode) || is_loop_opcode (orig_insn.opcode))
 | 
|---|
| 5044 |     record_alignment (now_seg, 2);
 | 
|---|
| 5045 | 
 | 
|---|
| 5046 |   xg_add_branch_and_loop_targets (&orig_insn);
 | 
|---|
| 5047 | 
 | 
|---|
| 5048 |   /* Special cases for instructions that force an alignment... */
 | 
|---|
| 5049 |   if (!orig_insn.is_specific_opcode && is_loop_opcode (orig_insn.opcode))
 | 
|---|
| 5050 |     {
 | 
|---|
| 5051 |       fragS *old_frag = frag_now;
 | 
|---|
| 5052 |       offsetT old_offset = frag_now_fix ();
 | 
|---|
| 5053 |       symbolS *old_sym = NULL;
 | 
|---|
| 5054 |       size_t max_fill;
 | 
|---|
| 5055 | 
 | 
|---|
| 5056 |       frag_now->tc_frag_data.is_insn = TRUE;
 | 
|---|
| 5057 |       frag_now->tc_frag_data.is_no_density = !code_density_available ();
 | 
|---|
| 5058 |       max_fill = get_text_align_max_fill_size
 | 
|---|
| 5059 |         (get_text_align_power (XTENSA_FETCH_WIDTH),
 | 
|---|
| 5060 |          TRUE, frag_now->tc_frag_data.is_no_density);
 | 
|---|
| 5061 |       frag_var (rs_machine_dependent, max_fill, max_fill,
 | 
|---|
| 5062 |                 RELAX_ALIGN_NEXT_OPCODE, frag_now->fr_symbol,
 | 
|---|
| 5063 |                 frag_now->fr_offset, NULL);
 | 
|---|
| 5064 | 
 | 
|---|
| 5065 |       /* Repeat until there are no more.  */
 | 
|---|
| 5066 |       while ((old_sym = xtensa_find_label (old_frag, old_offset, FALSE)))
 | 
|---|
| 5067 |         {
 | 
|---|
| 5068 |           S_SET_VALUE (old_sym, (valueT) 0);
 | 
|---|
| 5069 |           symbol_set_frag (old_sym, frag_now);
 | 
|---|
| 5070 |         }
 | 
|---|
| 5071 |     }
 | 
|---|
| 5072 | 
 | 
|---|
| 5073 |   /* Special count for "entry" instruction.  */
 | 
|---|
| 5074 |   if (is_entry_opcode (orig_insn.opcode))
 | 
|---|
| 5075 |     {
 | 
|---|
| 5076 |       /* Check that the second opcode (#1) is >= 16.  */
 | 
|---|
| 5077 |       if (orig_insn.ntok >= 2)
 | 
|---|
| 5078 |         {
 | 
|---|
| 5079 |           expressionS *exp = &orig_insn.tok[1];
 | 
|---|
| 5080 |           switch (exp->X_op)
 | 
|---|
| 5081 |             {
 | 
|---|
| 5082 |             case O_constant:
 | 
|---|
| 5083 |               if (exp->X_add_number < 16)
 | 
|---|
| 5084 |                 as_warn (_("entry instruction with stack decrement < 16"));
 | 
|---|
| 5085 |               break;
 | 
|---|
| 5086 | 
 | 
|---|
| 5087 |             default:
 | 
|---|
| 5088 |               as_warn (_("entry instruction with non-constant decrement"));
 | 
|---|
| 5089 |             }
 | 
|---|
| 5090 |         }
 | 
|---|
| 5091 |     }
 | 
|---|
| 5092 | 
 | 
|---|
| 5093 |   if (!orig_insn.is_specific_opcode && is_entry_opcode (orig_insn.opcode))
 | 
|---|
| 5094 |     {
 | 
|---|
| 5095 |       xtensa_mark_literal_pool_location (TRUE);
 | 
|---|
| 5096 | 
 | 
|---|
| 5097 |       /* Automatically align ENTRY instructions.  */
 | 
|---|
| 5098 |       frag_align (2, 0, 0);
 | 
|---|
| 5099 |     }
 | 
|---|
| 5100 | 
 | 
|---|
| 5101 |   if (software_a0_b_retw_interlock)
 | 
|---|
| 5102 |     set_last_insn_flags (now_seg, now_subseg, FLAG_IS_A0_WRITER,
 | 
|---|
| 5103 |                          is_register_writer (&orig_insn, "a", 0));
 | 
|---|
| 5104 | 
 | 
|---|
| 5105 |   set_last_insn_flags (now_seg, now_subseg, FLAG_IS_BAD_LOOPEND,
 | 
|---|
| 5106 |                        is_bad_loopend_opcode (&orig_insn));
 | 
|---|
| 5107 | 
 | 
|---|
| 5108 |   /* Finish it off:
 | 
|---|
| 5109 |      assemble_tokens (opcode, tok, ntok); 
 | 
|---|
| 5110 |      expand the tokens from the orig_insn into the 
 | 
|---|
| 5111 |      stack of instructions that will not expand 
 | 
|---|
| 5112 |      unless required at relaxation time.  */
 | 
|---|
| 5113 |   if (xg_expand_assembly_insn (&istack, &orig_insn))
 | 
|---|
| 5114 |     return;
 | 
|---|
| 5115 | 
 | 
|---|
| 5116 |   for (i = 0; i < istack.ninsn; i++)
 | 
|---|
| 5117 |     {
 | 
|---|
| 5118 |       TInsn *insn = &istack.insn[i];
 | 
|---|
| 5119 |       if (insn->insn_type == ITYPE_LITERAL)
 | 
|---|
| 5120 |         {
 | 
|---|
| 5121 |           assert (lit_sym == NULL);
 | 
|---|
| 5122 |           lit_sym = xg_assemble_literal (insn);
 | 
|---|
| 5123 |         }
 | 
|---|
| 5124 |       else
 | 
|---|
| 5125 |         {
 | 
|---|
| 5126 |           if (lit_sym)
 | 
|---|
| 5127 |             xg_resolve_literals (insn, lit_sym);
 | 
|---|
| 5128 |           xg_assemble_tokens (insn);
 | 
|---|
| 5129 |         }
 | 
|---|
| 5130 |     }
 | 
|---|
| 5131 | 
 | 
|---|
| 5132 |   /* Now, if the original opcode was a call... */
 | 
|---|
| 5133 |   if (align_targets && is_call_opcode (orig_insn.opcode))
 | 
|---|
| 5134 |     {
 | 
|---|
| 5135 |       frag_now->tc_frag_data.is_insn = TRUE;
 | 
|---|
| 5136 |       frag_var (rs_machine_dependent, 4, 4,
 | 
|---|
| 5137 |                 RELAX_DESIRE_ALIGN,
 | 
|---|
| 5138 |                 frag_now->fr_symbol,
 | 
|---|
| 5139 |                 frag_now->fr_offset,
 | 
|---|
| 5140 |                 NULL);
 | 
|---|
| 5141 |     }
 | 
|---|
| 5142 | }
 | 
|---|
| 5143 | 
 | 
|---|
| 5144 | 
 | 
|---|
| 5145 | /* TC_CONS_FIX_NEW hook: Check for "@PLT" suffix on symbol references.
 | 
|---|
| 5146 |    If found, use an XTENSA_PLT reloc for 4-byte values.  Otherwise, this
 | 
|---|
| 5147 |    is the same as the standard code in read.c.  */
 | 
|---|
| 5148 | 
 | 
|---|
| 5149 | void 
 | 
|---|
| 5150 | xtensa_cons_fix_new (frag, where, size, exp)
 | 
|---|
| 5151 |      fragS *frag;
 | 
|---|
| 5152 |      int where; 
 | 
|---|
| 5153 |      int size;
 | 
|---|
| 5154 |      expressionS *exp;
 | 
|---|
| 5155 | {
 | 
|---|
| 5156 |   bfd_reloc_code_real_type r;
 | 
|---|
| 5157 |   bfd_boolean plt = FALSE;
 | 
|---|
| 5158 | 
 | 
|---|
| 5159 |   if (*input_line_pointer == '@') 
 | 
|---|
| 5160 |     {
 | 
|---|
| 5161 |       if (!strncmp (input_line_pointer, PLT_SUFFIX, strlen (PLT_SUFFIX) - 1)
 | 
|---|
| 5162 |           && !strncmp (input_line_pointer, plt_suffix,
 | 
|---|
| 5163 |                        strlen (plt_suffix) - 1))
 | 
|---|
| 5164 |         {
 | 
|---|
| 5165 |           as_bad (_("undefined @ suffix '%s', expected '%s'"), 
 | 
|---|
| 5166 |                   input_line_pointer, plt_suffix);
 | 
|---|
| 5167 |           ignore_rest_of_line ();
 | 
|---|
| 5168 |           return;
 | 
|---|
| 5169 |         }
 | 
|---|
| 5170 | 
 | 
|---|
| 5171 |       input_line_pointer += strlen (plt_suffix);
 | 
|---|
| 5172 |       plt = TRUE;
 | 
|---|
| 5173 |     }
 | 
|---|
| 5174 | 
 | 
|---|
| 5175 |   switch (size)
 | 
|---|
| 5176 |     {
 | 
|---|
| 5177 |     case 1:
 | 
|---|
| 5178 |       r = BFD_RELOC_8;
 | 
|---|
| 5179 |       break;
 | 
|---|
| 5180 |     case 2:
 | 
|---|
| 5181 |       r = BFD_RELOC_16;
 | 
|---|
| 5182 |       break;
 | 
|---|
| 5183 |     case 4:
 | 
|---|
| 5184 |       r = plt ? BFD_RELOC_XTENSA_PLT : BFD_RELOC_32;
 | 
|---|
| 5185 |       break;
 | 
|---|
| 5186 |     case 8:
 | 
|---|
| 5187 |       r = BFD_RELOC_64;
 | 
|---|
| 5188 |       break;
 | 
|---|
| 5189 |     default:
 | 
|---|
| 5190 |       as_bad (_("unsupported BFD relocation size %u"), size);
 | 
|---|
| 5191 |       r = BFD_RELOC_32;
 | 
|---|
| 5192 |       break;
 | 
|---|
| 5193 |     }
 | 
|---|
| 5194 |   fix_new_exp (frag, where, size, exp, 0, r);
 | 
|---|
| 5195 | }
 | 
|---|
| 5196 |   
 | 
|---|
| 5197 | 
 | 
|---|
| 5198 | /* TC_FRAG_INIT hook */
 | 
|---|
| 5199 | 
 | 
|---|
| 5200 | void
 | 
|---|
| 5201 | xtensa_frag_init (frag)
 | 
|---|
| 5202 |      fragS *frag;
 | 
|---|
| 5203 | {
 | 
|---|
| 5204 |   frag->tc_frag_data.is_no_density = !code_density_available ();
 | 
|---|
| 5205 | }
 | 
|---|
| 5206 | 
 | 
|---|
| 5207 | 
 | 
|---|
| 5208 | symbolS *
 | 
|---|
| 5209 | md_undefined_symbol (name)
 | 
|---|
| 5210 |      char *name ATTRIBUTE_UNUSED;
 | 
|---|
| 5211 | {
 | 
|---|
| 5212 |   return NULL;
 | 
|---|
| 5213 | }
 | 
|---|
| 5214 | 
 | 
|---|
| 5215 | 
 | 
|---|
| 5216 | /* Round up a section size to the appropriate boundary.  */
 | 
|---|
| 5217 | 
 | 
|---|
| 5218 | valueT
 | 
|---|
| 5219 | md_section_align (segment, size)
 | 
|---|
| 5220 |      segT segment ATTRIBUTE_UNUSED;
 | 
|---|
| 5221 |      valueT size;
 | 
|---|
| 5222 | {
 | 
|---|
| 5223 |   return size;                  /* Byte alignment is fine.  */
 | 
|---|
| 5224 | }
 | 
|---|
| 5225 | 
 | 
|---|
| 5226 | 
 | 
|---|
| 5227 | long
 | 
|---|
| 5228 | md_pcrel_from (fixP)
 | 
|---|
| 5229 |      fixS *fixP;
 | 
|---|
| 5230 | {
 | 
|---|
| 5231 |   char *insn_p;
 | 
|---|
| 5232 |   static xtensa_insnbuf insnbuf = NULL;
 | 
|---|
| 5233 |   int opnum;
 | 
|---|
| 5234 |   xtensa_operand operand;
 | 
|---|
| 5235 |   xtensa_opcode opcode;
 | 
|---|
| 5236 |   xtensa_isa isa = xtensa_default_isa;
 | 
|---|
| 5237 |   valueT addr = fixP->fx_where + fixP->fx_frag->fr_address;
 | 
|---|
| 5238 | 
 | 
|---|
| 5239 |   if (fixP->fx_done)
 | 
|---|
| 5240 |     return addr;
 | 
|---|
| 5241 | 
 | 
|---|
| 5242 |   if (fixP->fx_r_type == BFD_RELOC_XTENSA_ASM_EXPAND)
 | 
|---|
| 5243 |     return addr;
 | 
|---|
| 5244 | 
 | 
|---|
| 5245 |   if (!insnbuf)
 | 
|---|
| 5246 |     insnbuf = xtensa_insnbuf_alloc (isa);
 | 
|---|
| 5247 | 
 | 
|---|
| 5248 |   insn_p = &fixP->fx_frag->fr_literal[fixP->fx_where];
 | 
|---|
| 5249 |   xtensa_insnbuf_from_chars (isa, insnbuf, insn_p);
 | 
|---|
| 5250 |   opcode = xtensa_decode_insn (isa, insnbuf);
 | 
|---|
| 5251 | 
 | 
|---|
| 5252 |   opnum = reloc_to_opnum (fixP->fx_r_type);
 | 
|---|
| 5253 | 
 | 
|---|
| 5254 |   if (opnum < 0)
 | 
|---|
| 5255 |     as_fatal (_("invalid operand relocation for '%s' instruction"),
 | 
|---|
| 5256 |               xtensa_opcode_name (isa, opcode));
 | 
|---|
| 5257 |   if (opnum >= xtensa_num_operands (isa, opcode))
 | 
|---|
| 5258 |     as_fatal (_("invalid relocation for operand %d in '%s' instruction"),
 | 
|---|
| 5259 |               opnum, xtensa_opcode_name (isa, opcode));
 | 
|---|
| 5260 |   operand = xtensa_get_operand (isa, opcode, opnum);
 | 
|---|
| 5261 |   if (!operand)
 | 
|---|
| 5262 |     {
 | 
|---|
| 5263 |       as_warn_where (fixP->fx_file,
 | 
|---|
| 5264 |                      fixP->fx_line,
 | 
|---|
| 5265 |                      _("invalid relocation type %d for %s instruction"),
 | 
|---|
| 5266 |                      fixP->fx_r_type, xtensa_opcode_name (isa, opcode));
 | 
|---|
| 5267 |       return addr;
 | 
|---|
| 5268 |     }
 | 
|---|
| 5269 | 
 | 
|---|
| 5270 |   if (!operand_is_pcrel_label (operand))
 | 
|---|
| 5271 |     {
 | 
|---|
| 5272 |       as_bad_where (fixP->fx_file,
 | 
|---|
| 5273 |                     fixP->fx_line,
 | 
|---|
| 5274 |                     _("invalid relocation for operand %d of '%s'"),
 | 
|---|
| 5275 |                     opnum, xtensa_opcode_name (isa, opcode));
 | 
|---|
| 5276 |       return addr;
 | 
|---|
| 5277 |     }
 | 
|---|
| 5278 |   if (!xtensa_operand_isPCRelative (operand))
 | 
|---|
| 5279 |     {
 | 
|---|
| 5280 |       as_warn_where (fixP->fx_file,
 | 
|---|
| 5281 |                      fixP->fx_line,
 | 
|---|
| 5282 |                      _("non-PCREL relocation operand %d for '%s': %s"),
 | 
|---|
| 5283 |                      opnum, xtensa_opcode_name (isa, opcode),
 | 
|---|
| 5284 |                      bfd_get_reloc_code_name (fixP->fx_r_type));
 | 
|---|
| 5285 |       return addr;
 | 
|---|
| 5286 |     }
 | 
|---|
| 5287 | 
 | 
|---|
| 5288 |   return 0 - xtensa_operand_do_reloc (operand, 0, addr);
 | 
|---|
| 5289 | }
 | 
|---|
| 5290 | 
 | 
|---|
| 5291 | 
 | 
|---|
| 5292 | /* tc_symbol_new_hook */
 | 
|---|
| 5293 | 
 | 
|---|
| 5294 | void
 | 
|---|
| 5295 | xtensa_symbol_new_hook (symbolP)
 | 
|---|
| 5296 |      symbolS *symbolP;
 | 
|---|
| 5297 | {
 | 
|---|
| 5298 |   symbolP->sy_tc.plt = 0;
 | 
|---|
| 5299 | }
 | 
|---|
| 5300 | 
 | 
|---|
| 5301 | 
 | 
|---|
| 5302 | /* tc_fix_adjustable hook */
 | 
|---|
| 5303 | 
 | 
|---|
| 5304 | bfd_boolean
 | 
|---|
| 5305 | xtensa_fix_adjustable (fixP)
 | 
|---|
| 5306 |      fixS *fixP;
 | 
|---|
| 5307 | {
 | 
|---|
| 5308 |   /* We need the symbol name for the VTABLE entries.  */
 | 
|---|
| 5309 |   if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
 | 
|---|
| 5310 |       || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
 | 
|---|
| 5311 |     return 0;
 | 
|---|
| 5312 | 
 | 
|---|
| 5313 |   return 1;
 | 
|---|
| 5314 | }
 | 
|---|
| 5315 | 
 | 
|---|
| 5316 | 
 | 
|---|
| 5317 | void
 | 
|---|
| 5318 | md_apply_fix3 (fixP, valP, seg)
 | 
|---|
| 5319 |      fixS *fixP;
 | 
|---|
| 5320 |      valueT *valP;
 | 
|---|
| 5321 |      segT seg ATTRIBUTE_UNUSED;
 | 
|---|
| 5322 | {
 | 
|---|
| 5323 |   if (fixP->fx_pcrel == 0 && fixP->fx_addsy == 0)
 | 
|---|
| 5324 |     {
 | 
|---|
| 5325 |       /* This happens when the relocation is within the current section. 
 | 
|---|
| 5326 |          It seems this implies a PCREL operation.  We'll catch it and error 
 | 
|---|
| 5327 |          if not.  */
 | 
|---|
| 5328 | 
 | 
|---|
| 5329 |       char *const fixpos = fixP->fx_frag->fr_literal + fixP->fx_where;
 | 
|---|
| 5330 |       static xtensa_insnbuf insnbuf = NULL;
 | 
|---|
| 5331 |       xtensa_opcode opcode;
 | 
|---|
| 5332 |       xtensa_isa isa;
 | 
|---|
| 5333 | 
 | 
|---|
| 5334 |       switch (fixP->fx_r_type)
 | 
|---|
| 5335 |         {
 | 
|---|
| 5336 |         case BFD_RELOC_XTENSA_ASM_EXPAND:
 | 
|---|
| 5337 |           fixP->fx_done = 1;
 | 
|---|
| 5338 |           break;
 | 
|---|
| 5339 | 
 | 
|---|
| 5340 |         case BFD_RELOC_XTENSA_ASM_SIMPLIFY:
 | 
|---|
| 5341 |           as_bad (_("unhandled local relocation fix %s"),
 | 
|---|
| 5342 |                   bfd_get_reloc_code_name (fixP->fx_r_type));
 | 
|---|
| 5343 |           break;
 | 
|---|
| 5344 | 
 | 
|---|
| 5345 |         case BFD_RELOC_32:
 | 
|---|
| 5346 |         case BFD_RELOC_16:
 | 
|---|
| 5347 |         case BFD_RELOC_8:
 | 
|---|
| 5348 |           /* The only one we support that isn't an instruction field.  */
 | 
|---|
| 5349 |           md_number_to_chars (fixpos, *valP, fixP->fx_size);
 | 
|---|
| 5350 |           fixP->fx_done = 1;
 | 
|---|
| 5351 |           break;
 | 
|---|
| 5352 | 
 | 
|---|
| 5353 |         case BFD_RELOC_XTENSA_OP0:
 | 
|---|
| 5354 |         case BFD_RELOC_XTENSA_OP1:
 | 
|---|
| 5355 |         case BFD_RELOC_XTENSA_OP2:
 | 
|---|
| 5356 |           isa = xtensa_default_isa;
 | 
|---|
| 5357 |           if (!insnbuf)
 | 
|---|
| 5358 |             insnbuf = xtensa_insnbuf_alloc (isa);
 | 
|---|
| 5359 | 
 | 
|---|
| 5360 |           xtensa_insnbuf_from_chars (isa, insnbuf, fixpos);
 | 
|---|
| 5361 |           opcode = xtensa_decode_insn (isa, insnbuf);
 | 
|---|
| 5362 |           if (opcode == XTENSA_UNDEFINED)
 | 
|---|
| 5363 |             as_fatal (_("undecodable FIX"));
 | 
|---|
| 5364 | 
 | 
|---|
| 5365 |           xtensa_insnbuf_set_immediate_field (opcode, insnbuf, *valP,
 | 
|---|
| 5366 |                                               fixP->fx_file, fixP->fx_line);
 | 
|---|
| 5367 | 
 | 
|---|
| 5368 |           fixP->fx_frag->tc_frag_data.is_insn = TRUE;
 | 
|---|
| 5369 |           xtensa_insnbuf_to_chars (isa, insnbuf, fixpos);
 | 
|---|
| 5370 |           fixP->fx_done = 1;
 | 
|---|
| 5371 |           break;
 | 
|---|
| 5372 | 
 | 
|---|
| 5373 |         case BFD_RELOC_VTABLE_INHERIT:
 | 
|---|
| 5374 |         case BFD_RELOC_VTABLE_ENTRY:
 | 
|---|
| 5375 |           fixP->fx_done = 0;
 | 
|---|
| 5376 |           break;
 | 
|---|
| 5377 | 
 | 
|---|
| 5378 |         default:
 | 
|---|
| 5379 |           as_bad (_("unhandled local relocation fix %s"),
 | 
|---|
| 5380 |                   bfd_get_reloc_code_name (fixP->fx_r_type));
 | 
|---|
| 5381 |         }
 | 
|---|
| 5382 |     }
 | 
|---|
| 5383 | }
 | 
|---|
| 5384 | 
 | 
|---|
| 5385 | 
 | 
|---|
| 5386 | char *
 | 
|---|
| 5387 | md_atof (type, litP, sizeP)
 | 
|---|
| 5388 |      int type;
 | 
|---|
| 5389 |      char *litP;
 | 
|---|
| 5390 |      int *sizeP;
 | 
|---|
| 5391 | {
 | 
|---|
| 5392 |   int prec;
 | 
|---|
| 5393 |   LITTLENUM_TYPE words[4];
 | 
|---|
| 5394 |   char *t;
 | 
|---|
| 5395 |   int i;
 | 
|---|
| 5396 | 
 | 
|---|
| 5397 |   switch (type)
 | 
|---|
| 5398 |     {
 | 
|---|
| 5399 |     case 'f':
 | 
|---|
| 5400 |       prec = 2;
 | 
|---|
| 5401 |       break;
 | 
|---|
| 5402 | 
 | 
|---|
| 5403 |     case 'd':
 | 
|---|
| 5404 |       prec = 4;
 | 
|---|
| 5405 |       break;
 | 
|---|
| 5406 | 
 | 
|---|
| 5407 |     default:
 | 
|---|
| 5408 |       *sizeP = 0;
 | 
|---|
| 5409 |       return "bad call to md_atof";
 | 
|---|
| 5410 |     }
 | 
|---|
| 5411 | 
 | 
|---|
| 5412 |   t = atof_ieee (input_line_pointer, type, words);
 | 
|---|
| 5413 |   if (t)
 | 
|---|
| 5414 |     input_line_pointer = t;
 | 
|---|
| 5415 | 
 | 
|---|
| 5416 |   *sizeP = prec * 2;
 | 
|---|
| 5417 | 
 | 
|---|
| 5418 |   for (i = prec - 1; i >= 0; i--)
 | 
|---|
| 5419 |     {
 | 
|---|
| 5420 |       int idx = i;
 | 
|---|
| 5421 |       if (target_big_endian)
 | 
|---|
| 5422 |         idx = (prec - 1 - i);
 | 
|---|
| 5423 | 
 | 
|---|
| 5424 |       md_number_to_chars (litP, (valueT) words[idx], 2);
 | 
|---|
| 5425 |       litP += 2;
 | 
|---|
| 5426 |     }
 | 
|---|
| 5427 | 
 | 
|---|
| 5428 |   return NULL;
 | 
|---|
| 5429 | }
 | 
|---|
| 5430 | 
 | 
|---|
| 5431 | 
 | 
|---|
| 5432 | int
 | 
|---|
| 5433 | md_estimate_size_before_relax (fragP, seg)
 | 
|---|
| 5434 |      fragS *fragP;
 | 
|---|
| 5435 |      segT seg ATTRIBUTE_UNUSED;
 | 
|---|
| 5436 | {
 | 
|---|
| 5437 |   return fragP->tc_frag_data.text_expansion;
 | 
|---|
| 5438 | }
 | 
|---|
| 5439 | 
 | 
|---|
| 5440 | 
 | 
|---|
| 5441 | /* Translate internal representation of relocation info to BFD target
 | 
|---|
| 5442 |    format.  */
 | 
|---|
| 5443 | 
 | 
|---|
| 5444 | arelent *
 | 
|---|
| 5445 | tc_gen_reloc (section, fixp)
 | 
|---|
| 5446 |      asection *section ATTRIBUTE_UNUSED;
 | 
|---|
| 5447 |      fixS *fixp;
 | 
|---|
| 5448 | {
 | 
|---|
| 5449 |   arelent *reloc;
 | 
|---|
| 5450 | 
 | 
|---|
| 5451 |   reloc = (arelent *) xmalloc (sizeof (arelent));
 | 
|---|
| 5452 |   reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
 | 
|---|
| 5453 |   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
 | 
|---|
| 5454 |   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
 | 
|---|
| 5455 | 
 | 
|---|
| 5456 |   /* Make sure none of our internal relocations make it this far.
 | 
|---|
| 5457 |      They'd better have been fully resolved by this point.  */
 | 
|---|
| 5458 |   assert ((int) fixp->fx_r_type > 0);
 | 
|---|
| 5459 | 
 | 
|---|
| 5460 |   reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
 | 
|---|
| 5461 |   if (reloc->howto == NULL)
 | 
|---|
| 5462 |     {
 | 
|---|
| 5463 |       as_bad_where (fixp->fx_file, fixp->fx_line,
 | 
|---|
| 5464 |                     _("cannot represent `%s' relocation in object file"),
 | 
|---|
| 5465 |                     bfd_get_reloc_code_name (fixp->fx_r_type));
 | 
|---|
| 5466 |       return NULL;
 | 
|---|
| 5467 |     }
 | 
|---|
| 5468 | 
 | 
|---|
| 5469 |   if (!fixp->fx_pcrel != !reloc->howto->pc_relative)
 | 
|---|
| 5470 |     {
 | 
|---|
| 5471 |       as_fatal (_("internal error? cannot generate `%s' relocation"),
 | 
|---|
| 5472 |                 bfd_get_reloc_code_name (fixp->fx_r_type));
 | 
|---|
| 5473 |     }
 | 
|---|
| 5474 |   assert (!fixp->fx_pcrel == !reloc->howto->pc_relative);
 | 
|---|
| 5475 | 
 | 
|---|
| 5476 |   reloc->addend = fixp->fx_offset;
 | 
|---|
| 5477 | 
 | 
|---|
| 5478 |   switch (fixp->fx_r_type)
 | 
|---|
| 5479 |     {
 | 
|---|
| 5480 |     case BFD_RELOC_XTENSA_OP0:
 | 
|---|
| 5481 |     case BFD_RELOC_XTENSA_OP1:
 | 
|---|
| 5482 |     case BFD_RELOC_XTENSA_OP2:
 | 
|---|
| 5483 |     case BFD_RELOC_XTENSA_ASM_EXPAND:
 | 
|---|
| 5484 |     case BFD_RELOC_32: 
 | 
|---|
| 5485 |     case BFD_RELOC_XTENSA_PLT: 
 | 
|---|
| 5486 |     case BFD_RELOC_VTABLE_INHERIT:
 | 
|---|
| 5487 |     case BFD_RELOC_VTABLE_ENTRY:
 | 
|---|
| 5488 |       break;
 | 
|---|
| 5489 | 
 | 
|---|
| 5490 |     case BFD_RELOC_XTENSA_ASM_SIMPLIFY:
 | 
|---|
| 5491 |       as_warn (_("emitting simplification relocation"));
 | 
|---|
| 5492 |       break;
 | 
|---|
| 5493 | 
 | 
|---|
| 5494 |     default:
 | 
|---|
| 5495 |       as_warn (_("emitting unknown relocation"));
 | 
|---|
| 5496 |     }
 | 
|---|
| 5497 | 
 | 
|---|
| 5498 |   return reloc;
 | 
|---|
| 5499 | }
 | 
|---|
| 5500 | 
 | 
|---|
| 5501 |  | 
|---|
| 5502 | 
 | 
|---|
| 5503 | void
 | 
|---|
| 5504 | xtensa_end ()
 | 
|---|
| 5505 | {
 | 
|---|
| 5506 |   directive_balance ();
 | 
|---|
| 5507 |   xtensa_move_literals ();
 | 
|---|
| 5508 | 
 | 
|---|
| 5509 |   xtensa_reorder_segments ();
 | 
|---|
| 5510 |   xtensa_mark_target_fragments ();
 | 
|---|
| 5511 |   xtensa_cleanup_align_frags ();
 | 
|---|
| 5512 |   xtensa_fix_target_frags ();
 | 
|---|
| 5513 |   if (software_a0_b_retw_interlock && has_a0_b_retw)
 | 
|---|
| 5514 |     xtensa_fix_a0_b_retw_frags ();
 | 
|---|
| 5515 |   if (software_avoid_b_j_loop_end && maybe_has_b_j_loop_end)
 | 
|---|
| 5516 |     xtensa_fix_b_j_loop_end_frags ();
 | 
|---|
| 5517 | 
 | 
|---|
| 5518 |   /* "close_loop_end" should be processed BEFORE "short_loop".  */
 | 
|---|
| 5519 |   if (software_avoid_close_loop_end && maybe_has_close_loop_end)
 | 
|---|
| 5520 |     xtensa_fix_close_loop_end_frags ();
 | 
|---|
| 5521 | 
 | 
|---|
| 5522 |   if (software_avoid_short_loop && maybe_has_short_loop)
 | 
|---|
| 5523 |     xtensa_fix_short_loop_frags ();
 | 
|---|
| 5524 | 
 | 
|---|
| 5525 |   xtensa_sanity_check ();
 | 
|---|
| 5526 | }
 | 
|---|
| 5527 | 
 | 
|---|
| 5528 | 
 | 
|---|
| 5529 | static void
 | 
|---|
| 5530 | xtensa_cleanup_align_frags ()
 | 
|---|
| 5531 | {
 | 
|---|
| 5532 |   frchainS *frchP;
 | 
|---|
| 5533 | 
 | 
|---|
| 5534 |   for (frchP = frchain_root; frchP; frchP = frchP->frch_next)
 | 
|---|
| 5535 |     {
 | 
|---|
| 5536 |       fragS *fragP;
 | 
|---|
| 5537 | 
 | 
|---|
| 5538 |       /* Walk over all of the fragments in a subsection.  */
 | 
|---|
| 5539 |       for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
 | 
|---|
| 5540 |         {
 | 
|---|
| 5541 |           if ((fragP->fr_type == rs_align
 | 
|---|
| 5542 |                || fragP->fr_type == rs_align_code
 | 
|---|
| 5543 |                || (fragP->fr_type == rs_machine_dependent
 | 
|---|
| 5544 |                    && (fragP->fr_subtype == RELAX_DESIRE_ALIGN
 | 
|---|
| 5545 |                        || fragP->fr_subtype == RELAX_DESIRE_ALIGN_IF_TARGET)))
 | 
|---|
| 5546 |               && fragP->fr_fix == 0)
 | 
|---|
| 5547 |             {
 | 
|---|
| 5548 |               fragS * next = fragP->fr_next;
 | 
|---|
| 5549 | 
 | 
|---|
| 5550 |               while (next
 | 
|---|
| 5551 |                      && next->fr_type == rs_machine_dependent 
 | 
|---|
| 5552 |                      && next->fr_subtype == RELAX_DESIRE_ALIGN_IF_TARGET) 
 | 
|---|
| 5553 |                 {
 | 
|---|
| 5554 |                   frag_wane (next);
 | 
|---|
| 5555 |                   next = next->fr_next;
 | 
|---|
| 5556 |                 }
 | 
|---|
| 5557 |             }
 | 
|---|
| 5558 |         }
 | 
|---|
| 5559 |     }
 | 
|---|
| 5560 | }
 | 
|---|
| 5561 | 
 | 
|---|
| 5562 | 
 | 
|---|
| 5563 | /* Re-process all of the fragments looking to convert all of the
 | 
|---|
| 5564 |    RELAX_DESIRE_ALIGN_IF_TARGET fragments.  If there is a branch
 | 
|---|
| 5565 |    target in the next fragment, convert this to RELAX_DESIRE_ALIGN.
 | 
|---|
| 5566 |    If the next fragment starts with a loop target, AND the previous
 | 
|---|
| 5567 |    fragment can be expanded to negate the branch, convert this to a
 | 
|---|
| 5568 |    RELAX_LOOP_END.  Otherwise, convert to a .fill 0.  */
 | 
|---|
| 5569 | 
 | 
|---|
| 5570 | static void
 | 
|---|
| 5571 | xtensa_fix_target_frags ()
 | 
|---|
| 5572 | {
 | 
|---|
| 5573 |   frchainS *frchP;
 | 
|---|
| 5574 | 
 | 
|---|
| 5575 |   /* When this routine is called, all of the subsections are still intact
 | 
|---|
| 5576 |      so we walk over subsections instead of sections.  */
 | 
|---|
| 5577 |   for (frchP = frchain_root; frchP; frchP = frchP->frch_next)
 | 
|---|
| 5578 |     {
 | 
|---|
| 5579 |       bfd_boolean prev_frag_can_negate_branch = FALSE;
 | 
|---|
| 5580 |       fragS *fragP;
 | 
|---|
| 5581 | 
 | 
|---|
| 5582 |       /* Walk over all of the fragments in a subsection.  */
 | 
|---|
| 5583 |       for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
 | 
|---|
| 5584 |         {
 | 
|---|
| 5585 |           if (fragP->fr_type == rs_machine_dependent
 | 
|---|
| 5586 |               && fragP->fr_subtype == RELAX_DESIRE_ALIGN_IF_TARGET)
 | 
|---|
| 5587 |             {
 | 
|---|
| 5588 |               if (next_frag_is_loop_target (fragP))
 | 
|---|
| 5589 |                 {
 | 
|---|
| 5590 |                   if (prev_frag_can_negate_branch)
 | 
|---|
| 5591 |                     fragP->fr_subtype = RELAX_LOOP_END;
 | 
|---|
| 5592 |                   else
 | 
|---|
| 5593 |                     {
 | 
|---|
| 5594 |                       if (!align_only_targets ||
 | 
|---|
| 5595 |                           next_frag_is_branch_target (fragP))
 | 
|---|
| 5596 |                         fragP->fr_subtype = RELAX_DESIRE_ALIGN;
 | 
|---|
| 5597 |                       else
 | 
|---|
| 5598 |                         frag_wane (fragP);
 | 
|---|
| 5599 |                     }
 | 
|---|
| 5600 |                 }
 | 
|---|
| 5601 |               else if (!align_only_targets
 | 
|---|
| 5602 |                        || next_frag_is_branch_target (fragP))
 | 
|---|
| 5603 |                 fragP->fr_subtype = RELAX_DESIRE_ALIGN;
 | 
|---|
| 5604 |               else
 | 
|---|
| 5605 |                 frag_wane (fragP);
 | 
|---|
| 5606 |             }
 | 
|---|
| 5607 |           if (fragP->fr_fix != 0)
 | 
|---|
| 5608 |             prev_frag_can_negate_branch = FALSE;
 | 
|---|
| 5609 |           if (frag_can_negate_branch (fragP))
 | 
|---|
| 5610 |             prev_frag_can_negate_branch = TRUE;
 | 
|---|
| 5611 |         }
 | 
|---|
| 5612 |     }
 | 
|---|
| 5613 | }
 | 
|---|
| 5614 | 
 | 
|---|
| 5615 | 
 | 
|---|
| 5616 | static bfd_boolean
 | 
|---|
| 5617 | frag_can_negate_branch (fragP)
 | 
|---|
| 5618 |      fragS *fragP;
 | 
|---|
| 5619 | {
 | 
|---|
| 5620 |   if (fragP->fr_type == rs_machine_dependent
 | 
|---|
| 5621 |       && fragP->fr_subtype == RELAX_IMMED)
 | 
|---|
| 5622 |     {
 | 
|---|
| 5623 |       TInsn t_insn;
 | 
|---|
| 5624 |       tinsn_from_chars (&t_insn, fragP->fr_opcode);
 | 
|---|
| 5625 |       if (is_negatable_branch (&t_insn))
 | 
|---|
| 5626 |         return TRUE;
 | 
|---|
| 5627 |     }
 | 
|---|
| 5628 |   return FALSE;
 | 
|---|
| 5629 | }
 | 
|---|
| 5630 | 
 | 
|---|
| 5631 | 
 | 
|---|
| 5632 | /* Re-process all of the fragments looking to convert all of the
 | 
|---|
| 5633 |    RELAX_ADD_NOP_IF_A0_B_RETW.  If the next instruction is a
 | 
|---|
| 5634 |    conditional branch or a retw/retw.n, convert this frag to one that
 | 
|---|
| 5635 |    will generate a NOP.  In any case close it off with a .fill 0.  */
 | 
|---|
| 5636 | 
 | 
|---|
| 5637 | static void
 | 
|---|
| 5638 | xtensa_fix_a0_b_retw_frags ()
 | 
|---|
| 5639 | {
 | 
|---|
| 5640 |   frchainS *frchP;
 | 
|---|
| 5641 | 
 | 
|---|
| 5642 |   /* When this routine is called, all of the subsections are still intact
 | 
|---|
| 5643 |      so we walk over subsections instead of sections.  */
 | 
|---|
| 5644 |   for (frchP = frchain_root; frchP; frchP = frchP->frch_next)
 | 
|---|
| 5645 |     {
 | 
|---|
| 5646 |       fragS *fragP;
 | 
|---|
| 5647 | 
 | 
|---|
| 5648 |       /* Walk over all of the fragments in a subsection.  */
 | 
|---|
| 5649 |       for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
 | 
|---|
| 5650 |         {
 | 
|---|
| 5651 |           if (fragP->fr_type == rs_machine_dependent
 | 
|---|
| 5652 |               && fragP->fr_subtype == RELAX_ADD_NOP_IF_A0_B_RETW)
 | 
|---|
| 5653 |             {
 | 
|---|
| 5654 |               if (next_instrs_are_b_retw (fragP))
 | 
|---|
| 5655 |                 relax_frag_add_nop (fragP);
 | 
|---|
| 5656 |               else
 | 
|---|
| 5657 |                 frag_wane (fragP);
 | 
|---|
| 5658 |             }
 | 
|---|
| 5659 |         }
 | 
|---|
| 5660 |     }
 | 
|---|
| 5661 | }
 | 
|---|
| 5662 | 
 | 
|---|
| 5663 | 
 | 
|---|
| 5664 | bfd_boolean
 | 
|---|
| 5665 | next_instrs_are_b_retw (fragP)
 | 
|---|
| 5666 |      fragS * fragP;
 | 
|---|
| 5667 | {
 | 
|---|
| 5668 |   xtensa_opcode opcode;
 | 
|---|
| 5669 |   const fragS *next_fragP = next_non_empty_frag (fragP);
 | 
|---|
| 5670 |   static xtensa_insnbuf insnbuf = NULL;
 | 
|---|
| 5671 |   xtensa_isa isa = xtensa_default_isa;
 | 
|---|
| 5672 |   int offset = 0;
 | 
|---|
| 5673 | 
 | 
|---|
| 5674 |   if (!insnbuf)
 | 
|---|
| 5675 |     insnbuf = xtensa_insnbuf_alloc (isa);
 | 
|---|
| 5676 | 
 | 
|---|
| 5677 |   if (next_fragP == NULL)
 | 
|---|
| 5678 |     return FALSE;
 | 
|---|
| 5679 | 
 | 
|---|
| 5680 |   /* Check for the conditional branch.  */
 | 
|---|
| 5681 |   xtensa_insnbuf_from_chars (isa, insnbuf, &next_fragP->fr_literal[offset]);
 | 
|---|
| 5682 |   opcode = xtensa_decode_insn (isa, insnbuf);
 | 
|---|
| 5683 | 
 | 
|---|
| 5684 |   if (!is_conditional_branch_opcode (opcode))
 | 
|---|
| 5685 |     return FALSE;
 | 
|---|
| 5686 | 
 | 
|---|
| 5687 |   offset += xtensa_insn_length (isa, opcode);
 | 
|---|
| 5688 |   if (offset == next_fragP->fr_fix)
 | 
|---|
| 5689 |     {
 | 
|---|
| 5690 |       next_fragP = next_non_empty_frag (next_fragP);
 | 
|---|
| 5691 |       offset = 0;
 | 
|---|
| 5692 |     }
 | 
|---|
| 5693 |   if (next_fragP == NULL)
 | 
|---|
| 5694 |     return FALSE;
 | 
|---|
| 5695 | 
 | 
|---|
| 5696 |   /* Check for the retw/retw.n.  */
 | 
|---|
| 5697 |   xtensa_insnbuf_from_chars (isa, insnbuf, &next_fragP->fr_literal[offset]);
 | 
|---|
| 5698 |   opcode = xtensa_decode_insn (isa, insnbuf);
 | 
|---|
| 5699 | 
 | 
|---|
| 5700 |   if (is_windowed_return_opcode (opcode))
 | 
|---|
| 5701 |     return TRUE;
 | 
|---|
| 5702 |   return FALSE;
 | 
|---|
| 5703 | }
 | 
|---|
| 5704 | 
 | 
|---|
| 5705 | 
 | 
|---|
| 5706 | /* Re-process all of the fragments looking to convert all of the
 | 
|---|
| 5707 |    RELAX_ADD_NOP_IF_PRE_LOOP_END.  If there is one instruction and a
 | 
|---|
| 5708 |    loop end label, convert this frag to one that will generate a NOP.
 | 
|---|
| 5709 |    In any case close it off with a .fill 0.  */
 | 
|---|
| 5710 | 
 | 
|---|
| 5711 | static void
 | 
|---|
| 5712 | xtensa_fix_b_j_loop_end_frags ()
 | 
|---|
| 5713 | {
 | 
|---|
| 5714 |   frchainS *frchP;
 | 
|---|
| 5715 | 
 | 
|---|
| 5716 |   /* When this routine is called, all of the subsections are still intact
 | 
|---|
| 5717 |      so we walk over subsections instead of sections.  */
 | 
|---|
| 5718 |   for (frchP = frchain_root; frchP; frchP = frchP->frch_next)
 | 
|---|
| 5719 |     {
 | 
|---|
| 5720 |       fragS *fragP;
 | 
|---|
| 5721 | 
 | 
|---|
| 5722 |       /* Walk over all of the fragments in a subsection.  */
 | 
|---|
| 5723 |       for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
 | 
|---|
| 5724 |         {
 | 
|---|
| 5725 |           if (fragP->fr_type == rs_machine_dependent
 | 
|---|
| 5726 |               && fragP->fr_subtype == RELAX_ADD_NOP_IF_PRE_LOOP_END)
 | 
|---|
| 5727 |             {
 | 
|---|
| 5728 |               if (next_instr_is_loop_end (fragP))
 | 
|---|
| 5729 |                 relax_frag_add_nop (fragP);
 | 
|---|
| 5730 |               else
 | 
|---|
| 5731 |                 frag_wane (fragP);
 | 
|---|
| 5732 |             }
 | 
|---|
| 5733 |         }
 | 
|---|
| 5734 |     }
 | 
|---|
| 5735 | }
 | 
|---|
| 5736 | 
 | 
|---|
| 5737 | 
 | 
|---|
| 5738 | bfd_boolean
 | 
|---|
| 5739 | next_instr_is_loop_end (fragP)
 | 
|---|
| 5740 |      fragS * fragP;
 | 
|---|
| 5741 | {
 | 
|---|
| 5742 |   const fragS *next_fragP;
 | 
|---|
| 5743 | 
 | 
|---|
| 5744 |   if (next_frag_is_loop_target (fragP))
 | 
|---|
| 5745 |     return FALSE;
 | 
|---|
| 5746 | 
 | 
|---|
| 5747 |   next_fragP = next_non_empty_frag (fragP);
 | 
|---|
| 5748 |   if (next_fragP == NULL)
 | 
|---|
| 5749 |     return FALSE;
 | 
|---|
| 5750 | 
 | 
|---|
| 5751 |   if (!next_frag_is_loop_target (next_fragP))
 | 
|---|
| 5752 |     return FALSE;
 | 
|---|
| 5753 | 
 | 
|---|
| 5754 |   /* If the size is >= 3 then there is more than one instruction here.
 | 
|---|
| 5755 |      The hardware bug will not fire.  */
 | 
|---|
| 5756 |   if (next_fragP->fr_fix > 3)
 | 
|---|
| 5757 |     return FALSE;
 | 
|---|
| 5758 | 
 | 
|---|
| 5759 |   return TRUE;
 | 
|---|
| 5760 | }
 | 
|---|
| 5761 | 
 | 
|---|
| 5762 | 
 | 
|---|
| 5763 | /* Re-process all of the fragments looking to convert all of the
 | 
|---|
| 5764 |    RELAX_ADD_NOP_IF_CLOSE_LOOP_END.  If there is an loop end that is
 | 
|---|
| 5765 |    not MY loop's loop end within 12 bytes, add enough nops here to
 | 
|---|
| 5766 |    make it at least 12 bytes away.  In any case close it off with a
 | 
|---|
| 5767 |    .fill 0.  */
 | 
|---|
| 5768 | 
 | 
|---|
| 5769 | static void
 | 
|---|
| 5770 | xtensa_fix_close_loop_end_frags ()
 | 
|---|
| 5771 | {
 | 
|---|
| 5772 |   frchainS *frchP;
 | 
|---|
| 5773 | 
 | 
|---|
| 5774 |   /* When this routine is called, all of the subsections are still intact
 | 
|---|
| 5775 |      so we walk over subsections instead of sections.  */
 | 
|---|
| 5776 |   for (frchP = frchain_root; frchP; frchP = frchP->frch_next)
 | 
|---|
| 5777 |     {
 | 
|---|
| 5778 |       fragS *fragP;
 | 
|---|
| 5779 | 
 | 
|---|
| 5780 |       fragS *current_target = NULL;
 | 
|---|
| 5781 |       offsetT current_offset = 0;
 | 
|---|
| 5782 | 
 | 
|---|
| 5783 |       /* Walk over all of the fragments in a subsection.  */
 | 
|---|
| 5784 |       for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
 | 
|---|
| 5785 |         {
 | 
|---|
| 5786 |           if (fragP->fr_type == rs_machine_dependent
 | 
|---|
| 5787 |               && fragP->fr_subtype == RELAX_IMMED)
 | 
|---|
| 5788 |             {
 | 
|---|
| 5789 |               /* Read it.  If the instruction is a loop, get the target.  */
 | 
|---|
| 5790 |               xtensa_opcode opcode = get_opcode_from_buf (fragP->fr_opcode);
 | 
|---|
| 5791 |               if (is_loop_opcode (opcode))
 | 
|---|
| 5792 |                 {
 | 
|---|
| 5793 |                   TInsn t_insn;
 | 
|---|
| 5794 | 
 | 
|---|
| 5795 |                   tinsn_from_chars (&t_insn, fragP->fr_opcode);
 | 
|---|
| 5796 |                   tinsn_immed_from_frag (&t_insn, fragP);
 | 
|---|
| 5797 | 
 | 
|---|
| 5798 |                   /* Get the current fragment target.  */
 | 
|---|
| 5799 |                   if (fragP->fr_symbol)
 | 
|---|
| 5800 |                     {
 | 
|---|
| 5801 |                       current_target = symbol_get_frag (fragP->fr_symbol);
 | 
|---|
| 5802 |                       current_offset = fragP->fr_offset;
 | 
|---|
| 5803 |                     }
 | 
|---|
| 5804 |                 }
 | 
|---|
| 5805 |             }
 | 
|---|
| 5806 | 
 | 
|---|
| 5807 |           if (current_target
 | 
|---|
| 5808 |               && fragP->fr_type == rs_machine_dependent
 | 
|---|
| 5809 |               && fragP->fr_subtype == RELAX_ADD_NOP_IF_CLOSE_LOOP_END)
 | 
|---|
| 5810 |             {
 | 
|---|
| 5811 |               size_t min_bytes;
 | 
|---|
| 5812 |               size_t bytes_added = 0;
 | 
|---|
| 5813 | 
 | 
|---|
| 5814 | #define REQUIRED_LOOP_DIVIDING_BYTES 12
 | 
|---|
| 5815 |               /* Max out at 12.  */
 | 
|---|
| 5816 |               min_bytes = min_bytes_to_other_loop_end
 | 
|---|
| 5817 |                 (fragP->fr_next, current_target, current_offset,
 | 
|---|
| 5818 |                  REQUIRED_LOOP_DIVIDING_BYTES);
 | 
|---|
| 5819 | 
 | 
|---|
| 5820 |               if (min_bytes < REQUIRED_LOOP_DIVIDING_BYTES)
 | 
|---|
| 5821 |                 {
 | 
|---|
| 5822 |                   while (min_bytes + bytes_added
 | 
|---|
| 5823 |                          < REQUIRED_LOOP_DIVIDING_BYTES)
 | 
|---|
| 5824 |                     {
 | 
|---|
| 5825 |                       int length = 3;
 | 
|---|
| 5826 | 
 | 
|---|
| 5827 |                       if (fragP->fr_var < length)
 | 
|---|
| 5828 |                         as_warn (_("fr_var %lu < length %d; ignoring"),
 | 
|---|
| 5829 |                                  fragP->fr_var, length);
 | 
|---|
| 5830 |                       else
 | 
|---|
| 5831 |                         {
 | 
|---|
| 5832 |                           assemble_nop (length,
 | 
|---|
| 5833 |                                         fragP->fr_literal + fragP->fr_fix);
 | 
|---|
| 5834 |                           fragP->fr_fix += length;
 | 
|---|
| 5835 |                           fragP->fr_var -= length;
 | 
|---|
| 5836 |                         }
 | 
|---|
| 5837 |                       bytes_added += length;
 | 
|---|
| 5838 |                     }
 | 
|---|
| 5839 |                 }
 | 
|---|
| 5840 |               frag_wane (fragP);
 | 
|---|
| 5841 |             }
 | 
|---|
| 5842 |         }
 | 
|---|
| 5843 |     }
 | 
|---|
| 5844 | }
 | 
|---|
| 5845 | 
 | 
|---|
| 5846 | 
 | 
|---|
| 5847 | size_t
 | 
|---|
| 5848 | min_bytes_to_other_loop_end (fragP, current_target, current_offset, max_size)
 | 
|---|
| 5849 |      fragS *fragP;
 | 
|---|
| 5850 |      fragS *current_target;
 | 
|---|
| 5851 |      offsetT current_offset;
 | 
|---|
| 5852 |      size_t max_size;
 | 
|---|
| 5853 | {
 | 
|---|
| 5854 |   size_t offset = 0;
 | 
|---|
| 5855 |   fragS *current_fragP;
 | 
|---|
| 5856 | 
 | 
|---|
| 5857 |   for (current_fragP = fragP;
 | 
|---|
| 5858 |        current_fragP;
 | 
|---|
| 5859 |        current_fragP = current_fragP->fr_next)
 | 
|---|
| 5860 |     {
 | 
|---|
| 5861 |       if (current_fragP->tc_frag_data.is_loop_target
 | 
|---|
| 5862 |           && current_fragP != current_target)
 | 
|---|
| 5863 |         return offset + current_offset;
 | 
|---|
| 5864 | 
 | 
|---|
| 5865 |       offset += unrelaxed_frag_min_size (current_fragP);
 | 
|---|
| 5866 | 
 | 
|---|
| 5867 |       if (offset + current_offset >= max_size)
 | 
|---|
| 5868 |         return max_size;
 | 
|---|
| 5869 |     }
 | 
|---|
| 5870 |   return max_size;
 | 
|---|
| 5871 | }
 | 
|---|
| 5872 | 
 | 
|---|
| 5873 | 
 | 
|---|
| 5874 | size_t
 | 
|---|
| 5875 | unrelaxed_frag_min_size (fragP)
 | 
|---|
| 5876 |      fragS * fragP;
 | 
|---|
| 5877 | {
 | 
|---|
| 5878 |   size_t size = fragP->fr_fix;
 | 
|---|
| 5879 | 
 | 
|---|
| 5880 |   /* add fill size */
 | 
|---|
| 5881 |   if (fragP->fr_type == rs_fill)
 | 
|---|
| 5882 |     size += fragP->fr_offset;
 | 
|---|
| 5883 | 
 | 
|---|
| 5884 |   return size;
 | 
|---|
| 5885 | }
 | 
|---|
| 5886 | 
 | 
|---|
| 5887 | 
 | 
|---|
| 5888 | /* Re-process all of the fragments looking to convert all
 | 
|---|
| 5889 |    of the RELAX_ADD_NOP_IF_SHORT_LOOP.  If:
 | 
|---|
| 5890 | 
 | 
|---|
| 5891 |    A)
 | 
|---|
| 5892 |      1) the instruction size count to the loop end label
 | 
|---|
| 5893 |         is too short (<= 2 instructions),
 | 
|---|
| 5894 |      2) loop has a jump or branch in it
 | 
|---|
| 5895 | 
 | 
|---|
| 5896 |    or B)
 | 
|---|
| 5897 |      1) software_avoid_all_short_loops is true
 | 
|---|
| 5898 |      2) The generating loop was a  'loopgtz' or 'loopnez'
 | 
|---|
| 5899 |      3) the instruction size count to the loop end label is too short
 | 
|---|
| 5900 |         (<= 2 instructions)
 | 
|---|
| 5901 |    then convert this frag (and maybe the next one) to generate a NOP.
 | 
|---|
| 5902 |    In any case close it off with a .fill 0.  */
 | 
|---|
| 5903 | 
 | 
|---|
| 5904 | static void
 | 
|---|
| 5905 | xtensa_fix_short_loop_frags ()
 | 
|---|
| 5906 | {
 | 
|---|
| 5907 |   frchainS *frchP;
 | 
|---|
| 5908 | 
 | 
|---|
| 5909 |   /* When this routine is called, all of the subsections are still intact
 | 
|---|
| 5910 |      so we walk over subsections instead of sections.  */
 | 
|---|
| 5911 |   for (frchP = frchain_root; frchP; frchP = frchP->frch_next)
 | 
|---|
| 5912 |     {
 | 
|---|
| 5913 |       fragS *fragP;
 | 
|---|
| 5914 |       fragS *current_target = NULL;
 | 
|---|
| 5915 |       offsetT current_offset = 0;
 | 
|---|
| 5916 |       xtensa_opcode current_opcode = XTENSA_UNDEFINED;
 | 
|---|
| 5917 | 
 | 
|---|
| 5918 |       /* Walk over all of the fragments in a subsection.  */
 | 
|---|
| 5919 |       for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
 | 
|---|
| 5920 |         {
 | 
|---|
| 5921 |           /* check on the current loop */
 | 
|---|
| 5922 |           if (fragP->fr_type == rs_machine_dependent
 | 
|---|
| 5923 |               && fragP->fr_subtype == RELAX_IMMED)
 | 
|---|
| 5924 |             {
 | 
|---|
| 5925 |               /* Read it.  If the instruction is a loop, get the target.  */
 | 
|---|
| 5926 |               xtensa_opcode opcode = get_opcode_from_buf (fragP->fr_opcode);
 | 
|---|
| 5927 |               if (is_loop_opcode (opcode))
 | 
|---|
| 5928 |                 {
 | 
|---|
| 5929 |                   TInsn t_insn;
 | 
|---|
| 5930 | 
 | 
|---|
| 5931 |                   tinsn_from_chars (&t_insn, fragP->fr_opcode);
 | 
|---|
| 5932 |                   tinsn_immed_from_frag (&t_insn, fragP);
 | 
|---|
| 5933 | 
 | 
|---|
| 5934 |                   /* Get the current fragment target.  */
 | 
|---|
| 5935 |                   if (fragP->fr_symbol)
 | 
|---|
| 5936 |                     {
 | 
|---|
| 5937 |                       current_target = symbol_get_frag (fragP->fr_symbol);
 | 
|---|
| 5938 |                       current_offset = fragP->fr_offset;
 | 
|---|
| 5939 |                       current_opcode = opcode;
 | 
|---|
| 5940 |                     }
 | 
|---|
| 5941 |                 }
 | 
|---|
| 5942 |             }
 | 
|---|
| 5943 | 
 | 
|---|
| 5944 |           if (fragP->fr_type == rs_machine_dependent
 | 
|---|
| 5945 |               && fragP->fr_subtype == RELAX_ADD_NOP_IF_SHORT_LOOP)
 | 
|---|
| 5946 |             {
 | 
|---|
| 5947 |               size_t insn_count =
 | 
|---|
| 5948 |                 count_insns_to_loop_end (fragP->fr_next, TRUE, 3);
 | 
|---|
| 5949 |               if (insn_count < 3
 | 
|---|
| 5950 |                   && (branch_before_loop_end (fragP->fr_next)
 | 
|---|
| 5951 |                       || (software_avoid_all_short_loops
 | 
|---|
| 5952 |                           && current_opcode != XTENSA_UNDEFINED
 | 
|---|
| 5953 |                           && !is_the_loop_opcode (current_opcode))))
 | 
|---|
| 5954 |                 relax_frag_add_nop (fragP);
 | 
|---|
| 5955 |               else
 | 
|---|
| 5956 |                 frag_wane (fragP);
 | 
|---|
| 5957 |             }
 | 
|---|
| 5958 |         }
 | 
|---|
| 5959 |     }
 | 
|---|
| 5960 | }
 | 
|---|
| 5961 | 
 | 
|---|
| 5962 | 
 | 
|---|
| 5963 | size_t
 | 
|---|
| 5964 | count_insns_to_loop_end (base_fragP, count_relax_add, max_count)
 | 
|---|
| 5965 |      fragS *base_fragP;
 | 
|---|
| 5966 |      bfd_boolean count_relax_add;
 | 
|---|
| 5967 |      size_t max_count;
 | 
|---|
| 5968 | {
 | 
|---|
| 5969 |   fragS *fragP = NULL;
 | 
|---|
| 5970 |   size_t insn_count = 0;
 | 
|---|
| 5971 | 
 | 
|---|
| 5972 |   fragP = base_fragP;
 | 
|---|
| 5973 | 
 | 
|---|
| 5974 |   for (; fragP && !fragP->tc_frag_data.is_loop_target; fragP = fragP->fr_next)
 | 
|---|
| 5975 |     {
 | 
|---|
| 5976 |       insn_count += unrelaxed_frag_min_insn_count (fragP);
 | 
|---|
| 5977 |       if (insn_count >= max_count)
 | 
|---|
| 5978 |         return max_count;
 | 
|---|
| 5979 | 
 | 
|---|
| 5980 |       if (count_relax_add)
 | 
|---|
| 5981 |         {
 | 
|---|
| 5982 |           if (fragP->fr_type == rs_machine_dependent
 | 
|---|
| 5983 |               && fragP->fr_subtype == RELAX_ADD_NOP_IF_SHORT_LOOP)
 | 
|---|
| 5984 |             {
 | 
|---|
| 5985 |               /* In order to add the appropriate number of
 | 
|---|
| 5986 |                  NOPs, we count an instruction for downstream
 | 
|---|
| 5987 |                  occurrences.  */
 | 
|---|
| 5988 |               insn_count++;
 | 
|---|
| 5989 |               if (insn_count >= max_count)
 | 
|---|
| 5990 |                 return max_count;
 | 
|---|
| 5991 |             }
 | 
|---|
| 5992 |         }
 | 
|---|
| 5993 |     }
 | 
|---|
| 5994 |   return insn_count;
 | 
|---|
| 5995 | }
 | 
|---|
| 5996 | 
 | 
|---|
| 5997 | 
 | 
|---|
| 5998 | size_t
 | 
|---|
| 5999 | unrelaxed_frag_min_insn_count (fragP)
 | 
|---|
| 6000 |      fragS *fragP;
 | 
|---|
| 6001 | {
 | 
|---|
| 6002 |   size_t insn_count = 0;
 | 
|---|
| 6003 |   int offset = 0;
 | 
|---|
| 6004 | 
 | 
|---|
| 6005 |   if (!fragP->tc_frag_data.is_insn)
 | 
|---|
| 6006 |     return insn_count;
 | 
|---|
| 6007 | 
 | 
|---|
| 6008 |   /* Decode the fixed instructions.  */
 | 
|---|
| 6009 |   while (offset < fragP->fr_fix)
 | 
|---|
| 6010 |     {
 | 
|---|
| 6011 |       xtensa_opcode opcode = get_opcode_from_buf (fragP->fr_literal + offset);
 | 
|---|
| 6012 |       if (opcode == XTENSA_UNDEFINED)
 | 
|---|
| 6013 |         {
 | 
|---|
| 6014 |           as_fatal (_("undecodable instruction in instruction frag"));
 | 
|---|
| 6015 |           return insn_count;
 | 
|---|
| 6016 |         }
 | 
|---|
| 6017 |       offset += xtensa_insn_length (xtensa_default_isa, opcode);
 | 
|---|
| 6018 |       insn_count++;
 | 
|---|
| 6019 |     }
 | 
|---|
| 6020 | 
 | 
|---|
| 6021 |   return insn_count;
 | 
|---|
| 6022 | }
 | 
|---|
| 6023 | 
 | 
|---|
| 6024 | 
 | 
|---|
| 6025 | bfd_boolean
 | 
|---|
| 6026 | branch_before_loop_end (base_fragP)
 | 
|---|
| 6027 |      fragS *base_fragP;
 | 
|---|
| 6028 | {
 | 
|---|
| 6029 |   fragS *fragP;
 | 
|---|
| 6030 | 
 | 
|---|
| 6031 |   for (fragP = base_fragP;
 | 
|---|
| 6032 |        fragP && !fragP->tc_frag_data.is_loop_target;
 | 
|---|
| 6033 |        fragP = fragP->fr_next)
 | 
|---|
| 6034 |     {
 | 
|---|
| 6035 |       if (unrelaxed_frag_has_b_j (fragP))
 | 
|---|
| 6036 |         return TRUE;
 | 
|---|
| 6037 |     }
 | 
|---|
| 6038 |   return FALSE;
 | 
|---|
| 6039 | }
 | 
|---|
| 6040 | 
 | 
|---|
| 6041 | 
 | 
|---|
| 6042 | bfd_boolean
 | 
|---|
| 6043 | unrelaxed_frag_has_b_j (fragP)
 | 
|---|
| 6044 |      fragS *fragP;
 | 
|---|
| 6045 | {
 | 
|---|
| 6046 |   size_t insn_count = 0;
 | 
|---|
| 6047 |   int offset = 0;
 | 
|---|
| 6048 | 
 | 
|---|
| 6049 |   if (!fragP->tc_frag_data.is_insn)
 | 
|---|
| 6050 |     return FALSE;
 | 
|---|
| 6051 | 
 | 
|---|
| 6052 |   /* Decode the fixed instructions.  */
 | 
|---|
| 6053 |   while (offset < fragP->fr_fix)
 | 
|---|
| 6054 |     {
 | 
|---|
| 6055 |       xtensa_opcode opcode = get_opcode_from_buf (fragP->fr_literal + offset);
 | 
|---|
| 6056 |       if (opcode == XTENSA_UNDEFINED)
 | 
|---|
| 6057 |         {
 | 
|---|
| 6058 |           as_fatal (_("undecodable instruction in instruction frag"));
 | 
|---|
| 6059 |           return insn_count;
 | 
|---|
| 6060 |         }
 | 
|---|
| 6061 |       if (is_branch_or_jump_opcode (opcode))
 | 
|---|
| 6062 |         return TRUE;
 | 
|---|
| 6063 |       offset += xtensa_insn_length (xtensa_default_isa, opcode);
 | 
|---|
| 6064 |     }
 | 
|---|
| 6065 |   return FALSE;
 | 
|---|
| 6066 | }
 | 
|---|
| 6067 | 
 | 
|---|
| 6068 | 
 | 
|---|
| 6069 | /* Checks to be made after initial assembly but before relaxation.  */
 | 
|---|
| 6070 | 
 | 
|---|
| 6071 | static void
 | 
|---|
| 6072 | xtensa_sanity_check ()
 | 
|---|
| 6073 | {
 | 
|---|
| 6074 |   char *file_name;
 | 
|---|
| 6075 |   int line;
 | 
|---|
| 6076 | 
 | 
|---|
| 6077 |   frchainS *frchP;
 | 
|---|
| 6078 | 
 | 
|---|
| 6079 |   as_where (&file_name, &line);
 | 
|---|
| 6080 |   for (frchP = frchain_root; frchP; frchP = frchP->frch_next)
 | 
|---|
| 6081 |     {
 | 
|---|
| 6082 |       fragS *fragP;
 | 
|---|
| 6083 | 
 | 
|---|
| 6084 |       /* Walk over all of the fragments in a subsection.  */
 | 
|---|
| 6085 |       for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
 | 
|---|
| 6086 |         {
 | 
|---|
| 6087 |           /* Currently we only check for empty loops here.  */
 | 
|---|
| 6088 |           if (fragP->fr_type == rs_machine_dependent
 | 
|---|
| 6089 |               && fragP->fr_subtype == RELAX_IMMED)
 | 
|---|
| 6090 |             {
 | 
|---|
| 6091 |               static xtensa_insnbuf insnbuf = NULL;
 | 
|---|
| 6092 |               TInsn t_insn;
 | 
|---|
| 6093 | 
 | 
|---|
| 6094 |               if (fragP->fr_opcode != NULL)
 | 
|---|
| 6095 |                 {
 | 
|---|
| 6096 |                   if (!insnbuf)
 | 
|---|
| 6097 |                     insnbuf = xtensa_insnbuf_alloc (xtensa_default_isa);
 | 
|---|
| 6098 |                   tinsn_from_chars (&t_insn, fragP->fr_opcode);
 | 
|---|
| 6099 |                   tinsn_immed_from_frag (&t_insn, fragP);
 | 
|---|
| 6100 | 
 | 
|---|
| 6101 |                   if (is_loop_opcode (t_insn.opcode))
 | 
|---|
| 6102 |                     {
 | 
|---|
| 6103 |                       if (is_empty_loop (&t_insn, fragP))
 | 
|---|
| 6104 |                         {
 | 
|---|
| 6105 |                           new_logical_line (fragP->fr_file, fragP->fr_line);
 | 
|---|
| 6106 |                           as_bad (_("invalid empty loop"));
 | 
|---|
| 6107 |                         }
 | 
|---|
| 6108 |                       if (!is_local_forward_loop (&t_insn, fragP))
 | 
|---|
| 6109 |                         {
 | 
|---|
| 6110 |                           new_logical_line (fragP->fr_file, fragP->fr_line);
 | 
|---|
| 6111 |                           as_bad (_("loop target does not follow "
 | 
|---|
| 6112 |                                     "loop instruction in section"));
 | 
|---|
| 6113 |                         }
 | 
|---|
| 6114 |                     }
 | 
|---|
| 6115 |                 }
 | 
|---|
| 6116 |             }
 | 
|---|
| 6117 |         }
 | 
|---|
| 6118 |     }
 | 
|---|
| 6119 |   new_logical_line (file_name, line);
 | 
|---|
| 6120 | }
 | 
|---|
| 6121 | 
 | 
|---|
| 6122 | 
 | 
|---|
| 6123 | #define LOOP_IMMED_OPN 1
 | 
|---|
| 6124 | 
 | 
|---|
| 6125 | /* Return true if the loop target is the next non-zero fragment.  */
 | 
|---|
| 6126 | 
 | 
|---|
| 6127 | bfd_boolean
 | 
|---|
| 6128 | is_empty_loop (insn, fragP)
 | 
|---|
| 6129 |      const TInsn *insn;
 | 
|---|
| 6130 |      fragS *fragP;
 | 
|---|
| 6131 | {
 | 
|---|
| 6132 |   const expressionS *expr;
 | 
|---|
| 6133 |   symbolS *symbolP;
 | 
|---|
| 6134 |   fragS *next_fragP;
 | 
|---|
| 6135 | 
 | 
|---|
| 6136 |   if (insn->insn_type != ITYPE_INSN)
 | 
|---|
| 6137 |     return FALSE;
 | 
|---|
| 6138 | 
 | 
|---|
| 6139 |   if (!is_loop_opcode (insn->opcode))
 | 
|---|
| 6140 |     return FALSE;
 | 
|---|
| 6141 | 
 | 
|---|
| 6142 |   if (insn->ntok <= LOOP_IMMED_OPN)
 | 
|---|
| 6143 |     return FALSE;
 | 
|---|
| 6144 | 
 | 
|---|
| 6145 |   expr = &insn->tok[LOOP_IMMED_OPN];
 | 
|---|
| 6146 | 
 | 
|---|
| 6147 |   if (expr->X_op != O_symbol)
 | 
|---|
| 6148 |     return FALSE;
 | 
|---|
| 6149 | 
 | 
|---|
| 6150 |   symbolP = expr->X_add_symbol;
 | 
|---|
| 6151 |   if (!symbolP)
 | 
|---|
| 6152 |     return FALSE;
 | 
|---|
| 6153 | 
 | 
|---|
| 6154 |   if (symbol_get_frag (symbolP) == NULL)
 | 
|---|
| 6155 |     return FALSE;
 | 
|---|
| 6156 | 
 | 
|---|
| 6157 |   if (S_GET_VALUE (symbolP) != 0)
 | 
|---|
| 6158 |     return FALSE;
 | 
|---|
| 6159 | 
 | 
|---|
| 6160 |   /* Walk through the zero-size fragments from this one.  If we find
 | 
|---|
| 6161 |      the target fragment, then this is a zero-size loop.  */
 | 
|---|
| 6162 |   for (next_fragP = fragP->fr_next;
 | 
|---|
| 6163 |        next_fragP != NULL;
 | 
|---|
| 6164 |        next_fragP = next_fragP->fr_next)
 | 
|---|
| 6165 |     {
 | 
|---|
| 6166 |       if (next_fragP == symbol_get_frag (symbolP))
 | 
|---|
| 6167 |         return TRUE;
 | 
|---|
| 6168 |       if (next_fragP->fr_fix != 0)
 | 
|---|
| 6169 |         return FALSE;
 | 
|---|
| 6170 |     }
 | 
|---|
| 6171 |   return FALSE;
 | 
|---|
| 6172 | }
 | 
|---|
| 6173 | 
 | 
|---|
| 6174 | 
 | 
|---|
| 6175 | bfd_boolean
 | 
|---|
| 6176 | is_local_forward_loop (insn, fragP)
 | 
|---|
| 6177 |      const TInsn *insn;
 | 
|---|
| 6178 |      fragS *fragP;
 | 
|---|
| 6179 | {
 | 
|---|
| 6180 |   const expressionS *expr;
 | 
|---|
| 6181 |   symbolS *symbolP;
 | 
|---|
| 6182 |   fragS *next_fragP;
 | 
|---|
| 6183 | 
 | 
|---|
| 6184 |   if (insn->insn_type != ITYPE_INSN)
 | 
|---|
| 6185 |     return FALSE;
 | 
|---|
| 6186 | 
 | 
|---|
| 6187 |   if (!is_loop_opcode (insn->opcode))
 | 
|---|
| 6188 |     return FALSE;
 | 
|---|
| 6189 | 
 | 
|---|
| 6190 |   if (insn->ntok <= LOOP_IMMED_OPN)
 | 
|---|
| 6191 |     return FALSE;
 | 
|---|
| 6192 | 
 | 
|---|
| 6193 |   expr = &insn->tok[LOOP_IMMED_OPN];
 | 
|---|
| 6194 | 
 | 
|---|
| 6195 |   if (expr->X_op != O_symbol)
 | 
|---|
| 6196 |     return FALSE;
 | 
|---|
| 6197 | 
 | 
|---|
| 6198 |   symbolP = expr->X_add_symbol;
 | 
|---|
| 6199 |   if (!symbolP)
 | 
|---|
| 6200 |     return FALSE;
 | 
|---|
| 6201 | 
 | 
|---|
| 6202 |   if (symbol_get_frag (symbolP) == NULL)
 | 
|---|
| 6203 |     return FALSE;
 | 
|---|
| 6204 | 
 | 
|---|
| 6205 |   /* Walk through fragments until we find the target.
 | 
|---|
| 6206 |      If we do not find the target, then this is an invalid loop.  */
 | 
|---|
| 6207 |   for (next_fragP = fragP->fr_next;
 | 
|---|
| 6208 |        next_fragP != NULL;
 | 
|---|
| 6209 |        next_fragP = next_fragP->fr_next)
 | 
|---|
| 6210 |     if (next_fragP == symbol_get_frag (symbolP))
 | 
|---|
| 6211 |       return TRUE;
 | 
|---|
| 6212 | 
 | 
|---|
| 6213 |   return FALSE;
 | 
|---|
| 6214 | }
 | 
|---|
| 6215 | 
 | 
|---|
| 6216 |  | 
|---|
| 6217 | 
 | 
|---|
| 6218 | /* Alignment Functions.  */
 | 
|---|
| 6219 | 
 | 
|---|
| 6220 | size_t
 | 
|---|
| 6221 | get_text_align_power (target_size)
 | 
|---|
| 6222 |      int target_size;
 | 
|---|
| 6223 | {
 | 
|---|
| 6224 |   size_t i = 0;
 | 
|---|
| 6225 |   for (i = 0; i < sizeof (size_t); i++)
 | 
|---|
| 6226 |     {
 | 
|---|
| 6227 |       if (target_size <= (1 << i))
 | 
|---|
| 6228 |         return i;
 | 
|---|
| 6229 |     }
 | 
|---|
| 6230 |   as_fatal (_("get_text_align_power: argument too large"));
 | 
|---|
| 6231 |   return 0;
 | 
|---|
| 6232 | }
 | 
|---|
| 6233 | 
 | 
|---|
| 6234 | 
 | 
|---|
| 6235 | addressT
 | 
|---|
| 6236 | get_text_align_max_fill_size (align_pow, use_nops, use_no_density)
 | 
|---|
| 6237 |      int align_pow;
 | 
|---|
| 6238 |      bfd_boolean use_nops;
 | 
|---|
| 6239 |      bfd_boolean use_no_density;
 | 
|---|
| 6240 | {
 | 
|---|
| 6241 |   if (!use_nops)
 | 
|---|
| 6242 |     return (1 << align_pow);
 | 
|---|
| 6243 |   if (use_no_density)
 | 
|---|
| 6244 |     return 3 * (1 << align_pow);
 | 
|---|
| 6245 | 
 | 
|---|
| 6246 |   return 1 + (1 << align_pow);
 | 
|---|
| 6247 | }
 | 
|---|
| 6248 | 
 | 
|---|
| 6249 | 
 | 
|---|
| 6250 | /* get_text_align_fill_size ()
 | 
|---|
| 6251 |   
 | 
|---|
| 6252 |    Desired alignments:
 | 
|---|
| 6253 |       give the address
 | 
|---|
| 6254 |       target_size = size of next instruction
 | 
|---|
| 6255 |       align_pow = get_text_align_power (target_size).
 | 
|---|
| 6256 |       use_nops = 0
 | 
|---|
| 6257 |       use_no_density = 0;
 | 
|---|
| 6258 |    Loop alignments:
 | 
|---|
| 6259 |       address = current address + loop instruction size;
 | 
|---|
| 6260 |       target_size = 3 (for 2 or 3 byte target)
 | 
|---|
| 6261 |                   = 8 (for 8 byte target)
 | 
|---|
| 6262 |       align_pow = get_text_align_power (target_size);
 | 
|---|
| 6263 |       use_nops = 1
 | 
|---|
| 6264 |       use_no_density = set appropriately
 | 
|---|
| 6265 |    Text alignments:
 | 
|---|
| 6266 |       address = current address + loop instruction size;
 | 
|---|
| 6267 |       target_size = 0
 | 
|---|
| 6268 |       align_pow = get_text_align_power (target_size);
 | 
|---|
| 6269 |       use_nops = 0
 | 
|---|
| 6270 |       use_no_density = 0.  */
 | 
|---|
| 6271 | 
 | 
|---|
| 6272 | addressT
 | 
|---|
| 6273 | get_text_align_fill_size (address, align_pow, target_size,
 | 
|---|
| 6274 |                           use_nops, use_no_density)
 | 
|---|
| 6275 |      addressT address;
 | 
|---|
| 6276 |      int align_pow;
 | 
|---|
| 6277 |      int target_size;
 | 
|---|
| 6278 |      bfd_boolean use_nops;
 | 
|---|
| 6279 |      bfd_boolean use_no_density;
 | 
|---|
| 6280 | {
 | 
|---|
| 6281 |   /* Input arguments:
 | 
|---|
| 6282 | 
 | 
|---|
| 6283 |      align_pow: log2 (required alignment).
 | 
|---|
| 6284 | 
 | 
|---|
| 6285 |      target_size: alignment must allow the new_address and
 | 
|---|
| 6286 |      new_address+target_size-1.
 | 
|---|
| 6287 | 
 | 
|---|
| 6288 |      use_nops: if true, then we can only use 2 or 3 byte nops.
 | 
|---|
| 6289 | 
 | 
|---|
| 6290 |      use_no_density: if use_nops and use_no_density, we can only use
 | 
|---|
| 6291 |      3-byte nops.
 | 
|---|
| 6292 | 
 | 
|---|
| 6293 |      Usually, for non-zero target_size, the align_pow is the power of 2
 | 
|---|
| 6294 |      that is greater than or equal to the target_size.  This handles the
 | 
|---|
| 6295 |      2-byte, 3-byte and 8-byte instructions.  */
 | 
|---|
| 6296 | 
 | 
|---|
| 6297 |   size_t alignment = (1 << align_pow);
 | 
|---|
| 6298 |   if (!use_nops)
 | 
|---|
| 6299 |     {
 | 
|---|
| 6300 |       /* This is the easy case.  */
 | 
|---|
| 6301 |       size_t mod;
 | 
|---|
| 6302 |       mod = address % alignment;
 | 
|---|
| 6303 |       if (mod != 0)
 | 
|---|
| 6304 |         mod = alignment - mod;
 | 
|---|
| 6305 |       assert ((address + mod) % alignment == 0);
 | 
|---|
| 6306 |       return mod;
 | 
|---|
| 6307 |     }
 | 
|---|
| 6308 | 
 | 
|---|
| 6309 |   /* This is the slightly harder case.  */
 | 
|---|
| 6310 |   assert ((int) alignment >= target_size);
 | 
|---|
| 6311 |   assert (target_size > 0);
 | 
|---|
| 6312 |   if (!use_no_density)
 | 
|---|
| 6313 |     {
 | 
|---|
| 6314 |       size_t i;
 | 
|---|
| 6315 |       for (i = 0; i < alignment * 2; i++)
 | 
|---|
| 6316 |         {
 | 
|---|
| 6317 |           if (i == 1)
 | 
|---|
| 6318 |             continue;
 | 
|---|
| 6319 |           if ((address + i) >> align_pow ==
 | 
|---|
| 6320 |               (address + i + target_size - 1) >> align_pow)
 | 
|---|
| 6321 |             return i;
 | 
|---|
| 6322 |         }
 | 
|---|
| 6323 |     }
 | 
|---|
| 6324 |   else
 | 
|---|
| 6325 |     {
 | 
|---|
| 6326 |       size_t i;
 | 
|---|
| 6327 | 
 | 
|---|
| 6328 |       /* Can only fill multiples of 3.  */
 | 
|---|
| 6329 |       for (i = 0; i <= alignment * 3; i += 3)
 | 
|---|
| 6330 |         {
 | 
|---|
| 6331 |           if ((address + i) >> align_pow ==
 | 
|---|
| 6332 |               (address + i + target_size - 1) >> align_pow)
 | 
|---|
| 6333 |             return i;
 | 
|---|
| 6334 |         }
 | 
|---|
| 6335 |     }
 | 
|---|
| 6336 |   assert (0);
 | 
|---|
| 6337 |   return 0;
 | 
|---|
| 6338 | }
 | 
|---|
| 6339 | 
 | 
|---|
| 6340 | 
 | 
|---|
| 6341 | /* This will assert if it is not possible.  */
 | 
|---|
| 6342 | 
 | 
|---|
| 6343 | size_t
 | 
|---|
| 6344 | get_text_align_nop_count (fill_size, use_no_density)
 | 
|---|
| 6345 |      size_t fill_size;
 | 
|---|
| 6346 |      bfd_boolean use_no_density;
 | 
|---|
| 6347 | {
 | 
|---|
| 6348 |   size_t count = 0;
 | 
|---|
| 6349 |   if (use_no_density)
 | 
|---|
| 6350 |     {
 | 
|---|
| 6351 |       assert (fill_size % 3 == 0);
 | 
|---|
| 6352 |       return (fill_size / 3);
 | 
|---|
| 6353 |     }
 | 
|---|
| 6354 | 
 | 
|---|
| 6355 |   assert (fill_size != 1);      /* Bad argument.  */
 | 
|---|
| 6356 | 
 | 
|---|
| 6357 |   while (fill_size > 1)
 | 
|---|
| 6358 |     {
 | 
|---|
| 6359 |       size_t insn_size = 3;
 | 
|---|
| 6360 |       if (fill_size == 2 || fill_size == 4)
 | 
|---|
| 6361 |         insn_size = 2;
 | 
|---|
| 6362 |       fill_size -= insn_size;
 | 
|---|
| 6363 |       count++;
 | 
|---|
| 6364 |     }
 | 
|---|
| 6365 |   assert (fill_size != 1);      /* Bad algorithm.  */
 | 
|---|
| 6366 |   return count;
 | 
|---|
| 6367 | }
 | 
|---|
| 6368 | 
 | 
|---|
| 6369 | 
 | 
|---|
| 6370 | size_t
 | 
|---|
| 6371 | get_text_align_nth_nop_size (fill_size, n, use_no_density)
 | 
|---|
| 6372 |      size_t fill_size;
 | 
|---|
| 6373 |      size_t n;
 | 
|---|
| 6374 |      bfd_boolean use_no_density;
 | 
|---|
| 6375 | {
 | 
|---|
| 6376 |   size_t count = 0;
 | 
|---|
| 6377 | 
 | 
|---|
| 6378 |   assert (get_text_align_nop_count (fill_size, use_no_density) > n);
 | 
|---|
| 6379 | 
 | 
|---|
| 6380 |   if (use_no_density)
 | 
|---|
| 6381 |     return 3;
 | 
|---|
| 6382 | 
 | 
|---|
| 6383 |   while (fill_size > 1)
 | 
|---|
| 6384 |     {
 | 
|---|
| 6385 |       size_t insn_size = 3;
 | 
|---|
| 6386 |       if (fill_size == 2 || fill_size == 4)
 | 
|---|
| 6387 |         insn_size = 2;
 | 
|---|
| 6388 |       fill_size -= insn_size;
 | 
|---|
| 6389 |       count++;
 | 
|---|
| 6390 |       if (n + 1 == count)
 | 
|---|
| 6391 |         return insn_size;
 | 
|---|
| 6392 |     }
 | 
|---|
| 6393 |   assert (0);
 | 
|---|
| 6394 |   return 0;
 | 
|---|
| 6395 | }
 | 
|---|
| 6396 | 
 | 
|---|
| 6397 | 
 | 
|---|
| 6398 | /* For the given fragment, find the appropriate address
 | 
|---|
| 6399 |    for it to begin at if we are using NOPs to align it.  */
 | 
|---|
| 6400 | 
 | 
|---|
| 6401 | static addressT
 | 
|---|
| 6402 | get_noop_aligned_address (fragP, address)
 | 
|---|
| 6403 |      fragS *fragP;
 | 
|---|
| 6404 |      addressT address;
 | 
|---|
| 6405 | {
 | 
|---|
| 6406 |   static xtensa_insnbuf insnbuf = NULL;
 | 
|---|
| 6407 |   size_t fill_size = 0;
 | 
|---|
| 6408 | 
 | 
|---|
| 6409 |   if (!insnbuf)
 | 
|---|
| 6410 |     insnbuf = xtensa_insnbuf_alloc (xtensa_default_isa);
 | 
|---|
| 6411 | 
 | 
|---|
| 6412 |   switch (fragP->fr_type)
 | 
|---|
| 6413 |     {
 | 
|---|
| 6414 |     case rs_machine_dependent:
 | 
|---|
| 6415 |       if (fragP->fr_subtype == RELAX_ALIGN_NEXT_OPCODE)
 | 
|---|
| 6416 |         {
 | 
|---|
| 6417 |           /* The rule is: get next fragment's FIRST instruction.  Find
 | 
|---|
| 6418 |              the smallest number of bytes that need to be added to
 | 
|---|
| 6419 |              ensure that the next fragment's FIRST instruction will fit
 | 
|---|
| 6420 |              in a single word.
 | 
|---|
| 6421 | 
 | 
|---|
| 6422 |              E.G.,   2 bytes : 0, 1, 2 mod 4 
 | 
|---|
| 6423 |                      3 bytes: 0, 1 mod 4 
 | 
|---|
| 6424 | 
 | 
|---|
| 6425 |              If the FIRST instruction MIGHT be relaxed, 
 | 
|---|
| 6426 |              assume that it will become a 3 byte instruction.  */
 | 
|---|
| 6427 | 
 | 
|---|
| 6428 |           int target_insn_size;
 | 
|---|
| 6429 |           xtensa_opcode opcode = next_frag_opcode (fragP);
 | 
|---|
| 6430 |           addressT pre_opcode_bytes;
 | 
|---|
| 6431 | 
 | 
|---|
| 6432 |           if (opcode == XTENSA_UNDEFINED)
 | 
|---|
| 6433 |             {
 | 
|---|
| 6434 |               as_bad_where (fragP->fr_file, fragP->fr_line,
 | 
|---|
| 6435 |                             _("invalid opcode for RELAX_ALIGN_NEXT_OPCODE"));
 | 
|---|
| 6436 |               as_fatal (_("cannot continue"));
 | 
|---|
| 6437 |             }
 | 
|---|
| 6438 | 
 | 
|---|
| 6439 |           target_insn_size = xtensa_insn_length (xtensa_default_isa, opcode);
 | 
|---|
| 6440 | 
 | 
|---|
| 6441 |           pre_opcode_bytes = next_frag_pre_opcode_bytes (fragP);
 | 
|---|
| 6442 | 
 | 
|---|
| 6443 |           if (is_loop_opcode (opcode))
 | 
|---|
| 6444 |             {
 | 
|---|
| 6445 |               /* next_fragP should be the loop.  */
 | 
|---|
| 6446 |               const fragS *next_fragP = next_non_empty_frag (fragP);
 | 
|---|
| 6447 |               xtensa_opcode next_opcode = next_frag_opcode (next_fragP);
 | 
|---|
| 6448 |               size_t alignment;
 | 
|---|
| 6449 | 
 | 
|---|
| 6450 |               pre_opcode_bytes += target_insn_size;
 | 
|---|
| 6451 | 
 | 
|---|
| 6452 |               /* For loops, the alignment depends on the size of the
 | 
|---|
| 6453 |                  instruction following the loop, not the loop instruction.  */
 | 
|---|
| 6454 |               if (next_opcode == XTENSA_UNDEFINED)
 | 
|---|
| 6455 |                 target_insn_size = 3;
 | 
|---|
| 6456 |               else
 | 
|---|
| 6457 |                 {
 | 
|---|
| 6458 |                   target_insn_size =
 | 
|---|
| 6459 |                     xtensa_insn_length (xtensa_default_isa, next_opcode);
 | 
|---|
| 6460 | 
 | 
|---|
| 6461 |                   if (target_insn_size == 2)
 | 
|---|
| 6462 |                     target_insn_size = 3;       /* ISA specifies this.  */
 | 
|---|
| 6463 |                 }
 | 
|---|
| 6464 | 
 | 
|---|
| 6465 |               /* If it was 8, then we'll need a larger alignment
 | 
|---|
| 6466 |                  for the section.  */
 | 
|---|
| 6467 |               alignment = get_text_align_power (target_insn_size);
 | 
|---|
| 6468 | 
 | 
|---|
| 6469 |               /* Is Now_seg valid */
 | 
|---|
| 6470 |               record_alignment (now_seg, alignment);
 | 
|---|
| 6471 |             }
 | 
|---|
| 6472 |           else
 | 
|---|
| 6473 |             as_fatal (_("expected loop opcode in relax align next target"));
 | 
|---|
| 6474 | 
 | 
|---|
| 6475 |           fill_size = get_text_align_fill_size
 | 
|---|
| 6476 |             (address + pre_opcode_bytes,
 | 
|---|
| 6477 |              get_text_align_power (target_insn_size),
 | 
|---|
| 6478 |              target_insn_size, TRUE, fragP->tc_frag_data.is_no_density);
 | 
|---|
| 6479 |         }
 | 
|---|
| 6480 |       break;
 | 
|---|
| 6481 | #if 0
 | 
|---|
| 6482 |     case rs_align:
 | 
|---|
| 6483 |     case rs_align_code:
 | 
|---|
| 6484 |       fill_size = get_text_align_fill_size
 | 
|---|
| 6485 |         (address, fragP->fr_offset, 1, TRUE,
 | 
|---|
| 6486 |          fragP->tc_frag_data.is_no_density);
 | 
|---|
| 6487 |       break;
 | 
|---|
| 6488 | #endif
 | 
|---|
| 6489 |     default:
 | 
|---|
| 6490 |       as_fatal (_("expected align_code or RELAX_ALIGN_NEXT_OPCODE"));
 | 
|---|
| 6491 |     }
 | 
|---|
| 6492 | 
 | 
|---|
| 6493 |   return address + fill_size;
 | 
|---|
| 6494 | }
 | 
|---|
| 6495 | 
 | 
|---|
| 6496 | 
 | 
|---|
| 6497 | /* 3 mechanisms for relaxing an alignment: 
 | 
|---|
| 6498 |    
 | 
|---|
| 6499 |    Align to a power of 2. 
 | 
|---|
| 6500 |    Align so the next fragment's instruction does not cross a word boundary. 
 | 
|---|
| 6501 |    Align the current instruction so that if the next instruction 
 | 
|---|
| 6502 |        were 3 bytes, it would not cross a word boundary. 
 | 
|---|
| 6503 |    
 | 
|---|
| 6504 |    We can align with:
 | 
|---|
| 6505 | 
 | 
|---|
| 6506 |    zeros    - This is easy; always insert zeros. 
 | 
|---|
| 6507 |    nops     - 3 and 2 byte instructions 
 | 
|---|
| 6508 |               2 - 2 byte nop 
 | 
|---|
| 6509 |               3 - 3 byte nop 
 | 
|---|
| 6510 |               4 - 2, 2-byte nops 
 | 
|---|
| 6511 |               >=5 : 3 byte instruction + fn(n-3) 
 | 
|---|
| 6512 |    widening - widen previous instructions.  */
 | 
|---|
| 6513 | 
 | 
|---|
| 6514 | static addressT
 | 
|---|
| 6515 | get_widen_aligned_address (fragP, address)
 | 
|---|
| 6516 |      fragS *fragP;
 | 
|---|
| 6517 |      addressT address;
 | 
|---|
| 6518 | {
 | 
|---|
| 6519 |   addressT align_pow, new_address, loop_insn_offset;
 | 
|---|
| 6520 |   fragS *next_frag;
 | 
|---|
| 6521 |   int insn_size;
 | 
|---|
| 6522 |   xtensa_opcode opcode, next_opcode;
 | 
|---|
| 6523 |   static xtensa_insnbuf insnbuf = NULL;
 | 
|---|
| 6524 | 
 | 
|---|
| 6525 |   if (!insnbuf)
 | 
|---|
| 6526 |     insnbuf = xtensa_insnbuf_alloc (xtensa_default_isa);
 | 
|---|
| 6527 | 
 | 
|---|
| 6528 |   if (fragP->fr_type == rs_align || fragP->fr_type == rs_align_code)
 | 
|---|
| 6529 |     {
 | 
|---|
| 6530 |       align_pow = fragP->fr_offset;
 | 
|---|
| 6531 |       new_address = ((address + ((1 << align_pow) - 1))
 | 
|---|
| 6532 |                      << align_pow) >> align_pow;
 | 
|---|
| 6533 |       return new_address;
 | 
|---|
| 6534 |     }
 | 
|---|
| 6535 | 
 | 
|---|
| 6536 |   if (fragP->fr_type == rs_machine_dependent)
 | 
|---|
| 6537 |     {
 | 
|---|
| 6538 |       switch (fragP->fr_subtype)
 | 
|---|
| 6539 |         {
 | 
|---|
| 6540 |         case RELAX_DESIRE_ALIGN:
 | 
|---|
| 6541 | 
 | 
|---|
| 6542 |           /* The rule is: get the next fragment's FIRST instruction. 
 | 
|---|
| 6543 |              Find the smallest number of bytes needed to be added 
 | 
|---|
| 6544 |              in order to ensure that the next fragment is FIRST 
 | 
|---|
| 6545 |              instruction will fit in a single word. 
 | 
|---|
| 6546 |              i.e.    2 bytes : 0, 1, 2.  mod 4 
 | 
|---|
| 6547 |                      3 bytes: 0, 1 mod 4 
 | 
|---|
| 6548 |              If the FIRST instruction MIGHT be relaxed, 
 | 
|---|
| 6549 |              assume that it will become a 3-byte instruction.  */
 | 
|---|
| 6550 | 
 | 
|---|
| 6551 |           insn_size = 3;
 | 
|---|
| 6552 |           /* Check to see if it might be 2 bytes.  */
 | 
|---|
| 6553 |           next_opcode = next_frag_opcode (fragP);
 | 
|---|
| 6554 |           if (next_opcode != XTENSA_UNDEFINED
 | 
|---|
| 6555 |               && xtensa_insn_length (xtensa_default_isa, next_opcode) == 2)
 | 
|---|
| 6556 |             insn_size = 2;
 | 
|---|
| 6557 | 
 | 
|---|
| 6558 |           assert (insn_size <= 4);
 | 
|---|
| 6559 |           for (new_address = address; new_address < address + 4; new_address++)
 | 
|---|
| 6560 |             {
 | 
|---|
| 6561 |               if (new_address >> 2 == (new_address + insn_size - 1) >> 2)
 | 
|---|
| 6562 |                 return new_address;
 | 
|---|
| 6563 |             }
 | 
|---|
| 6564 |           as_bad (_("internal error aligning"));
 | 
|---|
| 6565 |           return address;
 | 
|---|
| 6566 | 
 | 
|---|
| 6567 |         case RELAX_ALIGN_NEXT_OPCODE:
 | 
|---|
| 6568 |           /* The rule is: get next fragment's FIRST instruction. 
 | 
|---|
| 6569 |              Find the smallest number of bytes needed to be added 
 | 
|---|
| 6570 |              in order to ensure that the next fragment's FIRST 
 | 
|---|
| 6571 |              instruction will fit in a single word. 
 | 
|---|
| 6572 |              i.e.    2 bytes : 0, 1, 2.  mod 4 
 | 
|---|
| 6573 |                      3 bytes: 0, 1 mod 4 
 | 
|---|
| 6574 |              If the FIRST instruction MIGHT be relaxed, 
 | 
|---|
| 6575 |              assume that it will become a 3 byte instruction.  */
 | 
|---|
| 6576 | 
 | 
|---|
| 6577 |           opcode = next_frag_opcode (fragP);
 | 
|---|
| 6578 |           if (opcode == XTENSA_UNDEFINED)
 | 
|---|
| 6579 |             {
 | 
|---|
| 6580 |               as_bad_where (fragP->fr_file, fragP->fr_line,
 | 
|---|
| 6581 |                             _("invalid opcode for RELAX_ALIGN_NEXT_OPCODE"));
 | 
|---|
| 6582 |               as_fatal (_("cannot continue"));
 | 
|---|
| 6583 |             }
 | 
|---|
| 6584 |           insn_size = xtensa_insn_length (xtensa_default_isa, opcode);
 | 
|---|
| 6585 |           assert (insn_size <= 4);
 | 
|---|
| 6586 |           assert (is_loop_opcode (opcode));
 | 
|---|
| 6587 | 
 | 
|---|
| 6588 |           loop_insn_offset = 0;
 | 
|---|
| 6589 |           next_frag = next_non_empty_frag (fragP);
 | 
|---|
| 6590 | 
 | 
|---|
| 6591 |           /* If the loop has been expanded then the loop
 | 
|---|
| 6592 |              instruction could be at an offset from this fragment.  */
 | 
|---|
| 6593 |           if (next_frag->fr_subtype != RELAX_IMMED)
 | 
|---|
| 6594 |             loop_insn_offset = get_expanded_loop_offset (opcode);
 | 
|---|
| 6595 | 
 | 
|---|
| 6596 |           for (new_address = address; new_address < address + 4; new_address++)
 | 
|---|
| 6597 |             {
 | 
|---|
| 6598 |               if ((new_address + loop_insn_offset + insn_size) >> 2 ==
 | 
|---|
| 6599 |                   (new_address + loop_insn_offset + insn_size + 2) >> 2)
 | 
|---|
| 6600 |                 return new_address;
 | 
|---|
| 6601 |             }
 | 
|---|
| 6602 |           as_bad (_("internal error aligning"));
 | 
|---|
| 6603 |           return address;
 | 
|---|
| 6604 | 
 | 
|---|
| 6605 |         default:
 | 
|---|
| 6606 |           as_bad (_("internal error aligning"));
 | 
|---|
| 6607 |           return address;
 | 
|---|
| 6608 |         }
 | 
|---|
| 6609 |     }
 | 
|---|
| 6610 |   as_bad (_("internal error aligning"));
 | 
|---|
| 6611 |   return address;
 | 
|---|
| 6612 | }
 | 
|---|
| 6613 | 
 | 
|---|
| 6614 |  | 
|---|
| 6615 | 
 | 
|---|
| 6616 | /* md_relax_frag Hook and Helper Functions.  */
 | 
|---|
| 6617 | 
 | 
|---|
| 6618 | /* Return the number of bytes added to this fragment, given that the
 | 
|---|
| 6619 |    input has been stretched already by "stretch".  */
 | 
|---|
| 6620 | 
 | 
|---|
| 6621 | long
 | 
|---|
| 6622 | xtensa_relax_frag (fragP, stretch, stretched_p)
 | 
|---|
| 6623 |      fragS *fragP;
 | 
|---|
| 6624 |      long stretch;
 | 
|---|
| 6625 |      int *stretched_p;
 | 
|---|
| 6626 | {
 | 
|---|
| 6627 |   int unreported = fragP->tc_frag_data.unreported_expansion;
 | 
|---|
| 6628 |   long new_stretch = 0;
 | 
|---|
| 6629 |   char *file_name;
 | 
|---|
| 6630 |   int line, lit_size;
 | 
|---|
| 6631 | 
 | 
|---|
| 6632 |   as_where (&file_name, &line);
 | 
|---|
| 6633 |   new_logical_line (fragP->fr_file, fragP->fr_line);
 | 
|---|
| 6634 | 
 | 
|---|
| 6635 |   fragP->tc_frag_data.unreported_expansion = 0;
 | 
|---|
| 6636 | 
 | 
|---|
| 6637 |   switch (fragP->fr_subtype)
 | 
|---|
| 6638 |     {
 | 
|---|
| 6639 |     case RELAX_ALIGN_NEXT_OPCODE:
 | 
|---|
| 6640 |       /* Always convert.  */
 | 
|---|
| 6641 |       new_stretch = relax_frag_text_align (fragP, stretch);
 | 
|---|
| 6642 |       break;
 | 
|---|
| 6643 | 
 | 
|---|
| 6644 |     case RELAX_LOOP_END:
 | 
|---|
| 6645 |       /* Do nothing.  */
 | 
|---|
| 6646 |       break;
 | 
|---|
| 6647 | 
 | 
|---|
| 6648 |     case RELAX_LOOP_END_ADD_NOP:
 | 
|---|
| 6649 |       /* Add a NOP and switch to .fill 0.  */
 | 
|---|
| 6650 |       new_stretch = relax_frag_add_nop (fragP);
 | 
|---|
| 6651 |       break;
 | 
|---|
| 6652 | 
 | 
|---|
| 6653 |     case RELAX_DESIRE_ALIGN:
 | 
|---|
| 6654 |       /* We REALLY want to change the relaxation order here.  This
 | 
|---|
| 6655 |          should do NOTHING.  The narrowing before it will either align
 | 
|---|
| 6656 |          it or not.  */
 | 
|---|
| 6657 |       break;
 | 
|---|
| 6658 | 
 | 
|---|
| 6659 |     case RELAX_LITERAL:
 | 
|---|
| 6660 |     case RELAX_LITERAL_FINAL:
 | 
|---|
| 6661 |       return 0;
 | 
|---|
| 6662 | 
 | 
|---|
| 6663 |     case RELAX_LITERAL_NR:
 | 
|---|
| 6664 |       lit_size = 4;
 | 
|---|
| 6665 |       fragP->fr_subtype = RELAX_LITERAL_FINAL;
 | 
|---|
| 6666 |       assert (unreported == lit_size);
 | 
|---|
| 6667 |       memset (&fragP->fr_literal[fragP->fr_fix], 0, 4);
 | 
|---|
| 6668 |       fragP->fr_var -= lit_size;
 | 
|---|
| 6669 |       fragP->fr_fix += lit_size;
 | 
|---|
| 6670 |       new_stretch = 4;
 | 
|---|
| 6671 |       break;
 | 
|---|
| 6672 | 
 | 
|---|
| 6673 |     case RELAX_NARROW:
 | 
|---|
| 6674 |       new_stretch = relax_frag_narrow (fragP, stretch);
 | 
|---|
| 6675 |       break;
 | 
|---|
| 6676 | 
 | 
|---|
| 6677 |     case RELAX_IMMED:
 | 
|---|
| 6678 |     case RELAX_IMMED_STEP1:
 | 
|---|
| 6679 |     case RELAX_IMMED_STEP2:
 | 
|---|
| 6680 |       /* Place the immediate.  */
 | 
|---|
| 6681 |       new_stretch = relax_frag_immed (now_seg, fragP, stretch,
 | 
|---|
| 6682 |                                       fragP->fr_subtype - RELAX_IMMED,
 | 
|---|
| 6683 |                                       stretched_p);
 | 
|---|
| 6684 |       break;
 | 
|---|
| 6685 | 
 | 
|---|
| 6686 |     case RELAX_LITERAL_POOL_BEGIN:
 | 
|---|
| 6687 |     case RELAX_LITERAL_POOL_END:
 | 
|---|
| 6688 |       /* No relaxation required.  */
 | 
|---|
| 6689 |       break;
 | 
|---|
| 6690 | 
 | 
|---|
| 6691 |     default:
 | 
|---|
| 6692 |       as_bad (_("bad relaxation state"));
 | 
|---|
| 6693 |     }
 | 
|---|
| 6694 | 
 | 
|---|
| 6695 |   new_logical_line (file_name, line);
 | 
|---|
| 6696 |   return new_stretch;
 | 
|---|
| 6697 | }
 | 
|---|
| 6698 | 
 | 
|---|
| 6699 | 
 | 
|---|
| 6700 | static long
 | 
|---|
| 6701 | relax_frag_text_align (fragP, stretch)
 | 
|---|
| 6702 |      fragS *fragP;
 | 
|---|
| 6703 |      long stretch;
 | 
|---|
| 6704 | {
 | 
|---|
| 6705 |   addressT old_address, old_next_address, old_size;
 | 
|---|
| 6706 |   addressT new_address, new_next_address, new_size;
 | 
|---|
| 6707 |   addressT growth;
 | 
|---|
| 6708 | 
 | 
|---|
| 6709 |   /* Overview of the relaxation procedure for alignment
 | 
|---|
| 6710 |      inside an executable section:
 | 
|---|
| 6711 |     
 | 
|---|
| 6712 |      The old size is stored in the tc_frag_data.text_expansion field.
 | 
|---|
| 6713 |     
 | 
|---|
| 6714 |      Calculate the new address, fix up the text_expansion and
 | 
|---|
| 6715 |      return the growth.  */
 | 
|---|
| 6716 | 
 | 
|---|
| 6717 |   /* Calculate the old address of this fragment and the next fragment.  */
 | 
|---|
| 6718 |   old_address = fragP->fr_address - stretch;
 | 
|---|
| 6719 |   old_next_address = (fragP->fr_address - stretch + fragP->fr_fix +
 | 
|---|
| 6720 |                       fragP->tc_frag_data.text_expansion);
 | 
|---|
| 6721 |   old_size = old_next_address - old_address;
 | 
|---|
| 6722 | 
 | 
|---|
| 6723 |   /* Calculate the new address of this fragment and the next fragment.  */
 | 
|---|
| 6724 |   new_address = fragP->fr_address;
 | 
|---|
| 6725 |   new_next_address =
 | 
|---|
| 6726 |     get_noop_aligned_address (fragP, fragP->fr_address + fragP->fr_fix);
 | 
|---|
| 6727 |   new_size = new_next_address - new_address;
 | 
|---|
| 6728 | 
 | 
|---|
| 6729 |   growth = new_size - old_size;
 | 
|---|
| 6730 | 
 | 
|---|
| 6731 |   /* Fix up the text_expansion field and return the new growth.  */
 | 
|---|
| 6732 |   fragP->tc_frag_data.text_expansion += growth;
 | 
|---|
| 6733 |   return growth;
 | 
|---|
| 6734 | }
 | 
|---|
| 6735 | 
 | 
|---|
| 6736 | 
 | 
|---|
| 6737 | /* Add a NOP (i.e., "or a1, a1, a1").  Use the 3-byte one because we
 | 
|---|
| 6738 |    don't know about the availability of density yet.  TODO: When the
 | 
|---|
| 6739 |    flags are stored per fragment, use NOP.N when possible.  */
 | 
|---|
| 6740 | 
 | 
|---|
| 6741 | static long
 | 
|---|
| 6742 | relax_frag_add_nop (fragP)
 | 
|---|
| 6743 |      fragS *fragP;
 | 
|---|
| 6744 | {
 | 
|---|
| 6745 |   static xtensa_insnbuf insnbuf = NULL;
 | 
|---|
| 6746 |   TInsn t_insn;
 | 
|---|
| 6747 |   char *nop_buf = fragP->fr_literal + fragP->fr_fix;
 | 
|---|
| 6748 |   int length;
 | 
|---|
| 6749 |   if (!insnbuf)
 | 
|---|
| 6750 |     insnbuf = xtensa_insnbuf_alloc (xtensa_default_isa);
 | 
|---|
| 6751 | 
 | 
|---|
| 6752 |   tinsn_init (&t_insn);
 | 
|---|
| 6753 |   t_insn.opcode = xtensa_or_opcode;
 | 
|---|
| 6754 |   assert (t_insn.opcode != XTENSA_UNDEFINED);
 | 
|---|
| 6755 | 
 | 
|---|
| 6756 |   t_insn.ntok = 3;
 | 
|---|
| 6757 |   set_expr_const (&t_insn.tok[0], 1);
 | 
|---|
| 6758 |   set_expr_const (&t_insn.tok[1], 1);
 | 
|---|
| 6759 |   set_expr_const (&t_insn.tok[2], 1);
 | 
|---|
| 6760 | 
 | 
|---|
| 6761 |   tinsn_to_insnbuf (&t_insn, insnbuf);
 | 
|---|
| 6762 |   fragP->tc_frag_data.is_insn = TRUE;
 | 
|---|
| 6763 |   xtensa_insnbuf_to_chars (xtensa_default_isa, insnbuf, nop_buf);
 | 
|---|
| 6764 | 
 | 
|---|
| 6765 |   length = xtensa_insn_length (xtensa_default_isa, t_insn.opcode);
 | 
|---|
| 6766 |   if (fragP->fr_var < length)
 | 
|---|
| 6767 |     {
 | 
|---|
| 6768 |       as_warn (_("fr_var (%ld) < length (%d); ignoring"),
 | 
|---|
| 6769 |                fragP->fr_var, length);
 | 
|---|
| 6770 |       frag_wane (fragP);
 | 
|---|
| 6771 |       return 0;
 | 
|---|
| 6772 |     }
 | 
|---|
| 6773 | 
 | 
|---|
| 6774 |   fragP->fr_fix += length;
 | 
|---|
| 6775 |   fragP->fr_var -= length;
 | 
|---|
| 6776 |   frag_wane (fragP);
 | 
|---|
| 6777 |   return length;
 | 
|---|
| 6778 | }
 | 
|---|
| 6779 | 
 | 
|---|
| 6780 | 
 | 
|---|
| 6781 | static long
 | 
|---|
| 6782 | relax_frag_narrow (fragP, stretch)
 | 
|---|
| 6783 |      fragS *fragP;
 | 
|---|
| 6784 |      long stretch;
 | 
|---|
| 6785 | {
 | 
|---|
| 6786 |   /* Overview of the relaxation procedure for alignment inside an
 | 
|---|
| 6787 |      executable section: Find the number of widenings required and the
 | 
|---|
| 6788 |      number of nop bytes required. Store the number of bytes ALREADY
 | 
|---|
| 6789 |      widened. If there are enough instructions to widen (must go back
 | 
|---|
| 6790 |      ONLY through NARROW fragments), mark each of the fragments as TO BE
 | 
|---|
| 6791 |      widened, recalculate the fragment addresses.  */
 | 
|---|
| 6792 | 
 | 
|---|
| 6793 |   assert (fragP->fr_type == rs_machine_dependent
 | 
|---|
| 6794 |           && fragP->fr_subtype == RELAX_NARROW);
 | 
|---|
| 6795 | 
 | 
|---|
| 6796 |   if (!future_alignment_required (fragP, 0))
 | 
|---|
| 6797 |     {
 | 
|---|
| 6798 |       /* If already expanded but no longer needed because of a prior
 | 
|---|
| 6799 |          stretch, it is SAFE to unexpand because the next fragment will
 | 
|---|
| 6800 |          NEVER start at an address > the previous time through the
 | 
|---|
| 6801 |          relaxation.  */
 | 
|---|
| 6802 |       if (fragP->tc_frag_data.text_expansion)
 | 
|---|
| 6803 |         {
 | 
|---|
| 6804 |           if (stretch > 0)
 | 
|---|
| 6805 |             {
 | 
|---|
| 6806 |               fragP->tc_frag_data.text_expansion = 0;
 | 
|---|
| 6807 |               return -1;
 | 
|---|
| 6808 |             }
 | 
|---|
| 6809 |           /* Otherwise we have to live with this bad choice.  */
 | 
|---|
| 6810 |           return 0;
 | 
|---|
| 6811 |         }
 | 
|---|
| 6812 |       return 0;
 | 
|---|
| 6813 |     }
 | 
|---|
| 6814 | 
 | 
|---|
| 6815 |   if (fragP->tc_frag_data.text_expansion == 0)
 | 
|---|
| 6816 |     {
 | 
|---|
| 6817 |       fragP->tc_frag_data.text_expansion = 1;
 | 
|---|
| 6818 |       return 1;
 | 
|---|
| 6819 |     }
 | 
|---|
| 6820 | 
 | 
|---|
| 6821 |   return 0;
 | 
|---|
| 6822 | }
 | 
|---|
| 6823 | 
 | 
|---|
| 6824 | 
 | 
|---|
| 6825 | static bfd_boolean
 | 
|---|
| 6826 | future_alignment_required (fragP, stretch)
 | 
|---|
| 6827 |      fragS *fragP;
 | 
|---|
| 6828 |      long stretch;
 | 
|---|
| 6829 | {
 | 
|---|
| 6830 |   long address = fragP->fr_address + stretch;
 | 
|---|
| 6831 |   int num_widens = 0;
 | 
|---|
| 6832 |   addressT aligned_address;
 | 
|---|
| 6833 |   offsetT desired_diff;
 | 
|---|
| 6834 | 
 | 
|---|
| 6835 |   while (fragP)
 | 
|---|
| 6836 |     {
 | 
|---|
| 6837 |       /* Limit this to a small search.  */
 | 
|---|
| 6838 |       if (num_widens > 8)
 | 
|---|
| 6839 |         return FALSE;
 | 
|---|
| 6840 |       address += fragP->fr_fix;
 | 
|---|
| 6841 | 
 | 
|---|
| 6842 |       switch (fragP->fr_type)
 | 
|---|
| 6843 |         {
 | 
|---|
| 6844 |         case rs_fill:
 | 
|---|
| 6845 |           address += fragP->fr_offset * fragP->fr_var;
 | 
|---|
| 6846 |           break;
 | 
|---|
| 6847 | 
 | 
|---|
| 6848 |         case rs_machine_dependent:
 | 
|---|
| 6849 |           switch (fragP->fr_subtype)
 | 
|---|
| 6850 |             {
 | 
|---|
| 6851 |             case RELAX_NARROW:
 | 
|---|
| 6852 |               /* address += fragP->fr_fix; */
 | 
|---|
| 6853 |               num_widens++;
 | 
|---|
| 6854 |               break;
 | 
|---|
| 6855 | 
 | 
|---|
| 6856 |             case RELAX_IMMED:
 | 
|---|
| 6857 |               address += (/* fragP->fr_fix + */
 | 
|---|
| 6858 |                           fragP->tc_frag_data.text_expansion);
 | 
|---|
| 6859 |               break;
 | 
|---|
| 6860 | 
 | 
|---|
| 6861 |             case RELAX_ALIGN_NEXT_OPCODE:
 | 
|---|
| 6862 |             case RELAX_DESIRE_ALIGN:
 | 
|---|
| 6863 |               /* address += fragP->fr_fix; */
 | 
|---|
| 6864 |               aligned_address = get_widen_aligned_address (fragP, address);
 | 
|---|
| 6865 |               desired_diff = aligned_address - address;
 | 
|---|
| 6866 |               assert (desired_diff >= 0);
 | 
|---|
| 6867 |               /* If there are enough wideners in between do it.  */
 | 
|---|
| 6868 |               /* return (num_widens == desired_diff); */
 | 
|---|
| 6869 |               if (num_widens == desired_diff)
 | 
|---|
| 6870 |                 return TRUE;
 | 
|---|
| 6871 |               if (fragP->fr_subtype == RELAX_ALIGN_NEXT_OPCODE)
 | 
|---|
| 6872 |                 return FALSE;
 | 
|---|
| 6873 |               break;
 | 
|---|
| 6874 | 
 | 
|---|
| 6875 |             default:
 | 
|---|
| 6876 |               return FALSE;
 | 
|---|
| 6877 |             }
 | 
|---|
| 6878 |           break;
 | 
|---|
| 6879 | 
 | 
|---|
| 6880 |         default:
 | 
|---|
| 6881 |           return FALSE;
 | 
|---|
| 6882 |         }
 | 
|---|
| 6883 |       fragP = fragP->fr_next;
 | 
|---|
| 6884 |     }
 | 
|---|
| 6885 | 
 | 
|---|
| 6886 |   return FALSE;
 | 
|---|
| 6887 | }
 | 
|---|
| 6888 | 
 | 
|---|
| 6889 | 
 | 
|---|
| 6890 | static long
 | 
|---|
| 6891 | relax_frag_immed (segP, fragP, stretch, min_steps, stretched_p)
 | 
|---|
| 6892 |      segT segP;
 | 
|---|
| 6893 |      fragS *fragP;
 | 
|---|
| 6894 |      long stretch;
 | 
|---|
| 6895 |      int min_steps;
 | 
|---|
| 6896 |      int *stretched_p;
 | 
|---|
| 6897 | {
 | 
|---|
| 6898 |   static xtensa_insnbuf insnbuf = NULL;
 | 
|---|
| 6899 |   TInsn t_insn;
 | 
|---|
| 6900 |   int old_size;
 | 
|---|
| 6901 |   bfd_boolean negatable_branch = FALSE;
 | 
|---|
| 6902 |   bfd_boolean branch_jmp_to_next = FALSE;
 | 
|---|
| 6903 |   IStack istack;
 | 
|---|
| 6904 |   offsetT frag_offset;
 | 
|---|
| 6905 |   int num_steps;
 | 
|---|
| 6906 |   fragS *lit_fragP;
 | 
|---|
| 6907 |   int num_text_bytes, num_literal_bytes;
 | 
|---|
| 6908 |   int literal_diff, text_diff;
 | 
|---|
| 6909 | 
 | 
|---|
| 6910 |   assert (fragP->fr_opcode != NULL);
 | 
|---|
| 6911 | 
 | 
|---|
| 6912 |   if (!insnbuf)
 | 
|---|
| 6913 |     insnbuf = xtensa_insnbuf_alloc (xtensa_default_isa);
 | 
|---|
| 6914 | 
 | 
|---|
| 6915 |   tinsn_from_chars (&t_insn, fragP->fr_opcode);
 | 
|---|
| 6916 |   tinsn_immed_from_frag (&t_insn, fragP);
 | 
|---|
| 6917 | 
 | 
|---|
| 6918 |   negatable_branch = is_negatable_branch (&t_insn);
 | 
|---|
| 6919 | 
 | 
|---|
| 6920 |   old_size = xtensa_insn_length (xtensa_default_isa, t_insn.opcode);
 | 
|---|
| 6921 | 
 | 
|---|
| 6922 |   if (software_avoid_b_j_loop_end)
 | 
|---|
| 6923 |     branch_jmp_to_next = is_branch_jmp_to_next (&t_insn, fragP);
 | 
|---|
| 6924 | 
 | 
|---|
| 6925 |   /* Special case: replace a branch to the next instruction with a NOP.
 | 
|---|
| 6926 |      This is required to work around a hardware bug in T1040.0 and also
 | 
|---|
| 6927 |      serves as an optimization.  */
 | 
|---|
| 6928 | 
 | 
|---|
| 6929 |   if (branch_jmp_to_next
 | 
|---|
| 6930 |       && ((old_size == 2) || (old_size == 3))
 | 
|---|
| 6931 |       && !next_frag_is_loop_target (fragP))
 | 
|---|
| 6932 |     return 0;
 | 
|---|
| 6933 | 
 | 
|---|
| 6934 |   /* Here is the fun stuff: Get the immediate field from this
 | 
|---|
| 6935 |      instruction.  If it fits, we are done.  If not, find the next
 | 
|---|
| 6936 |      instruction sequence that fits.  */
 | 
|---|
| 6937 | 
 | 
|---|
| 6938 |   frag_offset = fragP->fr_opcode - fragP->fr_literal;
 | 
|---|
| 6939 |   istack_init (&istack);
 | 
|---|
| 6940 |   num_steps = xg_assembly_relax (&istack, &t_insn, segP, fragP, frag_offset,
 | 
|---|
| 6941 |                                  min_steps, stretch);
 | 
|---|
| 6942 |   if (num_steps < min_steps)
 | 
|---|
| 6943 |     {
 | 
|---|
| 6944 |       as_fatal (_("internal error: relaxation failed"));
 | 
|---|
| 6945 |       return 0;
 | 
|---|
| 6946 |     }
 | 
|---|
| 6947 | 
 | 
|---|
| 6948 |   if (num_steps > RELAX_IMMED_MAXSTEPS)
 | 
|---|
| 6949 |     {
 | 
|---|
| 6950 |       as_fatal (_("internal error: relaxation requires too many steps"));
 | 
|---|
| 6951 |       return 0;
 | 
|---|
| 6952 |     }
 | 
|---|
| 6953 | 
 | 
|---|
| 6954 |   fragP->fr_subtype = (int) RELAX_IMMED + num_steps;
 | 
|---|
| 6955 | 
 | 
|---|
| 6956 |   /* Figure out the number of bytes needed.  */
 | 
|---|
| 6957 |   lit_fragP = 0;
 | 
|---|
| 6958 |   num_text_bytes = get_num_stack_text_bytes (&istack) - old_size;
 | 
|---|
| 6959 |   num_literal_bytes = get_num_stack_literal_bytes (&istack);
 | 
|---|
| 6960 |   literal_diff = num_literal_bytes - fragP->tc_frag_data.literal_expansion;
 | 
|---|
| 6961 |   text_diff = num_text_bytes - fragP->tc_frag_data.text_expansion;
 | 
|---|
| 6962 | 
 | 
|---|
| 6963 |   /* It MUST get larger.  If not, we could get an infinite loop.  */
 | 
|---|
| 6964 |   know (num_text_bytes >= 0);
 | 
|---|
| 6965 |   know (literal_diff >= 0 && text_diff >= 0);
 | 
|---|
| 6966 | 
 | 
|---|
| 6967 |   fragP->tc_frag_data.text_expansion = num_text_bytes;
 | 
|---|
| 6968 |   fragP->tc_frag_data.literal_expansion = num_literal_bytes;
 | 
|---|
| 6969 | 
 | 
|---|
| 6970 |   /* Find the associated expandable literal for this.  */
 | 
|---|
| 6971 |   if (literal_diff != 0)
 | 
|---|
| 6972 |     {
 | 
|---|
| 6973 |       lit_fragP = fragP->tc_frag_data.literal_frag;
 | 
|---|
| 6974 |       if (lit_fragP)
 | 
|---|
| 6975 |         {
 | 
|---|
| 6976 |           assert (literal_diff == 4);
 | 
|---|
| 6977 |           lit_fragP->tc_frag_data.unreported_expansion += literal_diff;
 | 
|---|
| 6978 | 
 | 
|---|
| 6979 |           /* We expect that the literal section state has NOT been
 | 
|---|
| 6980 |              modified yet.  */
 | 
|---|
| 6981 |           assert (lit_fragP->fr_type == rs_machine_dependent
 | 
|---|
| 6982 |                   && lit_fragP->fr_subtype == RELAX_LITERAL);
 | 
|---|
| 6983 |           lit_fragP->fr_subtype = RELAX_LITERAL_NR;
 | 
|---|
| 6984 | 
 | 
|---|
| 6985 |           /* We need to mark this section for another iteration
 | 
|---|
| 6986 |              of relaxation.  */
 | 
|---|
| 6987 |           (*stretched_p)++;
 | 
|---|
| 6988 |         }
 | 
|---|
| 6989 |     }
 | 
|---|
| 6990 | 
 | 
|---|
| 6991 |   /* This implicitly uses the assumption that a branch is negated
 | 
|---|
| 6992 |      when the size of the output increases by at least 2 bytes.  */
 | 
|---|
| 6993 | 
 | 
|---|
| 6994 |   if (negatable_branch && num_text_bytes >= 2)
 | 
|---|
| 6995 |     {
 | 
|---|
| 6996 |       /* If next frag is a loop end, then switch it to add a NOP.  */
 | 
|---|
| 6997 |       update_next_frag_nop_state (fragP);
 | 
|---|
| 6998 |     }
 | 
|---|
| 6999 | 
 | 
|---|
| 7000 |   return text_diff;
 | 
|---|
| 7001 | }
 | 
|---|
| 7002 | 
 | 
|---|
| 7003 |  | 
|---|
| 7004 | 
 | 
|---|
| 7005 | /* md_convert_frag Hook and Helper Functions.  */
 | 
|---|
| 7006 | 
 | 
|---|
| 7007 | void
 | 
|---|
| 7008 | md_convert_frag (abfd, sec, fragp)
 | 
|---|
| 7009 |      bfd *abfd ATTRIBUTE_UNUSED;
 | 
|---|
| 7010 |      segT sec;
 | 
|---|
| 7011 |      fragS *fragp;
 | 
|---|
| 7012 | {
 | 
|---|
| 7013 |   char *file_name;
 | 
|---|
| 7014 |   int line;
 | 
|---|
| 7015 | 
 | 
|---|
| 7016 |   as_where (&file_name, &line);
 | 
|---|
| 7017 |   new_logical_line (fragp->fr_file, fragp->fr_line);
 | 
|---|
| 7018 | 
 | 
|---|
| 7019 |   switch (fragp->fr_subtype)
 | 
|---|
| 7020 |     {
 | 
|---|
| 7021 |     case RELAX_ALIGN_NEXT_OPCODE:
 | 
|---|
| 7022 |       /* Always convert.  */
 | 
|---|
| 7023 |       convert_frag_align_next_opcode (fragp);
 | 
|---|
| 7024 |       break;
 | 
|---|
| 7025 | 
 | 
|---|
| 7026 |     case RELAX_DESIRE_ALIGN:
 | 
|---|
| 7027 |       /* Do nothing.  If not aligned already, too bad.  */
 | 
|---|
| 7028 |       break;
 | 
|---|
| 7029 | 
 | 
|---|
| 7030 |     case RELAX_LITERAL:
 | 
|---|
| 7031 |     case RELAX_LITERAL_FINAL:
 | 
|---|
| 7032 |       break;
 | 
|---|
| 7033 | 
 | 
|---|
| 7034 |     case RELAX_NARROW:
 | 
|---|
| 7035 |       /* No conversion.  */
 | 
|---|
| 7036 |       convert_frag_narrow (fragp);
 | 
|---|
| 7037 |       break;
 | 
|---|
| 7038 | 
 | 
|---|
| 7039 |     case RELAX_IMMED:
 | 
|---|
| 7040 |     case RELAX_IMMED_STEP1:
 | 
|---|
| 7041 |     case RELAX_IMMED_STEP2:
 | 
|---|
| 7042 |       /* Place the immediate.  */
 | 
|---|
| 7043 |       convert_frag_immed (sec, fragp, fragp->fr_subtype - RELAX_IMMED);
 | 
|---|
| 7044 |       break;
 | 
|---|
| 7045 | 
 | 
|---|
| 7046 |     case RELAX_LITERAL_NR:
 | 
|---|
| 7047 |       if (use_literal_section)
 | 
|---|
| 7048 |         {
 | 
|---|
| 7049 |           /* This should have been handled during relaxation.  When
 | 
|---|
| 7050 |              relaxing a code segment, literals sometimes need to be
 | 
|---|
| 7051 |              added to the corresponding literal segment.  If that
 | 
|---|
| 7052 |              literal segment has already been relaxed, then we end up
 | 
|---|
| 7053 |              in this situation.  Marking the literal segments as data
 | 
|---|
| 7054 |              would make this happen less often (since GAS always relaxes
 | 
|---|
| 7055 |              code before data), but we could still get into trouble if
 | 
|---|
| 7056 |              there are instructions in a segment that is not marked as
 | 
|---|
| 7057 |              containing code.  Until we can implement a better solution,
 | 
|---|
| 7058 |              cheat and adjust the addresses of all the following frags.
 | 
|---|
| 7059 |              This could break subsequent alignments, but the linker's
 | 
|---|
| 7060 |              literal coalescing will do that anyway.  */
 | 
|---|
| 7061 | 
 | 
|---|
| 7062 |           fragS *f;
 | 
|---|
| 7063 |           fragp->fr_subtype = RELAX_LITERAL_FINAL;
 | 
|---|
| 7064 |           assert (fragp->tc_frag_data.unreported_expansion == 4);
 | 
|---|
| 7065 |           memset (&fragp->fr_literal[fragp->fr_fix], 0, 4);
 | 
|---|
| 7066 |           fragp->fr_var -= 4;
 | 
|---|
| 7067 |           fragp->fr_fix += 4;
 | 
|---|
| 7068 |           for (f = fragp->fr_next; f; f = f->fr_next)
 | 
|---|
| 7069 |             f->fr_address += 4;
 | 
|---|
| 7070 |         }
 | 
|---|
| 7071 |       else
 | 
|---|
| 7072 |         as_bad (_("invalid relaxation fragment result"));
 | 
|---|
| 7073 |       break;
 | 
|---|
| 7074 |     }
 | 
|---|
| 7075 | 
 | 
|---|
| 7076 |   fragp->fr_var = 0;
 | 
|---|
| 7077 |   new_logical_line (file_name, line);
 | 
|---|
| 7078 | }
 | 
|---|
| 7079 | 
 | 
|---|
| 7080 | 
 | 
|---|
| 7081 | void
 | 
|---|
| 7082 | convert_frag_align_next_opcode (fragp)
 | 
|---|
| 7083 |      fragS *fragp;
 | 
|---|
| 7084 | {
 | 
|---|
| 7085 |   char *nop_buf;                /* Location for Writing.  */
 | 
|---|
| 7086 |   size_t i;
 | 
|---|
| 7087 | 
 | 
|---|
| 7088 |   bfd_boolean use_no_density = fragp->tc_frag_data.is_no_density;
 | 
|---|
| 7089 |   addressT aligned_address;
 | 
|---|
| 7090 |   size_t fill_size, nop_count;
 | 
|---|
| 7091 | 
 | 
|---|
| 7092 |   aligned_address = get_noop_aligned_address (fragp, fragp->fr_address +
 | 
|---|
| 7093 |                                               fragp->fr_fix);
 | 
|---|
| 7094 |   fill_size = aligned_address - (fragp->fr_address + fragp->fr_fix);
 | 
|---|
| 7095 |   nop_count = get_text_align_nop_count (fill_size, use_no_density);
 | 
|---|
| 7096 |   nop_buf = fragp->fr_literal + fragp->fr_fix;
 | 
|---|
| 7097 | 
 | 
|---|
| 7098 |   for (i = 0; i < nop_count; i++)
 | 
|---|
| 7099 |     {
 | 
|---|
| 7100 |       size_t nop_size;
 | 
|---|
| 7101 |       nop_size = get_text_align_nth_nop_size (fill_size, i, use_no_density);
 | 
|---|
| 7102 | 
 | 
|---|
| 7103 |       assemble_nop (nop_size, nop_buf);
 | 
|---|
| 7104 |       nop_buf += nop_size;
 | 
|---|
| 7105 |     }
 | 
|---|
| 7106 | 
 | 
|---|
| 7107 |   fragp->fr_fix += fill_size;
 | 
|---|
| 7108 |   fragp->fr_var -= fill_size;
 | 
|---|
| 7109 | }
 | 
|---|
| 7110 | 
 | 
|---|
| 7111 | 
 | 
|---|
| 7112 | static void
 | 
|---|
| 7113 | convert_frag_narrow (fragP)
 | 
|---|
| 7114 |      fragS *fragP;
 | 
|---|
| 7115 | {
 | 
|---|
| 7116 |   static xtensa_insnbuf insnbuf = NULL;
 | 
|---|
| 7117 |   TInsn t_insn, single_target;
 | 
|---|
| 7118 |   int size, old_size, diff, error_val;
 | 
|---|
| 7119 |   offsetT frag_offset;
 | 
|---|
| 7120 | 
 | 
|---|
| 7121 |   if (fragP->tc_frag_data.text_expansion == 0)
 | 
|---|
| 7122 |     {
 | 
|---|
| 7123 |       /* No conversion.  */
 | 
|---|
| 7124 |       fragP->fr_var = 0;
 | 
|---|
| 7125 |       return;
 | 
|---|
| 7126 |     }
 | 
|---|
| 7127 | 
 | 
|---|
| 7128 |   assert (fragP->fr_opcode != NULL);
 | 
|---|
| 7129 | 
 | 
|---|
| 7130 |   if (!insnbuf)
 | 
|---|
| 7131 |     insnbuf = xtensa_insnbuf_alloc (xtensa_default_isa);
 | 
|---|
| 7132 | 
 | 
|---|
| 7133 |   tinsn_from_chars (&t_insn, fragP->fr_opcode);
 | 
|---|
| 7134 |   tinsn_immed_from_frag (&t_insn, fragP);
 | 
|---|
| 7135 | 
 | 
|---|
| 7136 |   /* Just convert it to a wide form....  */
 | 
|---|
| 7137 |   size = 0;
 | 
|---|
| 7138 |   old_size = xtensa_insn_length (xtensa_default_isa, t_insn.opcode);
 | 
|---|
| 7139 | 
 | 
|---|
| 7140 |   tinsn_init (&single_target);
 | 
|---|
| 7141 |   frag_offset = fragP->fr_opcode - fragP->fr_literal;
 | 
|---|
| 7142 | 
 | 
|---|
| 7143 |   error_val = xg_expand_narrow (&single_target, &t_insn);
 | 
|---|
| 7144 |   if (error_val)
 | 
|---|
| 7145 |     as_bad (_("unable to widen instruction"));
 | 
|---|
| 7146 | 
 | 
|---|
| 7147 |   size = xtensa_insn_length (xtensa_default_isa, single_target.opcode);
 | 
|---|
| 7148 |   xg_emit_insn_to_buf (&single_target, fragP->fr_opcode,
 | 
|---|
| 7149 |                        fragP, frag_offset, TRUE);
 | 
|---|
| 7150 | 
 | 
|---|
| 7151 |   diff = size - old_size;
 | 
|---|
| 7152 |   assert (diff >= 0);
 | 
|---|
| 7153 |   assert (diff <= fragP->fr_var);
 | 
|---|
| 7154 |   fragP->fr_var -= diff;
 | 
|---|
| 7155 |   fragP->fr_fix += diff;
 | 
|---|
| 7156 | 
 | 
|---|
| 7157 |   /* clean it up */
 | 
|---|
| 7158 |   fragP->fr_var = 0;
 | 
|---|
| 7159 | }
 | 
|---|
| 7160 | 
 | 
|---|
| 7161 | 
 | 
|---|
| 7162 | static void
 | 
|---|
| 7163 | convert_frag_immed (segP, fragP, min_steps)
 | 
|---|
| 7164 |      segT segP;
 | 
|---|
| 7165 |      fragS *fragP;
 | 
|---|
| 7166 |      int min_steps;
 | 
|---|
| 7167 | {
 | 
|---|
| 7168 |   char *immed_instr = fragP->fr_opcode;
 | 
|---|
| 7169 |   static xtensa_insnbuf insnbuf = NULL;
 | 
|---|
| 7170 |   TInsn orig_t_insn;
 | 
|---|
| 7171 |   bfd_boolean expanded = FALSE;
 | 
|---|
| 7172 |   char *fr_opcode = fragP->fr_opcode;
 | 
|---|
| 7173 |   bfd_boolean branch_jmp_to_next = FALSE;
 | 
|---|
| 7174 |   int size;
 | 
|---|
| 7175 | 
 | 
|---|
| 7176 |   assert (fragP->fr_opcode != NULL);
 | 
|---|
| 7177 | 
 | 
|---|
| 7178 |   if (!insnbuf)
 | 
|---|
| 7179 |     insnbuf = xtensa_insnbuf_alloc (xtensa_default_isa);
 | 
|---|
| 7180 | 
 | 
|---|
| 7181 |   tinsn_from_chars (&orig_t_insn, fragP->fr_opcode);
 | 
|---|
| 7182 |   tinsn_immed_from_frag (&orig_t_insn, fragP);
 | 
|---|
| 7183 | 
 | 
|---|
| 7184 |   /* Here is the fun stuff:  Get the immediate field from this
 | 
|---|
| 7185 |      instruction.  If it fits, we're done.  If not, find the next
 | 
|---|
| 7186 |      instruction sequence that fits.  */
 | 
|---|
| 7187 | 
 | 
|---|
| 7188 |   if (software_avoid_b_j_loop_end)
 | 
|---|
| 7189 |     branch_jmp_to_next = is_branch_jmp_to_next (&orig_t_insn, fragP);
 | 
|---|
| 7190 | 
 | 
|---|
| 7191 |   if (branch_jmp_to_next && !next_frag_is_loop_target (fragP))
 | 
|---|
| 7192 |     {
 | 
|---|
| 7193 |       /* Conversion just inserts a NOP and marks the fix as completed.  */
 | 
|---|
| 7194 |       size = xtensa_insn_length (xtensa_default_isa, orig_t_insn.opcode);
 | 
|---|
| 7195 |       assemble_nop (size, fragP->fr_opcode);
 | 
|---|
| 7196 |       fragP->fr_var = 0;
 | 
|---|
| 7197 |     }
 | 
|---|
| 7198 |   else
 | 
|---|
| 7199 |     {
 | 
|---|
| 7200 |       IStack istack;
 | 
|---|
| 7201 |       int i;
 | 
|---|
| 7202 |       symbolS *lit_sym = NULL;
 | 
|---|
| 7203 |       int total_size = 0;
 | 
|---|
| 7204 |       int old_size;
 | 
|---|
| 7205 |       int diff;
 | 
|---|
| 7206 |       symbolS *gen_label = NULL;
 | 
|---|
| 7207 |       offsetT frag_offset;
 | 
|---|
| 7208 | 
 | 
|---|
| 7209 |       /* It does not fit.  Find something that does and 
 | 
|---|
| 7210 |          convert immediately.  */
 | 
|---|
| 7211 |       frag_offset = fragP->fr_opcode - fragP->fr_literal;
 | 
|---|
| 7212 |       istack_init (&istack);
 | 
|---|
| 7213 |       xg_assembly_relax (&istack, &orig_t_insn,
 | 
|---|
| 7214 |                          segP, fragP, frag_offset, min_steps, 0);
 | 
|---|
| 7215 | 
 | 
|---|
| 7216 |       old_size = xtensa_insn_length (xtensa_default_isa, orig_t_insn.opcode);
 | 
|---|
| 7217 | 
 | 
|---|
| 7218 |       /* Assemble this right inline.  */
 | 
|---|
| 7219 | 
 | 
|---|
| 7220 |       /* First, create the mapping from a label name to the REAL label.  */
 | 
|---|
| 7221 |       total_size = 0;
 | 
|---|
| 7222 |       for (i = 0; i < istack.ninsn; i++)
 | 
|---|
| 7223 |         {
 | 
|---|
| 7224 |           TInsn *t_insn = &istack.insn[i];
 | 
|---|
| 7225 |           int size = 0;
 | 
|---|
| 7226 |           fragS *lit_frag;
 | 
|---|
| 7227 | 
 | 
|---|
| 7228 |           switch (t_insn->insn_type)
 | 
|---|
| 7229 |             {
 | 
|---|
| 7230 |             case ITYPE_LITERAL:
 | 
|---|
| 7231 |               if (lit_sym != NULL)
 | 
|---|
| 7232 |                 as_bad (_("multiple literals in expansion"));
 | 
|---|
| 7233 |               /* First find the appropriate space in the literal pool.  */
 | 
|---|
| 7234 |               lit_frag = fragP->tc_frag_data.literal_frag;
 | 
|---|
| 7235 |               if (lit_frag == NULL)
 | 
|---|
| 7236 |                 as_bad (_("no registered fragment for literal"));
 | 
|---|
| 7237 |               if (t_insn->ntok != 1)
 | 
|---|
| 7238 |                 as_bad (_("number of literal tokens != 1"));
 | 
|---|
| 7239 | 
 | 
|---|
| 7240 |               /* Set the literal symbol and add a fixup.  */
 | 
|---|
| 7241 |               lit_sym = lit_frag->fr_symbol;
 | 
|---|
| 7242 |               break;
 | 
|---|
| 7243 | 
 | 
|---|
| 7244 |             case ITYPE_LABEL:
 | 
|---|
| 7245 |               assert (gen_label == NULL);
 | 
|---|
| 7246 |               gen_label = symbol_new (FAKE_LABEL_NAME, now_seg,
 | 
|---|
| 7247 |                                       fragP->fr_opcode - fragP->fr_literal +
 | 
|---|
| 7248 |                                       total_size, fragP);
 | 
|---|
| 7249 |               break;
 | 
|---|
| 7250 | 
 | 
|---|
| 7251 |             case ITYPE_INSN:
 | 
|---|
| 7252 |               size = xtensa_insn_length (xtensa_default_isa, t_insn->opcode);
 | 
|---|
| 7253 |               total_size += size;
 | 
|---|
| 7254 |               break;
 | 
|---|
| 7255 |             }
 | 
|---|
| 7256 |         }
 | 
|---|
| 7257 | 
 | 
|---|
| 7258 |       total_size = 0;
 | 
|---|
| 7259 |       for (i = 0; i < istack.ninsn; i++)
 | 
|---|
| 7260 |         {
 | 
|---|
| 7261 |           TInsn *t_insn = &istack.insn[i];
 | 
|---|
| 7262 |           fragS *lit_frag;
 | 
|---|
| 7263 |           int size;
 | 
|---|
| 7264 |           segT target_seg;
 | 
|---|
| 7265 | 
 | 
|---|
| 7266 |           switch (t_insn->insn_type)
 | 
|---|
| 7267 |             {
 | 
|---|
| 7268 |             case ITYPE_LITERAL:
 | 
|---|
| 7269 |               lit_frag = fragP->tc_frag_data.literal_frag;
 | 
|---|
| 7270 |               /* already checked */
 | 
|---|
| 7271 |               assert (lit_frag != NULL);
 | 
|---|
| 7272 |               assert (lit_sym != NULL);
 | 
|---|
| 7273 |               assert (t_insn->ntok == 1);
 | 
|---|
| 7274 |               /* add a fixup */
 | 
|---|
| 7275 |               target_seg = S_GET_SEGMENT (lit_sym);
 | 
|---|
| 7276 |               assert (target_seg);
 | 
|---|
| 7277 |               fix_new_exp_in_seg (target_seg, 0, lit_frag, 0, 4,
 | 
|---|
| 7278 |                                   &t_insn->tok[0], FALSE, BFD_RELOC_32);
 | 
|---|
| 7279 |               break;
 | 
|---|
| 7280 | 
 | 
|---|
| 7281 |             case ITYPE_LABEL:
 | 
|---|
| 7282 |               break;
 | 
|---|
| 7283 | 
 | 
|---|
| 7284 |             case ITYPE_INSN:
 | 
|---|
| 7285 |               xg_resolve_labels (t_insn, gen_label);
 | 
|---|
| 7286 |               xg_resolve_literals (t_insn, lit_sym);
 | 
|---|
| 7287 |               size = xtensa_insn_length (xtensa_default_isa, t_insn->opcode);
 | 
|---|
| 7288 |               total_size += size;
 | 
|---|
| 7289 |               xg_emit_insn_to_buf (t_insn, immed_instr, fragP,
 | 
|---|
| 7290 |                                    immed_instr - fragP->fr_literal, TRUE);
 | 
|---|
| 7291 |               immed_instr += size;
 | 
|---|
| 7292 |               break;
 | 
|---|
| 7293 |             }
 | 
|---|
| 7294 |         }
 | 
|---|
| 7295 | 
 | 
|---|
| 7296 |       diff = total_size - old_size;
 | 
|---|
| 7297 |       assert (diff >= 0);
 | 
|---|
| 7298 |       if (diff != 0)
 | 
|---|
| 7299 |         expanded = TRUE;
 | 
|---|
| 7300 |       assert (diff <= fragP->fr_var);
 | 
|---|
| 7301 |       fragP->fr_var -= diff;
 | 
|---|
| 7302 |       fragP->fr_fix += diff;
 | 
|---|
| 7303 |     }
 | 
|---|
| 7304 | 
 | 
|---|
| 7305 |   /* Clean it up.  */
 | 
|---|
| 7306 |   fragP->fr_var = 0;
 | 
|---|
| 7307 | 
 | 
|---|
| 7308 |   /* Check for undefined immediates in LOOP instructions.  */
 | 
|---|
| 7309 |   if (is_loop_opcode (orig_t_insn.opcode))
 | 
|---|
| 7310 |     {
 | 
|---|
| 7311 |       symbolS *sym;
 | 
|---|
| 7312 |       sym = orig_t_insn.tok[1].X_add_symbol;
 | 
|---|
| 7313 |       if (sym != NULL && !S_IS_DEFINED (sym))
 | 
|---|
| 7314 |         {
 | 
|---|
| 7315 |           as_bad (_("unresolved loop target symbol: %s"), S_GET_NAME (sym));
 | 
|---|
| 7316 |           return;
 | 
|---|
| 7317 |         }
 | 
|---|
| 7318 |       sym = orig_t_insn.tok[1].X_op_symbol;
 | 
|---|
| 7319 |       if (sym != NULL && !S_IS_DEFINED (sym))
 | 
|---|
| 7320 |         {
 | 
|---|
| 7321 |           as_bad (_("unresolved loop target symbol: %s"), S_GET_NAME (sym));
 | 
|---|
| 7322 |           return;
 | 
|---|
| 7323 |         }
 | 
|---|
| 7324 |     }
 | 
|---|
| 7325 | 
 | 
|---|
| 7326 |   if (expanded && is_loop_opcode (orig_t_insn.opcode))
 | 
|---|
| 7327 |     convert_frag_immed_finish_loop (segP, fragP, &orig_t_insn);
 | 
|---|
| 7328 | 
 | 
|---|
| 7329 |   if (expanded && is_direct_call_opcode (orig_t_insn.opcode))
 | 
|---|
| 7330 |     {
 | 
|---|
| 7331 |       /* Add an expansion note on the expanded instruction.  */
 | 
|---|
| 7332 |       fix_new_exp_in_seg (now_seg, 0, fragP, fr_opcode - fragP->fr_literal, 4,
 | 
|---|
| 7333 |                           &orig_t_insn.tok[0], TRUE,
 | 
|---|
| 7334 |                           BFD_RELOC_XTENSA_ASM_EXPAND);
 | 
|---|
| 7335 | 
 | 
|---|
| 7336 |     }
 | 
|---|
| 7337 | }
 | 
|---|
| 7338 | 
 | 
|---|
| 7339 | 
 | 
|---|
| 7340 | /* Add a new fix expression into the desired segment.  We have to
 | 
|---|
| 7341 |    switch to that segment to do this.  */
 | 
|---|
| 7342 | 
 | 
|---|
| 7343 | static fixS *
 | 
|---|
| 7344 | fix_new_exp_in_seg (new_seg, new_subseg,
 | 
|---|
| 7345 |                     frag, where, size, exp, pcrel, r_type)
 | 
|---|
| 7346 |      segT new_seg;
 | 
|---|
| 7347 |      subsegT new_subseg;
 | 
|---|
| 7348 |      fragS *frag;
 | 
|---|
| 7349 |      int where;
 | 
|---|
| 7350 |      int size;
 | 
|---|
| 7351 |      expressionS *exp;
 | 
|---|
| 7352 |      int pcrel;
 | 
|---|
| 7353 |      bfd_reloc_code_real_type r_type;
 | 
|---|
| 7354 | {
 | 
|---|
| 7355 |   fixS *new_fix;
 | 
|---|
| 7356 |   segT seg = now_seg;
 | 
|---|
| 7357 |   subsegT subseg = now_subseg;
 | 
|---|
| 7358 |   assert (new_seg != 0);
 | 
|---|
| 7359 |   subseg_set (new_seg, new_subseg);
 | 
|---|
| 7360 | 
 | 
|---|
| 7361 |   if (r_type == BFD_RELOC_32
 | 
|---|
| 7362 |       && exp->X_add_symbol
 | 
|---|
| 7363 |       && exp->X_add_symbol->sy_tc.plt == 1)
 | 
|---|
| 7364 |     {
 | 
|---|
| 7365 |       r_type = BFD_RELOC_XTENSA_PLT;
 | 
|---|
| 7366 |     }
 | 
|---|
| 7367 | 
 | 
|---|
| 7368 |   new_fix = fix_new_exp (frag, where, size, exp, pcrel, r_type);
 | 
|---|
| 7369 |   subseg_set (seg, subseg);
 | 
|---|
| 7370 |   return new_fix;
 | 
|---|
| 7371 | }
 | 
|---|
| 7372 | 
 | 
|---|
| 7373 | 
 | 
|---|
| 7374 | /* Relax a loop instruction so that it can span loop >256 bytes.  */
 | 
|---|
| 7375 | /* 
 | 
|---|
| 7376 |                   loop    as, .L1 
 | 
|---|
| 7377 |           .L0: 
 | 
|---|
| 7378 |                   rsr     as, LEND 
 | 
|---|
| 7379 |                   wsr     as, LBEG 
 | 
|---|
| 7380 |                   addi    as, as, lo8(label-.L1) 
 | 
|---|
| 7381 |                   addmi   as, as, mid8(label-.L1) 
 | 
|---|
| 7382 |                   wsr     as, LEND 
 | 
|---|
| 7383 |                   isync 
 | 
|---|
| 7384 |                   rsr     as, LCOUNT 
 | 
|---|
| 7385 |                   addi    as, as, 1 
 | 
|---|
| 7386 |           .L1: 
 | 
|---|
| 7387 |                   <<body>> 
 | 
|---|
| 7388 |           label:                                     */
 | 
|---|
| 7389 | 
 | 
|---|
| 7390 | static void
 | 
|---|
| 7391 | convert_frag_immed_finish_loop (segP, fragP, t_insn)
 | 
|---|
| 7392 |      segT segP;
 | 
|---|
| 7393 |      fragS *fragP;
 | 
|---|
| 7394 |      TInsn *t_insn;
 | 
|---|
| 7395 | {
 | 
|---|
| 7396 |   TInsn loop_insn;
 | 
|---|
| 7397 |   TInsn addi_insn;
 | 
|---|
| 7398 |   TInsn addmi_insn;
 | 
|---|
| 7399 |   unsigned long target;
 | 
|---|
| 7400 |   static xtensa_insnbuf insnbuf = NULL;
 | 
|---|
| 7401 |   unsigned int loop_length, loop_length_hi, loop_length_lo;
 | 
|---|
| 7402 |   xtensa_isa isa = xtensa_default_isa;
 | 
|---|
| 7403 |   addressT loop_offset;
 | 
|---|
| 7404 |   addressT addi_offset = 9;
 | 
|---|
| 7405 |   addressT addmi_offset = 12;
 | 
|---|
| 7406 | 
 | 
|---|
| 7407 |   if (!insnbuf)
 | 
|---|
| 7408 |     insnbuf = xtensa_insnbuf_alloc (isa);
 | 
|---|
| 7409 | 
 | 
|---|
| 7410 |   /* Get the loop offset.  */
 | 
|---|
| 7411 |   loop_offset = get_expanded_loop_offset (t_insn->opcode);
 | 
|---|
| 7412 |   /* Validate that there really is a LOOP at the loop_offset.  */
 | 
|---|
| 7413 |   tinsn_from_chars (&loop_insn, fragP->fr_opcode + loop_offset);
 | 
|---|
| 7414 | 
 | 
|---|
| 7415 |   if (!is_loop_opcode (loop_insn.opcode))
 | 
|---|
| 7416 |     {
 | 
|---|
| 7417 |       as_bad_where (fragP->fr_file, fragP->fr_line,
 | 
|---|
| 7418 |                     _("loop relaxation specification does not correspond"));
 | 
|---|
| 7419 |       assert (0);
 | 
|---|
| 7420 |     }
 | 
|---|
| 7421 |   addi_offset += loop_offset;
 | 
|---|
| 7422 |   addmi_offset += loop_offset;
 | 
|---|
| 7423 | 
 | 
|---|
| 7424 |   assert (t_insn->ntok == 2);
 | 
|---|
| 7425 |   target = get_expression_value (segP, &t_insn->tok[1]);
 | 
|---|
| 7426 | 
 | 
|---|
| 7427 |   know (symbolP);
 | 
|---|
| 7428 |   know (symbolP->sy_frag);
 | 
|---|
| 7429 |   know (!(S_GET_SEGMENT (symbolP) == absolute_section)
 | 
|---|
| 7430 |         || symbol_get_frag (symbolP) == &zero_address_frag);
 | 
|---|
| 7431 | 
 | 
|---|
| 7432 |   loop_length = target - (fragP->fr_address + fragP->fr_fix);
 | 
|---|
| 7433 |   loop_length_hi = loop_length & ~0x0ff;
 | 
|---|
| 7434 |   loop_length_lo = loop_length & 0x0ff;
 | 
|---|
| 7435 |   if (loop_length_lo >= 128)
 | 
|---|
| 7436 |     {
 | 
|---|
| 7437 |       loop_length_lo -= 256;
 | 
|---|
| 7438 |       loop_length_hi += 256;
 | 
|---|
| 7439 |     }
 | 
|---|
| 7440 | 
 | 
|---|
| 7441 |   /* Because addmi sign-extends the immediate, 'loop_length_hi' can be at most 
 | 
|---|
| 7442 |      32512.  If the loop is larger than that, then we just fail.  */
 | 
|---|
| 7443 |   if (loop_length_hi > 32512)
 | 
|---|
| 7444 |     as_bad_where (fragP->fr_file, fragP->fr_line,
 | 
|---|
| 7445 |                   _("loop too long for LOOP instruction"));
 | 
|---|
| 7446 | 
 | 
|---|
| 7447 |   tinsn_from_chars (&addi_insn, fragP->fr_opcode + addi_offset);
 | 
|---|
| 7448 |   assert (addi_insn.opcode == xtensa_addi_opcode);
 | 
|---|
| 7449 | 
 | 
|---|
| 7450 |   tinsn_from_chars (&addmi_insn, fragP->fr_opcode + addmi_offset);
 | 
|---|
| 7451 |   assert (addmi_insn.opcode == xtensa_addmi_opcode);
 | 
|---|
| 7452 | 
 | 
|---|
| 7453 |   set_expr_const (&addi_insn.tok[2], loop_length_lo);
 | 
|---|
| 7454 |   tinsn_to_insnbuf (&addi_insn, insnbuf);
 | 
|---|
| 7455 |   
 | 
|---|
| 7456 |   fragP->tc_frag_data.is_insn = TRUE;
 | 
|---|
| 7457 |   xtensa_insnbuf_to_chars (isa, insnbuf, fragP->fr_opcode + addi_offset);
 | 
|---|
| 7458 | 
 | 
|---|
| 7459 |   set_expr_const (&addmi_insn.tok[2], loop_length_hi);
 | 
|---|
| 7460 |   tinsn_to_insnbuf (&addmi_insn, insnbuf);
 | 
|---|
| 7461 |   xtensa_insnbuf_to_chars (isa, insnbuf, fragP->fr_opcode + addmi_offset);
 | 
|---|
| 7462 | }
 | 
|---|
| 7463 | 
 | 
|---|
| 7464 | 
 | 
|---|
| 7465 | static offsetT
 | 
|---|
| 7466 | get_expression_value (segP, exp)
 | 
|---|
| 7467 |      segT segP;
 | 
|---|
| 7468 |      expressionS *exp;
 | 
|---|
| 7469 | {
 | 
|---|
| 7470 |   if (exp->X_op == O_constant)
 | 
|---|
| 7471 |     return exp->X_add_number;
 | 
|---|
| 7472 |   if (exp->X_op == O_symbol)
 | 
|---|
| 7473 |     {
 | 
|---|
| 7474 |       /* Find the fragment.  */
 | 
|---|
| 7475 |       symbolS *sym = exp->X_add_symbol;
 | 
|---|
| 7476 | 
 | 
|---|
| 7477 |       assert (S_GET_SEGMENT (sym) == segP
 | 
|---|
| 7478 |               || S_GET_SEGMENT (sym) == absolute_section);
 | 
|---|
| 7479 | 
 | 
|---|
| 7480 |       return (S_GET_VALUE (sym) + exp->X_add_number);
 | 
|---|
| 7481 |     }
 | 
|---|
| 7482 |   as_bad (_("invalid expression evaluation type %d"), exp->X_op);
 | 
|---|
| 7483 |   return 0;
 | 
|---|
| 7484 | }
 | 
|---|
| 7485 | 
 | 
|---|
| 7486 |  | 
|---|
| 7487 | 
 | 
|---|
| 7488 | /* A map that keeps information on a per-subsegment basis.  This is
 | 
|---|
| 7489 |    maintained during initial assembly, but is invalid once the
 | 
|---|
| 7490 |    subsegments are smashed together.  I.E., it cannot be used during
 | 
|---|
| 7491 |    the relaxation.  */
 | 
|---|
| 7492 | 
 | 
|---|
| 7493 | typedef struct subseg_map_struct
 | 
|---|
| 7494 | {
 | 
|---|
| 7495 |   /* the key */
 | 
|---|
| 7496 |   segT seg;
 | 
|---|
| 7497 |   subsegT subseg;
 | 
|---|
| 7498 | 
 | 
|---|
| 7499 |   /* the data */
 | 
|---|
| 7500 |   unsigned flags;
 | 
|---|
| 7501 | 
 | 
|---|
| 7502 |   struct subseg_map_struct *next;
 | 
|---|
| 7503 | } subseg_map;
 | 
|---|
| 7504 | 
 | 
|---|
| 7505 | static subseg_map *sseg_map = NULL;
 | 
|---|
| 7506 | 
 | 
|---|
| 7507 | 
 | 
|---|
| 7508 | static unsigned
 | 
|---|
| 7509 | get_last_insn_flags (seg, subseg)
 | 
|---|
| 7510 |      segT seg;
 | 
|---|
| 7511 |      subsegT subseg;
 | 
|---|
| 7512 | {
 | 
|---|
| 7513 |   subseg_map *subseg_e;
 | 
|---|
| 7514 | 
 | 
|---|
| 7515 |   for (subseg_e = sseg_map; subseg_e != NULL; subseg_e = subseg_e->next)
 | 
|---|
| 7516 |     if (seg == subseg_e->seg && subseg == subseg_e->subseg)
 | 
|---|
| 7517 |       return subseg_e->flags;
 | 
|---|
| 7518 | 
 | 
|---|
| 7519 |   return 0;
 | 
|---|
| 7520 | }
 | 
|---|
| 7521 | 
 | 
|---|
| 7522 | 
 | 
|---|
| 7523 | static void
 | 
|---|
| 7524 | set_last_insn_flags (seg, subseg, fl, val)
 | 
|---|
| 7525 |      segT seg;
 | 
|---|
| 7526 |      subsegT subseg;
 | 
|---|
| 7527 |      unsigned fl;
 | 
|---|
| 7528 |      bfd_boolean val;
 | 
|---|
| 7529 | {
 | 
|---|
| 7530 |   subseg_map *subseg_e;
 | 
|---|
| 7531 | 
 | 
|---|
| 7532 |   for (subseg_e = sseg_map; subseg_e; subseg_e = subseg_e->next)
 | 
|---|
| 7533 |     if (seg == subseg_e->seg && subseg == subseg_e->subseg)
 | 
|---|
| 7534 |       break;
 | 
|---|
| 7535 | 
 | 
|---|
| 7536 |   if (!subseg_e)
 | 
|---|
| 7537 |     {
 | 
|---|
| 7538 |       subseg_e = (subseg_map *) xmalloc (sizeof (subseg_map));
 | 
|---|
| 7539 |       memset (subseg_e, 0, sizeof (subseg_map));
 | 
|---|
| 7540 |       subseg_e->seg = seg;
 | 
|---|
| 7541 |       subseg_e->subseg = subseg;
 | 
|---|
| 7542 |       subseg_e->flags = 0;
 | 
|---|
| 7543 |       subseg_e->next = sseg_map;
 | 
|---|
| 7544 |       sseg_map = subseg_e;
 | 
|---|
| 7545 |     }
 | 
|---|
| 7546 | 
 | 
|---|
| 7547 |   if (val)
 | 
|---|
| 7548 |     subseg_e->flags |= fl;
 | 
|---|
| 7549 |   else
 | 
|---|
| 7550 |     subseg_e->flags &= ~fl;
 | 
|---|
| 7551 | }
 | 
|---|
| 7552 | 
 | 
|---|
| 7553 |  | 
|---|
| 7554 | 
 | 
|---|
| 7555 | /* Segment Lists and emit_state Stuff.  */
 | 
|---|
| 7556 | 
 | 
|---|
| 7557 | /* Remove the segment from the global sections list.  */
 | 
|---|
| 7558 | 
 | 
|---|
| 7559 | static void
 | 
|---|
| 7560 | xtensa_remove_section (sec)
 | 
|---|
| 7561 |      segT sec;
 | 
|---|
| 7562 | {
 | 
|---|
| 7563 |   /* Handle brain-dead bfd_section_list_remove macro, which
 | 
|---|
| 7564 |      expect the address of the prior section's "next" field, not
 | 
|---|
| 7565 |      just the address of the section to remove.  */
 | 
|---|
| 7566 | 
 | 
|---|
| 7567 |   segT *ps_next_ptr = &stdoutput->sections;
 | 
|---|
| 7568 |   while (*ps_next_ptr != sec && *ps_next_ptr != NULL) 
 | 
|---|
| 7569 |     ps_next_ptr = &(*ps_next_ptr)->next;
 | 
|---|
| 7570 |   
 | 
|---|
| 7571 |   assert (*ps_next_ptr != NULL);
 | 
|---|
| 7572 | 
 | 
|---|
| 7573 |   bfd_section_list_remove (stdoutput, ps_next_ptr);
 | 
|---|
| 7574 | }
 | 
|---|
| 7575 | 
 | 
|---|
| 7576 | 
 | 
|---|
| 7577 | static void
 | 
|---|
| 7578 | xtensa_insert_section (after_sec, sec)
 | 
|---|
| 7579 |      segT after_sec;
 | 
|---|
| 7580 |      segT sec;
 | 
|---|
| 7581 | {
 | 
|---|
| 7582 |   segT *after_sec_next;
 | 
|---|
| 7583 |   if (after_sec == NULL)
 | 
|---|
| 7584 |     after_sec_next = &stdoutput->sections;
 | 
|---|
| 7585 |   else
 | 
|---|
| 7586 |     after_sec_next = &after_sec->next;
 | 
|---|
| 7587 | 
 | 
|---|
| 7588 |   bfd_section_list_insert (stdoutput, after_sec_next, sec);
 | 
|---|
| 7589 | }
 | 
|---|
| 7590 | 
 | 
|---|
| 7591 | 
 | 
|---|
| 7592 | static void
 | 
|---|
| 7593 | xtensa_move_seg_list_to_beginning (head)
 | 
|---|
| 7594 |      seg_list *head;
 | 
|---|
| 7595 | {
 | 
|---|
| 7596 |   head = head->next;
 | 
|---|
| 7597 |   while (head)
 | 
|---|
| 7598 |     {
 | 
|---|
| 7599 |       segT literal_section = head->seg;
 | 
|---|
| 7600 | 
 | 
|---|
| 7601 |       /* Move the literal section to the front of the section list.  */
 | 
|---|
| 7602 |       assert (literal_section);
 | 
|---|
| 7603 |       xtensa_remove_section (literal_section);
 | 
|---|
| 7604 |       xtensa_insert_section (NULL, literal_section);
 | 
|---|
| 7605 | 
 | 
|---|
| 7606 |       head = head->next;
 | 
|---|
| 7607 |     }
 | 
|---|
| 7608 | }
 | 
|---|
| 7609 | 
 | 
|---|
| 7610 | 
 | 
|---|
| 7611 | void
 | 
|---|
| 7612 | xtensa_move_literals ()
 | 
|---|
| 7613 | {
 | 
|---|
| 7614 |   seg_list *segment;
 | 
|---|
| 7615 |   frchainS *frchain_from, *frchain_to;
 | 
|---|
| 7616 |   fragS *search_frag, *next_frag, *last_frag, *literal_pool, *insert_after;
 | 
|---|
| 7617 |   fragS **frag_splice;
 | 
|---|
| 7618 |   emit_state state;
 | 
|---|
| 7619 |   segT dest_seg;
 | 
|---|
| 7620 |   fixS *fix, *next_fix, **fix_splice;
 | 
|---|
| 7621 | 
 | 
|---|
| 7622 |   /* As clunky as this is, we can't rely on frag_var
 | 
|---|
| 7623 |      and frag_variant to get called in all situations.  */
 | 
|---|
| 7624 | 
 | 
|---|
| 7625 |   segment = literal_head->next;
 | 
|---|
| 7626 |   while (segment)
 | 
|---|
| 7627 |     {
 | 
|---|
| 7628 |       frchain_from = seg_info (segment->seg)->frchainP;
 | 
|---|
| 7629 |       search_frag = frchain_from->frch_root;
 | 
|---|
| 7630 |       while (search_frag) 
 | 
|---|
| 7631 |         {
 | 
|---|
| 7632 |           search_frag->tc_frag_data.is_literal = TRUE;
 | 
|---|
| 7633 |           search_frag = search_frag->fr_next;
 | 
|---|
| 7634 |         }
 | 
|---|
| 7635 |       segment = segment->next;
 | 
|---|
| 7636 |     }
 | 
|---|
| 7637 | 
 | 
|---|
| 7638 |   if (use_literal_section)
 | 
|---|
| 7639 |     return;
 | 
|---|
| 7640 | 
 | 
|---|
| 7641 |   segment = literal_head->next;
 | 
|---|
| 7642 |   while (segment)
 | 
|---|
| 7643 |     {
 | 
|---|
| 7644 |       frchain_from = seg_info (segment->seg)->frchainP;
 | 
|---|
| 7645 |       search_frag = frchain_from->frch_root;
 | 
|---|
| 7646 |       literal_pool = NULL;
 | 
|---|
| 7647 |       frchain_to = NULL;
 | 
|---|
| 7648 |       frag_splice = &(frchain_from->frch_root);
 | 
|---|
| 7649 | 
 | 
|---|
| 7650 |       while (!search_frag->tc_frag_data.literal_frag)
 | 
|---|
| 7651 |         {
 | 
|---|
| 7652 |           assert (search_frag->fr_fix == 0
 | 
|---|
| 7653 |                   || search_frag->fr_type == rs_align);
 | 
|---|
| 7654 |           search_frag = search_frag->fr_next;
 | 
|---|
| 7655 |         }
 | 
|---|
| 7656 | 
 | 
|---|
| 7657 |       assert (search_frag->tc_frag_data.literal_frag->fr_subtype
 | 
|---|
| 7658 |               == RELAX_LITERAL_POOL_BEGIN);
 | 
|---|
| 7659 |       xtensa_switch_section_emit_state (&state, segment->seg, 0);
 | 
|---|
| 7660 | 
 | 
|---|
| 7661 |       /* Make sure that all the frags in this series are closed, and
 | 
|---|
| 7662 |          that there is at least one left over of zero-size.  This
 | 
|---|
| 7663 |          prevents us from making a segment with an frchain without any
 | 
|---|
| 7664 |          frags in it.  */
 | 
|---|
| 7665 |       frag_variant (rs_fill, 0, 0, 0, NULL, 0, NULL);
 | 
|---|
| 7666 |       last_frag = frag_now;
 | 
|---|
| 7667 |       frag_variant (rs_fill, 0, 0, 0, NULL, 0, NULL);
 | 
|---|
| 7668 | 
 | 
|---|
| 7669 |       while (search_frag != frag_now) 
 | 
|---|
| 7670 |         {
 | 
|---|
| 7671 |           next_frag = search_frag->fr_next;
 | 
|---|
| 7672 | 
 | 
|---|
| 7673 |           /* First, move the frag out of the literal section and 
 | 
|---|
| 7674 |              to the appropriate place.  */
 | 
|---|
| 7675 |           if (search_frag->tc_frag_data.literal_frag)
 | 
|---|
| 7676 |             {
 | 
|---|
| 7677 |               literal_pool = search_frag->tc_frag_data.literal_frag;
 | 
|---|
| 7678 |               assert (literal_pool->fr_subtype == RELAX_LITERAL_POOL_BEGIN);
 | 
|---|
| 7679 |               /* Note that we set this fr_var to be a fix 
 | 
|---|
| 7680 |                  chain when we created the literal pool location
 | 
|---|
| 7681 |                  as RELAX_LITERAL_POOL_BEGIN.  */
 | 
|---|
| 7682 |               frchain_to = (frchainS *) literal_pool->fr_var;
 | 
|---|
| 7683 |             }
 | 
|---|
| 7684 |           insert_after = literal_pool;
 | 
|---|
| 7685 |           
 | 
|---|
| 7686 |           while (insert_after->fr_next->fr_subtype != RELAX_LITERAL_POOL_END)
 | 
|---|
| 7687 |             insert_after = insert_after->fr_next;
 | 
|---|
| 7688 | 
 | 
|---|
| 7689 |           dest_seg = (segT) insert_after->fr_next->fr_var;
 | 
|---|
| 7690 |           
 | 
|---|
| 7691 |           *frag_splice = next_frag;
 | 
|---|
| 7692 |           search_frag->fr_next = insert_after->fr_next;
 | 
|---|
| 7693 |           insert_after->fr_next = search_frag;
 | 
|---|
| 7694 |           search_frag->tc_frag_data.lit_seg = dest_seg;
 | 
|---|
| 7695 | 
 | 
|---|
| 7696 |           /* Now move any fixups associated with this frag to the
 | 
|---|
| 7697 |              right section.  */
 | 
|---|
| 7698 |           fix = frchain_from->fix_root;
 | 
|---|
| 7699 |           fix_splice = &(frchain_from->fix_root);
 | 
|---|
| 7700 |           while (fix)
 | 
|---|
| 7701 |             {
 | 
|---|
| 7702 |               next_fix = fix->fx_next;
 | 
|---|
| 7703 |               if (fix->fx_frag == search_frag)
 | 
|---|
| 7704 |                 {
 | 
|---|
| 7705 |                   *fix_splice = next_fix;
 | 
|---|
| 7706 |                   fix->fx_next = frchain_to->fix_root;
 | 
|---|
| 7707 |                   frchain_to->fix_root = fix;
 | 
|---|
| 7708 |                   if (frchain_to->fix_tail == NULL)
 | 
|---|
| 7709 |                     frchain_to->fix_tail = fix;
 | 
|---|
| 7710 |                 }
 | 
|---|
| 7711 |               else
 | 
|---|
| 7712 |                 fix_splice = &(fix->fx_next);
 | 
|---|
| 7713 |               fix = next_fix;
 | 
|---|
| 7714 |             }
 | 
|---|
| 7715 |           search_frag = next_frag;
 | 
|---|
| 7716 |         }
 | 
|---|
| 7717 | 
 | 
|---|
| 7718 |       if (frchain_from->fix_root != NULL)
 | 
|---|
| 7719 |         {
 | 
|---|
| 7720 |           frchain_from = seg_info (segment->seg)->frchainP;
 | 
|---|
| 7721 |           as_warn (_("fixes not all moved from %s"), segment->seg->name);
 | 
|---|
| 7722 | 
 | 
|---|
| 7723 |           assert (frchain_from->fix_root == NULL);
 | 
|---|
| 7724 |         }
 | 
|---|
| 7725 |       frchain_from->fix_tail = NULL;
 | 
|---|
| 7726 |       xtensa_restore_emit_state (&state);
 | 
|---|
| 7727 |       segment = segment->next;
 | 
|---|
| 7728 |     }
 | 
|---|
| 7729 | 
 | 
|---|
| 7730 |   xtensa_move_frag_symbols ();
 | 
|---|
| 7731 | }
 | 
|---|
| 7732 | 
 | 
|---|
| 7733 | 
 | 
|---|
| 7734 | static void
 | 
|---|
| 7735 | xtensa_move_frag_symbol (sym)
 | 
|---|
| 7736 |      symbolS *sym;
 | 
|---|
| 7737 | {
 | 
|---|
| 7738 |   fragS *frag = symbol_get_frag (sym);  
 | 
|---|
| 7739 | 
 | 
|---|
| 7740 |   if (frag->tc_frag_data.lit_seg != (segT) 0)
 | 
|---|
| 7741 |     S_SET_SEGMENT (sym, frag->tc_frag_data.lit_seg);
 | 
|---|
| 7742 | }
 | 
|---|
| 7743 | 
 | 
|---|
| 7744 | 
 | 
|---|
| 7745 | static void
 | 
|---|
| 7746 | xtensa_move_frag_symbols ()
 | 
|---|
| 7747 | {
 | 
|---|
| 7748 |   symbolS *symbolP;
 | 
|---|
| 7749 | 
 | 
|---|
| 7750 |   /* Although you might think that only one of these lists should be
 | 
|---|
| 7751 |      searched, it turns out that the difference of the two sets
 | 
|---|
| 7752 |      (either way) is not empty.  They do overlap quite a bit,
 | 
|---|
| 7753 |      however.  */
 | 
|---|
| 7754 | 
 | 
|---|
| 7755 |   for (symbolP = symbol_rootP; symbolP; symbolP = symbolP->sy_next)
 | 
|---|
| 7756 |     xtensa_move_frag_symbol (symbolP);
 | 
|---|
| 7757 | 
 | 
|---|
| 7758 |   map_over_defined_symbols (xtensa_move_frag_symbol);
 | 
|---|
| 7759 | }
 | 
|---|
| 7760 | 
 | 
|---|
| 7761 | 
 | 
|---|
| 7762 | static void
 | 
|---|
| 7763 | xtensa_reorder_seg_list (head, after)
 | 
|---|
| 7764 |      seg_list *head;
 | 
|---|
| 7765 |      segT after;
 | 
|---|
| 7766 | {
 | 
|---|
| 7767 |   /* Move all of the sections in the section list to come
 | 
|---|
| 7768 |      after "after" in the gnu segment list.  */
 | 
|---|
| 7769 | 
 | 
|---|
| 7770 |   head = head->next;
 | 
|---|
| 7771 |   while (head)
 | 
|---|
| 7772 |     {
 | 
|---|
| 7773 |       segT literal_section = head->seg;
 | 
|---|
| 7774 | 
 | 
|---|
| 7775 |       /* Move the literal section after "after".  */
 | 
|---|
| 7776 |       assert (literal_section);
 | 
|---|
| 7777 |       if (literal_section != after)
 | 
|---|
| 7778 |         {
 | 
|---|
| 7779 |           xtensa_remove_section (literal_section);
 | 
|---|
| 7780 |           xtensa_insert_section (after, literal_section);
 | 
|---|
| 7781 |         }
 | 
|---|
| 7782 | 
 | 
|---|
| 7783 |       head = head->next;
 | 
|---|
| 7784 |     }
 | 
|---|
| 7785 | }
 | 
|---|
| 7786 | 
 | 
|---|
| 7787 | 
 | 
|---|
| 7788 | /* Push all the literal segments to the end of the gnu list.  */
 | 
|---|
| 7789 | 
 | 
|---|
| 7790 | void
 | 
|---|
| 7791 | xtensa_reorder_segments ()
 | 
|---|
| 7792 | {
 | 
|---|
| 7793 |   segT sec;
 | 
|---|
| 7794 |   segT last_sec;
 | 
|---|
| 7795 |   int old_count = 0;
 | 
|---|
| 7796 |   int new_count = 0;
 | 
|---|
| 7797 | 
 | 
|---|
| 7798 |   for (sec = stdoutput->sections; sec != NULL; sec = sec->next)
 | 
|---|
| 7799 |     old_count++;
 | 
|---|
| 7800 | 
 | 
|---|
| 7801 |   /* Now that we have the last section, push all the literal
 | 
|---|
| 7802 |      sections to the end.  */
 | 
|---|
| 7803 |   last_sec = get_last_sec ();
 | 
|---|
| 7804 |   xtensa_reorder_seg_list (literal_head, last_sec);
 | 
|---|
| 7805 |   xtensa_reorder_seg_list (init_literal_head, last_sec);
 | 
|---|
| 7806 |   xtensa_reorder_seg_list (fini_literal_head, last_sec);
 | 
|---|
| 7807 | 
 | 
|---|
| 7808 |   /* Now perform the final error check.  */
 | 
|---|
| 7809 |   for (sec = stdoutput->sections; sec != NULL; sec = sec->next)
 | 
|---|
| 7810 |     new_count++;
 | 
|---|
| 7811 |   assert (new_count == old_count);
 | 
|---|
| 7812 | }
 | 
|---|
| 7813 | 
 | 
|---|
| 7814 | 
 | 
|---|
| 7815 | segT
 | 
|---|
| 7816 | get_last_sec ()
 | 
|---|
| 7817 | {
 | 
|---|
| 7818 |   segT last_sec = stdoutput->sections;
 | 
|---|
| 7819 |   while (last_sec->next != NULL)
 | 
|---|
| 7820 |     last_sec = last_sec->next;
 | 
|---|
| 7821 | 
 | 
|---|
| 7822 |   return last_sec;
 | 
|---|
| 7823 | }
 | 
|---|
| 7824 | 
 | 
|---|
| 7825 | 
 | 
|---|
| 7826 | /* Change the emit state (seg, subseg, and frag related stuff) to the
 | 
|---|
| 7827 |    correct location.  Return a emit_state which can be passed to
 | 
|---|
| 7828 |    xtensa_restore_emit_state to return to current fragment.  */
 | 
|---|
| 7829 | 
 | 
|---|
| 7830 | void
 | 
|---|
| 7831 | xtensa_switch_to_literal_fragment (result)
 | 
|---|
| 7832 |      emit_state *result;
 | 
|---|
| 7833 | {
 | 
|---|
| 7834 |   /* When we mark a literal pool location, we want to put a frag in
 | 
|---|
| 7835 |      the literal pool that points to it.  But to do that, we want to
 | 
|---|
| 7836 |      switch_to_literal_fragment.  But literal sections don't have
 | 
|---|
| 7837 |      literal pools, so their location is always null, so we would
 | 
|---|
| 7838 |      recurse forever.  This is kind of hacky, but it works.  */
 | 
|---|
| 7839 | 
 | 
|---|
| 7840 |   static bfd_boolean recursive = FALSE;
 | 
|---|
| 7841 |   fragS *pool_location = get_literal_pool_location (now_seg);
 | 
|---|
| 7842 |   bfd_boolean is_init = 
 | 
|---|
| 7843 |     (now_seg && !strcmp (segment_name (now_seg), INIT_SECTION_NAME));
 | 
|---|
| 7844 | 
 | 
|---|
| 7845 |   bfd_boolean is_fini = 
 | 
|---|
| 7846 |     (now_seg && !strcmp (segment_name (now_seg), FINI_SECTION_NAME));
 | 
|---|
| 7847 |   
 | 
|---|
| 7848 | 
 | 
|---|
| 7849 |   if (pool_location == NULL 
 | 
|---|
| 7850 |       && !use_literal_section 
 | 
|---|
| 7851 |       && !recursive
 | 
|---|
| 7852 |       && !is_init && ! is_fini)
 | 
|---|
| 7853 |     {
 | 
|---|
| 7854 |       as_warn (_("inlining literal pool; "
 | 
|---|
| 7855 |                  "specify location with .literal_position."));
 | 
|---|
| 7856 |       recursive = TRUE;
 | 
|---|
| 7857 |       xtensa_mark_literal_pool_location (FALSE);
 | 
|---|
| 7858 |       recursive = FALSE;
 | 
|---|
| 7859 |     }
 | 
|---|
| 7860 | 
 | 
|---|
| 7861 |   /* Special case: If we are in the ".fini" or ".init" section, then
 | 
|---|
| 7862 |      we will ALWAYS be generating to the ".fini.literal" and
 | 
|---|
| 7863 |      ".init.literal" sections.  */
 | 
|---|
| 7864 | 
 | 
|---|
| 7865 |   if (is_init)
 | 
|---|
| 7866 |     {
 | 
|---|
| 7867 |       cache_literal_section (init_literal_head,
 | 
|---|
| 7868 |                              default_lit_sections.init_lit_seg_name,
 | 
|---|
| 7869 |                              &default_lit_sections.init_lit_seg);
 | 
|---|
| 7870 |       xtensa_switch_section_emit_state (result,
 | 
|---|
| 7871 |                                         default_lit_sections.init_lit_seg, 0);
 | 
|---|
| 7872 |     }
 | 
|---|
| 7873 |   else if (is_fini)
 | 
|---|
| 7874 |     {
 | 
|---|
| 7875 |       cache_literal_section (fini_literal_head,
 | 
|---|
| 7876 |                              default_lit_sections.fini_lit_seg_name,
 | 
|---|
| 7877 |                              &default_lit_sections.fini_lit_seg);
 | 
|---|
| 7878 |       xtensa_switch_section_emit_state (result,
 | 
|---|
| 7879 |                                         default_lit_sections.fini_lit_seg, 0);
 | 
|---|
| 7880 |     }
 | 
|---|
| 7881 |   else 
 | 
|---|
| 7882 |     {
 | 
|---|
| 7883 |       cache_literal_section (literal_head,
 | 
|---|
| 7884 |                              default_lit_sections.lit_seg_name,
 | 
|---|
| 7885 |                              &default_lit_sections.lit_seg);
 | 
|---|
| 7886 |       xtensa_switch_section_emit_state (result,
 | 
|---|
| 7887 |                                         default_lit_sections.lit_seg, 0);
 | 
|---|
| 7888 |     }
 | 
|---|
| 7889 | 
 | 
|---|
| 7890 |   if (!use_literal_section &&
 | 
|---|
| 7891 |       !is_init && !is_fini &&
 | 
|---|
| 7892 |       get_literal_pool_location (now_seg) != pool_location)
 | 
|---|
| 7893 |     {
 | 
|---|
| 7894 |       /* Close whatever frag is there.  */
 | 
|---|
| 7895 |       frag_variant (rs_fill, 0, 0, 0, NULL, 0, NULL);
 | 
|---|
| 7896 |       frag_now->tc_frag_data.literal_frag = pool_location;
 | 
|---|
| 7897 |       frag_variant (rs_fill, 0, 0, 0, NULL, 0, NULL);
 | 
|---|
| 7898 |     }
 | 
|---|
| 7899 | 
 | 
|---|
| 7900 |   /* Do a 4 byte align here.  */
 | 
|---|
| 7901 |   frag_align (2, 0, 0);
 | 
|---|
| 7902 | }
 | 
|---|
| 7903 | 
 | 
|---|
| 7904 | 
 | 
|---|
| 7905 | /* Call this function before emitting data into the literal section.
 | 
|---|
| 7906 |    This is a helper function for xtensa_switch_to_literal_fragment.
 | 
|---|
| 7907 |    This is similar to a .section new_now_seg subseg. */
 | 
|---|
| 7908 | 
 | 
|---|
| 7909 | void
 | 
|---|
| 7910 | xtensa_switch_section_emit_state (state, new_now_seg, new_now_subseg)
 | 
|---|
| 7911 |      emit_state *state;
 | 
|---|
| 7912 |      segT new_now_seg;
 | 
|---|
| 7913 |      subsegT new_now_subseg;
 | 
|---|
| 7914 | {
 | 
|---|
| 7915 |   state->name = now_seg->name;
 | 
|---|
| 7916 |   state->now_seg = now_seg;
 | 
|---|
| 7917 |   state->now_subseg = now_subseg;
 | 
|---|
| 7918 |   state->generating_literals = generating_literals;
 | 
|---|
| 7919 |   generating_literals++;
 | 
|---|
| 7920 |   subseg_new (segment_name (new_now_seg), new_now_subseg);
 | 
|---|
| 7921 | }
 | 
|---|
| 7922 | 
 | 
|---|
| 7923 | 
 | 
|---|
| 7924 | /* Use to restore the emitting into the normal place.  */
 | 
|---|
| 7925 | 
 | 
|---|
| 7926 | void
 | 
|---|
| 7927 | xtensa_restore_emit_state (state)
 | 
|---|
| 7928 |      emit_state *state;
 | 
|---|
| 7929 | {
 | 
|---|
| 7930 |   generating_literals = state->generating_literals;
 | 
|---|
| 7931 |   subseg_new (state->name, state->now_subseg);
 | 
|---|
| 7932 | }
 | 
|---|
| 7933 | 
 | 
|---|
| 7934 | 
 | 
|---|
| 7935 | /* Get a segment of a given name.  If the segment is already
 | 
|---|
| 7936 |    present, return it; otherwise, create a new one.  */
 | 
|---|
| 7937 | 
 | 
|---|
| 7938 | static void
 | 
|---|
| 7939 | cache_literal_section (head, name, seg)
 | 
|---|
| 7940 |      seg_list *head;
 | 
|---|
| 7941 |      const char *name;
 | 
|---|
| 7942 |      segT *seg;
 | 
|---|
| 7943 | {
 | 
|---|
| 7944 |   segT current_section = now_seg;
 | 
|---|
| 7945 |   int current_subsec = now_subseg;
 | 
|---|
| 7946 | 
 | 
|---|
| 7947 |   if (*seg != 0)
 | 
|---|
| 7948 |     return;
 | 
|---|
| 7949 |   *seg = retrieve_literal_seg (head, name);
 | 
|---|
| 7950 |   subseg_set (current_section, current_subsec);
 | 
|---|
| 7951 | }
 | 
|---|
| 7952 | 
 | 
|---|
| 7953 | 
 | 
|---|
| 7954 | /* Get a segment of a given name.  If the segment is already
 | 
|---|
| 7955 |    present, return it; otherwise, create a new one.  */
 | 
|---|
| 7956 | 
 | 
|---|
| 7957 | static segT
 | 
|---|
| 7958 | retrieve_literal_seg (head, name)
 | 
|---|
| 7959 |      seg_list *head;
 | 
|---|
| 7960 |      const char *name;
 | 
|---|
| 7961 | {
 | 
|---|
| 7962 |   segT ret = 0;
 | 
|---|
| 7963 | 
 | 
|---|
| 7964 |   assert (head);
 | 
|---|
| 7965 | 
 | 
|---|
| 7966 |   ret = seg_present (name);
 | 
|---|
| 7967 |   if (!ret)
 | 
|---|
| 7968 |     {
 | 
|---|
| 7969 |       ret = subseg_new (name, (subsegT) 0);
 | 
|---|
| 7970 |       add_seg_list (head, ret);
 | 
|---|
| 7971 |       bfd_set_section_flags (stdoutput, ret, SEC_HAS_CONTENTS |
 | 
|---|
| 7972 |                              SEC_READONLY | SEC_ALLOC | SEC_LOAD | SEC_CODE);
 | 
|---|
| 7973 |       bfd_set_section_alignment (stdoutput, ret, 2);
 | 
|---|
| 7974 |     }
 | 
|---|
| 7975 | 
 | 
|---|
| 7976 |   return ret;
 | 
|---|
| 7977 | }
 | 
|---|
| 7978 | 
 | 
|---|
| 7979 | 
 | 
|---|
| 7980 | /* Return a segment of a given name if it is present.  */
 | 
|---|
| 7981 | 
 | 
|---|
| 7982 | static segT
 | 
|---|
| 7983 | seg_present (name)
 | 
|---|
| 7984 |      const char *name;
 | 
|---|
| 7985 | {
 | 
|---|
| 7986 |   segT seg;
 | 
|---|
| 7987 |   seg = stdoutput->sections;
 | 
|---|
| 7988 | 
 | 
|---|
| 7989 |   while (seg)
 | 
|---|
| 7990 |     {
 | 
|---|
| 7991 |       if (!strcmp (segment_name (seg), name))
 | 
|---|
| 7992 |         return seg;
 | 
|---|
| 7993 |       seg = seg->next;
 | 
|---|
| 7994 |     }
 | 
|---|
| 7995 | 
 | 
|---|
| 7996 |   return 0;
 | 
|---|
| 7997 | }
 | 
|---|
| 7998 | 
 | 
|---|
| 7999 | 
 | 
|---|
| 8000 | /* Add a segment to a segment list.  */
 | 
|---|
| 8001 | 
 | 
|---|
| 8002 | static void
 | 
|---|
| 8003 | add_seg_list (head, seg)
 | 
|---|
| 8004 |      seg_list *head;
 | 
|---|
| 8005 |      segT seg;
 | 
|---|
| 8006 | {
 | 
|---|
| 8007 |   seg_list *n;
 | 
|---|
| 8008 |   n = (seg_list *) xmalloc (sizeof (seg_list));
 | 
|---|
| 8009 |   assert (n);
 | 
|---|
| 8010 | 
 | 
|---|
| 8011 |   n->seg = seg;
 | 
|---|
| 8012 |   n->next = head->next;
 | 
|---|
| 8013 |   head->next = n;
 | 
|---|
| 8014 | }
 | 
|---|
| 8015 | 
 | 
|---|
| 8016 |  | 
|---|
| 8017 | 
 | 
|---|
| 8018 | /* Set up Property Tables after Relaxation.  */
 | 
|---|
| 8019 | 
 | 
|---|
| 8020 | #define XTENSA_INSN_SEC_NAME ".xt.insn"
 | 
|---|
| 8021 | #define XTENSA_LIT_SEC_NAME ".xt.lit"
 | 
|---|
| 8022 | 
 | 
|---|
| 8023 | void
 | 
|---|
| 8024 | xtensa_post_relax_hook ()
 | 
|---|
| 8025 | {
 | 
|---|
| 8026 |   xtensa_move_seg_list_to_beginning (literal_head);
 | 
|---|
| 8027 |   xtensa_move_seg_list_to_beginning (init_literal_head);
 | 
|---|
| 8028 |   xtensa_move_seg_list_to_beginning (fini_literal_head);
 | 
|---|
| 8029 | 
 | 
|---|
| 8030 |   xtensa_create_property_segments (get_frag_is_insn,
 | 
|---|
| 8031 |                                    XTENSA_INSN_SEC_NAME,
 | 
|---|
| 8032 |                                    xt_literal_sec);
 | 
|---|
| 8033 |   if (use_literal_section)
 | 
|---|
| 8034 |     xtensa_create_property_segments (get_frag_is_literal,
 | 
|---|
| 8035 |                                      XTENSA_LIT_SEC_NAME,
 | 
|---|
| 8036 |                                      xt_insn_sec);
 | 
|---|
| 8037 | }
 | 
|---|
| 8038 | 
 | 
|---|
| 8039 | 
 | 
|---|
| 8040 | static bfd_boolean
 | 
|---|
| 8041 | get_frag_is_literal (fragP)
 | 
|---|
| 8042 |      const fragS *fragP;
 | 
|---|
| 8043 | {
 | 
|---|
| 8044 |   assert (fragP != NULL);
 | 
|---|
| 8045 |   return (fragP->tc_frag_data.is_literal);
 | 
|---|
| 8046 | }
 | 
|---|
| 8047 |  
 | 
|---|
| 8048 | 
 | 
|---|
| 8049 | static bfd_boolean
 | 
|---|
| 8050 | get_frag_is_insn (fragP)
 | 
|---|
| 8051 |      const fragS *fragP;
 | 
|---|
| 8052 | {
 | 
|---|
| 8053 |   assert (fragP != NULL);
 | 
|---|
| 8054 |   return (fragP->tc_frag_data.is_insn);
 | 
|---|
| 8055 | }
 | 
|---|
| 8056 | 
 | 
|---|
| 8057 | 
 | 
|---|
| 8058 | static void
 | 
|---|
| 8059 | xtensa_create_property_segments (property_function, section_name_base, 
 | 
|---|
| 8060 |                                  sec_type)
 | 
|---|
| 8061 |      frag_predicate property_function;
 | 
|---|
| 8062 |      const char * section_name_base;
 | 
|---|
| 8063 |      xt_section_type sec_type;
 | 
|---|
| 8064 | {
 | 
|---|
| 8065 |   segT *seclist;
 | 
|---|
| 8066 | 
 | 
|---|
| 8067 |   /* Walk over all of the current segments.
 | 
|---|
| 8068 |      Walk over each fragment
 | 
|---|
| 8069 |       For each fragment that has instructions
 | 
|---|
| 8070 |       Build an instruction record (append where possible).  */
 | 
|---|
| 8071 | 
 | 
|---|
| 8072 |   for (seclist = &stdoutput->sections;
 | 
|---|
| 8073 |        seclist && *seclist;
 | 
|---|
| 8074 |        seclist = &(*seclist)->next)
 | 
|---|
| 8075 |     {
 | 
|---|
| 8076 |       segT sec = *seclist;
 | 
|---|
| 8077 |       if (section_has_property (sec, property_function))
 | 
|---|
| 8078 |         {
 | 
|---|
| 8079 |           char * property_section_name =
 | 
|---|
| 8080 |             xtensa_get_property_section_name (stdoutput, sec,
 | 
|---|
| 8081 |                                               section_name_base);
 | 
|---|
| 8082 |           segT insn_sec = retrieve_xtensa_section (property_section_name);
 | 
|---|
| 8083 |           segment_info_type *xt_seg_info = retrieve_segment_info (insn_sec);
 | 
|---|
| 8084 |           xtensa_block_info ** xt_blocks = 
 | 
|---|
| 8085 |             &xt_seg_info->tc_segment_info_data.blocks[sec_type];
 | 
|---|
| 8086 |           /* Walk over all of the frchains here and add new sections.  */
 | 
|---|
| 8087 |           add_xt_block_frags (sec, insn_sec, xt_blocks, property_function);
 | 
|---|
| 8088 |         }
 | 
|---|
| 8089 |     }
 | 
|---|
| 8090 | 
 | 
|---|
| 8091 |   /* Now we fill them out....  */
 | 
|---|
| 8092 | 
 | 
|---|
| 8093 |   for (seclist = &stdoutput->sections;
 | 
|---|
| 8094 |        seclist && *seclist;
 | 
|---|
| 8095 |        seclist = &(*seclist)->next)
 | 
|---|
| 8096 |     {
 | 
|---|
| 8097 |       segment_info_type *seginfo;
 | 
|---|
| 8098 |       xtensa_block_info *block;
 | 
|---|
| 8099 |       segT sec = *seclist;
 | 
|---|
| 8100 |       seginfo = seg_info (sec);
 | 
|---|
| 8101 |       block = seginfo->tc_segment_info_data.blocks[sec_type];
 | 
|---|
| 8102 | 
 | 
|---|
| 8103 |       if (block)
 | 
|---|
| 8104 |         {
 | 
|---|
| 8105 |           xtensa_block_info *cur_block;
 | 
|---|
| 8106 |           /* This is a section with some data.  */
 | 
|---|
| 8107 |           size_t num_recs = 0;
 | 
|---|
| 8108 |           size_t rec_size;
 | 
|---|
| 8109 | 
 | 
|---|
| 8110 |           for (cur_block = block; cur_block; cur_block = cur_block->next)
 | 
|---|
| 8111 |             num_recs++;
 | 
|---|
| 8112 | 
 | 
|---|
| 8113 |           rec_size = num_recs * 8;
 | 
|---|
| 8114 |           bfd_set_section_size (stdoutput, sec, rec_size);
 | 
|---|
| 8115 | 
 | 
|---|
| 8116 |           /* In order to make this work with the assembler, we have to
 | 
|---|
| 8117 |              build some frags and then build the "fixups" for it.  It
 | 
|---|
| 8118 |              would be easier to just set the contents then set the
 | 
|---|
| 8119 |              arlents.  */
 | 
|---|
| 8120 | 
 | 
|---|
| 8121 |           if (num_recs)
 | 
|---|
| 8122 |             {
 | 
|---|
| 8123 |               /* Allocate a fragment and leak it.  */
 | 
|---|
| 8124 |               fragS *fragP;
 | 
|---|
| 8125 |               size_t frag_size;
 | 
|---|
| 8126 |               fixS *fixes;
 | 
|---|
| 8127 |               frchainS *frchainP;
 | 
|---|
| 8128 |               size_t i;
 | 
|---|
| 8129 |               char *frag_data;
 | 
|---|
| 8130 | 
 | 
|---|
| 8131 |               frag_size = sizeof (fragS) + rec_size;
 | 
|---|
| 8132 |               fragP = (fragS *) xmalloc (frag_size);
 | 
|---|
| 8133 | 
 | 
|---|
| 8134 |               memset (fragP, 0, frag_size);
 | 
|---|
| 8135 |               fragP->fr_address = 0;
 | 
|---|
| 8136 |               fragP->fr_next = NULL;
 | 
|---|
| 8137 |               fragP->fr_fix = rec_size;
 | 
|---|
| 8138 |               fragP->fr_var = 0;
 | 
|---|
| 8139 |               fragP->fr_type = rs_fill;
 | 
|---|
| 8140 |               /* the rest are zeros */
 | 
|---|
| 8141 | 
 | 
|---|
| 8142 |               frchainP = seginfo->frchainP;
 | 
|---|
| 8143 |               frchainP->frch_root = fragP;
 | 
|---|
| 8144 |               frchainP->frch_last = fragP;
 | 
|---|
| 8145 | 
 | 
|---|
| 8146 |               fixes = (fixS *) xmalloc (sizeof (fixS) * num_recs);
 | 
|---|
| 8147 |               memset (fixes, 0, sizeof (fixS) * num_recs);
 | 
|---|
| 8148 | 
 | 
|---|
| 8149 |               seginfo->fix_root = fixes;
 | 
|---|
| 8150 |               seginfo->fix_tail = &fixes[num_recs - 1];
 | 
|---|
| 8151 |               cur_block = block;
 | 
|---|
| 8152 |               frag_data = &fragP->fr_literal[0];
 | 
|---|
| 8153 |               for (i = 0; i < num_recs; i++)
 | 
|---|
| 8154 |                 {
 | 
|---|
| 8155 |                   fixS *fix = &fixes[i];
 | 
|---|
| 8156 |                   assert (cur_block);
 | 
|---|
| 8157 | 
 | 
|---|
| 8158 |                   /* Write the fixup.  */
 | 
|---|
| 8159 |                   if (i != num_recs - 1)
 | 
|---|
| 8160 |                     fix->fx_next = &fixes[i + 1];
 | 
|---|
| 8161 |                   else
 | 
|---|
| 8162 |                     fix->fx_next = NULL;
 | 
|---|
| 8163 |                   fix->fx_size = 4;
 | 
|---|
| 8164 |                   fix->fx_done = 0;
 | 
|---|
| 8165 |                   fix->fx_frag = fragP;
 | 
|---|
| 8166 |                   fix->fx_where = i * 8;
 | 
|---|
| 8167 |                   fix->fx_addsy = section_symbol (cur_block->sec);
 | 
|---|
| 8168 |                   fix->fx_offset = cur_block->offset;
 | 
|---|
| 8169 |                   fix->fx_r_type = BFD_RELOC_32;
 | 
|---|
| 8170 |                   fix->fx_file = "Internal Assembly";
 | 
|---|
| 8171 |                   fix->fx_line = 0;
 | 
|---|
| 8172 | 
 | 
|---|
| 8173 |                   /* Write the length.  */
 | 
|---|
| 8174 |                   md_number_to_chars (&frag_data[4 + 8 * i],
 | 
|---|
| 8175 |                                       cur_block->size, 4);
 | 
|---|
| 8176 |                   cur_block = cur_block->next;
 | 
|---|
| 8177 |                 }
 | 
|---|
| 8178 |             }
 | 
|---|
| 8179 |         }
 | 
|---|
| 8180 |     }
 | 
|---|
| 8181 | }
 | 
|---|
| 8182 | 
 | 
|---|
| 8183 | 
 | 
|---|
| 8184 | segment_info_type *
 | 
|---|
| 8185 | retrieve_segment_info (seg)
 | 
|---|
| 8186 |      segT seg;
 | 
|---|
| 8187 | {
 | 
|---|
| 8188 |   segment_info_type *seginfo;
 | 
|---|
| 8189 |   seginfo = (segment_info_type *) bfd_get_section_userdata (stdoutput, seg);
 | 
|---|
| 8190 |   if (!seginfo)
 | 
|---|
| 8191 |     {
 | 
|---|
| 8192 |       frchainS *frchainP;
 | 
|---|
| 8193 | 
 | 
|---|
| 8194 |       seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo));
 | 
|---|
| 8195 |       memset ((PTR) seginfo, 0, sizeof (*seginfo));
 | 
|---|
| 8196 |       seginfo->fix_root = NULL;
 | 
|---|
| 8197 |       seginfo->fix_tail = NULL;
 | 
|---|
| 8198 |       seginfo->bfd_section = seg;
 | 
|---|
| 8199 |       seginfo->sym = 0;
 | 
|---|
| 8200 |       /* We will not be dealing with these, only our special ones.  */
 | 
|---|
| 8201 | #if 0
 | 
|---|
| 8202 |       if (seg == bfd_abs_section_ptr)
 | 
|---|
| 8203 |         abs_seg_info = seginfo;
 | 
|---|
| 8204 |       else if (seg == bfd_und_section_ptr)
 | 
|---|
| 8205 |         und_seg_info = seginfo;
 | 
|---|
| 8206 |       else
 | 
|---|
| 8207 | #endif
 | 
|---|
| 8208 |         bfd_set_section_userdata (stdoutput, seg, (PTR) seginfo);
 | 
|---|
| 8209 | #if 0
 | 
|---|
| 8210 |       seg_fix_rootP = &segment_info[seg].fix_root;
 | 
|---|
| 8211 |       seg_fix_tailP = &segment_info[seg].fix_tail;
 | 
|---|
| 8212 | #endif
 | 
|---|
| 8213 | 
 | 
|---|
| 8214 |       frchainP = (frchainS *) xmalloc (sizeof (frchainS));
 | 
|---|
| 8215 |       frchainP->frch_root = NULL;
 | 
|---|
| 8216 |       frchainP->frch_last = NULL;
 | 
|---|
| 8217 |       frchainP->frch_next = NULL;
 | 
|---|
| 8218 |       frchainP->frch_seg = seg;
 | 
|---|
| 8219 |       frchainP->frch_subseg = 0;
 | 
|---|
| 8220 |       frchainP->fix_root = NULL;
 | 
|---|
| 8221 |       frchainP->fix_tail = NULL;
 | 
|---|
| 8222 |       /* Do not init the objstack.  */
 | 
|---|
| 8223 |       /* obstack_begin (&frchainP->frch_obstack, chunksize); */
 | 
|---|
| 8224 |       /* frchainP->frch_frag_now = fragP; */
 | 
|---|
| 8225 |       frchainP->frch_frag_now = NULL;
 | 
|---|
| 8226 | 
 | 
|---|
| 8227 |       seginfo->frchainP = frchainP;
 | 
|---|
| 8228 |     }
 | 
|---|
| 8229 | 
 | 
|---|
| 8230 |   return seginfo;
 | 
|---|
| 8231 | }
 | 
|---|
| 8232 | 
 | 
|---|
| 8233 | 
 | 
|---|
| 8234 | segT
 | 
|---|
| 8235 | retrieve_xtensa_section (sec_name)
 | 
|---|
| 8236 |      char *sec_name;
 | 
|---|
| 8237 | {
 | 
|---|
| 8238 |   bfd *abfd = stdoutput;
 | 
|---|
| 8239 |   flagword flags, out_flags, link_once_flags;
 | 
|---|
| 8240 |   segT s;
 | 
|---|
| 8241 | 
 | 
|---|
| 8242 |   flags = bfd_get_section_flags (abfd, now_seg);
 | 
|---|
| 8243 |   link_once_flags = (flags & SEC_LINK_ONCE);
 | 
|---|
| 8244 |   if (link_once_flags)
 | 
|---|
| 8245 |     link_once_flags |= (flags & SEC_LINK_DUPLICATES);
 | 
|---|
| 8246 |   out_flags = (SEC_RELOC | SEC_HAS_CONTENTS | SEC_READONLY | link_once_flags);
 | 
|---|
| 8247 | 
 | 
|---|
| 8248 |   s = bfd_make_section_old_way (abfd, sec_name);
 | 
|---|
| 8249 |   if (s == NULL)
 | 
|---|
| 8250 |     as_bad (_("could not create section %s"), sec_name);
 | 
|---|
| 8251 |   if (!bfd_set_section_flags (abfd, s, out_flags))
 | 
|---|
| 8252 |     as_bad (_("invalid flag combination on section %s"), sec_name);
 | 
|---|
| 8253 | 
 | 
|---|
| 8254 |   return s;
 | 
|---|
| 8255 | }
 | 
|---|
| 8256 | 
 | 
|---|
| 8257 | 
 | 
|---|
| 8258 | bfd_boolean
 | 
|---|
| 8259 | section_has_property (sec, property_function)
 | 
|---|
| 8260 |      segT sec;
 | 
|---|
| 8261 |      frag_predicate property_function;
 | 
|---|
| 8262 | {
 | 
|---|
| 8263 |   segment_info_type *seginfo = seg_info (sec);
 | 
|---|
| 8264 |   fragS *fragP;
 | 
|---|
| 8265 | 
 | 
|---|
| 8266 |   if (seginfo && seginfo->frchainP)
 | 
|---|
| 8267 |     {
 | 
|---|
| 8268 |       for (fragP = seginfo->frchainP->frch_root; fragP; fragP = fragP->fr_next)
 | 
|---|
| 8269 |         {
 | 
|---|
| 8270 |           if (property_function (fragP)
 | 
|---|
| 8271 |               && (fragP->fr_type != rs_fill || fragP->fr_fix != 0))
 | 
|---|
| 8272 |             return TRUE;
 | 
|---|
| 8273 |         }
 | 
|---|
| 8274 |     }
 | 
|---|
| 8275 |   return FALSE;
 | 
|---|
| 8276 | }
 | 
|---|
| 8277 | 
 | 
|---|
| 8278 | 
 | 
|---|
| 8279 | /* Two types of block sections exist right now: literal and insns.  */
 | 
|---|
| 8280 | 
 | 
|---|
| 8281 | void
 | 
|---|
| 8282 | add_xt_block_frags (sec, xt_block_sec, xt_block, property_function)
 | 
|---|
| 8283 |      segT sec;
 | 
|---|
| 8284 |      segT xt_block_sec;
 | 
|---|
| 8285 |      xtensa_block_info **xt_block;
 | 
|---|
| 8286 |      frag_predicate property_function;
 | 
|---|
| 8287 | {
 | 
|---|
| 8288 |   segment_info_type *seg_info;
 | 
|---|
| 8289 |   segment_info_type *xt_seg_info;
 | 
|---|
| 8290 |   bfd_vma seg_offset;
 | 
|---|
| 8291 |   fragS *fragP;
 | 
|---|
| 8292 | 
 | 
|---|
| 8293 |   xt_seg_info = retrieve_segment_info (xt_block_sec);
 | 
|---|
| 8294 |   seg_info = retrieve_segment_info (sec);
 | 
|---|
| 8295 | 
 | 
|---|
| 8296 |   /* Build it if needed.  */
 | 
|---|
| 8297 |   while (*xt_block != NULL)
 | 
|---|
| 8298 |     xt_block = &(*xt_block)->next;
 | 
|---|
| 8299 |   /* We are either at NULL at the beginning or at the end.  */
 | 
|---|
| 8300 | 
 | 
|---|
| 8301 |   /* Walk through the frags.  */
 | 
|---|
| 8302 |   seg_offset = 0;
 | 
|---|
| 8303 | 
 | 
|---|
| 8304 |   if (seg_info->frchainP)
 | 
|---|
| 8305 |     {
 | 
|---|
| 8306 |       for (fragP = seg_info->frchainP->frch_root;
 | 
|---|
| 8307 |            fragP;
 | 
|---|
| 8308 |            fragP = fragP->fr_next)
 | 
|---|
| 8309 |         {
 | 
|---|
| 8310 |           if (property_function (fragP)
 | 
|---|
| 8311 |               && (fragP->fr_type != rs_fill || fragP->fr_fix != 0))
 | 
|---|
| 8312 |             {
 | 
|---|
| 8313 |               if (*xt_block != NULL)
 | 
|---|
| 8314 |                 {
 | 
|---|
| 8315 |                   if ((*xt_block)->offset + (*xt_block)->size
 | 
|---|
| 8316 |                       == fragP->fr_address)
 | 
|---|
| 8317 |                     (*xt_block)->size += fragP->fr_fix;
 | 
|---|
| 8318 |                   else
 | 
|---|
| 8319 |                     xt_block = &((*xt_block)->next);
 | 
|---|
| 8320 |                 }
 | 
|---|
| 8321 |               if (*xt_block == NULL)
 | 
|---|
| 8322 |                 {
 | 
|---|
| 8323 |                   xtensa_block_info *new_block = (xtensa_block_info *)
 | 
|---|
| 8324 |                     xmalloc (sizeof (xtensa_block_info));
 | 
|---|
| 8325 |                   new_block->sec = sec;
 | 
|---|
| 8326 |                   new_block->offset = fragP->fr_address;
 | 
|---|
| 8327 |                   new_block->size = fragP->fr_fix;
 | 
|---|
| 8328 |                   new_block->next = NULL;
 | 
|---|
| 8329 |                   *xt_block = new_block;
 | 
|---|
| 8330 |                 }
 | 
|---|
| 8331 |             }
 | 
|---|
| 8332 |         }
 | 
|---|
| 8333 |     }
 | 
|---|
| 8334 | }
 | 
|---|
| 8335 | 
 | 
|---|
| 8336 |  | 
|---|
| 8337 | 
 | 
|---|
| 8338 | /* Instruction Stack Functions (from "xtensa-istack.h").  */
 | 
|---|
| 8339 | 
 | 
|---|
| 8340 | void
 | 
|---|
| 8341 | istack_init (stack)
 | 
|---|
| 8342 |      IStack *stack;
 | 
|---|
| 8343 | {
 | 
|---|
| 8344 |   memset (stack, 0, sizeof (IStack));
 | 
|---|
| 8345 |   stack->ninsn = 0;
 | 
|---|
| 8346 | }
 | 
|---|
| 8347 | 
 | 
|---|
| 8348 | 
 | 
|---|
| 8349 | bfd_boolean
 | 
|---|
| 8350 | istack_empty (stack)
 | 
|---|
| 8351 |      IStack *stack;
 | 
|---|
| 8352 | {
 | 
|---|
| 8353 |   return (stack->ninsn == 0);
 | 
|---|
| 8354 | }
 | 
|---|
| 8355 | 
 | 
|---|
| 8356 | 
 | 
|---|
| 8357 | bfd_boolean
 | 
|---|
| 8358 | istack_full (stack)
 | 
|---|
| 8359 |      IStack *stack;
 | 
|---|
| 8360 | {
 | 
|---|
| 8361 |   return (stack->ninsn == MAX_ISTACK);
 | 
|---|
| 8362 | }
 | 
|---|
| 8363 | 
 | 
|---|
| 8364 | 
 | 
|---|
| 8365 | /* Return a pointer to the top IStack entry.
 | 
|---|
| 8366 |    It is an error to call this if istack_empty () is true. */
 | 
|---|
| 8367 | 
 | 
|---|
| 8368 | TInsn *
 | 
|---|
| 8369 | istack_top (stack)
 | 
|---|
| 8370 |      IStack *stack;
 | 
|---|
| 8371 | {
 | 
|---|
| 8372 |   int rec = stack->ninsn - 1;
 | 
|---|
| 8373 |   assert (!istack_empty (stack));
 | 
|---|
| 8374 |   return &stack->insn[rec];
 | 
|---|
| 8375 | }
 | 
|---|
| 8376 | 
 | 
|---|
| 8377 | 
 | 
|---|
| 8378 | /* Add a new TInsn to an IStack.
 | 
|---|
| 8379 |    It is an error to call this if istack_full () is true.  */
 | 
|---|
| 8380 | 
 | 
|---|
| 8381 | void
 | 
|---|
| 8382 | istack_push (stack, insn)
 | 
|---|
| 8383 |      IStack *stack;
 | 
|---|
| 8384 |      TInsn *insn;
 | 
|---|
| 8385 | {
 | 
|---|
| 8386 |   int rec = stack->ninsn;
 | 
|---|
| 8387 |   assert (!istack_full (stack));
 | 
|---|
| 8388 |   tinsn_copy (&stack->insn[rec], insn);
 | 
|---|
| 8389 |   stack->ninsn++;
 | 
|---|
| 8390 | }
 | 
|---|
| 8391 | 
 | 
|---|
| 8392 | 
 | 
|---|
| 8393 | /* Clear space for the next TInsn on the IStack and return a pointer
 | 
|---|
| 8394 |    to it.  It is an error to call this if istack_full () is true.  */
 | 
|---|
| 8395 | 
 | 
|---|
| 8396 | TInsn *
 | 
|---|
| 8397 | istack_push_space (stack)
 | 
|---|
| 8398 |      IStack *stack;
 | 
|---|
| 8399 | {
 | 
|---|
| 8400 |   int rec = stack->ninsn;
 | 
|---|
| 8401 |   TInsn *insn;
 | 
|---|
| 8402 |   assert (!istack_full (stack));
 | 
|---|
| 8403 |   insn = &stack->insn[rec];
 | 
|---|
| 8404 |   memset (insn, 0, sizeof (TInsn));
 | 
|---|
| 8405 |   stack->ninsn++;
 | 
|---|
| 8406 |   return insn;
 | 
|---|
| 8407 | }
 | 
|---|
| 8408 | 
 | 
|---|
| 8409 | 
 | 
|---|
| 8410 | /* Remove the last pushed instruction.  It is an error to call this if
 | 
|---|
| 8411 |    istack_empty () returns true.  */
 | 
|---|
| 8412 | 
 | 
|---|
| 8413 | void
 | 
|---|
| 8414 | istack_pop (stack)
 | 
|---|
| 8415 |      IStack *stack;
 | 
|---|
| 8416 | {
 | 
|---|
| 8417 |   int rec = stack->ninsn - 1;
 | 
|---|
| 8418 |   assert (!istack_empty (stack));
 | 
|---|
| 8419 |   stack->ninsn--;
 | 
|---|
| 8420 |   memset (&stack->insn[rec], 0, sizeof (TInsn));
 | 
|---|
| 8421 | }
 | 
|---|
| 8422 | 
 | 
|---|
| 8423 |  | 
|---|
| 8424 | 
 | 
|---|
| 8425 | /* TInsn functions.  */
 | 
|---|
| 8426 | 
 | 
|---|
| 8427 | void
 | 
|---|
| 8428 | tinsn_init (dst)
 | 
|---|
| 8429 |      TInsn *dst;
 | 
|---|
| 8430 | {
 | 
|---|
| 8431 |   memset (dst, 0, sizeof (TInsn));
 | 
|---|
| 8432 | }
 | 
|---|
| 8433 | 
 | 
|---|
| 8434 | 
 | 
|---|
| 8435 | void
 | 
|---|
| 8436 | tinsn_copy (dst, src)
 | 
|---|
| 8437 |      TInsn *dst;
 | 
|---|
| 8438 |      const TInsn *src;
 | 
|---|
| 8439 | {
 | 
|---|
| 8440 |   tinsn_init (dst);
 | 
|---|
| 8441 |   memcpy (dst, src, sizeof (TInsn));
 | 
|---|
| 8442 | }
 | 
|---|
| 8443 | 
 | 
|---|
| 8444 | 
 | 
|---|
| 8445 | /* Get the ``num''th token of the TInsn.
 | 
|---|
| 8446 |    It is illegal to call this if num > insn->ntoks.  */
 | 
|---|
| 8447 | 
 | 
|---|
| 8448 | expressionS *
 | 
|---|
| 8449 | tinsn_get_tok (insn, num)
 | 
|---|
| 8450 |      TInsn *insn;
 | 
|---|
| 8451 |      int num;
 | 
|---|
| 8452 | {
 | 
|---|
| 8453 |   assert (num < insn->ntok);
 | 
|---|
| 8454 |   return &insn->tok[num];
 | 
|---|
| 8455 | }
 | 
|---|
| 8456 | 
 | 
|---|
| 8457 | 
 | 
|---|
| 8458 | /* Return true if ANY of the operands in the insn are symbolic.  */
 | 
|---|
| 8459 | 
 | 
|---|
| 8460 | static bfd_boolean
 | 
|---|
| 8461 | tinsn_has_symbolic_operands (insn)
 | 
|---|
| 8462 |      const TInsn *insn;
 | 
|---|
| 8463 | {
 | 
|---|
| 8464 |   int i;
 | 
|---|
| 8465 |   int n = insn->ntok;
 | 
|---|
| 8466 | 
 | 
|---|
| 8467 |   assert (insn->insn_type == ITYPE_INSN);
 | 
|---|
| 8468 | 
 | 
|---|
| 8469 |   for (i = 0; i < n; ++i)
 | 
|---|
| 8470 |     {
 | 
|---|
| 8471 |       switch (insn->tok[i].X_op)
 | 
|---|
| 8472 |         {
 | 
|---|
| 8473 |         case O_register:
 | 
|---|
| 8474 |         case O_constant:
 | 
|---|
| 8475 |           break;
 | 
|---|
| 8476 |         default:
 | 
|---|
| 8477 |           return TRUE;
 | 
|---|
| 8478 |         }
 | 
|---|
| 8479 |     }
 | 
|---|
| 8480 |   return FALSE;
 | 
|---|
| 8481 | }
 | 
|---|
| 8482 | 
 | 
|---|
| 8483 | 
 | 
|---|
| 8484 | bfd_boolean
 | 
|---|
| 8485 | tinsn_has_invalid_symbolic_operands (insn)
 | 
|---|
| 8486 |      const TInsn *insn;
 | 
|---|
| 8487 | {
 | 
|---|
| 8488 |   int i;
 | 
|---|
| 8489 |   int n = insn->ntok;
 | 
|---|
| 8490 | 
 | 
|---|
| 8491 |   assert (insn->insn_type == ITYPE_INSN);
 | 
|---|
| 8492 | 
 | 
|---|
| 8493 |   for (i = 0; i < n; ++i)
 | 
|---|
| 8494 |     {
 | 
|---|
| 8495 |       switch (insn->tok[i].X_op)
 | 
|---|
| 8496 |         {
 | 
|---|
| 8497 |         case O_register:
 | 
|---|
| 8498 |         case O_constant:
 | 
|---|
| 8499 |           break;
 | 
|---|
| 8500 |         default:
 | 
|---|
| 8501 |           if (i == get_relaxable_immed (insn->opcode))
 | 
|---|
| 8502 |             break;
 | 
|---|
| 8503 |           as_bad (_("invalid symbolic operand %d on '%s'"),
 | 
|---|
| 8504 |                   i, xtensa_opcode_name (xtensa_default_isa, insn->opcode));
 | 
|---|
| 8505 |           return TRUE;
 | 
|---|
| 8506 |         }
 | 
|---|
| 8507 |     }
 | 
|---|
| 8508 |   return FALSE;
 | 
|---|
| 8509 | }
 | 
|---|
| 8510 | 
 | 
|---|
| 8511 | 
 | 
|---|
| 8512 | /* For assembly code with complex expressions (e.g. subtraction),
 | 
|---|
| 8513 |    we have to build them in the literal pool so that
 | 
|---|
| 8514 |    their results are calculated correctly after relaxation.
 | 
|---|
| 8515 |    The relaxation only handles expressions that
 | 
|---|
| 8516 |    boil down to SYMBOL + OFFSET.  */
 | 
|---|
| 8517 | 
 | 
|---|
| 8518 | static bfd_boolean
 | 
|---|
| 8519 | tinsn_has_complex_operands (insn)
 | 
|---|
| 8520 |      const TInsn *insn;
 | 
|---|
| 8521 | {
 | 
|---|
| 8522 |   int i;
 | 
|---|
| 8523 |   int n = insn->ntok;
 | 
|---|
| 8524 |   assert (insn->insn_type == ITYPE_INSN);
 | 
|---|
| 8525 |   for (i = 0; i < n; ++i)
 | 
|---|
| 8526 |     {
 | 
|---|
| 8527 |       switch (insn->tok[i].X_op)
 | 
|---|
| 8528 |         {
 | 
|---|
| 8529 |         case O_register:
 | 
|---|
| 8530 |         case O_constant:
 | 
|---|
| 8531 |         case O_symbol:
 | 
|---|
| 8532 |           break;
 | 
|---|
| 8533 |         default:
 | 
|---|
| 8534 |           return TRUE;
 | 
|---|
| 8535 |         }
 | 
|---|
| 8536 |     }
 | 
|---|
| 8537 |   return FALSE;
 | 
|---|
| 8538 | }
 | 
|---|
| 8539 | 
 | 
|---|
| 8540 | 
 | 
|---|
| 8541 | /* Convert the constant operands in the t_insn to insnbuf.
 | 
|---|
| 8542 |    Return true if there is a symbol in the immediate field.
 | 
|---|
| 8543 | 
 | 
|---|
| 8544 |    Before this is called, 
 | 
|---|
| 8545 |    1) the number of operands are correct
 | 
|---|
| 8546 |    2) the t_insn is a ITYPE_INSN
 | 
|---|
| 8547 |    3) ONLY the relaxable_ is built
 | 
|---|
| 8548 |    4) All operands are O_constant, O_symbol.  All constants fit
 | 
|---|
| 8549 |    The return value tells whether there are any remaining O_symbols.  */
 | 
|---|
| 8550 | 
 | 
|---|
| 8551 | static bfd_boolean
 | 
|---|
| 8552 | tinsn_to_insnbuf (t_insn, insnbuf)
 | 
|---|
| 8553 |      TInsn *t_insn;
 | 
|---|
| 8554 |      xtensa_insnbuf insnbuf;
 | 
|---|
| 8555 | {
 | 
|---|
| 8556 |   xtensa_isa isa = xtensa_default_isa;
 | 
|---|
| 8557 |   xtensa_opcode opcode = t_insn->opcode;
 | 
|---|
| 8558 |   bfd_boolean has_fixup = FALSE;
 | 
|---|
| 8559 |   int noperands = xtensa_num_operands (isa, opcode);
 | 
|---|
| 8560 |   int i;
 | 
|---|
| 8561 |   uint32 opnd_value;
 | 
|---|
| 8562 |   char *file_name;
 | 
|---|
| 8563 |   int line;
 | 
|---|
| 8564 | 
 | 
|---|
| 8565 |   assert (t_insn->insn_type == ITYPE_INSN);
 | 
|---|
| 8566 |   if (noperands != t_insn->ntok)
 | 
|---|
| 8567 |     as_fatal (_("operand number mismatch"));
 | 
|---|
| 8568 | 
 | 
|---|
| 8569 |   xtensa_encode_insn (isa, opcode, insnbuf);
 | 
|---|
| 8570 | 
 | 
|---|
| 8571 |   for (i = 0; i < noperands; ++i)
 | 
|---|
| 8572 |     {
 | 
|---|
| 8573 |       expressionS *expr = &t_insn->tok[i];
 | 
|---|
| 8574 |       xtensa_operand operand = xtensa_get_operand (isa, opcode, i);
 | 
|---|
| 8575 |       switch (expr->X_op)
 | 
|---|
| 8576 |         {
 | 
|---|
| 8577 |         case O_register:
 | 
|---|
| 8578 |           /* The register number has already been checked in  
 | 
|---|
| 8579 |              expression_maybe_register, so we don't need to check here.  */
 | 
|---|
| 8580 |           opnd_value = expr->X_add_number;
 | 
|---|
| 8581 |           (void) xtensa_operand_encode (operand, &opnd_value);
 | 
|---|
| 8582 |           xtensa_operand_set_field (operand, insnbuf, opnd_value);
 | 
|---|
| 8583 |           break;
 | 
|---|
| 8584 | 
 | 
|---|
| 8585 |         case O_constant:
 | 
|---|
| 8586 |           as_where (&file_name, &line);
 | 
|---|
| 8587 |           /* It is a constant and we called this function,
 | 
|---|
| 8588 |              then we have to try to fit it.  */
 | 
|---|
| 8589 |           xtensa_insnbuf_set_operand (insnbuf, opcode, operand,
 | 
|---|
| 8590 |                                       expr->X_add_number, file_name, line);
 | 
|---|
| 8591 |           break;
 | 
|---|
| 8592 | 
 | 
|---|
| 8593 |         case O_symbol:
 | 
|---|
| 8594 |         default:
 | 
|---|
| 8595 |           has_fixup = TRUE;
 | 
|---|
| 8596 |           break;
 | 
|---|
| 8597 |         }
 | 
|---|
| 8598 |     }
 | 
|---|
| 8599 |   return has_fixup;
 | 
|---|
| 8600 | }
 | 
|---|
| 8601 | 
 | 
|---|
| 8602 | 
 | 
|---|
| 8603 | /* Check the instruction arguments.  Return true on failure.  */
 | 
|---|
| 8604 | 
 | 
|---|
| 8605 | bfd_boolean
 | 
|---|
| 8606 | tinsn_check_arguments (insn)
 | 
|---|
| 8607 |      const TInsn *insn;
 | 
|---|
| 8608 | {
 | 
|---|
| 8609 |   xtensa_isa isa = xtensa_default_isa;
 | 
|---|
| 8610 |   xtensa_opcode opcode = insn->opcode;
 | 
|---|
| 8611 | 
 | 
|---|
| 8612 |   if (opcode == XTENSA_UNDEFINED)
 | 
|---|
| 8613 |     {
 | 
|---|
| 8614 |       as_bad (_("invalid opcode"));
 | 
|---|
| 8615 |       return TRUE;
 | 
|---|
| 8616 |     }
 | 
|---|
| 8617 | 
 | 
|---|
| 8618 |   if (xtensa_num_operands (isa, opcode) > insn->ntok)
 | 
|---|
| 8619 |     {
 | 
|---|
| 8620 |       as_bad (_("too few operands"));
 | 
|---|
| 8621 |       return TRUE;
 | 
|---|
| 8622 |     }
 | 
|---|
| 8623 | 
 | 
|---|
| 8624 |   if (xtensa_num_operands (isa, opcode) < insn->ntok)
 | 
|---|
| 8625 |     {
 | 
|---|
| 8626 |       as_bad (_("too many operands"));
 | 
|---|
| 8627 |       return TRUE;
 | 
|---|
| 8628 |     }
 | 
|---|
| 8629 |   return FALSE;
 | 
|---|
| 8630 | }
 | 
|---|
| 8631 | 
 | 
|---|
| 8632 | 
 | 
|---|
| 8633 | /* Load an instruction from its encoded form.  */
 | 
|---|
| 8634 | 
 | 
|---|
| 8635 | static void
 | 
|---|
| 8636 | tinsn_from_chars (t_insn, f)
 | 
|---|
| 8637 |      TInsn *t_insn;
 | 
|---|
| 8638 |      char *f;
 | 
|---|
| 8639 | {
 | 
|---|
| 8640 |   static xtensa_insnbuf insnbuf = NULL;
 | 
|---|
| 8641 |   int i;
 | 
|---|
| 8642 |   xtensa_opcode opcode;
 | 
|---|
| 8643 |   xtensa_isa isa = xtensa_default_isa;
 | 
|---|
| 8644 | 
 | 
|---|
| 8645 |   if (!insnbuf)
 | 
|---|
| 8646 |     insnbuf = xtensa_insnbuf_alloc (isa);
 | 
|---|
| 8647 | 
 | 
|---|
| 8648 |   xtensa_insnbuf_from_chars (isa, insnbuf, f);
 | 
|---|
| 8649 |   opcode = xtensa_decode_insn (isa, insnbuf);
 | 
|---|
| 8650 | 
 | 
|---|
| 8651 |   /* Find the immed.  */
 | 
|---|
| 8652 |   tinsn_init (t_insn);
 | 
|---|
| 8653 |   t_insn->insn_type = ITYPE_INSN;
 | 
|---|
| 8654 |   t_insn->is_specific_opcode = FALSE;   /* Must not be specific.  */
 | 
|---|
| 8655 |   t_insn->opcode = opcode;
 | 
|---|
| 8656 |   t_insn->ntok = xtensa_num_operands (isa, opcode);
 | 
|---|
| 8657 |   for (i = 0; i < t_insn->ntok; i++)
 | 
|---|
| 8658 |     {
 | 
|---|
| 8659 |       set_expr_const (&t_insn->tok[i],
 | 
|---|
| 8660 |                       xtensa_insnbuf_get_operand (insnbuf, opcode, i));
 | 
|---|
| 8661 |     }
 | 
|---|
| 8662 | }
 | 
|---|
| 8663 | 
 | 
|---|
| 8664 | 
 | 
|---|
| 8665 | /* Read the value of the relaxable immed from the fr_symbol and fr_offset.  */
 | 
|---|
| 8666 | 
 | 
|---|
| 8667 | static void
 | 
|---|
| 8668 | tinsn_immed_from_frag (t_insn, fragP)
 | 
|---|
| 8669 |      TInsn *t_insn;
 | 
|---|
| 8670 |      fragS *fragP;
 | 
|---|
| 8671 | {
 | 
|---|
| 8672 |   xtensa_opcode opcode = t_insn->opcode;
 | 
|---|
| 8673 |   int opnum;
 | 
|---|
| 8674 | 
 | 
|---|
| 8675 |   if (fragP->fr_symbol)
 | 
|---|
| 8676 |     {
 | 
|---|
| 8677 |       opnum = get_relaxable_immed (opcode);
 | 
|---|
| 8678 |       set_expr_symbol_offset (&t_insn->tok[opnum],
 | 
|---|
| 8679 |                               fragP->fr_symbol, fragP->fr_offset);
 | 
|---|
| 8680 |     }
 | 
|---|
| 8681 | }
 | 
|---|
| 8682 | 
 | 
|---|
| 8683 | 
 | 
|---|
| 8684 | static int
 | 
|---|
| 8685 | get_num_stack_text_bytes (istack)
 | 
|---|
| 8686 |      IStack *istack;
 | 
|---|
| 8687 | {
 | 
|---|
| 8688 |   int i;
 | 
|---|
| 8689 |   int text_bytes = 0;
 | 
|---|
| 8690 | 
 | 
|---|
| 8691 |   for (i = 0; i < istack->ninsn; i++)
 | 
|---|
| 8692 |     {
 | 
|---|
| 8693 |       TInsn *t_insn = &istack->insn[i];
 | 
|---|
| 8694 |       if (t_insn->insn_type == ITYPE_INSN)
 | 
|---|
| 8695 |         text_bytes += xg_get_insn_size (t_insn);
 | 
|---|
| 8696 |     }
 | 
|---|
| 8697 |   return text_bytes;
 | 
|---|
| 8698 | }
 | 
|---|
| 8699 | 
 | 
|---|
| 8700 | 
 | 
|---|
| 8701 | static int
 | 
|---|
| 8702 | get_num_stack_literal_bytes (istack)
 | 
|---|
| 8703 |      IStack *istack;
 | 
|---|
| 8704 | {
 | 
|---|
| 8705 |   int i;
 | 
|---|
| 8706 |   int lit_bytes = 0;
 | 
|---|
| 8707 | 
 | 
|---|
| 8708 |   for (i = 0; i < istack->ninsn; i++)
 | 
|---|
| 8709 |     {
 | 
|---|
| 8710 |       TInsn *t_insn = &istack->insn[i];
 | 
|---|
| 8711 | 
 | 
|---|
| 8712 |       if (t_insn->insn_type == ITYPE_LITERAL && t_insn->ntok == 1)
 | 
|---|
| 8713 |         lit_bytes += 4;
 | 
|---|
| 8714 |     }
 | 
|---|
| 8715 |   return lit_bytes;
 | 
|---|
| 8716 | }
 | 
|---|
| 8717 | 
 | 
|---|
| 8718 |  | 
|---|
| 8719 | 
 | 
|---|
| 8720 | /* Expression utilities.  */
 | 
|---|
| 8721 | 
 | 
|---|
| 8722 | /* Return true if the expression is an integer constant.  */
 | 
|---|
| 8723 | 
 | 
|---|
| 8724 | bfd_boolean
 | 
|---|
| 8725 | expr_is_const (s)
 | 
|---|
| 8726 |      const expressionS *s;
 | 
|---|
| 8727 | {
 | 
|---|
| 8728 |   return (s->X_op == O_constant);
 | 
|---|
| 8729 | }
 | 
|---|
| 8730 | 
 | 
|---|
| 8731 | 
 | 
|---|
| 8732 | /* Get the expression constant.
 | 
|---|
| 8733 |    Calling this is illegal if expr_is_const () returns true.  */
 | 
|---|
| 8734 | 
 | 
|---|
| 8735 | offsetT
 | 
|---|
| 8736 | get_expr_const (s)
 | 
|---|
| 8737 |      const expressionS *s;
 | 
|---|
| 8738 | {
 | 
|---|
| 8739 |   assert (expr_is_const (s));
 | 
|---|
| 8740 |   return s->X_add_number;
 | 
|---|
| 8741 | }
 | 
|---|
| 8742 | 
 | 
|---|
| 8743 | 
 | 
|---|
| 8744 | /* Set the expression to a constant value.  */
 | 
|---|
| 8745 | 
 | 
|---|
| 8746 | void
 | 
|---|
| 8747 | set_expr_const (s, val)
 | 
|---|
| 8748 |      expressionS *s;
 | 
|---|
| 8749 |      offsetT val;
 | 
|---|
| 8750 | {
 | 
|---|
| 8751 |   s->X_op = O_constant;
 | 
|---|
| 8752 |   s->X_add_number = val;
 | 
|---|
| 8753 |   s->X_add_symbol = NULL;
 | 
|---|
| 8754 |   s->X_op_symbol = NULL;
 | 
|---|
| 8755 | }
 | 
|---|
| 8756 | 
 | 
|---|
| 8757 | 
 | 
|---|
| 8758 | /* Set the expression to a symbol + constant offset.  */
 | 
|---|
| 8759 | 
 | 
|---|
| 8760 | void
 | 
|---|
| 8761 | set_expr_symbol_offset (s, sym, offset)
 | 
|---|
| 8762 |      expressionS *s;
 | 
|---|
| 8763 |      symbolS *sym;
 | 
|---|
| 8764 |      offsetT offset;
 | 
|---|
| 8765 | {
 | 
|---|
| 8766 |   s->X_op = O_symbol;
 | 
|---|
| 8767 |   s->X_add_symbol = sym;
 | 
|---|
| 8768 |   s->X_op_symbol = NULL;        /* unused */
 | 
|---|
| 8769 |   s->X_add_number = offset;
 | 
|---|
| 8770 | }
 | 
|---|
| 8771 | 
 | 
|---|
| 8772 | 
 | 
|---|
| 8773 | bfd_boolean
 | 
|---|
| 8774 | expr_is_equal (s1, s2)
 | 
|---|
| 8775 |      expressionS *s1;
 | 
|---|
| 8776 |      expressionS *s2;
 | 
|---|
| 8777 | {
 | 
|---|
| 8778 |   if (s1->X_op != s2->X_op)
 | 
|---|
| 8779 |     return FALSE;
 | 
|---|
| 8780 |   if (s1->X_add_symbol != s2->X_add_symbol)
 | 
|---|
| 8781 |     return FALSE;
 | 
|---|
| 8782 |   if (s1->X_op_symbol != s2->X_op_symbol)
 | 
|---|
| 8783 |     return FALSE;
 | 
|---|
| 8784 |   if (s1->X_add_number != s2->X_add_number)
 | 
|---|
| 8785 |     return FALSE;
 | 
|---|
| 8786 |   return TRUE;
 | 
|---|
| 8787 | }
 | 
|---|
| 8788 | 
 | 
|---|
| 8789 | 
 | 
|---|
| 8790 | static void
 | 
|---|
| 8791 | copy_expr (dst, src)
 | 
|---|
| 8792 |      expressionS *dst;
 | 
|---|
| 8793 |      const expressionS *src;
 | 
|---|
| 8794 | {
 | 
|---|
| 8795 |   memcpy (dst, src, sizeof (expressionS));
 | 
|---|
| 8796 | }
 | 
|---|
| 8797 | 
 | 
|---|
| 8798 |  | 
|---|
| 8799 | 
 | 
|---|
| 8800 | /* Support for Tensilica's "--rename-section" option.  */
 | 
|---|
| 8801 | 
 | 
|---|
| 8802 | #ifdef XTENSA_SECTION_RENAME
 | 
|---|
| 8803 | 
 | 
|---|
| 8804 | struct rename_section_struct
 | 
|---|
| 8805 | {
 | 
|---|
| 8806 |   char *old_name;
 | 
|---|
| 8807 |   char *new_name;
 | 
|---|
| 8808 |   struct rename_section_struct *next;
 | 
|---|
| 8809 | };
 | 
|---|
| 8810 | 
 | 
|---|
| 8811 | static struct rename_section_struct *section_rename;
 | 
|---|
| 8812 | 
 | 
|---|
| 8813 | 
 | 
|---|
| 8814 | /* Parse the string oldname=new_name:oldname2=new_name2 
 | 
|---|
| 8815 |    and call add_section_rename.  */
 | 
|---|
| 8816 | 
 | 
|---|
| 8817 | void
 | 
|---|
| 8818 | build_section_rename (arg)
 | 
|---|
| 8819 |      const char *arg;
 | 
|---|
| 8820 | {
 | 
|---|
| 8821 |   char *this_arg = NULL;
 | 
|---|
| 8822 |   char *next_arg = NULL;
 | 
|---|
| 8823 | 
 | 
|---|
| 8824 |   for (this_arg = strdup (arg); this_arg != NULL; this_arg = next_arg)
 | 
|---|
| 8825 |     {
 | 
|---|
| 8826 |       if (this_arg)
 | 
|---|
| 8827 |         {
 | 
|---|
| 8828 |           next_arg = strchr (this_arg, ':');
 | 
|---|
| 8829 |           if (next_arg)
 | 
|---|
| 8830 |             {
 | 
|---|
| 8831 |               *next_arg = '\0';
 | 
|---|
| 8832 |               next_arg++;
 | 
|---|
| 8833 |             }
 | 
|---|
| 8834 |         }
 | 
|---|
| 8835 |       {
 | 
|---|
| 8836 |         char *old_name = this_arg;
 | 
|---|
| 8837 |         char *new_name = strchr (this_arg, '=');
 | 
|---|
| 8838 | 
 | 
|---|
| 8839 |         if (*old_name == '\0')
 | 
|---|
| 8840 |           {
 | 
|---|
| 8841 |             as_warn (_("ignoring extra '-rename-section' delimiter ':'"));
 | 
|---|
| 8842 |             continue;
 | 
|---|
| 8843 |           }
 | 
|---|
| 8844 |         if (!new_name || new_name[1] == '\0')
 | 
|---|
| 8845 |           {
 | 
|---|
| 8846 |             as_warn (_("ignoring invalid '-rename-section' "
 | 
|---|
| 8847 |                        "specification: '%s'"), old_name);
 | 
|---|
| 8848 |             continue;
 | 
|---|
| 8849 |           }
 | 
|---|
| 8850 |         *new_name = '\0';
 | 
|---|
| 8851 |         new_name++;
 | 
|---|
| 8852 |         add_section_rename (old_name, new_name);
 | 
|---|
| 8853 |       }
 | 
|---|
| 8854 |     }
 | 
|---|
| 8855 | }
 | 
|---|
| 8856 | 
 | 
|---|
| 8857 | 
 | 
|---|
| 8858 | static void
 | 
|---|
| 8859 | add_section_rename (old_name, new_name)
 | 
|---|
| 8860 |      char *old_name;
 | 
|---|
| 8861 |      char *new_name;
 | 
|---|
| 8862 | {
 | 
|---|
| 8863 |   struct rename_section_struct *r = section_rename;
 | 
|---|
| 8864 | 
 | 
|---|
| 8865 |   /* Check for invalid section renaming.  */
 | 
|---|
| 8866 |   for (r = section_rename; r != NULL; r = r->next)
 | 
|---|
| 8867 |     {
 | 
|---|
| 8868 |       if (strcmp (r->old_name, old_name) == 0)
 | 
|---|
| 8869 |         as_bad (_("section %s renamed multiple times"), old_name);
 | 
|---|
| 8870 |       if (strcmp (r->new_name, new_name) == 0)
 | 
|---|
| 8871 |         as_bad (_("multiple sections remapped to output section %s"),
 | 
|---|
| 8872 |                 new_name);
 | 
|---|
| 8873 |     }
 | 
|---|
| 8874 | 
 | 
|---|
| 8875 |   /* Now add it.  */
 | 
|---|
| 8876 |   r = (struct rename_section_struct *)
 | 
|---|
| 8877 |     xmalloc (sizeof (struct rename_section_struct));
 | 
|---|
| 8878 |   r->old_name = strdup (old_name);
 | 
|---|
| 8879 |   r->new_name = strdup (new_name);
 | 
|---|
| 8880 |   r->next = section_rename;
 | 
|---|
| 8881 |   section_rename = r;
 | 
|---|
| 8882 | }
 | 
|---|
| 8883 | 
 | 
|---|
| 8884 | 
 | 
|---|
| 8885 | const char *
 | 
|---|
| 8886 | xtensa_section_rename (name)
 | 
|---|
| 8887 |      const char *name;
 | 
|---|
| 8888 | {
 | 
|---|
| 8889 |   struct rename_section_struct *r = section_rename;
 | 
|---|
| 8890 | 
 | 
|---|
| 8891 |   for (r = section_rename; r != NULL; r = r->next)
 | 
|---|
| 8892 |     if (strcmp (r->old_name, name) == 0)
 | 
|---|
| 8893 |       return r->new_name;
 | 
|---|
| 8894 | 
 | 
|---|
| 8895 |   return name;
 | 
|---|
| 8896 | }
 | 
|---|
| 8897 | 
 | 
|---|
| 8898 | #endif /* XTENSA_SECTION_RENAME */
 | 
|---|
| 8899 | 
 | 
|---|
| 8900 |  | 
|---|
| 8901 | 
 | 
|---|
| 8902 | /* Combining identical literals.  */
 | 
|---|
| 8903 | 
 | 
|---|
| 8904 | #ifdef XTENSA_COMBINE_LITERALS 
 | 
|---|
| 8905 | 
 | 
|---|
| 8906 | /* This code records all the .literal values that are ever seen and
 | 
|---|
| 8907 |    detects duplicates so that identical values can be combined.  This
 | 
|---|
| 8908 |    is currently disabled because it's only half-baked.  */
 | 
|---|
| 8909 | 
 | 
|---|
| 8910 | #define XTENSA_LIT_PLUS_OFFSET ".xtensa_litsym_offset_"
 | 
|---|
| 8911 | 
 | 
|---|
| 8912 | /* TODO: make this into a more efficient data structure.  */
 | 
|---|
| 8913 | typedef struct literal_list_elem
 | 
|---|
| 8914 | {
 | 
|---|
| 8915 |   symbolS *sym;                 /* The symbol that points to this literal.  */
 | 
|---|
| 8916 |   expressionS expr;             /* The expression.  */
 | 
|---|
| 8917 |   segT seg;
 | 
|---|
| 8918 |   struct literal_list_elem *next; /* Next in the list.  */
 | 
|---|
| 8919 | } literal_list_elem;
 | 
|---|
| 8920 | 
 | 
|---|
| 8921 | literal_list_elem *lit_cache = NULL;
 | 
|---|
| 8922 | 
 | 
|---|
| 8923 | typedef struct lit_sym_translation
 | 
|---|
| 8924 | {
 | 
|---|
| 8925 |   char *name;                   /* This name.  */
 | 
|---|
| 8926 |   offsetT offset;               /* Plus this offset.  */
 | 
|---|
| 8927 |   symbolS *sym;                 /* Should really mean this symbol.  */
 | 
|---|
| 8928 |   struct lit_sym_translation *next;
 | 
|---|
| 8929 | } lit_sym_translation;
 | 
|---|
| 8930 | 
 | 
|---|
| 8931 | lit_sym_translation *translations = NULL;
 | 
|---|
| 8932 | 
 | 
|---|
| 8933 | static bfd_boolean is_duplicate_expression
 | 
|---|
| 8934 |   PARAMS ((expressionS *, expressionS *));
 | 
|---|
| 8935 | static void cache_literal
 | 
|---|
| 8936 |   PARAMS ((char *sym_name, expressionS *, segT));
 | 
|---|
| 8937 | static symbolS *is_duplicate_literal
 | 
|---|
| 8938 |   PARAMS ((expressionS *, segT));
 | 
|---|
| 8939 | 
 | 
|---|
| 8940 | 
 | 
|---|
| 8941 | static bfd_boolean
 | 
|---|
| 8942 | is_duplicate_expression (e1, e2)
 | 
|---|
| 8943 |      expressionS *e1;
 | 
|---|
| 8944 |      expressionS *e2;
 | 
|---|
| 8945 | {
 | 
|---|
| 8946 |   if (e1->X_op != e2->X_op)
 | 
|---|
| 8947 |     return FALSE;
 | 
|---|
| 8948 |   if (e1->X_add_symbol != e2->X_add_symbol)
 | 
|---|
| 8949 |     return FALSE;
 | 
|---|
| 8950 |   if (e1->X_op_symbol != e2->X_op_symbol)
 | 
|---|
| 8951 |     return FALSE;
 | 
|---|
| 8952 |   if (e1->X_add_number != e2->X_add_number)
 | 
|---|
| 8953 |     return FALSE;
 | 
|---|
| 8954 |   if (e1->X_unsigned != e2->X_unsigned)
 | 
|---|
| 8955 |     return FALSE;
 | 
|---|
| 8956 |   if (e1->X_md != e2->X_md)
 | 
|---|
| 8957 |     return FALSE;
 | 
|---|
| 8958 |   return TRUE;
 | 
|---|
| 8959 | }
 | 
|---|
| 8960 | 
 | 
|---|
| 8961 | 
 | 
|---|
| 8962 | static void
 | 
|---|
| 8963 | cache_literal (sym_name, expP, seg)
 | 
|---|
| 8964 |      char *sym_name;
 | 
|---|
| 8965 |      expressionS *expP;
 | 
|---|
| 8966 |      segT seg;
 | 
|---|
| 8967 | {
 | 
|---|
| 8968 |   literal_list_elem *lit = xmalloc (sizeof (literal_list_elem));
 | 
|---|
| 8969 | 
 | 
|---|
| 8970 |   lit->sym = symbol_find (sym_name);
 | 
|---|
| 8971 |   lit->expr = *expP;
 | 
|---|
| 8972 |   lit->seg = seg;
 | 
|---|
| 8973 |   lit->next = lit_cache;
 | 
|---|
| 8974 |   lit_cache = lit;
 | 
|---|
| 8975 | }
 | 
|---|
| 8976 | 
 | 
|---|
| 8977 |  
 | 
|---|
| 8978 | static symbolS *
 | 
|---|
| 8979 | is_duplicate_literal (expr, seg)
 | 
|---|
| 8980 |      expressionS *expr;
 | 
|---|
| 8981 |      segT seg;
 | 
|---|
| 8982 | {
 | 
|---|
| 8983 |   literal_list_elem *lit = lit_cache;
 | 
|---|
| 8984 | 
 | 
|---|
| 8985 |   while (lit != NULL) 
 | 
|---|
| 8986 |     {
 | 
|---|
| 8987 |       if (is_duplicate_expression (&lit->expr, expr) && seg == lit->seg)
 | 
|---|
| 8988 |         return lit->sym;
 | 
|---|
| 8989 |       lit = lit->next;
 | 
|---|
| 8990 |     }
 | 
|---|
| 8991 | 
 | 
|---|
| 8992 |   return NULL;
 | 
|---|
| 8993 | }
 | 
|---|
| 8994 | 
 | 
|---|
| 8995 | 
 | 
|---|
| 8996 | static void
 | 
|---|
| 8997 | add_lit_sym_translation (name, offset, target)
 | 
|---|
| 8998 |      char * name;
 | 
|---|
| 8999 |      offsetT offset;
 | 
|---|
| 9000 |      symbolS * target;
 | 
|---|
| 9001 | {
 | 
|---|
| 9002 |   lit_sym_translation *lit_trans = xmalloc (sizeof (lit_sym_translation));
 | 
|---|
| 9003 | 
 | 
|---|
| 9004 |   lit_trans->name = name;
 | 
|---|
| 9005 |   lit_trans->offset = offset;
 | 
|---|
| 9006 |   lit_trans->sym = target;
 | 
|---|
| 9007 |   lit_trans->next = translations;
 | 
|---|
| 9008 |   translations = lit_trans;
 | 
|---|
| 9009 | }
 | 
|---|
| 9010 | 
 | 
|---|
| 9011 | 
 | 
|---|
| 9012 | static void
 | 
|---|
| 9013 | find_lit_sym_translation (expr)
 | 
|---|
| 9014 |      expressionS *expr;
 | 
|---|
| 9015 | {
 | 
|---|
| 9016 |   lit_sym_translation *lit_trans = translations;
 | 
|---|
| 9017 | 
 | 
|---|
| 9018 |   if (expr->X_op != O_symbol)
 | 
|---|
| 9019 |     return;
 | 
|---|
| 9020 | 
 | 
|---|
| 9021 |   while (lit_trans != NULL)
 | 
|---|
| 9022 |     {
 | 
|---|
| 9023 |       if (lit_trans->offset == expr->X_add_number 
 | 
|---|
| 9024 |           && strcmp (lit_trans->name, S_GET_NAME (expr->X_add_symbol)) == 0)
 | 
|---|
| 9025 |         {
 | 
|---|
| 9026 |           expr->X_add_symbol = lit_trans->sym;
 | 
|---|
| 9027 |           expr->X_add_number = 0;
 | 
|---|
| 9028 |           return;
 | 
|---|
| 9029 |         }
 | 
|---|
| 9030 |       lit_trans = lit_trans->next;
 | 
|---|
| 9031 |     }
 | 
|---|
| 9032 | }
 | 
|---|
| 9033 | 
 | 
|---|
| 9034 | #endif /* XTENSA_COMBINE_LITERALS */
 | 
|---|