1*3d8817e4Smiod /* tc-xtensa.c -- Assemble Xtensa instructions.
2*3d8817e4Smiod    Copyright 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
3*3d8817e4Smiod 
4*3d8817e4Smiod    This file is part of GAS, the GNU Assembler.
5*3d8817e4Smiod 
6*3d8817e4Smiod    GAS is free software; you can redistribute it and/or modify
7*3d8817e4Smiod    it under the terms of the GNU General Public License as published by
8*3d8817e4Smiod    the Free Software Foundation; either version 2, or (at your option)
9*3d8817e4Smiod    any later version.
10*3d8817e4Smiod 
11*3d8817e4Smiod    GAS is distributed in the hope that it will be useful,
12*3d8817e4Smiod    but WITHOUT ANY WARRANTY; without even the implied warranty of
13*3d8817e4Smiod    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*3d8817e4Smiod    GNU General Public License for more details.
15*3d8817e4Smiod 
16*3d8817e4Smiod    You should have received a copy of the GNU General Public License
17*3d8817e4Smiod    along with GAS; see the file COPYING.  If not, write to
18*3d8817e4Smiod    the Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
19*3d8817e4Smiod    MA 02110-1301, USA.  */
20*3d8817e4Smiod 
21*3d8817e4Smiod #include <string.h>
22*3d8817e4Smiod #include <limits.h>
23*3d8817e4Smiod #include "as.h"
24*3d8817e4Smiod #include "sb.h"
25*3d8817e4Smiod #include "safe-ctype.h"
26*3d8817e4Smiod #include "tc-xtensa.h"
27*3d8817e4Smiod #include "frags.h"
28*3d8817e4Smiod #include "subsegs.h"
29*3d8817e4Smiod #include "xtensa-relax.h"
30*3d8817e4Smiod #include "xtensa-istack.h"
31*3d8817e4Smiod #include "dwarf2dbg.h"
32*3d8817e4Smiod #include "struc-symbol.h"
33*3d8817e4Smiod #include "xtensa-config.h"
34*3d8817e4Smiod 
35*3d8817e4Smiod #ifndef uint32
36*3d8817e4Smiod #define uint32 unsigned int
37*3d8817e4Smiod #endif
38*3d8817e4Smiod #ifndef int32
39*3d8817e4Smiod #define int32 signed int
40*3d8817e4Smiod #endif
41*3d8817e4Smiod 
42*3d8817e4Smiod /* Notes:
43*3d8817e4Smiod 
44*3d8817e4Smiod    Naming conventions (used somewhat inconsistently):
45*3d8817e4Smiod       The xtensa_ functions are exported
46*3d8817e4Smiod       The xg_ functions are internal
47*3d8817e4Smiod 
48*3d8817e4Smiod    We also have a couple of different extensibility mechanisms.
49*3d8817e4Smiod    1) The idiom replacement:
50*3d8817e4Smiod       This is used when a line is first parsed to
51*3d8817e4Smiod       replace an instruction pattern with another instruction
52*3d8817e4Smiod       It is currently limited to replacements of instructions
53*3d8817e4Smiod       with constant operands.
54*3d8817e4Smiod    2) The xtensa-relax.c mechanism that has stronger instruction
55*3d8817e4Smiod       replacement patterns.  When an instruction's immediate field
56*3d8817e4Smiod       does not fit the next instruction sequence is attempted.
57*3d8817e4Smiod       In addition, "narrow" opcodes are supported this way.  */
58*3d8817e4Smiod 
59*3d8817e4Smiod 
60*3d8817e4Smiod /* Define characters with special meanings to GAS.  */
61*3d8817e4Smiod const char comment_chars[] = "#";
62*3d8817e4Smiod const char line_comment_chars[] = "#";
63*3d8817e4Smiod const char line_separator_chars[] = ";";
64*3d8817e4Smiod const char EXP_CHARS[] = "eE";
65*3d8817e4Smiod const char FLT_CHARS[] = "rRsSfFdDxXpP";
66*3d8817e4Smiod 
67*3d8817e4Smiod 
68*3d8817e4Smiod /* Flags to indicate whether the hardware supports the density and
69*3d8817e4Smiod    absolute literals options.  */
70*3d8817e4Smiod 
71*3d8817e4Smiod bfd_boolean density_supported = XCHAL_HAVE_DENSITY;
72*3d8817e4Smiod bfd_boolean absolute_literals_supported = XSHAL_USE_ABSOLUTE_LITERALS;
73*3d8817e4Smiod 
74*3d8817e4Smiod /* Maximum width we would pad an unreachable frag to get alignment.  */
75*3d8817e4Smiod #define UNREACHABLE_MAX_WIDTH  8
76*3d8817e4Smiod 
77*3d8817e4Smiod static vliw_insn cur_vinsn;
78*3d8817e4Smiod 
79*3d8817e4Smiod unsigned xtensa_fetch_width = XCHAL_INST_FETCH_WIDTH;
80*3d8817e4Smiod 
81*3d8817e4Smiod static enum debug_info_type xt_saved_debug_type = DEBUG_NONE;
82*3d8817e4Smiod 
83*3d8817e4Smiod /* Some functions are only valid in the front end.  This variable
84*3d8817e4Smiod    allows us to assert that we haven't crossed over into the
85*3d8817e4Smiod    back end.  */
86*3d8817e4Smiod static bfd_boolean past_xtensa_end = FALSE;
87*3d8817e4Smiod 
88*3d8817e4Smiod /* Flags for properties of the last instruction in a segment.  */
89*3d8817e4Smiod #define FLAG_IS_A0_WRITER	0x1
90*3d8817e4Smiod #define FLAG_IS_BAD_LOOPEND	0x2
91*3d8817e4Smiod 
92*3d8817e4Smiod 
93*3d8817e4Smiod /* We define a special segment names ".literal" to place literals
94*3d8817e4Smiod    into.  The .fini and .init sections are special because they
95*3d8817e4Smiod    contain code that is moved together by the linker.  We give them
96*3d8817e4Smiod    their own special .fini.literal and .init.literal sections.  */
97*3d8817e4Smiod 
98*3d8817e4Smiod #define LITERAL_SECTION_NAME		xtensa_section_rename (".literal")
99*3d8817e4Smiod #define LIT4_SECTION_NAME		xtensa_section_rename (".lit4")
100*3d8817e4Smiod #define FINI_SECTION_NAME		xtensa_section_rename (".fini")
101*3d8817e4Smiod #define INIT_SECTION_NAME		xtensa_section_rename (".init")
102*3d8817e4Smiod #define FINI_LITERAL_SECTION_NAME	xtensa_section_rename (".fini.literal")
103*3d8817e4Smiod #define INIT_LITERAL_SECTION_NAME	xtensa_section_rename (".init.literal")
104*3d8817e4Smiod 
105*3d8817e4Smiod 
106*3d8817e4Smiod /* This type is used for the directive_stack to keep track of the
107*3d8817e4Smiod    state of the literal collection pools.  */
108*3d8817e4Smiod 
109*3d8817e4Smiod typedef struct lit_state_struct
110*3d8817e4Smiod {
111*3d8817e4Smiod   const char *lit_seg_name;
112*3d8817e4Smiod   const char *lit4_seg_name;
113*3d8817e4Smiod   const char *init_lit_seg_name;
114*3d8817e4Smiod   const char *fini_lit_seg_name;
115*3d8817e4Smiod   segT lit_seg;
116*3d8817e4Smiod   segT lit4_seg;
117*3d8817e4Smiod   segT init_lit_seg;
118*3d8817e4Smiod   segT fini_lit_seg;
119*3d8817e4Smiod } lit_state;
120*3d8817e4Smiod 
121*3d8817e4Smiod static lit_state default_lit_sections;
122*3d8817e4Smiod 
123*3d8817e4Smiod 
124*3d8817e4Smiod /* We keep lists of literal segments.  The seg_list type is the node
125*3d8817e4Smiod    for such a list.  The *_literal_head locals are the heads of the
126*3d8817e4Smiod    various lists.  All of these lists have a dummy node at the start.  */
127*3d8817e4Smiod 
128*3d8817e4Smiod typedef struct seg_list_struct
129*3d8817e4Smiod {
130*3d8817e4Smiod   struct seg_list_struct *next;
131*3d8817e4Smiod   segT seg;
132*3d8817e4Smiod } seg_list;
133*3d8817e4Smiod 
134*3d8817e4Smiod static seg_list literal_head_h;
135*3d8817e4Smiod static seg_list *literal_head = &literal_head_h;
136*3d8817e4Smiod static seg_list init_literal_head_h;
137*3d8817e4Smiod static seg_list *init_literal_head = &init_literal_head_h;
138*3d8817e4Smiod static seg_list fini_literal_head_h;
139*3d8817e4Smiod static seg_list *fini_literal_head = &fini_literal_head_h;
140*3d8817e4Smiod 
141*3d8817e4Smiod 
142*3d8817e4Smiod /* Lists of symbols.  We keep a list of symbols that label the current
143*3d8817e4Smiod    instruction, so that we can adjust the symbols when inserting alignment
144*3d8817e4Smiod    for various instructions.  We also keep a list of all the symbols on
145*3d8817e4Smiod    literals, so that we can fix up those symbols when the literals are
146*3d8817e4Smiod    later moved into the text sections.  */
147*3d8817e4Smiod 
148*3d8817e4Smiod typedef struct sym_list_struct
149*3d8817e4Smiod {
150*3d8817e4Smiod   struct sym_list_struct *next;
151*3d8817e4Smiod   symbolS *sym;
152*3d8817e4Smiod } sym_list;
153*3d8817e4Smiod 
154*3d8817e4Smiod static sym_list *insn_labels = NULL;
155*3d8817e4Smiod static sym_list *free_insn_labels = NULL;
156*3d8817e4Smiod static sym_list *saved_insn_labels = NULL;
157*3d8817e4Smiod 
158*3d8817e4Smiod static sym_list *literal_syms;
159*3d8817e4Smiod 
160*3d8817e4Smiod 
161*3d8817e4Smiod /* Flags to determine whether to prefer const16 or l32r
162*3d8817e4Smiod    if both options are available.  */
163*3d8817e4Smiod int prefer_const16 = 0;
164*3d8817e4Smiod int prefer_l32r = 0;
165*3d8817e4Smiod 
166*3d8817e4Smiod /* Global flag to indicate when we are emitting literals.  */
167*3d8817e4Smiod int generating_literals = 0;
168*3d8817e4Smiod 
169*3d8817e4Smiod /* The following PROPERTY table definitions are copied from
170*3d8817e4Smiod    <elf/xtensa.h> and must be kept in sync with the code there.  */
171*3d8817e4Smiod 
172*3d8817e4Smiod /* Flags in the property tables to specify whether blocks of memory
173*3d8817e4Smiod    are literals, instructions, data, or unreachable.  For
174*3d8817e4Smiod    instructions, blocks that begin loop targets and branch targets are
175*3d8817e4Smiod    designated.  Blocks that do not allow density, instruction
176*3d8817e4Smiod    reordering or transformation are also specified.  Finally, for
177*3d8817e4Smiod    branch targets, branch target alignment priority is included.
178*3d8817e4Smiod    Alignment of the next block is specified in the current block
179*3d8817e4Smiod    and the size of the current block does not include any fill required
180*3d8817e4Smiod    to align to the next block.  */
181*3d8817e4Smiod 
182*3d8817e4Smiod #define XTENSA_PROP_LITERAL		0x00000001
183*3d8817e4Smiod #define XTENSA_PROP_INSN		0x00000002
184*3d8817e4Smiod #define XTENSA_PROP_DATA		0x00000004
185*3d8817e4Smiod #define XTENSA_PROP_UNREACHABLE		0x00000008
186*3d8817e4Smiod /* Instruction only properties at beginning of code.  */
187*3d8817e4Smiod #define XTENSA_PROP_INSN_LOOP_TARGET	0x00000010
188*3d8817e4Smiod #define XTENSA_PROP_INSN_BRANCH_TARGET	0x00000020
189*3d8817e4Smiod /* Instruction only properties about code.  */
190*3d8817e4Smiod #define XTENSA_PROP_INSN_NO_DENSITY	0x00000040
191*3d8817e4Smiod #define XTENSA_PROP_INSN_NO_REORDER	0x00000080
192*3d8817e4Smiod #define XTENSA_PROP_INSN_NO_TRANSFORM	0x00000100
193*3d8817e4Smiod 
194*3d8817e4Smiod /*  Branch target alignment information.  This transmits information
195*3d8817e4Smiod     to the linker optimization about the priority of aligning a
196*3d8817e4Smiod     particular block for branch target alignment: None, low priority,
197*3d8817e4Smiod     high priority, or required.  These only need to be checked in
198*3d8817e4Smiod     instruction blocks marked as XTENSA_PROP_INSN_BRANCH_TARGET.
199*3d8817e4Smiod     Common usage is
200*3d8817e4Smiod 
201*3d8817e4Smiod     switch (GET_XTENSA_PROP_BT_ALIGN (flags))
202*3d8817e4Smiod     case XTENSA_PROP_BT_ALIGN_NONE:
203*3d8817e4Smiod     case XTENSA_PROP_BT_ALIGN_LOW:
204*3d8817e4Smiod     case XTENSA_PROP_BT_ALIGN_HIGH:
205*3d8817e4Smiod     case XTENSA_PROP_BT_ALIGN_REQUIRE:
206*3d8817e4Smiod */
207*3d8817e4Smiod #define XTENSA_PROP_BT_ALIGN_MASK       0x00000600
208*3d8817e4Smiod 
209*3d8817e4Smiod /* No branch target alignment.  */
210*3d8817e4Smiod #define XTENSA_PROP_BT_ALIGN_NONE       0x0
211*3d8817e4Smiod /* Low priority branch target alignment.  */
212*3d8817e4Smiod #define XTENSA_PROP_BT_ALIGN_LOW        0x1
213*3d8817e4Smiod /* High priority branch target alignment.  */
214*3d8817e4Smiod #define XTENSA_PROP_BT_ALIGN_HIGH       0x2
215*3d8817e4Smiod /* Required branch target alignment.  */
216*3d8817e4Smiod #define XTENSA_PROP_BT_ALIGN_REQUIRE    0x3
217*3d8817e4Smiod 
218*3d8817e4Smiod #define GET_XTENSA_PROP_BT_ALIGN(flag) \
219*3d8817e4Smiod   (((unsigned) ((flag) & (XTENSA_PROP_BT_ALIGN_MASK))) >> 9)
220*3d8817e4Smiod #define SET_XTENSA_PROP_BT_ALIGN(flag, align) \
221*3d8817e4Smiod   (((flag) & (~XTENSA_PROP_BT_ALIGN_MASK)) | \
222*3d8817e4Smiod     (((align) << 9) & XTENSA_PROP_BT_ALIGN_MASK))
223*3d8817e4Smiod 
224*3d8817e4Smiod 
225*3d8817e4Smiod /* Alignment is specified in the block BEFORE the one that needs
226*3d8817e4Smiod    alignment.  Up to 5 bits.  Use GET_XTENSA_PROP_ALIGNMENT(flags) to
227*3d8817e4Smiod    get the required alignment specified as a power of 2.  Use
228*3d8817e4Smiod    SET_XTENSA_PROP_ALIGNMENT(flags, pow2) to set the required
229*3d8817e4Smiod    alignment.  Be careful of side effects since the SET will evaluate
230*3d8817e4Smiod    flags twice.  Also, note that the SIZE of a block in the property
231*3d8817e4Smiod    table does not include the alignment size, so the alignment fill
232*3d8817e4Smiod    must be calculated to determine if two blocks are contiguous.
233*3d8817e4Smiod    TEXT_ALIGN is not currently implemented but is a placeholder for a
234*3d8817e4Smiod    possible future implementation.  */
235*3d8817e4Smiod 
236*3d8817e4Smiod #define XTENSA_PROP_ALIGN		0x00000800
237*3d8817e4Smiod 
238*3d8817e4Smiod #define XTENSA_PROP_ALIGNMENT_MASK      0x0001f000
239*3d8817e4Smiod 
240*3d8817e4Smiod #define GET_XTENSA_PROP_ALIGNMENT(flag) \
241*3d8817e4Smiod   (((unsigned) ((flag) & (XTENSA_PROP_ALIGNMENT_MASK))) >> 12)
242*3d8817e4Smiod #define SET_XTENSA_PROP_ALIGNMENT(flag, align) \
243*3d8817e4Smiod   (((flag) & (~XTENSA_PROP_ALIGNMENT_MASK)) | \
244*3d8817e4Smiod     (((align) << 12) & XTENSA_PROP_ALIGNMENT_MASK))
245*3d8817e4Smiod 
246*3d8817e4Smiod #define XTENSA_PROP_INSN_ABSLIT 0x00020000
247*3d8817e4Smiod 
248*3d8817e4Smiod 
249*3d8817e4Smiod /* Structure for saving instruction and alignment per-fragment data
250*3d8817e4Smiod    that will be written to the object file.  This structure is
251*3d8817e4Smiod    equivalent to the actual data that will be written out to the file
252*3d8817e4Smiod    but is easier to use.   We provide a conversion to file flags
253*3d8817e4Smiod    in frag_flags_to_number.  */
254*3d8817e4Smiod 
255*3d8817e4Smiod typedef struct frag_flags_struct frag_flags;
256*3d8817e4Smiod 
257*3d8817e4Smiod struct frag_flags_struct
258*3d8817e4Smiod {
259*3d8817e4Smiod   /* is_literal should only be used after xtensa_move_literals.
260*3d8817e4Smiod      If you need to check if you are generating a literal fragment,
261*3d8817e4Smiod      then use the generating_literals global.  */
262*3d8817e4Smiod 
263*3d8817e4Smiod   unsigned is_literal : 1;
264*3d8817e4Smiod   unsigned is_insn : 1;
265*3d8817e4Smiod   unsigned is_data : 1;
266*3d8817e4Smiod   unsigned is_unreachable : 1;
267*3d8817e4Smiod 
268*3d8817e4Smiod   struct
269*3d8817e4Smiod   {
270*3d8817e4Smiod     unsigned is_loop_target : 1;
271*3d8817e4Smiod     unsigned is_branch_target : 1; /* Branch targets have a priority.  */
272*3d8817e4Smiod     unsigned bt_align_priority : 2;
273*3d8817e4Smiod 
274*3d8817e4Smiod     unsigned is_no_density : 1;
275*3d8817e4Smiod     /* no_longcalls flag does not need to be placed in the object file.  */
276*3d8817e4Smiod     /* is_specific_opcode implies no_transform.  */
277*3d8817e4Smiod     unsigned is_no_transform : 1;
278*3d8817e4Smiod 
279*3d8817e4Smiod     unsigned is_no_reorder : 1;
280*3d8817e4Smiod 
281*3d8817e4Smiod     /* Uses absolute literal addressing for l32r.  */
282*3d8817e4Smiod     unsigned is_abslit : 1;
283*3d8817e4Smiod   } insn;
284*3d8817e4Smiod   unsigned is_align : 1;
285*3d8817e4Smiod   unsigned alignment : 5;
286*3d8817e4Smiod };
287*3d8817e4Smiod 
288*3d8817e4Smiod 
289*3d8817e4Smiod /* Structure for saving information about a block of property data
290*3d8817e4Smiod    for frags that have the same flags.  */
291*3d8817e4Smiod struct xtensa_block_info_struct
292*3d8817e4Smiod {
293*3d8817e4Smiod   segT sec;
294*3d8817e4Smiod   bfd_vma offset;
295*3d8817e4Smiod   size_t size;
296*3d8817e4Smiod   frag_flags flags;
297*3d8817e4Smiod   struct xtensa_block_info_struct *next;
298*3d8817e4Smiod };
299*3d8817e4Smiod 
300*3d8817e4Smiod 
301*3d8817e4Smiod /* Structure for saving the current state before emitting literals.  */
302*3d8817e4Smiod typedef struct emit_state_struct
303*3d8817e4Smiod {
304*3d8817e4Smiod   const char *name;
305*3d8817e4Smiod   segT now_seg;
306*3d8817e4Smiod   subsegT now_subseg;
307*3d8817e4Smiod   int generating_literals;
308*3d8817e4Smiod } emit_state;
309*3d8817e4Smiod 
310*3d8817e4Smiod 
311*3d8817e4Smiod /* Opcode placement information */
312*3d8817e4Smiod 
313*3d8817e4Smiod typedef unsigned long long bitfield;
314*3d8817e4Smiod #define bit_is_set(bit, bf)	((bf) & (0x01ll << (bit)))
315*3d8817e4Smiod #define set_bit(bit, bf)	((bf) |= (0x01ll << (bit)))
316*3d8817e4Smiod #define clear_bit(bit, bf)	((bf) &= ~(0x01ll << (bit)))
317*3d8817e4Smiod 
318*3d8817e4Smiod #define MAX_FORMATS 32
319*3d8817e4Smiod 
320*3d8817e4Smiod typedef struct op_placement_info_struct
321*3d8817e4Smiod {
322*3d8817e4Smiod   int num_formats;
323*3d8817e4Smiod   /* A number describing how restrictive the issue is for this
324*3d8817e4Smiod      opcode.  For example, an opcode that fits lots of different
325*3d8817e4Smiod      formats has a high freedom, as does an opcode that fits
326*3d8817e4Smiod      only one format but many slots in that format.  The most
327*3d8817e4Smiod      restrictive is the opcode that fits only one slot in one
328*3d8817e4Smiod      format.  */
329*3d8817e4Smiod   int issuef;
330*3d8817e4Smiod   xtensa_format narrowest;
331*3d8817e4Smiod   char narrowest_size;
332*3d8817e4Smiod   char narrowest_slot;
333*3d8817e4Smiod 
334*3d8817e4Smiod   /* formats is a bitfield with the Nth bit set
335*3d8817e4Smiod      if the opcode fits in the Nth xtensa_format.  */
336*3d8817e4Smiod   bitfield formats;
337*3d8817e4Smiod 
338*3d8817e4Smiod   /* slots[N]'s Mth bit is set if the op fits in the
339*3d8817e4Smiod      Mth slot of the Nth xtensa_format.  */
340*3d8817e4Smiod   bitfield slots[MAX_FORMATS];
341*3d8817e4Smiod 
342*3d8817e4Smiod   /* A count of the number of slots in a given format
343*3d8817e4Smiod      an op can fit (i.e., the bitcount of the slot field above).  */
344*3d8817e4Smiod   char slots_in_format[MAX_FORMATS];
345*3d8817e4Smiod 
346*3d8817e4Smiod } op_placement_info, *op_placement_info_table;
347*3d8817e4Smiod 
348*3d8817e4Smiod op_placement_info_table op_placement_table;
349*3d8817e4Smiod 
350*3d8817e4Smiod 
351*3d8817e4Smiod /* Extra expression types.  */
352*3d8817e4Smiod 
353*3d8817e4Smiod #define O_pltrel	O_md1	/* like O_symbol but use a PLT reloc */
354*3d8817e4Smiod #define O_hi16		O_md2	/* use high 16 bits of symbolic value */
355*3d8817e4Smiod #define O_lo16		O_md3	/* use low 16 bits of symbolic value */
356*3d8817e4Smiod 
357*3d8817e4Smiod 
358*3d8817e4Smiod /* Directives.  */
359*3d8817e4Smiod 
360*3d8817e4Smiod typedef enum
361*3d8817e4Smiod {
362*3d8817e4Smiod   directive_none = 0,
363*3d8817e4Smiod   directive_literal,
364*3d8817e4Smiod   directive_density,
365*3d8817e4Smiod   directive_transform,
366*3d8817e4Smiod   directive_freeregs,
367*3d8817e4Smiod   directive_longcalls,
368*3d8817e4Smiod   directive_literal_prefix,
369*3d8817e4Smiod   directive_schedule,
370*3d8817e4Smiod   directive_absolute_literals,
371*3d8817e4Smiod   directive_last_directive
372*3d8817e4Smiod } directiveE;
373*3d8817e4Smiod 
374*3d8817e4Smiod typedef struct
375*3d8817e4Smiod {
376*3d8817e4Smiod   const char *name;
377*3d8817e4Smiod   bfd_boolean can_be_negated;
378*3d8817e4Smiod } directive_infoS;
379*3d8817e4Smiod 
380*3d8817e4Smiod const directive_infoS directive_info[] =
381*3d8817e4Smiod {
382*3d8817e4Smiod   { "none",		FALSE },
383*3d8817e4Smiod   { "literal",		FALSE },
384*3d8817e4Smiod   { "density",		TRUE },
385*3d8817e4Smiod   { "transform",	TRUE },
386*3d8817e4Smiod   { "freeregs",		FALSE },
387*3d8817e4Smiod   { "longcalls",	TRUE },
388*3d8817e4Smiod   { "literal_prefix",	FALSE },
389*3d8817e4Smiod   { "schedule",		TRUE },
390*3d8817e4Smiod   { "absolute-literals", TRUE }
391*3d8817e4Smiod };
392*3d8817e4Smiod 
393*3d8817e4Smiod bfd_boolean directive_state[] =
394*3d8817e4Smiod {
395*3d8817e4Smiod   FALSE,			/* none */
396*3d8817e4Smiod   FALSE,			/* literal */
397*3d8817e4Smiod #if !XCHAL_HAVE_DENSITY
398*3d8817e4Smiod   FALSE,			/* density */
399*3d8817e4Smiod #else
400*3d8817e4Smiod   TRUE,				/* density */
401*3d8817e4Smiod #endif
402*3d8817e4Smiod   TRUE,				/* transform */
403*3d8817e4Smiod   FALSE,			/* freeregs */
404*3d8817e4Smiod   FALSE,			/* longcalls */
405*3d8817e4Smiod   FALSE,			/* literal_prefix */
406*3d8817e4Smiod   TRUE,				/* schedule */
407*3d8817e4Smiod #if XSHAL_USE_ABSOLUTE_LITERALS
408*3d8817e4Smiod   TRUE				/* absolute_literals */
409*3d8817e4Smiod #else
410*3d8817e4Smiod   FALSE				/* absolute_literals */
411*3d8817e4Smiod #endif
412*3d8817e4Smiod };
413*3d8817e4Smiod 
414*3d8817e4Smiod 
415*3d8817e4Smiod /* Directive functions.  */
416*3d8817e4Smiod 
417*3d8817e4Smiod static void xtensa_begin_directive (int);
418*3d8817e4Smiod static void xtensa_end_directive (int);
419*3d8817e4Smiod static void xtensa_literal_prefix (char const *, int);
420*3d8817e4Smiod static void xtensa_literal_position (int);
421*3d8817e4Smiod static void xtensa_literal_pseudo (int);
422*3d8817e4Smiod static void xtensa_frequency_pseudo (int);
423*3d8817e4Smiod static void xtensa_elf_cons (int);
424*3d8817e4Smiod 
425*3d8817e4Smiod /* Parsing and Idiom Translation.  */
426*3d8817e4Smiod 
427*3d8817e4Smiod static bfd_reloc_code_real_type xtensa_elf_suffix (char **, expressionS *);
428*3d8817e4Smiod 
429*3d8817e4Smiod /* Various Other Internal Functions.  */
430*3d8817e4Smiod 
431*3d8817e4Smiod extern bfd_boolean xg_is_single_relaxable_insn (TInsn *, TInsn *, bfd_boolean);
432*3d8817e4Smiod static bfd_boolean xg_build_to_insn (TInsn *, TInsn *, BuildInstr *);
433*3d8817e4Smiod static void xtensa_mark_literal_pool_location (void);
434*3d8817e4Smiod static addressT get_expanded_loop_offset (xtensa_opcode);
435*3d8817e4Smiod static fragS *get_literal_pool_location (segT);
436*3d8817e4Smiod static void set_literal_pool_location (segT, fragS *);
437*3d8817e4Smiod static void xtensa_set_frag_assembly_state (fragS *);
438*3d8817e4Smiod static void finish_vinsn (vliw_insn *);
439*3d8817e4Smiod static bfd_boolean emit_single_op (TInsn *);
440*3d8817e4Smiod static int total_frag_text_expansion (fragS *);
441*3d8817e4Smiod 
442*3d8817e4Smiod /* Alignment Functions.  */
443*3d8817e4Smiod 
444*3d8817e4Smiod static int get_text_align_power (unsigned);
445*3d8817e4Smiod static int get_text_align_max_fill_size (int, bfd_boolean, bfd_boolean);
446*3d8817e4Smiod static int branch_align_power (segT);
447*3d8817e4Smiod 
448*3d8817e4Smiod /* Helpers for xtensa_relax_frag().  */
449*3d8817e4Smiod 
450*3d8817e4Smiod static long relax_frag_add_nop (fragS *);
451*3d8817e4Smiod 
452*3d8817e4Smiod /* Accessors for additional per-subsegment information.  */
453*3d8817e4Smiod 
454*3d8817e4Smiod static unsigned get_last_insn_flags (segT, subsegT);
455*3d8817e4Smiod static void set_last_insn_flags (segT, subsegT, unsigned, bfd_boolean);
456*3d8817e4Smiod static float get_subseg_total_freq (segT, subsegT);
457*3d8817e4Smiod static float get_subseg_target_freq (segT, subsegT);
458*3d8817e4Smiod static void set_subseg_freq (segT, subsegT, float, float);
459*3d8817e4Smiod 
460*3d8817e4Smiod /* Segment list functions.  */
461*3d8817e4Smiod 
462*3d8817e4Smiod static void xtensa_move_literals (void);
463*3d8817e4Smiod static void xtensa_reorder_segments (void);
464*3d8817e4Smiod static void xtensa_switch_to_literal_fragment (emit_state *);
465*3d8817e4Smiod static void xtensa_switch_to_non_abs_literal_fragment (emit_state *);
466*3d8817e4Smiod static void xtensa_switch_section_emit_state (emit_state *, segT, subsegT);
467*3d8817e4Smiod static void xtensa_restore_emit_state (emit_state *);
468*3d8817e4Smiod static void cache_literal_section
469*3d8817e4Smiod   (seg_list *, const char *, segT *, bfd_boolean);
470*3d8817e4Smiod 
471*3d8817e4Smiod /* Import from elf32-xtensa.c in BFD library.  */
472*3d8817e4Smiod 
473*3d8817e4Smiod extern char *xtensa_get_property_section_name (asection *, const char *);
474*3d8817e4Smiod 
475*3d8817e4Smiod /* op_placement_info functions.  */
476*3d8817e4Smiod 
477*3d8817e4Smiod static void init_op_placement_info_table (void);
478*3d8817e4Smiod extern bfd_boolean opcode_fits_format_slot (xtensa_opcode, xtensa_format, int);
479*3d8817e4Smiod static int xg_get_single_size (xtensa_opcode);
480*3d8817e4Smiod static xtensa_format xg_get_single_format (xtensa_opcode);
481*3d8817e4Smiod static int xg_get_single_slot (xtensa_opcode);
482*3d8817e4Smiod 
483*3d8817e4Smiod /* TInsn and IStack functions.  */
484*3d8817e4Smiod 
485*3d8817e4Smiod static bfd_boolean tinsn_has_symbolic_operands (const TInsn *);
486*3d8817e4Smiod static bfd_boolean tinsn_has_invalid_symbolic_operands (const TInsn *);
487*3d8817e4Smiod static bfd_boolean tinsn_has_complex_operands (const TInsn *);
488*3d8817e4Smiod static bfd_boolean tinsn_to_insnbuf (TInsn *, xtensa_insnbuf);
489*3d8817e4Smiod static bfd_boolean tinsn_check_arguments (const TInsn *);
490*3d8817e4Smiod static void tinsn_from_chars (TInsn *, char *, int);
491*3d8817e4Smiod static void tinsn_immed_from_frag (TInsn *, fragS *, int);
492*3d8817e4Smiod static int get_num_stack_text_bytes (IStack *);
493*3d8817e4Smiod static int get_num_stack_literal_bytes (IStack *);
494*3d8817e4Smiod 
495*3d8817e4Smiod /* vliw_insn functions.  */
496*3d8817e4Smiod 
497*3d8817e4Smiod static void xg_init_vinsn (vliw_insn *);
498*3d8817e4Smiod static void xg_clear_vinsn (vliw_insn *);
499*3d8817e4Smiod static bfd_boolean vinsn_has_specific_opcodes (vliw_insn *);
500*3d8817e4Smiod static void xg_free_vinsn (vliw_insn *);
501*3d8817e4Smiod static bfd_boolean vinsn_to_insnbuf
502*3d8817e4Smiod   (vliw_insn *, char *, fragS *, bfd_boolean);
503*3d8817e4Smiod static void vinsn_from_chars (vliw_insn *, char *);
504*3d8817e4Smiod 
505*3d8817e4Smiod /* Expression Utilities.  */
506*3d8817e4Smiod 
507*3d8817e4Smiod bfd_boolean expr_is_const (const expressionS *);
508*3d8817e4Smiod offsetT get_expr_const (const expressionS *);
509*3d8817e4Smiod void set_expr_const (expressionS *, offsetT);
510*3d8817e4Smiod bfd_boolean expr_is_register (const expressionS *);
511*3d8817e4Smiod offsetT get_expr_register (const expressionS *);
512*3d8817e4Smiod void set_expr_symbol_offset (expressionS *, symbolS *, offsetT);
513*3d8817e4Smiod bfd_boolean expr_is_equal (expressionS *, expressionS *);
514*3d8817e4Smiod static void copy_expr (expressionS *, const expressionS *);
515*3d8817e4Smiod 
516*3d8817e4Smiod /* Section renaming.  */
517*3d8817e4Smiod 
518*3d8817e4Smiod static void build_section_rename (const char *);
519*3d8817e4Smiod 
520*3d8817e4Smiod 
521*3d8817e4Smiod /* ISA imported from bfd.  */
522*3d8817e4Smiod extern xtensa_isa xtensa_default_isa;
523*3d8817e4Smiod 
524*3d8817e4Smiod extern int target_big_endian;
525*3d8817e4Smiod 
526*3d8817e4Smiod static xtensa_opcode xtensa_addi_opcode;
527*3d8817e4Smiod static xtensa_opcode xtensa_addmi_opcode;
528*3d8817e4Smiod static xtensa_opcode xtensa_call0_opcode;
529*3d8817e4Smiod static xtensa_opcode xtensa_call4_opcode;
530*3d8817e4Smiod static xtensa_opcode xtensa_call8_opcode;
531*3d8817e4Smiod static xtensa_opcode xtensa_call12_opcode;
532*3d8817e4Smiod static xtensa_opcode xtensa_callx0_opcode;
533*3d8817e4Smiod static xtensa_opcode xtensa_callx4_opcode;
534*3d8817e4Smiod static xtensa_opcode xtensa_callx8_opcode;
535*3d8817e4Smiod static xtensa_opcode xtensa_callx12_opcode;
536*3d8817e4Smiod static xtensa_opcode xtensa_const16_opcode;
537*3d8817e4Smiod static xtensa_opcode xtensa_entry_opcode;
538*3d8817e4Smiod static xtensa_opcode xtensa_movi_opcode;
539*3d8817e4Smiod static xtensa_opcode xtensa_movi_n_opcode;
540*3d8817e4Smiod static xtensa_opcode xtensa_isync_opcode;
541*3d8817e4Smiod static xtensa_opcode xtensa_jx_opcode;
542*3d8817e4Smiod static xtensa_opcode xtensa_l32r_opcode;
543*3d8817e4Smiod static xtensa_opcode xtensa_loop_opcode;
544*3d8817e4Smiod static xtensa_opcode xtensa_loopnez_opcode;
545*3d8817e4Smiod static xtensa_opcode xtensa_loopgtz_opcode;
546*3d8817e4Smiod static xtensa_opcode xtensa_nop_opcode;
547*3d8817e4Smiod static xtensa_opcode xtensa_nop_n_opcode;
548*3d8817e4Smiod static xtensa_opcode xtensa_or_opcode;
549*3d8817e4Smiod static xtensa_opcode xtensa_ret_opcode;
550*3d8817e4Smiod static xtensa_opcode xtensa_ret_n_opcode;
551*3d8817e4Smiod static xtensa_opcode xtensa_retw_opcode;
552*3d8817e4Smiod static xtensa_opcode xtensa_retw_n_opcode;
553*3d8817e4Smiod static xtensa_opcode xtensa_rsr_lcount_opcode;
554*3d8817e4Smiod static xtensa_opcode xtensa_waiti_opcode;
555*3d8817e4Smiod 
556*3d8817e4Smiod 
557*3d8817e4Smiod /* Command-line Options.  */
558*3d8817e4Smiod 
559*3d8817e4Smiod bfd_boolean use_literal_section = TRUE;
560*3d8817e4Smiod static bfd_boolean align_targets = TRUE;
561*3d8817e4Smiod static bfd_boolean warn_unaligned_branch_targets = FALSE;
562*3d8817e4Smiod static bfd_boolean has_a0_b_retw = FALSE;
563*3d8817e4Smiod static bfd_boolean workaround_a0_b_retw = FALSE;
564*3d8817e4Smiod static bfd_boolean workaround_b_j_loop_end = FALSE;
565*3d8817e4Smiod static bfd_boolean workaround_short_loop = FALSE;
566*3d8817e4Smiod static bfd_boolean maybe_has_short_loop = FALSE;
567*3d8817e4Smiod static bfd_boolean workaround_close_loop_end = FALSE;
568*3d8817e4Smiod static bfd_boolean maybe_has_close_loop_end = FALSE;
569*3d8817e4Smiod static bfd_boolean enforce_three_byte_loop_align = FALSE;
570*3d8817e4Smiod 
571*3d8817e4Smiod /* When workaround_short_loops is TRUE, all loops with early exits must
572*3d8817e4Smiod    have at least 3 instructions.  workaround_all_short_loops is a modifier
573*3d8817e4Smiod    to the workaround_short_loop flag.  In addition to the
574*3d8817e4Smiod    workaround_short_loop actions, all straightline loopgtz and loopnez
575*3d8817e4Smiod    must have at least 3 instructions.  */
576*3d8817e4Smiod 
577*3d8817e4Smiod static bfd_boolean workaround_all_short_loops = FALSE;
578*3d8817e4Smiod 
579*3d8817e4Smiod 
580*3d8817e4Smiod static void
xtensa_setup_hw_workarounds(int earliest,int latest)581*3d8817e4Smiod xtensa_setup_hw_workarounds (int earliest, int latest)
582*3d8817e4Smiod {
583*3d8817e4Smiod   if (earliest > latest)
584*3d8817e4Smiod     as_fatal (_("illegal range of target hardware versions"));
585*3d8817e4Smiod 
586*3d8817e4Smiod   /* Enable all workarounds for pre-T1050.0 hardware.  */
587*3d8817e4Smiod   if (earliest < 105000 || latest < 105000)
588*3d8817e4Smiod     {
589*3d8817e4Smiod       workaround_a0_b_retw |= TRUE;
590*3d8817e4Smiod       workaround_b_j_loop_end |= TRUE;
591*3d8817e4Smiod       workaround_short_loop |= TRUE;
592*3d8817e4Smiod       workaround_close_loop_end |= TRUE;
593*3d8817e4Smiod       workaround_all_short_loops |= TRUE;
594*3d8817e4Smiod       enforce_three_byte_loop_align = TRUE;
595*3d8817e4Smiod     }
596*3d8817e4Smiod }
597*3d8817e4Smiod 
598*3d8817e4Smiod 
599*3d8817e4Smiod enum
600*3d8817e4Smiod {
601*3d8817e4Smiod   option_density = OPTION_MD_BASE,
602*3d8817e4Smiod   option_no_density,
603*3d8817e4Smiod 
604*3d8817e4Smiod   option_relax,
605*3d8817e4Smiod   option_no_relax,
606*3d8817e4Smiod 
607*3d8817e4Smiod   option_link_relax,
608*3d8817e4Smiod   option_no_link_relax,
609*3d8817e4Smiod 
610*3d8817e4Smiod   option_generics,
611*3d8817e4Smiod   option_no_generics,
612*3d8817e4Smiod 
613*3d8817e4Smiod   option_transform,
614*3d8817e4Smiod   option_no_transform,
615*3d8817e4Smiod 
616*3d8817e4Smiod   option_text_section_literals,
617*3d8817e4Smiod   option_no_text_section_literals,
618*3d8817e4Smiod 
619*3d8817e4Smiod   option_absolute_literals,
620*3d8817e4Smiod   option_no_absolute_literals,
621*3d8817e4Smiod 
622*3d8817e4Smiod   option_align_targets,
623*3d8817e4Smiod   option_no_align_targets,
624*3d8817e4Smiod 
625*3d8817e4Smiod   option_warn_unaligned_targets,
626*3d8817e4Smiod 
627*3d8817e4Smiod   option_longcalls,
628*3d8817e4Smiod   option_no_longcalls,
629*3d8817e4Smiod 
630*3d8817e4Smiod   option_workaround_a0_b_retw,
631*3d8817e4Smiod   option_no_workaround_a0_b_retw,
632*3d8817e4Smiod 
633*3d8817e4Smiod   option_workaround_b_j_loop_end,
634*3d8817e4Smiod   option_no_workaround_b_j_loop_end,
635*3d8817e4Smiod 
636*3d8817e4Smiod   option_workaround_short_loop,
637*3d8817e4Smiod   option_no_workaround_short_loop,
638*3d8817e4Smiod 
639*3d8817e4Smiod   option_workaround_all_short_loops,
640*3d8817e4Smiod   option_no_workaround_all_short_loops,
641*3d8817e4Smiod 
642*3d8817e4Smiod   option_workaround_close_loop_end,
643*3d8817e4Smiod   option_no_workaround_close_loop_end,
644*3d8817e4Smiod 
645*3d8817e4Smiod   option_no_workarounds,
646*3d8817e4Smiod 
647*3d8817e4Smiod   option_rename_section_name,
648*3d8817e4Smiod 
649*3d8817e4Smiod   option_prefer_l32r,
650*3d8817e4Smiod   option_prefer_const16,
651*3d8817e4Smiod 
652*3d8817e4Smiod   option_target_hardware
653*3d8817e4Smiod };
654*3d8817e4Smiod 
655*3d8817e4Smiod const char *md_shortopts = "";
656*3d8817e4Smiod 
657*3d8817e4Smiod struct option md_longopts[] =
658*3d8817e4Smiod {
659*3d8817e4Smiod   { "density", no_argument, NULL, option_density },
660*3d8817e4Smiod   { "no-density", no_argument, NULL, option_no_density },
661*3d8817e4Smiod 
662*3d8817e4Smiod   /* Both "relax" and "generics" are deprecated and treated as equivalent
663*3d8817e4Smiod      to the "transform" option.  */
664*3d8817e4Smiod   { "relax", no_argument, NULL, option_relax },
665*3d8817e4Smiod   { "no-relax", no_argument, NULL, option_no_relax },
666*3d8817e4Smiod   { "generics", no_argument, NULL, option_generics },
667*3d8817e4Smiod   { "no-generics", no_argument, NULL, option_no_generics },
668*3d8817e4Smiod 
669*3d8817e4Smiod   { "transform", no_argument, NULL, option_transform },
670*3d8817e4Smiod   { "no-transform", no_argument, NULL, option_no_transform },
671*3d8817e4Smiod   { "text-section-literals", no_argument, NULL, option_text_section_literals },
672*3d8817e4Smiod   { "no-text-section-literals", no_argument, NULL,
673*3d8817e4Smiod     option_no_text_section_literals },
674*3d8817e4Smiod   { "absolute-literals", no_argument, NULL, option_absolute_literals },
675*3d8817e4Smiod   { "no-absolute-literals", no_argument, NULL, option_no_absolute_literals },
676*3d8817e4Smiod   /* This option was changed from -align-target to -target-align
677*3d8817e4Smiod      because it conflicted with the "-al" option.  */
678*3d8817e4Smiod   { "target-align", no_argument, NULL, option_align_targets },
679*3d8817e4Smiod   { "no-target-align", no_argument, NULL, option_no_align_targets },
680*3d8817e4Smiod   { "warn-unaligned-targets", no_argument, NULL,
681*3d8817e4Smiod     option_warn_unaligned_targets },
682*3d8817e4Smiod   { "longcalls", no_argument, NULL, option_longcalls },
683*3d8817e4Smiod   { "no-longcalls", no_argument, NULL, option_no_longcalls },
684*3d8817e4Smiod 
685*3d8817e4Smiod   { "no-workaround-a0-b-retw", no_argument, NULL,
686*3d8817e4Smiod     option_no_workaround_a0_b_retw },
687*3d8817e4Smiod   { "workaround-a0-b-retw", no_argument, NULL, option_workaround_a0_b_retw },
688*3d8817e4Smiod 
689*3d8817e4Smiod   { "no-workaround-b-j-loop-end", no_argument, NULL,
690*3d8817e4Smiod     option_no_workaround_b_j_loop_end },
691*3d8817e4Smiod   { "workaround-b-j-loop-end", no_argument, NULL,
692*3d8817e4Smiod     option_workaround_b_j_loop_end },
693*3d8817e4Smiod 
694*3d8817e4Smiod   { "no-workaround-short-loops", no_argument, NULL,
695*3d8817e4Smiod     option_no_workaround_short_loop },
696*3d8817e4Smiod   { "workaround-short-loops", no_argument, NULL,
697*3d8817e4Smiod     option_workaround_short_loop },
698*3d8817e4Smiod 
699*3d8817e4Smiod   { "no-workaround-all-short-loops", no_argument, NULL,
700*3d8817e4Smiod     option_no_workaround_all_short_loops },
701*3d8817e4Smiod   { "workaround-all-short-loop", no_argument, NULL,
702*3d8817e4Smiod     option_workaround_all_short_loops },
703*3d8817e4Smiod 
704*3d8817e4Smiod   { "prefer-l32r", no_argument, NULL, option_prefer_l32r },
705*3d8817e4Smiod   { "prefer-const16", no_argument, NULL, option_prefer_const16 },
706*3d8817e4Smiod 
707*3d8817e4Smiod   { "no-workarounds", no_argument, NULL, option_no_workarounds },
708*3d8817e4Smiod 
709*3d8817e4Smiod   { "no-workaround-close-loop-end", no_argument, NULL,
710*3d8817e4Smiod     option_no_workaround_close_loop_end },
711*3d8817e4Smiod   { "workaround-close-loop-end", no_argument, NULL,
712*3d8817e4Smiod     option_workaround_close_loop_end },
713*3d8817e4Smiod 
714*3d8817e4Smiod   { "rename-section", required_argument, NULL, option_rename_section_name },
715*3d8817e4Smiod 
716*3d8817e4Smiod   { "link-relax", no_argument, NULL, option_link_relax },
717*3d8817e4Smiod   { "no-link-relax", no_argument, NULL, option_no_link_relax },
718*3d8817e4Smiod 
719*3d8817e4Smiod   { "target-hardware", required_argument, NULL, option_target_hardware },
720*3d8817e4Smiod 
721*3d8817e4Smiod   { NULL, no_argument, NULL, 0 }
722*3d8817e4Smiod };
723*3d8817e4Smiod 
724*3d8817e4Smiod size_t md_longopts_size = sizeof md_longopts;
725*3d8817e4Smiod 
726*3d8817e4Smiod 
727*3d8817e4Smiod int
md_parse_option(int c,char * arg)728*3d8817e4Smiod md_parse_option (int c, char *arg)
729*3d8817e4Smiod {
730*3d8817e4Smiod   switch (c)
731*3d8817e4Smiod     {
732*3d8817e4Smiod     case option_density:
733*3d8817e4Smiod       as_warn (_("--density option is ignored"));
734*3d8817e4Smiod       return 1;
735*3d8817e4Smiod     case option_no_density:
736*3d8817e4Smiod       as_warn (_("--no-density option is ignored"));
737*3d8817e4Smiod       return 1;
738*3d8817e4Smiod     case option_link_relax:
739*3d8817e4Smiod       linkrelax = 1;
740*3d8817e4Smiod       return 1;
741*3d8817e4Smiod     case option_no_link_relax:
742*3d8817e4Smiod       linkrelax = 0;
743*3d8817e4Smiod       return 1;
744*3d8817e4Smiod     case option_generics:
745*3d8817e4Smiod       as_warn (_("--generics is deprecated; use --transform instead"));
746*3d8817e4Smiod       return md_parse_option (option_transform, arg);
747*3d8817e4Smiod     case option_no_generics:
748*3d8817e4Smiod       as_warn (_("--no-generics is deprecated; use --no-transform instead"));
749*3d8817e4Smiod       return md_parse_option (option_no_transform, arg);
750*3d8817e4Smiod     case option_relax:
751*3d8817e4Smiod       as_warn (_("--relax is deprecated; use --transform instead"));
752*3d8817e4Smiod       return md_parse_option (option_transform, arg);
753*3d8817e4Smiod     case option_no_relax:
754*3d8817e4Smiod       as_warn (_("--no-relax is deprecated; use --no-transform instead"));
755*3d8817e4Smiod       return md_parse_option (option_no_transform, arg);
756*3d8817e4Smiod     case option_longcalls:
757*3d8817e4Smiod       directive_state[directive_longcalls] = TRUE;
758*3d8817e4Smiod       return 1;
759*3d8817e4Smiod     case option_no_longcalls:
760*3d8817e4Smiod       directive_state[directive_longcalls] = FALSE;
761*3d8817e4Smiod       return 1;
762*3d8817e4Smiod     case option_text_section_literals:
763*3d8817e4Smiod       use_literal_section = FALSE;
764*3d8817e4Smiod       return 1;
765*3d8817e4Smiod     case option_no_text_section_literals:
766*3d8817e4Smiod       use_literal_section = TRUE;
767*3d8817e4Smiod       return 1;
768*3d8817e4Smiod     case option_absolute_literals:
769*3d8817e4Smiod       if (!absolute_literals_supported)
770*3d8817e4Smiod 	{
771*3d8817e4Smiod 	  as_fatal (_("--absolute-literals option not supported in this Xtensa configuration"));
772*3d8817e4Smiod 	  return 0;
773*3d8817e4Smiod 	}
774*3d8817e4Smiod       directive_state[directive_absolute_literals] = TRUE;
775*3d8817e4Smiod       return 1;
776*3d8817e4Smiod     case option_no_absolute_literals:
777*3d8817e4Smiod       directive_state[directive_absolute_literals] = FALSE;
778*3d8817e4Smiod       return 1;
779*3d8817e4Smiod 
780*3d8817e4Smiod     case option_workaround_a0_b_retw:
781*3d8817e4Smiod       workaround_a0_b_retw = TRUE;
782*3d8817e4Smiod       return 1;
783*3d8817e4Smiod     case option_no_workaround_a0_b_retw:
784*3d8817e4Smiod       workaround_a0_b_retw = FALSE;
785*3d8817e4Smiod       return 1;
786*3d8817e4Smiod     case option_workaround_b_j_loop_end:
787*3d8817e4Smiod       workaround_b_j_loop_end = TRUE;
788*3d8817e4Smiod       return 1;
789*3d8817e4Smiod     case option_no_workaround_b_j_loop_end:
790*3d8817e4Smiod       workaround_b_j_loop_end = FALSE;
791*3d8817e4Smiod       return 1;
792*3d8817e4Smiod 
793*3d8817e4Smiod     case option_workaround_short_loop:
794*3d8817e4Smiod       workaround_short_loop = TRUE;
795*3d8817e4Smiod       return 1;
796*3d8817e4Smiod     case option_no_workaround_short_loop:
797*3d8817e4Smiod       workaround_short_loop = FALSE;
798*3d8817e4Smiod       return 1;
799*3d8817e4Smiod 
800*3d8817e4Smiod     case option_workaround_all_short_loops:
801*3d8817e4Smiod       workaround_all_short_loops = TRUE;
802*3d8817e4Smiod       return 1;
803*3d8817e4Smiod     case option_no_workaround_all_short_loops:
804*3d8817e4Smiod       workaround_all_short_loops = FALSE;
805*3d8817e4Smiod       return 1;
806*3d8817e4Smiod 
807*3d8817e4Smiod     case option_workaround_close_loop_end:
808*3d8817e4Smiod       workaround_close_loop_end = TRUE;
809*3d8817e4Smiod       return 1;
810*3d8817e4Smiod     case option_no_workaround_close_loop_end:
811*3d8817e4Smiod       workaround_close_loop_end = FALSE;
812*3d8817e4Smiod       return 1;
813*3d8817e4Smiod 
814*3d8817e4Smiod     case option_no_workarounds:
815*3d8817e4Smiod       workaround_a0_b_retw = FALSE;
816*3d8817e4Smiod       workaround_b_j_loop_end = FALSE;
817*3d8817e4Smiod       workaround_short_loop = FALSE;
818*3d8817e4Smiod       workaround_all_short_loops = FALSE;
819*3d8817e4Smiod       workaround_close_loop_end = FALSE;
820*3d8817e4Smiod       return 1;
821*3d8817e4Smiod 
822*3d8817e4Smiod     case option_align_targets:
823*3d8817e4Smiod       align_targets = TRUE;
824*3d8817e4Smiod       return 1;
825*3d8817e4Smiod     case option_no_align_targets:
826*3d8817e4Smiod       align_targets = FALSE;
827*3d8817e4Smiod       return 1;
828*3d8817e4Smiod 
829*3d8817e4Smiod     case option_warn_unaligned_targets:
830*3d8817e4Smiod       warn_unaligned_branch_targets = TRUE;
831*3d8817e4Smiod       return 1;
832*3d8817e4Smiod 
833*3d8817e4Smiod     case option_rename_section_name:
834*3d8817e4Smiod       build_section_rename (arg);
835*3d8817e4Smiod       return 1;
836*3d8817e4Smiod 
837*3d8817e4Smiod     case 'Q':
838*3d8817e4Smiod       /* -Qy, -Qn: SVR4 arguments controlling whether a .comment section
839*3d8817e4Smiod          should be emitted or not.  FIXME: Not implemented.  */
840*3d8817e4Smiod       return 1;
841*3d8817e4Smiod 
842*3d8817e4Smiod     case option_prefer_l32r:
843*3d8817e4Smiod       if (prefer_const16)
844*3d8817e4Smiod 	as_fatal (_("prefer-l32r conflicts with prefer-const16"));
845*3d8817e4Smiod       prefer_l32r = 1;
846*3d8817e4Smiod       return 1;
847*3d8817e4Smiod 
848*3d8817e4Smiod     case option_prefer_const16:
849*3d8817e4Smiod       if (prefer_l32r)
850*3d8817e4Smiod 	as_fatal (_("prefer-const16 conflicts with prefer-l32r"));
851*3d8817e4Smiod       prefer_const16 = 1;
852*3d8817e4Smiod       return 1;
853*3d8817e4Smiod 
854*3d8817e4Smiod     case option_target_hardware:
855*3d8817e4Smiod       {
856*3d8817e4Smiod 	int earliest, latest = 0;
857*3d8817e4Smiod 	if (*arg == 0 || *arg == '-')
858*3d8817e4Smiod 	  as_fatal (_("invalid target hardware version"));
859*3d8817e4Smiod 
860*3d8817e4Smiod 	earliest = strtol (arg, &arg, 0);
861*3d8817e4Smiod 
862*3d8817e4Smiod 	if (*arg == 0)
863*3d8817e4Smiod 	  latest = earliest;
864*3d8817e4Smiod 	else if (*arg == '-')
865*3d8817e4Smiod 	  {
866*3d8817e4Smiod 	    if (*++arg == 0)
867*3d8817e4Smiod 	      as_fatal (_("invalid target hardware version"));
868*3d8817e4Smiod 	    latest = strtol (arg, &arg, 0);
869*3d8817e4Smiod 	  }
870*3d8817e4Smiod 	if (*arg != 0)
871*3d8817e4Smiod 	  as_fatal (_("invalid target hardware version"));
872*3d8817e4Smiod 
873*3d8817e4Smiod 	xtensa_setup_hw_workarounds (earliest, latest);
874*3d8817e4Smiod 	return 1;
875*3d8817e4Smiod       }
876*3d8817e4Smiod 
877*3d8817e4Smiod     case option_transform:
878*3d8817e4Smiod       /* This option has no affect other than to use the defaults,
879*3d8817e4Smiod 	 which are already set.  */
880*3d8817e4Smiod       return 1;
881*3d8817e4Smiod 
882*3d8817e4Smiod     case option_no_transform:
883*3d8817e4Smiod       /* This option turns off all transformations of any kind.
884*3d8817e4Smiod 	 However, because we want to preserve the state of other
885*3d8817e4Smiod 	 directives, we only change its own field.  Thus, before
886*3d8817e4Smiod 	 you perform any transformation, always check if transform
887*3d8817e4Smiod 	 is available.  If you use the functions we provide for this
888*3d8817e4Smiod 	 purpose, you will be ok.  */
889*3d8817e4Smiod       directive_state[directive_transform] = FALSE;
890*3d8817e4Smiod       return 1;
891*3d8817e4Smiod 
892*3d8817e4Smiod     default:
893*3d8817e4Smiod       return 0;
894*3d8817e4Smiod     }
895*3d8817e4Smiod }
896*3d8817e4Smiod 
897*3d8817e4Smiod 
898*3d8817e4Smiod void
md_show_usage(FILE * stream)899*3d8817e4Smiod md_show_usage (FILE *stream)
900*3d8817e4Smiod {
901*3d8817e4Smiod   fputs ("\n\
902*3d8817e4Smiod Xtensa options:\n\
903*3d8817e4Smiod   --[no-]text-section-literals\n\
904*3d8817e4Smiod                           [Do not] put literals in the text section\n\
905*3d8817e4Smiod   --[no-]absolute-literals\n\
906*3d8817e4Smiod                           [Do not] default to use non-PC-relative literals\n\
907*3d8817e4Smiod   --[no-]target-align     [Do not] try to align branch targets\n\
908*3d8817e4Smiod   --[no-]longcalls        [Do not] emit 32-bit call sequences\n\
909*3d8817e4Smiod   --[no-]transform        [Do not] transform instructions\n\
910*3d8817e4Smiod   --rename-section old=new Rename section 'old' to 'new'\n", stream);
911*3d8817e4Smiod }
912*3d8817e4Smiod 
913*3d8817e4Smiod 
914*3d8817e4Smiod /* Functions related to the list of current label symbols.  */
915*3d8817e4Smiod 
916*3d8817e4Smiod static void
xtensa_add_insn_label(symbolS * sym)917*3d8817e4Smiod xtensa_add_insn_label (symbolS *sym)
918*3d8817e4Smiod {
919*3d8817e4Smiod   sym_list *l;
920*3d8817e4Smiod 
921*3d8817e4Smiod   if (!free_insn_labels)
922*3d8817e4Smiod     l = (sym_list *) xmalloc (sizeof (sym_list));
923*3d8817e4Smiod   else
924*3d8817e4Smiod     {
925*3d8817e4Smiod       l = free_insn_labels;
926*3d8817e4Smiod       free_insn_labels = l->next;
927*3d8817e4Smiod     }
928*3d8817e4Smiod 
929*3d8817e4Smiod   l->sym = sym;
930*3d8817e4Smiod   l->next = insn_labels;
931*3d8817e4Smiod   insn_labels = l;
932*3d8817e4Smiod }
933*3d8817e4Smiod 
934*3d8817e4Smiod 
935*3d8817e4Smiod static void
xtensa_clear_insn_labels(void)936*3d8817e4Smiod xtensa_clear_insn_labels (void)
937*3d8817e4Smiod {
938*3d8817e4Smiod   sym_list **pl;
939*3d8817e4Smiod 
940*3d8817e4Smiod   for (pl = &free_insn_labels; *pl != NULL; pl = &(*pl)->next)
941*3d8817e4Smiod     ;
942*3d8817e4Smiod   *pl = insn_labels;
943*3d8817e4Smiod   insn_labels = NULL;
944*3d8817e4Smiod }
945*3d8817e4Smiod 
946*3d8817e4Smiod 
947*3d8817e4Smiod /* The "loops_ok" argument is provided to allow ignoring labels that
948*3d8817e4Smiod    define loop ends.  This fixes a bug where the NOPs to align a
949*3d8817e4Smiod    loop opcode were included in a previous zero-cost loop:
950*3d8817e4Smiod 
951*3d8817e4Smiod    loop a0, loopend
952*3d8817e4Smiod      <loop1 body>
953*3d8817e4Smiod    loopend:
954*3d8817e4Smiod 
955*3d8817e4Smiod    loop a2, loopend2
956*3d8817e4Smiod      <loop2 body>
957*3d8817e4Smiod 
958*3d8817e4Smiod    would become:
959*3d8817e4Smiod 
960*3d8817e4Smiod    loop a0, loopend
961*3d8817e4Smiod      <loop1 body>
962*3d8817e4Smiod      nop.n <===== bad!
963*3d8817e4Smiod    loopend:
964*3d8817e4Smiod 
965*3d8817e4Smiod    loop a2, loopend2
966*3d8817e4Smiod      <loop2 body>
967*3d8817e4Smiod 
968*3d8817e4Smiod    This argument is used to prevent moving the NOP to before the
969*3d8817e4Smiod    loop-end label, which is what you want in this special case.  */
970*3d8817e4Smiod 
971*3d8817e4Smiod static void
xtensa_move_labels(fragS * new_frag,valueT new_offset,bfd_boolean loops_ok)972*3d8817e4Smiod xtensa_move_labels (fragS *new_frag, valueT new_offset, bfd_boolean loops_ok)
973*3d8817e4Smiod {
974*3d8817e4Smiod   sym_list *lit;
975*3d8817e4Smiod 
976*3d8817e4Smiod   for (lit = insn_labels; lit; lit = lit->next)
977*3d8817e4Smiod     {
978*3d8817e4Smiod       symbolS *lit_sym = lit->sym;
979*3d8817e4Smiod       if (loops_ok || ! symbol_get_tc (lit_sym)->is_loop_target)
980*3d8817e4Smiod 	{
981*3d8817e4Smiod 	  S_SET_VALUE (lit_sym, new_offset);
982*3d8817e4Smiod 	  symbol_set_frag (lit_sym, new_frag);
983*3d8817e4Smiod 	}
984*3d8817e4Smiod     }
985*3d8817e4Smiod }
986*3d8817e4Smiod 
987*3d8817e4Smiod 
988*3d8817e4Smiod /* Directive data and functions.  */
989*3d8817e4Smiod 
990*3d8817e4Smiod typedef struct state_stackS_struct
991*3d8817e4Smiod {
992*3d8817e4Smiod   directiveE directive;
993*3d8817e4Smiod   bfd_boolean negated;
994*3d8817e4Smiod   bfd_boolean old_state;
995*3d8817e4Smiod   const char *file;
996*3d8817e4Smiod   unsigned int line;
997*3d8817e4Smiod   const void *datum;
998*3d8817e4Smiod   struct state_stackS_struct *prev;
999*3d8817e4Smiod } state_stackS;
1000*3d8817e4Smiod 
1001*3d8817e4Smiod state_stackS *directive_state_stack;
1002*3d8817e4Smiod 
1003*3d8817e4Smiod const pseudo_typeS md_pseudo_table[] =
1004*3d8817e4Smiod {
1005*3d8817e4Smiod   { "align", s_align_bytes, 0 }, /* Defaulting is invalid (0).  */
1006*3d8817e4Smiod   { "literal_position", xtensa_literal_position, 0 },
1007*3d8817e4Smiod   { "frame", s_ignore, 0 },	/* Formerly used for STABS debugging.  */
1008*3d8817e4Smiod   { "long", xtensa_elf_cons, 4 },
1009*3d8817e4Smiod   { "word", xtensa_elf_cons, 4 },
1010*3d8817e4Smiod   { "short", xtensa_elf_cons, 2 },
1011*3d8817e4Smiod   { "begin", xtensa_begin_directive, 0 },
1012*3d8817e4Smiod   { "end", xtensa_end_directive, 0 },
1013*3d8817e4Smiod   { "literal", xtensa_literal_pseudo, 0 },
1014*3d8817e4Smiod   { "frequency", xtensa_frequency_pseudo, 0 },
1015*3d8817e4Smiod   { NULL, 0, 0 },
1016*3d8817e4Smiod };
1017*3d8817e4Smiod 
1018*3d8817e4Smiod 
1019*3d8817e4Smiod static bfd_boolean
use_transform(void)1020*3d8817e4Smiod use_transform (void)
1021*3d8817e4Smiod {
1022*3d8817e4Smiod   /* After md_end, you should be checking frag by frag, rather
1023*3d8817e4Smiod      than state directives.  */
1024*3d8817e4Smiod   assert (!past_xtensa_end);
1025*3d8817e4Smiod   return directive_state[directive_transform];
1026*3d8817e4Smiod }
1027*3d8817e4Smiod 
1028*3d8817e4Smiod 
1029*3d8817e4Smiod static bfd_boolean
do_align_targets(void)1030*3d8817e4Smiod do_align_targets (void)
1031*3d8817e4Smiod {
1032*3d8817e4Smiod   /* Do not use this function after md_end; just look at align_targets
1033*3d8817e4Smiod      instead.  There is no target-align directive, so alignment is either
1034*3d8817e4Smiod      enabled for all frags or not done at all.  */
1035*3d8817e4Smiod   assert (!past_xtensa_end);
1036*3d8817e4Smiod   return align_targets && use_transform ();
1037*3d8817e4Smiod }
1038*3d8817e4Smiod 
1039*3d8817e4Smiod 
1040*3d8817e4Smiod static void
directive_push(directiveE directive,bfd_boolean negated,const void * datum)1041*3d8817e4Smiod directive_push (directiveE directive, bfd_boolean negated, const void *datum)
1042*3d8817e4Smiod {
1043*3d8817e4Smiod   char *file;
1044*3d8817e4Smiod   unsigned int line;
1045*3d8817e4Smiod   state_stackS *stack = (state_stackS *) xmalloc (sizeof (state_stackS));
1046*3d8817e4Smiod 
1047*3d8817e4Smiod   as_where (&file, &line);
1048*3d8817e4Smiod 
1049*3d8817e4Smiod   stack->directive = directive;
1050*3d8817e4Smiod   stack->negated = negated;
1051*3d8817e4Smiod   stack->old_state = directive_state[directive];
1052*3d8817e4Smiod   stack->file = file;
1053*3d8817e4Smiod   stack->line = line;
1054*3d8817e4Smiod   stack->datum = datum;
1055*3d8817e4Smiod   stack->prev = directive_state_stack;
1056*3d8817e4Smiod   directive_state_stack = stack;
1057*3d8817e4Smiod 
1058*3d8817e4Smiod   directive_state[directive] = !negated;
1059*3d8817e4Smiod }
1060*3d8817e4Smiod 
1061*3d8817e4Smiod 
1062*3d8817e4Smiod static void
directive_pop(directiveE * directive,bfd_boolean * negated,const char ** file,unsigned int * line,const void ** datum)1063*3d8817e4Smiod directive_pop (directiveE *directive,
1064*3d8817e4Smiod 	       bfd_boolean *negated,
1065*3d8817e4Smiod 	       const char **file,
1066*3d8817e4Smiod 	       unsigned int *line,
1067*3d8817e4Smiod 	       const void **datum)
1068*3d8817e4Smiod {
1069*3d8817e4Smiod   state_stackS *top = directive_state_stack;
1070*3d8817e4Smiod 
1071*3d8817e4Smiod   if (!directive_state_stack)
1072*3d8817e4Smiod     {
1073*3d8817e4Smiod       as_bad (_("unmatched end directive"));
1074*3d8817e4Smiod       *directive = directive_none;
1075*3d8817e4Smiod       return;
1076*3d8817e4Smiod     }
1077*3d8817e4Smiod 
1078*3d8817e4Smiod   directive_state[directive_state_stack->directive] = top->old_state;
1079*3d8817e4Smiod   *directive = top->directive;
1080*3d8817e4Smiod   *negated = top->negated;
1081*3d8817e4Smiod   *file = top->file;
1082*3d8817e4Smiod   *line = top->line;
1083*3d8817e4Smiod   *datum = top->datum;
1084*3d8817e4Smiod   directive_state_stack = top->prev;
1085*3d8817e4Smiod   free (top);
1086*3d8817e4Smiod }
1087*3d8817e4Smiod 
1088*3d8817e4Smiod 
1089*3d8817e4Smiod static void
directive_balance(void)1090*3d8817e4Smiod directive_balance (void)
1091*3d8817e4Smiod {
1092*3d8817e4Smiod   while (directive_state_stack)
1093*3d8817e4Smiod     {
1094*3d8817e4Smiod       directiveE directive;
1095*3d8817e4Smiod       bfd_boolean negated;
1096*3d8817e4Smiod       const char *file;
1097*3d8817e4Smiod       unsigned int line;
1098*3d8817e4Smiod       const void *datum;
1099*3d8817e4Smiod 
1100*3d8817e4Smiod       directive_pop (&directive, &negated, &file, &line, &datum);
1101*3d8817e4Smiod       as_warn_where ((char *) file, line,
1102*3d8817e4Smiod 		     _(".begin directive with no matching .end directive"));
1103*3d8817e4Smiod     }
1104*3d8817e4Smiod }
1105*3d8817e4Smiod 
1106*3d8817e4Smiod 
1107*3d8817e4Smiod static bfd_boolean
inside_directive(directiveE dir)1108*3d8817e4Smiod inside_directive (directiveE dir)
1109*3d8817e4Smiod {
1110*3d8817e4Smiod   state_stackS *top = directive_state_stack;
1111*3d8817e4Smiod 
1112*3d8817e4Smiod   while (top && top->directive != dir)
1113*3d8817e4Smiod     top = top->prev;
1114*3d8817e4Smiod 
1115*3d8817e4Smiod   return (top != NULL);
1116*3d8817e4Smiod }
1117*3d8817e4Smiod 
1118*3d8817e4Smiod 
1119*3d8817e4Smiod static void
get_directive(directiveE * directive,bfd_boolean * negated)1120*3d8817e4Smiod get_directive (directiveE *directive, bfd_boolean *negated)
1121*3d8817e4Smiod {
1122*3d8817e4Smiod   int len;
1123*3d8817e4Smiod   unsigned i;
1124*3d8817e4Smiod   char *directive_string;
1125*3d8817e4Smiod 
1126*3d8817e4Smiod   if (strncmp (input_line_pointer, "no-", 3) != 0)
1127*3d8817e4Smiod     *negated = FALSE;
1128*3d8817e4Smiod   else
1129*3d8817e4Smiod     {
1130*3d8817e4Smiod       *negated = TRUE;
1131*3d8817e4Smiod       input_line_pointer += 3;
1132*3d8817e4Smiod     }
1133*3d8817e4Smiod 
1134*3d8817e4Smiod   len = strspn (input_line_pointer,
1135*3d8817e4Smiod 		"abcdefghijklmnopqrstuvwxyz_-/0123456789.");
1136*3d8817e4Smiod 
1137*3d8817e4Smiod   /* This code is a hack to make .begin [no-][generics|relax] exactly
1138*3d8817e4Smiod      equivalent to .begin [no-]transform.  We should remove it when
1139*3d8817e4Smiod      we stop accepting those options.  */
1140*3d8817e4Smiod 
1141*3d8817e4Smiod   if (strncmp (input_line_pointer, "generics", strlen ("generics")) == 0)
1142*3d8817e4Smiod     {
1143*3d8817e4Smiod       as_warn (_("[no-]generics is deprecated; use [no-]transform instead"));
1144*3d8817e4Smiod       directive_string = "transform";
1145*3d8817e4Smiod     }
1146*3d8817e4Smiod   else if (strncmp (input_line_pointer, "relax", strlen ("relax")) == 0)
1147*3d8817e4Smiod     {
1148*3d8817e4Smiod       as_warn (_("[no-]relax is deprecated; use [no-]transform instead"));
1149*3d8817e4Smiod       directive_string = "transform";
1150*3d8817e4Smiod     }
1151*3d8817e4Smiod   else
1152*3d8817e4Smiod     directive_string = input_line_pointer;
1153*3d8817e4Smiod 
1154*3d8817e4Smiod   for (i = 0; i < sizeof (directive_info) / sizeof (*directive_info); ++i)
1155*3d8817e4Smiod     {
1156*3d8817e4Smiod       if (strncmp (directive_string, directive_info[i].name, len) == 0)
1157*3d8817e4Smiod 	{
1158*3d8817e4Smiod 	  input_line_pointer += len;
1159*3d8817e4Smiod 	  *directive = (directiveE) i;
1160*3d8817e4Smiod 	  if (*negated && !directive_info[i].can_be_negated)
1161*3d8817e4Smiod 	    as_bad (_("directive %s cannot be negated"),
1162*3d8817e4Smiod 		    directive_info[i].name);
1163*3d8817e4Smiod 	  return;
1164*3d8817e4Smiod 	}
1165*3d8817e4Smiod     }
1166*3d8817e4Smiod 
1167*3d8817e4Smiod   as_bad (_("unknown directive"));
1168*3d8817e4Smiod   *directive = (directiveE) XTENSA_UNDEFINED;
1169*3d8817e4Smiod }
1170*3d8817e4Smiod 
1171*3d8817e4Smiod 
1172*3d8817e4Smiod static void
xtensa_begin_directive(int ignore ATTRIBUTE_UNUSED)1173*3d8817e4Smiod xtensa_begin_directive (int ignore ATTRIBUTE_UNUSED)
1174*3d8817e4Smiod {
1175*3d8817e4Smiod   directiveE directive;
1176*3d8817e4Smiod   bfd_boolean negated;
1177*3d8817e4Smiod   emit_state *state;
1178*3d8817e4Smiod   int len;
1179*3d8817e4Smiod   lit_state *ls;
1180*3d8817e4Smiod 
1181*3d8817e4Smiod   get_directive (&directive, &negated);
1182*3d8817e4Smiod   if (directive == (directiveE) XTENSA_UNDEFINED)
1183*3d8817e4Smiod     {
1184*3d8817e4Smiod       discard_rest_of_line ();
1185*3d8817e4Smiod       return;
1186*3d8817e4Smiod     }
1187*3d8817e4Smiod 
1188*3d8817e4Smiod   if (cur_vinsn.inside_bundle)
1189*3d8817e4Smiod     as_bad (_("directives are not valid inside bundles"));
1190*3d8817e4Smiod 
1191*3d8817e4Smiod   switch (directive)
1192*3d8817e4Smiod     {
1193*3d8817e4Smiod     case directive_literal:
1194*3d8817e4Smiod       if (!inside_directive (directive_literal))
1195*3d8817e4Smiod 	{
1196*3d8817e4Smiod 	  /* Previous labels go with whatever follows this directive, not with
1197*3d8817e4Smiod 	     the literal, so save them now.  */
1198*3d8817e4Smiod 	  saved_insn_labels = insn_labels;
1199*3d8817e4Smiod 	  insn_labels = NULL;
1200*3d8817e4Smiod 	}
1201*3d8817e4Smiod       as_warn (_(".begin literal is deprecated; use .literal instead"));
1202*3d8817e4Smiod       state = (emit_state *) xmalloc (sizeof (emit_state));
1203*3d8817e4Smiod       xtensa_switch_to_literal_fragment (state);
1204*3d8817e4Smiod       directive_push (directive_literal, negated, state);
1205*3d8817e4Smiod       break;
1206*3d8817e4Smiod 
1207*3d8817e4Smiod     case directive_literal_prefix:
1208*3d8817e4Smiod       /* Have to flush pending output because a movi relaxed to an l32r
1209*3d8817e4Smiod 	 might produce a literal.  */
1210*3d8817e4Smiod       md_flush_pending_output ();
1211*3d8817e4Smiod       /* Check to see if the current fragment is a literal
1212*3d8817e4Smiod 	 fragment.  If it is, then this operation is not allowed.  */
1213*3d8817e4Smiod       if (generating_literals)
1214*3d8817e4Smiod 	{
1215*3d8817e4Smiod 	  as_bad (_("cannot set literal_prefix inside literal fragment"));
1216*3d8817e4Smiod 	  return;
1217*3d8817e4Smiod 	}
1218*3d8817e4Smiod 
1219*3d8817e4Smiod       /* Allocate the literal state for this section and push
1220*3d8817e4Smiod 	 onto the directive stack.  */
1221*3d8817e4Smiod       ls = xmalloc (sizeof (lit_state));
1222*3d8817e4Smiod       assert (ls);
1223*3d8817e4Smiod 
1224*3d8817e4Smiod       *ls = default_lit_sections;
1225*3d8817e4Smiod 
1226*3d8817e4Smiod       directive_push (directive_literal_prefix, negated, ls);
1227*3d8817e4Smiod 
1228*3d8817e4Smiod       /* Parse the new prefix from the input_line_pointer.  */
1229*3d8817e4Smiod       SKIP_WHITESPACE ();
1230*3d8817e4Smiod       len = strspn (input_line_pointer,
1231*3d8817e4Smiod 		    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1232*3d8817e4Smiod 		    "abcdefghijklmnopqrstuvwxyz_/0123456789.$");
1233*3d8817e4Smiod 
1234*3d8817e4Smiod       /* Process the new prefix.  */
1235*3d8817e4Smiod       xtensa_literal_prefix (input_line_pointer, len);
1236*3d8817e4Smiod 
1237*3d8817e4Smiod       /* Skip the name in the input line.  */
1238*3d8817e4Smiod       input_line_pointer += len;
1239*3d8817e4Smiod       break;
1240*3d8817e4Smiod 
1241*3d8817e4Smiod     case directive_freeregs:
1242*3d8817e4Smiod       /* This information is currently unused, but we'll accept the statement
1243*3d8817e4Smiod          and just discard the rest of the line.  This won't check the syntax,
1244*3d8817e4Smiod          but it will accept every correct freeregs directive.  */
1245*3d8817e4Smiod       input_line_pointer += strcspn (input_line_pointer, "\n");
1246*3d8817e4Smiod       directive_push (directive_freeregs, negated, 0);
1247*3d8817e4Smiod       break;
1248*3d8817e4Smiod 
1249*3d8817e4Smiod     case directive_schedule:
1250*3d8817e4Smiod       md_flush_pending_output ();
1251*3d8817e4Smiod       frag_var (rs_fill, 0, 0, frag_now->fr_subtype,
1252*3d8817e4Smiod 		frag_now->fr_symbol, frag_now->fr_offset, NULL);
1253*3d8817e4Smiod       directive_push (directive_schedule, negated, 0);
1254*3d8817e4Smiod       xtensa_set_frag_assembly_state (frag_now);
1255*3d8817e4Smiod       break;
1256*3d8817e4Smiod 
1257*3d8817e4Smiod     case directive_density:
1258*3d8817e4Smiod       as_warn (_(".begin [no-]density is ignored"));
1259*3d8817e4Smiod       break;
1260*3d8817e4Smiod 
1261*3d8817e4Smiod     case directive_absolute_literals:
1262*3d8817e4Smiod       md_flush_pending_output ();
1263*3d8817e4Smiod       if (!absolute_literals_supported && !negated)
1264*3d8817e4Smiod 	{
1265*3d8817e4Smiod 	  as_warn (_("Xtensa absolute literals option not supported; ignored"));
1266*3d8817e4Smiod 	  break;
1267*3d8817e4Smiod 	}
1268*3d8817e4Smiod       xtensa_set_frag_assembly_state (frag_now);
1269*3d8817e4Smiod       directive_push (directive, negated, 0);
1270*3d8817e4Smiod       break;
1271*3d8817e4Smiod 
1272*3d8817e4Smiod     default:
1273*3d8817e4Smiod       md_flush_pending_output ();
1274*3d8817e4Smiod       xtensa_set_frag_assembly_state (frag_now);
1275*3d8817e4Smiod       directive_push (directive, negated, 0);
1276*3d8817e4Smiod       break;
1277*3d8817e4Smiod     }
1278*3d8817e4Smiod 
1279*3d8817e4Smiod   demand_empty_rest_of_line ();
1280*3d8817e4Smiod }
1281*3d8817e4Smiod 
1282*3d8817e4Smiod 
1283*3d8817e4Smiod static void
xtensa_end_directive(int ignore ATTRIBUTE_UNUSED)1284*3d8817e4Smiod xtensa_end_directive (int ignore ATTRIBUTE_UNUSED)
1285*3d8817e4Smiod {
1286*3d8817e4Smiod   directiveE begin_directive, end_directive;
1287*3d8817e4Smiod   bfd_boolean begin_negated, end_negated;
1288*3d8817e4Smiod   const char *file;
1289*3d8817e4Smiod   unsigned int line;
1290*3d8817e4Smiod   emit_state *state;
1291*3d8817e4Smiod   emit_state **state_ptr;
1292*3d8817e4Smiod   lit_state *s;
1293*3d8817e4Smiod 
1294*3d8817e4Smiod   if (cur_vinsn.inside_bundle)
1295*3d8817e4Smiod     as_bad (_("directives are not valid inside bundles"));
1296*3d8817e4Smiod 
1297*3d8817e4Smiod   get_directive (&end_directive, &end_negated);
1298*3d8817e4Smiod 
1299*3d8817e4Smiod   md_flush_pending_output ();
1300*3d8817e4Smiod 
1301*3d8817e4Smiod   switch (end_directive)
1302*3d8817e4Smiod     {
1303*3d8817e4Smiod     case (directiveE) XTENSA_UNDEFINED:
1304*3d8817e4Smiod       discard_rest_of_line ();
1305*3d8817e4Smiod       return;
1306*3d8817e4Smiod 
1307*3d8817e4Smiod     case directive_density:
1308*3d8817e4Smiod       as_warn (_(".end [no-]density is ignored"));
1309*3d8817e4Smiod       demand_empty_rest_of_line ();
1310*3d8817e4Smiod       break;
1311*3d8817e4Smiod 
1312*3d8817e4Smiod     case directive_absolute_literals:
1313*3d8817e4Smiod       if (!absolute_literals_supported && !end_negated)
1314*3d8817e4Smiod 	{
1315*3d8817e4Smiod 	  as_warn (_("Xtensa absolute literals option not supported; ignored"));
1316*3d8817e4Smiod 	  demand_empty_rest_of_line ();
1317*3d8817e4Smiod 	  return;
1318*3d8817e4Smiod 	}
1319*3d8817e4Smiod       break;
1320*3d8817e4Smiod 
1321*3d8817e4Smiod     default:
1322*3d8817e4Smiod       break;
1323*3d8817e4Smiod     }
1324*3d8817e4Smiod 
1325*3d8817e4Smiod   state_ptr = &state; /* use state_ptr to avoid type-punning warning */
1326*3d8817e4Smiod   directive_pop (&begin_directive, &begin_negated, &file, &line,
1327*3d8817e4Smiod 		 (const void **) state_ptr);
1328*3d8817e4Smiod 
1329*3d8817e4Smiod   if (begin_directive != directive_none)
1330*3d8817e4Smiod     {
1331*3d8817e4Smiod       if (begin_directive != end_directive || begin_negated != end_negated)
1332*3d8817e4Smiod 	{
1333*3d8817e4Smiod 	  as_bad (_("does not match begin %s%s at %s:%d"),
1334*3d8817e4Smiod 		  begin_negated ? "no-" : "",
1335*3d8817e4Smiod 		  directive_info[begin_directive].name, file, line);
1336*3d8817e4Smiod 	}
1337*3d8817e4Smiod       else
1338*3d8817e4Smiod 	{
1339*3d8817e4Smiod 	  switch (end_directive)
1340*3d8817e4Smiod 	    {
1341*3d8817e4Smiod 	    case directive_literal:
1342*3d8817e4Smiod 	      frag_var (rs_fill, 0, 0, 0, NULL, 0, NULL);
1343*3d8817e4Smiod 	      xtensa_restore_emit_state (state);
1344*3d8817e4Smiod 	      xtensa_set_frag_assembly_state (frag_now);
1345*3d8817e4Smiod 	      free (state);
1346*3d8817e4Smiod 	      if (!inside_directive (directive_literal))
1347*3d8817e4Smiod 		{
1348*3d8817e4Smiod 		  /* Restore the list of current labels.  */
1349*3d8817e4Smiod 		  xtensa_clear_insn_labels ();
1350*3d8817e4Smiod 		  insn_labels = saved_insn_labels;
1351*3d8817e4Smiod 		}
1352*3d8817e4Smiod 	      break;
1353*3d8817e4Smiod 
1354*3d8817e4Smiod 	    case directive_literal_prefix:
1355*3d8817e4Smiod 	      /* Restore the default collection sections from saved state.  */
1356*3d8817e4Smiod 	      s = (lit_state *) state;
1357*3d8817e4Smiod 	      assert (s);
1358*3d8817e4Smiod 
1359*3d8817e4Smiod 	      default_lit_sections = *s;
1360*3d8817e4Smiod 
1361*3d8817e4Smiod 	      /* free the state storage */
1362*3d8817e4Smiod 	      free (s);
1363*3d8817e4Smiod 	      break;
1364*3d8817e4Smiod 
1365*3d8817e4Smiod 	    case directive_schedule:
1366*3d8817e4Smiod 	    case directive_freeregs:
1367*3d8817e4Smiod 	      break;
1368*3d8817e4Smiod 
1369*3d8817e4Smiod 	    default:
1370*3d8817e4Smiod 	      xtensa_set_frag_assembly_state (frag_now);
1371*3d8817e4Smiod 	      break;
1372*3d8817e4Smiod 	    }
1373*3d8817e4Smiod 	}
1374*3d8817e4Smiod     }
1375*3d8817e4Smiod 
1376*3d8817e4Smiod   demand_empty_rest_of_line ();
1377*3d8817e4Smiod }
1378*3d8817e4Smiod 
1379*3d8817e4Smiod 
1380*3d8817e4Smiod /* Place an aligned literal fragment at the current location.  */
1381*3d8817e4Smiod 
1382*3d8817e4Smiod static void
xtensa_literal_position(int ignore ATTRIBUTE_UNUSED)1383*3d8817e4Smiod xtensa_literal_position (int ignore ATTRIBUTE_UNUSED)
1384*3d8817e4Smiod {
1385*3d8817e4Smiod   md_flush_pending_output ();
1386*3d8817e4Smiod 
1387*3d8817e4Smiod   if (inside_directive (directive_literal))
1388*3d8817e4Smiod     as_warn (_(".literal_position inside literal directive; ignoring"));
1389*3d8817e4Smiod   xtensa_mark_literal_pool_location ();
1390*3d8817e4Smiod 
1391*3d8817e4Smiod   demand_empty_rest_of_line ();
1392*3d8817e4Smiod   xtensa_clear_insn_labels ();
1393*3d8817e4Smiod }
1394*3d8817e4Smiod 
1395*3d8817e4Smiod 
1396*3d8817e4Smiod /* Support .literal label, expr, ...  */
1397*3d8817e4Smiod 
1398*3d8817e4Smiod static void
xtensa_literal_pseudo(int ignored ATTRIBUTE_UNUSED)1399*3d8817e4Smiod xtensa_literal_pseudo (int ignored ATTRIBUTE_UNUSED)
1400*3d8817e4Smiod {
1401*3d8817e4Smiod   emit_state state;
1402*3d8817e4Smiod   char *p, *base_name;
1403*3d8817e4Smiod   char c;
1404*3d8817e4Smiod   segT dest_seg;
1405*3d8817e4Smiod 
1406*3d8817e4Smiod   if (inside_directive (directive_literal))
1407*3d8817e4Smiod     {
1408*3d8817e4Smiod       as_bad (_(".literal not allowed inside .begin literal region"));
1409*3d8817e4Smiod       ignore_rest_of_line ();
1410*3d8817e4Smiod       return;
1411*3d8817e4Smiod     }
1412*3d8817e4Smiod 
1413*3d8817e4Smiod   md_flush_pending_output ();
1414*3d8817e4Smiod 
1415*3d8817e4Smiod   /* Previous labels go with whatever follows this directive, not with
1416*3d8817e4Smiod      the literal, so save them now.  */
1417*3d8817e4Smiod   saved_insn_labels = insn_labels;
1418*3d8817e4Smiod   insn_labels = NULL;
1419*3d8817e4Smiod 
1420*3d8817e4Smiod   /* If we are using text-section literals, then this is the right value... */
1421*3d8817e4Smiod   dest_seg = now_seg;
1422*3d8817e4Smiod 
1423*3d8817e4Smiod   base_name = input_line_pointer;
1424*3d8817e4Smiod 
1425*3d8817e4Smiod   xtensa_switch_to_literal_fragment (&state);
1426*3d8817e4Smiod 
1427*3d8817e4Smiod   /* ...but if we aren't using text-section-literals, then we
1428*3d8817e4Smiod      need to put them in the section we just switched to.  */
1429*3d8817e4Smiod   if (use_literal_section || directive_state[directive_absolute_literals])
1430*3d8817e4Smiod     dest_seg = now_seg;
1431*3d8817e4Smiod 
1432*3d8817e4Smiod   /* All literals are aligned to four-byte boundaries.  */
1433*3d8817e4Smiod   frag_align (2, 0, 0);
1434*3d8817e4Smiod   record_alignment (now_seg, 2);
1435*3d8817e4Smiod 
1436*3d8817e4Smiod   c = get_symbol_end ();
1437*3d8817e4Smiod   /* Just after name is now '\0'.  */
1438*3d8817e4Smiod   p = input_line_pointer;
1439*3d8817e4Smiod   *p = c;
1440*3d8817e4Smiod   SKIP_WHITESPACE ();
1441*3d8817e4Smiod 
1442*3d8817e4Smiod   if (*input_line_pointer != ',' && *input_line_pointer != ':')
1443*3d8817e4Smiod     {
1444*3d8817e4Smiod       as_bad (_("expected comma or colon after symbol name; "
1445*3d8817e4Smiod 		"rest of line ignored"));
1446*3d8817e4Smiod       ignore_rest_of_line ();
1447*3d8817e4Smiod       xtensa_restore_emit_state (&state);
1448*3d8817e4Smiod       return;
1449*3d8817e4Smiod     }
1450*3d8817e4Smiod   *p = 0;
1451*3d8817e4Smiod 
1452*3d8817e4Smiod   colon (base_name);
1453*3d8817e4Smiod 
1454*3d8817e4Smiod   *p = c;
1455*3d8817e4Smiod   input_line_pointer++;		/* skip ',' or ':' */
1456*3d8817e4Smiod 
1457*3d8817e4Smiod   xtensa_elf_cons (4);
1458*3d8817e4Smiod 
1459*3d8817e4Smiod   xtensa_restore_emit_state (&state);
1460*3d8817e4Smiod 
1461*3d8817e4Smiod   /* Restore the list of current labels.  */
1462*3d8817e4Smiod   xtensa_clear_insn_labels ();
1463*3d8817e4Smiod   insn_labels = saved_insn_labels;
1464*3d8817e4Smiod }
1465*3d8817e4Smiod 
1466*3d8817e4Smiod 
1467*3d8817e4Smiod static void
xtensa_literal_prefix(char const * start,int len)1468*3d8817e4Smiod xtensa_literal_prefix (char const *start, int len)
1469*3d8817e4Smiod {
1470*3d8817e4Smiod   char *name, *linkonce_suffix;
1471*3d8817e4Smiod   char *newname, *newname4;
1472*3d8817e4Smiod   size_t linkonce_len;
1473*3d8817e4Smiod 
1474*3d8817e4Smiod   /* Get a null-terminated copy of the name.  */
1475*3d8817e4Smiod   name = xmalloc (len + 1);
1476*3d8817e4Smiod   assert (name);
1477*3d8817e4Smiod 
1478*3d8817e4Smiod   strncpy (name, start, len);
1479*3d8817e4Smiod   name[len] = 0;
1480*3d8817e4Smiod 
1481*3d8817e4Smiod   /* Allocate the sections (interesting note: the memory pointing to
1482*3d8817e4Smiod      the name is actually used for the name by the new section). */
1483*3d8817e4Smiod 
1484*3d8817e4Smiod   newname = xmalloc (len + strlen (".literal") + 1);
1485*3d8817e4Smiod   newname4 = xmalloc (len + strlen (".lit4") + 1);
1486*3d8817e4Smiod 
1487*3d8817e4Smiod   linkonce_len = sizeof (".gnu.linkonce.") - 1;
1488*3d8817e4Smiod   if (strncmp (name, ".gnu.linkonce.", linkonce_len) == 0
1489*3d8817e4Smiod       && (linkonce_suffix = strchr (name + linkonce_len, '.')) != 0)
1490*3d8817e4Smiod     {
1491*3d8817e4Smiod       strcpy (newname, ".gnu.linkonce.literal");
1492*3d8817e4Smiod       strcpy (newname4, ".gnu.linkonce.lit4");
1493*3d8817e4Smiod 
1494*3d8817e4Smiod       strcat (newname, linkonce_suffix);
1495*3d8817e4Smiod       strcat (newname4, linkonce_suffix);
1496*3d8817e4Smiod     }
1497*3d8817e4Smiod   else
1498*3d8817e4Smiod     {
1499*3d8817e4Smiod       int suffix_pos = len;
1500*3d8817e4Smiod 
1501*3d8817e4Smiod       /* If the section name ends with ".text", then replace that suffix
1502*3d8817e4Smiod 	 instead of appending an additional suffix.  */
1503*3d8817e4Smiod       if (len >= 5 && strcmp (name + len - 5, ".text") == 0)
1504*3d8817e4Smiod 	suffix_pos -= 5;
1505*3d8817e4Smiod 
1506*3d8817e4Smiod       strcpy (newname, name);
1507*3d8817e4Smiod       strcpy (newname4, name);
1508*3d8817e4Smiod 
1509*3d8817e4Smiod       strcpy (newname + suffix_pos, ".literal");
1510*3d8817e4Smiod       strcpy (newname4 + suffix_pos, ".lit4");
1511*3d8817e4Smiod     }
1512*3d8817e4Smiod 
1513*3d8817e4Smiod   /* Note that cache_literal_section does not create a segment if
1514*3d8817e4Smiod      it already exists.  */
1515*3d8817e4Smiod   default_lit_sections.lit_seg = NULL;
1516*3d8817e4Smiod   default_lit_sections.lit4_seg = NULL;
1517*3d8817e4Smiod 
1518*3d8817e4Smiod   /* Canonicalizing section names allows renaming literal
1519*3d8817e4Smiod      sections to occur correctly.  */
1520*3d8817e4Smiod   default_lit_sections.lit_seg_name = tc_canonicalize_symbol_name (newname);
1521*3d8817e4Smiod   default_lit_sections.lit4_seg_name = tc_canonicalize_symbol_name (newname4);
1522*3d8817e4Smiod 
1523*3d8817e4Smiod   free (name);
1524*3d8817e4Smiod }
1525*3d8817e4Smiod 
1526*3d8817e4Smiod 
1527*3d8817e4Smiod /* Support ".frequency branch_target_frequency fall_through_frequency".  */
1528*3d8817e4Smiod 
1529*3d8817e4Smiod static void
xtensa_frequency_pseudo(int ignored ATTRIBUTE_UNUSED)1530*3d8817e4Smiod xtensa_frequency_pseudo (int ignored ATTRIBUTE_UNUSED)
1531*3d8817e4Smiod {
1532*3d8817e4Smiod   float fall_through_f, target_f;
1533*3d8817e4Smiod 
1534*3d8817e4Smiod   fall_through_f = (float) strtod (input_line_pointer, &input_line_pointer);
1535*3d8817e4Smiod   if (fall_through_f < 0)
1536*3d8817e4Smiod     {
1537*3d8817e4Smiod       as_bad (_("fall through frequency must be greater than 0"));
1538*3d8817e4Smiod       ignore_rest_of_line ();
1539*3d8817e4Smiod       return;
1540*3d8817e4Smiod     }
1541*3d8817e4Smiod 
1542*3d8817e4Smiod   target_f = (float) strtod (input_line_pointer, &input_line_pointer);
1543*3d8817e4Smiod   if (target_f < 0)
1544*3d8817e4Smiod     {
1545*3d8817e4Smiod       as_bad (_("branch target frequency must be greater than 0"));
1546*3d8817e4Smiod       ignore_rest_of_line ();
1547*3d8817e4Smiod       return;
1548*3d8817e4Smiod     }
1549*3d8817e4Smiod 
1550*3d8817e4Smiod   set_subseg_freq (now_seg, now_subseg, target_f + fall_through_f, target_f);
1551*3d8817e4Smiod 
1552*3d8817e4Smiod   demand_empty_rest_of_line ();
1553*3d8817e4Smiod }
1554*3d8817e4Smiod 
1555*3d8817e4Smiod 
1556*3d8817e4Smiod /* Like normal .long/.short/.word, except support @plt, etc.
1557*3d8817e4Smiod    Clobbers input_line_pointer, checks end-of-line.  */
1558*3d8817e4Smiod 
1559*3d8817e4Smiod static void
xtensa_elf_cons(int nbytes)1560*3d8817e4Smiod xtensa_elf_cons (int nbytes)
1561*3d8817e4Smiod {
1562*3d8817e4Smiod   expressionS exp;
1563*3d8817e4Smiod   bfd_reloc_code_real_type reloc;
1564*3d8817e4Smiod 
1565*3d8817e4Smiod   md_flush_pending_output ();
1566*3d8817e4Smiod 
1567*3d8817e4Smiod   if (cur_vinsn.inside_bundle)
1568*3d8817e4Smiod     as_bad (_("directives are not valid inside bundles"));
1569*3d8817e4Smiod 
1570*3d8817e4Smiod   if (is_it_end_of_statement ())
1571*3d8817e4Smiod     {
1572*3d8817e4Smiod       demand_empty_rest_of_line ();
1573*3d8817e4Smiod       return;
1574*3d8817e4Smiod     }
1575*3d8817e4Smiod 
1576*3d8817e4Smiod   do
1577*3d8817e4Smiod     {
1578*3d8817e4Smiod       expression (&exp);
1579*3d8817e4Smiod       if (exp.X_op == O_symbol
1580*3d8817e4Smiod 	  && *input_line_pointer == '@'
1581*3d8817e4Smiod 	  && ((reloc = xtensa_elf_suffix (&input_line_pointer, &exp))
1582*3d8817e4Smiod 	      != BFD_RELOC_NONE))
1583*3d8817e4Smiod 	{
1584*3d8817e4Smiod 	  reloc_howto_type *reloc_howto =
1585*3d8817e4Smiod 	    bfd_reloc_type_lookup (stdoutput, reloc);
1586*3d8817e4Smiod 
1587*3d8817e4Smiod 	  if (reloc == BFD_RELOC_UNUSED || !reloc_howto)
1588*3d8817e4Smiod 	    as_bad (_("unsupported relocation"));
1589*3d8817e4Smiod 	  else if ((reloc >= BFD_RELOC_XTENSA_SLOT0_OP
1590*3d8817e4Smiod 		    && reloc <= BFD_RELOC_XTENSA_SLOT14_OP)
1591*3d8817e4Smiod 		   || (reloc >= BFD_RELOC_XTENSA_SLOT0_ALT
1592*3d8817e4Smiod 		       && reloc <= BFD_RELOC_XTENSA_SLOT14_ALT))
1593*3d8817e4Smiod 	    as_bad (_("opcode-specific %s relocation used outside "
1594*3d8817e4Smiod 		      "an instruction"), reloc_howto->name);
1595*3d8817e4Smiod 	  else if (nbytes != (int) bfd_get_reloc_size (reloc_howto))
1596*3d8817e4Smiod 	    as_bad (_("%s relocations do not fit in %d bytes"),
1597*3d8817e4Smiod 		    reloc_howto->name, nbytes);
1598*3d8817e4Smiod 	  else
1599*3d8817e4Smiod 	    {
1600*3d8817e4Smiod 	      char *p = frag_more ((int) nbytes);
1601*3d8817e4Smiod 	      xtensa_set_frag_assembly_state (frag_now);
1602*3d8817e4Smiod 	      fix_new_exp (frag_now, p - frag_now->fr_literal,
1603*3d8817e4Smiod 			   nbytes, &exp, 0, reloc);
1604*3d8817e4Smiod 	    }
1605*3d8817e4Smiod 	}
1606*3d8817e4Smiod       else
1607*3d8817e4Smiod 	emit_expr (&exp, (unsigned int) nbytes);
1608*3d8817e4Smiod     }
1609*3d8817e4Smiod   while (*input_line_pointer++ == ',');
1610*3d8817e4Smiod 
1611*3d8817e4Smiod   input_line_pointer--;		/* Put terminator back into stream.  */
1612*3d8817e4Smiod   demand_empty_rest_of_line ();
1613*3d8817e4Smiod }
1614*3d8817e4Smiod 
1615*3d8817e4Smiod 
1616*3d8817e4Smiod /* Parsing and Idiom Translation.  */
1617*3d8817e4Smiod 
1618*3d8817e4Smiod /* Parse @plt, etc. and return the desired relocation.  */
1619*3d8817e4Smiod static bfd_reloc_code_real_type
xtensa_elf_suffix(char ** str_p,expressionS * exp_p)1620*3d8817e4Smiod xtensa_elf_suffix (char **str_p, expressionS *exp_p)
1621*3d8817e4Smiod {
1622*3d8817e4Smiod   struct map_bfd
1623*3d8817e4Smiod   {
1624*3d8817e4Smiod     char *string;
1625*3d8817e4Smiod     int length;
1626*3d8817e4Smiod     bfd_reloc_code_real_type reloc;
1627*3d8817e4Smiod   };
1628*3d8817e4Smiod 
1629*3d8817e4Smiod   char ident[20];
1630*3d8817e4Smiod   char *str = *str_p;
1631*3d8817e4Smiod   char *str2;
1632*3d8817e4Smiod   int ch;
1633*3d8817e4Smiod   int len;
1634*3d8817e4Smiod   struct map_bfd *ptr;
1635*3d8817e4Smiod 
1636*3d8817e4Smiod #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
1637*3d8817e4Smiod 
1638*3d8817e4Smiod   static struct map_bfd mapping[] =
1639*3d8817e4Smiod   {
1640*3d8817e4Smiod     MAP ("l",		BFD_RELOC_LO16),
1641*3d8817e4Smiod     MAP ("h",		BFD_RELOC_HI16),
1642*3d8817e4Smiod     MAP ("plt",		BFD_RELOC_XTENSA_PLT),
1643*3d8817e4Smiod     { (char *) 0, 0,	BFD_RELOC_UNUSED }
1644*3d8817e4Smiod   };
1645*3d8817e4Smiod 
1646*3d8817e4Smiod   if (*str++ != '@')
1647*3d8817e4Smiod     return BFD_RELOC_NONE;
1648*3d8817e4Smiod 
1649*3d8817e4Smiod   for (ch = *str, str2 = ident;
1650*3d8817e4Smiod        (str2 < ident + sizeof (ident) - 1
1651*3d8817e4Smiod 	&& (ISALNUM (ch) || ch == '@'));
1652*3d8817e4Smiod        ch = *++str)
1653*3d8817e4Smiod     {
1654*3d8817e4Smiod       *str2++ = (ISLOWER (ch)) ? ch : TOLOWER (ch);
1655*3d8817e4Smiod     }
1656*3d8817e4Smiod 
1657*3d8817e4Smiod   *str2 = '\0';
1658*3d8817e4Smiod   len = str2 - ident;
1659*3d8817e4Smiod 
1660*3d8817e4Smiod   ch = ident[0];
1661*3d8817e4Smiod   for (ptr = &mapping[0]; ptr->length > 0; ptr++)
1662*3d8817e4Smiod     if (ch == ptr->string[0]
1663*3d8817e4Smiod 	&& len == ptr->length
1664*3d8817e4Smiod 	&& memcmp (ident, ptr->string, ptr->length) == 0)
1665*3d8817e4Smiod       {
1666*3d8817e4Smiod 	/* Now check for "identifier@suffix+constant".  */
1667*3d8817e4Smiod 	if (*str == '-' || *str == '+')
1668*3d8817e4Smiod 	  {
1669*3d8817e4Smiod 	    char *orig_line = input_line_pointer;
1670*3d8817e4Smiod 	    expressionS new_exp;
1671*3d8817e4Smiod 
1672*3d8817e4Smiod 	    input_line_pointer = str;
1673*3d8817e4Smiod 	    expression (&new_exp);
1674*3d8817e4Smiod 	    if (new_exp.X_op == O_constant)
1675*3d8817e4Smiod 	      {
1676*3d8817e4Smiod 		exp_p->X_add_number += new_exp.X_add_number;
1677*3d8817e4Smiod 		str = input_line_pointer;
1678*3d8817e4Smiod 	      }
1679*3d8817e4Smiod 
1680*3d8817e4Smiod 	    if (&input_line_pointer != str_p)
1681*3d8817e4Smiod 	      input_line_pointer = orig_line;
1682*3d8817e4Smiod 	  }
1683*3d8817e4Smiod 
1684*3d8817e4Smiod 	*str_p = str;
1685*3d8817e4Smiod 	return ptr->reloc;
1686*3d8817e4Smiod       }
1687*3d8817e4Smiod 
1688*3d8817e4Smiod   return BFD_RELOC_UNUSED;
1689*3d8817e4Smiod }
1690*3d8817e4Smiod 
1691*3d8817e4Smiod 
1692*3d8817e4Smiod static const char *
expression_end(const char * name)1693*3d8817e4Smiod expression_end (const char *name)
1694*3d8817e4Smiod {
1695*3d8817e4Smiod   while (1)
1696*3d8817e4Smiod     {
1697*3d8817e4Smiod       switch (*name)
1698*3d8817e4Smiod 	{
1699*3d8817e4Smiod 	case '}':
1700*3d8817e4Smiod 	case ';':
1701*3d8817e4Smiod 	case '\0':
1702*3d8817e4Smiod 	case ',':
1703*3d8817e4Smiod 	case ':':
1704*3d8817e4Smiod 	  return name;
1705*3d8817e4Smiod 	case ' ':
1706*3d8817e4Smiod 	case '\t':
1707*3d8817e4Smiod 	  ++name;
1708*3d8817e4Smiod 	  continue;
1709*3d8817e4Smiod 	default:
1710*3d8817e4Smiod 	  return 0;
1711*3d8817e4Smiod 	}
1712*3d8817e4Smiod     }
1713*3d8817e4Smiod }
1714*3d8817e4Smiod 
1715*3d8817e4Smiod 
1716*3d8817e4Smiod #define ERROR_REG_NUM ((unsigned) -1)
1717*3d8817e4Smiod 
1718*3d8817e4Smiod static unsigned
tc_get_register(const char * prefix)1719*3d8817e4Smiod tc_get_register (const char *prefix)
1720*3d8817e4Smiod {
1721*3d8817e4Smiod   unsigned reg;
1722*3d8817e4Smiod   const char *next_expr;
1723*3d8817e4Smiod   const char *old_line_pointer;
1724*3d8817e4Smiod 
1725*3d8817e4Smiod   SKIP_WHITESPACE ();
1726*3d8817e4Smiod   old_line_pointer = input_line_pointer;
1727*3d8817e4Smiod 
1728*3d8817e4Smiod   if (*input_line_pointer == '$')
1729*3d8817e4Smiod     ++input_line_pointer;
1730*3d8817e4Smiod 
1731*3d8817e4Smiod   /* Accept "sp" as a synonym for "a1".  */
1732*3d8817e4Smiod   if (input_line_pointer[0] == 's' && input_line_pointer[1] == 'p'
1733*3d8817e4Smiod       && expression_end (input_line_pointer + 2))
1734*3d8817e4Smiod     {
1735*3d8817e4Smiod       input_line_pointer += 2;
1736*3d8817e4Smiod       return 1;  /* AR[1] */
1737*3d8817e4Smiod     }
1738*3d8817e4Smiod 
1739*3d8817e4Smiod   while (*input_line_pointer++ == *prefix++)
1740*3d8817e4Smiod     ;
1741*3d8817e4Smiod   --input_line_pointer;
1742*3d8817e4Smiod   --prefix;
1743*3d8817e4Smiod 
1744*3d8817e4Smiod   if (*prefix)
1745*3d8817e4Smiod     {
1746*3d8817e4Smiod       as_bad (_("bad register name: %s"), old_line_pointer);
1747*3d8817e4Smiod       return ERROR_REG_NUM;
1748*3d8817e4Smiod     }
1749*3d8817e4Smiod 
1750*3d8817e4Smiod   if (!ISDIGIT ((unsigned char) *input_line_pointer))
1751*3d8817e4Smiod     {
1752*3d8817e4Smiod       as_bad (_("bad register number: %s"), input_line_pointer);
1753*3d8817e4Smiod       return ERROR_REG_NUM;
1754*3d8817e4Smiod     }
1755*3d8817e4Smiod 
1756*3d8817e4Smiod   reg = 0;
1757*3d8817e4Smiod 
1758*3d8817e4Smiod   while (ISDIGIT ((int) *input_line_pointer))
1759*3d8817e4Smiod     reg = reg * 10 + *input_line_pointer++ - '0';
1760*3d8817e4Smiod 
1761*3d8817e4Smiod   if (!(next_expr = expression_end (input_line_pointer)))
1762*3d8817e4Smiod     {
1763*3d8817e4Smiod       as_bad (_("bad register name: %s"), old_line_pointer);
1764*3d8817e4Smiod       return ERROR_REG_NUM;
1765*3d8817e4Smiod     }
1766*3d8817e4Smiod 
1767*3d8817e4Smiod   input_line_pointer = (char *) next_expr;
1768*3d8817e4Smiod 
1769*3d8817e4Smiod   return reg;
1770*3d8817e4Smiod }
1771*3d8817e4Smiod 
1772*3d8817e4Smiod 
1773*3d8817e4Smiod static void
expression_maybe_register(xtensa_opcode opc,int opnd,expressionS * tok)1774*3d8817e4Smiod expression_maybe_register (xtensa_opcode opc, int opnd, expressionS *tok)
1775*3d8817e4Smiod {
1776*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
1777*3d8817e4Smiod 
1778*3d8817e4Smiod   /* Check if this is an immediate operand.  */
1779*3d8817e4Smiod   if (xtensa_operand_is_register (isa, opc, opnd) == 0)
1780*3d8817e4Smiod     {
1781*3d8817e4Smiod       bfd_reloc_code_real_type reloc;
1782*3d8817e4Smiod       segT t = expression (tok);
1783*3d8817e4Smiod       if (t == absolute_section
1784*3d8817e4Smiod 	  && xtensa_operand_is_PCrelative (isa, opc, opnd) == 1)
1785*3d8817e4Smiod 	{
1786*3d8817e4Smiod 	  assert (tok->X_op == O_constant);
1787*3d8817e4Smiod 	  tok->X_op = O_symbol;
1788*3d8817e4Smiod 	  tok->X_add_symbol = &abs_symbol;
1789*3d8817e4Smiod 	}
1790*3d8817e4Smiod 
1791*3d8817e4Smiod       if ((tok->X_op == O_constant || tok->X_op == O_symbol)
1792*3d8817e4Smiod 	  && (reloc = xtensa_elf_suffix (&input_line_pointer, tok))
1793*3d8817e4Smiod 	  && (reloc != BFD_RELOC_NONE))
1794*3d8817e4Smiod 	{
1795*3d8817e4Smiod 	  switch (reloc)
1796*3d8817e4Smiod 	    {
1797*3d8817e4Smiod 	      default:
1798*3d8817e4Smiod 	      case BFD_RELOC_UNUSED:
1799*3d8817e4Smiod 		as_bad (_("unsupported relocation"));
1800*3d8817e4Smiod 	        break;
1801*3d8817e4Smiod 
1802*3d8817e4Smiod 	      case BFD_RELOC_XTENSA_PLT:
1803*3d8817e4Smiod 		tok->X_op = O_pltrel;
1804*3d8817e4Smiod 		break;
1805*3d8817e4Smiod 
1806*3d8817e4Smiod 	      case BFD_RELOC_LO16:
1807*3d8817e4Smiod 		if (tok->X_op == O_constant)
1808*3d8817e4Smiod 		  tok->X_add_number &= 0xffff;
1809*3d8817e4Smiod 		else
1810*3d8817e4Smiod 		  tok->X_op = O_lo16;
1811*3d8817e4Smiod 		break;
1812*3d8817e4Smiod 
1813*3d8817e4Smiod 	      case BFD_RELOC_HI16:
1814*3d8817e4Smiod 		if (tok->X_op == O_constant)
1815*3d8817e4Smiod 		  tok->X_add_number = ((unsigned) tok->X_add_number) >> 16;
1816*3d8817e4Smiod 		else
1817*3d8817e4Smiod 		  tok->X_op = O_hi16;
1818*3d8817e4Smiod 		break;
1819*3d8817e4Smiod 	    }
1820*3d8817e4Smiod 	}
1821*3d8817e4Smiod     }
1822*3d8817e4Smiod   else
1823*3d8817e4Smiod     {
1824*3d8817e4Smiod       xtensa_regfile opnd_rf = xtensa_operand_regfile (isa, opc, opnd);
1825*3d8817e4Smiod       unsigned reg = tc_get_register (xtensa_regfile_shortname (isa, opnd_rf));
1826*3d8817e4Smiod 
1827*3d8817e4Smiod       if (reg != ERROR_REG_NUM)	/* Already errored */
1828*3d8817e4Smiod 	{
1829*3d8817e4Smiod 	  uint32 buf = reg;
1830*3d8817e4Smiod 	  if (xtensa_operand_encode (isa, opc, opnd, &buf))
1831*3d8817e4Smiod 	    as_bad (_("register number out of range"));
1832*3d8817e4Smiod 	}
1833*3d8817e4Smiod 
1834*3d8817e4Smiod       tok->X_op = O_register;
1835*3d8817e4Smiod       tok->X_add_symbol = 0;
1836*3d8817e4Smiod       tok->X_add_number = reg;
1837*3d8817e4Smiod     }
1838*3d8817e4Smiod }
1839*3d8817e4Smiod 
1840*3d8817e4Smiod 
1841*3d8817e4Smiod /* Split up the arguments for an opcode or pseudo-op.  */
1842*3d8817e4Smiod 
1843*3d8817e4Smiod static int
tokenize_arguments(char ** args,char * str)1844*3d8817e4Smiod tokenize_arguments (char **args, char *str)
1845*3d8817e4Smiod {
1846*3d8817e4Smiod   char *old_input_line_pointer;
1847*3d8817e4Smiod   bfd_boolean saw_comma = FALSE;
1848*3d8817e4Smiod   bfd_boolean saw_arg = FALSE;
1849*3d8817e4Smiod   bfd_boolean saw_colon = FALSE;
1850*3d8817e4Smiod   int num_args = 0;
1851*3d8817e4Smiod   char *arg_end, *arg;
1852*3d8817e4Smiod   int arg_len;
1853*3d8817e4Smiod 
1854*3d8817e4Smiod   /* Save and restore input_line_pointer around this function.  */
1855*3d8817e4Smiod   old_input_line_pointer = input_line_pointer;
1856*3d8817e4Smiod   input_line_pointer = str;
1857*3d8817e4Smiod 
1858*3d8817e4Smiod   while (*input_line_pointer)
1859*3d8817e4Smiod     {
1860*3d8817e4Smiod       SKIP_WHITESPACE ();
1861*3d8817e4Smiod       switch (*input_line_pointer)
1862*3d8817e4Smiod 	{
1863*3d8817e4Smiod 	case '\0':
1864*3d8817e4Smiod 	case '}':
1865*3d8817e4Smiod 	  goto fini;
1866*3d8817e4Smiod 
1867*3d8817e4Smiod 	case ':':
1868*3d8817e4Smiod 	  input_line_pointer++;
1869*3d8817e4Smiod 	  if (saw_comma || saw_colon || !saw_arg)
1870*3d8817e4Smiod 	    goto err;
1871*3d8817e4Smiod 	  saw_colon = TRUE;
1872*3d8817e4Smiod 	  break;
1873*3d8817e4Smiod 
1874*3d8817e4Smiod 	case ',':
1875*3d8817e4Smiod 	  input_line_pointer++;
1876*3d8817e4Smiod 	  if (saw_comma || saw_colon || !saw_arg)
1877*3d8817e4Smiod 	    goto err;
1878*3d8817e4Smiod 	  saw_comma = TRUE;
1879*3d8817e4Smiod 	  break;
1880*3d8817e4Smiod 
1881*3d8817e4Smiod 	default:
1882*3d8817e4Smiod 	  if (!saw_comma && !saw_colon && saw_arg)
1883*3d8817e4Smiod 	    goto err;
1884*3d8817e4Smiod 
1885*3d8817e4Smiod 	  arg_end = input_line_pointer + 1;
1886*3d8817e4Smiod 	  while (!expression_end (arg_end))
1887*3d8817e4Smiod 	    arg_end += 1;
1888*3d8817e4Smiod 
1889*3d8817e4Smiod 	  arg_len = arg_end - input_line_pointer;
1890*3d8817e4Smiod 	  arg = (char *) xmalloc ((saw_colon ? 1 : 0) + arg_len + 1);
1891*3d8817e4Smiod 	  args[num_args] = arg;
1892*3d8817e4Smiod 
1893*3d8817e4Smiod 	  if (saw_colon)
1894*3d8817e4Smiod 	    *arg++ = ':';
1895*3d8817e4Smiod 	  strncpy (arg, input_line_pointer, arg_len);
1896*3d8817e4Smiod 	  arg[arg_len] = '\0';
1897*3d8817e4Smiod 
1898*3d8817e4Smiod 	  input_line_pointer = arg_end;
1899*3d8817e4Smiod 	  num_args += 1;
1900*3d8817e4Smiod 	  saw_comma = FALSE;
1901*3d8817e4Smiod 	  saw_colon = FALSE;
1902*3d8817e4Smiod 	  saw_arg = TRUE;
1903*3d8817e4Smiod 	  break;
1904*3d8817e4Smiod 	}
1905*3d8817e4Smiod     }
1906*3d8817e4Smiod 
1907*3d8817e4Smiod fini:
1908*3d8817e4Smiod   if (saw_comma || saw_colon)
1909*3d8817e4Smiod     goto err;
1910*3d8817e4Smiod   input_line_pointer = old_input_line_pointer;
1911*3d8817e4Smiod   return num_args;
1912*3d8817e4Smiod 
1913*3d8817e4Smiod err:
1914*3d8817e4Smiod   if (saw_comma)
1915*3d8817e4Smiod     as_bad (_("extra comma"));
1916*3d8817e4Smiod   else if (saw_colon)
1917*3d8817e4Smiod     as_bad (_("extra colon"));
1918*3d8817e4Smiod   else if (!saw_arg)
1919*3d8817e4Smiod     as_bad (_("missing argument"));
1920*3d8817e4Smiod   else
1921*3d8817e4Smiod     as_bad (_("missing comma or colon"));
1922*3d8817e4Smiod   input_line_pointer = old_input_line_pointer;
1923*3d8817e4Smiod   return -1;
1924*3d8817e4Smiod }
1925*3d8817e4Smiod 
1926*3d8817e4Smiod 
1927*3d8817e4Smiod /* Parse the arguments to an opcode.  Return TRUE on error.  */
1928*3d8817e4Smiod 
1929*3d8817e4Smiod static bfd_boolean
parse_arguments(TInsn * insn,int num_args,char ** arg_strings)1930*3d8817e4Smiod parse_arguments (TInsn *insn, int num_args, char **arg_strings)
1931*3d8817e4Smiod {
1932*3d8817e4Smiod   expressionS *tok, *last_tok;
1933*3d8817e4Smiod   xtensa_opcode opcode = insn->opcode;
1934*3d8817e4Smiod   bfd_boolean had_error = TRUE;
1935*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
1936*3d8817e4Smiod   int n, num_regs = 0;
1937*3d8817e4Smiod   int opcode_operand_count;
1938*3d8817e4Smiod   int opnd_cnt, last_opnd_cnt;
1939*3d8817e4Smiod   unsigned int next_reg = 0;
1940*3d8817e4Smiod   char *old_input_line_pointer;
1941*3d8817e4Smiod 
1942*3d8817e4Smiod   if (insn->insn_type == ITYPE_LITERAL)
1943*3d8817e4Smiod     opcode_operand_count = 1;
1944*3d8817e4Smiod   else
1945*3d8817e4Smiod     opcode_operand_count = xtensa_opcode_num_operands (isa, opcode);
1946*3d8817e4Smiod 
1947*3d8817e4Smiod   tok = insn->tok;
1948*3d8817e4Smiod   memset (tok, 0, sizeof (*tok) * MAX_INSN_ARGS);
1949*3d8817e4Smiod 
1950*3d8817e4Smiod   /* Save and restore input_line_pointer around this function.  */
1951*3d8817e4Smiod   old_input_line_pointer = input_line_pointer;
1952*3d8817e4Smiod 
1953*3d8817e4Smiod   last_tok = 0;
1954*3d8817e4Smiod   last_opnd_cnt = -1;
1955*3d8817e4Smiod   opnd_cnt = 0;
1956*3d8817e4Smiod 
1957*3d8817e4Smiod   /* Skip invisible operands.  */
1958*3d8817e4Smiod   while (xtensa_operand_is_visible (isa, opcode, opnd_cnt) == 0)
1959*3d8817e4Smiod     {
1960*3d8817e4Smiod       opnd_cnt += 1;
1961*3d8817e4Smiod       tok++;
1962*3d8817e4Smiod     }
1963*3d8817e4Smiod 
1964*3d8817e4Smiod   for (n = 0; n < num_args; n++)
1965*3d8817e4Smiod     {
1966*3d8817e4Smiod       input_line_pointer = arg_strings[n];
1967*3d8817e4Smiod       if (*input_line_pointer == ':')
1968*3d8817e4Smiod 	{
1969*3d8817e4Smiod 	  xtensa_regfile opnd_rf;
1970*3d8817e4Smiod 	  input_line_pointer++;
1971*3d8817e4Smiod 	  if (num_regs == 0)
1972*3d8817e4Smiod 	    goto err;
1973*3d8817e4Smiod 	  assert (opnd_cnt > 0);
1974*3d8817e4Smiod 	  num_regs--;
1975*3d8817e4Smiod 	  opnd_rf = xtensa_operand_regfile (isa, opcode, last_opnd_cnt);
1976*3d8817e4Smiod 	  if (next_reg
1977*3d8817e4Smiod 	      != tc_get_register (xtensa_regfile_shortname (isa, opnd_rf)))
1978*3d8817e4Smiod 	    as_warn (_("incorrect register number, ignoring"));
1979*3d8817e4Smiod 	  next_reg++;
1980*3d8817e4Smiod 	}
1981*3d8817e4Smiod       else
1982*3d8817e4Smiod 	{
1983*3d8817e4Smiod 	  if (opnd_cnt >= opcode_operand_count)
1984*3d8817e4Smiod 	    {
1985*3d8817e4Smiod 	      as_warn (_("too many arguments"));
1986*3d8817e4Smiod 	      goto err;
1987*3d8817e4Smiod 	    }
1988*3d8817e4Smiod 	  assert (opnd_cnt < MAX_INSN_ARGS);
1989*3d8817e4Smiod 
1990*3d8817e4Smiod 	  expression_maybe_register (opcode, opnd_cnt, tok);
1991*3d8817e4Smiod 	  next_reg = tok->X_add_number + 1;
1992*3d8817e4Smiod 
1993*3d8817e4Smiod 	  if (tok->X_op == O_illegal || tok->X_op == O_absent)
1994*3d8817e4Smiod 	    goto err;
1995*3d8817e4Smiod 	  if (xtensa_operand_is_register (isa, opcode, opnd_cnt) == 1)
1996*3d8817e4Smiod 	    {
1997*3d8817e4Smiod 	      num_regs = xtensa_operand_num_regs (isa, opcode, opnd_cnt) - 1;
1998*3d8817e4Smiod 	      /* minus 1 because we are seeing one right now */
1999*3d8817e4Smiod 	    }
2000*3d8817e4Smiod 	  else
2001*3d8817e4Smiod 	    num_regs = 0;
2002*3d8817e4Smiod 
2003*3d8817e4Smiod 	  last_tok = tok;
2004*3d8817e4Smiod 	  last_opnd_cnt = opnd_cnt;
2005*3d8817e4Smiod 
2006*3d8817e4Smiod 	  do
2007*3d8817e4Smiod 	    {
2008*3d8817e4Smiod 	      opnd_cnt += 1;
2009*3d8817e4Smiod 	      tok++;
2010*3d8817e4Smiod 	    }
2011*3d8817e4Smiod 	  while (xtensa_operand_is_visible (isa, opcode, opnd_cnt) == 0);
2012*3d8817e4Smiod 	}
2013*3d8817e4Smiod     }
2014*3d8817e4Smiod 
2015*3d8817e4Smiod   if (num_regs > 0 && ((int) next_reg != last_tok->X_add_number + 1))
2016*3d8817e4Smiod     goto err;
2017*3d8817e4Smiod 
2018*3d8817e4Smiod   insn->ntok = tok - insn->tok;
2019*3d8817e4Smiod   had_error = FALSE;
2020*3d8817e4Smiod 
2021*3d8817e4Smiod  err:
2022*3d8817e4Smiod   input_line_pointer = old_input_line_pointer;
2023*3d8817e4Smiod   return had_error;
2024*3d8817e4Smiod }
2025*3d8817e4Smiod 
2026*3d8817e4Smiod 
2027*3d8817e4Smiod static int
get_invisible_operands(TInsn * insn)2028*3d8817e4Smiod get_invisible_operands (TInsn *insn)
2029*3d8817e4Smiod {
2030*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
2031*3d8817e4Smiod   static xtensa_insnbuf slotbuf = NULL;
2032*3d8817e4Smiod   xtensa_format fmt;
2033*3d8817e4Smiod   xtensa_opcode opc = insn->opcode;
2034*3d8817e4Smiod   int slot, opnd, fmt_found;
2035*3d8817e4Smiod   unsigned val;
2036*3d8817e4Smiod 
2037*3d8817e4Smiod   if (!slotbuf)
2038*3d8817e4Smiod     slotbuf = xtensa_insnbuf_alloc (isa);
2039*3d8817e4Smiod 
2040*3d8817e4Smiod   /* Find format/slot where this can be encoded.  */
2041*3d8817e4Smiod   fmt_found = 0;
2042*3d8817e4Smiod   slot = 0;
2043*3d8817e4Smiod   for (fmt = 0; fmt < xtensa_isa_num_formats (isa); fmt++)
2044*3d8817e4Smiod     {
2045*3d8817e4Smiod       for (slot = 0; slot < xtensa_format_num_slots (isa, fmt); slot++)
2046*3d8817e4Smiod 	{
2047*3d8817e4Smiod 	  if (xtensa_opcode_encode (isa, fmt, slot, slotbuf, opc) == 0)
2048*3d8817e4Smiod 	    {
2049*3d8817e4Smiod 	      fmt_found = 1;
2050*3d8817e4Smiod 	      break;
2051*3d8817e4Smiod 	    }
2052*3d8817e4Smiod 	}
2053*3d8817e4Smiod       if (fmt_found) break;
2054*3d8817e4Smiod     }
2055*3d8817e4Smiod 
2056*3d8817e4Smiod   if (!fmt_found)
2057*3d8817e4Smiod     {
2058*3d8817e4Smiod       as_bad (_("cannot encode opcode \"%s\""), xtensa_opcode_name (isa, opc));
2059*3d8817e4Smiod       return -1;
2060*3d8817e4Smiod     }
2061*3d8817e4Smiod 
2062*3d8817e4Smiod   /* First encode all the visible operands
2063*3d8817e4Smiod      (to deal with shared field operands).  */
2064*3d8817e4Smiod   for (opnd = 0; opnd < insn->ntok; opnd++)
2065*3d8817e4Smiod     {
2066*3d8817e4Smiod       if (xtensa_operand_is_visible (isa, opc, opnd) == 1
2067*3d8817e4Smiod 	  && (insn->tok[opnd].X_op == O_register
2068*3d8817e4Smiod 	      || insn->tok[opnd].X_op == O_constant))
2069*3d8817e4Smiod 	{
2070*3d8817e4Smiod 	  val = insn->tok[opnd].X_add_number;
2071*3d8817e4Smiod 	  xtensa_operand_encode (isa, opc, opnd, &val);
2072*3d8817e4Smiod 	  xtensa_operand_set_field (isa, opc, opnd, fmt, slot, slotbuf, val);
2073*3d8817e4Smiod 	}
2074*3d8817e4Smiod     }
2075*3d8817e4Smiod 
2076*3d8817e4Smiod   /* Then pull out the values for the invisible ones.  */
2077*3d8817e4Smiod   for (opnd = 0; opnd < insn->ntok; opnd++)
2078*3d8817e4Smiod     {
2079*3d8817e4Smiod       if (xtensa_operand_is_visible (isa, opc, opnd) == 0)
2080*3d8817e4Smiod 	{
2081*3d8817e4Smiod 	  xtensa_operand_get_field (isa, opc, opnd, fmt, slot, slotbuf, &val);
2082*3d8817e4Smiod 	  xtensa_operand_decode (isa, opc, opnd, &val);
2083*3d8817e4Smiod 	  insn->tok[opnd].X_add_number = val;
2084*3d8817e4Smiod 	  if (xtensa_operand_is_register (isa, opc, opnd) == 1)
2085*3d8817e4Smiod 	    insn->tok[opnd].X_op = O_register;
2086*3d8817e4Smiod 	  else
2087*3d8817e4Smiod 	    insn->tok[opnd].X_op = O_constant;
2088*3d8817e4Smiod 	}
2089*3d8817e4Smiod     }
2090*3d8817e4Smiod 
2091*3d8817e4Smiod   return 0;
2092*3d8817e4Smiod }
2093*3d8817e4Smiod 
2094*3d8817e4Smiod 
2095*3d8817e4Smiod static void
xg_reverse_shift_count(char ** cnt_argp)2096*3d8817e4Smiod xg_reverse_shift_count (char **cnt_argp)
2097*3d8817e4Smiod {
2098*3d8817e4Smiod   char *cnt_arg, *new_arg;
2099*3d8817e4Smiod   cnt_arg = *cnt_argp;
2100*3d8817e4Smiod 
2101*3d8817e4Smiod   /* replace the argument with "31-(argument)" */
2102*3d8817e4Smiod   new_arg = (char *) xmalloc (strlen (cnt_arg) + 6);
2103*3d8817e4Smiod   sprintf (new_arg, "31-(%s)", cnt_arg);
2104*3d8817e4Smiod 
2105*3d8817e4Smiod   free (cnt_arg);
2106*3d8817e4Smiod   *cnt_argp = new_arg;
2107*3d8817e4Smiod }
2108*3d8817e4Smiod 
2109*3d8817e4Smiod 
2110*3d8817e4Smiod /* If "arg" is a constant expression, return non-zero with the value
2111*3d8817e4Smiod    in *valp.  */
2112*3d8817e4Smiod 
2113*3d8817e4Smiod static int
xg_arg_is_constant(char * arg,offsetT * valp)2114*3d8817e4Smiod xg_arg_is_constant (char *arg, offsetT *valp)
2115*3d8817e4Smiod {
2116*3d8817e4Smiod   expressionS exp;
2117*3d8817e4Smiod   char *save_ptr = input_line_pointer;
2118*3d8817e4Smiod 
2119*3d8817e4Smiod   input_line_pointer = arg;
2120*3d8817e4Smiod   expression (&exp);
2121*3d8817e4Smiod   input_line_pointer = save_ptr;
2122*3d8817e4Smiod 
2123*3d8817e4Smiod   if (exp.X_op == O_constant)
2124*3d8817e4Smiod     {
2125*3d8817e4Smiod       *valp = exp.X_add_number;
2126*3d8817e4Smiod       return 1;
2127*3d8817e4Smiod     }
2128*3d8817e4Smiod 
2129*3d8817e4Smiod   return 0;
2130*3d8817e4Smiod }
2131*3d8817e4Smiod 
2132*3d8817e4Smiod 
2133*3d8817e4Smiod static void
xg_replace_opname(char ** popname,char * newop)2134*3d8817e4Smiod xg_replace_opname (char **popname, char *newop)
2135*3d8817e4Smiod {
2136*3d8817e4Smiod   free (*popname);
2137*3d8817e4Smiod   *popname = (char *) xmalloc (strlen (newop) + 1);
2138*3d8817e4Smiod   strcpy (*popname, newop);
2139*3d8817e4Smiod }
2140*3d8817e4Smiod 
2141*3d8817e4Smiod 
2142*3d8817e4Smiod static int
xg_check_num_args(int * pnum_args,int expected_num,char * opname,char ** arg_strings)2143*3d8817e4Smiod xg_check_num_args (int *pnum_args,
2144*3d8817e4Smiod 		   int expected_num,
2145*3d8817e4Smiod 		   char *opname,
2146*3d8817e4Smiod 		   char **arg_strings)
2147*3d8817e4Smiod {
2148*3d8817e4Smiod   int num_args = *pnum_args;
2149*3d8817e4Smiod 
2150*3d8817e4Smiod   if (num_args < expected_num)
2151*3d8817e4Smiod     {
2152*3d8817e4Smiod       as_bad (_("not enough operands (%d) for '%s'; expected %d"),
2153*3d8817e4Smiod 	      num_args, opname, expected_num);
2154*3d8817e4Smiod       return -1;
2155*3d8817e4Smiod     }
2156*3d8817e4Smiod 
2157*3d8817e4Smiod   if (num_args > expected_num)
2158*3d8817e4Smiod     {
2159*3d8817e4Smiod       as_warn (_("too many operands (%d) for '%s'; expected %d"),
2160*3d8817e4Smiod 	       num_args, opname, expected_num);
2161*3d8817e4Smiod       while (num_args-- > expected_num)
2162*3d8817e4Smiod 	{
2163*3d8817e4Smiod 	  free (arg_strings[num_args]);
2164*3d8817e4Smiod 	  arg_strings[num_args] = 0;
2165*3d8817e4Smiod 	}
2166*3d8817e4Smiod       *pnum_args = expected_num;
2167*3d8817e4Smiod       return -1;
2168*3d8817e4Smiod     }
2169*3d8817e4Smiod 
2170*3d8817e4Smiod   return 0;
2171*3d8817e4Smiod }
2172*3d8817e4Smiod 
2173*3d8817e4Smiod 
2174*3d8817e4Smiod /* If the register is not specified as part of the opcode,
2175*3d8817e4Smiod    then get it from the operand and move it to the opcode.  */
2176*3d8817e4Smiod 
2177*3d8817e4Smiod static int
xg_translate_sysreg_op(char ** popname,int * pnum_args,char ** arg_strings)2178*3d8817e4Smiod xg_translate_sysreg_op (char **popname, int *pnum_args, char **arg_strings)
2179*3d8817e4Smiod {
2180*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
2181*3d8817e4Smiod   xtensa_sysreg sr;
2182*3d8817e4Smiod   char *opname, *new_opname;
2183*3d8817e4Smiod   const char *sr_name;
2184*3d8817e4Smiod   int is_user, is_write;
2185*3d8817e4Smiod 
2186*3d8817e4Smiod   opname = *popname;
2187*3d8817e4Smiod   if (*opname == '_')
2188*3d8817e4Smiod     opname += 1;
2189*3d8817e4Smiod   is_user = (opname[1] == 'u');
2190*3d8817e4Smiod   is_write = (opname[0] == 'w');
2191*3d8817e4Smiod 
2192*3d8817e4Smiod   /* Opname == [rw]ur or [rwx]sr... */
2193*3d8817e4Smiod 
2194*3d8817e4Smiod   if (xg_check_num_args (pnum_args, 2, opname, arg_strings))
2195*3d8817e4Smiod     return -1;
2196*3d8817e4Smiod 
2197*3d8817e4Smiod   /* Check if the argument is a symbolic register name.  */
2198*3d8817e4Smiod   sr = xtensa_sysreg_lookup_name (isa, arg_strings[1]);
2199*3d8817e4Smiod   /* Handle WSR to "INTSET" as a special case.  */
2200*3d8817e4Smiod   if (sr == XTENSA_UNDEFINED && is_write && !is_user
2201*3d8817e4Smiod       && !strcasecmp (arg_strings[1], "intset"))
2202*3d8817e4Smiod     sr = xtensa_sysreg_lookup_name (isa, "interrupt");
2203*3d8817e4Smiod   if (sr == XTENSA_UNDEFINED
2204*3d8817e4Smiod       || (xtensa_sysreg_is_user (isa, sr) == 1) != is_user)
2205*3d8817e4Smiod     {
2206*3d8817e4Smiod       /* Maybe it's a register number.... */
2207*3d8817e4Smiod       offsetT val;
2208*3d8817e4Smiod       if (!xg_arg_is_constant (arg_strings[1], &val))
2209*3d8817e4Smiod 	{
2210*3d8817e4Smiod 	  as_bad (_("invalid register '%s' for '%s' instruction"),
2211*3d8817e4Smiod 		  arg_strings[1], opname);
2212*3d8817e4Smiod 	  return -1;
2213*3d8817e4Smiod 	}
2214*3d8817e4Smiod       sr = xtensa_sysreg_lookup (isa, val, is_user);
2215*3d8817e4Smiod       if (sr == XTENSA_UNDEFINED)
2216*3d8817e4Smiod 	{
2217*3d8817e4Smiod 	  as_bad (_("invalid register number (%ld) for '%s' instruction"),
2218*3d8817e4Smiod 		  (long) val, opname);
2219*3d8817e4Smiod 	  return -1;
2220*3d8817e4Smiod 	}
2221*3d8817e4Smiod     }
2222*3d8817e4Smiod 
2223*3d8817e4Smiod   /* Remove the last argument, which is now part of the opcode.  */
2224*3d8817e4Smiod   free (arg_strings[1]);
2225*3d8817e4Smiod   arg_strings[1] = 0;
2226*3d8817e4Smiod   *pnum_args = 1;
2227*3d8817e4Smiod 
2228*3d8817e4Smiod   /* Translate the opcode.  */
2229*3d8817e4Smiod   sr_name = xtensa_sysreg_name (isa, sr);
2230*3d8817e4Smiod   /* Another special case for "WSR.INTSET"....  */
2231*3d8817e4Smiod   if (is_write && !is_user && !strcasecmp ("interrupt", sr_name))
2232*3d8817e4Smiod     sr_name = "intset";
2233*3d8817e4Smiod   new_opname = (char *) xmalloc (strlen (sr_name) + 6);
2234*3d8817e4Smiod   sprintf (new_opname, "%s.%s", *popname, sr_name);
2235*3d8817e4Smiod   free (*popname);
2236*3d8817e4Smiod   *popname = new_opname;
2237*3d8817e4Smiod 
2238*3d8817e4Smiod   return 0;
2239*3d8817e4Smiod }
2240*3d8817e4Smiod 
2241*3d8817e4Smiod 
2242*3d8817e4Smiod static int
xtensa_translate_old_userreg_ops(char ** popname)2243*3d8817e4Smiod xtensa_translate_old_userreg_ops (char **popname)
2244*3d8817e4Smiod {
2245*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
2246*3d8817e4Smiod   xtensa_sysreg sr;
2247*3d8817e4Smiod   char *opname, *new_opname;
2248*3d8817e4Smiod   const char *sr_name;
2249*3d8817e4Smiod   bfd_boolean has_underbar = FALSE;
2250*3d8817e4Smiod 
2251*3d8817e4Smiod   opname = *popname;
2252*3d8817e4Smiod   if (opname[0] == '_')
2253*3d8817e4Smiod     {
2254*3d8817e4Smiod       has_underbar = TRUE;
2255*3d8817e4Smiod       opname += 1;
2256*3d8817e4Smiod     }
2257*3d8817e4Smiod 
2258*3d8817e4Smiod   sr = xtensa_sysreg_lookup_name (isa, opname + 1);
2259*3d8817e4Smiod   if (sr != XTENSA_UNDEFINED)
2260*3d8817e4Smiod     {
2261*3d8817e4Smiod       /* The new default name ("nnn") is different from the old default
2262*3d8817e4Smiod 	 name ("URnnn").  The old default is handled below, and we don't
2263*3d8817e4Smiod 	 want to recognize [RW]nnn, so do nothing if the name is the (new)
2264*3d8817e4Smiod 	 default.  */
2265*3d8817e4Smiod       static char namebuf[10];
2266*3d8817e4Smiod       sprintf (namebuf, "%d", xtensa_sysreg_number (isa, sr));
2267*3d8817e4Smiod       if (strcmp (namebuf, opname + 1) == 0)
2268*3d8817e4Smiod 	return 0;
2269*3d8817e4Smiod     }
2270*3d8817e4Smiod   else
2271*3d8817e4Smiod     {
2272*3d8817e4Smiod       offsetT val;
2273*3d8817e4Smiod       char *end;
2274*3d8817e4Smiod 
2275*3d8817e4Smiod       /* Only continue if the reg name is "URnnn".  */
2276*3d8817e4Smiod       if (opname[1] != 'u' || opname[2] != 'r')
2277*3d8817e4Smiod 	return 0;
2278*3d8817e4Smiod       val = strtoul (opname + 3, &end, 10);
2279*3d8817e4Smiod       if (*end != '\0')
2280*3d8817e4Smiod 	return 0;
2281*3d8817e4Smiod 
2282*3d8817e4Smiod       sr = xtensa_sysreg_lookup (isa, val, 1);
2283*3d8817e4Smiod       if (sr == XTENSA_UNDEFINED)
2284*3d8817e4Smiod 	{
2285*3d8817e4Smiod 	  as_bad (_("invalid register number (%ld) for '%s'"),
2286*3d8817e4Smiod 		  (long) val, opname);
2287*3d8817e4Smiod 	  return -1;
2288*3d8817e4Smiod 	}
2289*3d8817e4Smiod     }
2290*3d8817e4Smiod 
2291*3d8817e4Smiod   /* Translate the opcode.  */
2292*3d8817e4Smiod   sr_name = xtensa_sysreg_name (isa, sr);
2293*3d8817e4Smiod   new_opname = (char *) xmalloc (strlen (sr_name) + 6);
2294*3d8817e4Smiod   sprintf (new_opname, "%s%cur.%s", (has_underbar ? "_" : ""),
2295*3d8817e4Smiod 	   opname[0], sr_name);
2296*3d8817e4Smiod   free (*popname);
2297*3d8817e4Smiod   *popname = new_opname;
2298*3d8817e4Smiod 
2299*3d8817e4Smiod   return 0;
2300*3d8817e4Smiod }
2301*3d8817e4Smiod 
2302*3d8817e4Smiod 
2303*3d8817e4Smiod static int
xtensa_translate_zero_immed(char * old_op,char * new_op,char ** popname,int * pnum_args,char ** arg_strings)2304*3d8817e4Smiod xtensa_translate_zero_immed (char *old_op,
2305*3d8817e4Smiod 			     char *new_op,
2306*3d8817e4Smiod 			     char **popname,
2307*3d8817e4Smiod 			     int *pnum_args,
2308*3d8817e4Smiod 			     char **arg_strings)
2309*3d8817e4Smiod {
2310*3d8817e4Smiod   char *opname;
2311*3d8817e4Smiod   offsetT val;
2312*3d8817e4Smiod 
2313*3d8817e4Smiod   opname = *popname;
2314*3d8817e4Smiod   assert (opname[0] != '_');
2315*3d8817e4Smiod 
2316*3d8817e4Smiod   if (strcmp (opname, old_op) != 0)
2317*3d8817e4Smiod     return 0;
2318*3d8817e4Smiod 
2319*3d8817e4Smiod   if (xg_check_num_args (pnum_args, 3, opname, arg_strings))
2320*3d8817e4Smiod     return -1;
2321*3d8817e4Smiod   if (xg_arg_is_constant (arg_strings[1], &val) && val == 0)
2322*3d8817e4Smiod     {
2323*3d8817e4Smiod       xg_replace_opname (popname, new_op);
2324*3d8817e4Smiod       free (arg_strings[1]);
2325*3d8817e4Smiod       arg_strings[1] = arg_strings[2];
2326*3d8817e4Smiod       arg_strings[2] = 0;
2327*3d8817e4Smiod       *pnum_args = 2;
2328*3d8817e4Smiod     }
2329*3d8817e4Smiod 
2330*3d8817e4Smiod   return 0;
2331*3d8817e4Smiod }
2332*3d8817e4Smiod 
2333*3d8817e4Smiod 
2334*3d8817e4Smiod /* If the instruction is an idiom (i.e., a built-in macro), translate it.
2335*3d8817e4Smiod    Returns non-zero if an error was found.  */
2336*3d8817e4Smiod 
2337*3d8817e4Smiod static int
xg_translate_idioms(char ** popname,int * pnum_args,char ** arg_strings)2338*3d8817e4Smiod xg_translate_idioms (char **popname, int *pnum_args, char **arg_strings)
2339*3d8817e4Smiod {
2340*3d8817e4Smiod   char *opname = *popname;
2341*3d8817e4Smiod   bfd_boolean has_underbar = FALSE;
2342*3d8817e4Smiod 
2343*3d8817e4Smiod   if (cur_vinsn.inside_bundle)
2344*3d8817e4Smiod     return 0;
2345*3d8817e4Smiod 
2346*3d8817e4Smiod   if (*opname == '_')
2347*3d8817e4Smiod     {
2348*3d8817e4Smiod       has_underbar = TRUE;
2349*3d8817e4Smiod       opname += 1;
2350*3d8817e4Smiod     }
2351*3d8817e4Smiod 
2352*3d8817e4Smiod   if (strcmp (opname, "mov") == 0)
2353*3d8817e4Smiod     {
2354*3d8817e4Smiod       if (use_transform () && !has_underbar && density_supported)
2355*3d8817e4Smiod 	xg_replace_opname (popname, "mov.n");
2356*3d8817e4Smiod       else
2357*3d8817e4Smiod 	{
2358*3d8817e4Smiod 	  if (xg_check_num_args (pnum_args, 2, opname, arg_strings))
2359*3d8817e4Smiod 	    return -1;
2360*3d8817e4Smiod 	  xg_replace_opname (popname, (has_underbar ? "_or" : "or"));
2361*3d8817e4Smiod 	  arg_strings[2] = (char *) xmalloc (strlen (arg_strings[1]) + 1);
2362*3d8817e4Smiod 	  strcpy (arg_strings[2], arg_strings[1]);
2363*3d8817e4Smiod 	  *pnum_args = 3;
2364*3d8817e4Smiod 	}
2365*3d8817e4Smiod       return 0;
2366*3d8817e4Smiod     }
2367*3d8817e4Smiod 
2368*3d8817e4Smiod   if (strcmp (opname, "bbsi.l") == 0)
2369*3d8817e4Smiod     {
2370*3d8817e4Smiod       if (xg_check_num_args (pnum_args, 3, opname, arg_strings))
2371*3d8817e4Smiod 	return -1;
2372*3d8817e4Smiod       xg_replace_opname (popname, (has_underbar ? "_bbsi" : "bbsi"));
2373*3d8817e4Smiod       if (target_big_endian)
2374*3d8817e4Smiod 	xg_reverse_shift_count (&arg_strings[1]);
2375*3d8817e4Smiod       return 0;
2376*3d8817e4Smiod     }
2377*3d8817e4Smiod 
2378*3d8817e4Smiod   if (strcmp (opname, "bbci.l") == 0)
2379*3d8817e4Smiod     {
2380*3d8817e4Smiod       if (xg_check_num_args (pnum_args, 3, opname, arg_strings))
2381*3d8817e4Smiod 	return -1;
2382*3d8817e4Smiod       xg_replace_opname (popname, (has_underbar ? "_bbci" : "bbci"));
2383*3d8817e4Smiod       if (target_big_endian)
2384*3d8817e4Smiod 	xg_reverse_shift_count (&arg_strings[1]);
2385*3d8817e4Smiod       return 0;
2386*3d8817e4Smiod     }
2387*3d8817e4Smiod 
2388*3d8817e4Smiod   if (xtensa_nop_opcode == XTENSA_UNDEFINED
2389*3d8817e4Smiod       && strcmp (opname, "nop") == 0)
2390*3d8817e4Smiod     {
2391*3d8817e4Smiod       if (use_transform () && !has_underbar && density_supported)
2392*3d8817e4Smiod 	xg_replace_opname (popname, "nop.n");
2393*3d8817e4Smiod       else
2394*3d8817e4Smiod 	{
2395*3d8817e4Smiod 	  if (xg_check_num_args (pnum_args, 0, opname, arg_strings))
2396*3d8817e4Smiod 	    return -1;
2397*3d8817e4Smiod 	  xg_replace_opname (popname, (has_underbar ? "_or" : "or"));
2398*3d8817e4Smiod 	  arg_strings[0] = (char *) xmalloc (3);
2399*3d8817e4Smiod 	  arg_strings[1] = (char *) xmalloc (3);
2400*3d8817e4Smiod 	  arg_strings[2] = (char *) xmalloc (3);
2401*3d8817e4Smiod 	  strcpy (arg_strings[0], "a1");
2402*3d8817e4Smiod 	  strcpy (arg_strings[1], "a1");
2403*3d8817e4Smiod 	  strcpy (arg_strings[2], "a1");
2404*3d8817e4Smiod 	  *pnum_args = 3;
2405*3d8817e4Smiod 	}
2406*3d8817e4Smiod       return 0;
2407*3d8817e4Smiod     }
2408*3d8817e4Smiod 
2409*3d8817e4Smiod   /* Recognize [RW]UR and [RWX]SR.  */
2410*3d8817e4Smiod   if ((((opname[0] == 'r' || opname[0] == 'w')
2411*3d8817e4Smiod 	&& (opname[1] == 'u' || opname[1] == 's'))
2412*3d8817e4Smiod        || (opname[0] == 'x' && opname[1] == 's'))
2413*3d8817e4Smiod       && opname[2] == 'r'
2414*3d8817e4Smiod       && opname[3] == '\0')
2415*3d8817e4Smiod     return xg_translate_sysreg_op (popname, pnum_args, arg_strings);
2416*3d8817e4Smiod 
2417*3d8817e4Smiod   /* Backward compatibility for RUR and WUR: Recognize [RW]UR<nnn> and
2418*3d8817e4Smiod      [RW]<name> if <name> is the non-default name of a user register.  */
2419*3d8817e4Smiod   if ((opname[0] == 'r' || opname[0] == 'w')
2420*3d8817e4Smiod       && xtensa_opcode_lookup (xtensa_default_isa, opname) == XTENSA_UNDEFINED)
2421*3d8817e4Smiod     return xtensa_translate_old_userreg_ops (popname);
2422*3d8817e4Smiod 
2423*3d8817e4Smiod   /* Relax branches that don't allow comparisons against an immediate value
2424*3d8817e4Smiod      of zero to the corresponding branches with implicit zero immediates.  */
2425*3d8817e4Smiod   if (!has_underbar && use_transform ())
2426*3d8817e4Smiod     {
2427*3d8817e4Smiod       if (xtensa_translate_zero_immed ("bnei", "bnez", popname,
2428*3d8817e4Smiod 				       pnum_args, arg_strings))
2429*3d8817e4Smiod 	return -1;
2430*3d8817e4Smiod 
2431*3d8817e4Smiod       if (xtensa_translate_zero_immed ("beqi", "beqz", popname,
2432*3d8817e4Smiod 				       pnum_args, arg_strings))
2433*3d8817e4Smiod 	return -1;
2434*3d8817e4Smiod 
2435*3d8817e4Smiod       if (xtensa_translate_zero_immed ("bgei", "bgez", popname,
2436*3d8817e4Smiod 				       pnum_args, arg_strings))
2437*3d8817e4Smiod 	return -1;
2438*3d8817e4Smiod 
2439*3d8817e4Smiod       if (xtensa_translate_zero_immed ("blti", "bltz", popname,
2440*3d8817e4Smiod 				       pnum_args, arg_strings))
2441*3d8817e4Smiod 	return -1;
2442*3d8817e4Smiod     }
2443*3d8817e4Smiod 
2444*3d8817e4Smiod   return 0;
2445*3d8817e4Smiod }
2446*3d8817e4Smiod 
2447*3d8817e4Smiod 
2448*3d8817e4Smiod /* Functions for dealing with the Xtensa ISA.  */
2449*3d8817e4Smiod 
2450*3d8817e4Smiod /* Currently the assembler only allows us to use a single target per
2451*3d8817e4Smiod    fragment.  Because of this, only one operand for a given
2452*3d8817e4Smiod    instruction may be symbolic.  If there is a PC-relative operand,
2453*3d8817e4Smiod    the last one is chosen.  Otherwise, the result is the number of the
2454*3d8817e4Smiod    last immediate operand, and if there are none of those, we fail and
2455*3d8817e4Smiod    return -1.  */
2456*3d8817e4Smiod 
2457*3d8817e4Smiod static int
get_relaxable_immed(xtensa_opcode opcode)2458*3d8817e4Smiod get_relaxable_immed (xtensa_opcode opcode)
2459*3d8817e4Smiod {
2460*3d8817e4Smiod   int last_immed = -1;
2461*3d8817e4Smiod   int noperands, opi;
2462*3d8817e4Smiod 
2463*3d8817e4Smiod   if (opcode == XTENSA_UNDEFINED)
2464*3d8817e4Smiod     return -1;
2465*3d8817e4Smiod 
2466*3d8817e4Smiod   noperands = xtensa_opcode_num_operands (xtensa_default_isa, opcode);
2467*3d8817e4Smiod   for (opi = noperands - 1; opi >= 0; opi--)
2468*3d8817e4Smiod     {
2469*3d8817e4Smiod       if (xtensa_operand_is_visible (xtensa_default_isa, opcode, opi) == 0)
2470*3d8817e4Smiod 	continue;
2471*3d8817e4Smiod       if (xtensa_operand_is_PCrelative (xtensa_default_isa, opcode, opi) == 1)
2472*3d8817e4Smiod 	return opi;
2473*3d8817e4Smiod       if (last_immed == -1
2474*3d8817e4Smiod 	  && xtensa_operand_is_register (xtensa_default_isa, opcode, opi) == 0)
2475*3d8817e4Smiod 	last_immed = opi;
2476*3d8817e4Smiod     }
2477*3d8817e4Smiod   return last_immed;
2478*3d8817e4Smiod }
2479*3d8817e4Smiod 
2480*3d8817e4Smiod 
2481*3d8817e4Smiod static xtensa_opcode
get_opcode_from_buf(const char * buf,int slot)2482*3d8817e4Smiod get_opcode_from_buf (const char *buf, int slot)
2483*3d8817e4Smiod {
2484*3d8817e4Smiod   static xtensa_insnbuf insnbuf = NULL;
2485*3d8817e4Smiod   static xtensa_insnbuf slotbuf = NULL;
2486*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
2487*3d8817e4Smiod   xtensa_format fmt;
2488*3d8817e4Smiod 
2489*3d8817e4Smiod   if (!insnbuf)
2490*3d8817e4Smiod     {
2491*3d8817e4Smiod       insnbuf = xtensa_insnbuf_alloc (isa);
2492*3d8817e4Smiod       slotbuf = xtensa_insnbuf_alloc (isa);
2493*3d8817e4Smiod     }
2494*3d8817e4Smiod 
2495*3d8817e4Smiod   xtensa_insnbuf_from_chars (isa, insnbuf, (const unsigned char *) buf, 0);
2496*3d8817e4Smiod   fmt = xtensa_format_decode (isa, insnbuf);
2497*3d8817e4Smiod   if (fmt == XTENSA_UNDEFINED)
2498*3d8817e4Smiod     return XTENSA_UNDEFINED;
2499*3d8817e4Smiod 
2500*3d8817e4Smiod   if (slot >= xtensa_format_num_slots (isa, fmt))
2501*3d8817e4Smiod     return XTENSA_UNDEFINED;
2502*3d8817e4Smiod 
2503*3d8817e4Smiod   xtensa_format_get_slot (isa, fmt, slot, insnbuf, slotbuf);
2504*3d8817e4Smiod   return xtensa_opcode_decode (isa, fmt, slot, slotbuf);
2505*3d8817e4Smiod }
2506*3d8817e4Smiod 
2507*3d8817e4Smiod 
2508*3d8817e4Smiod #ifdef TENSILICA_DEBUG
2509*3d8817e4Smiod 
2510*3d8817e4Smiod /* For debugging, print out the mapping of opcode numbers to opcodes.  */
2511*3d8817e4Smiod 
2512*3d8817e4Smiod static void
xtensa_print_insn_table(void)2513*3d8817e4Smiod xtensa_print_insn_table (void)
2514*3d8817e4Smiod {
2515*3d8817e4Smiod   int num_opcodes, num_operands;
2516*3d8817e4Smiod   xtensa_opcode opcode;
2517*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
2518*3d8817e4Smiod 
2519*3d8817e4Smiod   num_opcodes = xtensa_isa_num_opcodes (xtensa_default_isa);
2520*3d8817e4Smiod   for (opcode = 0; opcode < num_opcodes; opcode++)
2521*3d8817e4Smiod     {
2522*3d8817e4Smiod       int opn;
2523*3d8817e4Smiod       fprintf (stderr, "%d: %s: ", opcode, xtensa_opcode_name (isa, opcode));
2524*3d8817e4Smiod       num_operands = xtensa_opcode_num_operands (isa, opcode);
2525*3d8817e4Smiod       for (opn = 0; opn < num_operands; opn++)
2526*3d8817e4Smiod 	{
2527*3d8817e4Smiod 	  if (xtensa_operand_is_visible (isa, opcode, opn) == 0)
2528*3d8817e4Smiod 	    continue;
2529*3d8817e4Smiod 	  if (xtensa_operand_is_register (isa, opcode, opn) == 1)
2530*3d8817e4Smiod 	    {
2531*3d8817e4Smiod 	      xtensa_regfile opnd_rf =
2532*3d8817e4Smiod 		xtensa_operand_regfile (isa, opcode, opn);
2533*3d8817e4Smiod 	      fprintf (stderr, "%s ", xtensa_regfile_shortname (isa, opnd_rf));
2534*3d8817e4Smiod 	    }
2535*3d8817e4Smiod 	  else if (xtensa_operand_is_PCrelative (isa, opcode, opn) == 1)
2536*3d8817e4Smiod 	    fputs ("[lLr] ", stderr);
2537*3d8817e4Smiod 	  else
2538*3d8817e4Smiod 	    fputs ("i ", stderr);
2539*3d8817e4Smiod 	}
2540*3d8817e4Smiod       fprintf (stderr, "\n");
2541*3d8817e4Smiod     }
2542*3d8817e4Smiod }
2543*3d8817e4Smiod 
2544*3d8817e4Smiod 
2545*3d8817e4Smiod static void
print_vliw_insn(xtensa_insnbuf vbuf)2546*3d8817e4Smiod print_vliw_insn (xtensa_insnbuf vbuf)
2547*3d8817e4Smiod {
2548*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
2549*3d8817e4Smiod   xtensa_format f = xtensa_format_decode (isa, vbuf);
2550*3d8817e4Smiod   xtensa_insnbuf sbuf = xtensa_insnbuf_alloc (isa);
2551*3d8817e4Smiod   int op;
2552*3d8817e4Smiod 
2553*3d8817e4Smiod   fprintf (stderr, "format = %d\n", f);
2554*3d8817e4Smiod 
2555*3d8817e4Smiod   for (op = 0; op < xtensa_format_num_slots (isa, f); op++)
2556*3d8817e4Smiod     {
2557*3d8817e4Smiod       xtensa_opcode opcode;
2558*3d8817e4Smiod       const char *opname;
2559*3d8817e4Smiod       int operands;
2560*3d8817e4Smiod 
2561*3d8817e4Smiod       xtensa_format_get_slot (isa, f, op, vbuf, sbuf);
2562*3d8817e4Smiod       opcode = xtensa_opcode_decode (isa, f, op, sbuf);
2563*3d8817e4Smiod       opname = xtensa_opcode_name (isa, opcode);
2564*3d8817e4Smiod 
2565*3d8817e4Smiod       fprintf (stderr, "op in slot %i is %s;\n", op, opname);
2566*3d8817e4Smiod       fprintf (stderr, "   operands = ");
2567*3d8817e4Smiod       for (operands = 0;
2568*3d8817e4Smiod 	   operands < xtensa_opcode_num_operands (isa, opcode);
2569*3d8817e4Smiod 	   operands++)
2570*3d8817e4Smiod 	{
2571*3d8817e4Smiod 	  unsigned int val;
2572*3d8817e4Smiod 	  if (xtensa_operand_is_visible (isa, opcode, operands) == 0)
2573*3d8817e4Smiod 	    continue;
2574*3d8817e4Smiod 	  xtensa_operand_get_field (isa, opcode, operands, f, op, sbuf, &val);
2575*3d8817e4Smiod 	  xtensa_operand_decode (isa, opcode, operands, &val);
2576*3d8817e4Smiod 	  fprintf (stderr, "%d ", val);
2577*3d8817e4Smiod 	}
2578*3d8817e4Smiod       fprintf (stderr, "\n");
2579*3d8817e4Smiod     }
2580*3d8817e4Smiod   xtensa_insnbuf_free (isa, sbuf);
2581*3d8817e4Smiod }
2582*3d8817e4Smiod 
2583*3d8817e4Smiod #endif /* TENSILICA_DEBUG */
2584*3d8817e4Smiod 
2585*3d8817e4Smiod 
2586*3d8817e4Smiod static bfd_boolean
is_direct_call_opcode(xtensa_opcode opcode)2587*3d8817e4Smiod is_direct_call_opcode (xtensa_opcode opcode)
2588*3d8817e4Smiod {
2589*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
2590*3d8817e4Smiod   int n, num_operands;
2591*3d8817e4Smiod 
2592*3d8817e4Smiod   if (xtensa_opcode_is_call (isa, opcode) == 0)
2593*3d8817e4Smiod     return FALSE;
2594*3d8817e4Smiod 
2595*3d8817e4Smiod   num_operands = xtensa_opcode_num_operands (isa, opcode);
2596*3d8817e4Smiod   for (n = 0; n < num_operands; n++)
2597*3d8817e4Smiod     {
2598*3d8817e4Smiod       if (xtensa_operand_is_register (isa, opcode, n) == 0
2599*3d8817e4Smiod 	  && xtensa_operand_is_PCrelative (isa, opcode, n) == 1)
2600*3d8817e4Smiod 	return TRUE;
2601*3d8817e4Smiod     }
2602*3d8817e4Smiod   return FALSE;
2603*3d8817e4Smiod }
2604*3d8817e4Smiod 
2605*3d8817e4Smiod 
2606*3d8817e4Smiod /* Convert from BFD relocation type code to slot and operand number.
2607*3d8817e4Smiod    Returns non-zero on failure.  */
2608*3d8817e4Smiod 
2609*3d8817e4Smiod static int
decode_reloc(bfd_reloc_code_real_type reloc,int * slot,bfd_boolean * is_alt)2610*3d8817e4Smiod decode_reloc (bfd_reloc_code_real_type reloc, int *slot, bfd_boolean *is_alt)
2611*3d8817e4Smiod {
2612*3d8817e4Smiod   if (reloc >= BFD_RELOC_XTENSA_SLOT0_OP
2613*3d8817e4Smiod       && reloc <= BFD_RELOC_XTENSA_SLOT14_OP)
2614*3d8817e4Smiod     {
2615*3d8817e4Smiod       *slot = reloc - BFD_RELOC_XTENSA_SLOT0_OP;
2616*3d8817e4Smiod       *is_alt = FALSE;
2617*3d8817e4Smiod     }
2618*3d8817e4Smiod   else if (reloc >= BFD_RELOC_XTENSA_SLOT0_ALT
2619*3d8817e4Smiod       && reloc <= BFD_RELOC_XTENSA_SLOT14_ALT)
2620*3d8817e4Smiod     {
2621*3d8817e4Smiod       *slot = reloc - BFD_RELOC_XTENSA_SLOT0_ALT;
2622*3d8817e4Smiod       *is_alt = TRUE;
2623*3d8817e4Smiod     }
2624*3d8817e4Smiod   else
2625*3d8817e4Smiod     return -1;
2626*3d8817e4Smiod 
2627*3d8817e4Smiod   return 0;
2628*3d8817e4Smiod }
2629*3d8817e4Smiod 
2630*3d8817e4Smiod 
2631*3d8817e4Smiod /* Convert from slot number to BFD relocation type code for the
2632*3d8817e4Smiod    standard PC-relative relocations.  Return BFD_RELOC_NONE on
2633*3d8817e4Smiod    failure.  */
2634*3d8817e4Smiod 
2635*3d8817e4Smiod static bfd_reloc_code_real_type
encode_reloc(int slot)2636*3d8817e4Smiod encode_reloc (int slot)
2637*3d8817e4Smiod {
2638*3d8817e4Smiod   if (slot < 0 || slot > 14)
2639*3d8817e4Smiod     return BFD_RELOC_NONE;
2640*3d8817e4Smiod 
2641*3d8817e4Smiod   return BFD_RELOC_XTENSA_SLOT0_OP + slot;
2642*3d8817e4Smiod }
2643*3d8817e4Smiod 
2644*3d8817e4Smiod 
2645*3d8817e4Smiod /* Convert from slot numbers to BFD relocation type code for the
2646*3d8817e4Smiod    "alternate" relocations.  Return BFD_RELOC_NONE on failure.  */
2647*3d8817e4Smiod 
2648*3d8817e4Smiod static bfd_reloc_code_real_type
encode_alt_reloc(int slot)2649*3d8817e4Smiod encode_alt_reloc (int slot)
2650*3d8817e4Smiod {
2651*3d8817e4Smiod   if (slot < 0 || slot > 14)
2652*3d8817e4Smiod     return BFD_RELOC_NONE;
2653*3d8817e4Smiod 
2654*3d8817e4Smiod   return BFD_RELOC_XTENSA_SLOT0_ALT + slot;
2655*3d8817e4Smiod }
2656*3d8817e4Smiod 
2657*3d8817e4Smiod 
2658*3d8817e4Smiod static void
xtensa_insnbuf_set_operand(xtensa_insnbuf slotbuf,xtensa_format fmt,int slot,xtensa_opcode opcode,int operand,uint32 value,const char * file,unsigned int line)2659*3d8817e4Smiod xtensa_insnbuf_set_operand (xtensa_insnbuf slotbuf,
2660*3d8817e4Smiod 			    xtensa_format fmt,
2661*3d8817e4Smiod 			    int slot,
2662*3d8817e4Smiod 			    xtensa_opcode opcode,
2663*3d8817e4Smiod 			    int operand,
2664*3d8817e4Smiod 			    uint32 value,
2665*3d8817e4Smiod 			    const char *file,
2666*3d8817e4Smiod 			    unsigned int line)
2667*3d8817e4Smiod {
2668*3d8817e4Smiod   uint32 valbuf = value;
2669*3d8817e4Smiod 
2670*3d8817e4Smiod   if (xtensa_operand_encode (xtensa_default_isa, opcode, operand, &valbuf))
2671*3d8817e4Smiod     {
2672*3d8817e4Smiod       if (xtensa_operand_is_PCrelative (xtensa_default_isa, opcode, operand)
2673*3d8817e4Smiod 	  == 1)
2674*3d8817e4Smiod 	as_bad_where ((char *) file, line,
2675*3d8817e4Smiod 		      _("operand %d of '%s' has out of range value '%u'"),
2676*3d8817e4Smiod 		      operand + 1,
2677*3d8817e4Smiod 		      xtensa_opcode_name (xtensa_default_isa, opcode),
2678*3d8817e4Smiod 		      value);
2679*3d8817e4Smiod       else
2680*3d8817e4Smiod 	as_bad_where ((char *) file, line,
2681*3d8817e4Smiod 		      _("operand %d of '%s' has invalid value '%u'"),
2682*3d8817e4Smiod 		      operand + 1,
2683*3d8817e4Smiod 		      xtensa_opcode_name (xtensa_default_isa, opcode),
2684*3d8817e4Smiod 		      value);
2685*3d8817e4Smiod       return;
2686*3d8817e4Smiod     }
2687*3d8817e4Smiod 
2688*3d8817e4Smiod   xtensa_operand_set_field (xtensa_default_isa, opcode, operand, fmt, slot,
2689*3d8817e4Smiod 			    slotbuf, valbuf);
2690*3d8817e4Smiod }
2691*3d8817e4Smiod 
2692*3d8817e4Smiod 
2693*3d8817e4Smiod static uint32
xtensa_insnbuf_get_operand(xtensa_insnbuf slotbuf,xtensa_format fmt,int slot,xtensa_opcode opcode,int opnum)2694*3d8817e4Smiod xtensa_insnbuf_get_operand (xtensa_insnbuf slotbuf,
2695*3d8817e4Smiod 			    xtensa_format fmt,
2696*3d8817e4Smiod 			    int slot,
2697*3d8817e4Smiod 			    xtensa_opcode opcode,
2698*3d8817e4Smiod 			    int opnum)
2699*3d8817e4Smiod {
2700*3d8817e4Smiod   uint32 val = 0;
2701*3d8817e4Smiod   (void) xtensa_operand_get_field (xtensa_default_isa, opcode, opnum,
2702*3d8817e4Smiod 				   fmt, slot, slotbuf, &val);
2703*3d8817e4Smiod   (void) xtensa_operand_decode (xtensa_default_isa, opcode, opnum, &val);
2704*3d8817e4Smiod   return val;
2705*3d8817e4Smiod }
2706*3d8817e4Smiod 
2707*3d8817e4Smiod 
2708*3d8817e4Smiod /* Checks for rules from xtensa-relax tables.  */
2709*3d8817e4Smiod 
2710*3d8817e4Smiod /* The routine xg_instruction_matches_option_term must return TRUE
2711*3d8817e4Smiod    when a given option term is true.  The meaning of all of the option
2712*3d8817e4Smiod    terms is given interpretation by this function.  This is needed when
2713*3d8817e4Smiod    an option depends on the state of a directive, but there are no such
2714*3d8817e4Smiod    options in use right now.  */
2715*3d8817e4Smiod 
2716*3d8817e4Smiod static bfd_boolean
xg_instruction_matches_option_term(TInsn * insn ATTRIBUTE_UNUSED,const ReqOrOption * option)2717*3d8817e4Smiod xg_instruction_matches_option_term (TInsn *insn ATTRIBUTE_UNUSED,
2718*3d8817e4Smiod 				    const ReqOrOption *option)
2719*3d8817e4Smiod {
2720*3d8817e4Smiod   if (strcmp (option->option_name, "realnop") == 0
2721*3d8817e4Smiod       || strncmp (option->option_name, "IsaUse", 6) == 0)
2722*3d8817e4Smiod     {
2723*3d8817e4Smiod       /* These conditions were evaluated statically when building the
2724*3d8817e4Smiod 	 relaxation table.  There's no need to reevaluate them now.  */
2725*3d8817e4Smiod       return TRUE;
2726*3d8817e4Smiod     }
2727*3d8817e4Smiod   else
2728*3d8817e4Smiod     {
2729*3d8817e4Smiod       as_fatal (_("internal error: unknown option name '%s'"),
2730*3d8817e4Smiod 		option->option_name);
2731*3d8817e4Smiod     }
2732*3d8817e4Smiod }
2733*3d8817e4Smiod 
2734*3d8817e4Smiod 
2735*3d8817e4Smiod static bfd_boolean
xg_instruction_matches_or_options(TInsn * insn,const ReqOrOptionList * or_option)2736*3d8817e4Smiod xg_instruction_matches_or_options (TInsn *insn,
2737*3d8817e4Smiod 				   const ReqOrOptionList *or_option)
2738*3d8817e4Smiod {
2739*3d8817e4Smiod   const ReqOrOption *option;
2740*3d8817e4Smiod   /* Must match each of the AND terms.  */
2741*3d8817e4Smiod   for (option = or_option; option != NULL; option = option->next)
2742*3d8817e4Smiod     {
2743*3d8817e4Smiod       if (xg_instruction_matches_option_term (insn, option))
2744*3d8817e4Smiod 	return TRUE;
2745*3d8817e4Smiod     }
2746*3d8817e4Smiod   return FALSE;
2747*3d8817e4Smiod }
2748*3d8817e4Smiod 
2749*3d8817e4Smiod 
2750*3d8817e4Smiod static bfd_boolean
xg_instruction_matches_options(TInsn * insn,const ReqOptionList * options)2751*3d8817e4Smiod xg_instruction_matches_options (TInsn *insn, const ReqOptionList *options)
2752*3d8817e4Smiod {
2753*3d8817e4Smiod   const ReqOption *req_options;
2754*3d8817e4Smiod   /* Must match each of the AND terms.  */
2755*3d8817e4Smiod   for (req_options = options;
2756*3d8817e4Smiod        req_options != NULL;
2757*3d8817e4Smiod        req_options = req_options->next)
2758*3d8817e4Smiod     {
2759*3d8817e4Smiod       /* Must match one of the OR clauses.  */
2760*3d8817e4Smiod       if (!xg_instruction_matches_or_options (insn,
2761*3d8817e4Smiod 					      req_options->or_option_terms))
2762*3d8817e4Smiod 	return FALSE;
2763*3d8817e4Smiod     }
2764*3d8817e4Smiod   return TRUE;
2765*3d8817e4Smiod }
2766*3d8817e4Smiod 
2767*3d8817e4Smiod 
2768*3d8817e4Smiod /* Return the transition rule that matches or NULL if none matches.  */
2769*3d8817e4Smiod 
2770*3d8817e4Smiod static bfd_boolean
xg_instruction_matches_rule(TInsn * insn,TransitionRule * rule)2771*3d8817e4Smiod xg_instruction_matches_rule (TInsn *insn, TransitionRule *rule)
2772*3d8817e4Smiod {
2773*3d8817e4Smiod   PreconditionList *condition_l;
2774*3d8817e4Smiod 
2775*3d8817e4Smiod   if (rule->opcode != insn->opcode)
2776*3d8817e4Smiod     return FALSE;
2777*3d8817e4Smiod 
2778*3d8817e4Smiod   for (condition_l = rule->conditions;
2779*3d8817e4Smiod        condition_l != NULL;
2780*3d8817e4Smiod        condition_l = condition_l->next)
2781*3d8817e4Smiod     {
2782*3d8817e4Smiod       expressionS *exp1;
2783*3d8817e4Smiod       expressionS *exp2;
2784*3d8817e4Smiod       Precondition *cond = condition_l->precond;
2785*3d8817e4Smiod 
2786*3d8817e4Smiod       switch (cond->typ)
2787*3d8817e4Smiod 	{
2788*3d8817e4Smiod 	case OP_CONSTANT:
2789*3d8817e4Smiod 	  /* The expression must be the constant.  */
2790*3d8817e4Smiod 	  assert (cond->op_num < insn->ntok);
2791*3d8817e4Smiod 	  exp1 = &insn->tok[cond->op_num];
2792*3d8817e4Smiod 	  if (expr_is_const (exp1))
2793*3d8817e4Smiod 	    {
2794*3d8817e4Smiod 	      switch (cond->cmp)
2795*3d8817e4Smiod 		{
2796*3d8817e4Smiod 		case OP_EQUAL:
2797*3d8817e4Smiod 		  if (get_expr_const (exp1) != cond->op_data)
2798*3d8817e4Smiod 		    return FALSE;
2799*3d8817e4Smiod 		  break;
2800*3d8817e4Smiod 		case OP_NOTEQUAL:
2801*3d8817e4Smiod 		  if (get_expr_const (exp1) == cond->op_data)
2802*3d8817e4Smiod 		    return FALSE;
2803*3d8817e4Smiod 		  break;
2804*3d8817e4Smiod 		default:
2805*3d8817e4Smiod 		  return FALSE;
2806*3d8817e4Smiod 		}
2807*3d8817e4Smiod 	    }
2808*3d8817e4Smiod 	  else if (expr_is_register (exp1))
2809*3d8817e4Smiod 	    {
2810*3d8817e4Smiod 	      switch (cond->cmp)
2811*3d8817e4Smiod 		{
2812*3d8817e4Smiod 		case OP_EQUAL:
2813*3d8817e4Smiod 		  if (get_expr_register (exp1) != cond->op_data)
2814*3d8817e4Smiod 		    return FALSE;
2815*3d8817e4Smiod 		  break;
2816*3d8817e4Smiod 		case OP_NOTEQUAL:
2817*3d8817e4Smiod 		  if (get_expr_register (exp1) == cond->op_data)
2818*3d8817e4Smiod 		    return FALSE;
2819*3d8817e4Smiod 		  break;
2820*3d8817e4Smiod 		default:
2821*3d8817e4Smiod 		  return FALSE;
2822*3d8817e4Smiod 		}
2823*3d8817e4Smiod 	    }
2824*3d8817e4Smiod 	  else
2825*3d8817e4Smiod 	    return FALSE;
2826*3d8817e4Smiod 	  break;
2827*3d8817e4Smiod 
2828*3d8817e4Smiod 	case OP_OPERAND:
2829*3d8817e4Smiod 	  assert (cond->op_num < insn->ntok);
2830*3d8817e4Smiod 	  assert (cond->op_data < insn->ntok);
2831*3d8817e4Smiod 	  exp1 = &insn->tok[cond->op_num];
2832*3d8817e4Smiod 	  exp2 = &insn->tok[cond->op_data];
2833*3d8817e4Smiod 
2834*3d8817e4Smiod 	  switch (cond->cmp)
2835*3d8817e4Smiod 	    {
2836*3d8817e4Smiod 	    case OP_EQUAL:
2837*3d8817e4Smiod 	      if (!expr_is_equal (exp1, exp2))
2838*3d8817e4Smiod 		return FALSE;
2839*3d8817e4Smiod 	      break;
2840*3d8817e4Smiod 	    case OP_NOTEQUAL:
2841*3d8817e4Smiod 	      if (expr_is_equal (exp1, exp2))
2842*3d8817e4Smiod 		return FALSE;
2843*3d8817e4Smiod 	      break;
2844*3d8817e4Smiod 	    }
2845*3d8817e4Smiod 	  break;
2846*3d8817e4Smiod 
2847*3d8817e4Smiod 	case OP_LITERAL:
2848*3d8817e4Smiod 	case OP_LABEL:
2849*3d8817e4Smiod 	default:
2850*3d8817e4Smiod 	  return FALSE;
2851*3d8817e4Smiod 	}
2852*3d8817e4Smiod     }
2853*3d8817e4Smiod   if (!xg_instruction_matches_options (insn, rule->options))
2854*3d8817e4Smiod     return FALSE;
2855*3d8817e4Smiod 
2856*3d8817e4Smiod   return TRUE;
2857*3d8817e4Smiod }
2858*3d8817e4Smiod 
2859*3d8817e4Smiod 
2860*3d8817e4Smiod static int
transition_rule_cmp(const TransitionRule * a,const TransitionRule * b)2861*3d8817e4Smiod transition_rule_cmp (const TransitionRule *a, const TransitionRule *b)
2862*3d8817e4Smiod {
2863*3d8817e4Smiod   bfd_boolean a_greater = FALSE;
2864*3d8817e4Smiod   bfd_boolean b_greater = FALSE;
2865*3d8817e4Smiod 
2866*3d8817e4Smiod   ReqOptionList *l_a = a->options;
2867*3d8817e4Smiod   ReqOptionList *l_b = b->options;
2868*3d8817e4Smiod 
2869*3d8817e4Smiod   /* We only care if they both are the same except for
2870*3d8817e4Smiod      a const16 vs. an l32r.  */
2871*3d8817e4Smiod 
2872*3d8817e4Smiod   while (l_a && l_b && ((l_a->next == NULL) == (l_b->next == NULL)))
2873*3d8817e4Smiod     {
2874*3d8817e4Smiod       ReqOrOptionList *l_or_a = l_a->or_option_terms;
2875*3d8817e4Smiod       ReqOrOptionList *l_or_b = l_b->or_option_terms;
2876*3d8817e4Smiod       while (l_or_a && l_or_b && ((l_a->next == NULL) == (l_b->next == NULL)))
2877*3d8817e4Smiod 	{
2878*3d8817e4Smiod 	  if (l_or_a->is_true != l_or_b->is_true)
2879*3d8817e4Smiod 	    return 0;
2880*3d8817e4Smiod 	  if (strcmp (l_or_a->option_name, l_or_b->option_name) != 0)
2881*3d8817e4Smiod 	    {
2882*3d8817e4Smiod 	      /* This is the case we care about.  */
2883*3d8817e4Smiod 	      if (strcmp (l_or_a->option_name, "IsaUseConst16") == 0
2884*3d8817e4Smiod 		  && strcmp (l_or_b->option_name, "IsaUseL32R") == 0)
2885*3d8817e4Smiod 		{
2886*3d8817e4Smiod 		  if (prefer_const16)
2887*3d8817e4Smiod 		    a_greater = TRUE;
2888*3d8817e4Smiod 		  else
2889*3d8817e4Smiod 		    b_greater = TRUE;
2890*3d8817e4Smiod 		}
2891*3d8817e4Smiod 	      else if (strcmp (l_or_a->option_name, "IsaUseL32R") == 0
2892*3d8817e4Smiod 		       && strcmp (l_or_b->option_name, "IsaUseConst16") == 0)
2893*3d8817e4Smiod 		{
2894*3d8817e4Smiod 		  if (prefer_const16)
2895*3d8817e4Smiod 		    b_greater = TRUE;
2896*3d8817e4Smiod 		  else
2897*3d8817e4Smiod 		    a_greater = TRUE;
2898*3d8817e4Smiod 		}
2899*3d8817e4Smiod 	      else
2900*3d8817e4Smiod 		return 0;
2901*3d8817e4Smiod 	    }
2902*3d8817e4Smiod 	  l_or_a = l_or_a->next;
2903*3d8817e4Smiod 	  l_or_b = l_or_b->next;
2904*3d8817e4Smiod 	}
2905*3d8817e4Smiod       if (l_or_a || l_or_b)
2906*3d8817e4Smiod 	return 0;
2907*3d8817e4Smiod 
2908*3d8817e4Smiod       l_a = l_a->next;
2909*3d8817e4Smiod       l_b = l_b->next;
2910*3d8817e4Smiod     }
2911*3d8817e4Smiod   if (l_a || l_b)
2912*3d8817e4Smiod     return 0;
2913*3d8817e4Smiod 
2914*3d8817e4Smiod   /* Incomparable if the substitution was used differently in two cases.  */
2915*3d8817e4Smiod   if (a_greater && b_greater)
2916*3d8817e4Smiod     return 0;
2917*3d8817e4Smiod 
2918*3d8817e4Smiod   if (b_greater)
2919*3d8817e4Smiod     return 1;
2920*3d8817e4Smiod   if (a_greater)
2921*3d8817e4Smiod     return -1;
2922*3d8817e4Smiod 
2923*3d8817e4Smiod   return 0;
2924*3d8817e4Smiod }
2925*3d8817e4Smiod 
2926*3d8817e4Smiod 
2927*3d8817e4Smiod static TransitionRule *
xg_instruction_match(TInsn * insn)2928*3d8817e4Smiod xg_instruction_match (TInsn *insn)
2929*3d8817e4Smiod {
2930*3d8817e4Smiod   TransitionTable *table = xg_build_simplify_table (&transition_rule_cmp);
2931*3d8817e4Smiod   TransitionList *l;
2932*3d8817e4Smiod   assert (insn->opcode < table->num_opcodes);
2933*3d8817e4Smiod 
2934*3d8817e4Smiod   /* Walk through all of the possible transitions.  */
2935*3d8817e4Smiod   for (l = table->table[insn->opcode]; l != NULL; l = l->next)
2936*3d8817e4Smiod     {
2937*3d8817e4Smiod       TransitionRule *rule = l->rule;
2938*3d8817e4Smiod       if (xg_instruction_matches_rule (insn, rule))
2939*3d8817e4Smiod 	return rule;
2940*3d8817e4Smiod     }
2941*3d8817e4Smiod   return NULL;
2942*3d8817e4Smiod }
2943*3d8817e4Smiod 
2944*3d8817e4Smiod 
2945*3d8817e4Smiod /* Various Other Internal Functions.  */
2946*3d8817e4Smiod 
2947*3d8817e4Smiod static bfd_boolean
is_unique_insn_expansion(TransitionRule * r)2948*3d8817e4Smiod is_unique_insn_expansion (TransitionRule *r)
2949*3d8817e4Smiod {
2950*3d8817e4Smiod   if (!r->to_instr || r->to_instr->next != NULL)
2951*3d8817e4Smiod     return FALSE;
2952*3d8817e4Smiod   if (r->to_instr->typ != INSTR_INSTR)
2953*3d8817e4Smiod     return FALSE;
2954*3d8817e4Smiod   return TRUE;
2955*3d8817e4Smiod }
2956*3d8817e4Smiod 
2957*3d8817e4Smiod 
2958*3d8817e4Smiod /* Check if there is exactly one relaxation for INSN that converts it to
2959*3d8817e4Smiod    another instruction of equal or larger size.  If so, and if TARG is
2960*3d8817e4Smiod    non-null, go ahead and generate the relaxed instruction into TARG.  If
2961*3d8817e4Smiod    NARROW_ONLY is true, then only consider relaxations that widen a narrow
2962*3d8817e4Smiod    instruction, i.e., ignore relaxations that convert to an instruction of
2963*3d8817e4Smiod    equal size.  In some contexts where this function is used, only
2964*3d8817e4Smiod    a single widening is allowed and the NARROW_ONLY argument is used to
2965*3d8817e4Smiod    exclude cases like ADDI being "widened" to an ADDMI, which may
2966*3d8817e4Smiod    later be relaxed to an ADDMI/ADDI pair.  */
2967*3d8817e4Smiod 
2968*3d8817e4Smiod bfd_boolean
xg_is_single_relaxable_insn(TInsn * insn,TInsn * targ,bfd_boolean narrow_only)2969*3d8817e4Smiod xg_is_single_relaxable_insn (TInsn *insn, TInsn *targ, bfd_boolean narrow_only)
2970*3d8817e4Smiod {
2971*3d8817e4Smiod   TransitionTable *table = xg_build_widen_table (&transition_rule_cmp);
2972*3d8817e4Smiod   TransitionList *l;
2973*3d8817e4Smiod   TransitionRule *match = 0;
2974*3d8817e4Smiod 
2975*3d8817e4Smiod   assert (insn->insn_type == ITYPE_INSN);
2976*3d8817e4Smiod   assert (insn->opcode < table->num_opcodes);
2977*3d8817e4Smiod 
2978*3d8817e4Smiod   for (l = table->table[insn->opcode]; l != NULL; l = l->next)
2979*3d8817e4Smiod     {
2980*3d8817e4Smiod       TransitionRule *rule = l->rule;
2981*3d8817e4Smiod 
2982*3d8817e4Smiod       if (xg_instruction_matches_rule (insn, rule)
2983*3d8817e4Smiod 	  && is_unique_insn_expansion (rule)
2984*3d8817e4Smiod 	  && (xg_get_single_size (insn->opcode) + (narrow_only ? 1 : 0)
2985*3d8817e4Smiod 	      <= xg_get_single_size (rule->to_instr->opcode)))
2986*3d8817e4Smiod 	{
2987*3d8817e4Smiod 	  if (match)
2988*3d8817e4Smiod 	    return FALSE;
2989*3d8817e4Smiod 	  match = rule;
2990*3d8817e4Smiod 	}
2991*3d8817e4Smiod     }
2992*3d8817e4Smiod   if (!match)
2993*3d8817e4Smiod     return FALSE;
2994*3d8817e4Smiod 
2995*3d8817e4Smiod   if (targ)
2996*3d8817e4Smiod     xg_build_to_insn (targ, insn, match->to_instr);
2997*3d8817e4Smiod   return TRUE;
2998*3d8817e4Smiod }
2999*3d8817e4Smiod 
3000*3d8817e4Smiod 
3001*3d8817e4Smiod /* Return the maximum number of bytes this opcode can expand to.  */
3002*3d8817e4Smiod 
3003*3d8817e4Smiod static int
xg_get_max_insn_widen_size(xtensa_opcode opcode)3004*3d8817e4Smiod xg_get_max_insn_widen_size (xtensa_opcode opcode)
3005*3d8817e4Smiod {
3006*3d8817e4Smiod   TransitionTable *table = xg_build_widen_table (&transition_rule_cmp);
3007*3d8817e4Smiod   TransitionList *l;
3008*3d8817e4Smiod   int max_size = xg_get_single_size (opcode);
3009*3d8817e4Smiod 
3010*3d8817e4Smiod   assert (opcode < table->num_opcodes);
3011*3d8817e4Smiod 
3012*3d8817e4Smiod   for (l = table->table[opcode]; l != NULL; l = l->next)
3013*3d8817e4Smiod     {
3014*3d8817e4Smiod       TransitionRule *rule = l->rule;
3015*3d8817e4Smiod       BuildInstr *build_list;
3016*3d8817e4Smiod       int this_size = 0;
3017*3d8817e4Smiod 
3018*3d8817e4Smiod       if (!rule)
3019*3d8817e4Smiod 	continue;
3020*3d8817e4Smiod       build_list = rule->to_instr;
3021*3d8817e4Smiod       if (is_unique_insn_expansion (rule))
3022*3d8817e4Smiod 	{
3023*3d8817e4Smiod 	  assert (build_list->typ == INSTR_INSTR);
3024*3d8817e4Smiod 	  this_size = xg_get_max_insn_widen_size (build_list->opcode);
3025*3d8817e4Smiod 	}
3026*3d8817e4Smiod       else
3027*3d8817e4Smiod 	for (; build_list != NULL; build_list = build_list->next)
3028*3d8817e4Smiod 	  {
3029*3d8817e4Smiod 	    switch (build_list->typ)
3030*3d8817e4Smiod 	      {
3031*3d8817e4Smiod 	      case INSTR_INSTR:
3032*3d8817e4Smiod 		this_size += xg_get_single_size (build_list->opcode);
3033*3d8817e4Smiod 		break;
3034*3d8817e4Smiod 	      case INSTR_LITERAL_DEF:
3035*3d8817e4Smiod 	      case INSTR_LABEL_DEF:
3036*3d8817e4Smiod 	      default:
3037*3d8817e4Smiod 		break;
3038*3d8817e4Smiod 	      }
3039*3d8817e4Smiod 	  }
3040*3d8817e4Smiod       if (this_size > max_size)
3041*3d8817e4Smiod 	max_size = this_size;
3042*3d8817e4Smiod     }
3043*3d8817e4Smiod   return max_size;
3044*3d8817e4Smiod }
3045*3d8817e4Smiod 
3046*3d8817e4Smiod 
3047*3d8817e4Smiod /* Return the maximum number of literal bytes this opcode can generate.  */
3048*3d8817e4Smiod 
3049*3d8817e4Smiod static int
xg_get_max_insn_widen_literal_size(xtensa_opcode opcode)3050*3d8817e4Smiod xg_get_max_insn_widen_literal_size (xtensa_opcode opcode)
3051*3d8817e4Smiod {
3052*3d8817e4Smiod   TransitionTable *table = xg_build_widen_table (&transition_rule_cmp);
3053*3d8817e4Smiod   TransitionList *l;
3054*3d8817e4Smiod   int max_size = 0;
3055*3d8817e4Smiod 
3056*3d8817e4Smiod   assert (opcode < table->num_opcodes);
3057*3d8817e4Smiod 
3058*3d8817e4Smiod   for (l = table->table[opcode]; l != NULL; l = l->next)
3059*3d8817e4Smiod     {
3060*3d8817e4Smiod       TransitionRule *rule = l->rule;
3061*3d8817e4Smiod       BuildInstr *build_list;
3062*3d8817e4Smiod       int this_size = 0;
3063*3d8817e4Smiod 
3064*3d8817e4Smiod       if (!rule)
3065*3d8817e4Smiod 	continue;
3066*3d8817e4Smiod       build_list = rule->to_instr;
3067*3d8817e4Smiod       if (is_unique_insn_expansion (rule))
3068*3d8817e4Smiod 	{
3069*3d8817e4Smiod 	  assert (build_list->typ == INSTR_INSTR);
3070*3d8817e4Smiod 	  this_size = xg_get_max_insn_widen_literal_size (build_list->opcode);
3071*3d8817e4Smiod 	}
3072*3d8817e4Smiod       else
3073*3d8817e4Smiod 	for (; build_list != NULL; build_list = build_list->next)
3074*3d8817e4Smiod 	  {
3075*3d8817e4Smiod 	    switch (build_list->typ)
3076*3d8817e4Smiod 	      {
3077*3d8817e4Smiod 	      case INSTR_LITERAL_DEF:
3078*3d8817e4Smiod 		/* Hard-coded 4-byte literal.  */
3079*3d8817e4Smiod 		this_size += 4;
3080*3d8817e4Smiod 		break;
3081*3d8817e4Smiod 	      case INSTR_INSTR:
3082*3d8817e4Smiod 	      case INSTR_LABEL_DEF:
3083*3d8817e4Smiod 	      default:
3084*3d8817e4Smiod 		break;
3085*3d8817e4Smiod 	      }
3086*3d8817e4Smiod 	  }
3087*3d8817e4Smiod       if (this_size > max_size)
3088*3d8817e4Smiod 	max_size = this_size;
3089*3d8817e4Smiod     }
3090*3d8817e4Smiod   return max_size;
3091*3d8817e4Smiod }
3092*3d8817e4Smiod 
3093*3d8817e4Smiod 
3094*3d8817e4Smiod static bfd_boolean
xg_is_relaxable_insn(TInsn * insn,int lateral_steps)3095*3d8817e4Smiod xg_is_relaxable_insn (TInsn *insn, int lateral_steps)
3096*3d8817e4Smiod {
3097*3d8817e4Smiod   int steps_taken = 0;
3098*3d8817e4Smiod   TransitionTable *table = xg_build_widen_table (&transition_rule_cmp);
3099*3d8817e4Smiod   TransitionList *l;
3100*3d8817e4Smiod 
3101*3d8817e4Smiod   assert (insn->insn_type == ITYPE_INSN);
3102*3d8817e4Smiod   assert (insn->opcode < table->num_opcodes);
3103*3d8817e4Smiod 
3104*3d8817e4Smiod   for (l = table->table[insn->opcode]; l != NULL; l = l->next)
3105*3d8817e4Smiod     {
3106*3d8817e4Smiod       TransitionRule *rule = l->rule;
3107*3d8817e4Smiod 
3108*3d8817e4Smiod       if (xg_instruction_matches_rule (insn, rule))
3109*3d8817e4Smiod 	{
3110*3d8817e4Smiod 	  if (steps_taken == lateral_steps)
3111*3d8817e4Smiod 	    return TRUE;
3112*3d8817e4Smiod 	  steps_taken++;
3113*3d8817e4Smiod 	}
3114*3d8817e4Smiod     }
3115*3d8817e4Smiod   return FALSE;
3116*3d8817e4Smiod }
3117*3d8817e4Smiod 
3118*3d8817e4Smiod 
3119*3d8817e4Smiod static symbolS *
get_special_literal_symbol(void)3120*3d8817e4Smiod get_special_literal_symbol (void)
3121*3d8817e4Smiod {
3122*3d8817e4Smiod   static symbolS *sym = NULL;
3123*3d8817e4Smiod 
3124*3d8817e4Smiod   if (sym == NULL)
3125*3d8817e4Smiod     sym = symbol_find_or_make ("SPECIAL_LITERAL0\001");
3126*3d8817e4Smiod   return sym;
3127*3d8817e4Smiod }
3128*3d8817e4Smiod 
3129*3d8817e4Smiod 
3130*3d8817e4Smiod static symbolS *
get_special_label_symbol(void)3131*3d8817e4Smiod get_special_label_symbol (void)
3132*3d8817e4Smiod {
3133*3d8817e4Smiod   static symbolS *sym = NULL;
3134*3d8817e4Smiod 
3135*3d8817e4Smiod   if (sym == NULL)
3136*3d8817e4Smiod     sym = symbol_find_or_make ("SPECIAL_LABEL0\001");
3137*3d8817e4Smiod   return sym;
3138*3d8817e4Smiod }
3139*3d8817e4Smiod 
3140*3d8817e4Smiod 
3141*3d8817e4Smiod static bfd_boolean
xg_valid_literal_expression(const expressionS * exp)3142*3d8817e4Smiod xg_valid_literal_expression (const expressionS *exp)
3143*3d8817e4Smiod {
3144*3d8817e4Smiod   switch (exp->X_op)
3145*3d8817e4Smiod     {
3146*3d8817e4Smiod     case O_constant:
3147*3d8817e4Smiod     case O_symbol:
3148*3d8817e4Smiod     case O_big:
3149*3d8817e4Smiod     case O_uminus:
3150*3d8817e4Smiod     case O_subtract:
3151*3d8817e4Smiod     case O_pltrel:
3152*3d8817e4Smiod       return TRUE;
3153*3d8817e4Smiod     default:
3154*3d8817e4Smiod       return FALSE;
3155*3d8817e4Smiod     }
3156*3d8817e4Smiod }
3157*3d8817e4Smiod 
3158*3d8817e4Smiod 
3159*3d8817e4Smiod /* This will check to see if the value can be converted into the
3160*3d8817e4Smiod    operand type.  It will return TRUE if it does not fit.  */
3161*3d8817e4Smiod 
3162*3d8817e4Smiod static bfd_boolean
xg_check_operand(int32 value,xtensa_opcode opcode,int operand)3163*3d8817e4Smiod xg_check_operand (int32 value, xtensa_opcode opcode, int operand)
3164*3d8817e4Smiod {
3165*3d8817e4Smiod   uint32 valbuf = value;
3166*3d8817e4Smiod   if (xtensa_operand_encode (xtensa_default_isa, opcode, operand, &valbuf))
3167*3d8817e4Smiod     return TRUE;
3168*3d8817e4Smiod   return FALSE;
3169*3d8817e4Smiod }
3170*3d8817e4Smiod 
3171*3d8817e4Smiod 
3172*3d8817e4Smiod /* Assumes: All immeds are constants.  Check that all constants fit
3173*3d8817e4Smiod    into their immeds; return FALSE if not.  */
3174*3d8817e4Smiod 
3175*3d8817e4Smiod static bfd_boolean
xg_immeds_fit(const TInsn * insn)3176*3d8817e4Smiod xg_immeds_fit (const TInsn *insn)
3177*3d8817e4Smiod {
3178*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
3179*3d8817e4Smiod   int i;
3180*3d8817e4Smiod 
3181*3d8817e4Smiod   int n = insn->ntok;
3182*3d8817e4Smiod   assert (insn->insn_type == ITYPE_INSN);
3183*3d8817e4Smiod   for (i = 0; i < n; ++i)
3184*3d8817e4Smiod     {
3185*3d8817e4Smiod       const expressionS *expr = &insn->tok[i];
3186*3d8817e4Smiod       if (xtensa_operand_is_register (isa, insn->opcode, i) == 1)
3187*3d8817e4Smiod 	continue;
3188*3d8817e4Smiod 
3189*3d8817e4Smiod       switch (expr->X_op)
3190*3d8817e4Smiod 	{
3191*3d8817e4Smiod 	case O_register:
3192*3d8817e4Smiod 	case O_constant:
3193*3d8817e4Smiod 	  if (xg_check_operand (expr->X_add_number, insn->opcode, i))
3194*3d8817e4Smiod 	    return FALSE;
3195*3d8817e4Smiod 	  break;
3196*3d8817e4Smiod 
3197*3d8817e4Smiod 	default:
3198*3d8817e4Smiod 	  /* The symbol should have a fixup associated with it.  */
3199*3d8817e4Smiod 	  assert (FALSE);
3200*3d8817e4Smiod 	  break;
3201*3d8817e4Smiod 	}
3202*3d8817e4Smiod     }
3203*3d8817e4Smiod   return TRUE;
3204*3d8817e4Smiod }
3205*3d8817e4Smiod 
3206*3d8817e4Smiod 
3207*3d8817e4Smiod /* This should only be called after we have an initial
3208*3d8817e4Smiod    estimate of the addresses.  */
3209*3d8817e4Smiod 
3210*3d8817e4Smiod static bfd_boolean
xg_symbolic_immeds_fit(const TInsn * insn,segT pc_seg,fragS * pc_frag,offsetT pc_offset,long stretch)3211*3d8817e4Smiod xg_symbolic_immeds_fit (const TInsn *insn,
3212*3d8817e4Smiod 			segT pc_seg,
3213*3d8817e4Smiod 			fragS *pc_frag,
3214*3d8817e4Smiod 			offsetT pc_offset,
3215*3d8817e4Smiod 			long stretch)
3216*3d8817e4Smiod {
3217*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
3218*3d8817e4Smiod   symbolS *symbolP;
3219*3d8817e4Smiod   fragS *sym_frag;
3220*3d8817e4Smiod   offsetT target, pc;
3221*3d8817e4Smiod   uint32 new_offset;
3222*3d8817e4Smiod   int i;
3223*3d8817e4Smiod   int n = insn->ntok;
3224*3d8817e4Smiod 
3225*3d8817e4Smiod   assert (insn->insn_type == ITYPE_INSN);
3226*3d8817e4Smiod 
3227*3d8817e4Smiod   for (i = 0; i < n; ++i)
3228*3d8817e4Smiod     {
3229*3d8817e4Smiod       const expressionS *expr = &insn->tok[i];
3230*3d8817e4Smiod       if (xtensa_operand_is_register (isa, insn->opcode, i) == 1)
3231*3d8817e4Smiod 	continue;
3232*3d8817e4Smiod 
3233*3d8817e4Smiod       switch (expr->X_op)
3234*3d8817e4Smiod 	{
3235*3d8817e4Smiod 	case O_register:
3236*3d8817e4Smiod 	case O_constant:
3237*3d8817e4Smiod 	  if (xg_check_operand (expr->X_add_number, insn->opcode, i))
3238*3d8817e4Smiod 	    return FALSE;
3239*3d8817e4Smiod 	  break;
3240*3d8817e4Smiod 
3241*3d8817e4Smiod 	case O_lo16:
3242*3d8817e4Smiod 	case O_hi16:
3243*3d8817e4Smiod 	  /* Check for the worst case.  */
3244*3d8817e4Smiod 	  if (xg_check_operand (0xffff, insn->opcode, i))
3245*3d8817e4Smiod 	    return FALSE;
3246*3d8817e4Smiod 	  break;
3247*3d8817e4Smiod 
3248*3d8817e4Smiod 	case O_symbol:
3249*3d8817e4Smiod 	  /* We only allow symbols for PC-relative references.
3250*3d8817e4Smiod 	     If pc_frag == 0, then we don't have frag locations yet.  */
3251*3d8817e4Smiod 	  if (pc_frag == 0
3252*3d8817e4Smiod 	      || xtensa_operand_is_PCrelative (isa, insn->opcode, i) == 0)
3253*3d8817e4Smiod 	    return FALSE;
3254*3d8817e4Smiod 
3255*3d8817e4Smiod 	  /* If it is a weak symbol, then assume it won't reach.  */
3256*3d8817e4Smiod 	  if (S_IS_WEAK (expr->X_add_symbol))
3257*3d8817e4Smiod 	    return FALSE;
3258*3d8817e4Smiod 
3259*3d8817e4Smiod 	  if (is_direct_call_opcode (insn->opcode)
3260*3d8817e4Smiod 	      && ! pc_frag->tc_frag_data.use_longcalls)
3261*3d8817e4Smiod 	    {
3262*3d8817e4Smiod 	      /* If callee is undefined or in a different segment, be
3263*3d8817e4Smiod 		 optimistic and assume it will be in range.  */
3264*3d8817e4Smiod 	      if (S_GET_SEGMENT (expr->X_add_symbol) != pc_seg)
3265*3d8817e4Smiod 		return TRUE;
3266*3d8817e4Smiod 	    }
3267*3d8817e4Smiod 
3268*3d8817e4Smiod 	  /* Only references within a segment can be known to fit in the
3269*3d8817e4Smiod 	     operands at assembly time.  */
3270*3d8817e4Smiod 	  if (S_GET_SEGMENT (expr->X_add_symbol) != pc_seg)
3271*3d8817e4Smiod 	    return FALSE;
3272*3d8817e4Smiod 
3273*3d8817e4Smiod 	  symbolP = expr->X_add_symbol;
3274*3d8817e4Smiod 	  sym_frag = symbol_get_frag (symbolP);
3275*3d8817e4Smiod 	  target = S_GET_VALUE (symbolP) + expr->X_add_number;
3276*3d8817e4Smiod 	  pc = pc_frag->fr_address + pc_offset;
3277*3d8817e4Smiod 
3278*3d8817e4Smiod 	  /* If frag has yet to be reached on this pass, assume it
3279*3d8817e4Smiod 	     will move by STRETCH just as we did.  If this is not so,
3280*3d8817e4Smiod 	     it will be because some frag between grows, and that will
3281*3d8817e4Smiod 	     force another pass.  Beware zero-length frags.  There
3282*3d8817e4Smiod 	     should be a faster way to do this.  */
3283*3d8817e4Smiod 
3284*3d8817e4Smiod 	  if (stretch != 0
3285*3d8817e4Smiod 	      && sym_frag->relax_marker != pc_frag->relax_marker
3286*3d8817e4Smiod 	      && S_GET_SEGMENT (symbolP) == pc_seg)
3287*3d8817e4Smiod 	    {
3288*3d8817e4Smiod 	      target += stretch;
3289*3d8817e4Smiod 	    }
3290*3d8817e4Smiod 
3291*3d8817e4Smiod 	  new_offset = target;
3292*3d8817e4Smiod 	  xtensa_operand_do_reloc (isa, insn->opcode, i, &new_offset, pc);
3293*3d8817e4Smiod 	  if (xg_check_operand (new_offset, insn->opcode, i))
3294*3d8817e4Smiod 	    return FALSE;
3295*3d8817e4Smiod 	  break;
3296*3d8817e4Smiod 
3297*3d8817e4Smiod 	default:
3298*3d8817e4Smiod 	  /* The symbol should have a fixup associated with it.  */
3299*3d8817e4Smiod 	  return FALSE;
3300*3d8817e4Smiod 	}
3301*3d8817e4Smiod     }
3302*3d8817e4Smiod 
3303*3d8817e4Smiod   return TRUE;
3304*3d8817e4Smiod }
3305*3d8817e4Smiod 
3306*3d8817e4Smiod 
3307*3d8817e4Smiod /* Return TRUE on success.  */
3308*3d8817e4Smiod 
3309*3d8817e4Smiod static bfd_boolean
xg_build_to_insn(TInsn * targ,TInsn * insn,BuildInstr * bi)3310*3d8817e4Smiod xg_build_to_insn (TInsn *targ, TInsn *insn, BuildInstr *bi)
3311*3d8817e4Smiod {
3312*3d8817e4Smiod   BuildOp *op;
3313*3d8817e4Smiod   symbolS *sym;
3314*3d8817e4Smiod 
3315*3d8817e4Smiod   memset (targ, 0, sizeof (TInsn));
3316*3d8817e4Smiod   targ->linenum = insn->linenum;
3317*3d8817e4Smiod   switch (bi->typ)
3318*3d8817e4Smiod     {
3319*3d8817e4Smiod     case INSTR_INSTR:
3320*3d8817e4Smiod       op = bi->ops;
3321*3d8817e4Smiod       targ->opcode = bi->opcode;
3322*3d8817e4Smiod       targ->insn_type = ITYPE_INSN;
3323*3d8817e4Smiod       targ->is_specific_opcode = FALSE;
3324*3d8817e4Smiod 
3325*3d8817e4Smiod       for (; op != NULL; op = op->next)
3326*3d8817e4Smiod 	{
3327*3d8817e4Smiod 	  int op_num = op->op_num;
3328*3d8817e4Smiod 	  int op_data = op->op_data;
3329*3d8817e4Smiod 
3330*3d8817e4Smiod 	  assert (op->op_num < MAX_INSN_ARGS);
3331*3d8817e4Smiod 
3332*3d8817e4Smiod 	  if (targ->ntok <= op_num)
3333*3d8817e4Smiod 	    targ->ntok = op_num + 1;
3334*3d8817e4Smiod 
3335*3d8817e4Smiod 	  switch (op->typ)
3336*3d8817e4Smiod 	    {
3337*3d8817e4Smiod 	    case OP_CONSTANT:
3338*3d8817e4Smiod 	      set_expr_const (&targ->tok[op_num], op_data);
3339*3d8817e4Smiod 	      break;
3340*3d8817e4Smiod 	    case OP_OPERAND:
3341*3d8817e4Smiod 	      assert (op_data < insn->ntok);
3342*3d8817e4Smiod 	      copy_expr (&targ->tok[op_num], &insn->tok[op_data]);
3343*3d8817e4Smiod 	      break;
3344*3d8817e4Smiod 	    case OP_LITERAL:
3345*3d8817e4Smiod 	      sym = get_special_literal_symbol ();
3346*3d8817e4Smiod 	      set_expr_symbol_offset (&targ->tok[op_num], sym, 0);
3347*3d8817e4Smiod 	      break;
3348*3d8817e4Smiod 	    case OP_LABEL:
3349*3d8817e4Smiod 	      sym = get_special_label_symbol ();
3350*3d8817e4Smiod 	      set_expr_symbol_offset (&targ->tok[op_num], sym, 0);
3351*3d8817e4Smiod 	      break;
3352*3d8817e4Smiod 	    case OP_OPERAND_HI16U:
3353*3d8817e4Smiod 	    case OP_OPERAND_LOW16U:
3354*3d8817e4Smiod 	      assert (op_data < insn->ntok);
3355*3d8817e4Smiod 	      if (expr_is_const (&insn->tok[op_data]))
3356*3d8817e4Smiod 		{
3357*3d8817e4Smiod 		  long val;
3358*3d8817e4Smiod 		  copy_expr (&targ->tok[op_num], &insn->tok[op_data]);
3359*3d8817e4Smiod 		  val = xg_apply_userdef_op_fn (op->typ,
3360*3d8817e4Smiod 						targ->tok[op_num].
3361*3d8817e4Smiod 						X_add_number);
3362*3d8817e4Smiod 		  targ->tok[op_num].X_add_number = val;
3363*3d8817e4Smiod 		}
3364*3d8817e4Smiod 	      else
3365*3d8817e4Smiod 		{
3366*3d8817e4Smiod 		  /* For const16 we can create relocations for these.  */
3367*3d8817e4Smiod 		  if (targ->opcode == XTENSA_UNDEFINED
3368*3d8817e4Smiod 		      || (targ->opcode != xtensa_const16_opcode))
3369*3d8817e4Smiod 		    return FALSE;
3370*3d8817e4Smiod 		  assert (op_data < insn->ntok);
3371*3d8817e4Smiod 		  /* Need to build a O_lo16 or O_hi16.  */
3372*3d8817e4Smiod 		  copy_expr (&targ->tok[op_num], &insn->tok[op_data]);
3373*3d8817e4Smiod 		  if (targ->tok[op_num].X_op == O_symbol)
3374*3d8817e4Smiod 		    {
3375*3d8817e4Smiod 		      if (op->typ == OP_OPERAND_HI16U)
3376*3d8817e4Smiod 			targ->tok[op_num].X_op = O_hi16;
3377*3d8817e4Smiod 		      else if (op->typ == OP_OPERAND_LOW16U)
3378*3d8817e4Smiod 			targ->tok[op_num].X_op = O_lo16;
3379*3d8817e4Smiod 		      else
3380*3d8817e4Smiod 			return FALSE;
3381*3d8817e4Smiod 		    }
3382*3d8817e4Smiod 		}
3383*3d8817e4Smiod 	      break;
3384*3d8817e4Smiod 	    default:
3385*3d8817e4Smiod 	      /* currently handles:
3386*3d8817e4Smiod 		 OP_OPERAND_LOW8
3387*3d8817e4Smiod 		 OP_OPERAND_HI24S
3388*3d8817e4Smiod 		 OP_OPERAND_F32MINUS */
3389*3d8817e4Smiod 	      if (xg_has_userdef_op_fn (op->typ))
3390*3d8817e4Smiod 		{
3391*3d8817e4Smiod 		  assert (op_data < insn->ntok);
3392*3d8817e4Smiod 		  if (expr_is_const (&insn->tok[op_data]))
3393*3d8817e4Smiod 		    {
3394*3d8817e4Smiod 		      long val;
3395*3d8817e4Smiod 		      copy_expr (&targ->tok[op_num], &insn->tok[op_data]);
3396*3d8817e4Smiod 		      val = xg_apply_userdef_op_fn (op->typ,
3397*3d8817e4Smiod 						    targ->tok[op_num].
3398*3d8817e4Smiod 						    X_add_number);
3399*3d8817e4Smiod 		      targ->tok[op_num].X_add_number = val;
3400*3d8817e4Smiod 		    }
3401*3d8817e4Smiod 		  else
3402*3d8817e4Smiod 		    return FALSE; /* We cannot use a relocation for this.  */
3403*3d8817e4Smiod 		  break;
3404*3d8817e4Smiod 		}
3405*3d8817e4Smiod 	      assert (0);
3406*3d8817e4Smiod 	      break;
3407*3d8817e4Smiod 	    }
3408*3d8817e4Smiod 	}
3409*3d8817e4Smiod       break;
3410*3d8817e4Smiod 
3411*3d8817e4Smiod     case INSTR_LITERAL_DEF:
3412*3d8817e4Smiod       op = bi->ops;
3413*3d8817e4Smiod       targ->opcode = XTENSA_UNDEFINED;
3414*3d8817e4Smiod       targ->insn_type = ITYPE_LITERAL;
3415*3d8817e4Smiod       targ->is_specific_opcode = FALSE;
3416*3d8817e4Smiod       for (; op != NULL; op = op->next)
3417*3d8817e4Smiod 	{
3418*3d8817e4Smiod 	  int op_num = op->op_num;
3419*3d8817e4Smiod 	  int op_data = op->op_data;
3420*3d8817e4Smiod 	  assert (op->op_num < MAX_INSN_ARGS);
3421*3d8817e4Smiod 
3422*3d8817e4Smiod 	  if (targ->ntok <= op_num)
3423*3d8817e4Smiod 	    targ->ntok = op_num + 1;
3424*3d8817e4Smiod 
3425*3d8817e4Smiod 	  switch (op->typ)
3426*3d8817e4Smiod 	    {
3427*3d8817e4Smiod 	    case OP_OPERAND:
3428*3d8817e4Smiod 	      assert (op_data < insn->ntok);
3429*3d8817e4Smiod 	      /* We can only pass resolvable literals through.  */
3430*3d8817e4Smiod 	      if (!xg_valid_literal_expression (&insn->tok[op_data]))
3431*3d8817e4Smiod 		return FALSE;
3432*3d8817e4Smiod 	      copy_expr (&targ->tok[op_num], &insn->tok[op_data]);
3433*3d8817e4Smiod 	      break;
3434*3d8817e4Smiod 	    case OP_LITERAL:
3435*3d8817e4Smiod 	    case OP_CONSTANT:
3436*3d8817e4Smiod 	    case OP_LABEL:
3437*3d8817e4Smiod 	    default:
3438*3d8817e4Smiod 	      assert (0);
3439*3d8817e4Smiod 	      break;
3440*3d8817e4Smiod 	    }
3441*3d8817e4Smiod 	}
3442*3d8817e4Smiod       break;
3443*3d8817e4Smiod 
3444*3d8817e4Smiod     case INSTR_LABEL_DEF:
3445*3d8817e4Smiod       op = bi->ops;
3446*3d8817e4Smiod       targ->opcode = XTENSA_UNDEFINED;
3447*3d8817e4Smiod       targ->insn_type = ITYPE_LABEL;
3448*3d8817e4Smiod       targ->is_specific_opcode = FALSE;
3449*3d8817e4Smiod       /* Literal with no ops is a label?  */
3450*3d8817e4Smiod       assert (op == NULL);
3451*3d8817e4Smiod       break;
3452*3d8817e4Smiod 
3453*3d8817e4Smiod     default:
3454*3d8817e4Smiod       assert (0);
3455*3d8817e4Smiod     }
3456*3d8817e4Smiod 
3457*3d8817e4Smiod   return TRUE;
3458*3d8817e4Smiod }
3459*3d8817e4Smiod 
3460*3d8817e4Smiod 
3461*3d8817e4Smiod /* Return TRUE on success.  */
3462*3d8817e4Smiod 
3463*3d8817e4Smiod static bfd_boolean
xg_build_to_stack(IStack * istack,TInsn * insn,BuildInstr * bi)3464*3d8817e4Smiod xg_build_to_stack (IStack *istack, TInsn *insn, BuildInstr *bi)
3465*3d8817e4Smiod {
3466*3d8817e4Smiod   for (; bi != NULL; bi = bi->next)
3467*3d8817e4Smiod     {
3468*3d8817e4Smiod       TInsn *next_insn = istack_push_space (istack);
3469*3d8817e4Smiod 
3470*3d8817e4Smiod       if (!xg_build_to_insn (next_insn, insn, bi))
3471*3d8817e4Smiod 	return FALSE;
3472*3d8817e4Smiod     }
3473*3d8817e4Smiod   return TRUE;
3474*3d8817e4Smiod }
3475*3d8817e4Smiod 
3476*3d8817e4Smiod 
3477*3d8817e4Smiod /* Return TRUE on valid expansion.  */
3478*3d8817e4Smiod 
3479*3d8817e4Smiod static bfd_boolean
xg_expand_to_stack(IStack * istack,TInsn * insn,int lateral_steps)3480*3d8817e4Smiod xg_expand_to_stack (IStack *istack, TInsn *insn, int lateral_steps)
3481*3d8817e4Smiod {
3482*3d8817e4Smiod   int stack_size = istack->ninsn;
3483*3d8817e4Smiod   int steps_taken = 0;
3484*3d8817e4Smiod   TransitionTable *table = xg_build_widen_table (&transition_rule_cmp);
3485*3d8817e4Smiod   TransitionList *l;
3486*3d8817e4Smiod 
3487*3d8817e4Smiod   assert (insn->insn_type == ITYPE_INSN);
3488*3d8817e4Smiod   assert (insn->opcode < table->num_opcodes);
3489*3d8817e4Smiod 
3490*3d8817e4Smiod   for (l = table->table[insn->opcode]; l != NULL; l = l->next)
3491*3d8817e4Smiod     {
3492*3d8817e4Smiod       TransitionRule *rule = l->rule;
3493*3d8817e4Smiod 
3494*3d8817e4Smiod       if (xg_instruction_matches_rule (insn, rule))
3495*3d8817e4Smiod 	{
3496*3d8817e4Smiod 	  if (lateral_steps == steps_taken)
3497*3d8817e4Smiod 	    {
3498*3d8817e4Smiod 	      int i;
3499*3d8817e4Smiod 
3500*3d8817e4Smiod 	      /* This is it.  Expand the rule to the stack.  */
3501*3d8817e4Smiod 	      if (!xg_build_to_stack (istack, insn, rule->to_instr))
3502*3d8817e4Smiod 		return FALSE;
3503*3d8817e4Smiod 
3504*3d8817e4Smiod 	      /* Check to see if it fits.  */
3505*3d8817e4Smiod 	      for (i = stack_size; i < istack->ninsn; i++)
3506*3d8817e4Smiod 		{
3507*3d8817e4Smiod 		  TInsn *insn = &istack->insn[i];
3508*3d8817e4Smiod 
3509*3d8817e4Smiod 		  if (insn->insn_type == ITYPE_INSN
3510*3d8817e4Smiod 		      && !tinsn_has_symbolic_operands (insn)
3511*3d8817e4Smiod 		      && !xg_immeds_fit (insn))
3512*3d8817e4Smiod 		    {
3513*3d8817e4Smiod 		      istack->ninsn = stack_size;
3514*3d8817e4Smiod 		      return FALSE;
3515*3d8817e4Smiod 		    }
3516*3d8817e4Smiod 		}
3517*3d8817e4Smiod 	      return TRUE;
3518*3d8817e4Smiod 	    }
3519*3d8817e4Smiod 	  steps_taken++;
3520*3d8817e4Smiod 	}
3521*3d8817e4Smiod     }
3522*3d8817e4Smiod   return FALSE;
3523*3d8817e4Smiod }
3524*3d8817e4Smiod 
3525*3d8817e4Smiod 
3526*3d8817e4Smiod /* Relax the assembly instruction at least "min_steps".
3527*3d8817e4Smiod    Return the number of steps taken.  */
3528*3d8817e4Smiod 
3529*3d8817e4Smiod static int
xg_assembly_relax(IStack * istack,TInsn * insn,segT pc_seg,fragS * pc_frag,offsetT pc_offset,int min_steps,long stretch)3530*3d8817e4Smiod xg_assembly_relax (IStack *istack,
3531*3d8817e4Smiod 		   TInsn *insn,
3532*3d8817e4Smiod 		   segT pc_seg,
3533*3d8817e4Smiod 		   fragS *pc_frag,	/* if pc_frag == 0, not pc-relative */
3534*3d8817e4Smiod 		   offsetT pc_offset,	/* offset in fragment */
3535*3d8817e4Smiod 		   int min_steps,	/* minimum conversion steps */
3536*3d8817e4Smiod 		   long stretch)	/* number of bytes stretched so far */
3537*3d8817e4Smiod {
3538*3d8817e4Smiod   int steps_taken = 0;
3539*3d8817e4Smiod 
3540*3d8817e4Smiod   /* assert (has no symbolic operands)
3541*3d8817e4Smiod      Some of its immeds don't fit.
3542*3d8817e4Smiod      Try to build a relaxed version.
3543*3d8817e4Smiod      This may go through a couple of stages
3544*3d8817e4Smiod      of single instruction transformations before
3545*3d8817e4Smiod      we get there.  */
3546*3d8817e4Smiod 
3547*3d8817e4Smiod   TInsn single_target;
3548*3d8817e4Smiod   TInsn current_insn;
3549*3d8817e4Smiod   int lateral_steps = 0;
3550*3d8817e4Smiod   int istack_size = istack->ninsn;
3551*3d8817e4Smiod 
3552*3d8817e4Smiod   if (xg_symbolic_immeds_fit (insn, pc_seg, pc_frag, pc_offset, stretch)
3553*3d8817e4Smiod       && steps_taken >= min_steps)
3554*3d8817e4Smiod     {
3555*3d8817e4Smiod       istack_push (istack, insn);
3556*3d8817e4Smiod       return steps_taken;
3557*3d8817e4Smiod     }
3558*3d8817e4Smiod   current_insn = *insn;
3559*3d8817e4Smiod 
3560*3d8817e4Smiod   /* Walk through all of the single instruction expansions.  */
3561*3d8817e4Smiod   while (xg_is_single_relaxable_insn (&current_insn, &single_target, FALSE))
3562*3d8817e4Smiod     {
3563*3d8817e4Smiod       steps_taken++;
3564*3d8817e4Smiod       if (xg_symbolic_immeds_fit (&single_target, pc_seg, pc_frag, pc_offset,
3565*3d8817e4Smiod 				  stretch))
3566*3d8817e4Smiod 	{
3567*3d8817e4Smiod 	  if (steps_taken >= min_steps)
3568*3d8817e4Smiod 	    {
3569*3d8817e4Smiod 	      istack_push (istack, &single_target);
3570*3d8817e4Smiod 	      return steps_taken;
3571*3d8817e4Smiod 	    }
3572*3d8817e4Smiod 	}
3573*3d8817e4Smiod       current_insn = single_target;
3574*3d8817e4Smiod     }
3575*3d8817e4Smiod 
3576*3d8817e4Smiod   /* Now check for a multi-instruction expansion.  */
3577*3d8817e4Smiod   while (xg_is_relaxable_insn (&current_insn, lateral_steps))
3578*3d8817e4Smiod     {
3579*3d8817e4Smiod       if (xg_symbolic_immeds_fit (&current_insn, pc_seg, pc_frag, pc_offset,
3580*3d8817e4Smiod 				  stretch))
3581*3d8817e4Smiod 	{
3582*3d8817e4Smiod 	  if (steps_taken >= min_steps)
3583*3d8817e4Smiod 	    {
3584*3d8817e4Smiod 	      istack_push (istack, &current_insn);
3585*3d8817e4Smiod 	      return steps_taken;
3586*3d8817e4Smiod 	    }
3587*3d8817e4Smiod 	}
3588*3d8817e4Smiod       steps_taken++;
3589*3d8817e4Smiod       if (xg_expand_to_stack (istack, &current_insn, lateral_steps))
3590*3d8817e4Smiod 	{
3591*3d8817e4Smiod 	  if (steps_taken >= min_steps)
3592*3d8817e4Smiod 	    return steps_taken;
3593*3d8817e4Smiod 	}
3594*3d8817e4Smiod       lateral_steps++;
3595*3d8817e4Smiod       istack->ninsn = istack_size;
3596*3d8817e4Smiod     }
3597*3d8817e4Smiod 
3598*3d8817e4Smiod   /* It's not going to work -- use the original.  */
3599*3d8817e4Smiod   istack_push (istack, insn);
3600*3d8817e4Smiod   return steps_taken;
3601*3d8817e4Smiod }
3602*3d8817e4Smiod 
3603*3d8817e4Smiod 
3604*3d8817e4Smiod static void
xg_force_frag_space(int size)3605*3d8817e4Smiod xg_force_frag_space (int size)
3606*3d8817e4Smiod {
3607*3d8817e4Smiod   /* This may have the side effect of creating a new fragment for the
3608*3d8817e4Smiod      space to go into.  I just do not like the name of the "frag"
3609*3d8817e4Smiod      functions.  */
3610*3d8817e4Smiod   frag_grow (size);
3611*3d8817e4Smiod }
3612*3d8817e4Smiod 
3613*3d8817e4Smiod 
3614*3d8817e4Smiod static void
xg_finish_frag(char * last_insn,enum xtensa_relax_statesE frag_state,enum xtensa_relax_statesE slot0_state,int max_growth,bfd_boolean is_insn)3615*3d8817e4Smiod xg_finish_frag (char *last_insn,
3616*3d8817e4Smiod 		enum xtensa_relax_statesE frag_state,
3617*3d8817e4Smiod 		enum xtensa_relax_statesE slot0_state,
3618*3d8817e4Smiod 		int max_growth,
3619*3d8817e4Smiod 		bfd_boolean is_insn)
3620*3d8817e4Smiod {
3621*3d8817e4Smiod   /* Finish off this fragment so that it has at LEAST the desired
3622*3d8817e4Smiod      max_growth.  If it doesn't fit in this fragment, close this one
3623*3d8817e4Smiod      and start a new one.  In either case, return a pointer to the
3624*3d8817e4Smiod      beginning of the growth area.  */
3625*3d8817e4Smiod 
3626*3d8817e4Smiod   fragS *old_frag;
3627*3d8817e4Smiod 
3628*3d8817e4Smiod   xg_force_frag_space (max_growth);
3629*3d8817e4Smiod 
3630*3d8817e4Smiod   old_frag = frag_now;
3631*3d8817e4Smiod 
3632*3d8817e4Smiod   frag_now->fr_opcode = last_insn;
3633*3d8817e4Smiod   if (is_insn)
3634*3d8817e4Smiod     frag_now->tc_frag_data.is_insn = TRUE;
3635*3d8817e4Smiod 
3636*3d8817e4Smiod   frag_var (rs_machine_dependent, max_growth, max_growth,
3637*3d8817e4Smiod 	    frag_state, frag_now->fr_symbol, frag_now->fr_offset, last_insn);
3638*3d8817e4Smiod 
3639*3d8817e4Smiod   old_frag->tc_frag_data.slot_subtypes[0] = slot0_state;
3640*3d8817e4Smiod   xtensa_set_frag_assembly_state (frag_now);
3641*3d8817e4Smiod 
3642*3d8817e4Smiod   /* Just to make sure that we did not split it up.  */
3643*3d8817e4Smiod   assert (old_frag->fr_next == frag_now);
3644*3d8817e4Smiod }
3645*3d8817e4Smiod 
3646*3d8817e4Smiod 
3647*3d8817e4Smiod /* Return TRUE if the target frag is one of the next non-empty frags.  */
3648*3d8817e4Smiod 
3649*3d8817e4Smiod static bfd_boolean
is_next_frag_target(const fragS * fragP,const fragS * target)3650*3d8817e4Smiod is_next_frag_target (const fragS *fragP, const fragS *target)
3651*3d8817e4Smiod {
3652*3d8817e4Smiod   if (fragP == NULL)
3653*3d8817e4Smiod     return FALSE;
3654*3d8817e4Smiod 
3655*3d8817e4Smiod   for (; fragP; fragP = fragP->fr_next)
3656*3d8817e4Smiod     {
3657*3d8817e4Smiod       if (fragP == target)
3658*3d8817e4Smiod 	return TRUE;
3659*3d8817e4Smiod       if (fragP->fr_fix != 0)
3660*3d8817e4Smiod 	return FALSE;
3661*3d8817e4Smiod       if (fragP->fr_type == rs_fill && fragP->fr_offset != 0)
3662*3d8817e4Smiod 	return FALSE;
3663*3d8817e4Smiod       if ((fragP->fr_type == rs_align || fragP->fr_type == rs_align_code)
3664*3d8817e4Smiod 	  && ((fragP->fr_address % (1 << fragP->fr_offset)) != 0))
3665*3d8817e4Smiod 	return FALSE;
3666*3d8817e4Smiod       if (fragP->fr_type == rs_space)
3667*3d8817e4Smiod 	return FALSE;
3668*3d8817e4Smiod     }
3669*3d8817e4Smiod   return FALSE;
3670*3d8817e4Smiod }
3671*3d8817e4Smiod 
3672*3d8817e4Smiod 
3673*3d8817e4Smiod static bfd_boolean
is_branch_jmp_to_next(TInsn * insn,fragS * fragP)3674*3d8817e4Smiod is_branch_jmp_to_next (TInsn *insn, fragS *fragP)
3675*3d8817e4Smiod {
3676*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
3677*3d8817e4Smiod   int i;
3678*3d8817e4Smiod   int num_ops = xtensa_opcode_num_operands (isa, insn->opcode);
3679*3d8817e4Smiod   int target_op = -1;
3680*3d8817e4Smiod   symbolS *sym;
3681*3d8817e4Smiod   fragS *target_frag;
3682*3d8817e4Smiod 
3683*3d8817e4Smiod   if (xtensa_opcode_is_branch (isa, insn->opcode) == 0
3684*3d8817e4Smiod       && xtensa_opcode_is_jump (isa, insn->opcode) == 0)
3685*3d8817e4Smiod     return FALSE;
3686*3d8817e4Smiod 
3687*3d8817e4Smiod   for (i = 0; i < num_ops; i++)
3688*3d8817e4Smiod     {
3689*3d8817e4Smiod       if (xtensa_operand_is_PCrelative (isa, insn->opcode, i) == 1)
3690*3d8817e4Smiod 	{
3691*3d8817e4Smiod 	  target_op = i;
3692*3d8817e4Smiod 	  break;
3693*3d8817e4Smiod 	}
3694*3d8817e4Smiod     }
3695*3d8817e4Smiod   if (target_op == -1)
3696*3d8817e4Smiod     return FALSE;
3697*3d8817e4Smiod 
3698*3d8817e4Smiod   if (insn->ntok <= target_op)
3699*3d8817e4Smiod     return FALSE;
3700*3d8817e4Smiod 
3701*3d8817e4Smiod   if (insn->tok[target_op].X_op != O_symbol)
3702*3d8817e4Smiod     return FALSE;
3703*3d8817e4Smiod 
3704*3d8817e4Smiod   sym = insn->tok[target_op].X_add_symbol;
3705*3d8817e4Smiod   if (sym == NULL)
3706*3d8817e4Smiod     return FALSE;
3707*3d8817e4Smiod 
3708*3d8817e4Smiod   if (insn->tok[target_op].X_add_number != 0)
3709*3d8817e4Smiod     return FALSE;
3710*3d8817e4Smiod 
3711*3d8817e4Smiod   target_frag = symbol_get_frag (sym);
3712*3d8817e4Smiod   if (target_frag == NULL)
3713*3d8817e4Smiod     return FALSE;
3714*3d8817e4Smiod 
3715*3d8817e4Smiod   if (is_next_frag_target (fragP->fr_next, target_frag)
3716*3d8817e4Smiod       && S_GET_VALUE (sym) == target_frag->fr_address)
3717*3d8817e4Smiod     return TRUE;
3718*3d8817e4Smiod 
3719*3d8817e4Smiod   return FALSE;
3720*3d8817e4Smiod }
3721*3d8817e4Smiod 
3722*3d8817e4Smiod 
3723*3d8817e4Smiod static void
xg_add_branch_and_loop_targets(TInsn * insn)3724*3d8817e4Smiod xg_add_branch_and_loop_targets (TInsn *insn)
3725*3d8817e4Smiod {
3726*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
3727*3d8817e4Smiod   int num_ops = xtensa_opcode_num_operands (isa, insn->opcode);
3728*3d8817e4Smiod 
3729*3d8817e4Smiod   if (xtensa_opcode_is_loop (isa, insn->opcode) == 1)
3730*3d8817e4Smiod     {
3731*3d8817e4Smiod       int i = 1;
3732*3d8817e4Smiod       if (xtensa_operand_is_PCrelative (isa, insn->opcode, i) == 1
3733*3d8817e4Smiod 	  && insn->tok[i].X_op == O_symbol)
3734*3d8817e4Smiod 	symbol_get_tc (insn->tok[i].X_add_symbol)->is_loop_target = TRUE;
3735*3d8817e4Smiod       return;
3736*3d8817e4Smiod     }
3737*3d8817e4Smiod 
3738*3d8817e4Smiod   if (xtensa_opcode_is_branch (isa, insn->opcode) == 1
3739*3d8817e4Smiod       || xtensa_opcode_is_loop (isa, insn->opcode) == 1)
3740*3d8817e4Smiod     {
3741*3d8817e4Smiod       int i;
3742*3d8817e4Smiod 
3743*3d8817e4Smiod       for (i = 0; i < insn->ntok && i < num_ops; i++)
3744*3d8817e4Smiod 	{
3745*3d8817e4Smiod 	  if (xtensa_operand_is_PCrelative (isa, insn->opcode, i) == 1
3746*3d8817e4Smiod 	      && insn->tok[i].X_op == O_symbol)
3747*3d8817e4Smiod 	    {
3748*3d8817e4Smiod 	      symbolS *sym = insn->tok[i].X_add_symbol;
3749*3d8817e4Smiod 	      symbol_get_tc (sym)->is_branch_target = TRUE;
3750*3d8817e4Smiod 	      if (S_IS_DEFINED (sym))
3751*3d8817e4Smiod 		symbol_get_frag (sym)->tc_frag_data.is_branch_target = TRUE;
3752*3d8817e4Smiod 	    }
3753*3d8817e4Smiod 	}
3754*3d8817e4Smiod     }
3755*3d8817e4Smiod }
3756*3d8817e4Smiod 
3757*3d8817e4Smiod 
3758*3d8817e4Smiod /* Return FALSE if no error.  */
3759*3d8817e4Smiod 
3760*3d8817e4Smiod static bfd_boolean
xg_build_token_insn(BuildInstr * instr_spec,TInsn * old_insn,TInsn * new_insn)3761*3d8817e4Smiod xg_build_token_insn (BuildInstr *instr_spec, TInsn *old_insn, TInsn *new_insn)
3762*3d8817e4Smiod {
3763*3d8817e4Smiod   int num_ops = 0;
3764*3d8817e4Smiod   BuildOp *b_op;
3765*3d8817e4Smiod 
3766*3d8817e4Smiod   switch (instr_spec->typ)
3767*3d8817e4Smiod     {
3768*3d8817e4Smiod     case INSTR_INSTR:
3769*3d8817e4Smiod       new_insn->insn_type = ITYPE_INSN;
3770*3d8817e4Smiod       new_insn->opcode = instr_spec->opcode;
3771*3d8817e4Smiod       new_insn->is_specific_opcode = FALSE;
3772*3d8817e4Smiod       new_insn->linenum = old_insn->linenum;
3773*3d8817e4Smiod       break;
3774*3d8817e4Smiod     case INSTR_LITERAL_DEF:
3775*3d8817e4Smiod       new_insn->insn_type = ITYPE_LITERAL;
3776*3d8817e4Smiod       new_insn->opcode = XTENSA_UNDEFINED;
3777*3d8817e4Smiod       new_insn->is_specific_opcode = FALSE;
3778*3d8817e4Smiod       new_insn->linenum = old_insn->linenum;
3779*3d8817e4Smiod       break;
3780*3d8817e4Smiod     case INSTR_LABEL_DEF:
3781*3d8817e4Smiod       as_bad (_("INSTR_LABEL_DEF not supported yet"));
3782*3d8817e4Smiod       break;
3783*3d8817e4Smiod     }
3784*3d8817e4Smiod 
3785*3d8817e4Smiod   for (b_op = instr_spec->ops; b_op != NULL; b_op = b_op->next)
3786*3d8817e4Smiod     {
3787*3d8817e4Smiod       expressionS *exp;
3788*3d8817e4Smiod       const expressionS *src_exp;
3789*3d8817e4Smiod 
3790*3d8817e4Smiod       num_ops++;
3791*3d8817e4Smiod       switch (b_op->typ)
3792*3d8817e4Smiod 	{
3793*3d8817e4Smiod 	case OP_CONSTANT:
3794*3d8817e4Smiod 	  /* The expression must be the constant.  */
3795*3d8817e4Smiod 	  assert (b_op->op_num < MAX_INSN_ARGS);
3796*3d8817e4Smiod 	  exp = &new_insn->tok[b_op->op_num];
3797*3d8817e4Smiod 	  set_expr_const (exp, b_op->op_data);
3798*3d8817e4Smiod 	  break;
3799*3d8817e4Smiod 
3800*3d8817e4Smiod 	case OP_OPERAND:
3801*3d8817e4Smiod 	  assert (b_op->op_num < MAX_INSN_ARGS);
3802*3d8817e4Smiod 	  assert (b_op->op_data < (unsigned) old_insn->ntok);
3803*3d8817e4Smiod 	  src_exp = &old_insn->tok[b_op->op_data];
3804*3d8817e4Smiod 	  exp = &new_insn->tok[b_op->op_num];
3805*3d8817e4Smiod 	  copy_expr (exp, src_exp);
3806*3d8817e4Smiod 	  break;
3807*3d8817e4Smiod 
3808*3d8817e4Smiod 	case OP_LITERAL:
3809*3d8817e4Smiod 	case OP_LABEL:
3810*3d8817e4Smiod 	  as_bad (_("can't handle generation of literal/labels yet"));
3811*3d8817e4Smiod 	  assert (0);
3812*3d8817e4Smiod 
3813*3d8817e4Smiod 	default:
3814*3d8817e4Smiod 	  as_bad (_("can't handle undefined OP TYPE"));
3815*3d8817e4Smiod 	  assert (0);
3816*3d8817e4Smiod 	}
3817*3d8817e4Smiod     }
3818*3d8817e4Smiod 
3819*3d8817e4Smiod   new_insn->ntok = num_ops;
3820*3d8817e4Smiod   return FALSE;
3821*3d8817e4Smiod }
3822*3d8817e4Smiod 
3823*3d8817e4Smiod 
3824*3d8817e4Smiod /* Return TRUE if it was simplified.  */
3825*3d8817e4Smiod 
3826*3d8817e4Smiod static bfd_boolean
xg_simplify_insn(TInsn * old_insn,TInsn * new_insn)3827*3d8817e4Smiod xg_simplify_insn (TInsn *old_insn, TInsn *new_insn)
3828*3d8817e4Smiod {
3829*3d8817e4Smiod   TransitionRule *rule;
3830*3d8817e4Smiod   BuildInstr *insn_spec;
3831*3d8817e4Smiod 
3832*3d8817e4Smiod   if (old_insn->is_specific_opcode || !density_supported)
3833*3d8817e4Smiod     return FALSE;
3834*3d8817e4Smiod 
3835*3d8817e4Smiod   rule = xg_instruction_match (old_insn);
3836*3d8817e4Smiod   if (rule == NULL)
3837*3d8817e4Smiod     return FALSE;
3838*3d8817e4Smiod 
3839*3d8817e4Smiod   insn_spec = rule->to_instr;
3840*3d8817e4Smiod   /* There should only be one.  */
3841*3d8817e4Smiod   assert (insn_spec != NULL);
3842*3d8817e4Smiod   assert (insn_spec->next == NULL);
3843*3d8817e4Smiod   if (insn_spec->next != NULL)
3844*3d8817e4Smiod     return FALSE;
3845*3d8817e4Smiod 
3846*3d8817e4Smiod   xg_build_token_insn (insn_spec, old_insn, new_insn);
3847*3d8817e4Smiod 
3848*3d8817e4Smiod   return TRUE;
3849*3d8817e4Smiod }
3850*3d8817e4Smiod 
3851*3d8817e4Smiod 
3852*3d8817e4Smiod /* xg_expand_assembly_insn: (1) Simplify the instruction, i.e., l32i ->
3853*3d8817e4Smiod    l32i.n. (2) Check the number of operands.  (3) Place the instruction
3854*3d8817e4Smiod    tokens into the stack or relax it and place multiple
3855*3d8817e4Smiod    instructions/literals onto the stack.  Return FALSE if no error.  */
3856*3d8817e4Smiod 
3857*3d8817e4Smiod static bfd_boolean
xg_expand_assembly_insn(IStack * istack,TInsn * orig_insn)3858*3d8817e4Smiod xg_expand_assembly_insn (IStack *istack, TInsn *orig_insn)
3859*3d8817e4Smiod {
3860*3d8817e4Smiod   int noperands;
3861*3d8817e4Smiod   TInsn new_insn;
3862*3d8817e4Smiod   bfd_boolean do_expand;
3863*3d8817e4Smiod 
3864*3d8817e4Smiod   memset (&new_insn, 0, sizeof (TInsn));
3865*3d8817e4Smiod 
3866*3d8817e4Smiod   /* Narrow it if we can.  xg_simplify_insn now does all the
3867*3d8817e4Smiod      appropriate checking (e.g., for the density option).  */
3868*3d8817e4Smiod   if (xg_simplify_insn (orig_insn, &new_insn))
3869*3d8817e4Smiod     orig_insn = &new_insn;
3870*3d8817e4Smiod 
3871*3d8817e4Smiod   noperands = xtensa_opcode_num_operands (xtensa_default_isa,
3872*3d8817e4Smiod 					  orig_insn->opcode);
3873*3d8817e4Smiod   if (orig_insn->ntok < noperands)
3874*3d8817e4Smiod     {
3875*3d8817e4Smiod       as_bad (_("found %d operands for '%s':  Expected %d"),
3876*3d8817e4Smiod 	      orig_insn->ntok,
3877*3d8817e4Smiod 	      xtensa_opcode_name (xtensa_default_isa, orig_insn->opcode),
3878*3d8817e4Smiod 	      noperands);
3879*3d8817e4Smiod       return TRUE;
3880*3d8817e4Smiod     }
3881*3d8817e4Smiod   if (orig_insn->ntok > noperands)
3882*3d8817e4Smiod     as_warn (_("found too many (%d) operands for '%s':  Expected %d"),
3883*3d8817e4Smiod 	     orig_insn->ntok,
3884*3d8817e4Smiod 	     xtensa_opcode_name (xtensa_default_isa, orig_insn->opcode),
3885*3d8817e4Smiod 	     noperands);
3886*3d8817e4Smiod 
3887*3d8817e4Smiod   /* If there are not enough operands, we will assert above.  If there
3888*3d8817e4Smiod      are too many, just cut out the extras here.  */
3889*3d8817e4Smiod   orig_insn->ntok = noperands;
3890*3d8817e4Smiod 
3891*3d8817e4Smiod   if (tinsn_has_invalid_symbolic_operands (orig_insn))
3892*3d8817e4Smiod     return TRUE;
3893*3d8817e4Smiod 
3894*3d8817e4Smiod   /* If the instruction will definitely need to be relaxed, it is better
3895*3d8817e4Smiod      to expand it now for better scheduling.  Decide whether to expand
3896*3d8817e4Smiod      now....  */
3897*3d8817e4Smiod   do_expand = (!orig_insn->is_specific_opcode && use_transform ());
3898*3d8817e4Smiod 
3899*3d8817e4Smiod   /* Calls should be expanded to longcalls only in the backend relaxation
3900*3d8817e4Smiod      so that the assembly scheduler will keep the L32R/CALLX instructions
3901*3d8817e4Smiod      adjacent.  */
3902*3d8817e4Smiod   if (is_direct_call_opcode (orig_insn->opcode))
3903*3d8817e4Smiod     do_expand = FALSE;
3904*3d8817e4Smiod 
3905*3d8817e4Smiod   if (tinsn_has_symbolic_operands (orig_insn))
3906*3d8817e4Smiod     {
3907*3d8817e4Smiod       /* The values of symbolic operands are not known yet, so only expand
3908*3d8817e4Smiod 	 now if an operand is "complex" (e.g., difference of symbols) and
3909*3d8817e4Smiod 	 will have to be stored as a literal regardless of the value.  */
3910*3d8817e4Smiod       if (!tinsn_has_complex_operands (orig_insn))
3911*3d8817e4Smiod 	do_expand = FALSE;
3912*3d8817e4Smiod     }
3913*3d8817e4Smiod   else if (xg_immeds_fit (orig_insn))
3914*3d8817e4Smiod     do_expand = FALSE;
3915*3d8817e4Smiod 
3916*3d8817e4Smiod   if (do_expand)
3917*3d8817e4Smiod     xg_assembly_relax (istack, orig_insn, 0, 0, 0, 0, 0);
3918*3d8817e4Smiod   else
3919*3d8817e4Smiod     istack_push (istack, orig_insn);
3920*3d8817e4Smiod 
3921*3d8817e4Smiod   return FALSE;
3922*3d8817e4Smiod }
3923*3d8817e4Smiod 
3924*3d8817e4Smiod 
3925*3d8817e4Smiod /* Return TRUE if the section flags are marked linkonce
3926*3d8817e4Smiod    or the name is .gnu.linkonce*.  */
3927*3d8817e4Smiod 
3928*3d8817e4Smiod static bfd_boolean
get_is_linkonce_section(bfd * abfd ATTRIBUTE_UNUSED,segT sec)3929*3d8817e4Smiod get_is_linkonce_section (bfd *abfd ATTRIBUTE_UNUSED, segT sec)
3930*3d8817e4Smiod {
3931*3d8817e4Smiod   flagword flags, link_once_flags;
3932*3d8817e4Smiod 
3933*3d8817e4Smiod   flags = bfd_get_section_flags (abfd, sec);
3934*3d8817e4Smiod   link_once_flags = (flags & SEC_LINK_ONCE);
3935*3d8817e4Smiod 
3936*3d8817e4Smiod   /* Flags might not be set yet.  */
3937*3d8817e4Smiod   if (!link_once_flags)
3938*3d8817e4Smiod     {
3939*3d8817e4Smiod       static size_t len = sizeof ".gnu.linkonce.t.";
3940*3d8817e4Smiod 
3941*3d8817e4Smiod       if (strncmp (segment_name (sec), ".gnu.linkonce.t.", len - 1) == 0)
3942*3d8817e4Smiod 	link_once_flags = SEC_LINK_ONCE;
3943*3d8817e4Smiod     }
3944*3d8817e4Smiod   return (link_once_flags != 0);
3945*3d8817e4Smiod }
3946*3d8817e4Smiod 
3947*3d8817e4Smiod 
3948*3d8817e4Smiod static void
xtensa_add_literal_sym(symbolS * sym)3949*3d8817e4Smiod xtensa_add_literal_sym (symbolS *sym)
3950*3d8817e4Smiod {
3951*3d8817e4Smiod   sym_list *l;
3952*3d8817e4Smiod 
3953*3d8817e4Smiod   l = (sym_list *) xmalloc (sizeof (sym_list));
3954*3d8817e4Smiod   l->sym = sym;
3955*3d8817e4Smiod   l->next = literal_syms;
3956*3d8817e4Smiod   literal_syms = l;
3957*3d8817e4Smiod }
3958*3d8817e4Smiod 
3959*3d8817e4Smiod 
3960*3d8817e4Smiod static symbolS *
xtensa_create_literal_symbol(segT sec,fragS * frag)3961*3d8817e4Smiod xtensa_create_literal_symbol (segT sec, fragS *frag)
3962*3d8817e4Smiod {
3963*3d8817e4Smiod   static int lit_num = 0;
3964*3d8817e4Smiod   static char name[256];
3965*3d8817e4Smiod   symbolS *symbolP;
3966*3d8817e4Smiod 
3967*3d8817e4Smiod   sprintf (name, ".L_lit_sym%d", lit_num);
3968*3d8817e4Smiod 
3969*3d8817e4Smiod   /* Create a local symbol.  If it is in a linkonce section, we have to
3970*3d8817e4Smiod      be careful to make sure that if it is used in a relocation that the
3971*3d8817e4Smiod      symbol will be in the output file.  */
3972*3d8817e4Smiod   if (get_is_linkonce_section (stdoutput, sec))
3973*3d8817e4Smiod     {
3974*3d8817e4Smiod       symbolP = symbol_new (name, sec, 0, frag);
3975*3d8817e4Smiod       S_CLEAR_EXTERNAL (symbolP);
3976*3d8817e4Smiod       /* symbolP->local = 1; */
3977*3d8817e4Smiod     }
3978*3d8817e4Smiod   else
3979*3d8817e4Smiod     symbolP = symbol_new (name, sec, 0, frag);
3980*3d8817e4Smiod 
3981*3d8817e4Smiod   xtensa_add_literal_sym (symbolP);
3982*3d8817e4Smiod 
3983*3d8817e4Smiod   lit_num++;
3984*3d8817e4Smiod   return symbolP;
3985*3d8817e4Smiod }
3986*3d8817e4Smiod 
3987*3d8817e4Smiod 
3988*3d8817e4Smiod /* Currently all literals that are generated here are 32-bit L32R targets.  */
3989*3d8817e4Smiod 
3990*3d8817e4Smiod static symbolS *
xg_assemble_literal(TInsn * insn)3991*3d8817e4Smiod xg_assemble_literal (/* const */ TInsn *insn)
3992*3d8817e4Smiod {
3993*3d8817e4Smiod   emit_state state;
3994*3d8817e4Smiod   symbolS *lit_sym = NULL;
3995*3d8817e4Smiod 
3996*3d8817e4Smiod   /* size = 4 for L32R.  It could easily be larger when we move to
3997*3d8817e4Smiod      larger constants.  Add a parameter later.  */
3998*3d8817e4Smiod   offsetT litsize = 4;
3999*3d8817e4Smiod   offsetT litalign = 2;		/* 2^2 = 4 */
4000*3d8817e4Smiod   expressionS saved_loc;
4001*3d8817e4Smiod   expressionS * emit_val;
4002*3d8817e4Smiod 
4003*3d8817e4Smiod   set_expr_symbol_offset (&saved_loc, frag_now->fr_symbol, frag_now_fix ());
4004*3d8817e4Smiod 
4005*3d8817e4Smiod   assert (insn->insn_type == ITYPE_LITERAL);
4006*3d8817e4Smiod   assert (insn->ntok == 1);	/* must be only one token here */
4007*3d8817e4Smiod 
4008*3d8817e4Smiod   xtensa_switch_to_literal_fragment (&state);
4009*3d8817e4Smiod 
4010*3d8817e4Smiod   emit_val = &insn->tok[0];
4011*3d8817e4Smiod   if (emit_val->X_op == O_big)
4012*3d8817e4Smiod     {
4013*3d8817e4Smiod       int size = emit_val->X_add_number * CHARS_PER_LITTLENUM;
4014*3d8817e4Smiod       if (size > litsize)
4015*3d8817e4Smiod 	{
4016*3d8817e4Smiod 	  /* This happens when someone writes a "movi a2, big_number".  */
4017*3d8817e4Smiod 	  as_bad_where (frag_now->fr_file, frag_now->fr_line,
4018*3d8817e4Smiod 			_("invalid immediate"));
4019*3d8817e4Smiod 	  xtensa_restore_emit_state (&state);
4020*3d8817e4Smiod 	  return NULL;
4021*3d8817e4Smiod 	}
4022*3d8817e4Smiod     }
4023*3d8817e4Smiod 
4024*3d8817e4Smiod   /* Force a 4-byte align here.  Note that this opens a new frag, so all
4025*3d8817e4Smiod      literals done with this function have a frag to themselves.  That's
4026*3d8817e4Smiod      important for the way text section literals work.  */
4027*3d8817e4Smiod   frag_align (litalign, 0, 0);
4028*3d8817e4Smiod   record_alignment (now_seg, litalign);
4029*3d8817e4Smiod 
4030*3d8817e4Smiod   if (emit_val->X_op == O_pltrel)
4031*3d8817e4Smiod     {
4032*3d8817e4Smiod       char *p = frag_more (litsize);
4033*3d8817e4Smiod       xtensa_set_frag_assembly_state (frag_now);
4034*3d8817e4Smiod       if (emit_val->X_add_symbol)
4035*3d8817e4Smiod 	emit_val->X_op = O_symbol;
4036*3d8817e4Smiod       else
4037*3d8817e4Smiod 	emit_val->X_op = O_constant;
4038*3d8817e4Smiod       fix_new_exp (frag_now, p - frag_now->fr_literal,
4039*3d8817e4Smiod 		   litsize, emit_val, 0, BFD_RELOC_XTENSA_PLT);
4040*3d8817e4Smiod     }
4041*3d8817e4Smiod   else
4042*3d8817e4Smiod     emit_expr (emit_val, litsize);
4043*3d8817e4Smiod 
4044*3d8817e4Smiod   assert (frag_now->tc_frag_data.literal_frag == NULL);
4045*3d8817e4Smiod   frag_now->tc_frag_data.literal_frag = get_literal_pool_location (now_seg);
4046*3d8817e4Smiod   frag_now->fr_symbol = xtensa_create_literal_symbol (now_seg, frag_now);
4047*3d8817e4Smiod   lit_sym = frag_now->fr_symbol;
4048*3d8817e4Smiod 
4049*3d8817e4Smiod   /* Go back.  */
4050*3d8817e4Smiod   xtensa_restore_emit_state (&state);
4051*3d8817e4Smiod   return lit_sym;
4052*3d8817e4Smiod }
4053*3d8817e4Smiod 
4054*3d8817e4Smiod 
4055*3d8817e4Smiod static void
xg_assemble_literal_space(int size,int slot)4056*3d8817e4Smiod xg_assemble_literal_space (/* const */ int size, int slot)
4057*3d8817e4Smiod {
4058*3d8817e4Smiod   emit_state state;
4059*3d8817e4Smiod   /* We might have to do something about this alignment.  It only
4060*3d8817e4Smiod      takes effect if something is placed here.  */
4061*3d8817e4Smiod   offsetT litalign = 2;		/* 2^2 = 4 */
4062*3d8817e4Smiod   fragS *lit_saved_frag;
4063*3d8817e4Smiod 
4064*3d8817e4Smiod   assert (size % 4 == 0);
4065*3d8817e4Smiod 
4066*3d8817e4Smiod   xtensa_switch_to_literal_fragment (&state);
4067*3d8817e4Smiod 
4068*3d8817e4Smiod   /* Force a 4-byte align here.  */
4069*3d8817e4Smiod   frag_align (litalign, 0, 0);
4070*3d8817e4Smiod   record_alignment (now_seg, litalign);
4071*3d8817e4Smiod 
4072*3d8817e4Smiod   xg_force_frag_space (size);
4073*3d8817e4Smiod 
4074*3d8817e4Smiod   lit_saved_frag = frag_now;
4075*3d8817e4Smiod   frag_now->tc_frag_data.literal_frag = get_literal_pool_location (now_seg);
4076*3d8817e4Smiod   frag_now->fr_symbol = xtensa_create_literal_symbol (now_seg, frag_now);
4077*3d8817e4Smiod   xg_finish_frag (0, RELAX_LITERAL, 0, size, FALSE);
4078*3d8817e4Smiod 
4079*3d8817e4Smiod   /* Go back.  */
4080*3d8817e4Smiod   xtensa_restore_emit_state (&state);
4081*3d8817e4Smiod   frag_now->tc_frag_data.literal_frags[slot] = lit_saved_frag;
4082*3d8817e4Smiod }
4083*3d8817e4Smiod 
4084*3d8817e4Smiod 
4085*3d8817e4Smiod /* Put in a fixup record based on the opcode.
4086*3d8817e4Smiod    Return TRUE on success.  */
4087*3d8817e4Smiod 
4088*3d8817e4Smiod static bfd_boolean
xg_add_opcode_fix(TInsn * tinsn,int opnum,xtensa_format fmt,int slot,expressionS * expr,fragS * fragP,offsetT offset)4089*3d8817e4Smiod xg_add_opcode_fix (TInsn *tinsn,
4090*3d8817e4Smiod 		   int opnum,
4091*3d8817e4Smiod 		   xtensa_format fmt,
4092*3d8817e4Smiod 		   int slot,
4093*3d8817e4Smiod 		   expressionS *expr,
4094*3d8817e4Smiod 		   fragS *fragP,
4095*3d8817e4Smiod 		   offsetT offset)
4096*3d8817e4Smiod {
4097*3d8817e4Smiod   xtensa_opcode opcode = tinsn->opcode;
4098*3d8817e4Smiod   bfd_reloc_code_real_type reloc;
4099*3d8817e4Smiod   reloc_howto_type *howto;
4100*3d8817e4Smiod   int fmt_length;
4101*3d8817e4Smiod   fixS *the_fix;
4102*3d8817e4Smiod 
4103*3d8817e4Smiod   reloc = BFD_RELOC_NONE;
4104*3d8817e4Smiod 
4105*3d8817e4Smiod   /* First try the special cases for "alternate" relocs.  */
4106*3d8817e4Smiod   if (opcode == xtensa_l32r_opcode)
4107*3d8817e4Smiod     {
4108*3d8817e4Smiod       if (fragP->tc_frag_data.use_absolute_literals)
4109*3d8817e4Smiod 	reloc = encode_alt_reloc (slot);
4110*3d8817e4Smiod     }
4111*3d8817e4Smiod   else if (opcode == xtensa_const16_opcode)
4112*3d8817e4Smiod     {
4113*3d8817e4Smiod       if (expr->X_op == O_lo16)
4114*3d8817e4Smiod 	{
4115*3d8817e4Smiod 	  reloc = encode_reloc (slot);
4116*3d8817e4Smiod 	  expr->X_op = O_symbol;
4117*3d8817e4Smiod 	}
4118*3d8817e4Smiod       else if (expr->X_op == O_hi16)
4119*3d8817e4Smiod 	{
4120*3d8817e4Smiod 	  reloc = encode_alt_reloc (slot);
4121*3d8817e4Smiod 	  expr->X_op = O_symbol;
4122*3d8817e4Smiod 	}
4123*3d8817e4Smiod     }
4124*3d8817e4Smiod 
4125*3d8817e4Smiod   if (opnum != get_relaxable_immed (opcode))
4126*3d8817e4Smiod     {
4127*3d8817e4Smiod       as_bad (_("invalid relocation for operand %i of '%s'"),
4128*3d8817e4Smiod 	      opnum + 1, xtensa_opcode_name (xtensa_default_isa, opcode));
4129*3d8817e4Smiod       return FALSE;
4130*3d8817e4Smiod     }
4131*3d8817e4Smiod 
4132*3d8817e4Smiod   /* Handle erroneous "@h" and "@l" expressions here before they propagate
4133*3d8817e4Smiod      into the symbol table where the generic portions of the assembler
4134*3d8817e4Smiod      won't know what to do with them.  */
4135*3d8817e4Smiod   if (expr->X_op == O_lo16 || expr->X_op == O_hi16)
4136*3d8817e4Smiod     {
4137*3d8817e4Smiod       as_bad (_("invalid expression for operand %i of '%s'"),
4138*3d8817e4Smiod 	      opnum + 1, xtensa_opcode_name (xtensa_default_isa, opcode));
4139*3d8817e4Smiod       return FALSE;
4140*3d8817e4Smiod     }
4141*3d8817e4Smiod 
4142*3d8817e4Smiod   /* Next try the generic relocs.  */
4143*3d8817e4Smiod   if (reloc == BFD_RELOC_NONE)
4144*3d8817e4Smiod     reloc = encode_reloc (slot);
4145*3d8817e4Smiod   if (reloc == BFD_RELOC_NONE)
4146*3d8817e4Smiod     {
4147*3d8817e4Smiod       as_bad (_("invalid relocation in instruction slot %i"), slot);
4148*3d8817e4Smiod       return FALSE;
4149*3d8817e4Smiod     }
4150*3d8817e4Smiod 
4151*3d8817e4Smiod   howto = bfd_reloc_type_lookup (stdoutput, reloc);
4152*3d8817e4Smiod   if (!howto)
4153*3d8817e4Smiod     {
4154*3d8817e4Smiod       as_bad (_("undefined symbol for opcode \"%s\""),
4155*3d8817e4Smiod 	      xtensa_opcode_name (xtensa_default_isa, opcode));
4156*3d8817e4Smiod       return FALSE;
4157*3d8817e4Smiod     }
4158*3d8817e4Smiod 
4159*3d8817e4Smiod   fmt_length = xtensa_format_length (xtensa_default_isa, fmt);
4160*3d8817e4Smiod   the_fix = fix_new_exp (fragP, offset, fmt_length, expr,
4161*3d8817e4Smiod 			 howto->pc_relative, reloc);
4162*3d8817e4Smiod   the_fix->fx_no_overflow = 1;
4163*3d8817e4Smiod 
4164*3d8817e4Smiod   if (expr->X_add_symbol
4165*3d8817e4Smiod       && (S_IS_EXTERNAL (expr->X_add_symbol)
4166*3d8817e4Smiod 	  || S_IS_WEAK (expr->X_add_symbol)))
4167*3d8817e4Smiod     the_fix->fx_plt = TRUE;
4168*3d8817e4Smiod 
4169*3d8817e4Smiod   the_fix->tc_fix_data.X_add_symbol = expr->X_add_symbol;
4170*3d8817e4Smiod   the_fix->tc_fix_data.X_add_number = expr->X_add_number;
4171*3d8817e4Smiod   the_fix->tc_fix_data.slot = slot;
4172*3d8817e4Smiod 
4173*3d8817e4Smiod   return TRUE;
4174*3d8817e4Smiod }
4175*3d8817e4Smiod 
4176*3d8817e4Smiod 
4177*3d8817e4Smiod static bfd_boolean
xg_emit_insn_to_buf(TInsn * tinsn,char * buf,fragS * fragP,offsetT offset,bfd_boolean build_fix)4178*3d8817e4Smiod xg_emit_insn_to_buf (TInsn *tinsn,
4179*3d8817e4Smiod 		     char *buf,
4180*3d8817e4Smiod 		     fragS *fragP,
4181*3d8817e4Smiod 		     offsetT offset,
4182*3d8817e4Smiod 		     bfd_boolean build_fix)
4183*3d8817e4Smiod {
4184*3d8817e4Smiod   static xtensa_insnbuf insnbuf = NULL;
4185*3d8817e4Smiod   bfd_boolean has_symbolic_immed = FALSE;
4186*3d8817e4Smiod   bfd_boolean ok = TRUE;
4187*3d8817e4Smiod 
4188*3d8817e4Smiod   if (!insnbuf)
4189*3d8817e4Smiod     insnbuf = xtensa_insnbuf_alloc (xtensa_default_isa);
4190*3d8817e4Smiod 
4191*3d8817e4Smiod   has_symbolic_immed = tinsn_to_insnbuf (tinsn, insnbuf);
4192*3d8817e4Smiod   if (has_symbolic_immed && build_fix)
4193*3d8817e4Smiod     {
4194*3d8817e4Smiod       /* Add a fixup.  */
4195*3d8817e4Smiod       xtensa_format fmt = xg_get_single_format (tinsn->opcode);
4196*3d8817e4Smiod       int slot = xg_get_single_slot (tinsn->opcode);
4197*3d8817e4Smiod       int opnum = get_relaxable_immed (tinsn->opcode);
4198*3d8817e4Smiod       expressionS *exp = &tinsn->tok[opnum];
4199*3d8817e4Smiod 
4200*3d8817e4Smiod       if (!xg_add_opcode_fix (tinsn, opnum, fmt, slot, exp, fragP, offset))
4201*3d8817e4Smiod 	ok = FALSE;
4202*3d8817e4Smiod     }
4203*3d8817e4Smiod   fragP->tc_frag_data.is_insn = TRUE;
4204*3d8817e4Smiod   xtensa_insnbuf_to_chars (xtensa_default_isa, insnbuf,
4205*3d8817e4Smiod 			   (unsigned char *) buf, 0);
4206*3d8817e4Smiod   return ok;
4207*3d8817e4Smiod }
4208*3d8817e4Smiod 
4209*3d8817e4Smiod 
4210*3d8817e4Smiod static void
xg_resolve_literals(TInsn * insn,symbolS * lit_sym)4211*3d8817e4Smiod xg_resolve_literals (TInsn *insn, symbolS *lit_sym)
4212*3d8817e4Smiod {
4213*3d8817e4Smiod   symbolS *sym = get_special_literal_symbol ();
4214*3d8817e4Smiod   int i;
4215*3d8817e4Smiod   if (lit_sym == 0)
4216*3d8817e4Smiod     return;
4217*3d8817e4Smiod   assert (insn->insn_type == ITYPE_INSN);
4218*3d8817e4Smiod   for (i = 0; i < insn->ntok; i++)
4219*3d8817e4Smiod     if (insn->tok[i].X_add_symbol == sym)
4220*3d8817e4Smiod       insn->tok[i].X_add_symbol = lit_sym;
4221*3d8817e4Smiod 
4222*3d8817e4Smiod }
4223*3d8817e4Smiod 
4224*3d8817e4Smiod 
4225*3d8817e4Smiod static void
xg_resolve_labels(TInsn * insn,symbolS * label_sym)4226*3d8817e4Smiod xg_resolve_labels (TInsn *insn, symbolS *label_sym)
4227*3d8817e4Smiod {
4228*3d8817e4Smiod   symbolS *sym = get_special_label_symbol ();
4229*3d8817e4Smiod   int i;
4230*3d8817e4Smiod   for (i = 0; i < insn->ntok; i++)
4231*3d8817e4Smiod     if (insn->tok[i].X_add_symbol == sym)
4232*3d8817e4Smiod       insn->tok[i].X_add_symbol = label_sym;
4233*3d8817e4Smiod 
4234*3d8817e4Smiod }
4235*3d8817e4Smiod 
4236*3d8817e4Smiod 
4237*3d8817e4Smiod /* Return TRUE if the instruction can write to the specified
4238*3d8817e4Smiod    integer register.  */
4239*3d8817e4Smiod 
4240*3d8817e4Smiod static bfd_boolean
is_register_writer(const TInsn * insn,const char * regset,int regnum)4241*3d8817e4Smiod is_register_writer (const TInsn *insn, const char *regset, int regnum)
4242*3d8817e4Smiod {
4243*3d8817e4Smiod   int i;
4244*3d8817e4Smiod   int num_ops;
4245*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
4246*3d8817e4Smiod 
4247*3d8817e4Smiod   num_ops = xtensa_opcode_num_operands (isa, insn->opcode);
4248*3d8817e4Smiod 
4249*3d8817e4Smiod   for (i = 0; i < num_ops; i++)
4250*3d8817e4Smiod     {
4251*3d8817e4Smiod       char inout;
4252*3d8817e4Smiod       inout = xtensa_operand_inout (isa, insn->opcode, i);
4253*3d8817e4Smiod       if ((inout == 'o' || inout == 'm')
4254*3d8817e4Smiod 	  && xtensa_operand_is_register (isa, insn->opcode, i) == 1)
4255*3d8817e4Smiod 	{
4256*3d8817e4Smiod 	  xtensa_regfile opnd_rf =
4257*3d8817e4Smiod 	    xtensa_operand_regfile (isa, insn->opcode, i);
4258*3d8817e4Smiod 	  if (!strcmp (xtensa_regfile_shortname (isa, opnd_rf), regset))
4259*3d8817e4Smiod 	    {
4260*3d8817e4Smiod 	      if ((insn->tok[i].X_op == O_register)
4261*3d8817e4Smiod 		  && (insn->tok[i].X_add_number == regnum))
4262*3d8817e4Smiod 		return TRUE;
4263*3d8817e4Smiod 	    }
4264*3d8817e4Smiod 	}
4265*3d8817e4Smiod     }
4266*3d8817e4Smiod   return FALSE;
4267*3d8817e4Smiod }
4268*3d8817e4Smiod 
4269*3d8817e4Smiod 
4270*3d8817e4Smiod static bfd_boolean
is_bad_loopend_opcode(const TInsn * tinsn)4271*3d8817e4Smiod is_bad_loopend_opcode (const TInsn *tinsn)
4272*3d8817e4Smiod {
4273*3d8817e4Smiod   xtensa_opcode opcode = tinsn->opcode;
4274*3d8817e4Smiod 
4275*3d8817e4Smiod   if (opcode == XTENSA_UNDEFINED)
4276*3d8817e4Smiod     return FALSE;
4277*3d8817e4Smiod 
4278*3d8817e4Smiod   if (opcode == xtensa_call0_opcode
4279*3d8817e4Smiod       || opcode == xtensa_callx0_opcode
4280*3d8817e4Smiod       || opcode == xtensa_call4_opcode
4281*3d8817e4Smiod       || opcode == xtensa_callx4_opcode
4282*3d8817e4Smiod       || opcode == xtensa_call8_opcode
4283*3d8817e4Smiod       || opcode == xtensa_callx8_opcode
4284*3d8817e4Smiod       || opcode == xtensa_call12_opcode
4285*3d8817e4Smiod       || opcode == xtensa_callx12_opcode
4286*3d8817e4Smiod       || opcode == xtensa_isync_opcode
4287*3d8817e4Smiod       || opcode == xtensa_ret_opcode
4288*3d8817e4Smiod       || opcode == xtensa_ret_n_opcode
4289*3d8817e4Smiod       || opcode == xtensa_retw_opcode
4290*3d8817e4Smiod       || opcode == xtensa_retw_n_opcode
4291*3d8817e4Smiod       || opcode == xtensa_waiti_opcode
4292*3d8817e4Smiod       || opcode == xtensa_rsr_lcount_opcode)
4293*3d8817e4Smiod     return TRUE;
4294*3d8817e4Smiod 
4295*3d8817e4Smiod   return FALSE;
4296*3d8817e4Smiod }
4297*3d8817e4Smiod 
4298*3d8817e4Smiod 
4299*3d8817e4Smiod /* Labels that begin with ".Ln" or ".LM"  are unaligned.
4300*3d8817e4Smiod    This allows the debugger to add unaligned labels.
4301*3d8817e4Smiod    Also, the assembler generates stabs labels that need
4302*3d8817e4Smiod    not be aligned:  FAKE_LABEL_NAME . {"F", "L", "endfunc"}.  */
4303*3d8817e4Smiod 
4304*3d8817e4Smiod static bfd_boolean
is_unaligned_label(symbolS * sym)4305*3d8817e4Smiod is_unaligned_label (symbolS *sym)
4306*3d8817e4Smiod {
4307*3d8817e4Smiod   const char *name = S_GET_NAME (sym);
4308*3d8817e4Smiod   static size_t fake_size = 0;
4309*3d8817e4Smiod 
4310*3d8817e4Smiod   if (name
4311*3d8817e4Smiod       && name[0] == '.'
4312*3d8817e4Smiod       && name[1] == 'L' && (name[2] == 'n' || name[2] == 'M'))
4313*3d8817e4Smiod     return TRUE;
4314*3d8817e4Smiod 
4315*3d8817e4Smiod   /* FAKE_LABEL_NAME followed by "F", "L" or "endfunc" */
4316*3d8817e4Smiod   if (fake_size == 0)
4317*3d8817e4Smiod     fake_size = strlen (FAKE_LABEL_NAME);
4318*3d8817e4Smiod 
4319*3d8817e4Smiod   if (name
4320*3d8817e4Smiod       && strncmp (FAKE_LABEL_NAME, name, fake_size) == 0
4321*3d8817e4Smiod       && (name[fake_size] == 'F'
4322*3d8817e4Smiod 	  || name[fake_size] == 'L'
4323*3d8817e4Smiod 	  || (name[fake_size] == 'e'
4324*3d8817e4Smiod 	      && strncmp ("endfunc", name+fake_size, 7) == 0)))
4325*3d8817e4Smiod     return TRUE;
4326*3d8817e4Smiod 
4327*3d8817e4Smiod   return FALSE;
4328*3d8817e4Smiod }
4329*3d8817e4Smiod 
4330*3d8817e4Smiod 
4331*3d8817e4Smiod static fragS *
next_non_empty_frag(const fragS * fragP)4332*3d8817e4Smiod next_non_empty_frag (const fragS *fragP)
4333*3d8817e4Smiod {
4334*3d8817e4Smiod   fragS *next_fragP = fragP->fr_next;
4335*3d8817e4Smiod 
4336*3d8817e4Smiod   /* Sometimes an empty will end up here due storage allocation issues.
4337*3d8817e4Smiod      So we have to skip until we find something legit.  */
4338*3d8817e4Smiod   while (next_fragP && next_fragP->fr_fix == 0)
4339*3d8817e4Smiod     next_fragP = next_fragP->fr_next;
4340*3d8817e4Smiod 
4341*3d8817e4Smiod   if (next_fragP == NULL || next_fragP->fr_fix == 0)
4342*3d8817e4Smiod     return NULL;
4343*3d8817e4Smiod 
4344*3d8817e4Smiod   return next_fragP;
4345*3d8817e4Smiod }
4346*3d8817e4Smiod 
4347*3d8817e4Smiod 
4348*3d8817e4Smiod static bfd_boolean
next_frag_opcode_is_loop(const fragS * fragP,xtensa_opcode * opcode)4349*3d8817e4Smiod next_frag_opcode_is_loop (const fragS *fragP, xtensa_opcode *opcode)
4350*3d8817e4Smiod {
4351*3d8817e4Smiod   xtensa_opcode out_opcode;
4352*3d8817e4Smiod   const fragS *next_fragP = next_non_empty_frag (fragP);
4353*3d8817e4Smiod 
4354*3d8817e4Smiod   if (next_fragP == NULL)
4355*3d8817e4Smiod     return FALSE;
4356*3d8817e4Smiod 
4357*3d8817e4Smiod   out_opcode = get_opcode_from_buf (next_fragP->fr_literal, 0);
4358*3d8817e4Smiod   if (xtensa_opcode_is_loop (xtensa_default_isa, out_opcode) == 1)
4359*3d8817e4Smiod     {
4360*3d8817e4Smiod       *opcode = out_opcode;
4361*3d8817e4Smiod       return TRUE;
4362*3d8817e4Smiod     }
4363*3d8817e4Smiod   return FALSE;
4364*3d8817e4Smiod }
4365*3d8817e4Smiod 
4366*3d8817e4Smiod 
4367*3d8817e4Smiod static int
frag_format_size(const fragS * fragP)4368*3d8817e4Smiod frag_format_size (const fragS *fragP)
4369*3d8817e4Smiod {
4370*3d8817e4Smiod   static xtensa_insnbuf insnbuf = NULL;
4371*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
4372*3d8817e4Smiod   xtensa_format fmt;
4373*3d8817e4Smiod   int fmt_size;
4374*3d8817e4Smiod 
4375*3d8817e4Smiod   if (!insnbuf)
4376*3d8817e4Smiod     insnbuf = xtensa_insnbuf_alloc (isa);
4377*3d8817e4Smiod 
4378*3d8817e4Smiod   if (fragP == NULL)
4379*3d8817e4Smiod     return XTENSA_UNDEFINED;
4380*3d8817e4Smiod 
4381*3d8817e4Smiod   xtensa_insnbuf_from_chars (isa, insnbuf,
4382*3d8817e4Smiod 			     (unsigned char *) fragP->fr_literal, 0);
4383*3d8817e4Smiod 
4384*3d8817e4Smiod   fmt = xtensa_format_decode (isa, insnbuf);
4385*3d8817e4Smiod   if (fmt == XTENSA_UNDEFINED)
4386*3d8817e4Smiod     return XTENSA_UNDEFINED;
4387*3d8817e4Smiod   fmt_size = xtensa_format_length (isa, fmt);
4388*3d8817e4Smiod 
4389*3d8817e4Smiod   /* If the next format won't be changing due to relaxation, just
4390*3d8817e4Smiod      return the length of the first format.  */
4391*3d8817e4Smiod   if (fragP->fr_opcode != fragP->fr_literal)
4392*3d8817e4Smiod     return fmt_size;
4393*3d8817e4Smiod 
4394*3d8817e4Smiod   /* If during relaxation we have to pull an instruction out of a
4395*3d8817e4Smiod      multi-slot instruction, we will return the more conservative
4396*3d8817e4Smiod      number.  This works because alignment on bigger instructions
4397*3d8817e4Smiod      is more restrictive than alignment on smaller instructions.
4398*3d8817e4Smiod      This is more conservative than we would like, but it happens
4399*3d8817e4Smiod      infrequently.  */
4400*3d8817e4Smiod 
4401*3d8817e4Smiod   if (xtensa_format_num_slots (xtensa_default_isa, fmt) > 1)
4402*3d8817e4Smiod     return fmt_size;
4403*3d8817e4Smiod 
4404*3d8817e4Smiod   /* If we aren't doing one of our own relaxations or it isn't
4405*3d8817e4Smiod      slot-based, then the insn size won't change.  */
4406*3d8817e4Smiod   if (fragP->fr_type != rs_machine_dependent)
4407*3d8817e4Smiod     return fmt_size;
4408*3d8817e4Smiod   if (fragP->fr_subtype != RELAX_SLOTS)
4409*3d8817e4Smiod     return fmt_size;
4410*3d8817e4Smiod 
4411*3d8817e4Smiod   /* If an instruction is about to grow, return the longer size.  */
4412*3d8817e4Smiod   if (fragP->tc_frag_data.slot_subtypes[0] == RELAX_IMMED_STEP1
4413*3d8817e4Smiod       || fragP->tc_frag_data.slot_subtypes[0] == RELAX_IMMED_STEP2)
4414*3d8817e4Smiod     return 3;
4415*3d8817e4Smiod 
4416*3d8817e4Smiod   if (fragP->tc_frag_data.slot_subtypes[0] == RELAX_NARROW)
4417*3d8817e4Smiod     return 2 + fragP->tc_frag_data.text_expansion[0];
4418*3d8817e4Smiod 
4419*3d8817e4Smiod   return fmt_size;
4420*3d8817e4Smiod }
4421*3d8817e4Smiod 
4422*3d8817e4Smiod 
4423*3d8817e4Smiod static int
next_frag_format_size(const fragS * fragP)4424*3d8817e4Smiod next_frag_format_size (const fragS *fragP)
4425*3d8817e4Smiod {
4426*3d8817e4Smiod   const fragS *next_fragP = next_non_empty_frag (fragP);
4427*3d8817e4Smiod   return frag_format_size (next_fragP);
4428*3d8817e4Smiod }
4429*3d8817e4Smiod 
4430*3d8817e4Smiod 
4431*3d8817e4Smiod /* In early Xtensa Processors, for reasons that are unclear, the ISA
4432*3d8817e4Smiod    required two-byte instructions to be treated as three-byte instructions
4433*3d8817e4Smiod    for loop instruction alignment.  This restriction was removed beginning
4434*3d8817e4Smiod    with Xtensa LX.  Now the only requirement on loop instruction alignment
4435*3d8817e4Smiod    is that the first instruction of the loop must appear at an address that
4436*3d8817e4Smiod    does not cross a fetch boundary.  */
4437*3d8817e4Smiod 
4438*3d8817e4Smiod static int
get_loop_align_size(int insn_size)4439*3d8817e4Smiod get_loop_align_size (int insn_size)
4440*3d8817e4Smiod {
4441*3d8817e4Smiod   if (insn_size == XTENSA_UNDEFINED)
4442*3d8817e4Smiod     return xtensa_fetch_width;
4443*3d8817e4Smiod 
4444*3d8817e4Smiod   if (enforce_three_byte_loop_align && insn_size == 2)
4445*3d8817e4Smiod     return 3;
4446*3d8817e4Smiod 
4447*3d8817e4Smiod   return insn_size;
4448*3d8817e4Smiod }
4449*3d8817e4Smiod 
4450*3d8817e4Smiod 
4451*3d8817e4Smiod /* If the next legit fragment is an end-of-loop marker,
4452*3d8817e4Smiod    switch its state so it will instantiate a NOP.  */
4453*3d8817e4Smiod 
4454*3d8817e4Smiod static void
update_next_frag_state(fragS * fragP)4455*3d8817e4Smiod update_next_frag_state (fragS *fragP)
4456*3d8817e4Smiod {
4457*3d8817e4Smiod   fragS *next_fragP = fragP->fr_next;
4458*3d8817e4Smiod   fragS *new_target = NULL;
4459*3d8817e4Smiod 
4460*3d8817e4Smiod   if (align_targets)
4461*3d8817e4Smiod     {
4462*3d8817e4Smiod       /* We are guaranteed there will be one of these...   */
4463*3d8817e4Smiod       while (!(next_fragP->fr_type == rs_machine_dependent
4464*3d8817e4Smiod 	       && (next_fragP->fr_subtype == RELAX_MAYBE_UNREACHABLE
4465*3d8817e4Smiod 		   || next_fragP->fr_subtype == RELAX_UNREACHABLE)))
4466*3d8817e4Smiod 	next_fragP = next_fragP->fr_next;
4467*3d8817e4Smiod 
4468*3d8817e4Smiod       assert (next_fragP->fr_type == rs_machine_dependent
4469*3d8817e4Smiod 	      && (next_fragP->fr_subtype == RELAX_MAYBE_UNREACHABLE
4470*3d8817e4Smiod 		  || next_fragP->fr_subtype == RELAX_UNREACHABLE));
4471*3d8817e4Smiod 
4472*3d8817e4Smiod       /* ...and one of these.  */
4473*3d8817e4Smiod       new_target = next_fragP->fr_next;
4474*3d8817e4Smiod       while (!(new_target->fr_type == rs_machine_dependent
4475*3d8817e4Smiod 	       && (new_target->fr_subtype == RELAX_MAYBE_DESIRE_ALIGN
4476*3d8817e4Smiod 		   || new_target->fr_subtype == RELAX_DESIRE_ALIGN)))
4477*3d8817e4Smiod 	new_target = new_target->fr_next;
4478*3d8817e4Smiod 
4479*3d8817e4Smiod       assert (new_target->fr_type == rs_machine_dependent
4480*3d8817e4Smiod 	      && (new_target->fr_subtype == RELAX_MAYBE_DESIRE_ALIGN
4481*3d8817e4Smiod 		  || new_target->fr_subtype == RELAX_DESIRE_ALIGN));
4482*3d8817e4Smiod     }
4483*3d8817e4Smiod 
4484*3d8817e4Smiod   while (next_fragP && next_fragP->fr_fix == 0)
4485*3d8817e4Smiod     {
4486*3d8817e4Smiod       if (next_fragP->fr_type == rs_machine_dependent
4487*3d8817e4Smiod 	  && next_fragP->fr_subtype == RELAX_LOOP_END)
4488*3d8817e4Smiod 	{
4489*3d8817e4Smiod 	  next_fragP->fr_subtype = RELAX_LOOP_END_ADD_NOP;
4490*3d8817e4Smiod 	  return;
4491*3d8817e4Smiod 	}
4492*3d8817e4Smiod 
4493*3d8817e4Smiod       next_fragP = next_fragP->fr_next;
4494*3d8817e4Smiod     }
4495*3d8817e4Smiod }
4496*3d8817e4Smiod 
4497*3d8817e4Smiod 
4498*3d8817e4Smiod static bfd_boolean
next_frag_is_branch_target(const fragS * fragP)4499*3d8817e4Smiod next_frag_is_branch_target (const fragS *fragP)
4500*3d8817e4Smiod {
4501*3d8817e4Smiod   /* Sometimes an empty will end up here due to storage allocation issues,
4502*3d8817e4Smiod      so we have to skip until we find something legit.  */
4503*3d8817e4Smiod   for (fragP = fragP->fr_next; fragP; fragP = fragP->fr_next)
4504*3d8817e4Smiod     {
4505*3d8817e4Smiod       if (fragP->tc_frag_data.is_branch_target)
4506*3d8817e4Smiod 	return TRUE;
4507*3d8817e4Smiod       if (fragP->fr_fix != 0)
4508*3d8817e4Smiod 	break;
4509*3d8817e4Smiod     }
4510*3d8817e4Smiod   return FALSE;
4511*3d8817e4Smiod }
4512*3d8817e4Smiod 
4513*3d8817e4Smiod 
4514*3d8817e4Smiod static bfd_boolean
next_frag_is_loop_target(const fragS * fragP)4515*3d8817e4Smiod next_frag_is_loop_target (const fragS *fragP)
4516*3d8817e4Smiod {
4517*3d8817e4Smiod   /* Sometimes an empty will end up here due storage allocation issues.
4518*3d8817e4Smiod      So we have to skip until we find something legit. */
4519*3d8817e4Smiod   for (fragP = fragP->fr_next; fragP; fragP = fragP->fr_next)
4520*3d8817e4Smiod     {
4521*3d8817e4Smiod       if (fragP->tc_frag_data.is_loop_target)
4522*3d8817e4Smiod 	return TRUE;
4523*3d8817e4Smiod       if (fragP->fr_fix != 0)
4524*3d8817e4Smiod 	break;
4525*3d8817e4Smiod     }
4526*3d8817e4Smiod   return FALSE;
4527*3d8817e4Smiod }
4528*3d8817e4Smiod 
4529*3d8817e4Smiod 
4530*3d8817e4Smiod static addressT
next_frag_pre_opcode_bytes(const fragS * fragp)4531*3d8817e4Smiod next_frag_pre_opcode_bytes (const fragS *fragp)
4532*3d8817e4Smiod {
4533*3d8817e4Smiod   const fragS *next_fragp = fragp->fr_next;
4534*3d8817e4Smiod   xtensa_opcode next_opcode;
4535*3d8817e4Smiod 
4536*3d8817e4Smiod   if (!next_frag_opcode_is_loop (fragp, &next_opcode))
4537*3d8817e4Smiod     return 0;
4538*3d8817e4Smiod 
4539*3d8817e4Smiod   /* Sometimes an empty will end up here due to storage allocation issues,
4540*3d8817e4Smiod      so we have to skip until we find something legit.  */
4541*3d8817e4Smiod   while (next_fragp->fr_fix == 0)
4542*3d8817e4Smiod     next_fragp = next_fragp->fr_next;
4543*3d8817e4Smiod 
4544*3d8817e4Smiod   if (next_fragp->fr_type != rs_machine_dependent)
4545*3d8817e4Smiod     return 0;
4546*3d8817e4Smiod 
4547*3d8817e4Smiod   /* There is some implicit knowledge encoded in here.
4548*3d8817e4Smiod      The LOOP instructions that are NOT RELAX_IMMED have
4549*3d8817e4Smiod      been relaxed.  Note that we can assume that the LOOP
4550*3d8817e4Smiod      instruction is in slot 0 because loops aren't bundleable.  */
4551*3d8817e4Smiod   if (next_fragp->tc_frag_data.slot_subtypes[0] > RELAX_IMMED)
4552*3d8817e4Smiod       return get_expanded_loop_offset (next_opcode);
4553*3d8817e4Smiod 
4554*3d8817e4Smiod   return 0;
4555*3d8817e4Smiod }
4556*3d8817e4Smiod 
4557*3d8817e4Smiod 
4558*3d8817e4Smiod /* Mark a location where we can later insert literal frags.  Update
4559*3d8817e4Smiod    the section's literal_pool_loc, so subsequent literals can be
4560*3d8817e4Smiod    placed nearest to their use.  */
4561*3d8817e4Smiod 
4562*3d8817e4Smiod static void
xtensa_mark_literal_pool_location(void)4563*3d8817e4Smiod xtensa_mark_literal_pool_location (void)
4564*3d8817e4Smiod {
4565*3d8817e4Smiod   /* Any labels pointing to the current location need
4566*3d8817e4Smiod      to be adjusted to after the literal pool.  */
4567*3d8817e4Smiod   emit_state s;
4568*3d8817e4Smiod   fragS *pool_location;
4569*3d8817e4Smiod 
4570*3d8817e4Smiod   if (use_literal_section && !directive_state[directive_absolute_literals])
4571*3d8817e4Smiod     return;
4572*3d8817e4Smiod 
4573*3d8817e4Smiod   frag_align (2, 0, 0);
4574*3d8817e4Smiod   record_alignment (now_seg, 2);
4575*3d8817e4Smiod 
4576*3d8817e4Smiod   /* We stash info in these frags so we can later move the literal's
4577*3d8817e4Smiod      fixes into this frchain's fix list.  */
4578*3d8817e4Smiod   pool_location = frag_now;
4579*3d8817e4Smiod   frag_now->tc_frag_data.lit_frchain = frchain_now;
4580*3d8817e4Smiod   frag_variant (rs_machine_dependent, 0, 0,
4581*3d8817e4Smiod 		RELAX_LITERAL_POOL_BEGIN, NULL, 0, NULL);
4582*3d8817e4Smiod   xtensa_set_frag_assembly_state (frag_now);
4583*3d8817e4Smiod   frag_now->tc_frag_data.lit_seg = now_seg;
4584*3d8817e4Smiod   frag_variant (rs_machine_dependent, 0, 0,
4585*3d8817e4Smiod 		RELAX_LITERAL_POOL_END, NULL, 0, NULL);
4586*3d8817e4Smiod   xtensa_set_frag_assembly_state (frag_now);
4587*3d8817e4Smiod 
4588*3d8817e4Smiod   /* Now put a frag into the literal pool that points to this location.  */
4589*3d8817e4Smiod   set_literal_pool_location (now_seg, pool_location);
4590*3d8817e4Smiod   xtensa_switch_to_non_abs_literal_fragment (&s);
4591*3d8817e4Smiod   frag_align (2, 0, 0);
4592*3d8817e4Smiod   record_alignment (now_seg, 2);
4593*3d8817e4Smiod 
4594*3d8817e4Smiod   /* Close whatever frag is there.  */
4595*3d8817e4Smiod   frag_variant (rs_fill, 0, 0, 0, NULL, 0, NULL);
4596*3d8817e4Smiod   xtensa_set_frag_assembly_state (frag_now);
4597*3d8817e4Smiod   frag_now->tc_frag_data.literal_frag = pool_location;
4598*3d8817e4Smiod   frag_variant (rs_fill, 0, 0, 0, NULL, 0, NULL);
4599*3d8817e4Smiod   xtensa_restore_emit_state (&s);
4600*3d8817e4Smiod   xtensa_set_frag_assembly_state (frag_now);
4601*3d8817e4Smiod }
4602*3d8817e4Smiod 
4603*3d8817e4Smiod 
4604*3d8817e4Smiod /* Build a nop of the correct size into tinsn.  */
4605*3d8817e4Smiod 
4606*3d8817e4Smiod static void
build_nop(TInsn * tinsn,int size)4607*3d8817e4Smiod build_nop (TInsn *tinsn, int size)
4608*3d8817e4Smiod {
4609*3d8817e4Smiod   tinsn_init (tinsn);
4610*3d8817e4Smiod   switch (size)
4611*3d8817e4Smiod     {
4612*3d8817e4Smiod     case 2:
4613*3d8817e4Smiod       tinsn->opcode = xtensa_nop_n_opcode;
4614*3d8817e4Smiod       tinsn->ntok = 0;
4615*3d8817e4Smiod       if (tinsn->opcode == XTENSA_UNDEFINED)
4616*3d8817e4Smiod 	as_fatal (_("opcode 'NOP.N' unavailable in this configuration"));
4617*3d8817e4Smiod       break;
4618*3d8817e4Smiod 
4619*3d8817e4Smiod     case 3:
4620*3d8817e4Smiod       if (xtensa_nop_opcode == XTENSA_UNDEFINED)
4621*3d8817e4Smiod 	{
4622*3d8817e4Smiod 	  tinsn->opcode = xtensa_or_opcode;
4623*3d8817e4Smiod 	  set_expr_const (&tinsn->tok[0], 1);
4624*3d8817e4Smiod 	  set_expr_const (&tinsn->tok[1], 1);
4625*3d8817e4Smiod 	  set_expr_const (&tinsn->tok[2], 1);
4626*3d8817e4Smiod 	  tinsn->ntok = 3;
4627*3d8817e4Smiod 	}
4628*3d8817e4Smiod       else
4629*3d8817e4Smiod 	tinsn->opcode = xtensa_nop_opcode;
4630*3d8817e4Smiod 
4631*3d8817e4Smiod       assert (tinsn->opcode != XTENSA_UNDEFINED);
4632*3d8817e4Smiod     }
4633*3d8817e4Smiod }
4634*3d8817e4Smiod 
4635*3d8817e4Smiod 
4636*3d8817e4Smiod /* Assemble a NOP of the requested size in the buffer.  User must have
4637*3d8817e4Smiod    allocated "buf" with at least "size" bytes.  */
4638*3d8817e4Smiod 
4639*3d8817e4Smiod static void
assemble_nop(int size,char * buf)4640*3d8817e4Smiod assemble_nop (int size, char *buf)
4641*3d8817e4Smiod {
4642*3d8817e4Smiod   static xtensa_insnbuf insnbuf = NULL;
4643*3d8817e4Smiod   TInsn tinsn;
4644*3d8817e4Smiod 
4645*3d8817e4Smiod   build_nop (&tinsn, size);
4646*3d8817e4Smiod 
4647*3d8817e4Smiod   if (!insnbuf)
4648*3d8817e4Smiod     insnbuf = xtensa_insnbuf_alloc (xtensa_default_isa);
4649*3d8817e4Smiod 
4650*3d8817e4Smiod   tinsn_to_insnbuf (&tinsn, insnbuf);
4651*3d8817e4Smiod   xtensa_insnbuf_to_chars (xtensa_default_isa, insnbuf,
4652*3d8817e4Smiod 			   (unsigned char *) buf, 0);
4653*3d8817e4Smiod }
4654*3d8817e4Smiod 
4655*3d8817e4Smiod 
4656*3d8817e4Smiod /* Return the number of bytes for the offset of the expanded loop
4657*3d8817e4Smiod    instruction.  This should be incorporated into the relaxation
4658*3d8817e4Smiod    specification but is hard-coded here.  This is used to auto-align
4659*3d8817e4Smiod    the loop instruction.  It is invalid to call this function if the
4660*3d8817e4Smiod    configuration does not have loops or if the opcode is not a loop
4661*3d8817e4Smiod    opcode.  */
4662*3d8817e4Smiod 
4663*3d8817e4Smiod static addressT
get_expanded_loop_offset(xtensa_opcode opcode)4664*3d8817e4Smiod get_expanded_loop_offset (xtensa_opcode opcode)
4665*3d8817e4Smiod {
4666*3d8817e4Smiod   /* This is the OFFSET of the loop instruction in the expanded loop.
4667*3d8817e4Smiod      This MUST correspond directly to the specification of the loop
4668*3d8817e4Smiod      expansion.  It will be validated on fragment conversion.  */
4669*3d8817e4Smiod   assert (opcode != XTENSA_UNDEFINED);
4670*3d8817e4Smiod   if (opcode == xtensa_loop_opcode)
4671*3d8817e4Smiod     return 0;
4672*3d8817e4Smiod   if (opcode == xtensa_loopnez_opcode)
4673*3d8817e4Smiod     return 3;
4674*3d8817e4Smiod   if (opcode == xtensa_loopgtz_opcode)
4675*3d8817e4Smiod     return 6;
4676*3d8817e4Smiod   as_fatal (_("get_expanded_loop_offset: invalid opcode"));
4677*3d8817e4Smiod   return 0;
4678*3d8817e4Smiod }
4679*3d8817e4Smiod 
4680*3d8817e4Smiod 
4681*3d8817e4Smiod static fragS *
get_literal_pool_location(segT seg)4682*3d8817e4Smiod get_literal_pool_location (segT seg)
4683*3d8817e4Smiod {
4684*3d8817e4Smiod   return seg_info (seg)->tc_segment_info_data.literal_pool_loc;
4685*3d8817e4Smiod }
4686*3d8817e4Smiod 
4687*3d8817e4Smiod 
4688*3d8817e4Smiod static void
set_literal_pool_location(segT seg,fragS * literal_pool_loc)4689*3d8817e4Smiod set_literal_pool_location (segT seg, fragS *literal_pool_loc)
4690*3d8817e4Smiod {
4691*3d8817e4Smiod   seg_info (seg)->tc_segment_info_data.literal_pool_loc = literal_pool_loc;
4692*3d8817e4Smiod }
4693*3d8817e4Smiod 
4694*3d8817e4Smiod 
4695*3d8817e4Smiod /* Set frag assembly state should be called when a new frag is
4696*3d8817e4Smiod    opened and after a frag has been closed.  */
4697*3d8817e4Smiod 
4698*3d8817e4Smiod static void
xtensa_set_frag_assembly_state(fragS * fragP)4699*3d8817e4Smiod xtensa_set_frag_assembly_state (fragS *fragP)
4700*3d8817e4Smiod {
4701*3d8817e4Smiod   if (!density_supported)
4702*3d8817e4Smiod     fragP->tc_frag_data.is_no_density = TRUE;
4703*3d8817e4Smiod 
4704*3d8817e4Smiod   /* This function is called from subsegs_finish, which is called
4705*3d8817e4Smiod      after xtensa_end, so we can't use "use_transform" or
4706*3d8817e4Smiod      "use_schedule" here.  */
4707*3d8817e4Smiod   if (!directive_state[directive_transform])
4708*3d8817e4Smiod     fragP->tc_frag_data.is_no_transform = TRUE;
4709*3d8817e4Smiod   if (directive_state[directive_longcalls])
4710*3d8817e4Smiod     fragP->tc_frag_data.use_longcalls = TRUE;
4711*3d8817e4Smiod   fragP->tc_frag_data.use_absolute_literals =
4712*3d8817e4Smiod     directive_state[directive_absolute_literals];
4713*3d8817e4Smiod   fragP->tc_frag_data.is_assembly_state_set = TRUE;
4714*3d8817e4Smiod }
4715*3d8817e4Smiod 
4716*3d8817e4Smiod 
4717*3d8817e4Smiod static bfd_boolean
relaxable_section(asection * sec)4718*3d8817e4Smiod relaxable_section (asection *sec)
4719*3d8817e4Smiod {
4720*3d8817e4Smiod   return (sec->flags & SEC_DEBUGGING) == 0;
4721*3d8817e4Smiod }
4722*3d8817e4Smiod 
4723*3d8817e4Smiod 
4724*3d8817e4Smiod static void
xtensa_find_unmarked_state_frags(void)4725*3d8817e4Smiod xtensa_find_unmarked_state_frags (void)
4726*3d8817e4Smiod {
4727*3d8817e4Smiod   segT *seclist;
4728*3d8817e4Smiod 
4729*3d8817e4Smiod   /* Walk over each fragment of all of the current segments.  For each
4730*3d8817e4Smiod      unmarked fragment, mark it with the same info as the previous
4731*3d8817e4Smiod      fragment.  */
4732*3d8817e4Smiod   for (seclist = &stdoutput->sections;
4733*3d8817e4Smiod        seclist && *seclist;
4734*3d8817e4Smiod        seclist = &(*seclist)->next)
4735*3d8817e4Smiod     {
4736*3d8817e4Smiod       segT sec = *seclist;
4737*3d8817e4Smiod       segment_info_type *seginfo;
4738*3d8817e4Smiod       fragS *fragP;
4739*3d8817e4Smiod       flagword flags;
4740*3d8817e4Smiod       flags = bfd_get_section_flags (stdoutput, sec);
4741*3d8817e4Smiod       if (flags & SEC_DEBUGGING)
4742*3d8817e4Smiod 	continue;
4743*3d8817e4Smiod       if (!(flags & SEC_ALLOC))
4744*3d8817e4Smiod 	continue;
4745*3d8817e4Smiod 
4746*3d8817e4Smiod       seginfo = seg_info (sec);
4747*3d8817e4Smiod       if (seginfo && seginfo->frchainP)
4748*3d8817e4Smiod 	{
4749*3d8817e4Smiod 	  fragS *last_fragP = 0;
4750*3d8817e4Smiod 	  for (fragP = seginfo->frchainP->frch_root; fragP;
4751*3d8817e4Smiod 	       fragP = fragP->fr_next)
4752*3d8817e4Smiod 	    {
4753*3d8817e4Smiod 	      if (fragP->fr_fix != 0
4754*3d8817e4Smiod 		  && !fragP->tc_frag_data.is_assembly_state_set)
4755*3d8817e4Smiod 		{
4756*3d8817e4Smiod 		  if (last_fragP == 0)
4757*3d8817e4Smiod 		    {
4758*3d8817e4Smiod 		      as_warn_where (fragP->fr_file, fragP->fr_line,
4759*3d8817e4Smiod 				     _("assembly state not set for first frag in section %s"),
4760*3d8817e4Smiod 				     sec->name);
4761*3d8817e4Smiod 		    }
4762*3d8817e4Smiod 		  else
4763*3d8817e4Smiod 		    {
4764*3d8817e4Smiod 		      fragP->tc_frag_data.is_assembly_state_set = TRUE;
4765*3d8817e4Smiod 		      fragP->tc_frag_data.is_no_density =
4766*3d8817e4Smiod 			last_fragP->tc_frag_data.is_no_density;
4767*3d8817e4Smiod 		      fragP->tc_frag_data.is_no_transform =
4768*3d8817e4Smiod 			last_fragP->tc_frag_data.is_no_transform;
4769*3d8817e4Smiod 		      fragP->tc_frag_data.use_longcalls =
4770*3d8817e4Smiod 			last_fragP->tc_frag_data.use_longcalls;
4771*3d8817e4Smiod 		      fragP->tc_frag_data.use_absolute_literals =
4772*3d8817e4Smiod 			last_fragP->tc_frag_data.use_absolute_literals;
4773*3d8817e4Smiod 		    }
4774*3d8817e4Smiod 		}
4775*3d8817e4Smiod 	      if (fragP->tc_frag_data.is_assembly_state_set)
4776*3d8817e4Smiod 		last_fragP = fragP;
4777*3d8817e4Smiod 	    }
4778*3d8817e4Smiod 	}
4779*3d8817e4Smiod     }
4780*3d8817e4Smiod }
4781*3d8817e4Smiod 
4782*3d8817e4Smiod 
4783*3d8817e4Smiod static void
xtensa_find_unaligned_branch_targets(bfd * abfd ATTRIBUTE_UNUSED,asection * sec,void * unused ATTRIBUTE_UNUSED)4784*3d8817e4Smiod xtensa_find_unaligned_branch_targets (bfd *abfd ATTRIBUTE_UNUSED,
4785*3d8817e4Smiod 				      asection *sec,
4786*3d8817e4Smiod 				      void *unused ATTRIBUTE_UNUSED)
4787*3d8817e4Smiod {
4788*3d8817e4Smiod   flagword flags = bfd_get_section_flags (abfd, sec);
4789*3d8817e4Smiod   segment_info_type *seginfo = seg_info (sec);
4790*3d8817e4Smiod   fragS *frag = seginfo->frchainP->frch_root;
4791*3d8817e4Smiod 
4792*3d8817e4Smiod   if (flags & SEC_CODE)
4793*3d8817e4Smiod     {
4794*3d8817e4Smiod       xtensa_isa isa = xtensa_default_isa;
4795*3d8817e4Smiod       xtensa_insnbuf insnbuf = xtensa_insnbuf_alloc (isa);
4796*3d8817e4Smiod       while (frag != NULL)
4797*3d8817e4Smiod 	{
4798*3d8817e4Smiod 	  if (frag->tc_frag_data.is_branch_target)
4799*3d8817e4Smiod 	    {
4800*3d8817e4Smiod 	      int op_size;
4801*3d8817e4Smiod 	      addressT branch_align, frag_addr;
4802*3d8817e4Smiod 	      xtensa_format fmt;
4803*3d8817e4Smiod 
4804*3d8817e4Smiod 	      xtensa_insnbuf_from_chars
4805*3d8817e4Smiod 		(isa, insnbuf, (unsigned char *) frag->fr_literal, 0);
4806*3d8817e4Smiod 	      fmt = xtensa_format_decode (isa, insnbuf);
4807*3d8817e4Smiod 	      op_size = xtensa_format_length (isa, fmt);
4808*3d8817e4Smiod 	      branch_align = 1 << branch_align_power (sec);
4809*3d8817e4Smiod 	      frag_addr = frag->fr_address % branch_align;
4810*3d8817e4Smiod 	      if (frag_addr + op_size > branch_align)
4811*3d8817e4Smiod 		as_warn_where (frag->fr_file, frag->fr_line,
4812*3d8817e4Smiod 			       _("unaligned branch target: %d bytes at 0x%lx"),
4813*3d8817e4Smiod 			       op_size, (long) frag->fr_address);
4814*3d8817e4Smiod 	    }
4815*3d8817e4Smiod 	  frag = frag->fr_next;
4816*3d8817e4Smiod 	}
4817*3d8817e4Smiod       xtensa_insnbuf_free (isa, insnbuf);
4818*3d8817e4Smiod     }
4819*3d8817e4Smiod }
4820*3d8817e4Smiod 
4821*3d8817e4Smiod 
4822*3d8817e4Smiod static void
xtensa_find_unaligned_loops(bfd * abfd ATTRIBUTE_UNUSED,asection * sec,void * unused ATTRIBUTE_UNUSED)4823*3d8817e4Smiod xtensa_find_unaligned_loops (bfd *abfd ATTRIBUTE_UNUSED,
4824*3d8817e4Smiod 			     asection *sec,
4825*3d8817e4Smiod 			     void *unused ATTRIBUTE_UNUSED)
4826*3d8817e4Smiod {
4827*3d8817e4Smiod   flagword flags = bfd_get_section_flags (abfd, sec);
4828*3d8817e4Smiod   segment_info_type *seginfo = seg_info (sec);
4829*3d8817e4Smiod   fragS *frag = seginfo->frchainP->frch_root;
4830*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
4831*3d8817e4Smiod 
4832*3d8817e4Smiod   if (flags & SEC_CODE)
4833*3d8817e4Smiod     {
4834*3d8817e4Smiod       xtensa_insnbuf insnbuf = xtensa_insnbuf_alloc (isa);
4835*3d8817e4Smiod       while (frag != NULL)
4836*3d8817e4Smiod 	{
4837*3d8817e4Smiod 	  if (frag->tc_frag_data.is_first_loop_insn)
4838*3d8817e4Smiod 	    {
4839*3d8817e4Smiod 	      int op_size;
4840*3d8817e4Smiod 	      addressT frag_addr;
4841*3d8817e4Smiod 	      xtensa_format fmt;
4842*3d8817e4Smiod 
4843*3d8817e4Smiod 	      xtensa_insnbuf_from_chars
4844*3d8817e4Smiod 		(isa, insnbuf, (unsigned char *) frag->fr_literal, 0);
4845*3d8817e4Smiod 	      fmt = xtensa_format_decode (isa, insnbuf);
4846*3d8817e4Smiod 	      op_size = xtensa_format_length (isa, fmt);
4847*3d8817e4Smiod 	      frag_addr = frag->fr_address % xtensa_fetch_width;
4848*3d8817e4Smiod 
4849*3d8817e4Smiod 	      if (frag_addr + op_size > xtensa_fetch_width)
4850*3d8817e4Smiod 		as_warn_where (frag->fr_file, frag->fr_line,
4851*3d8817e4Smiod 			       _("unaligned loop: %d bytes at 0x%lx"),
4852*3d8817e4Smiod 			       op_size, (long) frag->fr_address);
4853*3d8817e4Smiod 	    }
4854*3d8817e4Smiod 	  frag = frag->fr_next;
4855*3d8817e4Smiod 	}
4856*3d8817e4Smiod       xtensa_insnbuf_free (isa, insnbuf);
4857*3d8817e4Smiod     }
4858*3d8817e4Smiod }
4859*3d8817e4Smiod 
4860*3d8817e4Smiod 
4861*3d8817e4Smiod static int
xg_apply_fix_value(fixS * fixP,valueT val)4862*3d8817e4Smiod xg_apply_fix_value (fixS *fixP, valueT val)
4863*3d8817e4Smiod {
4864*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
4865*3d8817e4Smiod   static xtensa_insnbuf insnbuf = NULL;
4866*3d8817e4Smiod   static xtensa_insnbuf slotbuf = NULL;
4867*3d8817e4Smiod   xtensa_format fmt;
4868*3d8817e4Smiod   int slot;
4869*3d8817e4Smiod   bfd_boolean alt_reloc;
4870*3d8817e4Smiod   xtensa_opcode opcode;
4871*3d8817e4Smiod   char *const fixpos = fixP->fx_frag->fr_literal + fixP->fx_where;
4872*3d8817e4Smiod 
4873*3d8817e4Smiod   (void) decode_reloc (fixP->fx_r_type, &slot, &alt_reloc);
4874*3d8817e4Smiod   if (alt_reloc)
4875*3d8817e4Smiod     as_fatal (_("unexpected fix"));
4876*3d8817e4Smiod 
4877*3d8817e4Smiod   if (!insnbuf)
4878*3d8817e4Smiod     {
4879*3d8817e4Smiod       insnbuf = xtensa_insnbuf_alloc (isa);
4880*3d8817e4Smiod       slotbuf = xtensa_insnbuf_alloc (isa);
4881*3d8817e4Smiod     }
4882*3d8817e4Smiod 
4883*3d8817e4Smiod   xtensa_insnbuf_from_chars (isa, insnbuf, (unsigned char *) fixpos, 0);
4884*3d8817e4Smiod   fmt = xtensa_format_decode (isa, insnbuf);
4885*3d8817e4Smiod   if (fmt == XTENSA_UNDEFINED)
4886*3d8817e4Smiod     as_fatal (_("undecodable fix"));
4887*3d8817e4Smiod   xtensa_format_get_slot (isa, fmt, slot, insnbuf, slotbuf);
4888*3d8817e4Smiod   opcode = xtensa_opcode_decode (isa, fmt, slot, slotbuf);
4889*3d8817e4Smiod   if (opcode == XTENSA_UNDEFINED)
4890*3d8817e4Smiod     as_fatal (_("undecodable fix"));
4891*3d8817e4Smiod 
4892*3d8817e4Smiod   /* CONST16 immediates are not PC-relative, despite the fact that we
4893*3d8817e4Smiod      reuse the normal PC-relative operand relocations for the low part
4894*3d8817e4Smiod      of a CONST16 operand.  */
4895*3d8817e4Smiod   if (opcode == xtensa_const16_opcode)
4896*3d8817e4Smiod     return 0;
4897*3d8817e4Smiod 
4898*3d8817e4Smiod   xtensa_insnbuf_set_operand (slotbuf, fmt, slot, opcode,
4899*3d8817e4Smiod 			      get_relaxable_immed (opcode), val,
4900*3d8817e4Smiod 			      fixP->fx_file, fixP->fx_line);
4901*3d8817e4Smiod 
4902*3d8817e4Smiod   xtensa_format_set_slot (isa, fmt, slot, insnbuf, slotbuf);
4903*3d8817e4Smiod   xtensa_insnbuf_to_chars (isa, insnbuf, (unsigned char *) fixpos, 0);
4904*3d8817e4Smiod 
4905*3d8817e4Smiod   return 1;
4906*3d8817e4Smiod }
4907*3d8817e4Smiod 
4908*3d8817e4Smiod 
4909*3d8817e4Smiod /* External Functions and Other GAS Hooks.  */
4910*3d8817e4Smiod 
4911*3d8817e4Smiod const char *
xtensa_target_format(void)4912*3d8817e4Smiod xtensa_target_format (void)
4913*3d8817e4Smiod {
4914*3d8817e4Smiod   return (target_big_endian ? "elf32-xtensa-be" : "elf32-xtensa-le");
4915*3d8817e4Smiod }
4916*3d8817e4Smiod 
4917*3d8817e4Smiod 
4918*3d8817e4Smiod void
xtensa_file_arch_init(bfd * abfd)4919*3d8817e4Smiod xtensa_file_arch_init (bfd *abfd)
4920*3d8817e4Smiod {
4921*3d8817e4Smiod   bfd_set_private_flags (abfd, 0x100 | 0x200);
4922*3d8817e4Smiod }
4923*3d8817e4Smiod 
4924*3d8817e4Smiod 
4925*3d8817e4Smiod void
md_number_to_chars(char * buf,valueT val,int n)4926*3d8817e4Smiod md_number_to_chars (char *buf, valueT val, int n)
4927*3d8817e4Smiod {
4928*3d8817e4Smiod   if (target_big_endian)
4929*3d8817e4Smiod     number_to_chars_bigendian (buf, val, n);
4930*3d8817e4Smiod   else
4931*3d8817e4Smiod     number_to_chars_littleendian (buf, val, n);
4932*3d8817e4Smiod }
4933*3d8817e4Smiod 
4934*3d8817e4Smiod 
4935*3d8817e4Smiod /* This function is called once, at assembler startup time.  It should
4936*3d8817e4Smiod    set up all the tables, etc. that the MD part of the assembler will
4937*3d8817e4Smiod    need.  */
4938*3d8817e4Smiod 
4939*3d8817e4Smiod void
md_begin(void)4940*3d8817e4Smiod md_begin (void)
4941*3d8817e4Smiod {
4942*3d8817e4Smiod   segT current_section = now_seg;
4943*3d8817e4Smiod   int current_subsec = now_subseg;
4944*3d8817e4Smiod   xtensa_isa isa;
4945*3d8817e4Smiod 
4946*3d8817e4Smiod   xtensa_default_isa = xtensa_isa_init (0, 0);
4947*3d8817e4Smiod   isa = xtensa_default_isa;
4948*3d8817e4Smiod 
4949*3d8817e4Smiod   linkrelax = 1;
4950*3d8817e4Smiod 
4951*3d8817e4Smiod   /* Set up the .literal, .fini.literal and .init.literal sections.  */
4952*3d8817e4Smiod   memset (&default_lit_sections, 0, sizeof (default_lit_sections));
4953*3d8817e4Smiod   default_lit_sections.init_lit_seg_name = INIT_LITERAL_SECTION_NAME;
4954*3d8817e4Smiod   default_lit_sections.fini_lit_seg_name = FINI_LITERAL_SECTION_NAME;
4955*3d8817e4Smiod   default_lit_sections.lit_seg_name = LITERAL_SECTION_NAME;
4956*3d8817e4Smiod   default_lit_sections.lit4_seg_name = LIT4_SECTION_NAME;
4957*3d8817e4Smiod 
4958*3d8817e4Smiod   subseg_set (current_section, current_subsec);
4959*3d8817e4Smiod 
4960*3d8817e4Smiod   xg_init_vinsn (&cur_vinsn);
4961*3d8817e4Smiod 
4962*3d8817e4Smiod   xtensa_addi_opcode = xtensa_opcode_lookup (isa, "addi");
4963*3d8817e4Smiod   xtensa_addmi_opcode = xtensa_opcode_lookup (isa, "addmi");
4964*3d8817e4Smiod   xtensa_call0_opcode = xtensa_opcode_lookup (isa, "call0");
4965*3d8817e4Smiod   xtensa_call4_opcode = xtensa_opcode_lookup (isa, "call4");
4966*3d8817e4Smiod   xtensa_call8_opcode = xtensa_opcode_lookup (isa, "call8");
4967*3d8817e4Smiod   xtensa_call12_opcode = xtensa_opcode_lookup (isa, "call12");
4968*3d8817e4Smiod   xtensa_callx0_opcode = xtensa_opcode_lookup (isa, "callx0");
4969*3d8817e4Smiod   xtensa_callx4_opcode = xtensa_opcode_lookup (isa, "callx4");
4970*3d8817e4Smiod   xtensa_callx8_opcode = xtensa_opcode_lookup (isa, "callx8");
4971*3d8817e4Smiod   xtensa_callx12_opcode = xtensa_opcode_lookup (isa, "callx12");
4972*3d8817e4Smiod   xtensa_const16_opcode = xtensa_opcode_lookup (isa, "const16");
4973*3d8817e4Smiod   xtensa_entry_opcode = xtensa_opcode_lookup (isa, "entry");
4974*3d8817e4Smiod   xtensa_movi_opcode = xtensa_opcode_lookup (isa, "movi");
4975*3d8817e4Smiod   xtensa_movi_n_opcode = xtensa_opcode_lookup (isa, "movi.n");
4976*3d8817e4Smiod   xtensa_isync_opcode = xtensa_opcode_lookup (isa, "isync");
4977*3d8817e4Smiod   xtensa_jx_opcode = xtensa_opcode_lookup (isa, "jx");
4978*3d8817e4Smiod   xtensa_l32r_opcode = xtensa_opcode_lookup (isa, "l32r");
4979*3d8817e4Smiod   xtensa_loop_opcode = xtensa_opcode_lookup (isa, "loop");
4980*3d8817e4Smiod   xtensa_loopnez_opcode = xtensa_opcode_lookup (isa, "loopnez");
4981*3d8817e4Smiod   xtensa_loopgtz_opcode = xtensa_opcode_lookup (isa, "loopgtz");
4982*3d8817e4Smiod   xtensa_nop_opcode = xtensa_opcode_lookup (isa, "nop");
4983*3d8817e4Smiod   xtensa_nop_n_opcode = xtensa_opcode_lookup (isa, "nop.n");
4984*3d8817e4Smiod   xtensa_or_opcode = xtensa_opcode_lookup (isa, "or");
4985*3d8817e4Smiod   xtensa_ret_opcode = xtensa_opcode_lookup (isa, "ret");
4986*3d8817e4Smiod   xtensa_ret_n_opcode = xtensa_opcode_lookup (isa, "ret.n");
4987*3d8817e4Smiod   xtensa_retw_opcode = xtensa_opcode_lookup (isa, "retw");
4988*3d8817e4Smiod   xtensa_retw_n_opcode = xtensa_opcode_lookup (isa, "retw.n");
4989*3d8817e4Smiod   xtensa_rsr_lcount_opcode = xtensa_opcode_lookup (isa, "rsr.lcount");
4990*3d8817e4Smiod   xtensa_waiti_opcode = xtensa_opcode_lookup (isa, "waiti");
4991*3d8817e4Smiod 
4992*3d8817e4Smiod   init_op_placement_info_table ();
4993*3d8817e4Smiod 
4994*3d8817e4Smiod   /* Set up the assembly state.  */
4995*3d8817e4Smiod   if (!frag_now->tc_frag_data.is_assembly_state_set)
4996*3d8817e4Smiod     xtensa_set_frag_assembly_state (frag_now);
4997*3d8817e4Smiod }
4998*3d8817e4Smiod 
4999*3d8817e4Smiod 
5000*3d8817e4Smiod /* TC_INIT_FIX_DATA hook */
5001*3d8817e4Smiod 
5002*3d8817e4Smiod void
xtensa_init_fix_data(fixS * x)5003*3d8817e4Smiod xtensa_init_fix_data (fixS *x)
5004*3d8817e4Smiod {
5005*3d8817e4Smiod   x->tc_fix_data.slot = 0;
5006*3d8817e4Smiod   x->tc_fix_data.X_add_symbol = NULL;
5007*3d8817e4Smiod   x->tc_fix_data.X_add_number = 0;
5008*3d8817e4Smiod }
5009*3d8817e4Smiod 
5010*3d8817e4Smiod 
5011*3d8817e4Smiod /* tc_frob_label hook */
5012*3d8817e4Smiod 
5013*3d8817e4Smiod void
xtensa_frob_label(symbolS * sym)5014*3d8817e4Smiod xtensa_frob_label (symbolS *sym)
5015*3d8817e4Smiod {
5016*3d8817e4Smiod   float freq;
5017*3d8817e4Smiod 
5018*3d8817e4Smiod   if (cur_vinsn.inside_bundle)
5019*3d8817e4Smiod     {
5020*3d8817e4Smiod       as_bad (_("labels are not valid inside bundles"));
5021*3d8817e4Smiod       return;
5022*3d8817e4Smiod     }
5023*3d8817e4Smiod 
5024*3d8817e4Smiod   freq = get_subseg_target_freq (now_seg, now_subseg);
5025*3d8817e4Smiod 
5026*3d8817e4Smiod   /* Since the label was already attached to a frag associated with the
5027*3d8817e4Smiod      previous basic block, it now needs to be reset to the current frag.  */
5028*3d8817e4Smiod   symbol_set_frag (sym, frag_now);
5029*3d8817e4Smiod   S_SET_VALUE (sym, (valueT) frag_now_fix ());
5030*3d8817e4Smiod 
5031*3d8817e4Smiod   if (generating_literals)
5032*3d8817e4Smiod     xtensa_add_literal_sym (sym);
5033*3d8817e4Smiod   else
5034*3d8817e4Smiod     xtensa_add_insn_label (sym);
5035*3d8817e4Smiod 
5036*3d8817e4Smiod   if (symbol_get_tc (sym)->is_loop_target)
5037*3d8817e4Smiod     {
5038*3d8817e4Smiod       if ((get_last_insn_flags (now_seg, now_subseg)
5039*3d8817e4Smiod 	  & FLAG_IS_BAD_LOOPEND) != 0)
5040*3d8817e4Smiod 	as_bad (_("invalid last instruction for a zero-overhead loop"));
5041*3d8817e4Smiod 
5042*3d8817e4Smiod       xtensa_set_frag_assembly_state (frag_now);
5043*3d8817e4Smiod       frag_var (rs_machine_dependent, 4, 4, RELAX_LOOP_END,
5044*3d8817e4Smiod 		frag_now->fr_symbol, frag_now->fr_offset, NULL);
5045*3d8817e4Smiod 
5046*3d8817e4Smiod       xtensa_set_frag_assembly_state (frag_now);
5047*3d8817e4Smiod       xtensa_move_labels (frag_now, 0, TRUE);
5048*3d8817e4Smiod     }
5049*3d8817e4Smiod 
5050*3d8817e4Smiod   /* No target aligning in the absolute section.  */
5051*3d8817e4Smiod   if (now_seg != absolute_section
5052*3d8817e4Smiod       && do_align_targets ()
5053*3d8817e4Smiod       && !is_unaligned_label (sym)
5054*3d8817e4Smiod       && !generating_literals)
5055*3d8817e4Smiod     {
5056*3d8817e4Smiod       xtensa_set_frag_assembly_state (frag_now);
5057*3d8817e4Smiod 
5058*3d8817e4Smiod       frag_var (rs_machine_dependent,
5059*3d8817e4Smiod 		0, (int) freq,
5060*3d8817e4Smiod 		RELAX_DESIRE_ALIGN_IF_TARGET,
5061*3d8817e4Smiod 		frag_now->fr_symbol, frag_now->fr_offset, NULL);
5062*3d8817e4Smiod       xtensa_set_frag_assembly_state (frag_now);
5063*3d8817e4Smiod       xtensa_move_labels (frag_now, 0, TRUE);
5064*3d8817e4Smiod     }
5065*3d8817e4Smiod 
5066*3d8817e4Smiod   /* We need to mark the following properties even if we aren't aligning.  */
5067*3d8817e4Smiod 
5068*3d8817e4Smiod   /* If the label is already known to be a branch target, i.e., a
5069*3d8817e4Smiod      forward branch, mark the frag accordingly.  Backward branches
5070*3d8817e4Smiod      are handled by xg_add_branch_and_loop_targets.  */
5071*3d8817e4Smiod   if (symbol_get_tc (sym)->is_branch_target)
5072*3d8817e4Smiod     symbol_get_frag (sym)->tc_frag_data.is_branch_target = TRUE;
5073*3d8817e4Smiod 
5074*3d8817e4Smiod   /* Loops only go forward, so they can be identified here.  */
5075*3d8817e4Smiod   if (symbol_get_tc (sym)->is_loop_target)
5076*3d8817e4Smiod     symbol_get_frag (sym)->tc_frag_data.is_loop_target = TRUE;
5077*3d8817e4Smiod 
5078*3d8817e4Smiod   dwarf2_emit_label (sym);
5079*3d8817e4Smiod }
5080*3d8817e4Smiod 
5081*3d8817e4Smiod 
5082*3d8817e4Smiod /* tc_unrecognized_line hook */
5083*3d8817e4Smiod 
5084*3d8817e4Smiod int
xtensa_unrecognized_line(int ch)5085*3d8817e4Smiod xtensa_unrecognized_line (int ch)
5086*3d8817e4Smiod {
5087*3d8817e4Smiod   switch (ch)
5088*3d8817e4Smiod     {
5089*3d8817e4Smiod     case '{' :
5090*3d8817e4Smiod       if (cur_vinsn.inside_bundle == 0)
5091*3d8817e4Smiod 	{
5092*3d8817e4Smiod 	  /* PR8110: Cannot emit line number info inside a FLIX bundle
5093*3d8817e4Smiod 	     when using --gstabs.  Temporarily disable debug info.  */
5094*3d8817e4Smiod 	  generate_lineno_debug ();
5095*3d8817e4Smiod 	  if (debug_type == DEBUG_STABS)
5096*3d8817e4Smiod 	    {
5097*3d8817e4Smiod 	      xt_saved_debug_type = debug_type;
5098*3d8817e4Smiod 	      debug_type = DEBUG_NONE;
5099*3d8817e4Smiod 	    }
5100*3d8817e4Smiod 
5101*3d8817e4Smiod 	  cur_vinsn.inside_bundle = 1;
5102*3d8817e4Smiod 	}
5103*3d8817e4Smiod       else
5104*3d8817e4Smiod 	{
5105*3d8817e4Smiod 	  as_bad (_("extra opening brace"));
5106*3d8817e4Smiod 	  return 0;
5107*3d8817e4Smiod 	}
5108*3d8817e4Smiod       break;
5109*3d8817e4Smiod 
5110*3d8817e4Smiod     case '}' :
5111*3d8817e4Smiod       if (cur_vinsn.inside_bundle)
5112*3d8817e4Smiod 	finish_vinsn (&cur_vinsn);
5113*3d8817e4Smiod       else
5114*3d8817e4Smiod 	{
5115*3d8817e4Smiod 	  as_bad (_("extra closing brace"));
5116*3d8817e4Smiod 	  return 0;
5117*3d8817e4Smiod 	}
5118*3d8817e4Smiod       break;
5119*3d8817e4Smiod     default:
5120*3d8817e4Smiod       as_bad (_("syntax error"));
5121*3d8817e4Smiod       return 0;
5122*3d8817e4Smiod     }
5123*3d8817e4Smiod   return 1;
5124*3d8817e4Smiod }
5125*3d8817e4Smiod 
5126*3d8817e4Smiod 
5127*3d8817e4Smiod /* md_flush_pending_output hook */
5128*3d8817e4Smiod 
5129*3d8817e4Smiod void
xtensa_flush_pending_output(void)5130*3d8817e4Smiod xtensa_flush_pending_output (void)
5131*3d8817e4Smiod {
5132*3d8817e4Smiod   if (cur_vinsn.inside_bundle)
5133*3d8817e4Smiod     as_bad (_("missing closing brace"));
5134*3d8817e4Smiod 
5135*3d8817e4Smiod   /* If there is a non-zero instruction fragment, close it.  */
5136*3d8817e4Smiod   if (frag_now_fix () != 0 && frag_now->tc_frag_data.is_insn)
5137*3d8817e4Smiod     {
5138*3d8817e4Smiod       frag_wane (frag_now);
5139*3d8817e4Smiod       frag_new (0);
5140*3d8817e4Smiod       xtensa_set_frag_assembly_state (frag_now);
5141*3d8817e4Smiod     }
5142*3d8817e4Smiod   frag_now->tc_frag_data.is_insn = FALSE;
5143*3d8817e4Smiod 
5144*3d8817e4Smiod   xtensa_clear_insn_labels ();
5145*3d8817e4Smiod }
5146*3d8817e4Smiod 
5147*3d8817e4Smiod 
5148*3d8817e4Smiod /* We had an error while parsing an instruction.  The string might look
5149*3d8817e4Smiod    like this: "insn arg1, arg2 }".  If so, we need to see the closing
5150*3d8817e4Smiod    brace and reset some fields.  Otherwise, the vinsn never gets closed
5151*3d8817e4Smiod    and the num_slots field will grow past the end of the array of slots,
5152*3d8817e4Smiod    and bad things happen.  */
5153*3d8817e4Smiod 
5154*3d8817e4Smiod static void
error_reset_cur_vinsn(void)5155*3d8817e4Smiod error_reset_cur_vinsn (void)
5156*3d8817e4Smiod {
5157*3d8817e4Smiod   if (cur_vinsn.inside_bundle)
5158*3d8817e4Smiod     {
5159*3d8817e4Smiod       if (*input_line_pointer == '}'
5160*3d8817e4Smiod 	  || *(input_line_pointer - 1) == '}'
5161*3d8817e4Smiod 	  || *(input_line_pointer - 2) == '}')
5162*3d8817e4Smiod 	xg_clear_vinsn (&cur_vinsn);
5163*3d8817e4Smiod     }
5164*3d8817e4Smiod }
5165*3d8817e4Smiod 
5166*3d8817e4Smiod 
5167*3d8817e4Smiod void
md_assemble(char * str)5168*3d8817e4Smiod md_assemble (char *str)
5169*3d8817e4Smiod {
5170*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
5171*3d8817e4Smiod   char *opname, *file_name;
5172*3d8817e4Smiod   unsigned opnamelen;
5173*3d8817e4Smiod   bfd_boolean has_underbar = FALSE;
5174*3d8817e4Smiod   char *arg_strings[MAX_INSN_ARGS];
5175*3d8817e4Smiod   int num_args;
5176*3d8817e4Smiod   TInsn orig_insn;		/* Original instruction from the input.  */
5177*3d8817e4Smiod 
5178*3d8817e4Smiod   tinsn_init (&orig_insn);
5179*3d8817e4Smiod 
5180*3d8817e4Smiod   /* Split off the opcode.  */
5181*3d8817e4Smiod   opnamelen = strspn (str, "abcdefghijklmnopqrstuvwxyz_/0123456789.");
5182*3d8817e4Smiod   opname = xmalloc (opnamelen + 1);
5183*3d8817e4Smiod   memcpy (opname, str, opnamelen);
5184*3d8817e4Smiod   opname[opnamelen] = '\0';
5185*3d8817e4Smiod 
5186*3d8817e4Smiod   num_args = tokenize_arguments (arg_strings, str + opnamelen);
5187*3d8817e4Smiod   if (num_args == -1)
5188*3d8817e4Smiod     {
5189*3d8817e4Smiod       as_bad (_("syntax error"));
5190*3d8817e4Smiod       return;
5191*3d8817e4Smiod     }
5192*3d8817e4Smiod 
5193*3d8817e4Smiod   if (xg_translate_idioms (&opname, &num_args, arg_strings))
5194*3d8817e4Smiod     return;
5195*3d8817e4Smiod 
5196*3d8817e4Smiod   /* Check for an underbar prefix.  */
5197*3d8817e4Smiod   if (*opname == '_')
5198*3d8817e4Smiod     {
5199*3d8817e4Smiod       has_underbar = TRUE;
5200*3d8817e4Smiod       opname += 1;
5201*3d8817e4Smiod     }
5202*3d8817e4Smiod 
5203*3d8817e4Smiod   orig_insn.insn_type = ITYPE_INSN;
5204*3d8817e4Smiod   orig_insn.ntok = 0;
5205*3d8817e4Smiod   orig_insn.is_specific_opcode = (has_underbar || !use_transform ());
5206*3d8817e4Smiod 
5207*3d8817e4Smiod   orig_insn.opcode = xtensa_opcode_lookup (isa, opname);
5208*3d8817e4Smiod   if (orig_insn.opcode == XTENSA_UNDEFINED)
5209*3d8817e4Smiod     {
5210*3d8817e4Smiod       xtensa_format fmt = xtensa_format_lookup (isa, opname);
5211*3d8817e4Smiod       if (fmt == XTENSA_UNDEFINED)
5212*3d8817e4Smiod 	{
5213*3d8817e4Smiod 	  as_bad (_("unknown opcode or format name '%s'"), opname);
5214*3d8817e4Smiod 	  error_reset_cur_vinsn ();
5215*3d8817e4Smiod 	  return;
5216*3d8817e4Smiod 	}
5217*3d8817e4Smiod       if (!cur_vinsn.inside_bundle)
5218*3d8817e4Smiod 	{
5219*3d8817e4Smiod 	  as_bad (_("format names only valid inside bundles"));
5220*3d8817e4Smiod 	  error_reset_cur_vinsn ();
5221*3d8817e4Smiod 	  return;
5222*3d8817e4Smiod 	}
5223*3d8817e4Smiod       if (cur_vinsn.format != XTENSA_UNDEFINED)
5224*3d8817e4Smiod 	as_warn (_("multiple formats specified for one bundle; using '%s'"),
5225*3d8817e4Smiod 		 opname);
5226*3d8817e4Smiod       cur_vinsn.format = fmt;
5227*3d8817e4Smiod       free (has_underbar ? opname - 1 : opname);
5228*3d8817e4Smiod       error_reset_cur_vinsn ();
5229*3d8817e4Smiod       return;
5230*3d8817e4Smiod     }
5231*3d8817e4Smiod 
5232*3d8817e4Smiod   /* Parse the arguments.  */
5233*3d8817e4Smiod   if (parse_arguments (&orig_insn, num_args, arg_strings))
5234*3d8817e4Smiod     {
5235*3d8817e4Smiod       as_bad (_("syntax error"));
5236*3d8817e4Smiod       error_reset_cur_vinsn ();
5237*3d8817e4Smiod       return;
5238*3d8817e4Smiod     }
5239*3d8817e4Smiod 
5240*3d8817e4Smiod   /* Free the opcode and argument strings, now that they've been parsed.  */
5241*3d8817e4Smiod   free (has_underbar ? opname - 1 : opname);
5242*3d8817e4Smiod   opname = 0;
5243*3d8817e4Smiod   while (num_args-- > 0)
5244*3d8817e4Smiod     free (arg_strings[num_args]);
5245*3d8817e4Smiod 
5246*3d8817e4Smiod   /* Get expressions for invisible operands.  */
5247*3d8817e4Smiod   if (get_invisible_operands (&orig_insn))
5248*3d8817e4Smiod     {
5249*3d8817e4Smiod       error_reset_cur_vinsn ();
5250*3d8817e4Smiod       return;
5251*3d8817e4Smiod     }
5252*3d8817e4Smiod 
5253*3d8817e4Smiod   /* Check for the right number and type of arguments.  */
5254*3d8817e4Smiod   if (tinsn_check_arguments (&orig_insn))
5255*3d8817e4Smiod     {
5256*3d8817e4Smiod       error_reset_cur_vinsn ();
5257*3d8817e4Smiod       return;
5258*3d8817e4Smiod     }
5259*3d8817e4Smiod 
5260*3d8817e4Smiod   /* A FLIX bundle may be spread across multiple input lines.  We want to
5261*3d8817e4Smiod      report the first such line in the debug information.  Record the line
5262*3d8817e4Smiod      number for each TInsn (assume the file name doesn't change), so the
5263*3d8817e4Smiod      first line can be found later.  */
5264*3d8817e4Smiod   as_where (&file_name, &orig_insn.linenum);
5265*3d8817e4Smiod 
5266*3d8817e4Smiod   xg_add_branch_and_loop_targets (&orig_insn);
5267*3d8817e4Smiod 
5268*3d8817e4Smiod   /* Check that immediate value for ENTRY is >= 16.  */
5269*3d8817e4Smiod   if (orig_insn.opcode == xtensa_entry_opcode && orig_insn.ntok >= 3)
5270*3d8817e4Smiod     {
5271*3d8817e4Smiod       expressionS *exp = &orig_insn.tok[2];
5272*3d8817e4Smiod       if (exp->X_op == O_constant && exp->X_add_number < 16)
5273*3d8817e4Smiod 	as_warn (_("entry instruction with stack decrement < 16"));
5274*3d8817e4Smiod     }
5275*3d8817e4Smiod 
5276*3d8817e4Smiod   /* Finish it off:
5277*3d8817e4Smiod      assemble_tokens (opcode, tok, ntok);
5278*3d8817e4Smiod      expand the tokens from the orig_insn into the
5279*3d8817e4Smiod      stack of instructions that will not expand
5280*3d8817e4Smiod      unless required at relaxation time.  */
5281*3d8817e4Smiod 
5282*3d8817e4Smiod   if (!cur_vinsn.inside_bundle)
5283*3d8817e4Smiod     emit_single_op (&orig_insn);
5284*3d8817e4Smiod   else /* We are inside a bundle.  */
5285*3d8817e4Smiod     {
5286*3d8817e4Smiod       cur_vinsn.slots[cur_vinsn.num_slots] = orig_insn;
5287*3d8817e4Smiod       cur_vinsn.num_slots++;
5288*3d8817e4Smiod       if (*input_line_pointer == '}'
5289*3d8817e4Smiod 	  || *(input_line_pointer - 1) == '}'
5290*3d8817e4Smiod 	  || *(input_line_pointer - 2) == '}')
5291*3d8817e4Smiod 	finish_vinsn (&cur_vinsn);
5292*3d8817e4Smiod     }
5293*3d8817e4Smiod 
5294*3d8817e4Smiod   /* We've just emitted a new instruction so clear the list of labels.  */
5295*3d8817e4Smiod   xtensa_clear_insn_labels ();
5296*3d8817e4Smiod }
5297*3d8817e4Smiod 
5298*3d8817e4Smiod 
5299*3d8817e4Smiod /* HANDLE_ALIGN hook */
5300*3d8817e4Smiod 
5301*3d8817e4Smiod /* For a .align directive, we mark the previous block with the alignment
5302*3d8817e4Smiod    information.  This will be placed in the object file in the
5303*3d8817e4Smiod    property section corresponding to this section.  */
5304*3d8817e4Smiod 
5305*3d8817e4Smiod void
xtensa_handle_align(fragS * fragP)5306*3d8817e4Smiod xtensa_handle_align (fragS *fragP)
5307*3d8817e4Smiod {
5308*3d8817e4Smiod   if (linkrelax
5309*3d8817e4Smiod       && ! fragP->tc_frag_data.is_literal
5310*3d8817e4Smiod       && (fragP->fr_type == rs_align
5311*3d8817e4Smiod 	  || fragP->fr_type == rs_align_code)
5312*3d8817e4Smiod       && fragP->fr_address + fragP->fr_fix > 0
5313*3d8817e4Smiod       && fragP->fr_offset > 0
5314*3d8817e4Smiod       && now_seg != bss_section)
5315*3d8817e4Smiod     {
5316*3d8817e4Smiod       fragP->tc_frag_data.is_align = TRUE;
5317*3d8817e4Smiod       fragP->tc_frag_data.alignment = fragP->fr_offset;
5318*3d8817e4Smiod     }
5319*3d8817e4Smiod 
5320*3d8817e4Smiod   if (fragP->fr_type == rs_align_test)
5321*3d8817e4Smiod     {
5322*3d8817e4Smiod       int count;
5323*3d8817e4Smiod       count = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
5324*3d8817e4Smiod       if (count != 0)
5325*3d8817e4Smiod 	as_bad_where (fragP->fr_file, fragP->fr_line,
5326*3d8817e4Smiod 		      _("unaligned entry instruction"));
5327*3d8817e4Smiod     }
5328*3d8817e4Smiod }
5329*3d8817e4Smiod 
5330*3d8817e4Smiod 
5331*3d8817e4Smiod /* TC_FRAG_INIT hook */
5332*3d8817e4Smiod 
5333*3d8817e4Smiod void
xtensa_frag_init(fragS * frag)5334*3d8817e4Smiod xtensa_frag_init (fragS *frag)
5335*3d8817e4Smiod {
5336*3d8817e4Smiod   xtensa_set_frag_assembly_state (frag);
5337*3d8817e4Smiod }
5338*3d8817e4Smiod 
5339*3d8817e4Smiod 
5340*3d8817e4Smiod symbolS *
md_undefined_symbol(char * name ATTRIBUTE_UNUSED)5341*3d8817e4Smiod md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
5342*3d8817e4Smiod {
5343*3d8817e4Smiod   return NULL;
5344*3d8817e4Smiod }
5345*3d8817e4Smiod 
5346*3d8817e4Smiod 
5347*3d8817e4Smiod /* Round up a section size to the appropriate boundary.  */
5348*3d8817e4Smiod 
5349*3d8817e4Smiod valueT
md_section_align(segT segment ATTRIBUTE_UNUSED,valueT size)5350*3d8817e4Smiod md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
5351*3d8817e4Smiod {
5352*3d8817e4Smiod   return size;			/* Byte alignment is fine.  */
5353*3d8817e4Smiod }
5354*3d8817e4Smiod 
5355*3d8817e4Smiod 
5356*3d8817e4Smiod long
md_pcrel_from(fixS * fixP)5357*3d8817e4Smiod md_pcrel_from (fixS *fixP)
5358*3d8817e4Smiod {
5359*3d8817e4Smiod   char *insn_p;
5360*3d8817e4Smiod   static xtensa_insnbuf insnbuf = NULL;
5361*3d8817e4Smiod   static xtensa_insnbuf slotbuf = NULL;
5362*3d8817e4Smiod   int opnum;
5363*3d8817e4Smiod   uint32 opnd_value;
5364*3d8817e4Smiod   xtensa_opcode opcode;
5365*3d8817e4Smiod   xtensa_format fmt;
5366*3d8817e4Smiod   int slot;
5367*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
5368*3d8817e4Smiod   valueT addr = fixP->fx_where + fixP->fx_frag->fr_address;
5369*3d8817e4Smiod   bfd_boolean alt_reloc;
5370*3d8817e4Smiod 
5371*3d8817e4Smiod   if (fixP->fx_r_type == BFD_RELOC_XTENSA_ASM_EXPAND)
5372*3d8817e4Smiod     return 0;
5373*3d8817e4Smiod 
5374*3d8817e4Smiod   if (!insnbuf)
5375*3d8817e4Smiod     {
5376*3d8817e4Smiod       insnbuf = xtensa_insnbuf_alloc (isa);
5377*3d8817e4Smiod       slotbuf = xtensa_insnbuf_alloc (isa);
5378*3d8817e4Smiod     }
5379*3d8817e4Smiod 
5380*3d8817e4Smiod   insn_p = &fixP->fx_frag->fr_literal[fixP->fx_where];
5381*3d8817e4Smiod   xtensa_insnbuf_from_chars (isa, insnbuf, (unsigned char *) insn_p, 0);
5382*3d8817e4Smiod   fmt = xtensa_format_decode (isa, insnbuf);
5383*3d8817e4Smiod 
5384*3d8817e4Smiod   if (fmt == XTENSA_UNDEFINED)
5385*3d8817e4Smiod     as_fatal (_("bad instruction format"));
5386*3d8817e4Smiod 
5387*3d8817e4Smiod   if (decode_reloc (fixP->fx_r_type, &slot, &alt_reloc) != 0)
5388*3d8817e4Smiod     as_fatal (_("invalid relocation"));
5389*3d8817e4Smiod 
5390*3d8817e4Smiod   xtensa_format_get_slot (isa, fmt, slot, insnbuf, slotbuf);
5391*3d8817e4Smiod   opcode = xtensa_opcode_decode (isa, fmt, slot, slotbuf);
5392*3d8817e4Smiod 
5393*3d8817e4Smiod   /* Check for "alternate" relocations (operand not specified).  None
5394*3d8817e4Smiod      of the current uses for these are really PC-relative.  */
5395*3d8817e4Smiod   if (alt_reloc || opcode == xtensa_const16_opcode)
5396*3d8817e4Smiod     {
5397*3d8817e4Smiod       if (opcode != xtensa_l32r_opcode
5398*3d8817e4Smiod 	  && opcode != xtensa_const16_opcode)
5399*3d8817e4Smiod 	as_fatal (_("invalid relocation for '%s' instruction"),
5400*3d8817e4Smiod 		  xtensa_opcode_name (isa, opcode));
5401*3d8817e4Smiod       return 0;
5402*3d8817e4Smiod     }
5403*3d8817e4Smiod 
5404*3d8817e4Smiod   opnum = get_relaxable_immed (opcode);
5405*3d8817e4Smiod   opnd_value = 0;
5406*3d8817e4Smiod   if (xtensa_operand_is_PCrelative (isa, opcode, opnum) != 1
5407*3d8817e4Smiod       || xtensa_operand_do_reloc (isa, opcode, opnum, &opnd_value, addr))
5408*3d8817e4Smiod     {
5409*3d8817e4Smiod       as_bad_where (fixP->fx_file,
5410*3d8817e4Smiod 		    fixP->fx_line,
5411*3d8817e4Smiod 		    _("invalid relocation for operand %d of '%s'"),
5412*3d8817e4Smiod 		    opnum, xtensa_opcode_name (isa, opcode));
5413*3d8817e4Smiod       return 0;
5414*3d8817e4Smiod     }
5415*3d8817e4Smiod   return 0 - opnd_value;
5416*3d8817e4Smiod }
5417*3d8817e4Smiod 
5418*3d8817e4Smiod 
5419*3d8817e4Smiod /* TC_FORCE_RELOCATION hook */
5420*3d8817e4Smiod 
5421*3d8817e4Smiod int
xtensa_force_relocation(fixS * fix)5422*3d8817e4Smiod xtensa_force_relocation (fixS *fix)
5423*3d8817e4Smiod {
5424*3d8817e4Smiod   switch (fix->fx_r_type)
5425*3d8817e4Smiod     {
5426*3d8817e4Smiod     case BFD_RELOC_XTENSA_ASM_EXPAND:
5427*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT0_ALT:
5428*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT1_ALT:
5429*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT2_ALT:
5430*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT3_ALT:
5431*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT4_ALT:
5432*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT5_ALT:
5433*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT6_ALT:
5434*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT7_ALT:
5435*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT8_ALT:
5436*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT9_ALT:
5437*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT10_ALT:
5438*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT11_ALT:
5439*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT12_ALT:
5440*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT13_ALT:
5441*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT14_ALT:
5442*3d8817e4Smiod       return 1;
5443*3d8817e4Smiod     default:
5444*3d8817e4Smiod       break;
5445*3d8817e4Smiod     }
5446*3d8817e4Smiod 
5447*3d8817e4Smiod   if (linkrelax && fix->fx_addsy
5448*3d8817e4Smiod       && relaxable_section (S_GET_SEGMENT (fix->fx_addsy)))
5449*3d8817e4Smiod     return 1;
5450*3d8817e4Smiod 
5451*3d8817e4Smiod   return generic_force_reloc (fix);
5452*3d8817e4Smiod }
5453*3d8817e4Smiod 
5454*3d8817e4Smiod 
5455*3d8817e4Smiod /* TC_VALIDATE_FIX_SUB hook */
5456*3d8817e4Smiod 
5457*3d8817e4Smiod int
xtensa_validate_fix_sub(fixS * fix)5458*3d8817e4Smiod xtensa_validate_fix_sub (fixS *fix)
5459*3d8817e4Smiod {
5460*3d8817e4Smiod   segT add_symbol_segment, sub_symbol_segment;
5461*3d8817e4Smiod 
5462*3d8817e4Smiod   /* The difference of two symbols should be resolved by the assembler when
5463*3d8817e4Smiod      linkrelax is not set.  If the linker may relax the section containing
5464*3d8817e4Smiod      the symbols, then an Xtensa DIFF relocation must be generated so that
5465*3d8817e4Smiod      the linker knows to adjust the difference value.  */
5466*3d8817e4Smiod   if (!linkrelax || fix->fx_addsy == NULL)
5467*3d8817e4Smiod     return 0;
5468*3d8817e4Smiod 
5469*3d8817e4Smiod   /* Make sure both symbols are in the same segment, and that segment is
5470*3d8817e4Smiod      "normal" and relaxable.  If the segment is not "normal", then the
5471*3d8817e4Smiod      fix is not valid.  If the segment is not "relaxable", then the fix
5472*3d8817e4Smiod      should have been handled earlier.  */
5473*3d8817e4Smiod   add_symbol_segment = S_GET_SEGMENT (fix->fx_addsy);
5474*3d8817e4Smiod   if (! SEG_NORMAL (add_symbol_segment) ||
5475*3d8817e4Smiod       ! relaxable_section (add_symbol_segment))
5476*3d8817e4Smiod     return 0;
5477*3d8817e4Smiod   sub_symbol_segment = S_GET_SEGMENT (fix->fx_subsy);
5478*3d8817e4Smiod   return (sub_symbol_segment == add_symbol_segment);
5479*3d8817e4Smiod }
5480*3d8817e4Smiod 
5481*3d8817e4Smiod 
5482*3d8817e4Smiod /* NO_PSEUDO_DOT hook */
5483*3d8817e4Smiod 
5484*3d8817e4Smiod /* This function has nothing to do with pseudo dots, but this is the
5485*3d8817e4Smiod    nearest macro to where the check needs to take place.  FIXME: This
5486*3d8817e4Smiod    seems wrong.  */
5487*3d8817e4Smiod 
5488*3d8817e4Smiod bfd_boolean
xtensa_check_inside_bundle(void)5489*3d8817e4Smiod xtensa_check_inside_bundle (void)
5490*3d8817e4Smiod {
5491*3d8817e4Smiod   if (cur_vinsn.inside_bundle && input_line_pointer[-1] == '.')
5492*3d8817e4Smiod     as_bad (_("directives are not valid inside bundles"));
5493*3d8817e4Smiod 
5494*3d8817e4Smiod   /* This function must always return FALSE because it is called via a
5495*3d8817e4Smiod      macro that has nothing to do with bundling.  */
5496*3d8817e4Smiod   return FALSE;
5497*3d8817e4Smiod }
5498*3d8817e4Smiod 
5499*3d8817e4Smiod 
5500*3d8817e4Smiod /* md_elf_section_change_hook */
5501*3d8817e4Smiod 
5502*3d8817e4Smiod void
xtensa_elf_section_change_hook(void)5503*3d8817e4Smiod xtensa_elf_section_change_hook (void)
5504*3d8817e4Smiod {
5505*3d8817e4Smiod   /* Set up the assembly state.  */
5506*3d8817e4Smiod   if (!frag_now->tc_frag_data.is_assembly_state_set)
5507*3d8817e4Smiod     xtensa_set_frag_assembly_state (frag_now);
5508*3d8817e4Smiod }
5509*3d8817e4Smiod 
5510*3d8817e4Smiod 
5511*3d8817e4Smiod /* tc_fix_adjustable hook */
5512*3d8817e4Smiod 
5513*3d8817e4Smiod bfd_boolean
xtensa_fix_adjustable(fixS * fixP)5514*3d8817e4Smiod xtensa_fix_adjustable (fixS *fixP)
5515*3d8817e4Smiod {
5516*3d8817e4Smiod   /* An offset is not allowed in combination with the difference of two
5517*3d8817e4Smiod      symbols, but that cannot be easily detected after a local symbol
5518*3d8817e4Smiod      has been adjusted to a (section+offset) form.  Return 0 so that such
5519*3d8817e4Smiod      an fix will not be adjusted.  */
5520*3d8817e4Smiod   if (fixP->fx_subsy && fixP->fx_addsy && fixP->fx_offset
5521*3d8817e4Smiod       && relaxable_section (S_GET_SEGMENT (fixP->fx_subsy)))
5522*3d8817e4Smiod     return 0;
5523*3d8817e4Smiod 
5524*3d8817e4Smiod   /* We need the symbol name for the VTABLE entries.  */
5525*3d8817e4Smiod   if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
5526*3d8817e4Smiod       || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
5527*3d8817e4Smiod     return 0;
5528*3d8817e4Smiod 
5529*3d8817e4Smiod   return 1;
5530*3d8817e4Smiod }
5531*3d8817e4Smiod 
5532*3d8817e4Smiod 
5533*3d8817e4Smiod void
md_apply_fix(fixS * fixP,valueT * valP,segT seg)5534*3d8817e4Smiod md_apply_fix (fixS *fixP, valueT *valP, segT seg)
5535*3d8817e4Smiod {
5536*3d8817e4Smiod   char *const fixpos = fixP->fx_frag->fr_literal + fixP->fx_where;
5537*3d8817e4Smiod   valueT val = 0;
5538*3d8817e4Smiod 
5539*3d8817e4Smiod   /* Subtracted symbols are only allowed for a few relocation types, and
5540*3d8817e4Smiod      unless linkrelax is enabled, they should not make it to this point.  */
5541*3d8817e4Smiod   if (fixP->fx_subsy && !(linkrelax && (fixP->fx_r_type == BFD_RELOC_32
5542*3d8817e4Smiod 					|| fixP->fx_r_type == BFD_RELOC_16
5543*3d8817e4Smiod 					|| fixP->fx_r_type == BFD_RELOC_8)))
5544*3d8817e4Smiod     as_bad_where (fixP->fx_file, fixP->fx_line, _("expression too complex"));
5545*3d8817e4Smiod 
5546*3d8817e4Smiod   switch (fixP->fx_r_type)
5547*3d8817e4Smiod     {
5548*3d8817e4Smiod     case BFD_RELOC_32:
5549*3d8817e4Smiod     case BFD_RELOC_16:
5550*3d8817e4Smiod     case BFD_RELOC_8:
5551*3d8817e4Smiod       if (fixP->fx_subsy)
5552*3d8817e4Smiod 	{
5553*3d8817e4Smiod 	  switch (fixP->fx_r_type)
5554*3d8817e4Smiod 	    {
5555*3d8817e4Smiod 	    case BFD_RELOC_8:
5556*3d8817e4Smiod 	      fixP->fx_r_type = BFD_RELOC_XTENSA_DIFF8;
5557*3d8817e4Smiod 	      break;
5558*3d8817e4Smiod 	    case BFD_RELOC_16:
5559*3d8817e4Smiod 	      fixP->fx_r_type = BFD_RELOC_XTENSA_DIFF16;
5560*3d8817e4Smiod 	      break;
5561*3d8817e4Smiod 	    case BFD_RELOC_32:
5562*3d8817e4Smiod 	      fixP->fx_r_type = BFD_RELOC_XTENSA_DIFF32;
5563*3d8817e4Smiod 	      break;
5564*3d8817e4Smiod 	    default:
5565*3d8817e4Smiod 	      break;
5566*3d8817e4Smiod 	    }
5567*3d8817e4Smiod 
5568*3d8817e4Smiod 	  /* An offset is only allowed when it results from adjusting a
5569*3d8817e4Smiod 	     local symbol into a section-relative offset.  If the offset
5570*3d8817e4Smiod 	     came from the original expression, tc_fix_adjustable will have
5571*3d8817e4Smiod 	     prevented the fix from being converted to a section-relative
5572*3d8817e4Smiod 	     form so that we can flag the error here.  */
5573*3d8817e4Smiod 	  if (fixP->fx_offset != 0 && !symbol_section_p (fixP->fx_addsy))
5574*3d8817e4Smiod 	    as_bad_where (fixP->fx_file, fixP->fx_line,
5575*3d8817e4Smiod 			  _("cannot represent subtraction with an offset"));
5576*3d8817e4Smiod 
5577*3d8817e4Smiod 	  val = (S_GET_VALUE (fixP->fx_addsy) + fixP->fx_offset
5578*3d8817e4Smiod 		 - S_GET_VALUE (fixP->fx_subsy));
5579*3d8817e4Smiod 
5580*3d8817e4Smiod 	  /* The difference value gets written out, and the DIFF reloc
5581*3d8817e4Smiod 	     identifies the address of the subtracted symbol (i.e., the one
5582*3d8817e4Smiod 	     with the lowest address).  */
5583*3d8817e4Smiod 	  *valP = val;
5584*3d8817e4Smiod 	  fixP->fx_offset -= val;
5585*3d8817e4Smiod 	  fixP->fx_subsy = NULL;
5586*3d8817e4Smiod 	}
5587*3d8817e4Smiod       else if (! fixP->fx_addsy)
5588*3d8817e4Smiod 	{
5589*3d8817e4Smiod 	  val = *valP;
5590*3d8817e4Smiod 	  fixP->fx_done = 1;
5591*3d8817e4Smiod 	}
5592*3d8817e4Smiod       /* fall through */
5593*3d8817e4Smiod 
5594*3d8817e4Smiod     case BFD_RELOC_XTENSA_PLT:
5595*3d8817e4Smiod       md_number_to_chars (fixpos, val, fixP->fx_size);
5596*3d8817e4Smiod       fixP->fx_no_overflow = 0; /* Use the standard overflow check.  */
5597*3d8817e4Smiod       break;
5598*3d8817e4Smiod 
5599*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT0_OP:
5600*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT1_OP:
5601*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT2_OP:
5602*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT3_OP:
5603*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT4_OP:
5604*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT5_OP:
5605*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT6_OP:
5606*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT7_OP:
5607*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT8_OP:
5608*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT9_OP:
5609*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT10_OP:
5610*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT11_OP:
5611*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT12_OP:
5612*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT13_OP:
5613*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT14_OP:
5614*3d8817e4Smiod       if (linkrelax)
5615*3d8817e4Smiod 	{
5616*3d8817e4Smiod 	  /* Write the tentative value of a PC-relative relocation to a
5617*3d8817e4Smiod 	     local symbol into the instruction.  The value will be ignored
5618*3d8817e4Smiod 	     by the linker, and it makes the object file disassembly
5619*3d8817e4Smiod 	     readable when all branch targets are encoded in relocations.  */
5620*3d8817e4Smiod 
5621*3d8817e4Smiod 	  assert (fixP->fx_addsy);
5622*3d8817e4Smiod 	  if (S_GET_SEGMENT (fixP->fx_addsy) == seg && !fixP->fx_plt
5623*3d8817e4Smiod 	      && !S_FORCE_RELOC (fixP->fx_addsy, 1))
5624*3d8817e4Smiod 	    {
5625*3d8817e4Smiod 	      val = (S_GET_VALUE (fixP->fx_addsy) + fixP->fx_offset
5626*3d8817e4Smiod 		     - md_pcrel_from (fixP));
5627*3d8817e4Smiod 	      (void) xg_apply_fix_value (fixP, val);
5628*3d8817e4Smiod 	    }
5629*3d8817e4Smiod 	}
5630*3d8817e4Smiod       else if (! fixP->fx_addsy)
5631*3d8817e4Smiod 	{
5632*3d8817e4Smiod 	  val = *valP;
5633*3d8817e4Smiod 	  if (xg_apply_fix_value (fixP, val))
5634*3d8817e4Smiod 	    fixP->fx_done = 1;
5635*3d8817e4Smiod 	}
5636*3d8817e4Smiod       break;
5637*3d8817e4Smiod 
5638*3d8817e4Smiod     case BFD_RELOC_XTENSA_ASM_EXPAND:
5639*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT0_ALT:
5640*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT1_ALT:
5641*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT2_ALT:
5642*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT3_ALT:
5643*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT4_ALT:
5644*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT5_ALT:
5645*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT6_ALT:
5646*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT7_ALT:
5647*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT8_ALT:
5648*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT9_ALT:
5649*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT10_ALT:
5650*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT11_ALT:
5651*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT12_ALT:
5652*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT13_ALT:
5653*3d8817e4Smiod     case BFD_RELOC_XTENSA_SLOT14_ALT:
5654*3d8817e4Smiod       /* These all need to be resolved at link-time.  Do nothing now.  */
5655*3d8817e4Smiod       break;
5656*3d8817e4Smiod 
5657*3d8817e4Smiod     case BFD_RELOC_VTABLE_INHERIT:
5658*3d8817e4Smiod     case BFD_RELOC_VTABLE_ENTRY:
5659*3d8817e4Smiod       fixP->fx_done = 0;
5660*3d8817e4Smiod       break;
5661*3d8817e4Smiod 
5662*3d8817e4Smiod     default:
5663*3d8817e4Smiod       as_bad (_("unhandled local relocation fix %s"),
5664*3d8817e4Smiod 	      bfd_get_reloc_code_name (fixP->fx_r_type));
5665*3d8817e4Smiod     }
5666*3d8817e4Smiod }
5667*3d8817e4Smiod 
5668*3d8817e4Smiod 
5669*3d8817e4Smiod char *
md_atof(int type,char * litP,int * sizeP)5670*3d8817e4Smiod md_atof (int type, char *litP, int *sizeP)
5671*3d8817e4Smiod {
5672*3d8817e4Smiod   int prec;
5673*3d8817e4Smiod   LITTLENUM_TYPE words[4];
5674*3d8817e4Smiod   char *t;
5675*3d8817e4Smiod   int i;
5676*3d8817e4Smiod 
5677*3d8817e4Smiod   switch (type)
5678*3d8817e4Smiod     {
5679*3d8817e4Smiod     case 'f':
5680*3d8817e4Smiod       prec = 2;
5681*3d8817e4Smiod       break;
5682*3d8817e4Smiod 
5683*3d8817e4Smiod     case 'd':
5684*3d8817e4Smiod       prec = 4;
5685*3d8817e4Smiod       break;
5686*3d8817e4Smiod 
5687*3d8817e4Smiod     default:
5688*3d8817e4Smiod       *sizeP = 0;
5689*3d8817e4Smiod       return "bad call to md_atof";
5690*3d8817e4Smiod     }
5691*3d8817e4Smiod 
5692*3d8817e4Smiod   t = atof_ieee (input_line_pointer, type, words);
5693*3d8817e4Smiod   if (t)
5694*3d8817e4Smiod     input_line_pointer = t;
5695*3d8817e4Smiod 
5696*3d8817e4Smiod   *sizeP = prec * 2;
5697*3d8817e4Smiod 
5698*3d8817e4Smiod   for (i = prec - 1; i >= 0; i--)
5699*3d8817e4Smiod     {
5700*3d8817e4Smiod       int idx = i;
5701*3d8817e4Smiod       if (target_big_endian)
5702*3d8817e4Smiod 	idx = (prec - 1 - i);
5703*3d8817e4Smiod 
5704*3d8817e4Smiod       md_number_to_chars (litP, (valueT) words[idx], 2);
5705*3d8817e4Smiod       litP += 2;
5706*3d8817e4Smiod     }
5707*3d8817e4Smiod 
5708*3d8817e4Smiod   return NULL;
5709*3d8817e4Smiod }
5710*3d8817e4Smiod 
5711*3d8817e4Smiod 
5712*3d8817e4Smiod int
md_estimate_size_before_relax(fragS * fragP,segT seg ATTRIBUTE_UNUSED)5713*3d8817e4Smiod md_estimate_size_before_relax (fragS *fragP, segT seg ATTRIBUTE_UNUSED)
5714*3d8817e4Smiod {
5715*3d8817e4Smiod   return total_frag_text_expansion (fragP);
5716*3d8817e4Smiod }
5717*3d8817e4Smiod 
5718*3d8817e4Smiod 
5719*3d8817e4Smiod /* Translate internal representation of relocation info to BFD target
5720*3d8817e4Smiod    format.  */
5721*3d8817e4Smiod 
5722*3d8817e4Smiod arelent *
tc_gen_reloc(asection * section ATTRIBUTE_UNUSED,fixS * fixp)5723*3d8817e4Smiod tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
5724*3d8817e4Smiod {
5725*3d8817e4Smiod   arelent *reloc;
5726*3d8817e4Smiod 
5727*3d8817e4Smiod   reloc = (arelent *) xmalloc (sizeof (arelent));
5728*3d8817e4Smiod   reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
5729*3d8817e4Smiod   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
5730*3d8817e4Smiod   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
5731*3d8817e4Smiod 
5732*3d8817e4Smiod   /* Make sure none of our internal relocations make it this far.
5733*3d8817e4Smiod      They'd better have been fully resolved by this point.  */
5734*3d8817e4Smiod   assert ((int) fixp->fx_r_type > 0);
5735*3d8817e4Smiod 
5736*3d8817e4Smiod   reloc->addend = fixp->fx_offset;
5737*3d8817e4Smiod 
5738*3d8817e4Smiod   reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
5739*3d8817e4Smiod   if (reloc->howto == NULL)
5740*3d8817e4Smiod     {
5741*3d8817e4Smiod       as_bad_where (fixp->fx_file, fixp->fx_line,
5742*3d8817e4Smiod 		    _("cannot represent `%s' relocation in object file"),
5743*3d8817e4Smiod 		    bfd_get_reloc_code_name (fixp->fx_r_type));
5744*3d8817e4Smiod       free (reloc->sym_ptr_ptr);
5745*3d8817e4Smiod       free (reloc);
5746*3d8817e4Smiod       return NULL;
5747*3d8817e4Smiod     }
5748*3d8817e4Smiod 
5749*3d8817e4Smiod   if (!fixp->fx_pcrel != !reloc->howto->pc_relative)
5750*3d8817e4Smiod     as_fatal (_("internal error? cannot generate `%s' relocation"),
5751*3d8817e4Smiod 	      bfd_get_reloc_code_name (fixp->fx_r_type));
5752*3d8817e4Smiod 
5753*3d8817e4Smiod   return reloc;
5754*3d8817e4Smiod }
5755*3d8817e4Smiod 
5756*3d8817e4Smiod 
5757*3d8817e4Smiod /* Checks for resource conflicts between instructions.  */
5758*3d8817e4Smiod 
5759*3d8817e4Smiod /* The func unit stuff could be implemented as bit-vectors rather
5760*3d8817e4Smiod    than the iterative approach here.  If it ends up being too
5761*3d8817e4Smiod    slow, we will switch it.  */
5762*3d8817e4Smiod 
5763*3d8817e4Smiod resource_table *
new_resource_table(void * data,int cycles,int nu,unit_num_copies_func uncf,opcode_num_units_func onuf,opcode_funcUnit_use_unit_func ouuf,opcode_funcUnit_use_stage_func ousf)5764*3d8817e4Smiod new_resource_table (void *data,
5765*3d8817e4Smiod 		    int cycles,
5766*3d8817e4Smiod 		    int nu,
5767*3d8817e4Smiod 		    unit_num_copies_func uncf,
5768*3d8817e4Smiod 		    opcode_num_units_func onuf,
5769*3d8817e4Smiod 		    opcode_funcUnit_use_unit_func ouuf,
5770*3d8817e4Smiod 		    opcode_funcUnit_use_stage_func ousf)
5771*3d8817e4Smiod {
5772*3d8817e4Smiod   int i;
5773*3d8817e4Smiod   resource_table *rt = (resource_table *) xmalloc (sizeof (resource_table));
5774*3d8817e4Smiod   rt->data = data;
5775*3d8817e4Smiod   rt->cycles = cycles;
5776*3d8817e4Smiod   rt->allocated_cycles = cycles;
5777*3d8817e4Smiod   rt->num_units = nu;
5778*3d8817e4Smiod   rt->unit_num_copies = uncf;
5779*3d8817e4Smiod   rt->opcode_num_units = onuf;
5780*3d8817e4Smiod   rt->opcode_unit_use = ouuf;
5781*3d8817e4Smiod   rt->opcode_unit_stage = ousf;
5782*3d8817e4Smiod 
5783*3d8817e4Smiod   rt->units = (unsigned char **) xcalloc (cycles, sizeof (unsigned char *));
5784*3d8817e4Smiod   for (i = 0; i < cycles; i++)
5785*3d8817e4Smiod     rt->units[i] = (unsigned char *) xcalloc (nu, sizeof (unsigned char));
5786*3d8817e4Smiod 
5787*3d8817e4Smiod   return rt;
5788*3d8817e4Smiod }
5789*3d8817e4Smiod 
5790*3d8817e4Smiod 
5791*3d8817e4Smiod void
clear_resource_table(resource_table * rt)5792*3d8817e4Smiod clear_resource_table (resource_table *rt)
5793*3d8817e4Smiod {
5794*3d8817e4Smiod   int i, j;
5795*3d8817e4Smiod   for (i = 0; i < rt->allocated_cycles; i++)
5796*3d8817e4Smiod     for (j = 0; j < rt->num_units; j++)
5797*3d8817e4Smiod       rt->units[i][j] = 0;
5798*3d8817e4Smiod }
5799*3d8817e4Smiod 
5800*3d8817e4Smiod 
5801*3d8817e4Smiod /* We never shrink it, just fake it into thinking so.  */
5802*3d8817e4Smiod 
5803*3d8817e4Smiod void
resize_resource_table(resource_table * rt,int cycles)5804*3d8817e4Smiod resize_resource_table (resource_table *rt, int cycles)
5805*3d8817e4Smiod {
5806*3d8817e4Smiod   int i, old_cycles;
5807*3d8817e4Smiod 
5808*3d8817e4Smiod   rt->cycles = cycles;
5809*3d8817e4Smiod   if (cycles <= rt->allocated_cycles)
5810*3d8817e4Smiod     return;
5811*3d8817e4Smiod 
5812*3d8817e4Smiod   old_cycles = rt->allocated_cycles;
5813*3d8817e4Smiod   rt->allocated_cycles = cycles;
5814*3d8817e4Smiod 
5815*3d8817e4Smiod   rt->units = xrealloc (rt->units,
5816*3d8817e4Smiod 			rt->allocated_cycles * sizeof (unsigned char *));
5817*3d8817e4Smiod   for (i = 0; i < old_cycles; i++)
5818*3d8817e4Smiod     rt->units[i] = xrealloc (rt->units[i],
5819*3d8817e4Smiod 			     rt->num_units * sizeof (unsigned char));
5820*3d8817e4Smiod   for (i = old_cycles; i < cycles; i++)
5821*3d8817e4Smiod     rt->units[i] = xcalloc (rt->num_units, sizeof (unsigned char));
5822*3d8817e4Smiod }
5823*3d8817e4Smiod 
5824*3d8817e4Smiod 
5825*3d8817e4Smiod bfd_boolean
resources_available(resource_table * rt,xtensa_opcode opcode,int cycle)5826*3d8817e4Smiod resources_available (resource_table *rt, xtensa_opcode opcode, int cycle)
5827*3d8817e4Smiod {
5828*3d8817e4Smiod   int i;
5829*3d8817e4Smiod   int uses = (rt->opcode_num_units) (rt->data, opcode);
5830*3d8817e4Smiod 
5831*3d8817e4Smiod   for (i = 0; i < uses; i++)
5832*3d8817e4Smiod     {
5833*3d8817e4Smiod       xtensa_funcUnit unit = (rt->opcode_unit_use) (rt->data, opcode, i);
5834*3d8817e4Smiod       int stage = (rt->opcode_unit_stage) (rt->data, opcode, i);
5835*3d8817e4Smiod       int copies_in_use = rt->units[stage + cycle][unit];
5836*3d8817e4Smiod       int copies = (rt->unit_num_copies) (rt->data, unit);
5837*3d8817e4Smiod       if (copies_in_use >= copies)
5838*3d8817e4Smiod 	return FALSE;
5839*3d8817e4Smiod     }
5840*3d8817e4Smiod   return TRUE;
5841*3d8817e4Smiod }
5842*3d8817e4Smiod 
5843*3d8817e4Smiod 
5844*3d8817e4Smiod void
reserve_resources(resource_table * rt,xtensa_opcode opcode,int cycle)5845*3d8817e4Smiod reserve_resources (resource_table *rt, xtensa_opcode opcode, int cycle)
5846*3d8817e4Smiod {
5847*3d8817e4Smiod   int i;
5848*3d8817e4Smiod   int uses = (rt->opcode_num_units) (rt->data, opcode);
5849*3d8817e4Smiod 
5850*3d8817e4Smiod   for (i = 0; i < uses; i++)
5851*3d8817e4Smiod     {
5852*3d8817e4Smiod       xtensa_funcUnit unit = (rt->opcode_unit_use) (rt->data, opcode, i);
5853*3d8817e4Smiod       int stage = (rt->opcode_unit_stage) (rt->data, opcode, i);
5854*3d8817e4Smiod       /* Note that this allows resources to be oversubscribed.  That's
5855*3d8817e4Smiod 	 essential to the way the optional scheduler works.
5856*3d8817e4Smiod 	 resources_available reports when a resource is over-subscribed,
5857*3d8817e4Smiod 	 so it's easy to tell.  */
5858*3d8817e4Smiod       rt->units[stage + cycle][unit]++;
5859*3d8817e4Smiod     }
5860*3d8817e4Smiod }
5861*3d8817e4Smiod 
5862*3d8817e4Smiod 
5863*3d8817e4Smiod void
release_resources(resource_table * rt,xtensa_opcode opcode,int cycle)5864*3d8817e4Smiod release_resources (resource_table *rt, xtensa_opcode opcode, int cycle)
5865*3d8817e4Smiod {
5866*3d8817e4Smiod   int i;
5867*3d8817e4Smiod   int uses = (rt->opcode_num_units) (rt->data, opcode);
5868*3d8817e4Smiod 
5869*3d8817e4Smiod   for (i = 0; i < uses; i++)
5870*3d8817e4Smiod     {
5871*3d8817e4Smiod       xtensa_funcUnit unit = (rt->opcode_unit_use) (rt->data, opcode, i);
5872*3d8817e4Smiod       int stage = (rt->opcode_unit_stage) (rt->data, opcode, i);
5873*3d8817e4Smiod       assert (rt->units[stage + cycle][unit] > 0);
5874*3d8817e4Smiod       rt->units[stage + cycle][unit]--;
5875*3d8817e4Smiod     }
5876*3d8817e4Smiod }
5877*3d8817e4Smiod 
5878*3d8817e4Smiod 
5879*3d8817e4Smiod /* Wrapper functions make parameterized resource reservation
5880*3d8817e4Smiod    more convenient.  */
5881*3d8817e4Smiod 
5882*3d8817e4Smiod int
opcode_funcUnit_use_unit(void * data,xtensa_opcode opcode,int idx)5883*3d8817e4Smiod opcode_funcUnit_use_unit (void *data, xtensa_opcode opcode, int idx)
5884*3d8817e4Smiod {
5885*3d8817e4Smiod   xtensa_funcUnit_use *use = xtensa_opcode_funcUnit_use (data, opcode, idx);
5886*3d8817e4Smiod   return use->unit;
5887*3d8817e4Smiod }
5888*3d8817e4Smiod 
5889*3d8817e4Smiod 
5890*3d8817e4Smiod int
opcode_funcUnit_use_stage(void * data,xtensa_opcode opcode,int idx)5891*3d8817e4Smiod opcode_funcUnit_use_stage (void *data, xtensa_opcode opcode, int idx)
5892*3d8817e4Smiod {
5893*3d8817e4Smiod   xtensa_funcUnit_use *use = xtensa_opcode_funcUnit_use (data, opcode, idx);
5894*3d8817e4Smiod   return use->stage;
5895*3d8817e4Smiod }
5896*3d8817e4Smiod 
5897*3d8817e4Smiod 
5898*3d8817e4Smiod /* Note that this function does not check issue constraints, but
5899*3d8817e4Smiod    solely whether the hardware is available to execute the given
5900*3d8817e4Smiod    instructions together.  It also doesn't check if the tinsns
5901*3d8817e4Smiod    write the same state, or access the same tieports.  That is
5902*3d8817e4Smiod    checked by check_t1_t2_reads_and_writes.  */
5903*3d8817e4Smiod 
5904*3d8817e4Smiod static bfd_boolean
resources_conflict(vliw_insn * vinsn)5905*3d8817e4Smiod resources_conflict (vliw_insn *vinsn)
5906*3d8817e4Smiod {
5907*3d8817e4Smiod   int i;
5908*3d8817e4Smiod   static resource_table *rt = NULL;
5909*3d8817e4Smiod 
5910*3d8817e4Smiod   /* This is the most common case by far.  Optimize it.  */
5911*3d8817e4Smiod   if (vinsn->num_slots == 1)
5912*3d8817e4Smiod     return FALSE;
5913*3d8817e4Smiod 
5914*3d8817e4Smiod   if (rt == NULL)
5915*3d8817e4Smiod     {
5916*3d8817e4Smiod       xtensa_isa isa = xtensa_default_isa;
5917*3d8817e4Smiod       rt = new_resource_table
5918*3d8817e4Smiod 	(isa, xtensa_isa_num_pipe_stages (isa),
5919*3d8817e4Smiod 	 xtensa_isa_num_funcUnits (isa),
5920*3d8817e4Smiod 	 (unit_num_copies_func) xtensa_funcUnit_num_copies,
5921*3d8817e4Smiod 	 (opcode_num_units_func) xtensa_opcode_num_funcUnit_uses,
5922*3d8817e4Smiod 	 opcode_funcUnit_use_unit,
5923*3d8817e4Smiod 	 opcode_funcUnit_use_stage);
5924*3d8817e4Smiod     }
5925*3d8817e4Smiod 
5926*3d8817e4Smiod   clear_resource_table (rt);
5927*3d8817e4Smiod 
5928*3d8817e4Smiod   for (i = 0; i < vinsn->num_slots; i++)
5929*3d8817e4Smiod     {
5930*3d8817e4Smiod       if (!resources_available (rt, vinsn->slots[i].opcode, 0))
5931*3d8817e4Smiod 	return TRUE;
5932*3d8817e4Smiod       reserve_resources (rt, vinsn->slots[i].opcode, 0);
5933*3d8817e4Smiod     }
5934*3d8817e4Smiod 
5935*3d8817e4Smiod   return FALSE;
5936*3d8817e4Smiod }
5937*3d8817e4Smiod 
5938*3d8817e4Smiod 
5939*3d8817e4Smiod /* finish_vinsn, emit_single_op and helper functions.  */
5940*3d8817e4Smiod 
5941*3d8817e4Smiod static bfd_boolean find_vinsn_conflicts (vliw_insn *);
5942*3d8817e4Smiod static xtensa_format xg_find_narrowest_format (vliw_insn *);
5943*3d8817e4Smiod static void xg_assemble_vliw_tokens (vliw_insn *);
5944*3d8817e4Smiod 
5945*3d8817e4Smiod 
5946*3d8817e4Smiod /* We have reached the end of a bundle; emit into the frag.  */
5947*3d8817e4Smiod 
5948*3d8817e4Smiod static void
finish_vinsn(vliw_insn * vinsn)5949*3d8817e4Smiod finish_vinsn (vliw_insn *vinsn)
5950*3d8817e4Smiod {
5951*3d8817e4Smiod   IStack slotstack;
5952*3d8817e4Smiod   int i;
5953*3d8817e4Smiod   char *file_name;
5954*3d8817e4Smiod   unsigned line;
5955*3d8817e4Smiod 
5956*3d8817e4Smiod   if (find_vinsn_conflicts (vinsn))
5957*3d8817e4Smiod     {
5958*3d8817e4Smiod       xg_clear_vinsn (vinsn);
5959*3d8817e4Smiod       return;
5960*3d8817e4Smiod     }
5961*3d8817e4Smiod 
5962*3d8817e4Smiod   /* First, find a format that works.  */
5963*3d8817e4Smiod   if (vinsn->format == XTENSA_UNDEFINED)
5964*3d8817e4Smiod     vinsn->format = xg_find_narrowest_format (vinsn);
5965*3d8817e4Smiod 
5966*3d8817e4Smiod   if (vinsn->format == XTENSA_UNDEFINED)
5967*3d8817e4Smiod     {
5968*3d8817e4Smiod       as_where (&file_name, &line);
5969*3d8817e4Smiod       as_bad_where (file_name, line,
5970*3d8817e4Smiod 		    _("couldn't find a valid instruction format"));
5971*3d8817e4Smiod       fprintf (stderr, _("    ops were: "));
5972*3d8817e4Smiod       for (i = 0; i < vinsn->num_slots; i++)
5973*3d8817e4Smiod 	fprintf (stderr, _(" %s;"),
5974*3d8817e4Smiod 		 xtensa_opcode_name (xtensa_default_isa,
5975*3d8817e4Smiod 				     vinsn->slots[i].opcode));
5976*3d8817e4Smiod       fprintf (stderr, _("\n"));
5977*3d8817e4Smiod       xg_clear_vinsn (vinsn);
5978*3d8817e4Smiod       return;
5979*3d8817e4Smiod     }
5980*3d8817e4Smiod 
5981*3d8817e4Smiod   if (vinsn->num_slots
5982*3d8817e4Smiod       != xtensa_format_num_slots (xtensa_default_isa, vinsn->format))
5983*3d8817e4Smiod     {
5984*3d8817e4Smiod       as_bad (_("format '%s' allows %d slots, but there are %d opcodes"),
5985*3d8817e4Smiod 	      xtensa_format_name (xtensa_default_isa, vinsn->format),
5986*3d8817e4Smiod 	      xtensa_format_num_slots (xtensa_default_isa, vinsn->format),
5987*3d8817e4Smiod 	      vinsn->num_slots);
5988*3d8817e4Smiod       xg_clear_vinsn (vinsn);
5989*3d8817e4Smiod       return;
5990*3d8817e4Smiod     }
5991*3d8817e4Smiod 
5992*3d8817e4Smiod   if (resources_conflict (vinsn))
5993*3d8817e4Smiod     {
5994*3d8817e4Smiod       as_where (&file_name, &line);
5995*3d8817e4Smiod       as_bad_where (file_name, line, _("illegal resource usage in bundle"));
5996*3d8817e4Smiod       fprintf (stderr, "    ops were: ");
5997*3d8817e4Smiod       for (i = 0; i < vinsn->num_slots; i++)
5998*3d8817e4Smiod 	fprintf (stderr, " %s;",
5999*3d8817e4Smiod 		 xtensa_opcode_name (xtensa_default_isa,
6000*3d8817e4Smiod 				     vinsn->slots[i].opcode));
6001*3d8817e4Smiod       fprintf (stderr, "\n");
6002*3d8817e4Smiod       xg_clear_vinsn (vinsn);
6003*3d8817e4Smiod       return;
6004*3d8817e4Smiod     }
6005*3d8817e4Smiod 
6006*3d8817e4Smiod   for (i = 0; i < vinsn->num_slots; i++)
6007*3d8817e4Smiod     {
6008*3d8817e4Smiod       if (vinsn->slots[i].opcode != XTENSA_UNDEFINED)
6009*3d8817e4Smiod 	{
6010*3d8817e4Smiod 	  symbolS *lit_sym = NULL;
6011*3d8817e4Smiod 	  int j;
6012*3d8817e4Smiod 	  bfd_boolean e = FALSE;
6013*3d8817e4Smiod 	  bfd_boolean saved_density = density_supported;
6014*3d8817e4Smiod 
6015*3d8817e4Smiod 	  /* We don't want to narrow ops inside multi-slot bundles.  */
6016*3d8817e4Smiod 	  if (vinsn->num_slots > 1)
6017*3d8817e4Smiod 	    density_supported = FALSE;
6018*3d8817e4Smiod 
6019*3d8817e4Smiod 	  istack_init (&slotstack);
6020*3d8817e4Smiod 	  if (vinsn->slots[i].opcode == xtensa_nop_opcode)
6021*3d8817e4Smiod 	    {
6022*3d8817e4Smiod 	      vinsn->slots[i].opcode =
6023*3d8817e4Smiod 		xtensa_format_slot_nop_opcode (xtensa_default_isa,
6024*3d8817e4Smiod 					       vinsn->format, i);
6025*3d8817e4Smiod 	      vinsn->slots[i].ntok = 0;
6026*3d8817e4Smiod 	    }
6027*3d8817e4Smiod 
6028*3d8817e4Smiod 	  if (xg_expand_assembly_insn (&slotstack, &vinsn->slots[i]))
6029*3d8817e4Smiod 	    {
6030*3d8817e4Smiod 	      e = TRUE;
6031*3d8817e4Smiod 	      continue;
6032*3d8817e4Smiod 	    }
6033*3d8817e4Smiod 
6034*3d8817e4Smiod 	  density_supported = saved_density;
6035*3d8817e4Smiod 
6036*3d8817e4Smiod 	  if (e)
6037*3d8817e4Smiod 	    {
6038*3d8817e4Smiod 	      xg_clear_vinsn (vinsn);
6039*3d8817e4Smiod 	      return;
6040*3d8817e4Smiod 	    }
6041*3d8817e4Smiod 
6042*3d8817e4Smiod 	  for (j = 0; j < slotstack.ninsn; j++)
6043*3d8817e4Smiod 	    {
6044*3d8817e4Smiod 	      TInsn *insn = &slotstack.insn[j];
6045*3d8817e4Smiod 	      if (insn->insn_type == ITYPE_LITERAL)
6046*3d8817e4Smiod 		{
6047*3d8817e4Smiod 		  assert (lit_sym == NULL);
6048*3d8817e4Smiod 		  lit_sym = xg_assemble_literal (insn);
6049*3d8817e4Smiod 		}
6050*3d8817e4Smiod 	      else
6051*3d8817e4Smiod 		{
6052*3d8817e4Smiod 		  assert (insn->insn_type == ITYPE_INSN);
6053*3d8817e4Smiod 		  if (lit_sym)
6054*3d8817e4Smiod 		    xg_resolve_literals (insn, lit_sym);
6055*3d8817e4Smiod 		  if (j != slotstack.ninsn - 1)
6056*3d8817e4Smiod 		    emit_single_op (insn);
6057*3d8817e4Smiod 		}
6058*3d8817e4Smiod 	    }
6059*3d8817e4Smiod 
6060*3d8817e4Smiod 	  if (vinsn->num_slots > 1)
6061*3d8817e4Smiod 	    {
6062*3d8817e4Smiod 	      if (opcode_fits_format_slot
6063*3d8817e4Smiod 		  (slotstack.insn[slotstack.ninsn - 1].opcode,
6064*3d8817e4Smiod 		   vinsn->format, i))
6065*3d8817e4Smiod 		{
6066*3d8817e4Smiod 		  vinsn->slots[i] = slotstack.insn[slotstack.ninsn - 1];
6067*3d8817e4Smiod 		}
6068*3d8817e4Smiod 	      else
6069*3d8817e4Smiod 		{
6070*3d8817e4Smiod 		  emit_single_op (&slotstack.insn[slotstack.ninsn - 1]);
6071*3d8817e4Smiod 		  if (vinsn->format == XTENSA_UNDEFINED)
6072*3d8817e4Smiod 		    vinsn->slots[i].opcode = xtensa_nop_opcode;
6073*3d8817e4Smiod 		  else
6074*3d8817e4Smiod 		    vinsn->slots[i].opcode
6075*3d8817e4Smiod 		      = xtensa_format_slot_nop_opcode (xtensa_default_isa,
6076*3d8817e4Smiod 						       vinsn->format, i);
6077*3d8817e4Smiod 
6078*3d8817e4Smiod 		  vinsn->slots[i].ntok = 0;
6079*3d8817e4Smiod 		}
6080*3d8817e4Smiod 	    }
6081*3d8817e4Smiod 	  else
6082*3d8817e4Smiod 	    {
6083*3d8817e4Smiod 	      vinsn->slots[0] = slotstack.insn[slotstack.ninsn - 1];
6084*3d8817e4Smiod 	      vinsn->format = XTENSA_UNDEFINED;
6085*3d8817e4Smiod 	    }
6086*3d8817e4Smiod 	}
6087*3d8817e4Smiod     }
6088*3d8817e4Smiod 
6089*3d8817e4Smiod   /* Now check resource conflicts on the modified bundle.  */
6090*3d8817e4Smiod   if (resources_conflict (vinsn))
6091*3d8817e4Smiod     {
6092*3d8817e4Smiod       as_where (&file_name, &line);
6093*3d8817e4Smiod       as_bad_where (file_name, line, _("illegal resource usage in bundle"));
6094*3d8817e4Smiod       fprintf (stderr, "    ops were: ");
6095*3d8817e4Smiod       for (i = 0; i < vinsn->num_slots; i++)
6096*3d8817e4Smiod 	fprintf (stderr, " %s;",
6097*3d8817e4Smiod 		 xtensa_opcode_name (xtensa_default_isa,
6098*3d8817e4Smiod 				     vinsn->slots[i].opcode));
6099*3d8817e4Smiod       fprintf (stderr, "\n");
6100*3d8817e4Smiod       xg_clear_vinsn (vinsn);
6101*3d8817e4Smiod       return;
6102*3d8817e4Smiod     }
6103*3d8817e4Smiod 
6104*3d8817e4Smiod   /* First, find a format that works.  */
6105*3d8817e4Smiod   if (vinsn->format == XTENSA_UNDEFINED)
6106*3d8817e4Smiod       vinsn->format = xg_find_narrowest_format (vinsn);
6107*3d8817e4Smiod 
6108*3d8817e4Smiod   xg_assemble_vliw_tokens (vinsn);
6109*3d8817e4Smiod 
6110*3d8817e4Smiod   xg_clear_vinsn (vinsn);
6111*3d8817e4Smiod }
6112*3d8817e4Smiod 
6113*3d8817e4Smiod 
6114*3d8817e4Smiod /* Given an vliw instruction, what conflicts are there in register
6115*3d8817e4Smiod    usage and in writes to states and queues?
6116*3d8817e4Smiod 
6117*3d8817e4Smiod    This function does two things:
6118*3d8817e4Smiod    1. Reports an error when a vinsn contains illegal combinations
6119*3d8817e4Smiod       of writes to registers states or queues.
6120*3d8817e4Smiod    2. Marks individual tinsns as not relaxable if the combination
6121*3d8817e4Smiod       contains antidependencies.
6122*3d8817e4Smiod 
6123*3d8817e4Smiod    Job 2 handles things like swap semantics in instructions that need
6124*3d8817e4Smiod    to be relaxed.  For example,
6125*3d8817e4Smiod 
6126*3d8817e4Smiod 	addi a0, a1, 100000
6127*3d8817e4Smiod 
6128*3d8817e4Smiod    normally would be relaxed to
6129*3d8817e4Smiod 
6130*3d8817e4Smiod 	l32r a0, some_label
6131*3d8817e4Smiod 	add a0, a1, a0
6132*3d8817e4Smiod 
6133*3d8817e4Smiod    _but_, if the above instruction is bundled with an a0 reader, e.g.,
6134*3d8817e4Smiod 
6135*3d8817e4Smiod 	{ addi a0, a1, 10000 ; add a2, a0, a4 ; }
6136*3d8817e4Smiod 
6137*3d8817e4Smiod    then we can't relax it into
6138*3d8817e4Smiod 
6139*3d8817e4Smiod 	l32r a0, some_label
6140*3d8817e4Smiod 	{ add a0, a1, a0 ; add a2, a0, a4 ; }
6141*3d8817e4Smiod 
6142*3d8817e4Smiod    because the value of a0 is trashed before the second add can read it.  */
6143*3d8817e4Smiod 
6144*3d8817e4Smiod static char check_t1_t2_reads_and_writes (TInsn *, TInsn *);
6145*3d8817e4Smiod 
6146*3d8817e4Smiod static bfd_boolean
find_vinsn_conflicts(vliw_insn * vinsn)6147*3d8817e4Smiod find_vinsn_conflicts (vliw_insn *vinsn)
6148*3d8817e4Smiod {
6149*3d8817e4Smiod   int i, j;
6150*3d8817e4Smiod   int branches = 0;
6151*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
6152*3d8817e4Smiod 
6153*3d8817e4Smiod   assert (!past_xtensa_end);
6154*3d8817e4Smiod 
6155*3d8817e4Smiod   for (i = 0 ; i < vinsn->num_slots; i++)
6156*3d8817e4Smiod     {
6157*3d8817e4Smiod       TInsn *op1 = &vinsn->slots[i];
6158*3d8817e4Smiod       if (op1->is_specific_opcode)
6159*3d8817e4Smiod 	op1->keep_wide = TRUE;
6160*3d8817e4Smiod       else
6161*3d8817e4Smiod 	op1->keep_wide = FALSE;
6162*3d8817e4Smiod     }
6163*3d8817e4Smiod 
6164*3d8817e4Smiod   for (i = 0 ; i < vinsn->num_slots; i++)
6165*3d8817e4Smiod     {
6166*3d8817e4Smiod       TInsn *op1 = &vinsn->slots[i];
6167*3d8817e4Smiod 
6168*3d8817e4Smiod       if (xtensa_opcode_is_branch (isa, op1->opcode) == 1)
6169*3d8817e4Smiod 	branches++;
6170*3d8817e4Smiod 
6171*3d8817e4Smiod       for (j = 0; j < vinsn->num_slots; j++)
6172*3d8817e4Smiod 	{
6173*3d8817e4Smiod 	  if (i != j)
6174*3d8817e4Smiod 	    {
6175*3d8817e4Smiod 	      TInsn *op2 = &vinsn->slots[j];
6176*3d8817e4Smiod 	      char conflict_type = check_t1_t2_reads_and_writes (op1, op2);
6177*3d8817e4Smiod 	      switch (conflict_type)
6178*3d8817e4Smiod 		{
6179*3d8817e4Smiod 		case 'c':
6180*3d8817e4Smiod 		  as_bad (_("opcodes '%s' (slot %d) and '%s' (slot %d) write the same register"),
6181*3d8817e4Smiod 			  xtensa_opcode_name (isa, op1->opcode), i,
6182*3d8817e4Smiod 			  xtensa_opcode_name (isa, op2->opcode), j);
6183*3d8817e4Smiod 		  return TRUE;
6184*3d8817e4Smiod 		case 'd':
6185*3d8817e4Smiod 		  as_bad (_("opcodes '%s' (slot %d) and '%s' (slot %d) write the same state"),
6186*3d8817e4Smiod 			  xtensa_opcode_name (isa, op1->opcode), i,
6187*3d8817e4Smiod 			  xtensa_opcode_name (isa, op2->opcode), j);
6188*3d8817e4Smiod 		  return TRUE;
6189*3d8817e4Smiod 		case 'e':
6190*3d8817e4Smiod 		  as_bad (_("opcodes '%s' (slot %d) and '%s' (slot %d) write the same port"),
6191*3d8817e4Smiod 			  xtensa_opcode_name (isa, op1->opcode), i,
6192*3d8817e4Smiod 			  xtensa_opcode_name (isa, op2->opcode), j);
6193*3d8817e4Smiod 		  return TRUE;
6194*3d8817e4Smiod 		case 'f':
6195*3d8817e4Smiod 		  as_bad (_("opcodes '%s' (slot %d) and '%s' (slot %d) both have volatile port accesses"),
6196*3d8817e4Smiod 			  xtensa_opcode_name (isa, op1->opcode), i,
6197*3d8817e4Smiod 			  xtensa_opcode_name (isa, op2->opcode), j);
6198*3d8817e4Smiod 		  return TRUE;
6199*3d8817e4Smiod 		default:
6200*3d8817e4Smiod 		  /* Everything is OK.  */
6201*3d8817e4Smiod 		  break;
6202*3d8817e4Smiod 		}
6203*3d8817e4Smiod 	      op2->is_specific_opcode = (op2->is_specific_opcode
6204*3d8817e4Smiod 					 || conflict_type == 'a');
6205*3d8817e4Smiod 	    }
6206*3d8817e4Smiod 	}
6207*3d8817e4Smiod     }
6208*3d8817e4Smiod 
6209*3d8817e4Smiod   if (branches > 1)
6210*3d8817e4Smiod     {
6211*3d8817e4Smiod       as_bad (_("multiple branches or jumps in the same bundle"));
6212*3d8817e4Smiod       return TRUE;
6213*3d8817e4Smiod     }
6214*3d8817e4Smiod 
6215*3d8817e4Smiod   return FALSE;
6216*3d8817e4Smiod }
6217*3d8817e4Smiod 
6218*3d8817e4Smiod 
6219*3d8817e4Smiod /* Check how the state used by t1 and t2 relate.
6220*3d8817e4Smiod    Cases found are:
6221*3d8817e4Smiod 
6222*3d8817e4Smiod    case A: t1 reads a register t2 writes (an antidependency within a bundle)
6223*3d8817e4Smiod    case B: no relationship between what is read and written (both could
6224*3d8817e4Smiod            read the same reg though)
6225*3d8817e4Smiod    case C: t1 writes a register t2 writes (a register conflict within a
6226*3d8817e4Smiod            bundle)
6227*3d8817e4Smiod    case D: t1 writes a state that t2 also writes
6228*3d8817e4Smiod    case E: t1 writes a tie queue that t2 also writes
6229*3d8817e4Smiod    case F: two volatile queue accesses
6230*3d8817e4Smiod */
6231*3d8817e4Smiod 
6232*3d8817e4Smiod static char
check_t1_t2_reads_and_writes(TInsn * t1,TInsn * t2)6233*3d8817e4Smiod check_t1_t2_reads_and_writes (TInsn *t1, TInsn *t2)
6234*3d8817e4Smiod {
6235*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
6236*3d8817e4Smiod   xtensa_regfile t1_regfile, t2_regfile;
6237*3d8817e4Smiod   int t1_reg, t2_reg;
6238*3d8817e4Smiod   int t1_base_reg, t1_last_reg;
6239*3d8817e4Smiod   int t2_base_reg, t2_last_reg;
6240*3d8817e4Smiod   char t1_inout, t2_inout;
6241*3d8817e4Smiod   int i, j;
6242*3d8817e4Smiod   char conflict = 'b';
6243*3d8817e4Smiod   int t1_states;
6244*3d8817e4Smiod   int t2_states;
6245*3d8817e4Smiod   int t1_interfaces;
6246*3d8817e4Smiod   int t2_interfaces;
6247*3d8817e4Smiod   bfd_boolean t1_volatile = FALSE;
6248*3d8817e4Smiod   bfd_boolean t2_volatile = FALSE;
6249*3d8817e4Smiod 
6250*3d8817e4Smiod   /* Check registers.  */
6251*3d8817e4Smiod   for (j = 0; j < t2->ntok; j++)
6252*3d8817e4Smiod     {
6253*3d8817e4Smiod       if (xtensa_operand_is_register (isa, t2->opcode, j) != 1)
6254*3d8817e4Smiod 	continue;
6255*3d8817e4Smiod 
6256*3d8817e4Smiod       t2_regfile = xtensa_operand_regfile (isa, t2->opcode, j);
6257*3d8817e4Smiod       t2_base_reg = t2->tok[j].X_add_number;
6258*3d8817e4Smiod       t2_last_reg = t2_base_reg + xtensa_operand_num_regs (isa, t2->opcode, j);
6259*3d8817e4Smiod 
6260*3d8817e4Smiod       for (i = 0; i < t1->ntok; i++)
6261*3d8817e4Smiod 	{
6262*3d8817e4Smiod 	  if (xtensa_operand_is_register (isa, t1->opcode, i) != 1)
6263*3d8817e4Smiod 	    continue;
6264*3d8817e4Smiod 
6265*3d8817e4Smiod 	  t1_regfile = xtensa_operand_regfile (isa, t1->opcode, i);
6266*3d8817e4Smiod 
6267*3d8817e4Smiod 	  if (t1_regfile != t2_regfile)
6268*3d8817e4Smiod 	    continue;
6269*3d8817e4Smiod 
6270*3d8817e4Smiod 	  t1_inout = xtensa_operand_inout (isa, t1->opcode, i);
6271*3d8817e4Smiod 	  t2_inout = xtensa_operand_inout (isa, t2->opcode, j);
6272*3d8817e4Smiod 
6273*3d8817e4Smiod 	  if (xtensa_operand_is_known_reg (isa, t1->opcode, i) == 0
6274*3d8817e4Smiod 	      || xtensa_operand_is_known_reg (isa, t2->opcode, j) == 0)
6275*3d8817e4Smiod 	    {
6276*3d8817e4Smiod 	      if (t1_inout == 'm' || t1_inout == 'o'
6277*3d8817e4Smiod 		  || t2_inout == 'm' || t2_inout == 'o')
6278*3d8817e4Smiod 		{
6279*3d8817e4Smiod 		  conflict = 'a';
6280*3d8817e4Smiod 		  continue;
6281*3d8817e4Smiod 		}
6282*3d8817e4Smiod 	    }
6283*3d8817e4Smiod 
6284*3d8817e4Smiod 	  t1_base_reg = t1->tok[i].X_add_number;
6285*3d8817e4Smiod 	  t1_last_reg = (t1_base_reg
6286*3d8817e4Smiod 			 + xtensa_operand_num_regs (isa, t1->opcode, i));
6287*3d8817e4Smiod 
6288*3d8817e4Smiod 	  for (t1_reg = t1_base_reg; t1_reg < t1_last_reg; t1_reg++)
6289*3d8817e4Smiod 	    {
6290*3d8817e4Smiod 	      for (t2_reg = t2_base_reg; t2_reg < t2_last_reg; t2_reg++)
6291*3d8817e4Smiod 		{
6292*3d8817e4Smiod 		  if (t1_reg != t2_reg)
6293*3d8817e4Smiod 		    continue;
6294*3d8817e4Smiod 
6295*3d8817e4Smiod 		  if (t2_inout == 'i' && (t1_inout == 'm' || t1_inout == 'o'))
6296*3d8817e4Smiod 		    {
6297*3d8817e4Smiod 		      conflict = 'a';
6298*3d8817e4Smiod 		      continue;
6299*3d8817e4Smiod 		    }
6300*3d8817e4Smiod 
6301*3d8817e4Smiod 		  if (t1_inout == 'i' && (t2_inout == 'm' || t2_inout == 'o'))
6302*3d8817e4Smiod 		    {
6303*3d8817e4Smiod 		      conflict = 'a';
6304*3d8817e4Smiod 		      continue;
6305*3d8817e4Smiod 		    }
6306*3d8817e4Smiod 
6307*3d8817e4Smiod 		  if (t1_inout != 'i' && t2_inout != 'i')
6308*3d8817e4Smiod 		    return 'c';
6309*3d8817e4Smiod 		}
6310*3d8817e4Smiod 	    }
6311*3d8817e4Smiod 	}
6312*3d8817e4Smiod     }
6313*3d8817e4Smiod 
6314*3d8817e4Smiod   /* Check states.  */
6315*3d8817e4Smiod   t1_states = xtensa_opcode_num_stateOperands (isa, t1->opcode);
6316*3d8817e4Smiod   t2_states = xtensa_opcode_num_stateOperands (isa, t2->opcode);
6317*3d8817e4Smiod   for (j = 0; j < t2_states; j++)
6318*3d8817e4Smiod     {
6319*3d8817e4Smiod       xtensa_state t2_so = xtensa_stateOperand_state (isa, t2->opcode, j);
6320*3d8817e4Smiod       t2_inout = xtensa_stateOperand_inout (isa, t2->opcode, j);
6321*3d8817e4Smiod       for (i = 0; i < t1_states; i++)
6322*3d8817e4Smiod 	{
6323*3d8817e4Smiod 	  xtensa_state t1_so = xtensa_stateOperand_state (isa, t1->opcode, i);
6324*3d8817e4Smiod 	  t1_inout = xtensa_stateOperand_inout (isa, t1->opcode, i);
6325*3d8817e4Smiod 	  if (t1_so != t2_so)
6326*3d8817e4Smiod 	    continue;
6327*3d8817e4Smiod 
6328*3d8817e4Smiod 	  if (t2_inout == 'i' && (t1_inout == 'm' || t1_inout == 'o'))
6329*3d8817e4Smiod 	    {
6330*3d8817e4Smiod 	      conflict = 'a';
6331*3d8817e4Smiod 	      continue;
6332*3d8817e4Smiod 	    }
6333*3d8817e4Smiod 
6334*3d8817e4Smiod 	  if (t1_inout == 'i' && (t2_inout == 'm' || t2_inout == 'o'))
6335*3d8817e4Smiod 	    {
6336*3d8817e4Smiod 	      conflict = 'a';
6337*3d8817e4Smiod 	      continue;
6338*3d8817e4Smiod 	    }
6339*3d8817e4Smiod 
6340*3d8817e4Smiod 	  if (t1_inout != 'i' && t2_inout != 'i')
6341*3d8817e4Smiod 	    return 'd';
6342*3d8817e4Smiod 	}
6343*3d8817e4Smiod     }
6344*3d8817e4Smiod 
6345*3d8817e4Smiod   /* Check tieports.  */
6346*3d8817e4Smiod   t1_interfaces = xtensa_opcode_num_interfaceOperands (isa, t1->opcode);
6347*3d8817e4Smiod   t2_interfaces = xtensa_opcode_num_interfaceOperands (isa, t2->opcode);
6348*3d8817e4Smiod   for (j = 0; j < t2_interfaces; j++)
6349*3d8817e4Smiod     {
6350*3d8817e4Smiod       xtensa_interface t2_int
6351*3d8817e4Smiod 	= xtensa_interfaceOperand_interface (isa, t2->opcode, j);
6352*3d8817e4Smiod       int t2_class = xtensa_interface_class_id (isa, t2_int);
6353*3d8817e4Smiod 
6354*3d8817e4Smiod       t2_inout = xtensa_interface_inout (isa, t2_int);
6355*3d8817e4Smiod       if (xtensa_interface_has_side_effect (isa, t2_int) == 1)
6356*3d8817e4Smiod 	t2_volatile = TRUE;
6357*3d8817e4Smiod 
6358*3d8817e4Smiod       for (i = 0; i < t1_interfaces; i++)
6359*3d8817e4Smiod 	{
6360*3d8817e4Smiod 	  xtensa_interface t1_int
6361*3d8817e4Smiod 	    = xtensa_interfaceOperand_interface (isa, t1->opcode, j);
6362*3d8817e4Smiod 	  int t1_class = xtensa_interface_class_id (isa, t1_int);
6363*3d8817e4Smiod 
6364*3d8817e4Smiod 	  t1_inout = xtensa_interface_inout (isa, t1_int);
6365*3d8817e4Smiod 	  if (xtensa_interface_has_side_effect (isa, t1_int) == 1)
6366*3d8817e4Smiod 	    t1_volatile = TRUE;
6367*3d8817e4Smiod 
6368*3d8817e4Smiod 	  if (t1_volatile && t2_volatile && (t1_class == t2_class))
6369*3d8817e4Smiod 	    return 'f';
6370*3d8817e4Smiod 
6371*3d8817e4Smiod 	  if (t1_int != t2_int)
6372*3d8817e4Smiod 	    continue;
6373*3d8817e4Smiod 
6374*3d8817e4Smiod 	  if (t2_inout == 'i' && t1_inout == 'o')
6375*3d8817e4Smiod 	    {
6376*3d8817e4Smiod 	      conflict = 'a';
6377*3d8817e4Smiod 	      continue;
6378*3d8817e4Smiod 	    }
6379*3d8817e4Smiod 
6380*3d8817e4Smiod 	  if (t1_inout == 'i' && t2_inout == 'o')
6381*3d8817e4Smiod 	    {
6382*3d8817e4Smiod 	      conflict = 'a';
6383*3d8817e4Smiod 	      continue;
6384*3d8817e4Smiod 	    }
6385*3d8817e4Smiod 
6386*3d8817e4Smiod 	  if (t1_inout != 'i' && t2_inout != 'i')
6387*3d8817e4Smiod 	    return 'e';
6388*3d8817e4Smiod 	}
6389*3d8817e4Smiod     }
6390*3d8817e4Smiod 
6391*3d8817e4Smiod   return conflict;
6392*3d8817e4Smiod }
6393*3d8817e4Smiod 
6394*3d8817e4Smiod 
6395*3d8817e4Smiod static xtensa_format
xg_find_narrowest_format(vliw_insn * vinsn)6396*3d8817e4Smiod xg_find_narrowest_format (vliw_insn *vinsn)
6397*3d8817e4Smiod {
6398*3d8817e4Smiod   /* Right now we assume that the ops within the vinsn are properly
6399*3d8817e4Smiod      ordered for the slots that the programmer wanted them in.  In
6400*3d8817e4Smiod      other words, we don't rearrange the ops in hopes of finding a
6401*3d8817e4Smiod      better format.  The scheduler handles that.  */
6402*3d8817e4Smiod 
6403*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
6404*3d8817e4Smiod   xtensa_format format;
6405*3d8817e4Smiod   vliw_insn v_copy = *vinsn;
6406*3d8817e4Smiod   xtensa_opcode nop_opcode = xtensa_nop_opcode;
6407*3d8817e4Smiod 
6408*3d8817e4Smiod   if (vinsn->num_slots == 1)
6409*3d8817e4Smiod     return xg_get_single_format (vinsn->slots[0].opcode);
6410*3d8817e4Smiod 
6411*3d8817e4Smiod   for (format = 0; format < xtensa_isa_num_formats (isa); format++)
6412*3d8817e4Smiod     {
6413*3d8817e4Smiod       v_copy = *vinsn;
6414*3d8817e4Smiod       if (xtensa_format_num_slots (isa, format) == v_copy.num_slots)
6415*3d8817e4Smiod 	{
6416*3d8817e4Smiod 	  int slot;
6417*3d8817e4Smiod 	  int fit = 0;
6418*3d8817e4Smiod 	  for (slot = 0; slot < v_copy.num_slots; slot++)
6419*3d8817e4Smiod 	    {
6420*3d8817e4Smiod 	      if (v_copy.slots[slot].opcode == nop_opcode)
6421*3d8817e4Smiod 		{
6422*3d8817e4Smiod 		  v_copy.slots[slot].opcode =
6423*3d8817e4Smiod 		    xtensa_format_slot_nop_opcode (isa, format, slot);
6424*3d8817e4Smiod 		  v_copy.slots[slot].ntok = 0;
6425*3d8817e4Smiod 		}
6426*3d8817e4Smiod 
6427*3d8817e4Smiod 	      if (opcode_fits_format_slot (v_copy.slots[slot].opcode,
6428*3d8817e4Smiod 					   format, slot))
6429*3d8817e4Smiod 		fit++;
6430*3d8817e4Smiod 	      else if (v_copy.num_slots > 1)
6431*3d8817e4Smiod 		{
6432*3d8817e4Smiod 		  TInsn widened;
6433*3d8817e4Smiod 		  /* Try the widened version.  */
6434*3d8817e4Smiod 		  if (!v_copy.slots[slot].keep_wide
6435*3d8817e4Smiod 		      && !v_copy.slots[slot].is_specific_opcode
6436*3d8817e4Smiod 		      && xg_is_single_relaxable_insn (&v_copy.slots[slot],
6437*3d8817e4Smiod 						      &widened, TRUE)
6438*3d8817e4Smiod 		      && opcode_fits_format_slot (widened.opcode,
6439*3d8817e4Smiod 						  format, slot))
6440*3d8817e4Smiod 		    {
6441*3d8817e4Smiod 		      v_copy.slots[slot] = widened;
6442*3d8817e4Smiod 		      fit++;
6443*3d8817e4Smiod 		    }
6444*3d8817e4Smiod 		}
6445*3d8817e4Smiod 	    }
6446*3d8817e4Smiod 	  if (fit == v_copy.num_slots)
6447*3d8817e4Smiod 	    {
6448*3d8817e4Smiod 	      *vinsn = v_copy;
6449*3d8817e4Smiod 	      xtensa_format_encode (isa, format, vinsn->insnbuf);
6450*3d8817e4Smiod 	      vinsn->format = format;
6451*3d8817e4Smiod 	      break;
6452*3d8817e4Smiod 	    }
6453*3d8817e4Smiod 	}
6454*3d8817e4Smiod     }
6455*3d8817e4Smiod 
6456*3d8817e4Smiod   if (format == xtensa_isa_num_formats (isa))
6457*3d8817e4Smiod     return XTENSA_UNDEFINED;
6458*3d8817e4Smiod 
6459*3d8817e4Smiod   return format;
6460*3d8817e4Smiod }
6461*3d8817e4Smiod 
6462*3d8817e4Smiod 
6463*3d8817e4Smiod /* Return the additional space needed in a frag
6464*3d8817e4Smiod    for possible relaxations of any ops in a VLIW insn.
6465*3d8817e4Smiod    Also fill out the relaxations that might be required of
6466*3d8817e4Smiod    each tinsn in the vinsn.  */
6467*3d8817e4Smiod 
6468*3d8817e4Smiod static int
relaxation_requirements(vliw_insn * vinsn,bfd_boolean * pfinish_frag)6469*3d8817e4Smiod relaxation_requirements (vliw_insn *vinsn, bfd_boolean *pfinish_frag)
6470*3d8817e4Smiod {
6471*3d8817e4Smiod   bfd_boolean finish_frag = FALSE;
6472*3d8817e4Smiod   int extra_space = 0;
6473*3d8817e4Smiod   int slot;
6474*3d8817e4Smiod 
6475*3d8817e4Smiod   for (slot = 0; slot < vinsn->num_slots; slot++)
6476*3d8817e4Smiod     {
6477*3d8817e4Smiod       TInsn *tinsn = &vinsn->slots[slot];
6478*3d8817e4Smiod       if (!tinsn_has_symbolic_operands (tinsn))
6479*3d8817e4Smiod 	{
6480*3d8817e4Smiod 	  /* A narrow instruction could be widened later to help
6481*3d8817e4Smiod 	     alignment issues.  */
6482*3d8817e4Smiod 	  if (xg_is_single_relaxable_insn (tinsn, 0, TRUE)
6483*3d8817e4Smiod 	      && !tinsn->is_specific_opcode
6484*3d8817e4Smiod 	      && vinsn->num_slots == 1)
6485*3d8817e4Smiod 	    {
6486*3d8817e4Smiod 	      /* Difference in bytes between narrow and wide insns...  */
6487*3d8817e4Smiod 	      extra_space += 1;
6488*3d8817e4Smiod 	      tinsn->subtype = RELAX_NARROW;
6489*3d8817e4Smiod 	    }
6490*3d8817e4Smiod 	}
6491*3d8817e4Smiod       else
6492*3d8817e4Smiod 	{
6493*3d8817e4Smiod 	  if (workaround_b_j_loop_end
6494*3d8817e4Smiod 	      && tinsn->opcode == xtensa_jx_opcode
6495*3d8817e4Smiod 	      && use_transform ())
6496*3d8817e4Smiod 	    {
6497*3d8817e4Smiod 	      /* Add 2 of these.  */
6498*3d8817e4Smiod 	      extra_space += 3; /* for the nop size */
6499*3d8817e4Smiod 	      tinsn->subtype = RELAX_ADD_NOP_IF_PRE_LOOP_END;
6500*3d8817e4Smiod 	    }
6501*3d8817e4Smiod 
6502*3d8817e4Smiod 	  /* Need to assemble it with space for the relocation.  */
6503*3d8817e4Smiod 	  if (xg_is_relaxable_insn (tinsn, 0)
6504*3d8817e4Smiod 	      && !tinsn->is_specific_opcode)
6505*3d8817e4Smiod 	    {
6506*3d8817e4Smiod 	      int max_size = xg_get_max_insn_widen_size (tinsn->opcode);
6507*3d8817e4Smiod 	      int max_literal_size =
6508*3d8817e4Smiod 		xg_get_max_insn_widen_literal_size (tinsn->opcode);
6509*3d8817e4Smiod 
6510*3d8817e4Smiod 	      tinsn->literal_space = max_literal_size;
6511*3d8817e4Smiod 
6512*3d8817e4Smiod 	      tinsn->subtype = RELAX_IMMED;
6513*3d8817e4Smiod 	      extra_space += max_size;
6514*3d8817e4Smiod 	    }
6515*3d8817e4Smiod 	  else
6516*3d8817e4Smiod 	    {
6517*3d8817e4Smiod 	      /* A fix record will be added for this instruction prior
6518*3d8817e4Smiod 		 to relaxation, so make it end the frag.  */
6519*3d8817e4Smiod 	      finish_frag = TRUE;
6520*3d8817e4Smiod 	    }
6521*3d8817e4Smiod 	}
6522*3d8817e4Smiod     }
6523*3d8817e4Smiod   *pfinish_frag = finish_frag;
6524*3d8817e4Smiod   return extra_space;
6525*3d8817e4Smiod }
6526*3d8817e4Smiod 
6527*3d8817e4Smiod 
6528*3d8817e4Smiod static void
bundle_tinsn(TInsn * tinsn,vliw_insn * vinsn)6529*3d8817e4Smiod bundle_tinsn (TInsn *tinsn, vliw_insn *vinsn)
6530*3d8817e4Smiod {
6531*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
6532*3d8817e4Smiod   int slot, chosen_slot;
6533*3d8817e4Smiod 
6534*3d8817e4Smiod   vinsn->format = xg_get_single_format (tinsn->opcode);
6535*3d8817e4Smiod   assert (vinsn->format != XTENSA_UNDEFINED);
6536*3d8817e4Smiod   vinsn->num_slots = xtensa_format_num_slots (isa, vinsn->format);
6537*3d8817e4Smiod 
6538*3d8817e4Smiod   chosen_slot = xg_get_single_slot (tinsn->opcode);
6539*3d8817e4Smiod   for (slot = 0; slot < vinsn->num_slots; slot++)
6540*3d8817e4Smiod     {
6541*3d8817e4Smiod       if (slot == chosen_slot)
6542*3d8817e4Smiod 	vinsn->slots[slot] = *tinsn;
6543*3d8817e4Smiod       else
6544*3d8817e4Smiod 	{
6545*3d8817e4Smiod 	  vinsn->slots[slot].opcode =
6546*3d8817e4Smiod 	    xtensa_format_slot_nop_opcode (isa, vinsn->format, slot);
6547*3d8817e4Smiod 	  vinsn->slots[slot].ntok = 0;
6548*3d8817e4Smiod 	  vinsn->slots[slot].insn_type = ITYPE_INSN;
6549*3d8817e4Smiod 	}
6550*3d8817e4Smiod     }
6551*3d8817e4Smiod }
6552*3d8817e4Smiod 
6553*3d8817e4Smiod 
6554*3d8817e4Smiod static bfd_boolean
emit_single_op(TInsn * orig_insn)6555*3d8817e4Smiod emit_single_op (TInsn *orig_insn)
6556*3d8817e4Smiod {
6557*3d8817e4Smiod   int i;
6558*3d8817e4Smiod   IStack istack;		/* put instructions into here */
6559*3d8817e4Smiod   symbolS *lit_sym = NULL;
6560*3d8817e4Smiod   symbolS *label_sym = NULL;
6561*3d8817e4Smiod 
6562*3d8817e4Smiod   istack_init (&istack);
6563*3d8817e4Smiod 
6564*3d8817e4Smiod   /* Special-case for "movi aX, foo" which is guaranteed to need relaxing.
6565*3d8817e4Smiod      Because the scheduling and bundling characteristics of movi and
6566*3d8817e4Smiod      l32r or const16 are so different, we can do much better if we relax
6567*3d8817e4Smiod      it prior to scheduling and bundling, rather than after.  */
6568*3d8817e4Smiod   if ((orig_insn->opcode == xtensa_movi_opcode
6569*3d8817e4Smiod        || orig_insn->opcode == xtensa_movi_n_opcode)
6570*3d8817e4Smiod       && !cur_vinsn.inside_bundle
6571*3d8817e4Smiod       && (orig_insn->tok[1].X_op == O_symbol
6572*3d8817e4Smiod 	  || orig_insn->tok[1].X_op == O_pltrel)
6573*3d8817e4Smiod       && !orig_insn->is_specific_opcode && use_transform ())
6574*3d8817e4Smiod     xg_assembly_relax (&istack, orig_insn, now_seg, frag_now, 0, 1, 0);
6575*3d8817e4Smiod   else
6576*3d8817e4Smiod     if (xg_expand_assembly_insn (&istack, orig_insn))
6577*3d8817e4Smiod       return TRUE;
6578*3d8817e4Smiod 
6579*3d8817e4Smiod   for (i = 0; i < istack.ninsn; i++)
6580*3d8817e4Smiod     {
6581*3d8817e4Smiod       TInsn *insn = &istack.insn[i];
6582*3d8817e4Smiod       switch (insn->insn_type)
6583*3d8817e4Smiod 	{
6584*3d8817e4Smiod 	case ITYPE_LITERAL:
6585*3d8817e4Smiod 	  assert (lit_sym == NULL);
6586*3d8817e4Smiod 	  lit_sym = xg_assemble_literal (insn);
6587*3d8817e4Smiod 	  break;
6588*3d8817e4Smiod 	case ITYPE_LABEL:
6589*3d8817e4Smiod 	  {
6590*3d8817e4Smiod 	    static int relaxed_sym_idx = 0;
6591*3d8817e4Smiod 	    char *label = xmalloc (strlen (FAKE_LABEL_NAME) + 12);
6592*3d8817e4Smiod 	    sprintf (label, "%s_rl_%x", FAKE_LABEL_NAME, relaxed_sym_idx++);
6593*3d8817e4Smiod 	    colon (label);
6594*3d8817e4Smiod 	    assert (label_sym == NULL);
6595*3d8817e4Smiod 	    label_sym = symbol_find_or_make (label);
6596*3d8817e4Smiod 	    assert (label_sym);
6597*3d8817e4Smiod 	    free (label);
6598*3d8817e4Smiod 	  }
6599*3d8817e4Smiod 	  break;
6600*3d8817e4Smiod 	case ITYPE_INSN:
6601*3d8817e4Smiod 	  {
6602*3d8817e4Smiod 	    vliw_insn v;
6603*3d8817e4Smiod 	    if (lit_sym)
6604*3d8817e4Smiod 	      xg_resolve_literals (insn, lit_sym);
6605*3d8817e4Smiod 	    if (label_sym)
6606*3d8817e4Smiod 	      xg_resolve_labels (insn, label_sym);
6607*3d8817e4Smiod 	    xg_init_vinsn (&v);
6608*3d8817e4Smiod 	    bundle_tinsn (insn, &v);
6609*3d8817e4Smiod 	    finish_vinsn (&v);
6610*3d8817e4Smiod 	    xg_free_vinsn (&v);
6611*3d8817e4Smiod 	  }
6612*3d8817e4Smiod 	  break;
6613*3d8817e4Smiod 	default:
6614*3d8817e4Smiod 	  assert (0);
6615*3d8817e4Smiod 	  break;
6616*3d8817e4Smiod 	}
6617*3d8817e4Smiod     }
6618*3d8817e4Smiod   return FALSE;
6619*3d8817e4Smiod }
6620*3d8817e4Smiod 
6621*3d8817e4Smiod 
6622*3d8817e4Smiod static int
total_frag_text_expansion(fragS * fragP)6623*3d8817e4Smiod total_frag_text_expansion (fragS *fragP)
6624*3d8817e4Smiod {
6625*3d8817e4Smiod   int slot;
6626*3d8817e4Smiod   int total_expansion = 0;
6627*3d8817e4Smiod 
6628*3d8817e4Smiod   for (slot = 0; slot < MAX_SLOTS; slot++)
6629*3d8817e4Smiod     total_expansion += fragP->tc_frag_data.text_expansion[slot];
6630*3d8817e4Smiod 
6631*3d8817e4Smiod   return total_expansion;
6632*3d8817e4Smiod }
6633*3d8817e4Smiod 
6634*3d8817e4Smiod 
6635*3d8817e4Smiod /* Emit a vliw instruction to the current fragment.  */
6636*3d8817e4Smiod 
6637*3d8817e4Smiod static void
xg_assemble_vliw_tokens(vliw_insn * vinsn)6638*3d8817e4Smiod xg_assemble_vliw_tokens (vliw_insn *vinsn)
6639*3d8817e4Smiod {
6640*3d8817e4Smiod   bfd_boolean finish_frag;
6641*3d8817e4Smiod   bfd_boolean is_jump = FALSE;
6642*3d8817e4Smiod   bfd_boolean is_branch = FALSE;
6643*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
6644*3d8817e4Smiod   int i;
6645*3d8817e4Smiod   int insn_size;
6646*3d8817e4Smiod   int extra_space;
6647*3d8817e4Smiod   char *f = NULL;
6648*3d8817e4Smiod   int slot;
6649*3d8817e4Smiod   unsigned current_line, best_linenum;
6650*3d8817e4Smiod   char *current_file;
6651*3d8817e4Smiod 
6652*3d8817e4Smiod   best_linenum = UINT_MAX;
6653*3d8817e4Smiod 
6654*3d8817e4Smiod   if (generating_literals)
6655*3d8817e4Smiod     {
6656*3d8817e4Smiod       static int reported = 0;
6657*3d8817e4Smiod       if (reported < 4)
6658*3d8817e4Smiod 	as_bad_where (frag_now->fr_file, frag_now->fr_line,
6659*3d8817e4Smiod 		      _("cannot assemble into a literal fragment"));
6660*3d8817e4Smiod       if (reported == 3)
6661*3d8817e4Smiod 	as_bad (_("..."));
6662*3d8817e4Smiod       reported++;
6663*3d8817e4Smiod       return;
6664*3d8817e4Smiod     }
6665*3d8817e4Smiod 
6666*3d8817e4Smiod   if (frag_now_fix () != 0
6667*3d8817e4Smiod       && (! frag_now->tc_frag_data.is_insn
6668*3d8817e4Smiod  	  || (vinsn_has_specific_opcodes (vinsn) && use_transform ())
6669*3d8817e4Smiod  	  || !use_transform () != frag_now->tc_frag_data.is_no_transform
6670*3d8817e4Smiod  	  || (directive_state[directive_longcalls]
6671*3d8817e4Smiod 	      != frag_now->tc_frag_data.use_longcalls)
6672*3d8817e4Smiod  	  || (directive_state[directive_absolute_literals]
6673*3d8817e4Smiod 	      != frag_now->tc_frag_data.use_absolute_literals)))
6674*3d8817e4Smiod     {
6675*3d8817e4Smiod       frag_wane (frag_now);
6676*3d8817e4Smiod       frag_new (0);
6677*3d8817e4Smiod       xtensa_set_frag_assembly_state (frag_now);
6678*3d8817e4Smiod     }
6679*3d8817e4Smiod 
6680*3d8817e4Smiod   if (workaround_a0_b_retw
6681*3d8817e4Smiod       && vinsn->num_slots == 1
6682*3d8817e4Smiod       && (get_last_insn_flags (now_seg, now_subseg) & FLAG_IS_A0_WRITER) != 0
6683*3d8817e4Smiod       && xtensa_opcode_is_branch (isa, vinsn->slots[0].opcode) == 1
6684*3d8817e4Smiod       && use_transform ())
6685*3d8817e4Smiod     {
6686*3d8817e4Smiod       has_a0_b_retw = TRUE;
6687*3d8817e4Smiod 
6688*3d8817e4Smiod       /* Mark this fragment with the special RELAX_ADD_NOP_IF_A0_B_RETW.
6689*3d8817e4Smiod 	 After the first assembly pass we will check all of them and
6690*3d8817e4Smiod 	 add a nop if needed.  */
6691*3d8817e4Smiod       frag_now->tc_frag_data.is_insn = TRUE;
6692*3d8817e4Smiod       frag_var (rs_machine_dependent, 4, 4,
6693*3d8817e4Smiod 		RELAX_ADD_NOP_IF_A0_B_RETW,
6694*3d8817e4Smiod 		frag_now->fr_symbol,
6695*3d8817e4Smiod 		frag_now->fr_offset,
6696*3d8817e4Smiod 		NULL);
6697*3d8817e4Smiod       xtensa_set_frag_assembly_state (frag_now);
6698*3d8817e4Smiod       frag_now->tc_frag_data.is_insn = TRUE;
6699*3d8817e4Smiod       frag_var (rs_machine_dependent, 4, 4,
6700*3d8817e4Smiod 		RELAX_ADD_NOP_IF_A0_B_RETW,
6701*3d8817e4Smiod 		frag_now->fr_symbol,
6702*3d8817e4Smiod 		frag_now->fr_offset,
6703*3d8817e4Smiod 		NULL);
6704*3d8817e4Smiod       xtensa_set_frag_assembly_state (frag_now);
6705*3d8817e4Smiod     }
6706*3d8817e4Smiod 
6707*3d8817e4Smiod   for (i = 0; i < vinsn->num_slots; i++)
6708*3d8817e4Smiod     {
6709*3d8817e4Smiod       /* See if the instruction implies an aligned section.  */
6710*3d8817e4Smiod       if (xtensa_opcode_is_loop (isa, vinsn->slots[i].opcode) == 1)
6711*3d8817e4Smiod 	record_alignment (now_seg, 2);
6712*3d8817e4Smiod 
6713*3d8817e4Smiod       /* Also determine the best line number for debug info.  */
6714*3d8817e4Smiod       best_linenum = vinsn->slots[i].linenum < best_linenum
6715*3d8817e4Smiod 	? vinsn->slots[i].linenum : best_linenum;
6716*3d8817e4Smiod     }
6717*3d8817e4Smiod 
6718*3d8817e4Smiod   /* Special cases for instructions that force an alignment... */
6719*3d8817e4Smiod   /* None of these opcodes are bundle-able.  */
6720*3d8817e4Smiod   if (xtensa_opcode_is_loop (isa, vinsn->slots[0].opcode) == 1)
6721*3d8817e4Smiod     {
6722*3d8817e4Smiod       int max_fill;
6723*3d8817e4Smiod 
6724*3d8817e4Smiod       /* Remember the symbol that marks the end of the loop in the frag
6725*3d8817e4Smiod 	 that marks the start of the loop.  This way we can easily find
6726*3d8817e4Smiod 	 the end of the loop at the beginning, without adding special code
6727*3d8817e4Smiod 	 to mark the loop instructions themselves.  */
6728*3d8817e4Smiod       symbolS *target_sym = NULL;
6729*3d8817e4Smiod       if (vinsn->slots[0].tok[1].X_op == O_symbol)
6730*3d8817e4Smiod 	target_sym = vinsn->slots[0].tok[1].X_add_symbol;
6731*3d8817e4Smiod 
6732*3d8817e4Smiod       xtensa_set_frag_assembly_state (frag_now);
6733*3d8817e4Smiod       frag_now->tc_frag_data.is_insn = TRUE;
6734*3d8817e4Smiod 
6735*3d8817e4Smiod       max_fill = get_text_align_max_fill_size
6736*3d8817e4Smiod 	(get_text_align_power (xtensa_fetch_width),
6737*3d8817e4Smiod 	 TRUE, frag_now->tc_frag_data.is_no_density);
6738*3d8817e4Smiod 
6739*3d8817e4Smiod       if (use_transform ())
6740*3d8817e4Smiod 	frag_var (rs_machine_dependent, max_fill, max_fill,
6741*3d8817e4Smiod 		  RELAX_ALIGN_NEXT_OPCODE, target_sym, 0, NULL);
6742*3d8817e4Smiod       else
6743*3d8817e4Smiod 	frag_var (rs_machine_dependent, 0, 0,
6744*3d8817e4Smiod 		  RELAX_CHECK_ALIGN_NEXT_OPCODE, target_sym, 0, NULL);
6745*3d8817e4Smiod       xtensa_set_frag_assembly_state (frag_now);
6746*3d8817e4Smiod 
6747*3d8817e4Smiod       xtensa_move_labels (frag_now, 0, FALSE);
6748*3d8817e4Smiod     }
6749*3d8817e4Smiod 
6750*3d8817e4Smiod   if (vinsn->slots[0].opcode == xtensa_entry_opcode
6751*3d8817e4Smiod       && !vinsn->slots[0].is_specific_opcode)
6752*3d8817e4Smiod     {
6753*3d8817e4Smiod       xtensa_mark_literal_pool_location ();
6754*3d8817e4Smiod       xtensa_move_labels (frag_now, 0, TRUE);
6755*3d8817e4Smiod       frag_var (rs_align_test, 1, 1, 0, NULL, 2, NULL);
6756*3d8817e4Smiod     }
6757*3d8817e4Smiod 
6758*3d8817e4Smiod   if (vinsn->num_slots == 1)
6759*3d8817e4Smiod     {
6760*3d8817e4Smiod       if (workaround_a0_b_retw && use_transform ())
6761*3d8817e4Smiod 	set_last_insn_flags (now_seg, now_subseg, FLAG_IS_A0_WRITER,
6762*3d8817e4Smiod 			     is_register_writer (&vinsn->slots[0], "a", 0));
6763*3d8817e4Smiod 
6764*3d8817e4Smiod       set_last_insn_flags (now_seg, now_subseg, FLAG_IS_BAD_LOOPEND,
6765*3d8817e4Smiod 			   is_bad_loopend_opcode (&vinsn->slots[0]));
6766*3d8817e4Smiod     }
6767*3d8817e4Smiod   else
6768*3d8817e4Smiod     set_last_insn_flags (now_seg, now_subseg, FLAG_IS_BAD_LOOPEND, FALSE);
6769*3d8817e4Smiod 
6770*3d8817e4Smiod   insn_size = xtensa_format_length (isa, vinsn->format);
6771*3d8817e4Smiod 
6772*3d8817e4Smiod   extra_space = relaxation_requirements (vinsn, &finish_frag);
6773*3d8817e4Smiod 
6774*3d8817e4Smiod   /* vinsn_to_insnbuf will produce the error.  */
6775*3d8817e4Smiod   if (vinsn->format != XTENSA_UNDEFINED)
6776*3d8817e4Smiod     {
6777*3d8817e4Smiod       f = frag_more (insn_size + extra_space);
6778*3d8817e4Smiod       xtensa_set_frag_assembly_state (frag_now);
6779*3d8817e4Smiod       frag_now->tc_frag_data.is_insn = TRUE;
6780*3d8817e4Smiod     }
6781*3d8817e4Smiod 
6782*3d8817e4Smiod   vinsn_to_insnbuf (vinsn, f, frag_now, FALSE);
6783*3d8817e4Smiod   if (vinsn->format == XTENSA_UNDEFINED)
6784*3d8817e4Smiod     return;
6785*3d8817e4Smiod 
6786*3d8817e4Smiod   xtensa_insnbuf_to_chars (isa, vinsn->insnbuf, (unsigned char *) f, 0);
6787*3d8817e4Smiod 
6788*3d8817e4Smiod   /* Temporarily set the logical line number to the one we want to appear
6789*3d8817e4Smiod      in the debug information.  */
6790*3d8817e4Smiod   as_where (&current_file, &current_line);
6791*3d8817e4Smiod   new_logical_line (current_file, best_linenum);
6792*3d8817e4Smiod   dwarf2_emit_insn (insn_size + extra_space);
6793*3d8817e4Smiod   new_logical_line (current_file, current_line);
6794*3d8817e4Smiod 
6795*3d8817e4Smiod   for (slot = 0; slot < vinsn->num_slots; slot++)
6796*3d8817e4Smiod     {
6797*3d8817e4Smiod       TInsn *tinsn = &vinsn->slots[slot];
6798*3d8817e4Smiod       frag_now->tc_frag_data.slot_subtypes[slot] = tinsn->subtype;
6799*3d8817e4Smiod       frag_now->tc_frag_data.slot_symbols[slot] = tinsn->symbol;
6800*3d8817e4Smiod       frag_now->tc_frag_data.slot_offsets[slot] = tinsn->offset;
6801*3d8817e4Smiod       frag_now->tc_frag_data.literal_frags[slot] = tinsn->literal_frag;
6802*3d8817e4Smiod       if (tinsn->literal_space != 0)
6803*3d8817e4Smiod 	xg_assemble_literal_space (tinsn->literal_space, slot);
6804*3d8817e4Smiod 
6805*3d8817e4Smiod       if (tinsn->subtype == RELAX_NARROW)
6806*3d8817e4Smiod 	assert (vinsn->num_slots == 1);
6807*3d8817e4Smiod       if (xtensa_opcode_is_jump (isa, tinsn->opcode) == 1)
6808*3d8817e4Smiod 	is_jump = TRUE;
6809*3d8817e4Smiod       if (xtensa_opcode_is_branch (isa, tinsn->opcode) == 1)
6810*3d8817e4Smiod 	is_branch = TRUE;
6811*3d8817e4Smiod 
6812*3d8817e4Smiod       if (tinsn->subtype || tinsn->symbol || tinsn->offset
6813*3d8817e4Smiod 	  || tinsn->literal_frag || is_jump || is_branch)
6814*3d8817e4Smiod 	finish_frag = TRUE;
6815*3d8817e4Smiod     }
6816*3d8817e4Smiod 
6817*3d8817e4Smiod   if (vinsn_has_specific_opcodes (vinsn) && use_transform ())
6818*3d8817e4Smiod     frag_now->tc_frag_data.is_specific_opcode = TRUE;
6819*3d8817e4Smiod 
6820*3d8817e4Smiod   if (finish_frag)
6821*3d8817e4Smiod     {
6822*3d8817e4Smiod       frag_variant (rs_machine_dependent,
6823*3d8817e4Smiod 		    extra_space, extra_space, RELAX_SLOTS,
6824*3d8817e4Smiod 		    frag_now->fr_symbol, frag_now->fr_offset, f);
6825*3d8817e4Smiod       xtensa_set_frag_assembly_state (frag_now);
6826*3d8817e4Smiod     }
6827*3d8817e4Smiod 
6828*3d8817e4Smiod   /* Special cases for loops:
6829*3d8817e4Smiod      close_loop_end should be inserted AFTER short_loop.
6830*3d8817e4Smiod      Make sure that CLOSE loops are processed BEFORE short_loops
6831*3d8817e4Smiod      when converting them.  */
6832*3d8817e4Smiod 
6833*3d8817e4Smiod   /* "short_loop": Add a NOP if the loop is < 4 bytes.  */
6834*3d8817e4Smiod   if (xtensa_opcode_is_loop (isa, vinsn->slots[0].opcode)
6835*3d8817e4Smiod       && !vinsn->slots[0].is_specific_opcode)
6836*3d8817e4Smiod     {
6837*3d8817e4Smiod       if (workaround_short_loop && use_transform ())
6838*3d8817e4Smiod 	{
6839*3d8817e4Smiod 	  maybe_has_short_loop = TRUE;
6840*3d8817e4Smiod 	  frag_now->tc_frag_data.is_insn = TRUE;
6841*3d8817e4Smiod 	  frag_var (rs_machine_dependent, 4, 4,
6842*3d8817e4Smiod 		    RELAX_ADD_NOP_IF_SHORT_LOOP,
6843*3d8817e4Smiod 		    frag_now->fr_symbol, frag_now->fr_offset, NULL);
6844*3d8817e4Smiod 	  frag_now->tc_frag_data.is_insn = TRUE;
6845*3d8817e4Smiod 	  frag_var (rs_machine_dependent, 4, 4,
6846*3d8817e4Smiod 		    RELAX_ADD_NOP_IF_SHORT_LOOP,
6847*3d8817e4Smiod 		    frag_now->fr_symbol, frag_now->fr_offset, NULL);
6848*3d8817e4Smiod 	}
6849*3d8817e4Smiod 
6850*3d8817e4Smiod       /* "close_loop_end": Add up to 12 bytes of NOPs to keep a
6851*3d8817e4Smiod 	 loop at least 12 bytes away from another loop's end.  */
6852*3d8817e4Smiod       if (workaround_close_loop_end && use_transform ())
6853*3d8817e4Smiod 	{
6854*3d8817e4Smiod 	  maybe_has_close_loop_end = TRUE;
6855*3d8817e4Smiod 	  frag_now->tc_frag_data.is_insn = TRUE;
6856*3d8817e4Smiod 	  frag_var (rs_machine_dependent, 12, 12,
6857*3d8817e4Smiod 		    RELAX_ADD_NOP_IF_CLOSE_LOOP_END,
6858*3d8817e4Smiod 		    frag_now->fr_symbol, frag_now->fr_offset, NULL);
6859*3d8817e4Smiod 	}
6860*3d8817e4Smiod     }
6861*3d8817e4Smiod 
6862*3d8817e4Smiod   if (use_transform ())
6863*3d8817e4Smiod     {
6864*3d8817e4Smiod       if (is_jump)
6865*3d8817e4Smiod 	{
6866*3d8817e4Smiod 	  assert (finish_frag);
6867*3d8817e4Smiod 	  frag_var (rs_machine_dependent,
6868*3d8817e4Smiod 		    UNREACHABLE_MAX_WIDTH, UNREACHABLE_MAX_WIDTH,
6869*3d8817e4Smiod 		    RELAX_UNREACHABLE,
6870*3d8817e4Smiod 		    frag_now->fr_symbol, frag_now->fr_offset, NULL);
6871*3d8817e4Smiod 	  xtensa_set_frag_assembly_state (frag_now);
6872*3d8817e4Smiod 	}
6873*3d8817e4Smiod       else if (is_branch && do_align_targets ())
6874*3d8817e4Smiod 	{
6875*3d8817e4Smiod 	  assert (finish_frag);
6876*3d8817e4Smiod 	  frag_var (rs_machine_dependent,
6877*3d8817e4Smiod 		    UNREACHABLE_MAX_WIDTH, UNREACHABLE_MAX_WIDTH,
6878*3d8817e4Smiod 		    RELAX_MAYBE_UNREACHABLE,
6879*3d8817e4Smiod 		    frag_now->fr_symbol, frag_now->fr_offset, NULL);
6880*3d8817e4Smiod 	  xtensa_set_frag_assembly_state (frag_now);
6881*3d8817e4Smiod 	  frag_var (rs_machine_dependent,
6882*3d8817e4Smiod 		    0, 0,
6883*3d8817e4Smiod 		    RELAX_MAYBE_DESIRE_ALIGN,
6884*3d8817e4Smiod 		    frag_now->fr_symbol, frag_now->fr_offset, NULL);
6885*3d8817e4Smiod 	  xtensa_set_frag_assembly_state (frag_now);
6886*3d8817e4Smiod 	}
6887*3d8817e4Smiod     }
6888*3d8817e4Smiod 
6889*3d8817e4Smiod   /* Now, if the original opcode was a call...  */
6890*3d8817e4Smiod   if (do_align_targets ()
6891*3d8817e4Smiod       && xtensa_opcode_is_call (isa, vinsn->slots[0].opcode) == 1)
6892*3d8817e4Smiod     {
6893*3d8817e4Smiod       float freq = get_subseg_total_freq (now_seg, now_subseg);
6894*3d8817e4Smiod       frag_now->tc_frag_data.is_insn = TRUE;
6895*3d8817e4Smiod       frag_var (rs_machine_dependent, 4, (int) freq, RELAX_DESIRE_ALIGN,
6896*3d8817e4Smiod 		frag_now->fr_symbol, frag_now->fr_offset, NULL);
6897*3d8817e4Smiod       xtensa_set_frag_assembly_state (frag_now);
6898*3d8817e4Smiod     }
6899*3d8817e4Smiod 
6900*3d8817e4Smiod   if (vinsn_has_specific_opcodes (vinsn) && use_transform ())
6901*3d8817e4Smiod     {
6902*3d8817e4Smiod       frag_wane (frag_now);
6903*3d8817e4Smiod       frag_new (0);
6904*3d8817e4Smiod       xtensa_set_frag_assembly_state (frag_now);
6905*3d8817e4Smiod     }
6906*3d8817e4Smiod }
6907*3d8817e4Smiod 
6908*3d8817e4Smiod 
6909*3d8817e4Smiod /* xtensa_end and helper functions.  */
6910*3d8817e4Smiod 
6911*3d8817e4Smiod static void xtensa_cleanup_align_frags (void);
6912*3d8817e4Smiod static void xtensa_fix_target_frags (void);
6913*3d8817e4Smiod static void xtensa_mark_narrow_branches (void);
6914*3d8817e4Smiod static void xtensa_mark_zcl_first_insns (void);
6915*3d8817e4Smiod static void xtensa_fix_a0_b_retw_frags (void);
6916*3d8817e4Smiod static void xtensa_fix_b_j_loop_end_frags (void);
6917*3d8817e4Smiod static void xtensa_fix_close_loop_end_frags (void);
6918*3d8817e4Smiod static void xtensa_fix_short_loop_frags (void);
6919*3d8817e4Smiod static void xtensa_sanity_check (void);
6920*3d8817e4Smiod 
6921*3d8817e4Smiod void
xtensa_end(void)6922*3d8817e4Smiod xtensa_end (void)
6923*3d8817e4Smiod {
6924*3d8817e4Smiod   directive_balance ();
6925*3d8817e4Smiod   xtensa_flush_pending_output ();
6926*3d8817e4Smiod 
6927*3d8817e4Smiod   past_xtensa_end = TRUE;
6928*3d8817e4Smiod 
6929*3d8817e4Smiod   xtensa_move_literals ();
6930*3d8817e4Smiod 
6931*3d8817e4Smiod   xtensa_reorder_segments ();
6932*3d8817e4Smiod   xtensa_cleanup_align_frags ();
6933*3d8817e4Smiod   xtensa_fix_target_frags ();
6934*3d8817e4Smiod   if (workaround_a0_b_retw && has_a0_b_retw)
6935*3d8817e4Smiod     xtensa_fix_a0_b_retw_frags ();
6936*3d8817e4Smiod   if (workaround_b_j_loop_end)
6937*3d8817e4Smiod     xtensa_fix_b_j_loop_end_frags ();
6938*3d8817e4Smiod 
6939*3d8817e4Smiod   /* "close_loop_end" should be processed BEFORE "short_loop".  */
6940*3d8817e4Smiod   if (workaround_close_loop_end && maybe_has_close_loop_end)
6941*3d8817e4Smiod     xtensa_fix_close_loop_end_frags ();
6942*3d8817e4Smiod 
6943*3d8817e4Smiod   if (workaround_short_loop && maybe_has_short_loop)
6944*3d8817e4Smiod     xtensa_fix_short_loop_frags ();
6945*3d8817e4Smiod   if (align_targets)
6946*3d8817e4Smiod     xtensa_mark_narrow_branches ();
6947*3d8817e4Smiod   xtensa_mark_zcl_first_insns ();
6948*3d8817e4Smiod 
6949*3d8817e4Smiod   xtensa_sanity_check ();
6950*3d8817e4Smiod }
6951*3d8817e4Smiod 
6952*3d8817e4Smiod 
6953*3d8817e4Smiod static void
xtensa_cleanup_align_frags(void)6954*3d8817e4Smiod xtensa_cleanup_align_frags (void)
6955*3d8817e4Smiod {
6956*3d8817e4Smiod   frchainS *frchP;
6957*3d8817e4Smiod 
6958*3d8817e4Smiod   for (frchP = frchain_root; frchP; frchP = frchP->frch_next)
6959*3d8817e4Smiod     {
6960*3d8817e4Smiod       fragS *fragP;
6961*3d8817e4Smiod       /* Walk over all of the fragments in a subsection.  */
6962*3d8817e4Smiod       for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
6963*3d8817e4Smiod 	{
6964*3d8817e4Smiod 	  if ((fragP->fr_type == rs_align
6965*3d8817e4Smiod 	       || fragP->fr_type == rs_align_code
6966*3d8817e4Smiod 	       || (fragP->fr_type == rs_machine_dependent
6967*3d8817e4Smiod 		   && (fragP->fr_subtype == RELAX_DESIRE_ALIGN
6968*3d8817e4Smiod 		       || fragP->fr_subtype == RELAX_DESIRE_ALIGN_IF_TARGET)))
6969*3d8817e4Smiod 	      && fragP->fr_fix == 0)
6970*3d8817e4Smiod 	    {
6971*3d8817e4Smiod 	      fragS *next = fragP->fr_next;
6972*3d8817e4Smiod 
6973*3d8817e4Smiod 	      while (next
6974*3d8817e4Smiod 		     && next->fr_fix == 0
6975*3d8817e4Smiod 		     && next->fr_type == rs_machine_dependent
6976*3d8817e4Smiod 		     && next->fr_subtype == RELAX_DESIRE_ALIGN_IF_TARGET)
6977*3d8817e4Smiod 		{
6978*3d8817e4Smiod 		  frag_wane (next);
6979*3d8817e4Smiod 		  next = next->fr_next;
6980*3d8817e4Smiod 		}
6981*3d8817e4Smiod 	    }
6982*3d8817e4Smiod 	  /* If we don't widen branch targets, then they
6983*3d8817e4Smiod 	     will be easier to align.  */
6984*3d8817e4Smiod 	  if (fragP->tc_frag_data.is_branch_target
6985*3d8817e4Smiod 	      && fragP->fr_opcode == fragP->fr_literal
6986*3d8817e4Smiod 	      && fragP->fr_type == rs_machine_dependent
6987*3d8817e4Smiod 	      && fragP->fr_subtype == RELAX_SLOTS
6988*3d8817e4Smiod 	      && fragP->tc_frag_data.slot_subtypes[0] == RELAX_NARROW)
6989*3d8817e4Smiod 	    frag_wane (fragP);
6990*3d8817e4Smiod 	  if (fragP->fr_type == rs_machine_dependent
6991*3d8817e4Smiod 	      && fragP->fr_subtype == RELAX_UNREACHABLE)
6992*3d8817e4Smiod 	    fragP->tc_frag_data.is_unreachable = TRUE;
6993*3d8817e4Smiod 	}
6994*3d8817e4Smiod     }
6995*3d8817e4Smiod }
6996*3d8817e4Smiod 
6997*3d8817e4Smiod 
6998*3d8817e4Smiod /* Re-process all of the fragments looking to convert all of the
6999*3d8817e4Smiod    RELAX_DESIRE_ALIGN_IF_TARGET fragments.  If there is a branch
7000*3d8817e4Smiod    target in the next fragment, convert this to RELAX_DESIRE_ALIGN.
7001*3d8817e4Smiod    Otherwise, convert to a .fill 0.  */
7002*3d8817e4Smiod 
7003*3d8817e4Smiod static void
xtensa_fix_target_frags(void)7004*3d8817e4Smiod xtensa_fix_target_frags (void)
7005*3d8817e4Smiod {
7006*3d8817e4Smiod   frchainS *frchP;
7007*3d8817e4Smiod 
7008*3d8817e4Smiod   /* When this routine is called, all of the subsections are still intact
7009*3d8817e4Smiod      so we walk over subsections instead of sections.  */
7010*3d8817e4Smiod   for (frchP = frchain_root; frchP; frchP = frchP->frch_next)
7011*3d8817e4Smiod     {
7012*3d8817e4Smiod       fragS *fragP;
7013*3d8817e4Smiod 
7014*3d8817e4Smiod       /* Walk over all of the fragments in a subsection.  */
7015*3d8817e4Smiod       for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
7016*3d8817e4Smiod 	{
7017*3d8817e4Smiod 	  if (fragP->fr_type == rs_machine_dependent
7018*3d8817e4Smiod 	      && fragP->fr_subtype == RELAX_DESIRE_ALIGN_IF_TARGET)
7019*3d8817e4Smiod 	    {
7020*3d8817e4Smiod 	      if (next_frag_is_branch_target (fragP))
7021*3d8817e4Smiod 		fragP->fr_subtype = RELAX_DESIRE_ALIGN;
7022*3d8817e4Smiod 	      else
7023*3d8817e4Smiod 		frag_wane (fragP);
7024*3d8817e4Smiod 	    }
7025*3d8817e4Smiod 	}
7026*3d8817e4Smiod     }
7027*3d8817e4Smiod }
7028*3d8817e4Smiod 
7029*3d8817e4Smiod 
7030*3d8817e4Smiod static bfd_boolean is_narrow_branch_guaranteed_in_range (fragS *, TInsn *);
7031*3d8817e4Smiod 
7032*3d8817e4Smiod static void
xtensa_mark_narrow_branches(void)7033*3d8817e4Smiod xtensa_mark_narrow_branches (void)
7034*3d8817e4Smiod {
7035*3d8817e4Smiod   frchainS *frchP;
7036*3d8817e4Smiod 
7037*3d8817e4Smiod   for (frchP = frchain_root; frchP; frchP = frchP->frch_next)
7038*3d8817e4Smiod     {
7039*3d8817e4Smiod       fragS *fragP;
7040*3d8817e4Smiod       /* Walk over all of the fragments in a subsection.  */
7041*3d8817e4Smiod       for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
7042*3d8817e4Smiod 	{
7043*3d8817e4Smiod 	  if (fragP->fr_type == rs_machine_dependent
7044*3d8817e4Smiod 	      && fragP->fr_subtype == RELAX_SLOTS
7045*3d8817e4Smiod 	      && fragP->tc_frag_data.slot_subtypes[0] == RELAX_IMMED)
7046*3d8817e4Smiod 	    {
7047*3d8817e4Smiod 	      vliw_insn vinsn;
7048*3d8817e4Smiod 
7049*3d8817e4Smiod 	      vinsn_from_chars (&vinsn, fragP->fr_opcode);
7050*3d8817e4Smiod 	      tinsn_immed_from_frag (&vinsn.slots[0], fragP, 0);
7051*3d8817e4Smiod 
7052*3d8817e4Smiod 	      if (vinsn.num_slots == 1
7053*3d8817e4Smiod 		  && xtensa_opcode_is_branch (xtensa_default_isa,
7054*3d8817e4Smiod 					      vinsn.slots[0].opcode)
7055*3d8817e4Smiod 		  && xg_get_single_size (vinsn.slots[0].opcode) == 2
7056*3d8817e4Smiod 		  && is_narrow_branch_guaranteed_in_range (fragP,
7057*3d8817e4Smiod 							   &vinsn.slots[0]))
7058*3d8817e4Smiod 		{
7059*3d8817e4Smiod 		  fragP->fr_subtype = RELAX_SLOTS;
7060*3d8817e4Smiod 		  fragP->tc_frag_data.slot_subtypes[0] = RELAX_NARROW;
7061*3d8817e4Smiod 		  fragP->tc_frag_data.is_aligning_branch = 1;
7062*3d8817e4Smiod 		}
7063*3d8817e4Smiod 	    }
7064*3d8817e4Smiod 	}
7065*3d8817e4Smiod     }
7066*3d8817e4Smiod }
7067*3d8817e4Smiod 
7068*3d8817e4Smiod 
7069*3d8817e4Smiod /* A branch is typically widened only when its target is out of
7070*3d8817e4Smiod    range.  However, we would like to widen them to align a subsequent
7071*3d8817e4Smiod    branch target when possible.
7072*3d8817e4Smiod 
7073*3d8817e4Smiod    Because the branch relaxation code is so convoluted, the optimal solution
7074*3d8817e4Smiod    (combining the two cases) is difficult to get right in all circumstances.
7075*3d8817e4Smiod    We therefore go with an "almost as good" solution, where we only
7076*3d8817e4Smiod    use for alignment narrow branches that definitely will not expand to a
7077*3d8817e4Smiod    jump and a branch.  These functions find and mark these cases.  */
7078*3d8817e4Smiod 
7079*3d8817e4Smiod /* The range in bytes of BNEZ.N and BEQZ.N.  The target operand is encoded
7080*3d8817e4Smiod    as PC + 4 + imm6, where imm6 is a 6-bit immediate ranging from 0 to 63.
7081*3d8817e4Smiod    We start counting beginning with the frag after the 2-byte branch, so the
7082*3d8817e4Smiod    maximum offset is (4 - 2) + 63 = 65.  */
7083*3d8817e4Smiod #define MAX_IMMED6 65
7084*3d8817e4Smiod 
7085*3d8817e4Smiod static offsetT unrelaxed_frag_max_size (fragS *);
7086*3d8817e4Smiod 
7087*3d8817e4Smiod static bfd_boolean
is_narrow_branch_guaranteed_in_range(fragS * fragP,TInsn * tinsn)7088*3d8817e4Smiod is_narrow_branch_guaranteed_in_range (fragS *fragP, TInsn *tinsn)
7089*3d8817e4Smiod {
7090*3d8817e4Smiod   const expressionS *expr = &tinsn->tok[1];
7091*3d8817e4Smiod   symbolS *symbolP = expr->X_add_symbol;
7092*3d8817e4Smiod   offsetT max_distance = expr->X_add_number;
7093*3d8817e4Smiod   fragS *target_frag;
7094*3d8817e4Smiod 
7095*3d8817e4Smiod   if (expr->X_op != O_symbol)
7096*3d8817e4Smiod     return FALSE;
7097*3d8817e4Smiod 
7098*3d8817e4Smiod   target_frag = symbol_get_frag (symbolP);
7099*3d8817e4Smiod 
7100*3d8817e4Smiod   max_distance += (S_GET_VALUE (symbolP) - target_frag->fr_address);
7101*3d8817e4Smiod   if (is_branch_jmp_to_next (tinsn, fragP))
7102*3d8817e4Smiod     return FALSE;
7103*3d8817e4Smiod 
7104*3d8817e4Smiod   /* The branch doesn't branch over it's own frag,
7105*3d8817e4Smiod      but over the subsequent ones.  */
7106*3d8817e4Smiod   fragP = fragP->fr_next;
7107*3d8817e4Smiod   while (fragP != NULL && fragP != target_frag && max_distance <= MAX_IMMED6)
7108*3d8817e4Smiod     {
7109*3d8817e4Smiod       max_distance += unrelaxed_frag_max_size (fragP);
7110*3d8817e4Smiod       fragP = fragP->fr_next;
7111*3d8817e4Smiod     }
7112*3d8817e4Smiod   if (max_distance <= MAX_IMMED6 && fragP == target_frag)
7113*3d8817e4Smiod     return TRUE;
7114*3d8817e4Smiod   return FALSE;
7115*3d8817e4Smiod }
7116*3d8817e4Smiod 
7117*3d8817e4Smiod 
7118*3d8817e4Smiod static void
xtensa_mark_zcl_first_insns(void)7119*3d8817e4Smiod xtensa_mark_zcl_first_insns (void)
7120*3d8817e4Smiod {
7121*3d8817e4Smiod   frchainS *frchP;
7122*3d8817e4Smiod 
7123*3d8817e4Smiod   for (frchP = frchain_root; frchP; frchP = frchP->frch_next)
7124*3d8817e4Smiod     {
7125*3d8817e4Smiod       fragS *fragP;
7126*3d8817e4Smiod       /* Walk over all of the fragments in a subsection.  */
7127*3d8817e4Smiod       for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
7128*3d8817e4Smiod 	{
7129*3d8817e4Smiod 	  if (fragP->fr_type == rs_machine_dependent
7130*3d8817e4Smiod 	      && (fragP->fr_subtype == RELAX_ALIGN_NEXT_OPCODE
7131*3d8817e4Smiod 		  || fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE))
7132*3d8817e4Smiod 	    {
7133*3d8817e4Smiod 	      /* Find the loop frag.  */
7134*3d8817e4Smiod 	      fragS *targ_frag = next_non_empty_frag (fragP);
7135*3d8817e4Smiod 	      /* Find the first insn frag.  */
7136*3d8817e4Smiod 	      targ_frag = next_non_empty_frag (targ_frag);
7137*3d8817e4Smiod 
7138*3d8817e4Smiod 	      /* Of course, sometimes (mostly for toy test cases) a
7139*3d8817e4Smiod 		 zero-cost loop instruction is the last in a section.  */
7140*3d8817e4Smiod 	      if (targ_frag)
7141*3d8817e4Smiod 		{
7142*3d8817e4Smiod 		  targ_frag->tc_frag_data.is_first_loop_insn = TRUE;
7143*3d8817e4Smiod 		  /* Do not widen a frag that is the first instruction of a
7144*3d8817e4Smiod 		     zero-cost loop.  It makes that loop harder to align.  */
7145*3d8817e4Smiod 		  if (targ_frag->fr_type == rs_machine_dependent
7146*3d8817e4Smiod 		      && targ_frag->fr_subtype == RELAX_SLOTS
7147*3d8817e4Smiod 		      && (targ_frag->tc_frag_data.slot_subtypes[0]
7148*3d8817e4Smiod 			  == RELAX_NARROW))
7149*3d8817e4Smiod 		    {
7150*3d8817e4Smiod 		      if (targ_frag->tc_frag_data.is_aligning_branch)
7151*3d8817e4Smiod 			targ_frag->tc_frag_data.slot_subtypes[0] = RELAX_IMMED;
7152*3d8817e4Smiod 		      else
7153*3d8817e4Smiod 			{
7154*3d8817e4Smiod 			  frag_wane (targ_frag);
7155*3d8817e4Smiod 			  targ_frag->tc_frag_data.slot_subtypes[0] = 0;
7156*3d8817e4Smiod 			}
7157*3d8817e4Smiod 		    }
7158*3d8817e4Smiod 		}
7159*3d8817e4Smiod 	      if (fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE)
7160*3d8817e4Smiod 		frag_wane (fragP);
7161*3d8817e4Smiod 	    }
7162*3d8817e4Smiod 	}
7163*3d8817e4Smiod     }
7164*3d8817e4Smiod }
7165*3d8817e4Smiod 
7166*3d8817e4Smiod 
7167*3d8817e4Smiod /* Re-process all of the fragments looking to convert all of the
7168*3d8817e4Smiod    RELAX_ADD_NOP_IF_A0_B_RETW.  If the next instruction is a
7169*3d8817e4Smiod    conditional branch or a retw/retw.n, convert this frag to one that
7170*3d8817e4Smiod    will generate a NOP.  In any case close it off with a .fill 0.  */
7171*3d8817e4Smiod 
7172*3d8817e4Smiod static bfd_boolean next_instrs_are_b_retw (fragS *);
7173*3d8817e4Smiod 
7174*3d8817e4Smiod static void
xtensa_fix_a0_b_retw_frags(void)7175*3d8817e4Smiod xtensa_fix_a0_b_retw_frags (void)
7176*3d8817e4Smiod {
7177*3d8817e4Smiod   frchainS *frchP;
7178*3d8817e4Smiod 
7179*3d8817e4Smiod   /* When this routine is called, all of the subsections are still intact
7180*3d8817e4Smiod      so we walk over subsections instead of sections.  */
7181*3d8817e4Smiod   for (frchP = frchain_root; frchP; frchP = frchP->frch_next)
7182*3d8817e4Smiod     {
7183*3d8817e4Smiod       fragS *fragP;
7184*3d8817e4Smiod 
7185*3d8817e4Smiod       /* Walk over all of the fragments in a subsection.  */
7186*3d8817e4Smiod       for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
7187*3d8817e4Smiod 	{
7188*3d8817e4Smiod 	  if (fragP->fr_type == rs_machine_dependent
7189*3d8817e4Smiod 	      && fragP->fr_subtype == RELAX_ADD_NOP_IF_A0_B_RETW)
7190*3d8817e4Smiod 	    {
7191*3d8817e4Smiod 	      if (next_instrs_are_b_retw (fragP))
7192*3d8817e4Smiod 		{
7193*3d8817e4Smiod 		  if (fragP->tc_frag_data.is_no_transform)
7194*3d8817e4Smiod 		    as_bad (_("instruction sequence (write a0, branch, retw) may trigger hardware errata"));
7195*3d8817e4Smiod 		  else
7196*3d8817e4Smiod 		    relax_frag_add_nop (fragP);
7197*3d8817e4Smiod 		}
7198*3d8817e4Smiod 	      frag_wane (fragP);
7199*3d8817e4Smiod 	    }
7200*3d8817e4Smiod 	}
7201*3d8817e4Smiod     }
7202*3d8817e4Smiod }
7203*3d8817e4Smiod 
7204*3d8817e4Smiod 
7205*3d8817e4Smiod static bfd_boolean
next_instrs_are_b_retw(fragS * fragP)7206*3d8817e4Smiod next_instrs_are_b_retw (fragS *fragP)
7207*3d8817e4Smiod {
7208*3d8817e4Smiod   xtensa_opcode opcode;
7209*3d8817e4Smiod   xtensa_format fmt;
7210*3d8817e4Smiod   const fragS *next_fragP = next_non_empty_frag (fragP);
7211*3d8817e4Smiod   static xtensa_insnbuf insnbuf = NULL;
7212*3d8817e4Smiod   static xtensa_insnbuf slotbuf = NULL;
7213*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
7214*3d8817e4Smiod   int offset = 0;
7215*3d8817e4Smiod   int slot;
7216*3d8817e4Smiod   bfd_boolean branch_seen = FALSE;
7217*3d8817e4Smiod 
7218*3d8817e4Smiod   if (!insnbuf)
7219*3d8817e4Smiod     {
7220*3d8817e4Smiod       insnbuf = xtensa_insnbuf_alloc (isa);
7221*3d8817e4Smiod       slotbuf = xtensa_insnbuf_alloc (isa);
7222*3d8817e4Smiod     }
7223*3d8817e4Smiod 
7224*3d8817e4Smiod   if (next_fragP == NULL)
7225*3d8817e4Smiod     return FALSE;
7226*3d8817e4Smiod 
7227*3d8817e4Smiod   /* Check for the conditional branch.  */
7228*3d8817e4Smiod   xtensa_insnbuf_from_chars
7229*3d8817e4Smiod     (isa, insnbuf, (unsigned char *) &next_fragP->fr_literal[offset], 0);
7230*3d8817e4Smiod   fmt = xtensa_format_decode (isa, insnbuf);
7231*3d8817e4Smiod   if (fmt == XTENSA_UNDEFINED)
7232*3d8817e4Smiod     return FALSE;
7233*3d8817e4Smiod 
7234*3d8817e4Smiod   for (slot = 0; slot < xtensa_format_num_slots (isa, fmt); slot++)
7235*3d8817e4Smiod     {
7236*3d8817e4Smiod       xtensa_format_get_slot (isa, fmt, slot, insnbuf, slotbuf);
7237*3d8817e4Smiod       opcode = xtensa_opcode_decode (isa, fmt, slot, slotbuf);
7238*3d8817e4Smiod 
7239*3d8817e4Smiod       branch_seen = (branch_seen
7240*3d8817e4Smiod 		     || xtensa_opcode_is_branch (isa, opcode) == 1);
7241*3d8817e4Smiod     }
7242*3d8817e4Smiod 
7243*3d8817e4Smiod   if (!branch_seen)
7244*3d8817e4Smiod     return FALSE;
7245*3d8817e4Smiod 
7246*3d8817e4Smiod   offset += xtensa_format_length (isa, fmt);
7247*3d8817e4Smiod   if (offset == next_fragP->fr_fix)
7248*3d8817e4Smiod     {
7249*3d8817e4Smiod       next_fragP = next_non_empty_frag (next_fragP);
7250*3d8817e4Smiod       offset = 0;
7251*3d8817e4Smiod     }
7252*3d8817e4Smiod 
7253*3d8817e4Smiod   if (next_fragP == NULL)
7254*3d8817e4Smiod     return FALSE;
7255*3d8817e4Smiod 
7256*3d8817e4Smiod   /* Check for the retw/retw.n.  */
7257*3d8817e4Smiod   xtensa_insnbuf_from_chars
7258*3d8817e4Smiod     (isa, insnbuf, (unsigned char *) &next_fragP->fr_literal[offset], 0);
7259*3d8817e4Smiod   fmt = xtensa_format_decode (isa, insnbuf);
7260*3d8817e4Smiod 
7261*3d8817e4Smiod   /* Because RETW[.N] is not bundleable, a VLIW bundle here means that we
7262*3d8817e4Smiod      have no problems.  */
7263*3d8817e4Smiod   if (fmt == XTENSA_UNDEFINED
7264*3d8817e4Smiod       || xtensa_format_num_slots (isa, fmt) != 1)
7265*3d8817e4Smiod     return FALSE;
7266*3d8817e4Smiod 
7267*3d8817e4Smiod   xtensa_format_get_slot (isa, fmt, 0, insnbuf, slotbuf);
7268*3d8817e4Smiod   opcode = xtensa_opcode_decode (isa, fmt, 0, slotbuf);
7269*3d8817e4Smiod 
7270*3d8817e4Smiod   if (opcode == xtensa_retw_opcode || opcode == xtensa_retw_n_opcode)
7271*3d8817e4Smiod     return TRUE;
7272*3d8817e4Smiod 
7273*3d8817e4Smiod   return FALSE;
7274*3d8817e4Smiod }
7275*3d8817e4Smiod 
7276*3d8817e4Smiod 
7277*3d8817e4Smiod /* Re-process all of the fragments looking to convert all of the
7278*3d8817e4Smiod    RELAX_ADD_NOP_IF_PRE_LOOP_END.  If there is one instruction and a
7279*3d8817e4Smiod    loop end label, convert this frag to one that will generate a NOP.
7280*3d8817e4Smiod    In any case close it off with a .fill 0.  */
7281*3d8817e4Smiod 
7282*3d8817e4Smiod static bfd_boolean next_instr_is_loop_end (fragS *);
7283*3d8817e4Smiod 
7284*3d8817e4Smiod static void
xtensa_fix_b_j_loop_end_frags(void)7285*3d8817e4Smiod xtensa_fix_b_j_loop_end_frags (void)
7286*3d8817e4Smiod {
7287*3d8817e4Smiod   frchainS *frchP;
7288*3d8817e4Smiod 
7289*3d8817e4Smiod   /* When this routine is called, all of the subsections are still intact
7290*3d8817e4Smiod      so we walk over subsections instead of sections.  */
7291*3d8817e4Smiod   for (frchP = frchain_root; frchP; frchP = frchP->frch_next)
7292*3d8817e4Smiod     {
7293*3d8817e4Smiod       fragS *fragP;
7294*3d8817e4Smiod 
7295*3d8817e4Smiod       /* Walk over all of the fragments in a subsection.  */
7296*3d8817e4Smiod       for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
7297*3d8817e4Smiod 	{
7298*3d8817e4Smiod 	  if (fragP->fr_type == rs_machine_dependent
7299*3d8817e4Smiod 	      && fragP->fr_subtype == RELAX_ADD_NOP_IF_PRE_LOOP_END)
7300*3d8817e4Smiod 	    {
7301*3d8817e4Smiod 	      if (next_instr_is_loop_end (fragP))
7302*3d8817e4Smiod 		{
7303*3d8817e4Smiod 		  if (fragP->tc_frag_data.is_no_transform)
7304*3d8817e4Smiod 		    as_bad (_("branching or jumping to a loop end may trigger hardware errata"));
7305*3d8817e4Smiod 		  else
7306*3d8817e4Smiod 		    relax_frag_add_nop (fragP);
7307*3d8817e4Smiod 		}
7308*3d8817e4Smiod 	      frag_wane (fragP);
7309*3d8817e4Smiod 	    }
7310*3d8817e4Smiod 	}
7311*3d8817e4Smiod     }
7312*3d8817e4Smiod }
7313*3d8817e4Smiod 
7314*3d8817e4Smiod 
7315*3d8817e4Smiod static bfd_boolean
next_instr_is_loop_end(fragS * fragP)7316*3d8817e4Smiod next_instr_is_loop_end (fragS *fragP)
7317*3d8817e4Smiod {
7318*3d8817e4Smiod   const fragS *next_fragP;
7319*3d8817e4Smiod 
7320*3d8817e4Smiod   if (next_frag_is_loop_target (fragP))
7321*3d8817e4Smiod     return FALSE;
7322*3d8817e4Smiod 
7323*3d8817e4Smiod   next_fragP = next_non_empty_frag (fragP);
7324*3d8817e4Smiod   if (next_fragP == NULL)
7325*3d8817e4Smiod     return FALSE;
7326*3d8817e4Smiod 
7327*3d8817e4Smiod   if (!next_frag_is_loop_target (next_fragP))
7328*3d8817e4Smiod     return FALSE;
7329*3d8817e4Smiod 
7330*3d8817e4Smiod   /* If the size is >= 3 then there is more than one instruction here.
7331*3d8817e4Smiod      The hardware bug will not fire.  */
7332*3d8817e4Smiod   if (next_fragP->fr_fix > 3)
7333*3d8817e4Smiod     return FALSE;
7334*3d8817e4Smiod 
7335*3d8817e4Smiod   return TRUE;
7336*3d8817e4Smiod }
7337*3d8817e4Smiod 
7338*3d8817e4Smiod 
7339*3d8817e4Smiod /* Re-process all of the fragments looking to convert all of the
7340*3d8817e4Smiod    RELAX_ADD_NOP_IF_CLOSE_LOOP_END.  If there is an loop end that is
7341*3d8817e4Smiod    not MY loop's loop end within 12 bytes, add enough nops here to
7342*3d8817e4Smiod    make it at least 12 bytes away.  In any case close it off with a
7343*3d8817e4Smiod    .fill 0.  */
7344*3d8817e4Smiod 
7345*3d8817e4Smiod static offsetT min_bytes_to_other_loop_end
7346*3d8817e4Smiod   (fragS *, fragS *, offsetT);
7347*3d8817e4Smiod 
7348*3d8817e4Smiod static void
xtensa_fix_close_loop_end_frags(void)7349*3d8817e4Smiod xtensa_fix_close_loop_end_frags (void)
7350*3d8817e4Smiod {
7351*3d8817e4Smiod   frchainS *frchP;
7352*3d8817e4Smiod 
7353*3d8817e4Smiod   /* When this routine is called, all of the subsections are still intact
7354*3d8817e4Smiod      so we walk over subsections instead of sections.  */
7355*3d8817e4Smiod   for (frchP = frchain_root; frchP; frchP = frchP->frch_next)
7356*3d8817e4Smiod     {
7357*3d8817e4Smiod       fragS *fragP;
7358*3d8817e4Smiod 
7359*3d8817e4Smiod       fragS *current_target = NULL;
7360*3d8817e4Smiod 
7361*3d8817e4Smiod       /* Walk over all of the fragments in a subsection.  */
7362*3d8817e4Smiod       for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
7363*3d8817e4Smiod 	{
7364*3d8817e4Smiod 	  if (fragP->fr_type == rs_machine_dependent
7365*3d8817e4Smiod 	      && ((fragP->fr_subtype == RELAX_ALIGN_NEXT_OPCODE)
7366*3d8817e4Smiod 		  || (fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE)))
7367*3d8817e4Smiod 	      current_target = symbol_get_frag (fragP->fr_symbol);
7368*3d8817e4Smiod 
7369*3d8817e4Smiod 	  if (current_target
7370*3d8817e4Smiod 	      && fragP->fr_type == rs_machine_dependent
7371*3d8817e4Smiod 	      && fragP->fr_subtype == RELAX_ADD_NOP_IF_CLOSE_LOOP_END)
7372*3d8817e4Smiod 	    {
7373*3d8817e4Smiod 	      offsetT min_bytes;
7374*3d8817e4Smiod 	      int bytes_added = 0;
7375*3d8817e4Smiod 
7376*3d8817e4Smiod #define REQUIRED_LOOP_DIVIDING_BYTES 12
7377*3d8817e4Smiod 	      /* Max out at 12.  */
7378*3d8817e4Smiod 	      min_bytes = min_bytes_to_other_loop_end
7379*3d8817e4Smiod 		(fragP->fr_next, current_target, REQUIRED_LOOP_DIVIDING_BYTES);
7380*3d8817e4Smiod 
7381*3d8817e4Smiod 	      if (min_bytes < REQUIRED_LOOP_DIVIDING_BYTES)
7382*3d8817e4Smiod 		{
7383*3d8817e4Smiod 		  if (fragP->tc_frag_data.is_no_transform)
7384*3d8817e4Smiod 		    as_bad (_("loop end too close to another loop end may trigger hardware errata"));
7385*3d8817e4Smiod 		  else
7386*3d8817e4Smiod 		    {
7387*3d8817e4Smiod 		      while (min_bytes + bytes_added
7388*3d8817e4Smiod 			     < REQUIRED_LOOP_DIVIDING_BYTES)
7389*3d8817e4Smiod 			{
7390*3d8817e4Smiod 			  int length = 3;
7391*3d8817e4Smiod 
7392*3d8817e4Smiod 			  if (fragP->fr_var < length)
7393*3d8817e4Smiod 			    as_fatal (_("fr_var %lu < length %d"),
7394*3d8817e4Smiod 				      (long) fragP->fr_var, length);
7395*3d8817e4Smiod 			  else
7396*3d8817e4Smiod 			    {
7397*3d8817e4Smiod 			      assemble_nop (length,
7398*3d8817e4Smiod 					    fragP->fr_literal + fragP->fr_fix);
7399*3d8817e4Smiod 			      fragP->fr_fix += length;
7400*3d8817e4Smiod 			      fragP->fr_var -= length;
7401*3d8817e4Smiod 			    }
7402*3d8817e4Smiod 			  bytes_added += length;
7403*3d8817e4Smiod 			}
7404*3d8817e4Smiod 		    }
7405*3d8817e4Smiod 		}
7406*3d8817e4Smiod 	      frag_wane (fragP);
7407*3d8817e4Smiod 	    }
7408*3d8817e4Smiod 	  assert (fragP->fr_type != rs_machine_dependent
7409*3d8817e4Smiod 		  || fragP->fr_subtype != RELAX_ADD_NOP_IF_CLOSE_LOOP_END);
7410*3d8817e4Smiod 	}
7411*3d8817e4Smiod     }
7412*3d8817e4Smiod }
7413*3d8817e4Smiod 
7414*3d8817e4Smiod 
7415*3d8817e4Smiod static offsetT unrelaxed_frag_min_size (fragS *);
7416*3d8817e4Smiod 
7417*3d8817e4Smiod static offsetT
min_bytes_to_other_loop_end(fragS * fragP,fragS * current_target,offsetT max_size)7418*3d8817e4Smiod min_bytes_to_other_loop_end (fragS *fragP,
7419*3d8817e4Smiod 			     fragS *current_target,
7420*3d8817e4Smiod 			     offsetT max_size)
7421*3d8817e4Smiod {
7422*3d8817e4Smiod   offsetT offset = 0;
7423*3d8817e4Smiod   fragS *current_fragP;
7424*3d8817e4Smiod 
7425*3d8817e4Smiod   for (current_fragP = fragP;
7426*3d8817e4Smiod        current_fragP;
7427*3d8817e4Smiod        current_fragP = current_fragP->fr_next)
7428*3d8817e4Smiod     {
7429*3d8817e4Smiod       if (current_fragP->tc_frag_data.is_loop_target
7430*3d8817e4Smiod 	  && current_fragP != current_target)
7431*3d8817e4Smiod 	return offset;
7432*3d8817e4Smiod 
7433*3d8817e4Smiod       offset += unrelaxed_frag_min_size (current_fragP);
7434*3d8817e4Smiod 
7435*3d8817e4Smiod       if (offset >= max_size)
7436*3d8817e4Smiod 	return max_size;
7437*3d8817e4Smiod     }
7438*3d8817e4Smiod   return max_size;
7439*3d8817e4Smiod }
7440*3d8817e4Smiod 
7441*3d8817e4Smiod 
7442*3d8817e4Smiod static offsetT
unrelaxed_frag_min_size(fragS * fragP)7443*3d8817e4Smiod unrelaxed_frag_min_size (fragS *fragP)
7444*3d8817e4Smiod {
7445*3d8817e4Smiod   offsetT size = fragP->fr_fix;
7446*3d8817e4Smiod 
7447*3d8817e4Smiod   /* Add fill size.  */
7448*3d8817e4Smiod   if (fragP->fr_type == rs_fill)
7449*3d8817e4Smiod     size += fragP->fr_offset;
7450*3d8817e4Smiod 
7451*3d8817e4Smiod   return size;
7452*3d8817e4Smiod }
7453*3d8817e4Smiod 
7454*3d8817e4Smiod 
7455*3d8817e4Smiod static offsetT
unrelaxed_frag_max_size(fragS * fragP)7456*3d8817e4Smiod unrelaxed_frag_max_size (fragS *fragP)
7457*3d8817e4Smiod {
7458*3d8817e4Smiod   offsetT size = fragP->fr_fix;
7459*3d8817e4Smiod   switch (fragP->fr_type)
7460*3d8817e4Smiod     {
7461*3d8817e4Smiod     case 0:
7462*3d8817e4Smiod       /* Empty frags created by the obstack allocation scheme
7463*3d8817e4Smiod 	 end up with type 0.  */
7464*3d8817e4Smiod       break;
7465*3d8817e4Smiod     case rs_fill:
7466*3d8817e4Smiod     case rs_org:
7467*3d8817e4Smiod     case rs_space:
7468*3d8817e4Smiod       size += fragP->fr_offset;
7469*3d8817e4Smiod       break;
7470*3d8817e4Smiod     case rs_align:
7471*3d8817e4Smiod     case rs_align_code:
7472*3d8817e4Smiod     case rs_align_test:
7473*3d8817e4Smiod     case rs_leb128:
7474*3d8817e4Smiod     case rs_cfa:
7475*3d8817e4Smiod     case rs_dwarf2dbg:
7476*3d8817e4Smiod       /* No further adjustments needed.  */
7477*3d8817e4Smiod       break;
7478*3d8817e4Smiod     case rs_machine_dependent:
7479*3d8817e4Smiod       if (fragP->fr_subtype != RELAX_DESIRE_ALIGN)
7480*3d8817e4Smiod 	size += fragP->fr_var;
7481*3d8817e4Smiod       break;
7482*3d8817e4Smiod     default:
7483*3d8817e4Smiod       /* We had darn well better know how big it is.  */
7484*3d8817e4Smiod       assert (0);
7485*3d8817e4Smiod       break;
7486*3d8817e4Smiod     }
7487*3d8817e4Smiod 
7488*3d8817e4Smiod   return size;
7489*3d8817e4Smiod }
7490*3d8817e4Smiod 
7491*3d8817e4Smiod 
7492*3d8817e4Smiod /* Re-process all of the fragments looking to convert all
7493*3d8817e4Smiod    of the RELAX_ADD_NOP_IF_SHORT_LOOP.  If:
7494*3d8817e4Smiod 
7495*3d8817e4Smiod    A)
7496*3d8817e4Smiod      1) the instruction size count to the loop end label
7497*3d8817e4Smiod         is too short (<= 2 instructions),
7498*3d8817e4Smiod      2) loop has a jump or branch in it
7499*3d8817e4Smiod 
7500*3d8817e4Smiod    or B)
7501*3d8817e4Smiod      1) workaround_all_short_loops is TRUE
7502*3d8817e4Smiod      2) The generating loop was a  'loopgtz' or 'loopnez'
7503*3d8817e4Smiod      3) the instruction size count to the loop end label is too short
7504*3d8817e4Smiod         (<= 2 instructions)
7505*3d8817e4Smiod    then convert this frag (and maybe the next one) to generate a NOP.
7506*3d8817e4Smiod    In any case close it off with a .fill 0.  */
7507*3d8817e4Smiod 
7508*3d8817e4Smiod static int count_insns_to_loop_end (fragS *, bfd_boolean, int);
7509*3d8817e4Smiod static bfd_boolean branch_before_loop_end (fragS *);
7510*3d8817e4Smiod 
7511*3d8817e4Smiod static void
xtensa_fix_short_loop_frags(void)7512*3d8817e4Smiod xtensa_fix_short_loop_frags (void)
7513*3d8817e4Smiod {
7514*3d8817e4Smiod   frchainS *frchP;
7515*3d8817e4Smiod 
7516*3d8817e4Smiod   /* When this routine is called, all of the subsections are still intact
7517*3d8817e4Smiod      so we walk over subsections instead of sections.  */
7518*3d8817e4Smiod   for (frchP = frchain_root; frchP; frchP = frchP->frch_next)
7519*3d8817e4Smiod     {
7520*3d8817e4Smiod       fragS *fragP;
7521*3d8817e4Smiod       fragS *current_target = NULL;
7522*3d8817e4Smiod       xtensa_opcode current_opcode = XTENSA_UNDEFINED;
7523*3d8817e4Smiod 
7524*3d8817e4Smiod       /* Walk over all of the fragments in a subsection.  */
7525*3d8817e4Smiod       for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
7526*3d8817e4Smiod 	{
7527*3d8817e4Smiod 	  if (fragP->fr_type == rs_machine_dependent
7528*3d8817e4Smiod 	      && ((fragP->fr_subtype == RELAX_ALIGN_NEXT_OPCODE)
7529*3d8817e4Smiod 		  || (fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE)))
7530*3d8817e4Smiod 	    {
7531*3d8817e4Smiod 	      TInsn t_insn;
7532*3d8817e4Smiod 	      fragS *loop_frag = next_non_empty_frag (fragP);
7533*3d8817e4Smiod 	      tinsn_from_chars (&t_insn, loop_frag->fr_opcode, 0);
7534*3d8817e4Smiod 	      current_target = symbol_get_frag (fragP->fr_symbol);
7535*3d8817e4Smiod 	      current_opcode = t_insn.opcode;
7536*3d8817e4Smiod 	      assert (xtensa_opcode_is_loop (xtensa_default_isa,
7537*3d8817e4Smiod 					     current_opcode));
7538*3d8817e4Smiod 	    }
7539*3d8817e4Smiod 
7540*3d8817e4Smiod 	  if (fragP->fr_type == rs_machine_dependent
7541*3d8817e4Smiod 	      && fragP->fr_subtype == RELAX_ADD_NOP_IF_SHORT_LOOP)
7542*3d8817e4Smiod 	    {
7543*3d8817e4Smiod 	      if (count_insns_to_loop_end (fragP->fr_next, TRUE, 3) < 3
7544*3d8817e4Smiod 		  && (branch_before_loop_end (fragP->fr_next)
7545*3d8817e4Smiod 		      || (workaround_all_short_loops
7546*3d8817e4Smiod 			  && current_opcode != XTENSA_UNDEFINED
7547*3d8817e4Smiod 			  && current_opcode != xtensa_loop_opcode)))
7548*3d8817e4Smiod 		{
7549*3d8817e4Smiod 		  if (fragP->tc_frag_data.is_no_transform)
7550*3d8817e4Smiod 		    as_bad (_("loop containing less than three instructions may trigger hardware errata"));
7551*3d8817e4Smiod 		  else
7552*3d8817e4Smiod 		    relax_frag_add_nop (fragP);
7553*3d8817e4Smiod 		}
7554*3d8817e4Smiod 	      frag_wane (fragP);
7555*3d8817e4Smiod 	    }
7556*3d8817e4Smiod 	}
7557*3d8817e4Smiod     }
7558*3d8817e4Smiod }
7559*3d8817e4Smiod 
7560*3d8817e4Smiod 
7561*3d8817e4Smiod static int unrelaxed_frag_min_insn_count (fragS *);
7562*3d8817e4Smiod 
7563*3d8817e4Smiod static int
count_insns_to_loop_end(fragS * base_fragP,bfd_boolean count_relax_add,int max_count)7564*3d8817e4Smiod count_insns_to_loop_end (fragS *base_fragP,
7565*3d8817e4Smiod 			 bfd_boolean count_relax_add,
7566*3d8817e4Smiod 			 int max_count)
7567*3d8817e4Smiod {
7568*3d8817e4Smiod   fragS *fragP = NULL;
7569*3d8817e4Smiod   int insn_count = 0;
7570*3d8817e4Smiod 
7571*3d8817e4Smiod   fragP = base_fragP;
7572*3d8817e4Smiod 
7573*3d8817e4Smiod   for (; fragP && !fragP->tc_frag_data.is_loop_target; fragP = fragP->fr_next)
7574*3d8817e4Smiod     {
7575*3d8817e4Smiod       insn_count += unrelaxed_frag_min_insn_count (fragP);
7576*3d8817e4Smiod       if (insn_count >= max_count)
7577*3d8817e4Smiod 	return max_count;
7578*3d8817e4Smiod 
7579*3d8817e4Smiod       if (count_relax_add)
7580*3d8817e4Smiod 	{
7581*3d8817e4Smiod 	  if (fragP->fr_type == rs_machine_dependent
7582*3d8817e4Smiod 	      && fragP->fr_subtype == RELAX_ADD_NOP_IF_SHORT_LOOP)
7583*3d8817e4Smiod 	    {
7584*3d8817e4Smiod 	      /* In order to add the appropriate number of
7585*3d8817e4Smiod 	         NOPs, we count an instruction for downstream
7586*3d8817e4Smiod 	         occurrences.  */
7587*3d8817e4Smiod 	      insn_count++;
7588*3d8817e4Smiod 	      if (insn_count >= max_count)
7589*3d8817e4Smiod 		return max_count;
7590*3d8817e4Smiod 	    }
7591*3d8817e4Smiod 	}
7592*3d8817e4Smiod     }
7593*3d8817e4Smiod   return insn_count;
7594*3d8817e4Smiod }
7595*3d8817e4Smiod 
7596*3d8817e4Smiod 
7597*3d8817e4Smiod static int
unrelaxed_frag_min_insn_count(fragS * fragP)7598*3d8817e4Smiod unrelaxed_frag_min_insn_count (fragS *fragP)
7599*3d8817e4Smiod {
7600*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
7601*3d8817e4Smiod   static xtensa_insnbuf insnbuf = NULL;
7602*3d8817e4Smiod   int insn_count = 0;
7603*3d8817e4Smiod   int offset = 0;
7604*3d8817e4Smiod 
7605*3d8817e4Smiod   if (!fragP->tc_frag_data.is_insn)
7606*3d8817e4Smiod     return insn_count;
7607*3d8817e4Smiod 
7608*3d8817e4Smiod   if (!insnbuf)
7609*3d8817e4Smiod     insnbuf = xtensa_insnbuf_alloc (isa);
7610*3d8817e4Smiod 
7611*3d8817e4Smiod   /* Decode the fixed instructions.  */
7612*3d8817e4Smiod   while (offset < fragP->fr_fix)
7613*3d8817e4Smiod     {
7614*3d8817e4Smiod       xtensa_format fmt;
7615*3d8817e4Smiod 
7616*3d8817e4Smiod       xtensa_insnbuf_from_chars
7617*3d8817e4Smiod 	(isa, insnbuf, (unsigned char *) fragP->fr_literal + offset, 0);
7618*3d8817e4Smiod       fmt = xtensa_format_decode (isa, insnbuf);
7619*3d8817e4Smiod 
7620*3d8817e4Smiod       if (fmt == XTENSA_UNDEFINED)
7621*3d8817e4Smiod 	{
7622*3d8817e4Smiod 	  as_fatal (_("undecodable instruction in instruction frag"));
7623*3d8817e4Smiod 	  return insn_count;
7624*3d8817e4Smiod 	}
7625*3d8817e4Smiod       offset += xtensa_format_length (isa, fmt);
7626*3d8817e4Smiod       insn_count++;
7627*3d8817e4Smiod     }
7628*3d8817e4Smiod 
7629*3d8817e4Smiod   return insn_count;
7630*3d8817e4Smiod }
7631*3d8817e4Smiod 
7632*3d8817e4Smiod 
7633*3d8817e4Smiod static bfd_boolean unrelaxed_frag_has_b_j (fragS *);
7634*3d8817e4Smiod 
7635*3d8817e4Smiod static bfd_boolean
branch_before_loop_end(fragS * base_fragP)7636*3d8817e4Smiod branch_before_loop_end (fragS *base_fragP)
7637*3d8817e4Smiod {
7638*3d8817e4Smiod   fragS *fragP;
7639*3d8817e4Smiod 
7640*3d8817e4Smiod   for (fragP = base_fragP;
7641*3d8817e4Smiod        fragP && !fragP->tc_frag_data.is_loop_target;
7642*3d8817e4Smiod        fragP = fragP->fr_next)
7643*3d8817e4Smiod     {
7644*3d8817e4Smiod       if (unrelaxed_frag_has_b_j (fragP))
7645*3d8817e4Smiod 	return TRUE;
7646*3d8817e4Smiod     }
7647*3d8817e4Smiod   return FALSE;
7648*3d8817e4Smiod }
7649*3d8817e4Smiod 
7650*3d8817e4Smiod 
7651*3d8817e4Smiod static bfd_boolean
unrelaxed_frag_has_b_j(fragS * fragP)7652*3d8817e4Smiod unrelaxed_frag_has_b_j (fragS *fragP)
7653*3d8817e4Smiod {
7654*3d8817e4Smiod   static xtensa_insnbuf insnbuf = NULL;
7655*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
7656*3d8817e4Smiod   int offset = 0;
7657*3d8817e4Smiod 
7658*3d8817e4Smiod   if (!fragP->tc_frag_data.is_insn)
7659*3d8817e4Smiod     return FALSE;
7660*3d8817e4Smiod 
7661*3d8817e4Smiod   if (!insnbuf)
7662*3d8817e4Smiod     insnbuf = xtensa_insnbuf_alloc (isa);
7663*3d8817e4Smiod 
7664*3d8817e4Smiod   /* Decode the fixed instructions.  */
7665*3d8817e4Smiod   while (offset < fragP->fr_fix)
7666*3d8817e4Smiod     {
7667*3d8817e4Smiod       xtensa_format fmt;
7668*3d8817e4Smiod       int slot;
7669*3d8817e4Smiod 
7670*3d8817e4Smiod       xtensa_insnbuf_from_chars
7671*3d8817e4Smiod 	(isa, insnbuf, (unsigned char *) fragP->fr_literal + offset, 0);
7672*3d8817e4Smiod       fmt = xtensa_format_decode (isa, insnbuf);
7673*3d8817e4Smiod       if (fmt == XTENSA_UNDEFINED)
7674*3d8817e4Smiod 	return FALSE;
7675*3d8817e4Smiod 
7676*3d8817e4Smiod       for (slot = 0; slot < xtensa_format_num_slots (isa, fmt); slot++)
7677*3d8817e4Smiod 	{
7678*3d8817e4Smiod 	  xtensa_opcode opcode =
7679*3d8817e4Smiod 	    get_opcode_from_buf (fragP->fr_literal + offset, slot);
7680*3d8817e4Smiod 	  if (xtensa_opcode_is_branch (isa, opcode) == 1
7681*3d8817e4Smiod 	      || xtensa_opcode_is_jump (isa, opcode) == 1)
7682*3d8817e4Smiod 	    return TRUE;
7683*3d8817e4Smiod 	}
7684*3d8817e4Smiod       offset += xtensa_format_length (isa, fmt);
7685*3d8817e4Smiod     }
7686*3d8817e4Smiod   return FALSE;
7687*3d8817e4Smiod }
7688*3d8817e4Smiod 
7689*3d8817e4Smiod 
7690*3d8817e4Smiod /* Checks to be made after initial assembly but before relaxation.  */
7691*3d8817e4Smiod 
7692*3d8817e4Smiod static bfd_boolean is_empty_loop (const TInsn *, fragS *);
7693*3d8817e4Smiod static bfd_boolean is_local_forward_loop (const TInsn *, fragS *);
7694*3d8817e4Smiod 
7695*3d8817e4Smiod static void
xtensa_sanity_check(void)7696*3d8817e4Smiod xtensa_sanity_check (void)
7697*3d8817e4Smiod {
7698*3d8817e4Smiod   char *file_name;
7699*3d8817e4Smiod   unsigned line;
7700*3d8817e4Smiod 
7701*3d8817e4Smiod   frchainS *frchP;
7702*3d8817e4Smiod 
7703*3d8817e4Smiod   as_where (&file_name, &line);
7704*3d8817e4Smiod   for (frchP = frchain_root; frchP; frchP = frchP->frch_next)
7705*3d8817e4Smiod     {
7706*3d8817e4Smiod       fragS *fragP;
7707*3d8817e4Smiod 
7708*3d8817e4Smiod       /* Walk over all of the fragments in a subsection.  */
7709*3d8817e4Smiod       for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
7710*3d8817e4Smiod 	{
7711*3d8817e4Smiod 	  /* Currently we only check for empty loops here.  */
7712*3d8817e4Smiod 	  if (fragP->fr_type == rs_machine_dependent
7713*3d8817e4Smiod 	      && fragP->fr_subtype == RELAX_IMMED)
7714*3d8817e4Smiod 	    {
7715*3d8817e4Smiod 	      static xtensa_insnbuf insnbuf = NULL;
7716*3d8817e4Smiod 	      TInsn t_insn;
7717*3d8817e4Smiod 
7718*3d8817e4Smiod 	      if (fragP->fr_opcode != NULL)
7719*3d8817e4Smiod 		{
7720*3d8817e4Smiod 		  if (!insnbuf)
7721*3d8817e4Smiod 		    insnbuf = xtensa_insnbuf_alloc (xtensa_default_isa);
7722*3d8817e4Smiod 		  tinsn_from_chars (&t_insn, fragP->fr_opcode, 0);
7723*3d8817e4Smiod 		  tinsn_immed_from_frag (&t_insn, fragP, 0);
7724*3d8817e4Smiod 
7725*3d8817e4Smiod 		  if (xtensa_opcode_is_loop (xtensa_default_isa,
7726*3d8817e4Smiod 					     t_insn.opcode) == 1)
7727*3d8817e4Smiod 		    {
7728*3d8817e4Smiod 		      if (is_empty_loop (&t_insn, fragP))
7729*3d8817e4Smiod 			{
7730*3d8817e4Smiod 			  new_logical_line (fragP->fr_file, fragP->fr_line);
7731*3d8817e4Smiod 			  as_bad (_("invalid empty loop"));
7732*3d8817e4Smiod 			}
7733*3d8817e4Smiod 		      if (!is_local_forward_loop (&t_insn, fragP))
7734*3d8817e4Smiod 			{
7735*3d8817e4Smiod 			  new_logical_line (fragP->fr_file, fragP->fr_line);
7736*3d8817e4Smiod 			  as_bad (_("loop target does not follow "
7737*3d8817e4Smiod 				    "loop instruction in section"));
7738*3d8817e4Smiod 			}
7739*3d8817e4Smiod 		    }
7740*3d8817e4Smiod 		}
7741*3d8817e4Smiod 	    }
7742*3d8817e4Smiod 	}
7743*3d8817e4Smiod     }
7744*3d8817e4Smiod   new_logical_line (file_name, line);
7745*3d8817e4Smiod }
7746*3d8817e4Smiod 
7747*3d8817e4Smiod 
7748*3d8817e4Smiod #define LOOP_IMMED_OPN 1
7749*3d8817e4Smiod 
7750*3d8817e4Smiod /* Return TRUE if the loop target is the next non-zero fragment.  */
7751*3d8817e4Smiod 
7752*3d8817e4Smiod static bfd_boolean
is_empty_loop(const TInsn * insn,fragS * fragP)7753*3d8817e4Smiod is_empty_loop (const TInsn *insn, fragS *fragP)
7754*3d8817e4Smiod {
7755*3d8817e4Smiod   const expressionS *expr;
7756*3d8817e4Smiod   symbolS *symbolP;
7757*3d8817e4Smiod   fragS *next_fragP;
7758*3d8817e4Smiod 
7759*3d8817e4Smiod   if (insn->insn_type != ITYPE_INSN)
7760*3d8817e4Smiod     return FALSE;
7761*3d8817e4Smiod 
7762*3d8817e4Smiod   if (xtensa_opcode_is_loop (xtensa_default_isa, insn->opcode) != 1)
7763*3d8817e4Smiod     return FALSE;
7764*3d8817e4Smiod 
7765*3d8817e4Smiod   if (insn->ntok <= LOOP_IMMED_OPN)
7766*3d8817e4Smiod     return FALSE;
7767*3d8817e4Smiod 
7768*3d8817e4Smiod   expr = &insn->tok[LOOP_IMMED_OPN];
7769*3d8817e4Smiod 
7770*3d8817e4Smiod   if (expr->X_op != O_symbol)
7771*3d8817e4Smiod     return FALSE;
7772*3d8817e4Smiod 
7773*3d8817e4Smiod   symbolP = expr->X_add_symbol;
7774*3d8817e4Smiod   if (!symbolP)
7775*3d8817e4Smiod     return FALSE;
7776*3d8817e4Smiod 
7777*3d8817e4Smiod   if (symbol_get_frag (symbolP) == NULL)
7778*3d8817e4Smiod     return FALSE;
7779*3d8817e4Smiod 
7780*3d8817e4Smiod   if (S_GET_VALUE (symbolP) != 0)
7781*3d8817e4Smiod     return FALSE;
7782*3d8817e4Smiod 
7783*3d8817e4Smiod   /* Walk through the zero-size fragments from this one.  If we find
7784*3d8817e4Smiod      the target fragment, then this is a zero-size loop.  */
7785*3d8817e4Smiod 
7786*3d8817e4Smiod   for (next_fragP = fragP->fr_next;
7787*3d8817e4Smiod        next_fragP != NULL;
7788*3d8817e4Smiod        next_fragP = next_fragP->fr_next)
7789*3d8817e4Smiod     {
7790*3d8817e4Smiod       if (next_fragP == symbol_get_frag (symbolP))
7791*3d8817e4Smiod 	return TRUE;
7792*3d8817e4Smiod       if (next_fragP->fr_fix != 0)
7793*3d8817e4Smiod 	return FALSE;
7794*3d8817e4Smiod     }
7795*3d8817e4Smiod   return FALSE;
7796*3d8817e4Smiod }
7797*3d8817e4Smiod 
7798*3d8817e4Smiod 
7799*3d8817e4Smiod static bfd_boolean
is_local_forward_loop(const TInsn * insn,fragS * fragP)7800*3d8817e4Smiod is_local_forward_loop (const TInsn *insn, fragS *fragP)
7801*3d8817e4Smiod {
7802*3d8817e4Smiod   const expressionS *expr;
7803*3d8817e4Smiod   symbolS *symbolP;
7804*3d8817e4Smiod   fragS *next_fragP;
7805*3d8817e4Smiod 
7806*3d8817e4Smiod   if (insn->insn_type != ITYPE_INSN)
7807*3d8817e4Smiod     return FALSE;
7808*3d8817e4Smiod 
7809*3d8817e4Smiod   if (xtensa_opcode_is_loop (xtensa_default_isa, insn->opcode) == 0)
7810*3d8817e4Smiod     return FALSE;
7811*3d8817e4Smiod 
7812*3d8817e4Smiod   if (insn->ntok <= LOOP_IMMED_OPN)
7813*3d8817e4Smiod     return FALSE;
7814*3d8817e4Smiod 
7815*3d8817e4Smiod   expr = &insn->tok[LOOP_IMMED_OPN];
7816*3d8817e4Smiod 
7817*3d8817e4Smiod   if (expr->X_op != O_symbol)
7818*3d8817e4Smiod     return FALSE;
7819*3d8817e4Smiod 
7820*3d8817e4Smiod   symbolP = expr->X_add_symbol;
7821*3d8817e4Smiod   if (!symbolP)
7822*3d8817e4Smiod     return FALSE;
7823*3d8817e4Smiod 
7824*3d8817e4Smiod   if (symbol_get_frag (symbolP) == NULL)
7825*3d8817e4Smiod     return FALSE;
7826*3d8817e4Smiod 
7827*3d8817e4Smiod   /* Walk through fragments until we find the target.
7828*3d8817e4Smiod      If we do not find the target, then this is an invalid loop.  */
7829*3d8817e4Smiod 
7830*3d8817e4Smiod   for (next_fragP = fragP->fr_next;
7831*3d8817e4Smiod        next_fragP != NULL;
7832*3d8817e4Smiod        next_fragP = next_fragP->fr_next)
7833*3d8817e4Smiod     {
7834*3d8817e4Smiod       if (next_fragP == symbol_get_frag (symbolP))
7835*3d8817e4Smiod 	return TRUE;
7836*3d8817e4Smiod     }
7837*3d8817e4Smiod 
7838*3d8817e4Smiod   return FALSE;
7839*3d8817e4Smiod }
7840*3d8817e4Smiod 
7841*3d8817e4Smiod 
7842*3d8817e4Smiod /* Alignment Functions.  */
7843*3d8817e4Smiod 
7844*3d8817e4Smiod static int
get_text_align_power(unsigned target_size)7845*3d8817e4Smiod get_text_align_power (unsigned target_size)
7846*3d8817e4Smiod {
7847*3d8817e4Smiod   if (target_size <= 4)
7848*3d8817e4Smiod     return 2;
7849*3d8817e4Smiod   assert (target_size == 8);
7850*3d8817e4Smiod   return 3;
7851*3d8817e4Smiod }
7852*3d8817e4Smiod 
7853*3d8817e4Smiod 
7854*3d8817e4Smiod static int
get_text_align_max_fill_size(int align_pow,bfd_boolean use_nops,bfd_boolean use_no_density)7855*3d8817e4Smiod get_text_align_max_fill_size (int align_pow,
7856*3d8817e4Smiod 			      bfd_boolean use_nops,
7857*3d8817e4Smiod 			      bfd_boolean use_no_density)
7858*3d8817e4Smiod {
7859*3d8817e4Smiod   if (!use_nops)
7860*3d8817e4Smiod     return (1 << align_pow);
7861*3d8817e4Smiod   if (use_no_density)
7862*3d8817e4Smiod     return 3 * (1 << align_pow);
7863*3d8817e4Smiod 
7864*3d8817e4Smiod   return 1 + (1 << align_pow);
7865*3d8817e4Smiod }
7866*3d8817e4Smiod 
7867*3d8817e4Smiod 
7868*3d8817e4Smiod /* Calculate the minimum bytes of fill needed at "address" to align a
7869*3d8817e4Smiod    target instruction of size "target_size" so that it does not cross a
7870*3d8817e4Smiod    power-of-two boundary specified by "align_pow".  If "use_nops" is FALSE,
7871*3d8817e4Smiod    the fill can be an arbitrary number of bytes.  Otherwise, the space must
7872*3d8817e4Smiod    be filled by NOP instructions.  */
7873*3d8817e4Smiod 
7874*3d8817e4Smiod static int
get_text_align_fill_size(addressT address,int align_pow,int target_size,bfd_boolean use_nops,bfd_boolean use_no_density)7875*3d8817e4Smiod get_text_align_fill_size (addressT address,
7876*3d8817e4Smiod 			  int align_pow,
7877*3d8817e4Smiod 			  int target_size,
7878*3d8817e4Smiod 			  bfd_boolean use_nops,
7879*3d8817e4Smiod 			  bfd_boolean use_no_density)
7880*3d8817e4Smiod {
7881*3d8817e4Smiod   addressT alignment, fill, fill_limit, fill_step;
7882*3d8817e4Smiod   bfd_boolean skip_one = FALSE;
7883*3d8817e4Smiod 
7884*3d8817e4Smiod   alignment = (1 << align_pow);
7885*3d8817e4Smiod   assert (target_size > 0 && alignment >= (addressT) target_size);
7886*3d8817e4Smiod 
7887*3d8817e4Smiod   if (!use_nops)
7888*3d8817e4Smiod     {
7889*3d8817e4Smiod       fill_limit = alignment;
7890*3d8817e4Smiod       fill_step = 1;
7891*3d8817e4Smiod     }
7892*3d8817e4Smiod   else if (!use_no_density)
7893*3d8817e4Smiod     {
7894*3d8817e4Smiod       /* Combine 2- and 3-byte NOPs to fill anything larger than one.  */
7895*3d8817e4Smiod       fill_limit = alignment * 2;
7896*3d8817e4Smiod       fill_step = 1;
7897*3d8817e4Smiod       skip_one = TRUE;
7898*3d8817e4Smiod     }
7899*3d8817e4Smiod   else
7900*3d8817e4Smiod     {
7901*3d8817e4Smiod       /* Fill with 3-byte NOPs -- can only fill multiples of 3.  */
7902*3d8817e4Smiod       fill_limit = alignment * 3;
7903*3d8817e4Smiod       fill_step = 3;
7904*3d8817e4Smiod     }
7905*3d8817e4Smiod 
7906*3d8817e4Smiod   /* Try all fill sizes until finding one that works.  */
7907*3d8817e4Smiod   for (fill = 0; fill < fill_limit; fill += fill_step)
7908*3d8817e4Smiod     {
7909*3d8817e4Smiod       if (skip_one && fill == 1)
7910*3d8817e4Smiod 	continue;
7911*3d8817e4Smiod       if ((address + fill) >> align_pow
7912*3d8817e4Smiod 	  == (address + fill + target_size - 1) >> align_pow)
7913*3d8817e4Smiod 	return fill;
7914*3d8817e4Smiod     }
7915*3d8817e4Smiod   assert (0);
7916*3d8817e4Smiod   return 0;
7917*3d8817e4Smiod }
7918*3d8817e4Smiod 
7919*3d8817e4Smiod 
7920*3d8817e4Smiod static int
branch_align_power(segT sec)7921*3d8817e4Smiod branch_align_power (segT sec)
7922*3d8817e4Smiod {
7923*3d8817e4Smiod   /* If the Xtensa processor has a fetch width of 8 bytes, and the section
7924*3d8817e4Smiod      is aligned to at least an 8-byte boundary, then a branch target need
7925*3d8817e4Smiod      only fit within an 8-byte aligned block of memory to avoid a stall.
7926*3d8817e4Smiod      Otherwise, try to fit branch targets within 4-byte aligned blocks
7927*3d8817e4Smiod      (which may be insufficient, e.g., if the section has no alignment, but
7928*3d8817e4Smiod      it's good enough).  */
7929*3d8817e4Smiod   if (xtensa_fetch_width == 8)
7930*3d8817e4Smiod     {
7931*3d8817e4Smiod       if (get_recorded_alignment (sec) >= 3)
7932*3d8817e4Smiod 	return 3;
7933*3d8817e4Smiod     }
7934*3d8817e4Smiod   else
7935*3d8817e4Smiod     assert (xtensa_fetch_width == 4);
7936*3d8817e4Smiod 
7937*3d8817e4Smiod   return 2;
7938*3d8817e4Smiod }
7939*3d8817e4Smiod 
7940*3d8817e4Smiod 
7941*3d8817e4Smiod /* This will assert if it is not possible.  */
7942*3d8817e4Smiod 
7943*3d8817e4Smiod static int
get_text_align_nop_count(offsetT fill_size,bfd_boolean use_no_density)7944*3d8817e4Smiod get_text_align_nop_count (offsetT fill_size, bfd_boolean use_no_density)
7945*3d8817e4Smiod {
7946*3d8817e4Smiod   int count = 0;
7947*3d8817e4Smiod 
7948*3d8817e4Smiod   if (use_no_density)
7949*3d8817e4Smiod     {
7950*3d8817e4Smiod       assert (fill_size % 3 == 0);
7951*3d8817e4Smiod       return (fill_size / 3);
7952*3d8817e4Smiod     }
7953*3d8817e4Smiod 
7954*3d8817e4Smiod   assert (fill_size != 1);	/* Bad argument.  */
7955*3d8817e4Smiod 
7956*3d8817e4Smiod   while (fill_size > 1)
7957*3d8817e4Smiod     {
7958*3d8817e4Smiod       int insn_size = 3;
7959*3d8817e4Smiod       if (fill_size == 2 || fill_size == 4)
7960*3d8817e4Smiod 	insn_size = 2;
7961*3d8817e4Smiod       fill_size -= insn_size;
7962*3d8817e4Smiod       count++;
7963*3d8817e4Smiod     }
7964*3d8817e4Smiod   assert (fill_size != 1);	/* Bad algorithm.  */
7965*3d8817e4Smiod   return count;
7966*3d8817e4Smiod }
7967*3d8817e4Smiod 
7968*3d8817e4Smiod 
7969*3d8817e4Smiod static int
get_text_align_nth_nop_size(offsetT fill_size,int n,bfd_boolean use_no_density)7970*3d8817e4Smiod get_text_align_nth_nop_size (offsetT fill_size,
7971*3d8817e4Smiod 			     int n,
7972*3d8817e4Smiod 			     bfd_boolean use_no_density)
7973*3d8817e4Smiod {
7974*3d8817e4Smiod   int count = 0;
7975*3d8817e4Smiod 
7976*3d8817e4Smiod   if (use_no_density)
7977*3d8817e4Smiod     return 3;
7978*3d8817e4Smiod 
7979*3d8817e4Smiod   assert (fill_size != 1);	/* Bad argument.  */
7980*3d8817e4Smiod 
7981*3d8817e4Smiod   while (fill_size > 1)
7982*3d8817e4Smiod     {
7983*3d8817e4Smiod       int insn_size = 3;
7984*3d8817e4Smiod       if (fill_size == 2 || fill_size == 4)
7985*3d8817e4Smiod 	insn_size = 2;
7986*3d8817e4Smiod       fill_size -= insn_size;
7987*3d8817e4Smiod       count++;
7988*3d8817e4Smiod       if (n + 1 == count)
7989*3d8817e4Smiod 	return insn_size;
7990*3d8817e4Smiod     }
7991*3d8817e4Smiod   assert (0);
7992*3d8817e4Smiod   return 0;
7993*3d8817e4Smiod }
7994*3d8817e4Smiod 
7995*3d8817e4Smiod 
7996*3d8817e4Smiod /* For the given fragment, find the appropriate address
7997*3d8817e4Smiod    for it to begin at if we are using NOPs to align it.  */
7998*3d8817e4Smiod 
7999*3d8817e4Smiod static addressT
get_noop_aligned_address(fragS * fragP,addressT address)8000*3d8817e4Smiod get_noop_aligned_address (fragS *fragP, addressT address)
8001*3d8817e4Smiod {
8002*3d8817e4Smiod   /* The rule is: get next fragment's FIRST instruction.  Find
8003*3d8817e4Smiod      the smallest number of bytes that need to be added to
8004*3d8817e4Smiod      ensure that the next fragment's FIRST instruction will fit
8005*3d8817e4Smiod      in a single word.
8006*3d8817e4Smiod 
8007*3d8817e4Smiod      E.G.,   2 bytes : 0, 1, 2 mod 4
8008*3d8817e4Smiod 	     3 bytes: 0, 1 mod 4
8009*3d8817e4Smiod 
8010*3d8817e4Smiod      If the FIRST instruction MIGHT be relaxed,
8011*3d8817e4Smiod      assume that it will become a 3-byte instruction.
8012*3d8817e4Smiod 
8013*3d8817e4Smiod      Note again here that LOOP instructions are not bundleable,
8014*3d8817e4Smiod      and this relaxation only applies to LOOP opcodes.  */
8015*3d8817e4Smiod 
8016*3d8817e4Smiod   int fill_size = 0;
8017*3d8817e4Smiod   int first_insn_size;
8018*3d8817e4Smiod   int loop_insn_size;
8019*3d8817e4Smiod   addressT pre_opcode_bytes;
8020*3d8817e4Smiod   int align_power;
8021*3d8817e4Smiod   fragS *first_insn;
8022*3d8817e4Smiod   xtensa_opcode opcode;
8023*3d8817e4Smiod   bfd_boolean is_loop;
8024*3d8817e4Smiod 
8025*3d8817e4Smiod   assert (fragP->fr_type == rs_machine_dependent);
8026*3d8817e4Smiod   assert (fragP->fr_subtype == RELAX_ALIGN_NEXT_OPCODE);
8027*3d8817e4Smiod 
8028*3d8817e4Smiod   /* Find the loop frag.  */
8029*3d8817e4Smiod   first_insn = next_non_empty_frag (fragP);
8030*3d8817e4Smiod   /* Now find the first insn frag.  */
8031*3d8817e4Smiod   first_insn = next_non_empty_frag (first_insn);
8032*3d8817e4Smiod 
8033*3d8817e4Smiod   is_loop = next_frag_opcode_is_loop (fragP, &opcode);
8034*3d8817e4Smiod   assert (is_loop);
8035*3d8817e4Smiod   loop_insn_size = xg_get_single_size (opcode);
8036*3d8817e4Smiod 
8037*3d8817e4Smiod   pre_opcode_bytes = next_frag_pre_opcode_bytes (fragP);
8038*3d8817e4Smiod   pre_opcode_bytes += loop_insn_size;
8039*3d8817e4Smiod 
8040*3d8817e4Smiod   /* For loops, the alignment depends on the size of the
8041*3d8817e4Smiod      instruction following the loop, not the LOOP instruction.  */
8042*3d8817e4Smiod 
8043*3d8817e4Smiod   if (first_insn == NULL)
8044*3d8817e4Smiod     first_insn_size = xtensa_fetch_width;
8045*3d8817e4Smiod   else
8046*3d8817e4Smiod     first_insn_size = get_loop_align_size (frag_format_size (first_insn));
8047*3d8817e4Smiod 
8048*3d8817e4Smiod   /* If it was 8, then we'll need a larger alignment for the section.  */
8049*3d8817e4Smiod   align_power = get_text_align_power (first_insn_size);
8050*3d8817e4Smiod   record_alignment (now_seg, align_power);
8051*3d8817e4Smiod 
8052*3d8817e4Smiod   fill_size = get_text_align_fill_size
8053*3d8817e4Smiod     (address + pre_opcode_bytes, align_power, first_insn_size, TRUE,
8054*3d8817e4Smiod      fragP->tc_frag_data.is_no_density);
8055*3d8817e4Smiod 
8056*3d8817e4Smiod   return address + fill_size;
8057*3d8817e4Smiod }
8058*3d8817e4Smiod 
8059*3d8817e4Smiod 
8060*3d8817e4Smiod /* 3 mechanisms for relaxing an alignment:
8061*3d8817e4Smiod 
8062*3d8817e4Smiod    Align to a power of 2.
8063*3d8817e4Smiod    Align so the next fragment's instruction does not cross a word boundary.
8064*3d8817e4Smiod    Align the current instruction so that if the next instruction
8065*3d8817e4Smiod        were 3 bytes, it would not cross a word boundary.
8066*3d8817e4Smiod 
8067*3d8817e4Smiod    We can align with:
8068*3d8817e4Smiod 
8069*3d8817e4Smiod    zeros    - This is easy; always insert zeros.
8070*3d8817e4Smiod    nops     - 3-byte and 2-byte instructions
8071*3d8817e4Smiod               2 - 2-byte nop
8072*3d8817e4Smiod               3 - 3-byte nop
8073*3d8817e4Smiod               4 - 2 2-byte nops
8074*3d8817e4Smiod               >=5 : 3-byte instruction + fn (n-3)
8075*3d8817e4Smiod    widening - widen previous instructions.  */
8076*3d8817e4Smiod 
8077*3d8817e4Smiod static offsetT
get_aligned_diff(fragS * fragP,addressT address,offsetT * max_diff)8078*3d8817e4Smiod get_aligned_diff (fragS *fragP, addressT address, offsetT *max_diff)
8079*3d8817e4Smiod {
8080*3d8817e4Smiod   addressT target_address, loop_insn_offset;
8081*3d8817e4Smiod   int target_size;
8082*3d8817e4Smiod   xtensa_opcode loop_opcode;
8083*3d8817e4Smiod   bfd_boolean is_loop;
8084*3d8817e4Smiod   int align_power;
8085*3d8817e4Smiod   offsetT opt_diff;
8086*3d8817e4Smiod   offsetT branch_align;
8087*3d8817e4Smiod 
8088*3d8817e4Smiod   assert (fragP->fr_type == rs_machine_dependent);
8089*3d8817e4Smiod   switch (fragP->fr_subtype)
8090*3d8817e4Smiod     {
8091*3d8817e4Smiod     case RELAX_DESIRE_ALIGN:
8092*3d8817e4Smiod       target_size = next_frag_format_size (fragP);
8093*3d8817e4Smiod       if (target_size == XTENSA_UNDEFINED)
8094*3d8817e4Smiod 	target_size = 3;
8095*3d8817e4Smiod       align_power = branch_align_power (now_seg);
8096*3d8817e4Smiod       branch_align = 1 << align_power;
8097*3d8817e4Smiod       /* Don't count on the section alignment being as large as the target.  */
8098*3d8817e4Smiod       if (target_size > branch_align)
8099*3d8817e4Smiod 	target_size = branch_align;
8100*3d8817e4Smiod       opt_diff = get_text_align_fill_size (address, align_power,
8101*3d8817e4Smiod 					   target_size, FALSE, FALSE);
8102*3d8817e4Smiod 
8103*3d8817e4Smiod       *max_diff = (opt_diff + branch_align
8104*3d8817e4Smiod 		   - (target_size + ((address + opt_diff) % branch_align)));
8105*3d8817e4Smiod       assert (*max_diff >= opt_diff);
8106*3d8817e4Smiod       return opt_diff;
8107*3d8817e4Smiod 
8108*3d8817e4Smiod     case RELAX_ALIGN_NEXT_OPCODE:
8109*3d8817e4Smiod       target_size = get_loop_align_size (next_frag_format_size (fragP));
8110*3d8817e4Smiod       loop_insn_offset = 0;
8111*3d8817e4Smiod       is_loop = next_frag_opcode_is_loop (fragP, &loop_opcode);
8112*3d8817e4Smiod       assert (is_loop);
8113*3d8817e4Smiod 
8114*3d8817e4Smiod       /* If the loop has been expanded then the LOOP instruction
8115*3d8817e4Smiod 	 could be at an offset from this fragment.  */
8116*3d8817e4Smiod       if (next_non_empty_frag(fragP)->tc_frag_data.slot_subtypes[0]
8117*3d8817e4Smiod 	  != RELAX_IMMED)
8118*3d8817e4Smiod 	loop_insn_offset = get_expanded_loop_offset (loop_opcode);
8119*3d8817e4Smiod 
8120*3d8817e4Smiod       /* In an ideal world, which is what we are shooting for here,
8121*3d8817e4Smiod 	 we wouldn't need to use any NOPs immediately prior to the
8122*3d8817e4Smiod 	 LOOP instruction.  If this approach fails, relax_frag_loop_align
8123*3d8817e4Smiod 	 will call get_noop_aligned_address.  */
8124*3d8817e4Smiod       target_address =
8125*3d8817e4Smiod 	address + loop_insn_offset + xg_get_single_size (loop_opcode);
8126*3d8817e4Smiod       align_power = get_text_align_power (target_size),
8127*3d8817e4Smiod       opt_diff = get_text_align_fill_size (target_address, align_power,
8128*3d8817e4Smiod 					   target_size, FALSE, FALSE);
8129*3d8817e4Smiod 
8130*3d8817e4Smiod       *max_diff = xtensa_fetch_width
8131*3d8817e4Smiod 	- ((target_address + opt_diff) % xtensa_fetch_width)
8132*3d8817e4Smiod 	- target_size + opt_diff;
8133*3d8817e4Smiod       assert (*max_diff >= opt_diff);
8134*3d8817e4Smiod       return opt_diff;
8135*3d8817e4Smiod 
8136*3d8817e4Smiod     default:
8137*3d8817e4Smiod       break;
8138*3d8817e4Smiod     }
8139*3d8817e4Smiod   assert (0);
8140*3d8817e4Smiod   return 0;
8141*3d8817e4Smiod }
8142*3d8817e4Smiod 
8143*3d8817e4Smiod 
8144*3d8817e4Smiod /* md_relax_frag Hook and Helper Functions.  */
8145*3d8817e4Smiod 
8146*3d8817e4Smiod static long relax_frag_loop_align (fragS *, long);
8147*3d8817e4Smiod static long relax_frag_for_align (fragS *, long);
8148*3d8817e4Smiod static long relax_frag_immed
8149*3d8817e4Smiod   (segT, fragS *, long, int, xtensa_format, int, int *, bfd_boolean);
8150*3d8817e4Smiod 
8151*3d8817e4Smiod 
8152*3d8817e4Smiod /* Return the number of bytes added to this fragment, given that the
8153*3d8817e4Smiod    input has been stretched already by "stretch".  */
8154*3d8817e4Smiod 
8155*3d8817e4Smiod long
xtensa_relax_frag(fragS * fragP,long stretch,int * stretched_p)8156*3d8817e4Smiod xtensa_relax_frag (fragS *fragP, long stretch, int *stretched_p)
8157*3d8817e4Smiod {
8158*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
8159*3d8817e4Smiod   int unreported = fragP->tc_frag_data.unreported_expansion;
8160*3d8817e4Smiod   long new_stretch = 0;
8161*3d8817e4Smiod   char *file_name;
8162*3d8817e4Smiod   unsigned line;
8163*3d8817e4Smiod   int lit_size;
8164*3d8817e4Smiod   static xtensa_insnbuf vbuf = NULL;
8165*3d8817e4Smiod   int slot, num_slots;
8166*3d8817e4Smiod   xtensa_format fmt;
8167*3d8817e4Smiod 
8168*3d8817e4Smiod   as_where (&file_name, &line);
8169*3d8817e4Smiod   new_logical_line (fragP->fr_file, fragP->fr_line);
8170*3d8817e4Smiod 
8171*3d8817e4Smiod   fragP->tc_frag_data.unreported_expansion = 0;
8172*3d8817e4Smiod 
8173*3d8817e4Smiod   switch (fragP->fr_subtype)
8174*3d8817e4Smiod     {
8175*3d8817e4Smiod     case RELAX_ALIGN_NEXT_OPCODE:
8176*3d8817e4Smiod       /* Always convert.  */
8177*3d8817e4Smiod       if (fragP->tc_frag_data.relax_seen)
8178*3d8817e4Smiod 	new_stretch = relax_frag_loop_align (fragP, stretch);
8179*3d8817e4Smiod       break;
8180*3d8817e4Smiod 
8181*3d8817e4Smiod     case RELAX_LOOP_END:
8182*3d8817e4Smiod       /* Do nothing.  */
8183*3d8817e4Smiod       break;
8184*3d8817e4Smiod 
8185*3d8817e4Smiod     case RELAX_LOOP_END_ADD_NOP:
8186*3d8817e4Smiod       /* Add a NOP and switch to .fill 0.  */
8187*3d8817e4Smiod       new_stretch = relax_frag_add_nop (fragP);
8188*3d8817e4Smiod       frag_wane (fragP);
8189*3d8817e4Smiod       break;
8190*3d8817e4Smiod 
8191*3d8817e4Smiod     case RELAX_DESIRE_ALIGN:
8192*3d8817e4Smiod       /* Do nothing. The narrowing before this frag will either align
8193*3d8817e4Smiod          it or not.  */
8194*3d8817e4Smiod       break;
8195*3d8817e4Smiod 
8196*3d8817e4Smiod     case RELAX_LITERAL:
8197*3d8817e4Smiod     case RELAX_LITERAL_FINAL:
8198*3d8817e4Smiod       return 0;
8199*3d8817e4Smiod 
8200*3d8817e4Smiod     case RELAX_LITERAL_NR:
8201*3d8817e4Smiod       lit_size = 4;
8202*3d8817e4Smiod       fragP->fr_subtype = RELAX_LITERAL_FINAL;
8203*3d8817e4Smiod       assert (unreported == lit_size);
8204*3d8817e4Smiod       memset (&fragP->fr_literal[fragP->fr_fix], 0, 4);
8205*3d8817e4Smiod       fragP->fr_var -= lit_size;
8206*3d8817e4Smiod       fragP->fr_fix += lit_size;
8207*3d8817e4Smiod       new_stretch = 4;
8208*3d8817e4Smiod       break;
8209*3d8817e4Smiod 
8210*3d8817e4Smiod     case RELAX_SLOTS:
8211*3d8817e4Smiod       if (vbuf == NULL)
8212*3d8817e4Smiod 	vbuf = xtensa_insnbuf_alloc (isa);
8213*3d8817e4Smiod 
8214*3d8817e4Smiod       xtensa_insnbuf_from_chars
8215*3d8817e4Smiod 	(isa, vbuf, (unsigned char *) fragP->fr_opcode, 0);
8216*3d8817e4Smiod       fmt = xtensa_format_decode (isa, vbuf);
8217*3d8817e4Smiod       num_slots = xtensa_format_num_slots (isa, fmt);
8218*3d8817e4Smiod 
8219*3d8817e4Smiod       for (slot = 0; slot < num_slots; slot++)
8220*3d8817e4Smiod 	{
8221*3d8817e4Smiod 	  switch (fragP->tc_frag_data.slot_subtypes[slot])
8222*3d8817e4Smiod 	    {
8223*3d8817e4Smiod 	    case RELAX_NARROW:
8224*3d8817e4Smiod 	      if (fragP->tc_frag_data.relax_seen)
8225*3d8817e4Smiod 		new_stretch += relax_frag_for_align (fragP, stretch);
8226*3d8817e4Smiod 	      break;
8227*3d8817e4Smiod 
8228*3d8817e4Smiod 	    case RELAX_IMMED:
8229*3d8817e4Smiod 	    case RELAX_IMMED_STEP1:
8230*3d8817e4Smiod 	    case RELAX_IMMED_STEP2:
8231*3d8817e4Smiod 	      /* Place the immediate.  */
8232*3d8817e4Smiod 	      new_stretch += relax_frag_immed
8233*3d8817e4Smiod 		(now_seg, fragP, stretch,
8234*3d8817e4Smiod 		 fragP->tc_frag_data.slot_subtypes[slot] - RELAX_IMMED,
8235*3d8817e4Smiod 		 fmt, slot, stretched_p, FALSE);
8236*3d8817e4Smiod 	      break;
8237*3d8817e4Smiod 
8238*3d8817e4Smiod 	    default:
8239*3d8817e4Smiod 	      /* This is OK; see the note in xg_assemble_vliw_tokens.  */
8240*3d8817e4Smiod 	      break;
8241*3d8817e4Smiod 	    }
8242*3d8817e4Smiod 	}
8243*3d8817e4Smiod       break;
8244*3d8817e4Smiod 
8245*3d8817e4Smiod     case RELAX_LITERAL_POOL_BEGIN:
8246*3d8817e4Smiod     case RELAX_LITERAL_POOL_END:
8247*3d8817e4Smiod     case RELAX_MAYBE_UNREACHABLE:
8248*3d8817e4Smiod     case RELAX_MAYBE_DESIRE_ALIGN:
8249*3d8817e4Smiod       /* No relaxation required.  */
8250*3d8817e4Smiod       break;
8251*3d8817e4Smiod 
8252*3d8817e4Smiod     case RELAX_FILL_NOP:
8253*3d8817e4Smiod     case RELAX_UNREACHABLE:
8254*3d8817e4Smiod       if (fragP->tc_frag_data.relax_seen)
8255*3d8817e4Smiod 	new_stretch += relax_frag_for_align (fragP, stretch);
8256*3d8817e4Smiod       break;
8257*3d8817e4Smiod 
8258*3d8817e4Smiod     default:
8259*3d8817e4Smiod       as_bad (_("bad relaxation state"));
8260*3d8817e4Smiod     }
8261*3d8817e4Smiod 
8262*3d8817e4Smiod   /* Tell gas we need another relaxation pass.  */
8263*3d8817e4Smiod   if (! fragP->tc_frag_data.relax_seen)
8264*3d8817e4Smiod     {
8265*3d8817e4Smiod       fragP->tc_frag_data.relax_seen = TRUE;
8266*3d8817e4Smiod       *stretched_p = 1;
8267*3d8817e4Smiod     }
8268*3d8817e4Smiod 
8269*3d8817e4Smiod   new_logical_line (file_name, line);
8270*3d8817e4Smiod   return new_stretch;
8271*3d8817e4Smiod }
8272*3d8817e4Smiod 
8273*3d8817e4Smiod 
8274*3d8817e4Smiod static long
relax_frag_loop_align(fragS * fragP,long stretch)8275*3d8817e4Smiod relax_frag_loop_align (fragS *fragP, long stretch)
8276*3d8817e4Smiod {
8277*3d8817e4Smiod   addressT old_address, old_next_address, old_size;
8278*3d8817e4Smiod   addressT new_address, new_next_address, new_size;
8279*3d8817e4Smiod   addressT growth;
8280*3d8817e4Smiod 
8281*3d8817e4Smiod   /* All the frags with relax_frag_for_alignment prior to this one in the
8282*3d8817e4Smiod      section have been done, hopefully eliminating the need for a NOP here.
8283*3d8817e4Smiod      But, this will put it in if necessary.  */
8284*3d8817e4Smiod 
8285*3d8817e4Smiod   /* Calculate the old address of this fragment and the next fragment.  */
8286*3d8817e4Smiod   old_address = fragP->fr_address - stretch;
8287*3d8817e4Smiod   old_next_address = (fragP->fr_address - stretch + fragP->fr_fix +
8288*3d8817e4Smiod 		      fragP->tc_frag_data.text_expansion[0]);
8289*3d8817e4Smiod   old_size = old_next_address - old_address;
8290*3d8817e4Smiod 
8291*3d8817e4Smiod   /* Calculate the new address of this fragment and the next fragment.  */
8292*3d8817e4Smiod   new_address = fragP->fr_address;
8293*3d8817e4Smiod   new_next_address =
8294*3d8817e4Smiod     get_noop_aligned_address (fragP, fragP->fr_address + fragP->fr_fix);
8295*3d8817e4Smiod   new_size = new_next_address - new_address;
8296*3d8817e4Smiod 
8297*3d8817e4Smiod   growth = new_size - old_size;
8298*3d8817e4Smiod 
8299*3d8817e4Smiod   /* Fix up the text_expansion field and return the new growth.  */
8300*3d8817e4Smiod   fragP->tc_frag_data.text_expansion[0] += growth;
8301*3d8817e4Smiod   return growth;
8302*3d8817e4Smiod }
8303*3d8817e4Smiod 
8304*3d8817e4Smiod 
8305*3d8817e4Smiod /* Add a NOP instruction.  */
8306*3d8817e4Smiod 
8307*3d8817e4Smiod static long
relax_frag_add_nop(fragS * fragP)8308*3d8817e4Smiod relax_frag_add_nop (fragS *fragP)
8309*3d8817e4Smiod {
8310*3d8817e4Smiod   char *nop_buf = fragP->fr_literal + fragP->fr_fix;
8311*3d8817e4Smiod   int length = fragP->tc_frag_data.is_no_density ? 3 : 2;
8312*3d8817e4Smiod   assemble_nop (length, nop_buf);
8313*3d8817e4Smiod   fragP->tc_frag_data.is_insn = TRUE;
8314*3d8817e4Smiod 
8315*3d8817e4Smiod   if (fragP->fr_var < length)
8316*3d8817e4Smiod     {
8317*3d8817e4Smiod       as_fatal (_("fr_var (%ld) < length (%d)"), (long) fragP->fr_var, length);
8318*3d8817e4Smiod       return 0;
8319*3d8817e4Smiod     }
8320*3d8817e4Smiod 
8321*3d8817e4Smiod   fragP->fr_fix += length;
8322*3d8817e4Smiod   fragP->fr_var -= length;
8323*3d8817e4Smiod   return length;
8324*3d8817e4Smiod }
8325*3d8817e4Smiod 
8326*3d8817e4Smiod 
8327*3d8817e4Smiod static long future_alignment_required (fragS *, long);
8328*3d8817e4Smiod 
8329*3d8817e4Smiod static long
relax_frag_for_align(fragS * fragP,long stretch)8330*3d8817e4Smiod relax_frag_for_align (fragS *fragP, long stretch)
8331*3d8817e4Smiod {
8332*3d8817e4Smiod   /* Overview of the relaxation procedure for alignment:
8333*3d8817e4Smiod      We can widen with NOPs or by widening instructions or by filling
8334*3d8817e4Smiod      bytes after jump instructions.  Find the opportune places and widen
8335*3d8817e4Smiod      them if necessary.  */
8336*3d8817e4Smiod 
8337*3d8817e4Smiod   long stretch_me;
8338*3d8817e4Smiod   long diff;
8339*3d8817e4Smiod 
8340*3d8817e4Smiod   assert (fragP->fr_subtype == RELAX_FILL_NOP
8341*3d8817e4Smiod 	  || fragP->fr_subtype == RELAX_UNREACHABLE
8342*3d8817e4Smiod 	  || (fragP->fr_subtype == RELAX_SLOTS
8343*3d8817e4Smiod 	      && fragP->tc_frag_data.slot_subtypes[0] == RELAX_NARROW));
8344*3d8817e4Smiod 
8345*3d8817e4Smiod   stretch_me = future_alignment_required (fragP, stretch);
8346*3d8817e4Smiod   diff = stretch_me - fragP->tc_frag_data.text_expansion[0];
8347*3d8817e4Smiod   if (diff == 0)
8348*3d8817e4Smiod     return 0;
8349*3d8817e4Smiod 
8350*3d8817e4Smiod   if (diff < 0)
8351*3d8817e4Smiod     {
8352*3d8817e4Smiod       /* We expanded on a previous pass.  Can we shrink now?  */
8353*3d8817e4Smiod       long shrink = fragP->tc_frag_data.text_expansion[0] - stretch_me;
8354*3d8817e4Smiod       if (shrink <= stretch && stretch > 0)
8355*3d8817e4Smiod 	{
8356*3d8817e4Smiod 	  fragP->tc_frag_data.text_expansion[0] = stretch_me;
8357*3d8817e4Smiod 	  return -shrink;
8358*3d8817e4Smiod 	}
8359*3d8817e4Smiod       return 0;
8360*3d8817e4Smiod     }
8361*3d8817e4Smiod 
8362*3d8817e4Smiod   /* Below here, diff > 0.  */
8363*3d8817e4Smiod   fragP->tc_frag_data.text_expansion[0] = stretch_me;
8364*3d8817e4Smiod 
8365*3d8817e4Smiod   return diff;
8366*3d8817e4Smiod }
8367*3d8817e4Smiod 
8368*3d8817e4Smiod 
8369*3d8817e4Smiod /* Return the address of the next frag that should be aligned.
8370*3d8817e4Smiod 
8371*3d8817e4Smiod    By "address" we mean the address it _would_ be at if there
8372*3d8817e4Smiod    is no action taken to align it between here and the target frag.
8373*3d8817e4Smiod    In other words, if no narrows and no fill nops are used between
8374*3d8817e4Smiod    here and the frag to align, _even_if_ some of the frags we use
8375*3d8817e4Smiod    to align targets have already expanded on a previous relaxation
8376*3d8817e4Smiod    pass.
8377*3d8817e4Smiod 
8378*3d8817e4Smiod    Also, count each frag that may be used to help align the target.
8379*3d8817e4Smiod 
8380*3d8817e4Smiod    Return 0 if there are no frags left in the chain that need to be
8381*3d8817e4Smiod    aligned.  */
8382*3d8817e4Smiod 
8383*3d8817e4Smiod static addressT
find_address_of_next_align_frag(fragS ** fragPP,int * wide_nops,int * narrow_nops,int * widens,bfd_boolean * paddable)8384*3d8817e4Smiod find_address_of_next_align_frag (fragS **fragPP,
8385*3d8817e4Smiod 				 int *wide_nops,
8386*3d8817e4Smiod 				 int *narrow_nops,
8387*3d8817e4Smiod 				 int *widens,
8388*3d8817e4Smiod 				 bfd_boolean *paddable)
8389*3d8817e4Smiod {
8390*3d8817e4Smiod   fragS *fragP = *fragPP;
8391*3d8817e4Smiod   addressT address = fragP->fr_address;
8392*3d8817e4Smiod 
8393*3d8817e4Smiod   /* Do not reset the counts to 0.  */
8394*3d8817e4Smiod 
8395*3d8817e4Smiod   while (fragP)
8396*3d8817e4Smiod     {
8397*3d8817e4Smiod       /* Limit this to a small search.  */
8398*3d8817e4Smiod       if (*widens >= (int) xtensa_fetch_width)
8399*3d8817e4Smiod 	{
8400*3d8817e4Smiod 	  *fragPP = fragP;
8401*3d8817e4Smiod 	  return 0;
8402*3d8817e4Smiod 	}
8403*3d8817e4Smiod       address += fragP->fr_fix;
8404*3d8817e4Smiod 
8405*3d8817e4Smiod       if (fragP->fr_type == rs_fill)
8406*3d8817e4Smiod 	address += fragP->fr_offset * fragP->fr_var;
8407*3d8817e4Smiod       else if (fragP->fr_type == rs_machine_dependent)
8408*3d8817e4Smiod 	{
8409*3d8817e4Smiod 	  switch (fragP->fr_subtype)
8410*3d8817e4Smiod 	    {
8411*3d8817e4Smiod 	    case RELAX_UNREACHABLE:
8412*3d8817e4Smiod 	      *paddable = TRUE;
8413*3d8817e4Smiod 	      break;
8414*3d8817e4Smiod 
8415*3d8817e4Smiod 	    case RELAX_FILL_NOP:
8416*3d8817e4Smiod 	      (*wide_nops)++;
8417*3d8817e4Smiod 	      if (!fragP->tc_frag_data.is_no_density)
8418*3d8817e4Smiod 		(*narrow_nops)++;
8419*3d8817e4Smiod 	      break;
8420*3d8817e4Smiod 
8421*3d8817e4Smiod 	    case RELAX_SLOTS:
8422*3d8817e4Smiod 	      if (fragP->tc_frag_data.slot_subtypes[0] == RELAX_NARROW)
8423*3d8817e4Smiod 		{
8424*3d8817e4Smiod 		  (*widens)++;
8425*3d8817e4Smiod 		  break;
8426*3d8817e4Smiod 		}
8427*3d8817e4Smiod 	      address += total_frag_text_expansion (fragP);;
8428*3d8817e4Smiod 	      break;
8429*3d8817e4Smiod 
8430*3d8817e4Smiod 	    case RELAX_IMMED:
8431*3d8817e4Smiod 	      address += fragP->tc_frag_data.text_expansion[0];
8432*3d8817e4Smiod 	      break;
8433*3d8817e4Smiod 
8434*3d8817e4Smiod 	    case RELAX_ALIGN_NEXT_OPCODE:
8435*3d8817e4Smiod 	    case RELAX_DESIRE_ALIGN:
8436*3d8817e4Smiod 	      *fragPP = fragP;
8437*3d8817e4Smiod 	      return address;
8438*3d8817e4Smiod 
8439*3d8817e4Smiod 	    case RELAX_MAYBE_UNREACHABLE:
8440*3d8817e4Smiod 	    case RELAX_MAYBE_DESIRE_ALIGN:
8441*3d8817e4Smiod 	      /* Do nothing.  */
8442*3d8817e4Smiod 	      break;
8443*3d8817e4Smiod 
8444*3d8817e4Smiod 	    default:
8445*3d8817e4Smiod 	      /* Just punt if we don't know the type.  */
8446*3d8817e4Smiod 	      *fragPP = fragP;
8447*3d8817e4Smiod 	      return 0;
8448*3d8817e4Smiod 	    }
8449*3d8817e4Smiod 	}
8450*3d8817e4Smiod       else
8451*3d8817e4Smiod 	{
8452*3d8817e4Smiod 	  /* Just punt if we don't know the type.  */
8453*3d8817e4Smiod 	  *fragPP = fragP;
8454*3d8817e4Smiod 	  return 0;
8455*3d8817e4Smiod 	}
8456*3d8817e4Smiod       fragP = fragP->fr_next;
8457*3d8817e4Smiod     }
8458*3d8817e4Smiod 
8459*3d8817e4Smiod   *fragPP = fragP;
8460*3d8817e4Smiod   return 0;
8461*3d8817e4Smiod }
8462*3d8817e4Smiod 
8463*3d8817e4Smiod 
8464*3d8817e4Smiod static long bytes_to_stretch (fragS *, int, int, int, int);
8465*3d8817e4Smiod 
8466*3d8817e4Smiod static long
future_alignment_required(fragS * fragP,long stretch ATTRIBUTE_UNUSED)8467*3d8817e4Smiod future_alignment_required (fragS *fragP, long stretch ATTRIBUTE_UNUSED)
8468*3d8817e4Smiod {
8469*3d8817e4Smiod   fragS *this_frag = fragP;
8470*3d8817e4Smiod   long address;
8471*3d8817e4Smiod   int num_widens = 0;
8472*3d8817e4Smiod   int wide_nops = 0;
8473*3d8817e4Smiod   int narrow_nops = 0;
8474*3d8817e4Smiod   bfd_boolean paddable = FALSE;
8475*3d8817e4Smiod   offsetT local_opt_diff;
8476*3d8817e4Smiod   offsetT opt_diff;
8477*3d8817e4Smiod   offsetT max_diff;
8478*3d8817e4Smiod   int stretch_amount = 0;
8479*3d8817e4Smiod   int local_stretch_amount;
8480*3d8817e4Smiod   int global_stretch_amount;
8481*3d8817e4Smiod 
8482*3d8817e4Smiod   address = find_address_of_next_align_frag
8483*3d8817e4Smiod     (&fragP, &wide_nops, &narrow_nops, &num_widens, &paddable);
8484*3d8817e4Smiod 
8485*3d8817e4Smiod   if (!address)
8486*3d8817e4Smiod     {
8487*3d8817e4Smiod       if (this_frag->tc_frag_data.is_aligning_branch)
8488*3d8817e4Smiod 	this_frag->tc_frag_data.slot_subtypes[0] = RELAX_IMMED;
8489*3d8817e4Smiod       else
8490*3d8817e4Smiod 	frag_wane (this_frag);
8491*3d8817e4Smiod     }
8492*3d8817e4Smiod   else
8493*3d8817e4Smiod     {
8494*3d8817e4Smiod       local_opt_diff = get_aligned_diff (fragP, address, &max_diff);
8495*3d8817e4Smiod       opt_diff = local_opt_diff;
8496*3d8817e4Smiod       assert (opt_diff >= 0);
8497*3d8817e4Smiod       assert (max_diff >= opt_diff);
8498*3d8817e4Smiod       if (max_diff == 0)
8499*3d8817e4Smiod 	return 0;
8500*3d8817e4Smiod 
8501*3d8817e4Smiod       if (fragP)
8502*3d8817e4Smiod 	fragP = fragP->fr_next;
8503*3d8817e4Smiod 
8504*3d8817e4Smiod       while (fragP && opt_diff < max_diff && address)
8505*3d8817e4Smiod 	{
8506*3d8817e4Smiod 	  /* We only use these to determine if we can exit early
8507*3d8817e4Smiod 	     because there will be plenty of ways to align future
8508*3d8817e4Smiod 	     align frags.  */
8509*3d8817e4Smiod 	  int glob_widens = 0;
8510*3d8817e4Smiod 	  int dnn = 0;
8511*3d8817e4Smiod 	  int dw = 0;
8512*3d8817e4Smiod 	  bfd_boolean glob_pad = 0;
8513*3d8817e4Smiod 	  address = find_address_of_next_align_frag
8514*3d8817e4Smiod 	    (&fragP, &glob_widens, &dnn, &dw, &glob_pad);
8515*3d8817e4Smiod 	  /* If there is a padable portion, then skip.  */
8516*3d8817e4Smiod 	  if (glob_pad || glob_widens >= (1 << branch_align_power (now_seg)))
8517*3d8817e4Smiod 	    address = 0;
8518*3d8817e4Smiod 
8519*3d8817e4Smiod 	  if (address)
8520*3d8817e4Smiod 	    {
8521*3d8817e4Smiod 	      offsetT next_m_diff;
8522*3d8817e4Smiod 	      offsetT next_o_diff;
8523*3d8817e4Smiod 
8524*3d8817e4Smiod 	      /* Downrange frags haven't had stretch added to them yet.  */
8525*3d8817e4Smiod 	      address += stretch;
8526*3d8817e4Smiod 
8527*3d8817e4Smiod 	      /* The address also includes any text expansion from this
8528*3d8817e4Smiod 		 frag in a previous pass, but we don't want that.  */
8529*3d8817e4Smiod 	      address -= this_frag->tc_frag_data.text_expansion[0];
8530*3d8817e4Smiod 
8531*3d8817e4Smiod 	      /* Assume we are going to move at least opt_diff.  In
8532*3d8817e4Smiod 		 reality, we might not be able to, but assuming that
8533*3d8817e4Smiod 		 we will helps catch cases where moving opt_diff pushes
8534*3d8817e4Smiod 		 the next target from aligned to unaligned.  */
8535*3d8817e4Smiod 	      address += opt_diff;
8536*3d8817e4Smiod 
8537*3d8817e4Smiod 	      next_o_diff = get_aligned_diff (fragP, address, &next_m_diff);
8538*3d8817e4Smiod 
8539*3d8817e4Smiod 	      /* Now cleanup for the adjustments to address.  */
8540*3d8817e4Smiod 	      next_o_diff += opt_diff;
8541*3d8817e4Smiod 	      next_m_diff += opt_diff;
8542*3d8817e4Smiod 	      if (next_o_diff <= max_diff && next_o_diff > opt_diff)
8543*3d8817e4Smiod 		opt_diff = next_o_diff;
8544*3d8817e4Smiod 	      if (next_m_diff < max_diff)
8545*3d8817e4Smiod 		max_diff = next_m_diff;
8546*3d8817e4Smiod 	      fragP = fragP->fr_next;
8547*3d8817e4Smiod 	    }
8548*3d8817e4Smiod 	}
8549*3d8817e4Smiod 
8550*3d8817e4Smiod       /* If there are enough wideners in between, do it.  */
8551*3d8817e4Smiod       if (paddable)
8552*3d8817e4Smiod 	{
8553*3d8817e4Smiod 	  if (this_frag->fr_subtype == RELAX_UNREACHABLE)
8554*3d8817e4Smiod 	    {
8555*3d8817e4Smiod 	      assert (opt_diff <= UNREACHABLE_MAX_WIDTH);
8556*3d8817e4Smiod 	      return opt_diff;
8557*3d8817e4Smiod 	    }
8558*3d8817e4Smiod 	  return 0;
8559*3d8817e4Smiod 	}
8560*3d8817e4Smiod       local_stretch_amount
8561*3d8817e4Smiod 	= bytes_to_stretch (this_frag, wide_nops, narrow_nops,
8562*3d8817e4Smiod 			    num_widens, local_opt_diff);
8563*3d8817e4Smiod       global_stretch_amount
8564*3d8817e4Smiod 	= bytes_to_stretch (this_frag, wide_nops, narrow_nops,
8565*3d8817e4Smiod 			    num_widens, opt_diff);
8566*3d8817e4Smiod       /* If the condition below is true, then the frag couldn't
8567*3d8817e4Smiod 	 stretch the correct amount for the global case, so we just
8568*3d8817e4Smiod 	 optimize locally.  We'll rely on the subsequent frags to get
8569*3d8817e4Smiod 	 the correct alignment in the global case.  */
8570*3d8817e4Smiod       if (global_stretch_amount < local_stretch_amount)
8571*3d8817e4Smiod 	stretch_amount = local_stretch_amount;
8572*3d8817e4Smiod       else
8573*3d8817e4Smiod 	stretch_amount = global_stretch_amount;
8574*3d8817e4Smiod 
8575*3d8817e4Smiod       if (this_frag->fr_subtype == RELAX_SLOTS
8576*3d8817e4Smiod 	  && this_frag->tc_frag_data.slot_subtypes[0] == RELAX_NARROW)
8577*3d8817e4Smiod 	assert (stretch_amount <= 1);
8578*3d8817e4Smiod       else if (this_frag->fr_subtype == RELAX_FILL_NOP)
8579*3d8817e4Smiod 	{
8580*3d8817e4Smiod 	  if (this_frag->tc_frag_data.is_no_density)
8581*3d8817e4Smiod 	    assert (stretch_amount == 3 || stretch_amount == 0);
8582*3d8817e4Smiod 	  else
8583*3d8817e4Smiod 	    assert (stretch_amount <= 3);
8584*3d8817e4Smiod 	}
8585*3d8817e4Smiod     }
8586*3d8817e4Smiod   return stretch_amount;
8587*3d8817e4Smiod }
8588*3d8817e4Smiod 
8589*3d8817e4Smiod 
8590*3d8817e4Smiod /* The idea: widen everything you can to get a target or loop aligned,
8591*3d8817e4Smiod    then start using NOPs.
8592*3d8817e4Smiod 
8593*3d8817e4Smiod    When we must have a NOP, here is a table of how we decide
8594*3d8817e4Smiod    (so you don't have to fight through the control flow below):
8595*3d8817e4Smiod 
8596*3d8817e4Smiod    wide_nops   = the number of wide NOPs available for aligning
8597*3d8817e4Smiod    narrow_nops = the number of narrow NOPs available for aligning
8598*3d8817e4Smiod 		 (a subset of wide_nops)
8599*3d8817e4Smiod    widens      = the number of narrow instructions that should be widened
8600*3d8817e4Smiod 
8601*3d8817e4Smiod    Desired   wide   narrow
8602*3d8817e4Smiod    Diff      nop    nop      widens
8603*3d8817e4Smiod    1           0      0         1
8604*3d8817e4Smiod    2           0      1         0
8605*3d8817e4Smiod    3a          1      0         0
8606*3d8817e4Smiod     b          0      1         1 (case 3a makes this case unnecessary)
8607*3d8817e4Smiod    4a          1      0         1
8608*3d8817e4Smiod     b          0      2         0
8609*3d8817e4Smiod     c          0      1         2 (case 4a makes this case unnecessary)
8610*3d8817e4Smiod    5a          1      0         2
8611*3d8817e4Smiod     b          1      1         0
8612*3d8817e4Smiod     c          0      2         1 (case 5b makes this case unnecessary)
8613*3d8817e4Smiod    6a          2      0         0
8614*3d8817e4Smiod     b          1      0         3
8615*3d8817e4Smiod     c          0      1         4 (case 6b makes this case unneccesary)
8616*3d8817e4Smiod     d          1      1         1 (case 6a makes this case unnecessary)
8617*3d8817e4Smiod     e          0      2         2 (case 6a makes this case unnecessary)
8618*3d8817e4Smiod     f          0      3         0 (case 6a makes this case unnecessary)
8619*3d8817e4Smiod    7a          1      0         4
8620*3d8817e4Smiod     b          2      0         1
8621*3d8817e4Smiod     c          1      1         2 (case 7b makes this case unnecessary)
8622*3d8817e4Smiod     d          0      1         5 (case 7a makes this case unnecessary)
8623*3d8817e4Smiod     e          0      2         3 (case 7b makes this case unnecessary)
8624*3d8817e4Smiod     f          0      3         1 (case 7b makes this case unnecessary)
8625*3d8817e4Smiod     g          1      2         1 (case 7b makes this case unnecessary)
8626*3d8817e4Smiod */
8627*3d8817e4Smiod 
8628*3d8817e4Smiod static long
bytes_to_stretch(fragS * this_frag,int wide_nops,int narrow_nops,int num_widens,int desired_diff)8629*3d8817e4Smiod bytes_to_stretch (fragS *this_frag,
8630*3d8817e4Smiod 		  int wide_nops,
8631*3d8817e4Smiod 		  int narrow_nops,
8632*3d8817e4Smiod 		  int num_widens,
8633*3d8817e4Smiod 		  int desired_diff)
8634*3d8817e4Smiod {
8635*3d8817e4Smiod   int bytes_short = desired_diff - num_widens;
8636*3d8817e4Smiod 
8637*3d8817e4Smiod   assert (desired_diff >= 0 && desired_diff < 8);
8638*3d8817e4Smiod   if (desired_diff == 0)
8639*3d8817e4Smiod     return 0;
8640*3d8817e4Smiod 
8641*3d8817e4Smiod   assert (wide_nops > 0 || num_widens > 0);
8642*3d8817e4Smiod 
8643*3d8817e4Smiod   /* Always prefer widening to NOP-filling.  */
8644*3d8817e4Smiod   if (bytes_short < 0)
8645*3d8817e4Smiod     {
8646*3d8817e4Smiod       /* There are enough RELAX_NARROW frags after this one
8647*3d8817e4Smiod 	 to align the target without widening this frag in any way.  */
8648*3d8817e4Smiod       return 0;
8649*3d8817e4Smiod     }
8650*3d8817e4Smiod 
8651*3d8817e4Smiod   if (bytes_short == 0)
8652*3d8817e4Smiod     {
8653*3d8817e4Smiod       /* Widen every narrow between here and the align target
8654*3d8817e4Smiod 	 and the align target will be properly aligned.  */
8655*3d8817e4Smiod       if (this_frag->fr_subtype == RELAX_FILL_NOP)
8656*3d8817e4Smiod 	return 0;
8657*3d8817e4Smiod       else
8658*3d8817e4Smiod 	return 1;
8659*3d8817e4Smiod     }
8660*3d8817e4Smiod 
8661*3d8817e4Smiod   /* From here we will need at least one NOP to get an alignment.
8662*3d8817e4Smiod      However, we may not be able to align at all, in which case,
8663*3d8817e4Smiod      don't widen.  */
8664*3d8817e4Smiod   if (this_frag->fr_subtype == RELAX_FILL_NOP)
8665*3d8817e4Smiod     {
8666*3d8817e4Smiod       switch (desired_diff)
8667*3d8817e4Smiod 	{
8668*3d8817e4Smiod 	case 1:
8669*3d8817e4Smiod 	  return 0;
8670*3d8817e4Smiod 	case 2:
8671*3d8817e4Smiod 	  if (!this_frag->tc_frag_data.is_no_density && narrow_nops == 1)
8672*3d8817e4Smiod 	    return 2; /* case 2 */
8673*3d8817e4Smiod 	  return 0;
8674*3d8817e4Smiod 	case 3:
8675*3d8817e4Smiod 	  if (wide_nops > 1)
8676*3d8817e4Smiod 	    return 0;
8677*3d8817e4Smiod 	  else
8678*3d8817e4Smiod 	    return 3; /* case 3a */
8679*3d8817e4Smiod 	case 4:
8680*3d8817e4Smiod 	  if (num_widens >= 1 && wide_nops == 1)
8681*3d8817e4Smiod 	    return 3; /* case 4a */
8682*3d8817e4Smiod 	  if (!this_frag->tc_frag_data.is_no_density && narrow_nops == 2)
8683*3d8817e4Smiod 	    return 2; /* case 4b */
8684*3d8817e4Smiod 	  return 0;
8685*3d8817e4Smiod 	case 5:
8686*3d8817e4Smiod 	  if (num_widens >= 2 && wide_nops == 1)
8687*3d8817e4Smiod 	    return 3; /* case 5a */
8688*3d8817e4Smiod 	  /* We will need two nops.  Are there enough nops
8689*3d8817e4Smiod 	     between here and the align target?  */
8690*3d8817e4Smiod 	  if (wide_nops < 2 || narrow_nops == 0)
8691*3d8817e4Smiod 	    return 0;
8692*3d8817e4Smiod 	  /* Are there other nops closer that can serve instead?  */
8693*3d8817e4Smiod 	  if (wide_nops > 2 && narrow_nops > 1)
8694*3d8817e4Smiod 	    return 0;
8695*3d8817e4Smiod 	  /* Take the density one first, because there might not be
8696*3d8817e4Smiod 	     another density one available.  */
8697*3d8817e4Smiod 	  if (!this_frag->tc_frag_data.is_no_density)
8698*3d8817e4Smiod 	    return 2; /* case 5b narrow */
8699*3d8817e4Smiod 	  else
8700*3d8817e4Smiod 	    return 3; /* case 5b wide */
8701*3d8817e4Smiod 	  return 0;
8702*3d8817e4Smiod 	case 6:
8703*3d8817e4Smiod 	  if (wide_nops == 2)
8704*3d8817e4Smiod 	    return 3; /* case 6a */
8705*3d8817e4Smiod 	  else if (num_widens >= 3 && wide_nops == 1)
8706*3d8817e4Smiod 	    return 3; /* case 6b */
8707*3d8817e4Smiod 	  return 0;
8708*3d8817e4Smiod 	case 7:
8709*3d8817e4Smiod 	  if (wide_nops == 1 && num_widens >= 4)
8710*3d8817e4Smiod 	    return 3; /* case 7a */
8711*3d8817e4Smiod 	  else if (wide_nops == 2 && num_widens >= 1)
8712*3d8817e4Smiod 	    return 3; /* case 7b */
8713*3d8817e4Smiod 	  return 0;
8714*3d8817e4Smiod 	default:
8715*3d8817e4Smiod 	  assert (0);
8716*3d8817e4Smiod 	}
8717*3d8817e4Smiod     }
8718*3d8817e4Smiod   else
8719*3d8817e4Smiod     {
8720*3d8817e4Smiod       /* We will need a NOP no matter what, but should we widen
8721*3d8817e4Smiod 	 this instruction to help?
8722*3d8817e4Smiod 
8723*3d8817e4Smiod 	 This is a RELAX_NARROW frag.  */
8724*3d8817e4Smiod       switch (desired_diff)
8725*3d8817e4Smiod 	{
8726*3d8817e4Smiod 	case 1:
8727*3d8817e4Smiod 	  assert (0);
8728*3d8817e4Smiod 	  return 0;
8729*3d8817e4Smiod 	case 2:
8730*3d8817e4Smiod 	case 3:
8731*3d8817e4Smiod 	  return 0;
8732*3d8817e4Smiod 	case 4:
8733*3d8817e4Smiod 	  if (wide_nops >= 1 && num_widens == 1)
8734*3d8817e4Smiod 	    return 1; /* case 4a */
8735*3d8817e4Smiod 	  return 0;
8736*3d8817e4Smiod 	case 5:
8737*3d8817e4Smiod 	  if (wide_nops >= 1 && num_widens == 2)
8738*3d8817e4Smiod 	    return 1; /* case 5a */
8739*3d8817e4Smiod 	  return 0;
8740*3d8817e4Smiod 	case 6:
8741*3d8817e4Smiod 	  if (wide_nops >= 2)
8742*3d8817e4Smiod 	    return 0; /* case 6a */
8743*3d8817e4Smiod 	  else if (wide_nops >= 1 && num_widens == 3)
8744*3d8817e4Smiod 	    return 1; /* case 6b */
8745*3d8817e4Smiod 	  return 0;
8746*3d8817e4Smiod 	case 7:
8747*3d8817e4Smiod 	  if (wide_nops >= 1 && num_widens == 4)
8748*3d8817e4Smiod 	    return 1; /* case 7a */
8749*3d8817e4Smiod 	  else if (wide_nops >= 2 && num_widens == 1)
8750*3d8817e4Smiod 	    return 1; /* case 7b */
8751*3d8817e4Smiod 	  return 0;
8752*3d8817e4Smiod 	default:
8753*3d8817e4Smiod 	  assert (0);
8754*3d8817e4Smiod 	  return 0;
8755*3d8817e4Smiod 	}
8756*3d8817e4Smiod     }
8757*3d8817e4Smiod   assert (0);
8758*3d8817e4Smiod   return 0;
8759*3d8817e4Smiod }
8760*3d8817e4Smiod 
8761*3d8817e4Smiod 
8762*3d8817e4Smiod static long
relax_frag_immed(segT segP,fragS * fragP,long stretch,int min_steps,xtensa_format fmt,int slot,int * stretched_p,bfd_boolean estimate_only)8763*3d8817e4Smiod relax_frag_immed (segT segP,
8764*3d8817e4Smiod 		  fragS *fragP,
8765*3d8817e4Smiod 		  long stretch,
8766*3d8817e4Smiod 		  int min_steps,
8767*3d8817e4Smiod 		  xtensa_format fmt,
8768*3d8817e4Smiod 		  int slot,
8769*3d8817e4Smiod 		  int *stretched_p,
8770*3d8817e4Smiod 		  bfd_boolean estimate_only)
8771*3d8817e4Smiod {
8772*3d8817e4Smiod   TInsn tinsn;
8773*3d8817e4Smiod   int old_size;
8774*3d8817e4Smiod   bfd_boolean negatable_branch = FALSE;
8775*3d8817e4Smiod   bfd_boolean branch_jmp_to_next = FALSE;
8776*3d8817e4Smiod   bfd_boolean wide_insn = FALSE;
8777*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
8778*3d8817e4Smiod   IStack istack;
8779*3d8817e4Smiod   offsetT frag_offset;
8780*3d8817e4Smiod   int num_steps;
8781*3d8817e4Smiod   fragS *lit_fragP;
8782*3d8817e4Smiod   int num_text_bytes, num_literal_bytes;
8783*3d8817e4Smiod   int literal_diff, total_text_diff, this_text_diff, first;
8784*3d8817e4Smiod 
8785*3d8817e4Smiod   assert (fragP->fr_opcode != NULL);
8786*3d8817e4Smiod 
8787*3d8817e4Smiod   xg_clear_vinsn (&cur_vinsn);
8788*3d8817e4Smiod   vinsn_from_chars (&cur_vinsn, fragP->fr_opcode);
8789*3d8817e4Smiod   if (cur_vinsn.num_slots > 1)
8790*3d8817e4Smiod     wide_insn = TRUE;
8791*3d8817e4Smiod 
8792*3d8817e4Smiod   tinsn = cur_vinsn.slots[slot];
8793*3d8817e4Smiod   tinsn_immed_from_frag (&tinsn, fragP, slot);
8794*3d8817e4Smiod 
8795*3d8817e4Smiod   if (estimate_only && xtensa_opcode_is_loop (isa, tinsn.opcode))
8796*3d8817e4Smiod     return 0;
8797*3d8817e4Smiod 
8798*3d8817e4Smiod   if (workaround_b_j_loop_end && ! fragP->tc_frag_data.is_no_transform)
8799*3d8817e4Smiod     branch_jmp_to_next = is_branch_jmp_to_next (&tinsn, fragP);
8800*3d8817e4Smiod 
8801*3d8817e4Smiod   negatable_branch = (xtensa_opcode_is_branch (isa, tinsn.opcode) == 1);
8802*3d8817e4Smiod 
8803*3d8817e4Smiod   old_size = xtensa_format_length (isa, fmt);
8804*3d8817e4Smiod 
8805*3d8817e4Smiod   /* Special case: replace a branch to the next instruction with a NOP.
8806*3d8817e4Smiod      This is required to work around a hardware bug in T1040.0 and also
8807*3d8817e4Smiod      serves as an optimization.  */
8808*3d8817e4Smiod 
8809*3d8817e4Smiod   if (branch_jmp_to_next
8810*3d8817e4Smiod       && ((old_size == 2) || (old_size == 3))
8811*3d8817e4Smiod       && !next_frag_is_loop_target (fragP))
8812*3d8817e4Smiod     return 0;
8813*3d8817e4Smiod 
8814*3d8817e4Smiod   /* Here is the fun stuff: Get the immediate field from this
8815*3d8817e4Smiod      instruction.  If it fits, we are done.  If not, find the next
8816*3d8817e4Smiod      instruction sequence that fits.  */
8817*3d8817e4Smiod 
8818*3d8817e4Smiod   frag_offset = fragP->fr_opcode - fragP->fr_literal;
8819*3d8817e4Smiod   istack_init (&istack);
8820*3d8817e4Smiod   num_steps = xg_assembly_relax (&istack, &tinsn, segP, fragP, frag_offset,
8821*3d8817e4Smiod 				 min_steps, stretch);
8822*3d8817e4Smiod   if (num_steps < min_steps)
8823*3d8817e4Smiod     {
8824*3d8817e4Smiod       as_fatal (_("internal error: relaxation failed"));
8825*3d8817e4Smiod       return 0;
8826*3d8817e4Smiod     }
8827*3d8817e4Smiod 
8828*3d8817e4Smiod   if (num_steps > RELAX_IMMED_MAXSTEPS)
8829*3d8817e4Smiod     {
8830*3d8817e4Smiod       as_fatal (_("internal error: relaxation requires too many steps"));
8831*3d8817e4Smiod       return 0;
8832*3d8817e4Smiod     }
8833*3d8817e4Smiod 
8834*3d8817e4Smiod   fragP->tc_frag_data.slot_subtypes[slot] = (int) RELAX_IMMED + num_steps;
8835*3d8817e4Smiod 
8836*3d8817e4Smiod   /* Figure out the number of bytes needed.  */
8837*3d8817e4Smiod   lit_fragP = 0;
8838*3d8817e4Smiod   num_literal_bytes = get_num_stack_literal_bytes (&istack);
8839*3d8817e4Smiod   literal_diff =
8840*3d8817e4Smiod     num_literal_bytes - fragP->tc_frag_data.literal_expansion[slot];
8841*3d8817e4Smiod   first = 0;
8842*3d8817e4Smiod   while (istack.insn[first].opcode == XTENSA_UNDEFINED)
8843*3d8817e4Smiod     first++;
8844*3d8817e4Smiod   num_text_bytes = get_num_stack_text_bytes (&istack);
8845*3d8817e4Smiod   if (wide_insn)
8846*3d8817e4Smiod     {
8847*3d8817e4Smiod       num_text_bytes += old_size;
8848*3d8817e4Smiod       if (opcode_fits_format_slot (istack.insn[first].opcode, fmt, slot))
8849*3d8817e4Smiod 	num_text_bytes -= xg_get_single_size (istack.insn[first].opcode);
8850*3d8817e4Smiod     }
8851*3d8817e4Smiod   total_text_diff = num_text_bytes - old_size;
8852*3d8817e4Smiod   this_text_diff = total_text_diff - fragP->tc_frag_data.text_expansion[slot];
8853*3d8817e4Smiod 
8854*3d8817e4Smiod   /* It MUST get larger.  If not, we could get an infinite loop.  */
8855*3d8817e4Smiod   assert (num_text_bytes >= 0);
8856*3d8817e4Smiod   assert (literal_diff >= 0);
8857*3d8817e4Smiod   assert (total_text_diff >= 0);
8858*3d8817e4Smiod 
8859*3d8817e4Smiod   fragP->tc_frag_data.text_expansion[slot] = total_text_diff;
8860*3d8817e4Smiod   fragP->tc_frag_data.literal_expansion[slot] = num_literal_bytes;
8861*3d8817e4Smiod   assert (fragP->tc_frag_data.text_expansion[slot] >= 0);
8862*3d8817e4Smiod   assert (fragP->tc_frag_data.literal_expansion[slot] >= 0);
8863*3d8817e4Smiod 
8864*3d8817e4Smiod   /* Find the associated expandable literal for this.  */
8865*3d8817e4Smiod   if (literal_diff != 0)
8866*3d8817e4Smiod     {
8867*3d8817e4Smiod       lit_fragP = fragP->tc_frag_data.literal_frags[slot];
8868*3d8817e4Smiod       if (lit_fragP)
8869*3d8817e4Smiod 	{
8870*3d8817e4Smiod 	  assert (literal_diff == 4);
8871*3d8817e4Smiod 	  lit_fragP->tc_frag_data.unreported_expansion += literal_diff;
8872*3d8817e4Smiod 
8873*3d8817e4Smiod 	  /* We expect that the literal section state has NOT been
8874*3d8817e4Smiod 	     modified yet.  */
8875*3d8817e4Smiod 	  assert (lit_fragP->fr_type == rs_machine_dependent
8876*3d8817e4Smiod 		  && lit_fragP->fr_subtype == RELAX_LITERAL);
8877*3d8817e4Smiod 	  lit_fragP->fr_subtype = RELAX_LITERAL_NR;
8878*3d8817e4Smiod 
8879*3d8817e4Smiod 	  /* We need to mark this section for another iteration
8880*3d8817e4Smiod 	     of relaxation.  */
8881*3d8817e4Smiod 	  (*stretched_p)++;
8882*3d8817e4Smiod 	}
8883*3d8817e4Smiod     }
8884*3d8817e4Smiod 
8885*3d8817e4Smiod   if (negatable_branch && istack.ninsn > 1)
8886*3d8817e4Smiod     update_next_frag_state (fragP);
8887*3d8817e4Smiod 
8888*3d8817e4Smiod   return this_text_diff;
8889*3d8817e4Smiod }
8890*3d8817e4Smiod 
8891*3d8817e4Smiod 
8892*3d8817e4Smiod /* md_convert_frag Hook and Helper Functions.  */
8893*3d8817e4Smiod 
8894*3d8817e4Smiod static void convert_frag_align_next_opcode (fragS *);
8895*3d8817e4Smiod static void convert_frag_narrow (segT, fragS *, xtensa_format, int);
8896*3d8817e4Smiod static void convert_frag_fill_nop (fragS *);
8897*3d8817e4Smiod static void convert_frag_immed (segT, fragS *, int, xtensa_format, int);
8898*3d8817e4Smiod 
8899*3d8817e4Smiod void
md_convert_frag(bfd * abfd ATTRIBUTE_UNUSED,segT sec,fragS * fragp)8900*3d8817e4Smiod md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec, fragS *fragp)
8901*3d8817e4Smiod {
8902*3d8817e4Smiod   static xtensa_insnbuf vbuf = NULL;
8903*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
8904*3d8817e4Smiod   int slot;
8905*3d8817e4Smiod   int num_slots;
8906*3d8817e4Smiod   xtensa_format fmt;
8907*3d8817e4Smiod   char *file_name;
8908*3d8817e4Smiod   unsigned line;
8909*3d8817e4Smiod 
8910*3d8817e4Smiod   as_where (&file_name, &line);
8911*3d8817e4Smiod   new_logical_line (fragp->fr_file, fragp->fr_line);
8912*3d8817e4Smiod 
8913*3d8817e4Smiod   switch (fragp->fr_subtype)
8914*3d8817e4Smiod     {
8915*3d8817e4Smiod     case RELAX_ALIGN_NEXT_OPCODE:
8916*3d8817e4Smiod       /* Always convert.  */
8917*3d8817e4Smiod       convert_frag_align_next_opcode (fragp);
8918*3d8817e4Smiod       break;
8919*3d8817e4Smiod 
8920*3d8817e4Smiod     case RELAX_DESIRE_ALIGN:
8921*3d8817e4Smiod       /* Do nothing.  If not aligned already, too bad.  */
8922*3d8817e4Smiod       break;
8923*3d8817e4Smiod 
8924*3d8817e4Smiod     case RELAX_LITERAL:
8925*3d8817e4Smiod     case RELAX_LITERAL_FINAL:
8926*3d8817e4Smiod       break;
8927*3d8817e4Smiod 
8928*3d8817e4Smiod     case RELAX_SLOTS:
8929*3d8817e4Smiod       if (vbuf == NULL)
8930*3d8817e4Smiod 	vbuf = xtensa_insnbuf_alloc (isa);
8931*3d8817e4Smiod 
8932*3d8817e4Smiod       xtensa_insnbuf_from_chars
8933*3d8817e4Smiod 	(isa, vbuf, (unsigned char *) fragp->fr_opcode, 0);
8934*3d8817e4Smiod       fmt = xtensa_format_decode (isa, vbuf);
8935*3d8817e4Smiod       num_slots = xtensa_format_num_slots (isa, fmt);
8936*3d8817e4Smiod 
8937*3d8817e4Smiod       for (slot = 0; slot < num_slots; slot++)
8938*3d8817e4Smiod 	{
8939*3d8817e4Smiod 	  switch (fragp->tc_frag_data.slot_subtypes[slot])
8940*3d8817e4Smiod 	    {
8941*3d8817e4Smiod 	    case RELAX_NARROW:
8942*3d8817e4Smiod 	      convert_frag_narrow (sec, fragp, fmt, slot);
8943*3d8817e4Smiod 	      break;
8944*3d8817e4Smiod 
8945*3d8817e4Smiod 	    case RELAX_IMMED:
8946*3d8817e4Smiod 	    case RELAX_IMMED_STEP1:
8947*3d8817e4Smiod 	    case RELAX_IMMED_STEP2:
8948*3d8817e4Smiod 	      /* Place the immediate.  */
8949*3d8817e4Smiod 	      convert_frag_immed
8950*3d8817e4Smiod 		(sec, fragp,
8951*3d8817e4Smiod 		 fragp->tc_frag_data.slot_subtypes[slot] - RELAX_IMMED,
8952*3d8817e4Smiod 		 fmt, slot);
8953*3d8817e4Smiod 	      break;
8954*3d8817e4Smiod 
8955*3d8817e4Smiod 	    default:
8956*3d8817e4Smiod 	      /* This is OK because some slots could have
8957*3d8817e4Smiod 		 relaxations and others have none.  */
8958*3d8817e4Smiod 	      break;
8959*3d8817e4Smiod 	    }
8960*3d8817e4Smiod 	}
8961*3d8817e4Smiod       break;
8962*3d8817e4Smiod 
8963*3d8817e4Smiod     case RELAX_UNREACHABLE:
8964*3d8817e4Smiod       memset (&fragp->fr_literal[fragp->fr_fix], 0, fragp->fr_var);
8965*3d8817e4Smiod       fragp->fr_fix += fragp->tc_frag_data.text_expansion[0];
8966*3d8817e4Smiod       fragp->fr_var -= fragp->tc_frag_data.text_expansion[0];
8967*3d8817e4Smiod       frag_wane (fragp);
8968*3d8817e4Smiod       break;
8969*3d8817e4Smiod 
8970*3d8817e4Smiod     case RELAX_MAYBE_UNREACHABLE:
8971*3d8817e4Smiod     case RELAX_MAYBE_DESIRE_ALIGN:
8972*3d8817e4Smiod       frag_wane (fragp);
8973*3d8817e4Smiod       break;
8974*3d8817e4Smiod 
8975*3d8817e4Smiod     case RELAX_FILL_NOP:
8976*3d8817e4Smiod       convert_frag_fill_nop (fragp);
8977*3d8817e4Smiod       break;
8978*3d8817e4Smiod 
8979*3d8817e4Smiod     case RELAX_LITERAL_NR:
8980*3d8817e4Smiod       if (use_literal_section)
8981*3d8817e4Smiod 	{
8982*3d8817e4Smiod 	  /* This should have been handled during relaxation.  When
8983*3d8817e4Smiod 	     relaxing a code segment, literals sometimes need to be
8984*3d8817e4Smiod 	     added to the corresponding literal segment.  If that
8985*3d8817e4Smiod 	     literal segment has already been relaxed, then we end up
8986*3d8817e4Smiod 	     in this situation.  Marking the literal segments as data
8987*3d8817e4Smiod 	     would make this happen less often (since GAS always relaxes
8988*3d8817e4Smiod 	     code before data), but we could still get into trouble if
8989*3d8817e4Smiod 	     there are instructions in a segment that is not marked as
8990*3d8817e4Smiod 	     containing code.  Until we can implement a better solution,
8991*3d8817e4Smiod 	     cheat and adjust the addresses of all the following frags.
8992*3d8817e4Smiod 	     This could break subsequent alignments, but the linker's
8993*3d8817e4Smiod 	     literal coalescing will do that anyway.  */
8994*3d8817e4Smiod 
8995*3d8817e4Smiod 	  fragS *f;
8996*3d8817e4Smiod 	  fragp->fr_subtype = RELAX_LITERAL_FINAL;
8997*3d8817e4Smiod 	  assert (fragp->tc_frag_data.unreported_expansion == 4);
8998*3d8817e4Smiod 	  memset (&fragp->fr_literal[fragp->fr_fix], 0, 4);
8999*3d8817e4Smiod 	  fragp->fr_var -= 4;
9000*3d8817e4Smiod 	  fragp->fr_fix += 4;
9001*3d8817e4Smiod 	  for (f = fragp->fr_next; f; f = f->fr_next)
9002*3d8817e4Smiod 	    f->fr_address += 4;
9003*3d8817e4Smiod 	}
9004*3d8817e4Smiod       else
9005*3d8817e4Smiod 	as_bad (_("invalid relaxation fragment result"));
9006*3d8817e4Smiod       break;
9007*3d8817e4Smiod     }
9008*3d8817e4Smiod 
9009*3d8817e4Smiod   fragp->fr_var = 0;
9010*3d8817e4Smiod   new_logical_line (file_name, line);
9011*3d8817e4Smiod }
9012*3d8817e4Smiod 
9013*3d8817e4Smiod 
9014*3d8817e4Smiod static void
convert_frag_align_next_opcode(fragS * fragp)9015*3d8817e4Smiod convert_frag_align_next_opcode (fragS *fragp)
9016*3d8817e4Smiod {
9017*3d8817e4Smiod   char *nop_buf;		/* Location for Writing.  */
9018*3d8817e4Smiod   bfd_boolean use_no_density = fragp->tc_frag_data.is_no_density;
9019*3d8817e4Smiod   addressT aligned_address;
9020*3d8817e4Smiod   offsetT fill_size;
9021*3d8817e4Smiod   int nop, nop_count;
9022*3d8817e4Smiod 
9023*3d8817e4Smiod   aligned_address = get_noop_aligned_address (fragp, fragp->fr_address +
9024*3d8817e4Smiod 					      fragp->fr_fix);
9025*3d8817e4Smiod   fill_size = aligned_address - (fragp->fr_address + fragp->fr_fix);
9026*3d8817e4Smiod   nop_count = get_text_align_nop_count (fill_size, use_no_density);
9027*3d8817e4Smiod   nop_buf = fragp->fr_literal + fragp->fr_fix;
9028*3d8817e4Smiod 
9029*3d8817e4Smiod   for (nop = 0; nop < nop_count; nop++)
9030*3d8817e4Smiod     {
9031*3d8817e4Smiod       int nop_size;
9032*3d8817e4Smiod       nop_size = get_text_align_nth_nop_size (fill_size, nop, use_no_density);
9033*3d8817e4Smiod 
9034*3d8817e4Smiod       assemble_nop (nop_size, nop_buf);
9035*3d8817e4Smiod       nop_buf += nop_size;
9036*3d8817e4Smiod     }
9037*3d8817e4Smiod 
9038*3d8817e4Smiod   fragp->fr_fix += fill_size;
9039*3d8817e4Smiod   fragp->fr_var -= fill_size;
9040*3d8817e4Smiod }
9041*3d8817e4Smiod 
9042*3d8817e4Smiod 
9043*3d8817e4Smiod static void
convert_frag_narrow(segT segP,fragS * fragP,xtensa_format fmt,int slot)9044*3d8817e4Smiod convert_frag_narrow (segT segP, fragS *fragP, xtensa_format fmt, int slot)
9045*3d8817e4Smiod {
9046*3d8817e4Smiod   TInsn tinsn, single_target;
9047*3d8817e4Smiod   int size, old_size, diff;
9048*3d8817e4Smiod   offsetT frag_offset;
9049*3d8817e4Smiod 
9050*3d8817e4Smiod   assert (slot == 0);
9051*3d8817e4Smiod   tinsn_from_chars (&tinsn, fragP->fr_opcode, 0);
9052*3d8817e4Smiod 
9053*3d8817e4Smiod   if (fragP->tc_frag_data.is_aligning_branch == 1)
9054*3d8817e4Smiod     {
9055*3d8817e4Smiod       assert (fragP->tc_frag_data.text_expansion[0] == 1
9056*3d8817e4Smiod 	      || fragP->tc_frag_data.text_expansion[0] == 0);
9057*3d8817e4Smiod       convert_frag_immed (segP, fragP, fragP->tc_frag_data.text_expansion[0],
9058*3d8817e4Smiod 			  fmt, slot);
9059*3d8817e4Smiod       return;
9060*3d8817e4Smiod     }
9061*3d8817e4Smiod 
9062*3d8817e4Smiod   if (fragP->tc_frag_data.text_expansion[0] == 0)
9063*3d8817e4Smiod     {
9064*3d8817e4Smiod       /* No conversion.  */
9065*3d8817e4Smiod       fragP->fr_var = 0;
9066*3d8817e4Smiod       return;
9067*3d8817e4Smiod     }
9068*3d8817e4Smiod 
9069*3d8817e4Smiod   assert (fragP->fr_opcode != NULL);
9070*3d8817e4Smiod 
9071*3d8817e4Smiod   /* Frags in this relaxation state should only contain
9072*3d8817e4Smiod      single instruction bundles.  */
9073*3d8817e4Smiod   tinsn_immed_from_frag (&tinsn, fragP, 0);
9074*3d8817e4Smiod 
9075*3d8817e4Smiod   /* Just convert it to a wide form....  */
9076*3d8817e4Smiod   size = 0;
9077*3d8817e4Smiod   old_size = xg_get_single_size (tinsn.opcode);
9078*3d8817e4Smiod 
9079*3d8817e4Smiod   tinsn_init (&single_target);
9080*3d8817e4Smiod   frag_offset = fragP->fr_opcode - fragP->fr_literal;
9081*3d8817e4Smiod 
9082*3d8817e4Smiod   if (! xg_is_single_relaxable_insn (&tinsn, &single_target, FALSE))
9083*3d8817e4Smiod     {
9084*3d8817e4Smiod       as_bad (_("unable to widen instruction"));
9085*3d8817e4Smiod       return;
9086*3d8817e4Smiod     }
9087*3d8817e4Smiod 
9088*3d8817e4Smiod   size = xg_get_single_size (single_target.opcode);
9089*3d8817e4Smiod   xg_emit_insn_to_buf (&single_target, fragP->fr_opcode, fragP,
9090*3d8817e4Smiod 		       frag_offset, TRUE);
9091*3d8817e4Smiod 
9092*3d8817e4Smiod   diff = size - old_size;
9093*3d8817e4Smiod   assert (diff >= 0);
9094*3d8817e4Smiod   assert (diff <= fragP->fr_var);
9095*3d8817e4Smiod   fragP->fr_var -= diff;
9096*3d8817e4Smiod   fragP->fr_fix += diff;
9097*3d8817e4Smiod 
9098*3d8817e4Smiod   /* clean it up */
9099*3d8817e4Smiod   fragP->fr_var = 0;
9100*3d8817e4Smiod }
9101*3d8817e4Smiod 
9102*3d8817e4Smiod 
9103*3d8817e4Smiod static void
convert_frag_fill_nop(fragS * fragP)9104*3d8817e4Smiod convert_frag_fill_nop (fragS *fragP)
9105*3d8817e4Smiod {
9106*3d8817e4Smiod   char *loc = &fragP->fr_literal[fragP->fr_fix];
9107*3d8817e4Smiod   int size = fragP->tc_frag_data.text_expansion[0];
9108*3d8817e4Smiod   assert ((unsigned) size == (fragP->fr_next->fr_address
9109*3d8817e4Smiod 			      - fragP->fr_address - fragP->fr_fix));
9110*3d8817e4Smiod   if (size == 0)
9111*3d8817e4Smiod     {
9112*3d8817e4Smiod       /* No conversion.  */
9113*3d8817e4Smiod       fragP->fr_var = 0;
9114*3d8817e4Smiod       return;
9115*3d8817e4Smiod     }
9116*3d8817e4Smiod   assemble_nop (size, loc);
9117*3d8817e4Smiod   fragP->tc_frag_data.is_insn = TRUE;
9118*3d8817e4Smiod   fragP->fr_var -= size;
9119*3d8817e4Smiod   fragP->fr_fix += size;
9120*3d8817e4Smiod   frag_wane (fragP);
9121*3d8817e4Smiod }
9122*3d8817e4Smiod 
9123*3d8817e4Smiod 
9124*3d8817e4Smiod static fixS *fix_new_exp_in_seg
9125*3d8817e4Smiod   (segT, subsegT, fragS *, int, int, expressionS *, int,
9126*3d8817e4Smiod    bfd_reloc_code_real_type);
9127*3d8817e4Smiod static void convert_frag_immed_finish_loop (segT, fragS *, TInsn *);
9128*3d8817e4Smiod 
9129*3d8817e4Smiod static void
convert_frag_immed(segT segP,fragS * fragP,int min_steps,xtensa_format fmt,int slot)9130*3d8817e4Smiod convert_frag_immed (segT segP,
9131*3d8817e4Smiod 		    fragS *fragP,
9132*3d8817e4Smiod 		    int min_steps,
9133*3d8817e4Smiod 		    xtensa_format fmt,
9134*3d8817e4Smiod 		    int slot)
9135*3d8817e4Smiod {
9136*3d8817e4Smiod   char *immed_instr = fragP->fr_opcode;
9137*3d8817e4Smiod   TInsn orig_tinsn;
9138*3d8817e4Smiod   bfd_boolean expanded = FALSE;
9139*3d8817e4Smiod   bfd_boolean branch_jmp_to_next = FALSE;
9140*3d8817e4Smiod   char *fr_opcode = fragP->fr_opcode;
9141*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
9142*3d8817e4Smiod   bfd_boolean wide_insn = FALSE;
9143*3d8817e4Smiod   int bytes;
9144*3d8817e4Smiod   bfd_boolean is_loop;
9145*3d8817e4Smiod 
9146*3d8817e4Smiod   assert (fr_opcode != NULL);
9147*3d8817e4Smiod 
9148*3d8817e4Smiod   xg_clear_vinsn (&cur_vinsn);
9149*3d8817e4Smiod 
9150*3d8817e4Smiod   vinsn_from_chars (&cur_vinsn, fr_opcode);
9151*3d8817e4Smiod   if (cur_vinsn.num_slots > 1)
9152*3d8817e4Smiod     wide_insn = TRUE;
9153*3d8817e4Smiod 
9154*3d8817e4Smiod   orig_tinsn = cur_vinsn.slots[slot];
9155*3d8817e4Smiod   tinsn_immed_from_frag (&orig_tinsn, fragP, slot);
9156*3d8817e4Smiod 
9157*3d8817e4Smiod   is_loop = xtensa_opcode_is_loop (xtensa_default_isa, orig_tinsn.opcode) == 1;
9158*3d8817e4Smiod 
9159*3d8817e4Smiod   if (workaround_b_j_loop_end && ! fragP->tc_frag_data.is_no_transform)
9160*3d8817e4Smiod     branch_jmp_to_next = is_branch_jmp_to_next (&orig_tinsn, fragP);
9161*3d8817e4Smiod 
9162*3d8817e4Smiod   if (branch_jmp_to_next && !next_frag_is_loop_target (fragP))
9163*3d8817e4Smiod     {
9164*3d8817e4Smiod       /* Conversion just inserts a NOP and marks the fix as completed.  */
9165*3d8817e4Smiod       bytes = xtensa_format_length (isa, fmt);
9166*3d8817e4Smiod       if (bytes >= 4)
9167*3d8817e4Smiod 	{
9168*3d8817e4Smiod 	  cur_vinsn.slots[slot].opcode =
9169*3d8817e4Smiod 	    xtensa_format_slot_nop_opcode (isa, cur_vinsn.format, slot);
9170*3d8817e4Smiod 	  cur_vinsn.slots[slot].ntok = 0;
9171*3d8817e4Smiod 	}
9172*3d8817e4Smiod       else
9173*3d8817e4Smiod 	{
9174*3d8817e4Smiod 	  bytes += fragP->tc_frag_data.text_expansion[0];
9175*3d8817e4Smiod 	  assert (bytes == 2 || bytes == 3);
9176*3d8817e4Smiod 	  build_nop (&cur_vinsn.slots[0], bytes);
9177*3d8817e4Smiod 	  fragP->fr_fix += fragP->tc_frag_data.text_expansion[0];
9178*3d8817e4Smiod 	}
9179*3d8817e4Smiod       vinsn_to_insnbuf (&cur_vinsn, fr_opcode, frag_now, TRUE);
9180*3d8817e4Smiod       xtensa_insnbuf_to_chars
9181*3d8817e4Smiod 	(isa, cur_vinsn.insnbuf, (unsigned char *) fr_opcode, 0);
9182*3d8817e4Smiod       fragP->fr_var = 0;
9183*3d8817e4Smiod     }
9184*3d8817e4Smiod   else
9185*3d8817e4Smiod     {
9186*3d8817e4Smiod       /* Here is the fun stuff:  Get the immediate field from this
9187*3d8817e4Smiod 	 instruction.  If it fits, we're done.  If not, find the next
9188*3d8817e4Smiod 	 instruction sequence that fits.  */
9189*3d8817e4Smiod 
9190*3d8817e4Smiod       IStack istack;
9191*3d8817e4Smiod       int i;
9192*3d8817e4Smiod       symbolS *lit_sym = NULL;
9193*3d8817e4Smiod       int total_size = 0;
9194*3d8817e4Smiod       int target_offset = 0;
9195*3d8817e4Smiod       int old_size;
9196*3d8817e4Smiod       int diff;
9197*3d8817e4Smiod       symbolS *gen_label = NULL;
9198*3d8817e4Smiod       offsetT frag_offset;
9199*3d8817e4Smiod       bfd_boolean first = TRUE;
9200*3d8817e4Smiod       bfd_boolean last_is_jump;
9201*3d8817e4Smiod 
9202*3d8817e4Smiod       /* It does not fit.  Find something that does and
9203*3d8817e4Smiod          convert immediately.  */
9204*3d8817e4Smiod       frag_offset = fr_opcode - fragP->fr_literal;
9205*3d8817e4Smiod       istack_init (&istack);
9206*3d8817e4Smiod       xg_assembly_relax (&istack, &orig_tinsn,
9207*3d8817e4Smiod 			 segP, fragP, frag_offset, min_steps, 0);
9208*3d8817e4Smiod 
9209*3d8817e4Smiod       old_size = xtensa_format_length (isa, fmt);
9210*3d8817e4Smiod 
9211*3d8817e4Smiod       /* Assemble this right inline.  */
9212*3d8817e4Smiod 
9213*3d8817e4Smiod       /* First, create the mapping from a label name to the REAL label.  */
9214*3d8817e4Smiod       target_offset = 0;
9215*3d8817e4Smiod       for (i = 0; i < istack.ninsn; i++)
9216*3d8817e4Smiod 	{
9217*3d8817e4Smiod 	  TInsn *tinsn = &istack.insn[i];
9218*3d8817e4Smiod 	  fragS *lit_frag;
9219*3d8817e4Smiod 
9220*3d8817e4Smiod 	  switch (tinsn->insn_type)
9221*3d8817e4Smiod 	    {
9222*3d8817e4Smiod 	    case ITYPE_LITERAL:
9223*3d8817e4Smiod 	      if (lit_sym != NULL)
9224*3d8817e4Smiod 		as_bad (_("multiple literals in expansion"));
9225*3d8817e4Smiod 	      /* First find the appropriate space in the literal pool.  */
9226*3d8817e4Smiod 	      lit_frag = fragP->tc_frag_data.literal_frags[slot];
9227*3d8817e4Smiod 	      if (lit_frag == NULL)
9228*3d8817e4Smiod 		as_bad (_("no registered fragment for literal"));
9229*3d8817e4Smiod 	      if (tinsn->ntok != 1)
9230*3d8817e4Smiod 		as_bad (_("number of literal tokens != 1"));
9231*3d8817e4Smiod 
9232*3d8817e4Smiod 	      /* Set the literal symbol and add a fixup.  */
9233*3d8817e4Smiod 	      lit_sym = lit_frag->fr_symbol;
9234*3d8817e4Smiod 	      break;
9235*3d8817e4Smiod 
9236*3d8817e4Smiod 	    case ITYPE_LABEL:
9237*3d8817e4Smiod 	      if (align_targets && !is_loop)
9238*3d8817e4Smiod 		{
9239*3d8817e4Smiod 		  fragS *unreach = fragP->fr_next;
9240*3d8817e4Smiod 		  while (!(unreach->fr_type == rs_machine_dependent
9241*3d8817e4Smiod 			   && (unreach->fr_subtype == RELAX_MAYBE_UNREACHABLE
9242*3d8817e4Smiod 			       || unreach->fr_subtype == RELAX_UNREACHABLE)))
9243*3d8817e4Smiod 		    {
9244*3d8817e4Smiod 		      unreach = unreach->fr_next;
9245*3d8817e4Smiod 		    }
9246*3d8817e4Smiod 
9247*3d8817e4Smiod 		  assert (unreach->fr_type == rs_machine_dependent
9248*3d8817e4Smiod 			  && (unreach->fr_subtype == RELAX_MAYBE_UNREACHABLE
9249*3d8817e4Smiod 			      || unreach->fr_subtype == RELAX_UNREACHABLE));
9250*3d8817e4Smiod 
9251*3d8817e4Smiod 		  target_offset += unreach->tc_frag_data.text_expansion[0];
9252*3d8817e4Smiod 		}
9253*3d8817e4Smiod 	      assert (gen_label == NULL);
9254*3d8817e4Smiod 	      gen_label = symbol_new (FAKE_LABEL_NAME, now_seg,
9255*3d8817e4Smiod 				      fr_opcode - fragP->fr_literal
9256*3d8817e4Smiod 				      + target_offset, fragP);
9257*3d8817e4Smiod 	      break;
9258*3d8817e4Smiod 
9259*3d8817e4Smiod 	    case ITYPE_INSN:
9260*3d8817e4Smiod 	      if (first && wide_insn)
9261*3d8817e4Smiod 		{
9262*3d8817e4Smiod 		  target_offset += xtensa_format_length (isa, fmt);
9263*3d8817e4Smiod 		  first = FALSE;
9264*3d8817e4Smiod 		  if (!opcode_fits_format_slot (tinsn->opcode, fmt, slot))
9265*3d8817e4Smiod 		    target_offset += xg_get_single_size (tinsn->opcode);
9266*3d8817e4Smiod 		}
9267*3d8817e4Smiod 	      else
9268*3d8817e4Smiod 		target_offset += xg_get_single_size (tinsn->opcode);
9269*3d8817e4Smiod 	      break;
9270*3d8817e4Smiod 	    }
9271*3d8817e4Smiod 	}
9272*3d8817e4Smiod 
9273*3d8817e4Smiod       total_size = 0;
9274*3d8817e4Smiod       first = TRUE;
9275*3d8817e4Smiod       last_is_jump = FALSE;
9276*3d8817e4Smiod       for (i = 0; i < istack.ninsn; i++)
9277*3d8817e4Smiod 	{
9278*3d8817e4Smiod 	  TInsn *tinsn = &istack.insn[i];
9279*3d8817e4Smiod 	  fragS *lit_frag;
9280*3d8817e4Smiod 	  int size;
9281*3d8817e4Smiod 	  segT target_seg;
9282*3d8817e4Smiod 	  bfd_reloc_code_real_type reloc_type;
9283*3d8817e4Smiod 
9284*3d8817e4Smiod 	  switch (tinsn->insn_type)
9285*3d8817e4Smiod 	    {
9286*3d8817e4Smiod 	    case ITYPE_LITERAL:
9287*3d8817e4Smiod 	      lit_frag = fragP->tc_frag_data.literal_frags[slot];
9288*3d8817e4Smiod 	      /* Already checked.  */
9289*3d8817e4Smiod 	      assert (lit_frag != NULL);
9290*3d8817e4Smiod 	      assert (lit_sym != NULL);
9291*3d8817e4Smiod 	      assert (tinsn->ntok == 1);
9292*3d8817e4Smiod 	      /* Add a fixup.  */
9293*3d8817e4Smiod 	      target_seg = S_GET_SEGMENT (lit_sym);
9294*3d8817e4Smiod 	      assert (target_seg);
9295*3d8817e4Smiod 	      if (tinsn->tok[0].X_op == O_pltrel)
9296*3d8817e4Smiod 		reloc_type = BFD_RELOC_XTENSA_PLT;
9297*3d8817e4Smiod 	      else
9298*3d8817e4Smiod 		reloc_type = BFD_RELOC_32;
9299*3d8817e4Smiod 	      fix_new_exp_in_seg (target_seg, 0, lit_frag, 0, 4,
9300*3d8817e4Smiod 				  &tinsn->tok[0], FALSE, reloc_type);
9301*3d8817e4Smiod 	      break;
9302*3d8817e4Smiod 
9303*3d8817e4Smiod 	    case ITYPE_LABEL:
9304*3d8817e4Smiod 	      break;
9305*3d8817e4Smiod 
9306*3d8817e4Smiod 	    case ITYPE_INSN:
9307*3d8817e4Smiod 	      xg_resolve_labels (tinsn, gen_label);
9308*3d8817e4Smiod 	      xg_resolve_literals (tinsn, lit_sym);
9309*3d8817e4Smiod 	      if (wide_insn && first)
9310*3d8817e4Smiod 		{
9311*3d8817e4Smiod 		  first = FALSE;
9312*3d8817e4Smiod 		  if (opcode_fits_format_slot (tinsn->opcode, fmt, slot))
9313*3d8817e4Smiod 		    {
9314*3d8817e4Smiod 		      cur_vinsn.slots[slot] = *tinsn;
9315*3d8817e4Smiod 		    }
9316*3d8817e4Smiod 		  else
9317*3d8817e4Smiod 		    {
9318*3d8817e4Smiod 		      cur_vinsn.slots[slot].opcode =
9319*3d8817e4Smiod 			xtensa_format_slot_nop_opcode (isa, fmt, slot);
9320*3d8817e4Smiod 		      cur_vinsn.slots[slot].ntok = 0;
9321*3d8817e4Smiod 		    }
9322*3d8817e4Smiod 		  vinsn_to_insnbuf (&cur_vinsn, immed_instr, fragP, TRUE);
9323*3d8817e4Smiod 		  xtensa_insnbuf_to_chars (isa, cur_vinsn.insnbuf,
9324*3d8817e4Smiod 					   (unsigned char *) immed_instr, 0);
9325*3d8817e4Smiod 		  fragP->tc_frag_data.is_insn = TRUE;
9326*3d8817e4Smiod 		  size = xtensa_format_length (isa, fmt);
9327*3d8817e4Smiod 		  if (!opcode_fits_format_slot (tinsn->opcode, fmt, slot))
9328*3d8817e4Smiod 		    {
9329*3d8817e4Smiod 		      xg_emit_insn_to_buf
9330*3d8817e4Smiod 			(tinsn, immed_instr + size, fragP,
9331*3d8817e4Smiod 			 immed_instr - fragP->fr_literal + size, TRUE);
9332*3d8817e4Smiod 		      size += xg_get_single_size (tinsn->opcode);
9333*3d8817e4Smiod 		    }
9334*3d8817e4Smiod 		}
9335*3d8817e4Smiod 	      else
9336*3d8817e4Smiod 		{
9337*3d8817e4Smiod 		  size = xg_get_single_size (tinsn->opcode);
9338*3d8817e4Smiod 		  xg_emit_insn_to_buf (tinsn, immed_instr, fragP,
9339*3d8817e4Smiod 				       immed_instr - fragP->fr_literal, TRUE);
9340*3d8817e4Smiod 		}
9341*3d8817e4Smiod 	      immed_instr += size;
9342*3d8817e4Smiod 	      total_size += size;
9343*3d8817e4Smiod 	      break;
9344*3d8817e4Smiod 	    }
9345*3d8817e4Smiod 	}
9346*3d8817e4Smiod 
9347*3d8817e4Smiod       diff = total_size - old_size;
9348*3d8817e4Smiod       assert (diff >= 0);
9349*3d8817e4Smiod       if (diff != 0)
9350*3d8817e4Smiod 	expanded = TRUE;
9351*3d8817e4Smiod       assert (diff <= fragP->fr_var);
9352*3d8817e4Smiod       fragP->fr_var -= diff;
9353*3d8817e4Smiod       fragP->fr_fix += diff;
9354*3d8817e4Smiod     }
9355*3d8817e4Smiod 
9356*3d8817e4Smiod   /* Check for undefined immediates in LOOP instructions.  */
9357*3d8817e4Smiod   if (is_loop)
9358*3d8817e4Smiod     {
9359*3d8817e4Smiod       symbolS *sym;
9360*3d8817e4Smiod       sym = orig_tinsn.tok[1].X_add_symbol;
9361*3d8817e4Smiod       if (sym != NULL && !S_IS_DEFINED (sym))
9362*3d8817e4Smiod 	{
9363*3d8817e4Smiod 	  as_bad (_("unresolved loop target symbol: %s"), S_GET_NAME (sym));
9364*3d8817e4Smiod 	  return;
9365*3d8817e4Smiod 	}
9366*3d8817e4Smiod       sym = orig_tinsn.tok[1].X_op_symbol;
9367*3d8817e4Smiod       if (sym != NULL && !S_IS_DEFINED (sym))
9368*3d8817e4Smiod 	{
9369*3d8817e4Smiod 	  as_bad (_("unresolved loop target symbol: %s"), S_GET_NAME (sym));
9370*3d8817e4Smiod 	  return;
9371*3d8817e4Smiod 	}
9372*3d8817e4Smiod     }
9373*3d8817e4Smiod 
9374*3d8817e4Smiod   if (expanded && xtensa_opcode_is_loop (isa, orig_tinsn.opcode) == 1)
9375*3d8817e4Smiod     convert_frag_immed_finish_loop (segP, fragP, &orig_tinsn);
9376*3d8817e4Smiod 
9377*3d8817e4Smiod   if (expanded && is_direct_call_opcode (orig_tinsn.opcode))
9378*3d8817e4Smiod     {
9379*3d8817e4Smiod       /* Add an expansion note on the expanded instruction.  */
9380*3d8817e4Smiod       fix_new_exp_in_seg (now_seg, 0, fragP, fr_opcode - fragP->fr_literal, 4,
9381*3d8817e4Smiod 			  &orig_tinsn.tok[0], TRUE,
9382*3d8817e4Smiod 			  BFD_RELOC_XTENSA_ASM_EXPAND);
9383*3d8817e4Smiod     }
9384*3d8817e4Smiod }
9385*3d8817e4Smiod 
9386*3d8817e4Smiod 
9387*3d8817e4Smiod /* Add a new fix expression into the desired segment.  We have to
9388*3d8817e4Smiod    switch to that segment to do this.  */
9389*3d8817e4Smiod 
9390*3d8817e4Smiod static fixS *
fix_new_exp_in_seg(segT new_seg,subsegT new_subseg,fragS * frag,int where,int size,expressionS * exp,int pcrel,bfd_reloc_code_real_type r_type)9391*3d8817e4Smiod fix_new_exp_in_seg (segT new_seg,
9392*3d8817e4Smiod 		    subsegT new_subseg,
9393*3d8817e4Smiod 		    fragS *frag,
9394*3d8817e4Smiod 		    int where,
9395*3d8817e4Smiod 		    int size,
9396*3d8817e4Smiod 		    expressionS *exp,
9397*3d8817e4Smiod 		    int pcrel,
9398*3d8817e4Smiod 		    bfd_reloc_code_real_type r_type)
9399*3d8817e4Smiod {
9400*3d8817e4Smiod   fixS *new_fix;
9401*3d8817e4Smiod   segT seg = now_seg;
9402*3d8817e4Smiod   subsegT subseg = now_subseg;
9403*3d8817e4Smiod 
9404*3d8817e4Smiod   assert (new_seg != 0);
9405*3d8817e4Smiod   subseg_set (new_seg, new_subseg);
9406*3d8817e4Smiod 
9407*3d8817e4Smiod   new_fix = fix_new_exp (frag, where, size, exp, pcrel, r_type);
9408*3d8817e4Smiod   subseg_set (seg, subseg);
9409*3d8817e4Smiod   return new_fix;
9410*3d8817e4Smiod }
9411*3d8817e4Smiod 
9412*3d8817e4Smiod 
9413*3d8817e4Smiod /* Relax a loop instruction so that it can span loop >256 bytes.
9414*3d8817e4Smiod 
9415*3d8817e4Smiod                   loop    as, .L1
9416*3d8817e4Smiod           .L0:
9417*3d8817e4Smiod                   rsr     as, LEND
9418*3d8817e4Smiod                   wsr     as, LBEG
9419*3d8817e4Smiod                   addi    as, as, lo8 (label-.L1)
9420*3d8817e4Smiod                   addmi   as, as, mid8 (label-.L1)
9421*3d8817e4Smiod                   wsr     as, LEND
9422*3d8817e4Smiod                   isync
9423*3d8817e4Smiod                   rsr     as, LCOUNT
9424*3d8817e4Smiod                   addi    as, as, 1
9425*3d8817e4Smiod           .L1:
9426*3d8817e4Smiod                   <<body>>
9427*3d8817e4Smiod           label:
9428*3d8817e4Smiod */
9429*3d8817e4Smiod 
9430*3d8817e4Smiod static void
convert_frag_immed_finish_loop(segT segP,fragS * fragP,TInsn * tinsn)9431*3d8817e4Smiod convert_frag_immed_finish_loop (segT segP, fragS *fragP, TInsn *tinsn)
9432*3d8817e4Smiod {
9433*3d8817e4Smiod   TInsn loop_insn;
9434*3d8817e4Smiod   TInsn addi_insn;
9435*3d8817e4Smiod   TInsn addmi_insn;
9436*3d8817e4Smiod   unsigned long target;
9437*3d8817e4Smiod   static xtensa_insnbuf insnbuf = NULL;
9438*3d8817e4Smiod   unsigned int loop_length, loop_length_hi, loop_length_lo;
9439*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
9440*3d8817e4Smiod   addressT loop_offset;
9441*3d8817e4Smiod   addressT addi_offset = 9;
9442*3d8817e4Smiod   addressT addmi_offset = 12;
9443*3d8817e4Smiod   fragS *next_fragP;
9444*3d8817e4Smiod   int target_count;
9445*3d8817e4Smiod 
9446*3d8817e4Smiod   if (!insnbuf)
9447*3d8817e4Smiod     insnbuf = xtensa_insnbuf_alloc (isa);
9448*3d8817e4Smiod 
9449*3d8817e4Smiod   /* Get the loop offset.  */
9450*3d8817e4Smiod   loop_offset = get_expanded_loop_offset (tinsn->opcode);
9451*3d8817e4Smiod 
9452*3d8817e4Smiod   /* Validate that there really is a LOOP at the loop_offset.  Because
9453*3d8817e4Smiod      loops are not bundleable, we can assume that the instruction will be
9454*3d8817e4Smiod      in slot 0.  */
9455*3d8817e4Smiod   tinsn_from_chars (&loop_insn, fragP->fr_opcode + loop_offset, 0);
9456*3d8817e4Smiod   tinsn_immed_from_frag (&loop_insn, fragP, 0);
9457*3d8817e4Smiod 
9458*3d8817e4Smiod   assert (xtensa_opcode_is_loop (isa, loop_insn.opcode) == 1);
9459*3d8817e4Smiod   addi_offset += loop_offset;
9460*3d8817e4Smiod   addmi_offset += loop_offset;
9461*3d8817e4Smiod 
9462*3d8817e4Smiod   assert (tinsn->ntok == 2);
9463*3d8817e4Smiod   if (tinsn->tok[1].X_op == O_constant)
9464*3d8817e4Smiod     target = tinsn->tok[1].X_add_number;
9465*3d8817e4Smiod   else if (tinsn->tok[1].X_op == O_symbol)
9466*3d8817e4Smiod     {
9467*3d8817e4Smiod       /* Find the fragment.  */
9468*3d8817e4Smiod       symbolS *sym = tinsn->tok[1].X_add_symbol;
9469*3d8817e4Smiod       assert (S_GET_SEGMENT (sym) == segP
9470*3d8817e4Smiod 	      || S_GET_SEGMENT (sym) == absolute_section);
9471*3d8817e4Smiod       target = (S_GET_VALUE (sym) + tinsn->tok[1].X_add_number);
9472*3d8817e4Smiod     }
9473*3d8817e4Smiod   else
9474*3d8817e4Smiod     {
9475*3d8817e4Smiod       as_bad (_("invalid expression evaluation type %d"), tinsn->tok[1].X_op);
9476*3d8817e4Smiod       target = 0;
9477*3d8817e4Smiod     }
9478*3d8817e4Smiod 
9479*3d8817e4Smiod   know (symbolP);
9480*3d8817e4Smiod   know (symbolP->sy_frag);
9481*3d8817e4Smiod   know (!(S_GET_SEGMENT (symbolP) == absolute_section)
9482*3d8817e4Smiod 	|| symbol_get_frag (symbolP) == &zero_address_frag);
9483*3d8817e4Smiod 
9484*3d8817e4Smiod   loop_length = target - (fragP->fr_address + fragP->fr_fix);
9485*3d8817e4Smiod   loop_length_hi = loop_length & ~0x0ff;
9486*3d8817e4Smiod   loop_length_lo = loop_length & 0x0ff;
9487*3d8817e4Smiod   if (loop_length_lo >= 128)
9488*3d8817e4Smiod     {
9489*3d8817e4Smiod       loop_length_lo -= 256;
9490*3d8817e4Smiod       loop_length_hi += 256;
9491*3d8817e4Smiod     }
9492*3d8817e4Smiod 
9493*3d8817e4Smiod   /* Because addmi sign-extends the immediate, 'loop_length_hi' can be at most
9494*3d8817e4Smiod      32512.  If the loop is larger than that, then we just fail.  */
9495*3d8817e4Smiod   if (loop_length_hi > 32512)
9496*3d8817e4Smiod     as_bad_where (fragP->fr_file, fragP->fr_line,
9497*3d8817e4Smiod 		  _("loop too long for LOOP instruction"));
9498*3d8817e4Smiod 
9499*3d8817e4Smiod   tinsn_from_chars (&addi_insn, fragP->fr_opcode + addi_offset, 0);
9500*3d8817e4Smiod   assert (addi_insn.opcode == xtensa_addi_opcode);
9501*3d8817e4Smiod 
9502*3d8817e4Smiod   tinsn_from_chars (&addmi_insn, fragP->fr_opcode + addmi_offset, 0);
9503*3d8817e4Smiod   assert (addmi_insn.opcode == xtensa_addmi_opcode);
9504*3d8817e4Smiod 
9505*3d8817e4Smiod   set_expr_const (&addi_insn.tok[2], loop_length_lo);
9506*3d8817e4Smiod   tinsn_to_insnbuf (&addi_insn, insnbuf);
9507*3d8817e4Smiod 
9508*3d8817e4Smiod   fragP->tc_frag_data.is_insn = TRUE;
9509*3d8817e4Smiod   xtensa_insnbuf_to_chars
9510*3d8817e4Smiod     (isa, insnbuf, (unsigned char *) fragP->fr_opcode + addi_offset, 0);
9511*3d8817e4Smiod 
9512*3d8817e4Smiod   set_expr_const (&addmi_insn.tok[2], loop_length_hi);
9513*3d8817e4Smiod   tinsn_to_insnbuf (&addmi_insn, insnbuf);
9514*3d8817e4Smiod   xtensa_insnbuf_to_chars
9515*3d8817e4Smiod     (isa, insnbuf, (unsigned char *) fragP->fr_opcode + addmi_offset, 0);
9516*3d8817e4Smiod 
9517*3d8817e4Smiod   /* Walk through all of the frags from here to the loop end
9518*3d8817e4Smiod      and mark them as no_transform to keep them from being modified
9519*3d8817e4Smiod      by the linker.  If we ever have a relocation for the
9520*3d8817e4Smiod      addi/addmi of the difference of two symbols we can remove this.  */
9521*3d8817e4Smiod 
9522*3d8817e4Smiod   target_count = 0;
9523*3d8817e4Smiod   for (next_fragP = fragP; next_fragP != NULL;
9524*3d8817e4Smiod        next_fragP = next_fragP->fr_next)
9525*3d8817e4Smiod     {
9526*3d8817e4Smiod       next_fragP->tc_frag_data.is_no_transform = TRUE;
9527*3d8817e4Smiod       if (next_fragP->tc_frag_data.is_loop_target)
9528*3d8817e4Smiod 	target_count++;
9529*3d8817e4Smiod       if (target_count == 2)
9530*3d8817e4Smiod 	break;
9531*3d8817e4Smiod     }
9532*3d8817e4Smiod }
9533*3d8817e4Smiod 
9534*3d8817e4Smiod 
9535*3d8817e4Smiod /* A map that keeps information on a per-subsegment basis.  This is
9536*3d8817e4Smiod    maintained during initial assembly, but is invalid once the
9537*3d8817e4Smiod    subsegments are smashed together.  I.E., it cannot be used during
9538*3d8817e4Smiod    the relaxation.  */
9539*3d8817e4Smiod 
9540*3d8817e4Smiod typedef struct subseg_map_struct
9541*3d8817e4Smiod {
9542*3d8817e4Smiod   /* the key */
9543*3d8817e4Smiod   segT seg;
9544*3d8817e4Smiod   subsegT subseg;
9545*3d8817e4Smiod 
9546*3d8817e4Smiod   /* the data */
9547*3d8817e4Smiod   unsigned flags;
9548*3d8817e4Smiod   float total_freq;	/* fall-through + branch target frequency */
9549*3d8817e4Smiod   float target_freq;	/* branch target frequency alone */
9550*3d8817e4Smiod 
9551*3d8817e4Smiod   struct subseg_map_struct *next;
9552*3d8817e4Smiod } subseg_map;
9553*3d8817e4Smiod 
9554*3d8817e4Smiod 
9555*3d8817e4Smiod static subseg_map *sseg_map = NULL;
9556*3d8817e4Smiod 
9557*3d8817e4Smiod static subseg_map *
get_subseg_info(segT seg,subsegT subseg)9558*3d8817e4Smiod get_subseg_info (segT seg, subsegT subseg)
9559*3d8817e4Smiod {
9560*3d8817e4Smiod   subseg_map *subseg_e;
9561*3d8817e4Smiod 
9562*3d8817e4Smiod   for (subseg_e = sseg_map; subseg_e; subseg_e = subseg_e->next)
9563*3d8817e4Smiod     {
9564*3d8817e4Smiod       if (seg == subseg_e->seg && subseg == subseg_e->subseg)
9565*3d8817e4Smiod 	break;
9566*3d8817e4Smiod     }
9567*3d8817e4Smiod   return subseg_e;
9568*3d8817e4Smiod }
9569*3d8817e4Smiod 
9570*3d8817e4Smiod 
9571*3d8817e4Smiod static subseg_map *
add_subseg_info(segT seg,subsegT subseg)9572*3d8817e4Smiod add_subseg_info (segT seg, subsegT subseg)
9573*3d8817e4Smiod {
9574*3d8817e4Smiod   subseg_map *subseg_e = (subseg_map *) xmalloc (sizeof (subseg_map));
9575*3d8817e4Smiod   memset (subseg_e, 0, sizeof (subseg_map));
9576*3d8817e4Smiod   subseg_e->seg = seg;
9577*3d8817e4Smiod   subseg_e->subseg = subseg;
9578*3d8817e4Smiod   subseg_e->flags = 0;
9579*3d8817e4Smiod   /* Start off considering every branch target very important.  */
9580*3d8817e4Smiod   subseg_e->target_freq = 1.0;
9581*3d8817e4Smiod   subseg_e->total_freq = 1.0;
9582*3d8817e4Smiod   subseg_e->next = sseg_map;
9583*3d8817e4Smiod   sseg_map = subseg_e;
9584*3d8817e4Smiod   return subseg_e;
9585*3d8817e4Smiod }
9586*3d8817e4Smiod 
9587*3d8817e4Smiod 
9588*3d8817e4Smiod static unsigned
get_last_insn_flags(segT seg,subsegT subseg)9589*3d8817e4Smiod get_last_insn_flags (segT seg, subsegT subseg)
9590*3d8817e4Smiod {
9591*3d8817e4Smiod   subseg_map *subseg_e = get_subseg_info (seg, subseg);
9592*3d8817e4Smiod   if (subseg_e)
9593*3d8817e4Smiod     return subseg_e->flags;
9594*3d8817e4Smiod   return 0;
9595*3d8817e4Smiod }
9596*3d8817e4Smiod 
9597*3d8817e4Smiod 
9598*3d8817e4Smiod static void
set_last_insn_flags(segT seg,subsegT subseg,unsigned fl,bfd_boolean val)9599*3d8817e4Smiod set_last_insn_flags (segT seg,
9600*3d8817e4Smiod 		     subsegT subseg,
9601*3d8817e4Smiod 		     unsigned fl,
9602*3d8817e4Smiod 		     bfd_boolean val)
9603*3d8817e4Smiod {
9604*3d8817e4Smiod   subseg_map *subseg_e = get_subseg_info (seg, subseg);
9605*3d8817e4Smiod   if (! subseg_e)
9606*3d8817e4Smiod     subseg_e = add_subseg_info (seg, subseg);
9607*3d8817e4Smiod   if (val)
9608*3d8817e4Smiod     subseg_e->flags |= fl;
9609*3d8817e4Smiod   else
9610*3d8817e4Smiod     subseg_e->flags &= ~fl;
9611*3d8817e4Smiod }
9612*3d8817e4Smiod 
9613*3d8817e4Smiod 
9614*3d8817e4Smiod static float
get_subseg_total_freq(segT seg,subsegT subseg)9615*3d8817e4Smiod get_subseg_total_freq (segT seg, subsegT subseg)
9616*3d8817e4Smiod {
9617*3d8817e4Smiod   subseg_map *subseg_e = get_subseg_info (seg, subseg);
9618*3d8817e4Smiod   if (subseg_e)
9619*3d8817e4Smiod     return subseg_e->total_freq;
9620*3d8817e4Smiod   return 1.0;
9621*3d8817e4Smiod }
9622*3d8817e4Smiod 
9623*3d8817e4Smiod 
9624*3d8817e4Smiod static float
get_subseg_target_freq(segT seg,subsegT subseg)9625*3d8817e4Smiod get_subseg_target_freq (segT seg, subsegT subseg)
9626*3d8817e4Smiod {
9627*3d8817e4Smiod   subseg_map *subseg_e = get_subseg_info (seg, subseg);
9628*3d8817e4Smiod   if (subseg_e)
9629*3d8817e4Smiod     return subseg_e->target_freq;
9630*3d8817e4Smiod   return 1.0;
9631*3d8817e4Smiod }
9632*3d8817e4Smiod 
9633*3d8817e4Smiod 
9634*3d8817e4Smiod static void
set_subseg_freq(segT seg,subsegT subseg,float total_f,float target_f)9635*3d8817e4Smiod set_subseg_freq (segT seg, subsegT subseg, float total_f, float target_f)
9636*3d8817e4Smiod {
9637*3d8817e4Smiod   subseg_map *subseg_e = get_subseg_info (seg, subseg);
9638*3d8817e4Smiod   if (! subseg_e)
9639*3d8817e4Smiod     subseg_e = add_subseg_info (seg, subseg);
9640*3d8817e4Smiod   subseg_e->total_freq = total_f;
9641*3d8817e4Smiod   subseg_e->target_freq = target_f;
9642*3d8817e4Smiod }
9643*3d8817e4Smiod 
9644*3d8817e4Smiod 
9645*3d8817e4Smiod /* Segment Lists and emit_state Stuff.  */
9646*3d8817e4Smiod 
9647*3d8817e4Smiod static void
xtensa_move_seg_list_to_beginning(seg_list * head)9648*3d8817e4Smiod xtensa_move_seg_list_to_beginning (seg_list *head)
9649*3d8817e4Smiod {
9650*3d8817e4Smiod   head = head->next;
9651*3d8817e4Smiod   while (head)
9652*3d8817e4Smiod     {
9653*3d8817e4Smiod       segT literal_section = head->seg;
9654*3d8817e4Smiod 
9655*3d8817e4Smiod       /* Move the literal section to the front of the section list.  */
9656*3d8817e4Smiod       assert (literal_section);
9657*3d8817e4Smiod       if (literal_section != stdoutput->sections)
9658*3d8817e4Smiod 	{
9659*3d8817e4Smiod 	  bfd_section_list_remove (stdoutput, literal_section);
9660*3d8817e4Smiod 	  bfd_section_list_prepend (stdoutput, literal_section);
9661*3d8817e4Smiod 	}
9662*3d8817e4Smiod       head = head->next;
9663*3d8817e4Smiod     }
9664*3d8817e4Smiod }
9665*3d8817e4Smiod 
9666*3d8817e4Smiod 
9667*3d8817e4Smiod static void mark_literal_frags (seg_list *);
9668*3d8817e4Smiod 
9669*3d8817e4Smiod static void
xtensa_move_literals(void)9670*3d8817e4Smiod xtensa_move_literals (void)
9671*3d8817e4Smiod {
9672*3d8817e4Smiod   seg_list *segment;
9673*3d8817e4Smiod   frchainS *frchain_from, *frchain_to;
9674*3d8817e4Smiod   fragS *search_frag, *next_frag, *last_frag, *literal_pool, *insert_after;
9675*3d8817e4Smiod   fragS **frag_splice;
9676*3d8817e4Smiod   emit_state state;
9677*3d8817e4Smiod   segT dest_seg;
9678*3d8817e4Smiod   fixS *fix, *next_fix, **fix_splice;
9679*3d8817e4Smiod   sym_list *lit;
9680*3d8817e4Smiod 
9681*3d8817e4Smiod   mark_literal_frags (literal_head->next);
9682*3d8817e4Smiod   mark_literal_frags (init_literal_head->next);
9683*3d8817e4Smiod   mark_literal_frags (fini_literal_head->next);
9684*3d8817e4Smiod 
9685*3d8817e4Smiod   if (use_literal_section)
9686*3d8817e4Smiod     return;
9687*3d8817e4Smiod 
9688*3d8817e4Smiod   segment = literal_head->next;
9689*3d8817e4Smiod   while (segment)
9690*3d8817e4Smiod     {
9691*3d8817e4Smiod       frchain_from = seg_info (segment->seg)->frchainP;
9692*3d8817e4Smiod       search_frag = frchain_from->frch_root;
9693*3d8817e4Smiod       literal_pool = NULL;
9694*3d8817e4Smiod       frchain_to = NULL;
9695*3d8817e4Smiod       frag_splice = &(frchain_from->frch_root);
9696*3d8817e4Smiod 
9697*3d8817e4Smiod       while (!search_frag->tc_frag_data.literal_frag)
9698*3d8817e4Smiod 	{
9699*3d8817e4Smiod 	  assert (search_frag->fr_fix == 0
9700*3d8817e4Smiod 		  || search_frag->fr_type == rs_align);
9701*3d8817e4Smiod 	  search_frag = search_frag->fr_next;
9702*3d8817e4Smiod 	}
9703*3d8817e4Smiod 
9704*3d8817e4Smiod       assert (search_frag->tc_frag_data.literal_frag->fr_subtype
9705*3d8817e4Smiod 	      == RELAX_LITERAL_POOL_BEGIN);
9706*3d8817e4Smiod       xtensa_switch_section_emit_state (&state, segment->seg, 0);
9707*3d8817e4Smiod 
9708*3d8817e4Smiod       /* Make sure that all the frags in this series are closed, and
9709*3d8817e4Smiod 	 that there is at least one left over of zero-size.  This
9710*3d8817e4Smiod 	 prevents us from making a segment with an frchain without any
9711*3d8817e4Smiod 	 frags in it.  */
9712*3d8817e4Smiod       frag_variant (rs_fill, 0, 0, 0, NULL, 0, NULL);
9713*3d8817e4Smiod       xtensa_set_frag_assembly_state (frag_now);
9714*3d8817e4Smiod       last_frag = frag_now;
9715*3d8817e4Smiod       frag_variant (rs_fill, 0, 0, 0, NULL, 0, NULL);
9716*3d8817e4Smiod       xtensa_set_frag_assembly_state (frag_now);
9717*3d8817e4Smiod 
9718*3d8817e4Smiod       while (search_frag != frag_now)
9719*3d8817e4Smiod 	{
9720*3d8817e4Smiod 	  next_frag = search_frag->fr_next;
9721*3d8817e4Smiod 
9722*3d8817e4Smiod 	  /* First, move the frag out of the literal section and
9723*3d8817e4Smiod 	     to the appropriate place.  */
9724*3d8817e4Smiod 	  if (search_frag->tc_frag_data.literal_frag)
9725*3d8817e4Smiod 	    {
9726*3d8817e4Smiod 	      literal_pool = search_frag->tc_frag_data.literal_frag;
9727*3d8817e4Smiod 	      assert (literal_pool->fr_subtype == RELAX_LITERAL_POOL_BEGIN);
9728*3d8817e4Smiod 	      frchain_to = literal_pool->tc_frag_data.lit_frchain;
9729*3d8817e4Smiod 	      assert (frchain_to);
9730*3d8817e4Smiod 	    }
9731*3d8817e4Smiod 	  insert_after = literal_pool;
9732*3d8817e4Smiod 
9733*3d8817e4Smiod 	  while (insert_after->fr_next->fr_subtype != RELAX_LITERAL_POOL_END)
9734*3d8817e4Smiod 	    insert_after = insert_after->fr_next;
9735*3d8817e4Smiod 
9736*3d8817e4Smiod 	  dest_seg = insert_after->fr_next->tc_frag_data.lit_seg;
9737*3d8817e4Smiod 
9738*3d8817e4Smiod 	  *frag_splice = next_frag;
9739*3d8817e4Smiod 	  search_frag->fr_next = insert_after->fr_next;
9740*3d8817e4Smiod 	  insert_after->fr_next = search_frag;
9741*3d8817e4Smiod 	  search_frag->tc_frag_data.lit_seg = dest_seg;
9742*3d8817e4Smiod 
9743*3d8817e4Smiod 	  /* Now move any fixups associated with this frag to the
9744*3d8817e4Smiod 	     right section.  */
9745*3d8817e4Smiod 	  fix = frchain_from->fix_root;
9746*3d8817e4Smiod 	  fix_splice = &(frchain_from->fix_root);
9747*3d8817e4Smiod 	  while (fix)
9748*3d8817e4Smiod 	    {
9749*3d8817e4Smiod 	      next_fix = fix->fx_next;
9750*3d8817e4Smiod 	      if (fix->fx_frag == search_frag)
9751*3d8817e4Smiod 		{
9752*3d8817e4Smiod 		  *fix_splice = next_fix;
9753*3d8817e4Smiod 		  fix->fx_next = frchain_to->fix_root;
9754*3d8817e4Smiod 		  frchain_to->fix_root = fix;
9755*3d8817e4Smiod 		  if (frchain_to->fix_tail == NULL)
9756*3d8817e4Smiod 		    frchain_to->fix_tail = fix;
9757*3d8817e4Smiod 		}
9758*3d8817e4Smiod 	      else
9759*3d8817e4Smiod 		fix_splice = &(fix->fx_next);
9760*3d8817e4Smiod 	      fix = next_fix;
9761*3d8817e4Smiod 	    }
9762*3d8817e4Smiod 	  search_frag = next_frag;
9763*3d8817e4Smiod 	}
9764*3d8817e4Smiod 
9765*3d8817e4Smiod       if (frchain_from->fix_root != NULL)
9766*3d8817e4Smiod 	{
9767*3d8817e4Smiod 	  frchain_from = seg_info (segment->seg)->frchainP;
9768*3d8817e4Smiod 	  as_warn (_("fixes not all moved from %s"), segment->seg->name);
9769*3d8817e4Smiod 
9770*3d8817e4Smiod 	  assert (frchain_from->fix_root == NULL);
9771*3d8817e4Smiod 	}
9772*3d8817e4Smiod       frchain_from->fix_tail = NULL;
9773*3d8817e4Smiod       xtensa_restore_emit_state (&state);
9774*3d8817e4Smiod       segment = segment->next;
9775*3d8817e4Smiod     }
9776*3d8817e4Smiod 
9777*3d8817e4Smiod   /* Now fix up the SEGMENT value for all the literal symbols.  */
9778*3d8817e4Smiod   for (lit = literal_syms; lit; lit = lit->next)
9779*3d8817e4Smiod     {
9780*3d8817e4Smiod       symbolS *lit_sym = lit->sym;
9781*3d8817e4Smiod       segT dest_seg = symbol_get_frag (lit_sym)->tc_frag_data.lit_seg;
9782*3d8817e4Smiod       if (dest_seg)
9783*3d8817e4Smiod 	S_SET_SEGMENT (lit_sym, dest_seg);
9784*3d8817e4Smiod     }
9785*3d8817e4Smiod }
9786*3d8817e4Smiod 
9787*3d8817e4Smiod 
9788*3d8817e4Smiod /* Walk over all the frags for segments in a list and mark them as
9789*3d8817e4Smiod    containing literals.  As clunky as this is, we can't rely on frag_var
9790*3d8817e4Smiod    and frag_variant to get called in all situations.  */
9791*3d8817e4Smiod 
9792*3d8817e4Smiod static void
mark_literal_frags(seg_list * segment)9793*3d8817e4Smiod mark_literal_frags (seg_list *segment)
9794*3d8817e4Smiod {
9795*3d8817e4Smiod   frchainS *frchain_from;
9796*3d8817e4Smiod   fragS *search_frag;
9797*3d8817e4Smiod 
9798*3d8817e4Smiod   while (segment)
9799*3d8817e4Smiod     {
9800*3d8817e4Smiod       frchain_from = seg_info (segment->seg)->frchainP;
9801*3d8817e4Smiod       search_frag = frchain_from->frch_root;
9802*3d8817e4Smiod       while (search_frag)
9803*3d8817e4Smiod 	{
9804*3d8817e4Smiod 	  search_frag->tc_frag_data.is_literal = TRUE;
9805*3d8817e4Smiod 	  search_frag = search_frag->fr_next;
9806*3d8817e4Smiod 	}
9807*3d8817e4Smiod       segment = segment->next;
9808*3d8817e4Smiod     }
9809*3d8817e4Smiod }
9810*3d8817e4Smiod 
9811*3d8817e4Smiod 
9812*3d8817e4Smiod static void
xtensa_reorder_seg_list(seg_list * head,segT after)9813*3d8817e4Smiod xtensa_reorder_seg_list (seg_list *head, segT after)
9814*3d8817e4Smiod {
9815*3d8817e4Smiod   /* Move all of the sections in the section list to come
9816*3d8817e4Smiod      after "after" in the gnu segment list.  */
9817*3d8817e4Smiod 
9818*3d8817e4Smiod   head = head->next;
9819*3d8817e4Smiod   while (head)
9820*3d8817e4Smiod     {
9821*3d8817e4Smiod       segT literal_section = head->seg;
9822*3d8817e4Smiod 
9823*3d8817e4Smiod       /* Move the literal section after "after".  */
9824*3d8817e4Smiod       assert (literal_section);
9825*3d8817e4Smiod       if (literal_section != after)
9826*3d8817e4Smiod 	{
9827*3d8817e4Smiod 	  bfd_section_list_remove (stdoutput, literal_section);
9828*3d8817e4Smiod 	  bfd_section_list_insert_after (stdoutput, after, literal_section);
9829*3d8817e4Smiod 	}
9830*3d8817e4Smiod 
9831*3d8817e4Smiod       head = head->next;
9832*3d8817e4Smiod     }
9833*3d8817e4Smiod }
9834*3d8817e4Smiod 
9835*3d8817e4Smiod 
9836*3d8817e4Smiod /* Push all the literal segments to the end of the gnu list.  */
9837*3d8817e4Smiod 
9838*3d8817e4Smiod static void
xtensa_reorder_segments(void)9839*3d8817e4Smiod xtensa_reorder_segments (void)
9840*3d8817e4Smiod {
9841*3d8817e4Smiod   segT sec;
9842*3d8817e4Smiod   segT last_sec = 0;
9843*3d8817e4Smiod   int old_count = 0;
9844*3d8817e4Smiod   int new_count = 0;
9845*3d8817e4Smiod 
9846*3d8817e4Smiod   for (sec = stdoutput->sections; sec != NULL; sec = sec->next)
9847*3d8817e4Smiod     {
9848*3d8817e4Smiod       last_sec = sec;
9849*3d8817e4Smiod       old_count++;
9850*3d8817e4Smiod     }
9851*3d8817e4Smiod 
9852*3d8817e4Smiod   /* Now that we have the last section, push all the literal
9853*3d8817e4Smiod      sections to the end.  */
9854*3d8817e4Smiod   xtensa_reorder_seg_list (literal_head, last_sec);
9855*3d8817e4Smiod   xtensa_reorder_seg_list (init_literal_head, last_sec);
9856*3d8817e4Smiod   xtensa_reorder_seg_list (fini_literal_head, last_sec);
9857*3d8817e4Smiod 
9858*3d8817e4Smiod   /* Now perform the final error check.  */
9859*3d8817e4Smiod   for (sec = stdoutput->sections; sec != NULL; sec = sec->next)
9860*3d8817e4Smiod     new_count++;
9861*3d8817e4Smiod   assert (new_count == old_count);
9862*3d8817e4Smiod }
9863*3d8817e4Smiod 
9864*3d8817e4Smiod 
9865*3d8817e4Smiod /* Change the emit state (seg, subseg, and frag related stuff) to the
9866*3d8817e4Smiod    correct location.  Return a emit_state which can be passed to
9867*3d8817e4Smiod    xtensa_restore_emit_state to return to current fragment.  */
9868*3d8817e4Smiod 
9869*3d8817e4Smiod static void
xtensa_switch_to_literal_fragment(emit_state * result)9870*3d8817e4Smiod xtensa_switch_to_literal_fragment (emit_state *result)
9871*3d8817e4Smiod {
9872*3d8817e4Smiod   if (directive_state[directive_absolute_literals])
9873*3d8817e4Smiod     {
9874*3d8817e4Smiod       cache_literal_section (0, default_lit_sections.lit4_seg_name,
9875*3d8817e4Smiod 			     &default_lit_sections.lit4_seg, FALSE);
9876*3d8817e4Smiod       xtensa_switch_section_emit_state (result,
9877*3d8817e4Smiod 					default_lit_sections.lit4_seg, 0);
9878*3d8817e4Smiod     }
9879*3d8817e4Smiod   else
9880*3d8817e4Smiod     xtensa_switch_to_non_abs_literal_fragment (result);
9881*3d8817e4Smiod 
9882*3d8817e4Smiod   /* Do a 4-byte align here.  */
9883*3d8817e4Smiod   frag_align (2, 0, 0);
9884*3d8817e4Smiod   record_alignment (now_seg, 2);
9885*3d8817e4Smiod }
9886*3d8817e4Smiod 
9887*3d8817e4Smiod 
9888*3d8817e4Smiod static void
xtensa_switch_to_non_abs_literal_fragment(emit_state * result)9889*3d8817e4Smiod xtensa_switch_to_non_abs_literal_fragment (emit_state *result)
9890*3d8817e4Smiod {
9891*3d8817e4Smiod   /* When we mark a literal pool location, we want to put a frag in
9892*3d8817e4Smiod      the literal pool that points to it.  But to do that, we want to
9893*3d8817e4Smiod      switch_to_literal_fragment.  But literal sections don't have
9894*3d8817e4Smiod      literal pools, so their location is always null, so we would
9895*3d8817e4Smiod      recurse forever.  This is kind of hacky, but it works.  */
9896*3d8817e4Smiod 
9897*3d8817e4Smiod   static bfd_boolean recursive = FALSE;
9898*3d8817e4Smiod   fragS *pool_location = get_literal_pool_location (now_seg);
9899*3d8817e4Smiod   bfd_boolean is_init =
9900*3d8817e4Smiod     (now_seg && !strcmp (segment_name (now_seg), INIT_SECTION_NAME));
9901*3d8817e4Smiod 
9902*3d8817e4Smiod   bfd_boolean is_fini =
9903*3d8817e4Smiod     (now_seg && !strcmp (segment_name (now_seg), FINI_SECTION_NAME));
9904*3d8817e4Smiod 
9905*3d8817e4Smiod   if (pool_location == NULL
9906*3d8817e4Smiod       && !use_literal_section
9907*3d8817e4Smiod       && !recursive
9908*3d8817e4Smiod       && !is_init && ! is_fini)
9909*3d8817e4Smiod     {
9910*3d8817e4Smiod       as_bad (_("literal pool location required for text-section-literals; specify with .literal_position"));
9911*3d8817e4Smiod       recursive = TRUE;
9912*3d8817e4Smiod       xtensa_mark_literal_pool_location ();
9913*3d8817e4Smiod       recursive = FALSE;
9914*3d8817e4Smiod     }
9915*3d8817e4Smiod 
9916*3d8817e4Smiod   /* Special case: If we are in the ".fini" or ".init" section, then
9917*3d8817e4Smiod      we will ALWAYS be generating to the ".fini.literal" and
9918*3d8817e4Smiod      ".init.literal" sections.  */
9919*3d8817e4Smiod 
9920*3d8817e4Smiod   if (is_init)
9921*3d8817e4Smiod     {
9922*3d8817e4Smiod       cache_literal_section (init_literal_head,
9923*3d8817e4Smiod 			     default_lit_sections.init_lit_seg_name,
9924*3d8817e4Smiod 			     &default_lit_sections.init_lit_seg, TRUE);
9925*3d8817e4Smiod       xtensa_switch_section_emit_state (result,
9926*3d8817e4Smiod 					default_lit_sections.init_lit_seg, 0);
9927*3d8817e4Smiod     }
9928*3d8817e4Smiod   else if (is_fini)
9929*3d8817e4Smiod     {
9930*3d8817e4Smiod       cache_literal_section (fini_literal_head,
9931*3d8817e4Smiod 			     default_lit_sections.fini_lit_seg_name,
9932*3d8817e4Smiod 			     &default_lit_sections.fini_lit_seg, TRUE);
9933*3d8817e4Smiod       xtensa_switch_section_emit_state (result,
9934*3d8817e4Smiod 					default_lit_sections.fini_lit_seg, 0);
9935*3d8817e4Smiod     }
9936*3d8817e4Smiod   else
9937*3d8817e4Smiod     {
9938*3d8817e4Smiod       cache_literal_section (literal_head,
9939*3d8817e4Smiod 			     default_lit_sections.lit_seg_name,
9940*3d8817e4Smiod 			     &default_lit_sections.lit_seg, TRUE);
9941*3d8817e4Smiod       xtensa_switch_section_emit_state (result,
9942*3d8817e4Smiod 					default_lit_sections.lit_seg, 0);
9943*3d8817e4Smiod     }
9944*3d8817e4Smiod 
9945*3d8817e4Smiod   if (!use_literal_section
9946*3d8817e4Smiod       && !is_init && !is_fini
9947*3d8817e4Smiod       && get_literal_pool_location (now_seg) != pool_location)
9948*3d8817e4Smiod     {
9949*3d8817e4Smiod       /* Close whatever frag is there.  */
9950*3d8817e4Smiod       frag_variant (rs_fill, 0, 0, 0, NULL, 0, NULL);
9951*3d8817e4Smiod       xtensa_set_frag_assembly_state (frag_now);
9952*3d8817e4Smiod       frag_now->tc_frag_data.literal_frag = pool_location;
9953*3d8817e4Smiod       frag_variant (rs_fill, 0, 0, 0, NULL, 0, NULL);
9954*3d8817e4Smiod       xtensa_set_frag_assembly_state (frag_now);
9955*3d8817e4Smiod     }
9956*3d8817e4Smiod }
9957*3d8817e4Smiod 
9958*3d8817e4Smiod 
9959*3d8817e4Smiod /* Call this function before emitting data into the literal section.
9960*3d8817e4Smiod    This is a helper function for xtensa_switch_to_literal_fragment.
9961*3d8817e4Smiod    This is similar to a .section new_now_seg subseg. */
9962*3d8817e4Smiod 
9963*3d8817e4Smiod static void
xtensa_switch_section_emit_state(emit_state * state,segT new_now_seg,subsegT new_now_subseg)9964*3d8817e4Smiod xtensa_switch_section_emit_state (emit_state *state,
9965*3d8817e4Smiod 				  segT new_now_seg,
9966*3d8817e4Smiod 				  subsegT new_now_subseg)
9967*3d8817e4Smiod {
9968*3d8817e4Smiod   state->name = now_seg->name;
9969*3d8817e4Smiod   state->now_seg = now_seg;
9970*3d8817e4Smiod   state->now_subseg = now_subseg;
9971*3d8817e4Smiod   state->generating_literals = generating_literals;
9972*3d8817e4Smiod   generating_literals++;
9973*3d8817e4Smiod   subseg_set (new_now_seg, new_now_subseg);
9974*3d8817e4Smiod }
9975*3d8817e4Smiod 
9976*3d8817e4Smiod 
9977*3d8817e4Smiod /* Use to restore the emitting into the normal place.  */
9978*3d8817e4Smiod 
9979*3d8817e4Smiod static void
xtensa_restore_emit_state(emit_state * state)9980*3d8817e4Smiod xtensa_restore_emit_state (emit_state *state)
9981*3d8817e4Smiod {
9982*3d8817e4Smiod   generating_literals = state->generating_literals;
9983*3d8817e4Smiod   subseg_set (state->now_seg, state->now_subseg);
9984*3d8817e4Smiod }
9985*3d8817e4Smiod 
9986*3d8817e4Smiod 
9987*3d8817e4Smiod /* Get a segment of a given name.  If the segment is already
9988*3d8817e4Smiod    present, return it; otherwise, create a new one.  */
9989*3d8817e4Smiod 
9990*3d8817e4Smiod static void
cache_literal_section(seg_list * head,const char * name,segT * pseg,bfd_boolean is_code)9991*3d8817e4Smiod cache_literal_section (seg_list *head,
9992*3d8817e4Smiod 		       const char *name,
9993*3d8817e4Smiod 		       segT *pseg,
9994*3d8817e4Smiod 		       bfd_boolean is_code)
9995*3d8817e4Smiod {
9996*3d8817e4Smiod   segT current_section = now_seg;
9997*3d8817e4Smiod   int current_subsec = now_subseg;
9998*3d8817e4Smiod   segT seg;
9999*3d8817e4Smiod 
10000*3d8817e4Smiod   if (*pseg != 0)
10001*3d8817e4Smiod     return;
10002*3d8817e4Smiod 
10003*3d8817e4Smiod   /* Check if the named section exists.  */
10004*3d8817e4Smiod   for (seg = stdoutput->sections; seg; seg = seg->next)
10005*3d8817e4Smiod     {
10006*3d8817e4Smiod       if (!strcmp (segment_name (seg), name))
10007*3d8817e4Smiod 	break;
10008*3d8817e4Smiod     }
10009*3d8817e4Smiod 
10010*3d8817e4Smiod   if (!seg)
10011*3d8817e4Smiod     {
10012*3d8817e4Smiod       /* Create a new literal section.  */
10013*3d8817e4Smiod       seg = subseg_new (name, (subsegT) 0);
10014*3d8817e4Smiod       if (head)
10015*3d8817e4Smiod 	{
10016*3d8817e4Smiod 	  /* Add the newly created literal segment to the specified list.  */
10017*3d8817e4Smiod 	  seg_list *n = (seg_list *) xmalloc (sizeof (seg_list));
10018*3d8817e4Smiod 	  n->seg = seg;
10019*3d8817e4Smiod 	  n->next = head->next;
10020*3d8817e4Smiod 	  head->next = n;
10021*3d8817e4Smiod 	}
10022*3d8817e4Smiod       bfd_set_section_flags (stdoutput, seg, SEC_HAS_CONTENTS |
10023*3d8817e4Smiod 			     SEC_READONLY | SEC_ALLOC | SEC_LOAD
10024*3d8817e4Smiod 			     | (is_code ? SEC_CODE : SEC_DATA));
10025*3d8817e4Smiod       bfd_set_section_alignment (stdoutput, seg, 2);
10026*3d8817e4Smiod     }
10027*3d8817e4Smiod 
10028*3d8817e4Smiod   *pseg = seg;
10029*3d8817e4Smiod   subseg_set (current_section, current_subsec);
10030*3d8817e4Smiod }
10031*3d8817e4Smiod 
10032*3d8817e4Smiod 
10033*3d8817e4Smiod /* Property Tables Stuff.  */
10034*3d8817e4Smiod 
10035*3d8817e4Smiod #define XTENSA_INSN_SEC_NAME ".xt.insn"
10036*3d8817e4Smiod #define XTENSA_LIT_SEC_NAME ".xt.lit"
10037*3d8817e4Smiod #define XTENSA_PROP_SEC_NAME ".xt.prop"
10038*3d8817e4Smiod 
10039*3d8817e4Smiod typedef bfd_boolean (*frag_predicate) (const fragS *);
10040*3d8817e4Smiod typedef void (*frag_flags_fn) (const fragS *, frag_flags *);
10041*3d8817e4Smiod 
10042*3d8817e4Smiod static bfd_boolean get_frag_is_literal (const fragS *);
10043*3d8817e4Smiod static void xtensa_create_property_segments
10044*3d8817e4Smiod   (frag_predicate, frag_predicate, const char *, xt_section_type);
10045*3d8817e4Smiod static void xtensa_create_xproperty_segments
10046*3d8817e4Smiod   (frag_flags_fn, const char *, xt_section_type);
10047*3d8817e4Smiod static segment_info_type *retrieve_segment_info (segT);
10048*3d8817e4Smiod static segT retrieve_xtensa_section (char *);
10049*3d8817e4Smiod static bfd_boolean section_has_property (segT, frag_predicate);
10050*3d8817e4Smiod static bfd_boolean section_has_xproperty (segT, frag_flags_fn);
10051*3d8817e4Smiod static void add_xt_block_frags
10052*3d8817e4Smiod   (segT, segT, xtensa_block_info **, frag_predicate, frag_predicate);
10053*3d8817e4Smiod static bfd_boolean xtensa_frag_flags_is_empty (const frag_flags *);
10054*3d8817e4Smiod static void xtensa_frag_flags_init (frag_flags *);
10055*3d8817e4Smiod static void get_frag_property_flags (const fragS *, frag_flags *);
10056*3d8817e4Smiod static bfd_vma frag_flags_to_number (const frag_flags *);
10057*3d8817e4Smiod static void add_xt_prop_frags
10058*3d8817e4Smiod   (segT, segT, xtensa_block_info **, frag_flags_fn);
10059*3d8817e4Smiod 
10060*3d8817e4Smiod /* Set up property tables after relaxation.  */
10061*3d8817e4Smiod 
10062*3d8817e4Smiod void
xtensa_post_relax_hook(void)10063*3d8817e4Smiod xtensa_post_relax_hook (void)
10064*3d8817e4Smiod {
10065*3d8817e4Smiod   xtensa_move_seg_list_to_beginning (literal_head);
10066*3d8817e4Smiod   xtensa_move_seg_list_to_beginning (init_literal_head);
10067*3d8817e4Smiod   xtensa_move_seg_list_to_beginning (fini_literal_head);
10068*3d8817e4Smiod 
10069*3d8817e4Smiod   xtensa_find_unmarked_state_frags ();
10070*3d8817e4Smiod 
10071*3d8817e4Smiod   xtensa_create_property_segments (get_frag_is_literal,
10072*3d8817e4Smiod 				   NULL,
10073*3d8817e4Smiod 				   XTENSA_LIT_SEC_NAME,
10074*3d8817e4Smiod 				   xt_literal_sec);
10075*3d8817e4Smiod   xtensa_create_xproperty_segments (get_frag_property_flags,
10076*3d8817e4Smiod 				    XTENSA_PROP_SEC_NAME,
10077*3d8817e4Smiod 				    xt_prop_sec);
10078*3d8817e4Smiod 
10079*3d8817e4Smiod   if (warn_unaligned_branch_targets)
10080*3d8817e4Smiod     bfd_map_over_sections (stdoutput, xtensa_find_unaligned_branch_targets, 0);
10081*3d8817e4Smiod   bfd_map_over_sections (stdoutput, xtensa_find_unaligned_loops, 0);
10082*3d8817e4Smiod }
10083*3d8817e4Smiod 
10084*3d8817e4Smiod 
10085*3d8817e4Smiod /* This function is only meaningful after xtensa_move_literals.  */
10086*3d8817e4Smiod 
10087*3d8817e4Smiod static bfd_boolean
get_frag_is_literal(const fragS * fragP)10088*3d8817e4Smiod get_frag_is_literal (const fragS *fragP)
10089*3d8817e4Smiod {
10090*3d8817e4Smiod   assert (fragP != NULL);
10091*3d8817e4Smiod   return fragP->tc_frag_data.is_literal;
10092*3d8817e4Smiod }
10093*3d8817e4Smiod 
10094*3d8817e4Smiod 
10095*3d8817e4Smiod static void
xtensa_create_property_segments(frag_predicate property_function,frag_predicate end_property_function,const char * section_name_base,xt_section_type sec_type)10096*3d8817e4Smiod xtensa_create_property_segments (frag_predicate property_function,
10097*3d8817e4Smiod 				 frag_predicate end_property_function,
10098*3d8817e4Smiod 				 const char *section_name_base,
10099*3d8817e4Smiod 				 xt_section_type sec_type)
10100*3d8817e4Smiod {
10101*3d8817e4Smiod   segT *seclist;
10102*3d8817e4Smiod 
10103*3d8817e4Smiod   /* Walk over all of the current segments.
10104*3d8817e4Smiod      Walk over each fragment
10105*3d8817e4Smiod      For each non-empty fragment,
10106*3d8817e4Smiod      Build a property record (append where possible).  */
10107*3d8817e4Smiod 
10108*3d8817e4Smiod   for (seclist = &stdoutput->sections;
10109*3d8817e4Smiod        seclist && *seclist;
10110*3d8817e4Smiod        seclist = &(*seclist)->next)
10111*3d8817e4Smiod     {
10112*3d8817e4Smiod       segT sec = *seclist;
10113*3d8817e4Smiod       flagword flags;
10114*3d8817e4Smiod 
10115*3d8817e4Smiod       flags = bfd_get_section_flags (stdoutput, sec);
10116*3d8817e4Smiod       if (flags & SEC_DEBUGGING)
10117*3d8817e4Smiod 	continue;
10118*3d8817e4Smiod       if (!(flags & SEC_ALLOC))
10119*3d8817e4Smiod 	continue;
10120*3d8817e4Smiod 
10121*3d8817e4Smiod       if (section_has_property (sec, property_function))
10122*3d8817e4Smiod 	{
10123*3d8817e4Smiod 	  char *property_section_name =
10124*3d8817e4Smiod 	    xtensa_get_property_section_name (sec, section_name_base);
10125*3d8817e4Smiod 	  segT insn_sec = retrieve_xtensa_section (property_section_name);
10126*3d8817e4Smiod 	  segment_info_type *xt_seg_info = retrieve_segment_info (insn_sec);
10127*3d8817e4Smiod 	  xtensa_block_info **xt_blocks =
10128*3d8817e4Smiod 	    &xt_seg_info->tc_segment_info_data.blocks[sec_type];
10129*3d8817e4Smiod 	  /* Walk over all of the frchains here and add new sections.  */
10130*3d8817e4Smiod 	  add_xt_block_frags (sec, insn_sec, xt_blocks, property_function,
10131*3d8817e4Smiod 			      end_property_function);
10132*3d8817e4Smiod 	}
10133*3d8817e4Smiod     }
10134*3d8817e4Smiod 
10135*3d8817e4Smiod   /* Now we fill them out....  */
10136*3d8817e4Smiod 
10137*3d8817e4Smiod   for (seclist = &stdoutput->sections;
10138*3d8817e4Smiod        seclist && *seclist;
10139*3d8817e4Smiod        seclist = &(*seclist)->next)
10140*3d8817e4Smiod     {
10141*3d8817e4Smiod       segment_info_type *seginfo;
10142*3d8817e4Smiod       xtensa_block_info *block;
10143*3d8817e4Smiod       segT sec = *seclist;
10144*3d8817e4Smiod 
10145*3d8817e4Smiod       seginfo = seg_info (sec);
10146*3d8817e4Smiod       block = seginfo->tc_segment_info_data.blocks[sec_type];
10147*3d8817e4Smiod 
10148*3d8817e4Smiod       if (block)
10149*3d8817e4Smiod 	{
10150*3d8817e4Smiod 	  xtensa_block_info *cur_block;
10151*3d8817e4Smiod 	  /* This is a section with some data.  */
10152*3d8817e4Smiod 	  int num_recs = 0;
10153*3d8817e4Smiod 	  bfd_size_type rec_size;
10154*3d8817e4Smiod 
10155*3d8817e4Smiod 	  for (cur_block = block; cur_block; cur_block = cur_block->next)
10156*3d8817e4Smiod 	    num_recs++;
10157*3d8817e4Smiod 
10158*3d8817e4Smiod 	  rec_size = num_recs * 8;
10159*3d8817e4Smiod 	  bfd_set_section_size (stdoutput, sec, rec_size);
10160*3d8817e4Smiod 
10161*3d8817e4Smiod 	  /* In order to make this work with the assembler, we have to
10162*3d8817e4Smiod 	     build some frags and then build the "fixups" for it.  It
10163*3d8817e4Smiod 	     would be easier to just set the contents then set the
10164*3d8817e4Smiod 	     arlents.  */
10165*3d8817e4Smiod 
10166*3d8817e4Smiod 	  if (num_recs)
10167*3d8817e4Smiod 	    {
10168*3d8817e4Smiod 	      /* Allocate a fragment and leak it.  */
10169*3d8817e4Smiod 	      fragS *fragP;
10170*3d8817e4Smiod 	      bfd_size_type frag_size;
10171*3d8817e4Smiod 	      fixS *fixes;
10172*3d8817e4Smiod 	      frchainS *frchainP;
10173*3d8817e4Smiod 	      int i;
10174*3d8817e4Smiod 	      char *frag_data;
10175*3d8817e4Smiod 
10176*3d8817e4Smiod 	      frag_size = sizeof (fragS) + rec_size;
10177*3d8817e4Smiod 	      fragP = (fragS *) xmalloc (frag_size);
10178*3d8817e4Smiod 
10179*3d8817e4Smiod 	      memset (fragP, 0, frag_size);
10180*3d8817e4Smiod 	      fragP->fr_address = 0;
10181*3d8817e4Smiod 	      fragP->fr_next = NULL;
10182*3d8817e4Smiod 	      fragP->fr_fix = rec_size;
10183*3d8817e4Smiod 	      fragP->fr_var = 0;
10184*3d8817e4Smiod 	      fragP->fr_type = rs_fill;
10185*3d8817e4Smiod 	      /* The rest are zeros.  */
10186*3d8817e4Smiod 
10187*3d8817e4Smiod 	      frchainP = seginfo->frchainP;
10188*3d8817e4Smiod 	      frchainP->frch_root = fragP;
10189*3d8817e4Smiod 	      frchainP->frch_last = fragP;
10190*3d8817e4Smiod 
10191*3d8817e4Smiod 	      fixes = (fixS *) xmalloc (sizeof (fixS) * num_recs);
10192*3d8817e4Smiod 	      memset (fixes, 0, sizeof (fixS) * num_recs);
10193*3d8817e4Smiod 
10194*3d8817e4Smiod 	      seginfo->fix_root = fixes;
10195*3d8817e4Smiod 	      seginfo->fix_tail = &fixes[num_recs - 1];
10196*3d8817e4Smiod 	      cur_block = block;
10197*3d8817e4Smiod 	      frag_data = &fragP->fr_literal[0];
10198*3d8817e4Smiod 	      for (i = 0; i < num_recs; i++)
10199*3d8817e4Smiod 		{
10200*3d8817e4Smiod 		  fixS *fix = &fixes[i];
10201*3d8817e4Smiod 		  assert (cur_block);
10202*3d8817e4Smiod 
10203*3d8817e4Smiod 		  /* Write the fixup.  */
10204*3d8817e4Smiod 		  if (i != num_recs - 1)
10205*3d8817e4Smiod 		    fix->fx_next = &fixes[i + 1];
10206*3d8817e4Smiod 		  else
10207*3d8817e4Smiod 		    fix->fx_next = NULL;
10208*3d8817e4Smiod 		  fix->fx_size = 4;
10209*3d8817e4Smiod 		  fix->fx_done = 0;
10210*3d8817e4Smiod 		  fix->fx_frag = fragP;
10211*3d8817e4Smiod 		  fix->fx_where = i * 8;
10212*3d8817e4Smiod 		  fix->fx_addsy = section_symbol (cur_block->sec);
10213*3d8817e4Smiod 		  fix->fx_offset = cur_block->offset;
10214*3d8817e4Smiod 		  fix->fx_r_type = BFD_RELOC_32;
10215*3d8817e4Smiod 		  fix->fx_file = "Internal Assembly";
10216*3d8817e4Smiod 		  fix->fx_line = 0;
10217*3d8817e4Smiod 
10218*3d8817e4Smiod 		  /* Write the length.  */
10219*3d8817e4Smiod 		  md_number_to_chars (&frag_data[4 + 8 * i],
10220*3d8817e4Smiod 				      cur_block->size, 4);
10221*3d8817e4Smiod 		  cur_block = cur_block->next;
10222*3d8817e4Smiod 		}
10223*3d8817e4Smiod 	    }
10224*3d8817e4Smiod 	}
10225*3d8817e4Smiod     }
10226*3d8817e4Smiod }
10227*3d8817e4Smiod 
10228*3d8817e4Smiod 
10229*3d8817e4Smiod static void
xtensa_create_xproperty_segments(frag_flags_fn flag_fn,const char * section_name_base,xt_section_type sec_type)10230*3d8817e4Smiod xtensa_create_xproperty_segments (frag_flags_fn flag_fn,
10231*3d8817e4Smiod 				  const char *section_name_base,
10232*3d8817e4Smiod 				  xt_section_type sec_type)
10233*3d8817e4Smiod {
10234*3d8817e4Smiod   segT *seclist;
10235*3d8817e4Smiod 
10236*3d8817e4Smiod   /* Walk over all of the current segments.
10237*3d8817e4Smiod      Walk over each fragment.
10238*3d8817e4Smiod      For each fragment that has instructions,
10239*3d8817e4Smiod      build an instruction record (append where possible).  */
10240*3d8817e4Smiod 
10241*3d8817e4Smiod   for (seclist = &stdoutput->sections;
10242*3d8817e4Smiod        seclist && *seclist;
10243*3d8817e4Smiod        seclist = &(*seclist)->next)
10244*3d8817e4Smiod     {
10245*3d8817e4Smiod       segT sec = *seclist;
10246*3d8817e4Smiod       flagword flags;
10247*3d8817e4Smiod 
10248*3d8817e4Smiod       flags = bfd_get_section_flags (stdoutput, sec);
10249*3d8817e4Smiod       if ((flags & SEC_DEBUGGING)
10250*3d8817e4Smiod 	  || !(flags & SEC_ALLOC)
10251*3d8817e4Smiod 	  || (flags & SEC_MERGE))
10252*3d8817e4Smiod 	continue;
10253*3d8817e4Smiod 
10254*3d8817e4Smiod       if (section_has_xproperty (sec, flag_fn))
10255*3d8817e4Smiod 	{
10256*3d8817e4Smiod 	  char *property_section_name =
10257*3d8817e4Smiod 	    xtensa_get_property_section_name (sec, section_name_base);
10258*3d8817e4Smiod 	  segT insn_sec = retrieve_xtensa_section (property_section_name);
10259*3d8817e4Smiod 	  segment_info_type *xt_seg_info = retrieve_segment_info (insn_sec);
10260*3d8817e4Smiod 	  xtensa_block_info **xt_blocks =
10261*3d8817e4Smiod 	    &xt_seg_info->tc_segment_info_data.blocks[sec_type];
10262*3d8817e4Smiod 	  /* Walk over all of the frchains here and add new sections.  */
10263*3d8817e4Smiod 	  add_xt_prop_frags (sec, insn_sec, xt_blocks, flag_fn);
10264*3d8817e4Smiod 	}
10265*3d8817e4Smiod     }
10266*3d8817e4Smiod 
10267*3d8817e4Smiod   /* Now we fill them out....  */
10268*3d8817e4Smiod 
10269*3d8817e4Smiod   for (seclist = &stdoutput->sections;
10270*3d8817e4Smiod        seclist && *seclist;
10271*3d8817e4Smiod        seclist = &(*seclist)->next)
10272*3d8817e4Smiod     {
10273*3d8817e4Smiod       segment_info_type *seginfo;
10274*3d8817e4Smiod       xtensa_block_info *block;
10275*3d8817e4Smiod       segT sec = *seclist;
10276*3d8817e4Smiod 
10277*3d8817e4Smiod       seginfo = seg_info (sec);
10278*3d8817e4Smiod       block = seginfo->tc_segment_info_data.blocks[sec_type];
10279*3d8817e4Smiod 
10280*3d8817e4Smiod       if (block)
10281*3d8817e4Smiod 	{
10282*3d8817e4Smiod 	  xtensa_block_info *cur_block;
10283*3d8817e4Smiod 	  /* This is a section with some data.  */
10284*3d8817e4Smiod 	  int num_recs = 0;
10285*3d8817e4Smiod 	  bfd_size_type rec_size;
10286*3d8817e4Smiod 
10287*3d8817e4Smiod 	  for (cur_block = block; cur_block; cur_block = cur_block->next)
10288*3d8817e4Smiod 	    num_recs++;
10289*3d8817e4Smiod 
10290*3d8817e4Smiod 	  rec_size = num_recs * (8 + 4);
10291*3d8817e4Smiod 	  bfd_set_section_size (stdoutput, sec, rec_size);
10292*3d8817e4Smiod 
10293*3d8817e4Smiod 	  /* elf_section_data (sec)->this_hdr.sh_entsize = 12; */
10294*3d8817e4Smiod 
10295*3d8817e4Smiod 	  /* In order to make this work with the assembler, we have to build
10296*3d8817e4Smiod 	     some frags then build the "fixups" for it.  It would be easier to
10297*3d8817e4Smiod 	     just set the contents then set the arlents.  */
10298*3d8817e4Smiod 
10299*3d8817e4Smiod 	  if (num_recs)
10300*3d8817e4Smiod 	    {
10301*3d8817e4Smiod 	      /* Allocate a fragment and (unfortunately) leak it.  */
10302*3d8817e4Smiod 	      fragS *fragP;
10303*3d8817e4Smiod 	      bfd_size_type frag_size;
10304*3d8817e4Smiod 	      fixS *fixes;
10305*3d8817e4Smiod 	      frchainS *frchainP;
10306*3d8817e4Smiod 	      int i;
10307*3d8817e4Smiod 	      char *frag_data;
10308*3d8817e4Smiod 
10309*3d8817e4Smiod 	      frag_size = sizeof (fragS) + rec_size;
10310*3d8817e4Smiod 	      fragP = (fragS *) xmalloc (frag_size);
10311*3d8817e4Smiod 
10312*3d8817e4Smiod 	      memset (fragP, 0, frag_size);
10313*3d8817e4Smiod 	      fragP->fr_address = 0;
10314*3d8817e4Smiod 	      fragP->fr_next = NULL;
10315*3d8817e4Smiod 	      fragP->fr_fix = rec_size;
10316*3d8817e4Smiod 	      fragP->fr_var = 0;
10317*3d8817e4Smiod 	      fragP->fr_type = rs_fill;
10318*3d8817e4Smiod 	      /* The rest are zeros.  */
10319*3d8817e4Smiod 
10320*3d8817e4Smiod 	      frchainP = seginfo->frchainP;
10321*3d8817e4Smiod 	      frchainP->frch_root = fragP;
10322*3d8817e4Smiod 	      frchainP->frch_last = fragP;
10323*3d8817e4Smiod 
10324*3d8817e4Smiod 	      fixes = (fixS *) xmalloc (sizeof (fixS) * num_recs);
10325*3d8817e4Smiod 	      memset (fixes, 0, sizeof (fixS) * num_recs);
10326*3d8817e4Smiod 
10327*3d8817e4Smiod 	      seginfo->fix_root = fixes;
10328*3d8817e4Smiod 	      seginfo->fix_tail = &fixes[num_recs - 1];
10329*3d8817e4Smiod 	      cur_block = block;
10330*3d8817e4Smiod 	      frag_data = &fragP->fr_literal[0];
10331*3d8817e4Smiod 	      for (i = 0; i < num_recs; i++)
10332*3d8817e4Smiod 		{
10333*3d8817e4Smiod 		  fixS *fix = &fixes[i];
10334*3d8817e4Smiod 		  assert (cur_block);
10335*3d8817e4Smiod 
10336*3d8817e4Smiod 		  /* Write the fixup.  */
10337*3d8817e4Smiod 		  if (i != num_recs - 1)
10338*3d8817e4Smiod 		    fix->fx_next = &fixes[i + 1];
10339*3d8817e4Smiod 		  else
10340*3d8817e4Smiod 		    fix->fx_next = NULL;
10341*3d8817e4Smiod 		  fix->fx_size = 4;
10342*3d8817e4Smiod 		  fix->fx_done = 0;
10343*3d8817e4Smiod 		  fix->fx_frag = fragP;
10344*3d8817e4Smiod 		  fix->fx_where = i * (8 + 4);
10345*3d8817e4Smiod 		  fix->fx_addsy = section_symbol (cur_block->sec);
10346*3d8817e4Smiod 		  fix->fx_offset = cur_block->offset;
10347*3d8817e4Smiod 		  fix->fx_r_type = BFD_RELOC_32;
10348*3d8817e4Smiod 		  fix->fx_file = "Internal Assembly";
10349*3d8817e4Smiod 		  fix->fx_line = 0;
10350*3d8817e4Smiod 
10351*3d8817e4Smiod 		  /* Write the length.  */
10352*3d8817e4Smiod 		  md_number_to_chars (&frag_data[4 + (8+4) * i],
10353*3d8817e4Smiod 				      cur_block->size, 4);
10354*3d8817e4Smiod 		  md_number_to_chars (&frag_data[8 + (8+4) * i],
10355*3d8817e4Smiod 				      frag_flags_to_number (&cur_block->flags),
10356*3d8817e4Smiod 				      4);
10357*3d8817e4Smiod 		  cur_block = cur_block->next;
10358*3d8817e4Smiod 		}
10359*3d8817e4Smiod 	    }
10360*3d8817e4Smiod 	}
10361*3d8817e4Smiod     }
10362*3d8817e4Smiod }
10363*3d8817e4Smiod 
10364*3d8817e4Smiod 
10365*3d8817e4Smiod static segment_info_type *
retrieve_segment_info(segT seg)10366*3d8817e4Smiod retrieve_segment_info (segT seg)
10367*3d8817e4Smiod {
10368*3d8817e4Smiod   segment_info_type *seginfo;
10369*3d8817e4Smiod   seginfo = (segment_info_type *) bfd_get_section_userdata (stdoutput, seg);
10370*3d8817e4Smiod   if (!seginfo)
10371*3d8817e4Smiod     {
10372*3d8817e4Smiod       frchainS *frchainP;
10373*3d8817e4Smiod 
10374*3d8817e4Smiod       seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo));
10375*3d8817e4Smiod       memset ((void *) seginfo, 0, sizeof (*seginfo));
10376*3d8817e4Smiod       seginfo->fix_root = NULL;
10377*3d8817e4Smiod       seginfo->fix_tail = NULL;
10378*3d8817e4Smiod       seginfo->bfd_section = seg;
10379*3d8817e4Smiod       seginfo->sym = 0;
10380*3d8817e4Smiod       /* We will not be dealing with these, only our special ones.  */
10381*3d8817e4Smiod       bfd_set_section_userdata (stdoutput, seg, (void *) seginfo);
10382*3d8817e4Smiod 
10383*3d8817e4Smiod       frchainP = (frchainS *) xmalloc (sizeof (frchainS));
10384*3d8817e4Smiod       frchainP->frch_root = NULL;
10385*3d8817e4Smiod       frchainP->frch_last = NULL;
10386*3d8817e4Smiod       frchainP->frch_next = NULL;
10387*3d8817e4Smiod       frchainP->frch_seg = seg;
10388*3d8817e4Smiod       frchainP->frch_subseg = 0;
10389*3d8817e4Smiod       frchainP->fix_root = NULL;
10390*3d8817e4Smiod       frchainP->fix_tail = NULL;
10391*3d8817e4Smiod       /* Do not init the objstack.  */
10392*3d8817e4Smiod       /* obstack_begin (&frchainP->frch_obstack, chunksize); */
10393*3d8817e4Smiod       /* frchainP->frch_frag_now = fragP; */
10394*3d8817e4Smiod       frchainP->frch_frag_now = NULL;
10395*3d8817e4Smiod 
10396*3d8817e4Smiod       seginfo->frchainP = frchainP;
10397*3d8817e4Smiod     }
10398*3d8817e4Smiod 
10399*3d8817e4Smiod   return seginfo;
10400*3d8817e4Smiod }
10401*3d8817e4Smiod 
10402*3d8817e4Smiod 
10403*3d8817e4Smiod static segT
retrieve_xtensa_section(char * sec_name)10404*3d8817e4Smiod retrieve_xtensa_section (char *sec_name)
10405*3d8817e4Smiod {
10406*3d8817e4Smiod   bfd *abfd = stdoutput;
10407*3d8817e4Smiod   flagword flags, out_flags, link_once_flags;
10408*3d8817e4Smiod   segT s;
10409*3d8817e4Smiod 
10410*3d8817e4Smiod   flags = bfd_get_section_flags (abfd, now_seg);
10411*3d8817e4Smiod   link_once_flags = (flags & SEC_LINK_ONCE);
10412*3d8817e4Smiod   if (link_once_flags)
10413*3d8817e4Smiod     link_once_flags |= (flags & SEC_LINK_DUPLICATES);
10414*3d8817e4Smiod   out_flags = (SEC_RELOC | SEC_HAS_CONTENTS | SEC_READONLY | link_once_flags);
10415*3d8817e4Smiod 
10416*3d8817e4Smiod   s = bfd_make_section_old_way (abfd, sec_name);
10417*3d8817e4Smiod   if (s == NULL)
10418*3d8817e4Smiod     as_bad (_("could not create section %s"), sec_name);
10419*3d8817e4Smiod   if (!bfd_set_section_flags (abfd, s, out_flags))
10420*3d8817e4Smiod     as_bad (_("invalid flag combination on section %s"), sec_name);
10421*3d8817e4Smiod 
10422*3d8817e4Smiod   return s;
10423*3d8817e4Smiod }
10424*3d8817e4Smiod 
10425*3d8817e4Smiod 
10426*3d8817e4Smiod static bfd_boolean
section_has_property(segT sec,frag_predicate property_function)10427*3d8817e4Smiod section_has_property (segT sec, frag_predicate property_function)
10428*3d8817e4Smiod {
10429*3d8817e4Smiod   segment_info_type *seginfo = seg_info (sec);
10430*3d8817e4Smiod   fragS *fragP;
10431*3d8817e4Smiod 
10432*3d8817e4Smiod   if (seginfo && seginfo->frchainP)
10433*3d8817e4Smiod     {
10434*3d8817e4Smiod       for (fragP = seginfo->frchainP->frch_root; fragP; fragP = fragP->fr_next)
10435*3d8817e4Smiod 	{
10436*3d8817e4Smiod 	  if (property_function (fragP)
10437*3d8817e4Smiod 	      && (fragP->fr_type != rs_fill || fragP->fr_fix != 0))
10438*3d8817e4Smiod 	    return TRUE;
10439*3d8817e4Smiod 	}
10440*3d8817e4Smiod     }
10441*3d8817e4Smiod   return FALSE;
10442*3d8817e4Smiod }
10443*3d8817e4Smiod 
10444*3d8817e4Smiod 
10445*3d8817e4Smiod static bfd_boolean
section_has_xproperty(segT sec,frag_flags_fn property_function)10446*3d8817e4Smiod section_has_xproperty (segT sec, frag_flags_fn property_function)
10447*3d8817e4Smiod {
10448*3d8817e4Smiod   segment_info_type *seginfo = seg_info (sec);
10449*3d8817e4Smiod   fragS *fragP;
10450*3d8817e4Smiod 
10451*3d8817e4Smiod   if (seginfo && seginfo->frchainP)
10452*3d8817e4Smiod     {
10453*3d8817e4Smiod       for (fragP = seginfo->frchainP->frch_root; fragP; fragP = fragP->fr_next)
10454*3d8817e4Smiod 	{
10455*3d8817e4Smiod 	  frag_flags prop_flags;
10456*3d8817e4Smiod 	  property_function (fragP, &prop_flags);
10457*3d8817e4Smiod 	  if (!xtensa_frag_flags_is_empty (&prop_flags))
10458*3d8817e4Smiod 	    return TRUE;
10459*3d8817e4Smiod 	}
10460*3d8817e4Smiod     }
10461*3d8817e4Smiod   return FALSE;
10462*3d8817e4Smiod }
10463*3d8817e4Smiod 
10464*3d8817e4Smiod 
10465*3d8817e4Smiod /* Two types of block sections exist right now: literal and insns.  */
10466*3d8817e4Smiod 
10467*3d8817e4Smiod static void
add_xt_block_frags(segT sec,segT xt_block_sec,xtensa_block_info ** xt_block,frag_predicate property_function,frag_predicate end_property_function)10468*3d8817e4Smiod add_xt_block_frags (segT sec,
10469*3d8817e4Smiod 		    segT xt_block_sec,
10470*3d8817e4Smiod 		    xtensa_block_info **xt_block,
10471*3d8817e4Smiod 		    frag_predicate property_function,
10472*3d8817e4Smiod 		    frag_predicate end_property_function)
10473*3d8817e4Smiod {
10474*3d8817e4Smiod   segment_info_type *seg_info;
10475*3d8817e4Smiod   segment_info_type *xt_seg_info;
10476*3d8817e4Smiod   bfd_vma seg_offset;
10477*3d8817e4Smiod   fragS *fragP;
10478*3d8817e4Smiod 
10479*3d8817e4Smiod   xt_seg_info = retrieve_segment_info (xt_block_sec);
10480*3d8817e4Smiod   seg_info = retrieve_segment_info (sec);
10481*3d8817e4Smiod 
10482*3d8817e4Smiod   /* Build it if needed.  */
10483*3d8817e4Smiod   while (*xt_block != NULL)
10484*3d8817e4Smiod     xt_block = &(*xt_block)->next;
10485*3d8817e4Smiod   /* We are either at NULL at the beginning or at the end.  */
10486*3d8817e4Smiod 
10487*3d8817e4Smiod   /* Walk through the frags.  */
10488*3d8817e4Smiod   seg_offset = 0;
10489*3d8817e4Smiod 
10490*3d8817e4Smiod   if (seg_info->frchainP)
10491*3d8817e4Smiod     {
10492*3d8817e4Smiod       for (fragP = seg_info->frchainP->frch_root;
10493*3d8817e4Smiod 	   fragP;
10494*3d8817e4Smiod 	   fragP = fragP->fr_next)
10495*3d8817e4Smiod 	{
10496*3d8817e4Smiod 	  if (property_function (fragP)
10497*3d8817e4Smiod 	      && (fragP->fr_type != rs_fill || fragP->fr_fix != 0))
10498*3d8817e4Smiod 	    {
10499*3d8817e4Smiod 	      if (*xt_block != NULL)
10500*3d8817e4Smiod 		{
10501*3d8817e4Smiod 		  if ((*xt_block)->offset + (*xt_block)->size
10502*3d8817e4Smiod 		      == fragP->fr_address)
10503*3d8817e4Smiod 		    (*xt_block)->size += fragP->fr_fix;
10504*3d8817e4Smiod 		  else
10505*3d8817e4Smiod 		    xt_block = &((*xt_block)->next);
10506*3d8817e4Smiod 		}
10507*3d8817e4Smiod 	      if (*xt_block == NULL)
10508*3d8817e4Smiod 		{
10509*3d8817e4Smiod 		  xtensa_block_info *new_block = (xtensa_block_info *)
10510*3d8817e4Smiod 		    xmalloc (sizeof (xtensa_block_info));
10511*3d8817e4Smiod 		  new_block->sec = sec;
10512*3d8817e4Smiod 		  new_block->offset = fragP->fr_address;
10513*3d8817e4Smiod 		  new_block->size = fragP->fr_fix;
10514*3d8817e4Smiod 		  new_block->next = NULL;
10515*3d8817e4Smiod 		  xtensa_frag_flags_init (&new_block->flags);
10516*3d8817e4Smiod 		  *xt_block = new_block;
10517*3d8817e4Smiod 		}
10518*3d8817e4Smiod 	      if (end_property_function
10519*3d8817e4Smiod 		  && end_property_function (fragP))
10520*3d8817e4Smiod 		{
10521*3d8817e4Smiod 		  xt_block = &((*xt_block)->next);
10522*3d8817e4Smiod 		}
10523*3d8817e4Smiod 	    }
10524*3d8817e4Smiod 	}
10525*3d8817e4Smiod     }
10526*3d8817e4Smiod }
10527*3d8817e4Smiod 
10528*3d8817e4Smiod 
10529*3d8817e4Smiod /* Break the encapsulation of add_xt_prop_frags here.  */
10530*3d8817e4Smiod 
10531*3d8817e4Smiod static bfd_boolean
xtensa_frag_flags_is_empty(const frag_flags * prop_flags)10532*3d8817e4Smiod xtensa_frag_flags_is_empty (const frag_flags *prop_flags)
10533*3d8817e4Smiod {
10534*3d8817e4Smiod   if (prop_flags->is_literal
10535*3d8817e4Smiod       || prop_flags->is_insn
10536*3d8817e4Smiod       || prop_flags->is_data
10537*3d8817e4Smiod       || prop_flags->is_unreachable)
10538*3d8817e4Smiod     return FALSE;
10539*3d8817e4Smiod   return TRUE;
10540*3d8817e4Smiod }
10541*3d8817e4Smiod 
10542*3d8817e4Smiod 
10543*3d8817e4Smiod static void
xtensa_frag_flags_init(frag_flags * prop_flags)10544*3d8817e4Smiod xtensa_frag_flags_init (frag_flags *prop_flags)
10545*3d8817e4Smiod {
10546*3d8817e4Smiod   memset (prop_flags, 0, sizeof (frag_flags));
10547*3d8817e4Smiod }
10548*3d8817e4Smiod 
10549*3d8817e4Smiod 
10550*3d8817e4Smiod static void
get_frag_property_flags(const fragS * fragP,frag_flags * prop_flags)10551*3d8817e4Smiod get_frag_property_flags (const fragS *fragP, frag_flags *prop_flags)
10552*3d8817e4Smiod {
10553*3d8817e4Smiod   xtensa_frag_flags_init (prop_flags);
10554*3d8817e4Smiod   if (fragP->tc_frag_data.is_literal)
10555*3d8817e4Smiod     prop_flags->is_literal = TRUE;
10556*3d8817e4Smiod   if (fragP->tc_frag_data.is_unreachable)
10557*3d8817e4Smiod     prop_flags->is_unreachable = TRUE;
10558*3d8817e4Smiod   else if (fragP->tc_frag_data.is_insn)
10559*3d8817e4Smiod     {
10560*3d8817e4Smiod       prop_flags->is_insn = TRUE;
10561*3d8817e4Smiod       if (fragP->tc_frag_data.is_loop_target)
10562*3d8817e4Smiod 	prop_flags->insn.is_loop_target = TRUE;
10563*3d8817e4Smiod       if (fragP->tc_frag_data.is_branch_target)
10564*3d8817e4Smiod 	prop_flags->insn.is_branch_target = TRUE;
10565*3d8817e4Smiod       if (fragP->tc_frag_data.is_specific_opcode
10566*3d8817e4Smiod 	  || fragP->tc_frag_data.is_no_transform)
10567*3d8817e4Smiod 	prop_flags->insn.is_no_transform = TRUE;
10568*3d8817e4Smiod       if (fragP->tc_frag_data.is_no_density)
10569*3d8817e4Smiod 	prop_flags->insn.is_no_density = TRUE;
10570*3d8817e4Smiod       if (fragP->tc_frag_data.use_absolute_literals)
10571*3d8817e4Smiod 	prop_flags->insn.is_abslit = TRUE;
10572*3d8817e4Smiod     }
10573*3d8817e4Smiod   if (fragP->tc_frag_data.is_align)
10574*3d8817e4Smiod     {
10575*3d8817e4Smiod       prop_flags->is_align = TRUE;
10576*3d8817e4Smiod       prop_flags->alignment = fragP->tc_frag_data.alignment;
10577*3d8817e4Smiod       if (xtensa_frag_flags_is_empty (prop_flags))
10578*3d8817e4Smiod 	prop_flags->is_data = TRUE;
10579*3d8817e4Smiod     }
10580*3d8817e4Smiod }
10581*3d8817e4Smiod 
10582*3d8817e4Smiod 
10583*3d8817e4Smiod static bfd_vma
frag_flags_to_number(const frag_flags * prop_flags)10584*3d8817e4Smiod frag_flags_to_number (const frag_flags *prop_flags)
10585*3d8817e4Smiod {
10586*3d8817e4Smiod   bfd_vma num = 0;
10587*3d8817e4Smiod   if (prop_flags->is_literal)
10588*3d8817e4Smiod     num |= XTENSA_PROP_LITERAL;
10589*3d8817e4Smiod   if (prop_flags->is_insn)
10590*3d8817e4Smiod     num |= XTENSA_PROP_INSN;
10591*3d8817e4Smiod   if (prop_flags->is_data)
10592*3d8817e4Smiod     num |= XTENSA_PROP_DATA;
10593*3d8817e4Smiod   if (prop_flags->is_unreachable)
10594*3d8817e4Smiod     num |= XTENSA_PROP_UNREACHABLE;
10595*3d8817e4Smiod   if (prop_flags->insn.is_loop_target)
10596*3d8817e4Smiod     num |= XTENSA_PROP_INSN_LOOP_TARGET;
10597*3d8817e4Smiod   if (prop_flags->insn.is_branch_target)
10598*3d8817e4Smiod     {
10599*3d8817e4Smiod       num |= XTENSA_PROP_INSN_BRANCH_TARGET;
10600*3d8817e4Smiod       num = SET_XTENSA_PROP_BT_ALIGN (num, prop_flags->insn.bt_align_priority);
10601*3d8817e4Smiod     }
10602*3d8817e4Smiod 
10603*3d8817e4Smiod   if (prop_flags->insn.is_no_density)
10604*3d8817e4Smiod     num |= XTENSA_PROP_INSN_NO_DENSITY;
10605*3d8817e4Smiod   if (prop_flags->insn.is_no_transform)
10606*3d8817e4Smiod     num |= XTENSA_PROP_INSN_NO_TRANSFORM;
10607*3d8817e4Smiod   if (prop_flags->insn.is_no_reorder)
10608*3d8817e4Smiod     num |= XTENSA_PROP_INSN_NO_REORDER;
10609*3d8817e4Smiod   if (prop_flags->insn.is_abslit)
10610*3d8817e4Smiod     num |= XTENSA_PROP_INSN_ABSLIT;
10611*3d8817e4Smiod 
10612*3d8817e4Smiod   if (prop_flags->is_align)
10613*3d8817e4Smiod     {
10614*3d8817e4Smiod       num |= XTENSA_PROP_ALIGN;
10615*3d8817e4Smiod       num = SET_XTENSA_PROP_ALIGNMENT (num, prop_flags->alignment);
10616*3d8817e4Smiod     }
10617*3d8817e4Smiod 
10618*3d8817e4Smiod   return num;
10619*3d8817e4Smiod }
10620*3d8817e4Smiod 
10621*3d8817e4Smiod 
10622*3d8817e4Smiod static bfd_boolean
xtensa_frag_flags_combinable(const frag_flags * prop_flags_1,const frag_flags * prop_flags_2)10623*3d8817e4Smiod xtensa_frag_flags_combinable (const frag_flags *prop_flags_1,
10624*3d8817e4Smiod 			      const frag_flags *prop_flags_2)
10625*3d8817e4Smiod {
10626*3d8817e4Smiod   /* Cannot combine with an end marker.  */
10627*3d8817e4Smiod 
10628*3d8817e4Smiod   if (prop_flags_1->is_literal != prop_flags_2->is_literal)
10629*3d8817e4Smiod     return FALSE;
10630*3d8817e4Smiod   if (prop_flags_1->is_insn != prop_flags_2->is_insn)
10631*3d8817e4Smiod     return FALSE;
10632*3d8817e4Smiod   if (prop_flags_1->is_data != prop_flags_2->is_data)
10633*3d8817e4Smiod     return FALSE;
10634*3d8817e4Smiod 
10635*3d8817e4Smiod   if (prop_flags_1->is_insn)
10636*3d8817e4Smiod     {
10637*3d8817e4Smiod       /* Properties of the beginning of the frag.  */
10638*3d8817e4Smiod       if (prop_flags_2->insn.is_loop_target)
10639*3d8817e4Smiod 	return FALSE;
10640*3d8817e4Smiod       if (prop_flags_2->insn.is_branch_target)
10641*3d8817e4Smiod 	return FALSE;
10642*3d8817e4Smiod       if (prop_flags_1->insn.is_no_density !=
10643*3d8817e4Smiod 	  prop_flags_2->insn.is_no_density)
10644*3d8817e4Smiod 	return FALSE;
10645*3d8817e4Smiod       if (prop_flags_1->insn.is_no_transform !=
10646*3d8817e4Smiod 	  prop_flags_2->insn.is_no_transform)
10647*3d8817e4Smiod 	return FALSE;
10648*3d8817e4Smiod       if (prop_flags_1->insn.is_no_reorder !=
10649*3d8817e4Smiod 	  prop_flags_2->insn.is_no_reorder)
10650*3d8817e4Smiod 	return FALSE;
10651*3d8817e4Smiod       if (prop_flags_1->insn.is_abslit !=
10652*3d8817e4Smiod 	  prop_flags_2->insn.is_abslit)
10653*3d8817e4Smiod 	return FALSE;
10654*3d8817e4Smiod     }
10655*3d8817e4Smiod 
10656*3d8817e4Smiod   if (prop_flags_1->is_align)
10657*3d8817e4Smiod     return FALSE;
10658*3d8817e4Smiod 
10659*3d8817e4Smiod   return TRUE;
10660*3d8817e4Smiod }
10661*3d8817e4Smiod 
10662*3d8817e4Smiod 
10663*3d8817e4Smiod static bfd_vma
xt_block_aligned_size(const xtensa_block_info * xt_block)10664*3d8817e4Smiod xt_block_aligned_size (const xtensa_block_info *xt_block)
10665*3d8817e4Smiod {
10666*3d8817e4Smiod   bfd_vma end_addr;
10667*3d8817e4Smiod   unsigned align_bits;
10668*3d8817e4Smiod 
10669*3d8817e4Smiod   if (!xt_block->flags.is_align)
10670*3d8817e4Smiod     return xt_block->size;
10671*3d8817e4Smiod 
10672*3d8817e4Smiod   end_addr = xt_block->offset + xt_block->size;
10673*3d8817e4Smiod   align_bits = xt_block->flags.alignment;
10674*3d8817e4Smiod   end_addr = ((end_addr + ((1 << align_bits) -1)) >> align_bits) << align_bits;
10675*3d8817e4Smiod   return end_addr - xt_block->offset;
10676*3d8817e4Smiod }
10677*3d8817e4Smiod 
10678*3d8817e4Smiod 
10679*3d8817e4Smiod static bfd_boolean
xtensa_xt_block_combine(xtensa_block_info * xt_block,const xtensa_block_info * xt_block_2)10680*3d8817e4Smiod xtensa_xt_block_combine (xtensa_block_info *xt_block,
10681*3d8817e4Smiod 			 const xtensa_block_info *xt_block_2)
10682*3d8817e4Smiod {
10683*3d8817e4Smiod   if (xt_block->sec != xt_block_2->sec)
10684*3d8817e4Smiod     return FALSE;
10685*3d8817e4Smiod   if (xt_block->offset + xt_block_aligned_size (xt_block)
10686*3d8817e4Smiod       != xt_block_2->offset)
10687*3d8817e4Smiod     return FALSE;
10688*3d8817e4Smiod 
10689*3d8817e4Smiod   if (xt_block_2->size == 0
10690*3d8817e4Smiod       && (!xt_block_2->flags.is_unreachable
10691*3d8817e4Smiod 	  || xt_block->flags.is_unreachable))
10692*3d8817e4Smiod     {
10693*3d8817e4Smiod       if (xt_block_2->flags.is_align
10694*3d8817e4Smiod 	  && xt_block->flags.is_align)
10695*3d8817e4Smiod 	{
10696*3d8817e4Smiod 	  /* Nothing needed.  */
10697*3d8817e4Smiod 	  if (xt_block->flags.alignment >= xt_block_2->flags.alignment)
10698*3d8817e4Smiod 	    return TRUE;
10699*3d8817e4Smiod 	}
10700*3d8817e4Smiod       else
10701*3d8817e4Smiod 	{
10702*3d8817e4Smiod 	  if (xt_block_2->flags.is_align)
10703*3d8817e4Smiod 	    {
10704*3d8817e4Smiod 	      /* Push alignment to previous entry.  */
10705*3d8817e4Smiod 	      xt_block->flags.is_align = xt_block_2->flags.is_align;
10706*3d8817e4Smiod 	      xt_block->flags.alignment = xt_block_2->flags.alignment;
10707*3d8817e4Smiod 	    }
10708*3d8817e4Smiod 	  return TRUE;
10709*3d8817e4Smiod 	}
10710*3d8817e4Smiod     }
10711*3d8817e4Smiod   if (!xtensa_frag_flags_combinable (&xt_block->flags,
10712*3d8817e4Smiod 				     &xt_block_2->flags))
10713*3d8817e4Smiod     return FALSE;
10714*3d8817e4Smiod 
10715*3d8817e4Smiod   xt_block->size += xt_block_2->size;
10716*3d8817e4Smiod 
10717*3d8817e4Smiod   if (xt_block_2->flags.is_align)
10718*3d8817e4Smiod     {
10719*3d8817e4Smiod       xt_block->flags.is_align = TRUE;
10720*3d8817e4Smiod       xt_block->flags.alignment = xt_block_2->flags.alignment;
10721*3d8817e4Smiod     }
10722*3d8817e4Smiod 
10723*3d8817e4Smiod   return TRUE;
10724*3d8817e4Smiod }
10725*3d8817e4Smiod 
10726*3d8817e4Smiod 
10727*3d8817e4Smiod static void
add_xt_prop_frags(segT sec,segT xt_block_sec,xtensa_block_info ** xt_block,frag_flags_fn property_function)10728*3d8817e4Smiod add_xt_prop_frags (segT sec,
10729*3d8817e4Smiod 		   segT xt_block_sec,
10730*3d8817e4Smiod 		   xtensa_block_info **xt_block,
10731*3d8817e4Smiod 		   frag_flags_fn property_function)
10732*3d8817e4Smiod {
10733*3d8817e4Smiod   segment_info_type *seg_info;
10734*3d8817e4Smiod   segment_info_type *xt_seg_info;
10735*3d8817e4Smiod   bfd_vma seg_offset;
10736*3d8817e4Smiod   fragS *fragP;
10737*3d8817e4Smiod 
10738*3d8817e4Smiod   xt_seg_info = retrieve_segment_info (xt_block_sec);
10739*3d8817e4Smiod   seg_info = retrieve_segment_info (sec);
10740*3d8817e4Smiod   /* Build it if needed.  */
10741*3d8817e4Smiod   while (*xt_block != NULL)
10742*3d8817e4Smiod     {
10743*3d8817e4Smiod       xt_block = &(*xt_block)->next;
10744*3d8817e4Smiod     }
10745*3d8817e4Smiod   /* We are either at NULL at the beginning or at the end.  */
10746*3d8817e4Smiod 
10747*3d8817e4Smiod   /* Walk through the frags.  */
10748*3d8817e4Smiod   seg_offset = 0;
10749*3d8817e4Smiod 
10750*3d8817e4Smiod   if (seg_info->frchainP)
10751*3d8817e4Smiod     {
10752*3d8817e4Smiod       for (fragP = seg_info->frchainP->frch_root; fragP;
10753*3d8817e4Smiod 	   fragP = fragP->fr_next)
10754*3d8817e4Smiod 	{
10755*3d8817e4Smiod 	  xtensa_block_info tmp_block;
10756*3d8817e4Smiod 	  tmp_block.sec = sec;
10757*3d8817e4Smiod 	  tmp_block.offset = fragP->fr_address;
10758*3d8817e4Smiod 	  tmp_block.size = fragP->fr_fix;
10759*3d8817e4Smiod 	  tmp_block.next = NULL;
10760*3d8817e4Smiod 	  property_function (fragP, &tmp_block.flags);
10761*3d8817e4Smiod 
10762*3d8817e4Smiod 	  if (!xtensa_frag_flags_is_empty (&tmp_block.flags))
10763*3d8817e4Smiod 	    /* && fragP->fr_fix != 0) */
10764*3d8817e4Smiod 	    {
10765*3d8817e4Smiod 	      if ((*xt_block) == NULL
10766*3d8817e4Smiod 		  || !xtensa_xt_block_combine (*xt_block, &tmp_block))
10767*3d8817e4Smiod 		{
10768*3d8817e4Smiod 		  xtensa_block_info *new_block;
10769*3d8817e4Smiod 		  if ((*xt_block) != NULL)
10770*3d8817e4Smiod 		    xt_block = &(*xt_block)->next;
10771*3d8817e4Smiod 		  new_block = (xtensa_block_info *)
10772*3d8817e4Smiod 		    xmalloc (sizeof (xtensa_block_info));
10773*3d8817e4Smiod 		  *new_block = tmp_block;
10774*3d8817e4Smiod 		  *xt_block = new_block;
10775*3d8817e4Smiod 		}
10776*3d8817e4Smiod 	    }
10777*3d8817e4Smiod 	}
10778*3d8817e4Smiod     }
10779*3d8817e4Smiod }
10780*3d8817e4Smiod 
10781*3d8817e4Smiod 
10782*3d8817e4Smiod /* op_placement_info_table */
10783*3d8817e4Smiod 
10784*3d8817e4Smiod /* op_placement_info makes it easier to determine which
10785*3d8817e4Smiod    ops can go in which slots.  */
10786*3d8817e4Smiod 
10787*3d8817e4Smiod static void
init_op_placement_info_table(void)10788*3d8817e4Smiod init_op_placement_info_table (void)
10789*3d8817e4Smiod {
10790*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
10791*3d8817e4Smiod   xtensa_insnbuf ibuf = xtensa_insnbuf_alloc (isa);
10792*3d8817e4Smiod   xtensa_opcode opcode;
10793*3d8817e4Smiod   xtensa_format fmt;
10794*3d8817e4Smiod   int slot;
10795*3d8817e4Smiod   int num_opcodes = xtensa_isa_num_opcodes (isa);
10796*3d8817e4Smiod 
10797*3d8817e4Smiod   op_placement_table = (op_placement_info_table)
10798*3d8817e4Smiod     xmalloc (sizeof (op_placement_info) * num_opcodes);
10799*3d8817e4Smiod   assert (xtensa_isa_num_formats (isa) < MAX_FORMATS);
10800*3d8817e4Smiod 
10801*3d8817e4Smiod   for (opcode = 0; opcode < num_opcodes; opcode++)
10802*3d8817e4Smiod     {
10803*3d8817e4Smiod       op_placement_info *opi = &op_placement_table[opcode];
10804*3d8817e4Smiod       /* FIXME: Make tinsn allocation dynamic.  */
10805*3d8817e4Smiod       if (xtensa_opcode_num_operands (isa, opcode) >= MAX_INSN_ARGS)
10806*3d8817e4Smiod 	as_fatal (_("too many operands in instruction"));
10807*3d8817e4Smiod       opi->narrowest = XTENSA_UNDEFINED;
10808*3d8817e4Smiod       opi->narrowest_size = 0x7F;
10809*3d8817e4Smiod       opi->narrowest_slot = 0;
10810*3d8817e4Smiod       opi->formats = 0;
10811*3d8817e4Smiod       opi->num_formats = 0;
10812*3d8817e4Smiod       opi->issuef = 0;
10813*3d8817e4Smiod       for (fmt = 0; fmt < xtensa_isa_num_formats (isa); fmt++)
10814*3d8817e4Smiod 	{
10815*3d8817e4Smiod 	  opi->slots[fmt] = 0;
10816*3d8817e4Smiod 	  for (slot = 0; slot < xtensa_format_num_slots (isa, fmt); slot++)
10817*3d8817e4Smiod 	    {
10818*3d8817e4Smiod 	      if (xtensa_opcode_encode (isa, fmt, slot, ibuf, opcode) == 0)
10819*3d8817e4Smiod 		{
10820*3d8817e4Smiod 		  int fmt_length = xtensa_format_length (isa, fmt);
10821*3d8817e4Smiod 		  opi->issuef++;
10822*3d8817e4Smiod 		  set_bit (fmt, opi->formats);
10823*3d8817e4Smiod 		  set_bit (slot, opi->slots[fmt]);
10824*3d8817e4Smiod 		  if (fmt_length < opi->narrowest_size
10825*3d8817e4Smiod 		      || (fmt_length == opi->narrowest_size
10826*3d8817e4Smiod 			  && (xtensa_format_num_slots (isa, fmt)
10827*3d8817e4Smiod 			      < xtensa_format_num_slots (isa,
10828*3d8817e4Smiod 							 opi->narrowest))))
10829*3d8817e4Smiod 		    {
10830*3d8817e4Smiod 		      opi->narrowest = fmt;
10831*3d8817e4Smiod 		      opi->narrowest_size = fmt_length;
10832*3d8817e4Smiod 		      opi->narrowest_slot = slot;
10833*3d8817e4Smiod 		    }
10834*3d8817e4Smiod 		}
10835*3d8817e4Smiod 	    }
10836*3d8817e4Smiod 	  if (opi->formats)
10837*3d8817e4Smiod 	    opi->num_formats++;
10838*3d8817e4Smiod 	}
10839*3d8817e4Smiod     }
10840*3d8817e4Smiod   xtensa_insnbuf_free (isa, ibuf);
10841*3d8817e4Smiod }
10842*3d8817e4Smiod 
10843*3d8817e4Smiod 
10844*3d8817e4Smiod bfd_boolean
opcode_fits_format_slot(xtensa_opcode opcode,xtensa_format fmt,int slot)10845*3d8817e4Smiod opcode_fits_format_slot (xtensa_opcode opcode, xtensa_format fmt, int slot)
10846*3d8817e4Smiod {
10847*3d8817e4Smiod   return bit_is_set (slot, op_placement_table[opcode].slots[fmt]);
10848*3d8817e4Smiod }
10849*3d8817e4Smiod 
10850*3d8817e4Smiod 
10851*3d8817e4Smiod /* If the opcode is available in a single slot format, return its size.  */
10852*3d8817e4Smiod 
10853*3d8817e4Smiod static int
xg_get_single_size(xtensa_opcode opcode)10854*3d8817e4Smiod xg_get_single_size (xtensa_opcode opcode)
10855*3d8817e4Smiod {
10856*3d8817e4Smiod   return op_placement_table[opcode].narrowest_size;
10857*3d8817e4Smiod }
10858*3d8817e4Smiod 
10859*3d8817e4Smiod 
10860*3d8817e4Smiod static xtensa_format
xg_get_single_format(xtensa_opcode opcode)10861*3d8817e4Smiod xg_get_single_format (xtensa_opcode opcode)
10862*3d8817e4Smiod {
10863*3d8817e4Smiod   return op_placement_table[opcode].narrowest;
10864*3d8817e4Smiod }
10865*3d8817e4Smiod 
10866*3d8817e4Smiod 
10867*3d8817e4Smiod static int
xg_get_single_slot(xtensa_opcode opcode)10868*3d8817e4Smiod xg_get_single_slot (xtensa_opcode opcode)
10869*3d8817e4Smiod {
10870*3d8817e4Smiod   return op_placement_table[opcode].narrowest_slot;
10871*3d8817e4Smiod }
10872*3d8817e4Smiod 
10873*3d8817e4Smiod 
10874*3d8817e4Smiod /* Instruction Stack Functions (from "xtensa-istack.h").  */
10875*3d8817e4Smiod 
10876*3d8817e4Smiod void
istack_init(IStack * stack)10877*3d8817e4Smiod istack_init (IStack *stack)
10878*3d8817e4Smiod {
10879*3d8817e4Smiod   memset (stack, 0, sizeof (IStack));
10880*3d8817e4Smiod   stack->ninsn = 0;
10881*3d8817e4Smiod }
10882*3d8817e4Smiod 
10883*3d8817e4Smiod 
10884*3d8817e4Smiod bfd_boolean
istack_empty(IStack * stack)10885*3d8817e4Smiod istack_empty (IStack *stack)
10886*3d8817e4Smiod {
10887*3d8817e4Smiod   return (stack->ninsn == 0);
10888*3d8817e4Smiod }
10889*3d8817e4Smiod 
10890*3d8817e4Smiod 
10891*3d8817e4Smiod bfd_boolean
istack_full(IStack * stack)10892*3d8817e4Smiod istack_full (IStack *stack)
10893*3d8817e4Smiod {
10894*3d8817e4Smiod   return (stack->ninsn == MAX_ISTACK);
10895*3d8817e4Smiod }
10896*3d8817e4Smiod 
10897*3d8817e4Smiod 
10898*3d8817e4Smiod /* Return a pointer to the top IStack entry.
10899*3d8817e4Smiod    It is an error to call this if istack_empty () is TRUE. */
10900*3d8817e4Smiod 
10901*3d8817e4Smiod TInsn *
istack_top(IStack * stack)10902*3d8817e4Smiod istack_top (IStack *stack)
10903*3d8817e4Smiod {
10904*3d8817e4Smiod   int rec = stack->ninsn - 1;
10905*3d8817e4Smiod   assert (!istack_empty (stack));
10906*3d8817e4Smiod   return &stack->insn[rec];
10907*3d8817e4Smiod }
10908*3d8817e4Smiod 
10909*3d8817e4Smiod 
10910*3d8817e4Smiod /* Add a new TInsn to an IStack.
10911*3d8817e4Smiod    It is an error to call this if istack_full () is TRUE.  */
10912*3d8817e4Smiod 
10913*3d8817e4Smiod void
istack_push(IStack * stack,TInsn * insn)10914*3d8817e4Smiod istack_push (IStack *stack, TInsn *insn)
10915*3d8817e4Smiod {
10916*3d8817e4Smiod   int rec = stack->ninsn;
10917*3d8817e4Smiod   assert (!istack_full (stack));
10918*3d8817e4Smiod   stack->insn[rec] = *insn;
10919*3d8817e4Smiod   stack->ninsn++;
10920*3d8817e4Smiod }
10921*3d8817e4Smiod 
10922*3d8817e4Smiod 
10923*3d8817e4Smiod /* Clear space for the next TInsn on the IStack and return a pointer
10924*3d8817e4Smiod    to it.  It is an error to call this if istack_full () is TRUE.  */
10925*3d8817e4Smiod 
10926*3d8817e4Smiod TInsn *
istack_push_space(IStack * stack)10927*3d8817e4Smiod istack_push_space (IStack *stack)
10928*3d8817e4Smiod {
10929*3d8817e4Smiod   int rec = stack->ninsn;
10930*3d8817e4Smiod   TInsn *insn;
10931*3d8817e4Smiod   assert (!istack_full (stack));
10932*3d8817e4Smiod   insn = &stack->insn[rec];
10933*3d8817e4Smiod   memset (insn, 0, sizeof (TInsn));
10934*3d8817e4Smiod   stack->ninsn++;
10935*3d8817e4Smiod   return insn;
10936*3d8817e4Smiod }
10937*3d8817e4Smiod 
10938*3d8817e4Smiod 
10939*3d8817e4Smiod /* Remove the last pushed instruction.  It is an error to call this if
10940*3d8817e4Smiod    istack_empty () returns TRUE.  */
10941*3d8817e4Smiod 
10942*3d8817e4Smiod void
istack_pop(IStack * stack)10943*3d8817e4Smiod istack_pop (IStack *stack)
10944*3d8817e4Smiod {
10945*3d8817e4Smiod   int rec = stack->ninsn - 1;
10946*3d8817e4Smiod   assert (!istack_empty (stack));
10947*3d8817e4Smiod   stack->ninsn--;
10948*3d8817e4Smiod   memset (&stack->insn[rec], 0, sizeof (TInsn));
10949*3d8817e4Smiod }
10950*3d8817e4Smiod 
10951*3d8817e4Smiod 
10952*3d8817e4Smiod /* TInsn functions.  */
10953*3d8817e4Smiod 
10954*3d8817e4Smiod void
tinsn_init(TInsn * dst)10955*3d8817e4Smiod tinsn_init (TInsn *dst)
10956*3d8817e4Smiod {
10957*3d8817e4Smiod   memset (dst, 0, sizeof (TInsn));
10958*3d8817e4Smiod }
10959*3d8817e4Smiod 
10960*3d8817e4Smiod 
10961*3d8817e4Smiod /* Get the ``num''th token of the TInsn.
10962*3d8817e4Smiod    It is illegal to call this if num > insn->ntoks.  */
10963*3d8817e4Smiod 
10964*3d8817e4Smiod expressionS *
tinsn_get_tok(TInsn * insn,int num)10965*3d8817e4Smiod tinsn_get_tok (TInsn *insn, int num)
10966*3d8817e4Smiod {
10967*3d8817e4Smiod   assert (num < insn->ntok);
10968*3d8817e4Smiod   return &insn->tok[num];
10969*3d8817e4Smiod }
10970*3d8817e4Smiod 
10971*3d8817e4Smiod 
10972*3d8817e4Smiod /* Return TRUE if ANY of the operands in the insn are symbolic.  */
10973*3d8817e4Smiod 
10974*3d8817e4Smiod static bfd_boolean
tinsn_has_symbolic_operands(const TInsn * insn)10975*3d8817e4Smiod tinsn_has_symbolic_operands (const TInsn *insn)
10976*3d8817e4Smiod {
10977*3d8817e4Smiod   int i;
10978*3d8817e4Smiod   int n = insn->ntok;
10979*3d8817e4Smiod 
10980*3d8817e4Smiod   assert (insn->insn_type == ITYPE_INSN);
10981*3d8817e4Smiod 
10982*3d8817e4Smiod   for (i = 0; i < n; ++i)
10983*3d8817e4Smiod     {
10984*3d8817e4Smiod       switch (insn->tok[i].X_op)
10985*3d8817e4Smiod 	{
10986*3d8817e4Smiod 	case O_register:
10987*3d8817e4Smiod 	case O_constant:
10988*3d8817e4Smiod 	  break;
10989*3d8817e4Smiod 	default:
10990*3d8817e4Smiod 	  return TRUE;
10991*3d8817e4Smiod 	}
10992*3d8817e4Smiod     }
10993*3d8817e4Smiod   return FALSE;
10994*3d8817e4Smiod }
10995*3d8817e4Smiod 
10996*3d8817e4Smiod 
10997*3d8817e4Smiod bfd_boolean
tinsn_has_invalid_symbolic_operands(const TInsn * insn)10998*3d8817e4Smiod tinsn_has_invalid_symbolic_operands (const TInsn *insn)
10999*3d8817e4Smiod {
11000*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
11001*3d8817e4Smiod   int i;
11002*3d8817e4Smiod   int n = insn->ntok;
11003*3d8817e4Smiod 
11004*3d8817e4Smiod   assert (insn->insn_type == ITYPE_INSN);
11005*3d8817e4Smiod 
11006*3d8817e4Smiod   for (i = 0; i < n; ++i)
11007*3d8817e4Smiod     {
11008*3d8817e4Smiod       switch (insn->tok[i].X_op)
11009*3d8817e4Smiod 	{
11010*3d8817e4Smiod 	case O_register:
11011*3d8817e4Smiod 	case O_constant:
11012*3d8817e4Smiod 	  break;
11013*3d8817e4Smiod 	case O_big:
11014*3d8817e4Smiod 	case O_illegal:
11015*3d8817e4Smiod 	case O_absent:
11016*3d8817e4Smiod 	  /* Errors for these types are caught later.  */
11017*3d8817e4Smiod 	  break;
11018*3d8817e4Smiod 	case O_hi16:
11019*3d8817e4Smiod 	case O_lo16:
11020*3d8817e4Smiod 	default:
11021*3d8817e4Smiod 	  /* Symbolic immediates are only allowed on the last immediate
11022*3d8817e4Smiod 	     operand.  At this time, CONST16 is the only opcode where we
11023*3d8817e4Smiod 	     support non-PC-relative relocations.  */
11024*3d8817e4Smiod 	  if (i != get_relaxable_immed (insn->opcode)
11025*3d8817e4Smiod 	      || (xtensa_operand_is_PCrelative (isa, insn->opcode, i) != 1
11026*3d8817e4Smiod 		  && insn->opcode != xtensa_const16_opcode))
11027*3d8817e4Smiod 	    {
11028*3d8817e4Smiod 	      as_bad (_("invalid symbolic operand"));
11029*3d8817e4Smiod 	      return TRUE;
11030*3d8817e4Smiod 	    }
11031*3d8817e4Smiod 	}
11032*3d8817e4Smiod     }
11033*3d8817e4Smiod   return FALSE;
11034*3d8817e4Smiod }
11035*3d8817e4Smiod 
11036*3d8817e4Smiod 
11037*3d8817e4Smiod /* For assembly code with complex expressions (e.g. subtraction),
11038*3d8817e4Smiod    we have to build them in the literal pool so that
11039*3d8817e4Smiod    their results are calculated correctly after relaxation.
11040*3d8817e4Smiod    The relaxation only handles expressions that
11041*3d8817e4Smiod    boil down to SYMBOL + OFFSET.  */
11042*3d8817e4Smiod 
11043*3d8817e4Smiod static bfd_boolean
tinsn_has_complex_operands(const TInsn * insn)11044*3d8817e4Smiod tinsn_has_complex_operands (const TInsn *insn)
11045*3d8817e4Smiod {
11046*3d8817e4Smiod   int i;
11047*3d8817e4Smiod   int n = insn->ntok;
11048*3d8817e4Smiod   assert (insn->insn_type == ITYPE_INSN);
11049*3d8817e4Smiod   for (i = 0; i < n; ++i)
11050*3d8817e4Smiod     {
11051*3d8817e4Smiod       switch (insn->tok[i].X_op)
11052*3d8817e4Smiod 	{
11053*3d8817e4Smiod 	case O_register:
11054*3d8817e4Smiod 	case O_constant:
11055*3d8817e4Smiod 	case O_symbol:
11056*3d8817e4Smiod 	case O_lo16:
11057*3d8817e4Smiod 	case O_hi16:
11058*3d8817e4Smiod 	  break;
11059*3d8817e4Smiod 	default:
11060*3d8817e4Smiod 	  return TRUE;
11061*3d8817e4Smiod 	}
11062*3d8817e4Smiod     }
11063*3d8817e4Smiod   return FALSE;
11064*3d8817e4Smiod }
11065*3d8817e4Smiod 
11066*3d8817e4Smiod 
11067*3d8817e4Smiod /* Encode a TInsn opcode and its constant operands into slotbuf.
11068*3d8817e4Smiod    Return TRUE if there is a symbol in the immediate field.  This
11069*3d8817e4Smiod    function assumes that:
11070*3d8817e4Smiod    1) The number of operands are correct.
11071*3d8817e4Smiod    2) The insn_type is ITYPE_INSN.
11072*3d8817e4Smiod    3) The opcode can be encoded in the specified format and slot.
11073*3d8817e4Smiod    4) Operands are either O_constant or O_symbol, and all constants fit.  */
11074*3d8817e4Smiod 
11075*3d8817e4Smiod static bfd_boolean
tinsn_to_slotbuf(xtensa_format fmt,int slot,TInsn * tinsn,xtensa_insnbuf slotbuf)11076*3d8817e4Smiod tinsn_to_slotbuf (xtensa_format fmt,
11077*3d8817e4Smiod 		  int slot,
11078*3d8817e4Smiod 		  TInsn *tinsn,
11079*3d8817e4Smiod 		  xtensa_insnbuf slotbuf)
11080*3d8817e4Smiod {
11081*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
11082*3d8817e4Smiod   xtensa_opcode opcode = tinsn->opcode;
11083*3d8817e4Smiod   bfd_boolean has_fixup = FALSE;
11084*3d8817e4Smiod   int noperands = xtensa_opcode_num_operands (isa, opcode);
11085*3d8817e4Smiod   int i;
11086*3d8817e4Smiod 
11087*3d8817e4Smiod   assert (tinsn->insn_type == ITYPE_INSN);
11088*3d8817e4Smiod   if (noperands != tinsn->ntok)
11089*3d8817e4Smiod     as_fatal (_("operand number mismatch"));
11090*3d8817e4Smiod 
11091*3d8817e4Smiod   if (xtensa_opcode_encode (isa, fmt, slot, slotbuf, opcode))
11092*3d8817e4Smiod     {
11093*3d8817e4Smiod       as_bad (_("cannot encode opcode \"%s\" in the given format \"%s\""),
11094*3d8817e4Smiod 	      xtensa_opcode_name (isa, opcode), xtensa_format_name (isa, fmt));
11095*3d8817e4Smiod       return FALSE;
11096*3d8817e4Smiod     }
11097*3d8817e4Smiod 
11098*3d8817e4Smiod   for (i = 0; i < noperands; i++)
11099*3d8817e4Smiod     {
11100*3d8817e4Smiod       expressionS *expr = &tinsn->tok[i];
11101*3d8817e4Smiod       int rc;
11102*3d8817e4Smiod       unsigned line;
11103*3d8817e4Smiod       char *file_name;
11104*3d8817e4Smiod       uint32 opnd_value;
11105*3d8817e4Smiod 
11106*3d8817e4Smiod       switch (expr->X_op)
11107*3d8817e4Smiod 	{
11108*3d8817e4Smiod 	case O_register:
11109*3d8817e4Smiod 	  if (xtensa_operand_is_visible (isa, opcode, i) == 0)
11110*3d8817e4Smiod 	    break;
11111*3d8817e4Smiod 	  /* The register number has already been checked in
11112*3d8817e4Smiod 	     expression_maybe_register, so we don't need to check here.  */
11113*3d8817e4Smiod 	  opnd_value = expr->X_add_number;
11114*3d8817e4Smiod 	  (void) xtensa_operand_encode (isa, opcode, i, &opnd_value);
11115*3d8817e4Smiod 	  rc = xtensa_operand_set_field (isa, opcode, i, fmt, slot, slotbuf,
11116*3d8817e4Smiod 					 opnd_value);
11117*3d8817e4Smiod 	  if (rc != 0)
11118*3d8817e4Smiod 	    as_warn (_("xtensa-isa failure: %s"), xtensa_isa_error_msg (isa));
11119*3d8817e4Smiod 	  break;
11120*3d8817e4Smiod 
11121*3d8817e4Smiod 	case O_constant:
11122*3d8817e4Smiod 	  if (xtensa_operand_is_visible (isa, opcode, i) == 0)
11123*3d8817e4Smiod 	    break;
11124*3d8817e4Smiod 	  as_where (&file_name, &line);
11125*3d8817e4Smiod 	  /* It is a constant and we called this function
11126*3d8817e4Smiod 	     then we have to try to fit it.  */
11127*3d8817e4Smiod 	  xtensa_insnbuf_set_operand (slotbuf, fmt, slot, opcode, i,
11128*3d8817e4Smiod 				      expr->X_add_number, file_name, line);
11129*3d8817e4Smiod 	  break;
11130*3d8817e4Smiod 
11131*3d8817e4Smiod 	default:
11132*3d8817e4Smiod 	  has_fixup = TRUE;
11133*3d8817e4Smiod 	  break;
11134*3d8817e4Smiod 	}
11135*3d8817e4Smiod     }
11136*3d8817e4Smiod 
11137*3d8817e4Smiod   return has_fixup;
11138*3d8817e4Smiod }
11139*3d8817e4Smiod 
11140*3d8817e4Smiod 
11141*3d8817e4Smiod /* Encode a single TInsn into an insnbuf.  If the opcode can only be encoded
11142*3d8817e4Smiod    into a multi-slot instruction, fill the other slots with NOPs.
11143*3d8817e4Smiod    Return TRUE if there is a symbol in the immediate field.  See also the
11144*3d8817e4Smiod    assumptions listed for tinsn_to_slotbuf.  */
11145*3d8817e4Smiod 
11146*3d8817e4Smiod static bfd_boolean
tinsn_to_insnbuf(TInsn * tinsn,xtensa_insnbuf insnbuf)11147*3d8817e4Smiod tinsn_to_insnbuf (TInsn *tinsn, xtensa_insnbuf insnbuf)
11148*3d8817e4Smiod {
11149*3d8817e4Smiod   static xtensa_insnbuf slotbuf = 0;
11150*3d8817e4Smiod   static vliw_insn vinsn;
11151*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
11152*3d8817e4Smiod   bfd_boolean has_fixup = FALSE;
11153*3d8817e4Smiod   int i;
11154*3d8817e4Smiod 
11155*3d8817e4Smiod   if (!slotbuf)
11156*3d8817e4Smiod     {
11157*3d8817e4Smiod       slotbuf = xtensa_insnbuf_alloc (isa);
11158*3d8817e4Smiod       xg_init_vinsn (&vinsn);
11159*3d8817e4Smiod     }
11160*3d8817e4Smiod 
11161*3d8817e4Smiod   xg_clear_vinsn (&vinsn);
11162*3d8817e4Smiod 
11163*3d8817e4Smiod   bundle_tinsn (tinsn, &vinsn);
11164*3d8817e4Smiod 
11165*3d8817e4Smiod   xtensa_format_encode (isa, vinsn.format, insnbuf);
11166*3d8817e4Smiod 
11167*3d8817e4Smiod   for (i = 0; i < vinsn.num_slots; i++)
11168*3d8817e4Smiod     {
11169*3d8817e4Smiod       /* Only one slot may have a fix-up because the rest contains NOPs.  */
11170*3d8817e4Smiod       has_fixup |=
11171*3d8817e4Smiod 	tinsn_to_slotbuf (vinsn.format, i, &vinsn.slots[i], vinsn.slotbuf[i]);
11172*3d8817e4Smiod       xtensa_format_set_slot (isa, vinsn.format, i, insnbuf, vinsn.slotbuf[i]);
11173*3d8817e4Smiod     }
11174*3d8817e4Smiod 
11175*3d8817e4Smiod   return has_fixup;
11176*3d8817e4Smiod }
11177*3d8817e4Smiod 
11178*3d8817e4Smiod 
11179*3d8817e4Smiod /* Check the instruction arguments.  Return TRUE on failure.  */
11180*3d8817e4Smiod 
11181*3d8817e4Smiod static bfd_boolean
tinsn_check_arguments(const TInsn * insn)11182*3d8817e4Smiod tinsn_check_arguments (const TInsn *insn)
11183*3d8817e4Smiod {
11184*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
11185*3d8817e4Smiod   xtensa_opcode opcode = insn->opcode;
11186*3d8817e4Smiod 
11187*3d8817e4Smiod   if (opcode == XTENSA_UNDEFINED)
11188*3d8817e4Smiod     {
11189*3d8817e4Smiod       as_bad (_("invalid opcode"));
11190*3d8817e4Smiod       return TRUE;
11191*3d8817e4Smiod     }
11192*3d8817e4Smiod 
11193*3d8817e4Smiod   if (xtensa_opcode_num_operands (isa, opcode) > insn->ntok)
11194*3d8817e4Smiod     {
11195*3d8817e4Smiod       as_bad (_("too few operands"));
11196*3d8817e4Smiod       return TRUE;
11197*3d8817e4Smiod     }
11198*3d8817e4Smiod 
11199*3d8817e4Smiod   if (xtensa_opcode_num_operands (isa, opcode) < insn->ntok)
11200*3d8817e4Smiod     {
11201*3d8817e4Smiod       as_bad (_("too many operands"));
11202*3d8817e4Smiod       return TRUE;
11203*3d8817e4Smiod     }
11204*3d8817e4Smiod   return FALSE;
11205*3d8817e4Smiod }
11206*3d8817e4Smiod 
11207*3d8817e4Smiod 
11208*3d8817e4Smiod /* Load an instruction from its encoded form.  */
11209*3d8817e4Smiod 
11210*3d8817e4Smiod static void
tinsn_from_chars(TInsn * tinsn,char * f,int slot)11211*3d8817e4Smiod tinsn_from_chars (TInsn *tinsn, char *f, int slot)
11212*3d8817e4Smiod {
11213*3d8817e4Smiod   vliw_insn vinsn;
11214*3d8817e4Smiod 
11215*3d8817e4Smiod   xg_init_vinsn (&vinsn);
11216*3d8817e4Smiod   vinsn_from_chars (&vinsn, f);
11217*3d8817e4Smiod 
11218*3d8817e4Smiod   *tinsn = vinsn.slots[slot];
11219*3d8817e4Smiod   xg_free_vinsn (&vinsn);
11220*3d8817e4Smiod }
11221*3d8817e4Smiod 
11222*3d8817e4Smiod 
11223*3d8817e4Smiod static void
tinsn_from_insnbuf(TInsn * tinsn,xtensa_insnbuf slotbuf,xtensa_format fmt,int slot)11224*3d8817e4Smiod tinsn_from_insnbuf (TInsn *tinsn,
11225*3d8817e4Smiod 		    xtensa_insnbuf slotbuf,
11226*3d8817e4Smiod 		    xtensa_format fmt,
11227*3d8817e4Smiod 		    int slot)
11228*3d8817e4Smiod {
11229*3d8817e4Smiod   int i;
11230*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
11231*3d8817e4Smiod 
11232*3d8817e4Smiod   /* Find the immed.  */
11233*3d8817e4Smiod   tinsn_init (tinsn);
11234*3d8817e4Smiod   tinsn->insn_type = ITYPE_INSN;
11235*3d8817e4Smiod   tinsn->is_specific_opcode = FALSE;	/* must not be specific */
11236*3d8817e4Smiod   tinsn->opcode = xtensa_opcode_decode (isa, fmt, slot, slotbuf);
11237*3d8817e4Smiod   tinsn->ntok = xtensa_opcode_num_operands (isa, tinsn->opcode);
11238*3d8817e4Smiod   for (i = 0; i < tinsn->ntok; i++)
11239*3d8817e4Smiod     {
11240*3d8817e4Smiod       set_expr_const (&tinsn->tok[i],
11241*3d8817e4Smiod 		      xtensa_insnbuf_get_operand (slotbuf, fmt, slot,
11242*3d8817e4Smiod 						  tinsn->opcode, i));
11243*3d8817e4Smiod     }
11244*3d8817e4Smiod }
11245*3d8817e4Smiod 
11246*3d8817e4Smiod 
11247*3d8817e4Smiod /* Read the value of the relaxable immed from the fr_symbol and fr_offset.  */
11248*3d8817e4Smiod 
11249*3d8817e4Smiod static void
tinsn_immed_from_frag(TInsn * tinsn,fragS * fragP,int slot)11250*3d8817e4Smiod tinsn_immed_from_frag (TInsn *tinsn, fragS *fragP, int slot)
11251*3d8817e4Smiod {
11252*3d8817e4Smiod   xtensa_opcode opcode = tinsn->opcode;
11253*3d8817e4Smiod   int opnum;
11254*3d8817e4Smiod 
11255*3d8817e4Smiod   if (fragP->tc_frag_data.slot_symbols[slot])
11256*3d8817e4Smiod     {
11257*3d8817e4Smiod       opnum = get_relaxable_immed (opcode);
11258*3d8817e4Smiod       assert (opnum >= 0);
11259*3d8817e4Smiod       set_expr_symbol_offset (&tinsn->tok[opnum],
11260*3d8817e4Smiod 			      fragP->tc_frag_data.slot_symbols[slot],
11261*3d8817e4Smiod 			      fragP->tc_frag_data.slot_offsets[slot]);
11262*3d8817e4Smiod     }
11263*3d8817e4Smiod }
11264*3d8817e4Smiod 
11265*3d8817e4Smiod 
11266*3d8817e4Smiod static int
get_num_stack_text_bytes(IStack * istack)11267*3d8817e4Smiod get_num_stack_text_bytes (IStack *istack)
11268*3d8817e4Smiod {
11269*3d8817e4Smiod   int i;
11270*3d8817e4Smiod   int text_bytes = 0;
11271*3d8817e4Smiod 
11272*3d8817e4Smiod   for (i = 0; i < istack->ninsn; i++)
11273*3d8817e4Smiod     {
11274*3d8817e4Smiod       TInsn *tinsn = &istack->insn[i];
11275*3d8817e4Smiod       if (tinsn->insn_type == ITYPE_INSN)
11276*3d8817e4Smiod 	text_bytes += xg_get_single_size (tinsn->opcode);
11277*3d8817e4Smiod     }
11278*3d8817e4Smiod   return text_bytes;
11279*3d8817e4Smiod }
11280*3d8817e4Smiod 
11281*3d8817e4Smiod 
11282*3d8817e4Smiod static int
get_num_stack_literal_bytes(IStack * istack)11283*3d8817e4Smiod get_num_stack_literal_bytes (IStack *istack)
11284*3d8817e4Smiod {
11285*3d8817e4Smiod   int i;
11286*3d8817e4Smiod   int lit_bytes = 0;
11287*3d8817e4Smiod 
11288*3d8817e4Smiod   for (i = 0; i < istack->ninsn; i++)
11289*3d8817e4Smiod     {
11290*3d8817e4Smiod       TInsn *tinsn = &istack->insn[i];
11291*3d8817e4Smiod       if (tinsn->insn_type == ITYPE_LITERAL && tinsn->ntok == 1)
11292*3d8817e4Smiod 	lit_bytes += 4;
11293*3d8817e4Smiod     }
11294*3d8817e4Smiod   return lit_bytes;
11295*3d8817e4Smiod }
11296*3d8817e4Smiod 
11297*3d8817e4Smiod 
11298*3d8817e4Smiod /* vliw_insn functions.  */
11299*3d8817e4Smiod 
11300*3d8817e4Smiod static void
xg_init_vinsn(vliw_insn * v)11301*3d8817e4Smiod xg_init_vinsn (vliw_insn *v)
11302*3d8817e4Smiod {
11303*3d8817e4Smiod   int i;
11304*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
11305*3d8817e4Smiod 
11306*3d8817e4Smiod   xg_clear_vinsn (v);
11307*3d8817e4Smiod 
11308*3d8817e4Smiod   v->insnbuf = xtensa_insnbuf_alloc (isa);
11309*3d8817e4Smiod   if (v->insnbuf == NULL)
11310*3d8817e4Smiod     as_fatal (_("out of memory"));
11311*3d8817e4Smiod 
11312*3d8817e4Smiod   for (i = 0; i < MAX_SLOTS; i++)
11313*3d8817e4Smiod     {
11314*3d8817e4Smiod       v->slotbuf[i] = xtensa_insnbuf_alloc (isa);
11315*3d8817e4Smiod       if (v->slotbuf[i] == NULL)
11316*3d8817e4Smiod 	as_fatal (_("out of memory"));
11317*3d8817e4Smiod     }
11318*3d8817e4Smiod }
11319*3d8817e4Smiod 
11320*3d8817e4Smiod 
11321*3d8817e4Smiod static void
xg_clear_vinsn(vliw_insn * v)11322*3d8817e4Smiod xg_clear_vinsn (vliw_insn *v)
11323*3d8817e4Smiod {
11324*3d8817e4Smiod   int i;
11325*3d8817e4Smiod 
11326*3d8817e4Smiod   memset (v, 0, offsetof (vliw_insn, insnbuf));
11327*3d8817e4Smiod 
11328*3d8817e4Smiod   v->format = XTENSA_UNDEFINED;
11329*3d8817e4Smiod   v->num_slots = 0;
11330*3d8817e4Smiod   v->inside_bundle = FALSE;
11331*3d8817e4Smiod 
11332*3d8817e4Smiod   if (xt_saved_debug_type != DEBUG_NONE)
11333*3d8817e4Smiod     debug_type = xt_saved_debug_type;
11334*3d8817e4Smiod 
11335*3d8817e4Smiod   for (i = 0; i < MAX_SLOTS; i++)
11336*3d8817e4Smiod     v->slots[i].opcode = XTENSA_UNDEFINED;
11337*3d8817e4Smiod }
11338*3d8817e4Smiod 
11339*3d8817e4Smiod 
11340*3d8817e4Smiod static bfd_boolean
vinsn_has_specific_opcodes(vliw_insn * v)11341*3d8817e4Smiod vinsn_has_specific_opcodes (vliw_insn *v)
11342*3d8817e4Smiod {
11343*3d8817e4Smiod   int i;
11344*3d8817e4Smiod 
11345*3d8817e4Smiod   for (i = 0; i < v->num_slots; i++)
11346*3d8817e4Smiod     {
11347*3d8817e4Smiod       if (v->slots[i].is_specific_opcode)
11348*3d8817e4Smiod 	return TRUE;
11349*3d8817e4Smiod     }
11350*3d8817e4Smiod   return FALSE;
11351*3d8817e4Smiod }
11352*3d8817e4Smiod 
11353*3d8817e4Smiod 
11354*3d8817e4Smiod static void
xg_free_vinsn(vliw_insn * v)11355*3d8817e4Smiod xg_free_vinsn (vliw_insn *v)
11356*3d8817e4Smiod {
11357*3d8817e4Smiod   int i;
11358*3d8817e4Smiod   xtensa_insnbuf_free (xtensa_default_isa, v->insnbuf);
11359*3d8817e4Smiod   for (i = 0; i < MAX_SLOTS; i++)
11360*3d8817e4Smiod     xtensa_insnbuf_free (xtensa_default_isa, v->slotbuf[i]);
11361*3d8817e4Smiod }
11362*3d8817e4Smiod 
11363*3d8817e4Smiod 
11364*3d8817e4Smiod /* Encode a vliw_insn into an insnbuf.  Return TRUE if there are any symbolic
11365*3d8817e4Smiod    operands.  See also the assumptions listed for tinsn_to_slotbuf.  */
11366*3d8817e4Smiod 
11367*3d8817e4Smiod static bfd_boolean
vinsn_to_insnbuf(vliw_insn * vinsn,char * frag_offset,fragS * fragP,bfd_boolean record_fixup)11368*3d8817e4Smiod vinsn_to_insnbuf (vliw_insn *vinsn,
11369*3d8817e4Smiod 		  char *frag_offset,
11370*3d8817e4Smiod 		  fragS *fragP,
11371*3d8817e4Smiod 		  bfd_boolean record_fixup)
11372*3d8817e4Smiod {
11373*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
11374*3d8817e4Smiod   xtensa_format fmt = vinsn->format;
11375*3d8817e4Smiod   xtensa_insnbuf insnbuf = vinsn->insnbuf;
11376*3d8817e4Smiod   int slot;
11377*3d8817e4Smiod   bfd_boolean has_fixup = FALSE;
11378*3d8817e4Smiod 
11379*3d8817e4Smiod   xtensa_format_encode (isa, fmt, insnbuf);
11380*3d8817e4Smiod 
11381*3d8817e4Smiod   for (slot = 0; slot < vinsn->num_slots; slot++)
11382*3d8817e4Smiod     {
11383*3d8817e4Smiod       TInsn *tinsn = &vinsn->slots[slot];
11384*3d8817e4Smiod       bfd_boolean tinsn_has_fixup =
11385*3d8817e4Smiod 	tinsn_to_slotbuf (vinsn->format, slot, tinsn,
11386*3d8817e4Smiod 			  vinsn->slotbuf[slot]);
11387*3d8817e4Smiod 
11388*3d8817e4Smiod       xtensa_format_set_slot (isa, fmt, slot,
11389*3d8817e4Smiod 			      insnbuf, vinsn->slotbuf[slot]);
11390*3d8817e4Smiod       if (tinsn_has_fixup)
11391*3d8817e4Smiod 	{
11392*3d8817e4Smiod 	  int i;
11393*3d8817e4Smiod 	  xtensa_opcode opcode = tinsn->opcode;
11394*3d8817e4Smiod 	  int noperands = xtensa_opcode_num_operands (isa, opcode);
11395*3d8817e4Smiod 	  has_fixup = TRUE;
11396*3d8817e4Smiod 
11397*3d8817e4Smiod 	  for (i = 0; i < noperands; i++)
11398*3d8817e4Smiod 	    {
11399*3d8817e4Smiod 	      expressionS* expr = &tinsn->tok[i];
11400*3d8817e4Smiod 	      switch (expr->X_op)
11401*3d8817e4Smiod 		{
11402*3d8817e4Smiod 		case O_symbol:
11403*3d8817e4Smiod 		case O_lo16:
11404*3d8817e4Smiod 		case O_hi16:
11405*3d8817e4Smiod 		  if (get_relaxable_immed (opcode) == i)
11406*3d8817e4Smiod 		    {
11407*3d8817e4Smiod 		      /* Add a fix record for the instruction, except if this
11408*3d8817e4Smiod 			 function is being called prior to relaxation, i.e.,
11409*3d8817e4Smiod 			 if record_fixup is false, and the instruction might
11410*3d8817e4Smiod 			 be relaxed later.  */
11411*3d8817e4Smiod 		      if (record_fixup
11412*3d8817e4Smiod 			  || tinsn->is_specific_opcode
11413*3d8817e4Smiod 			  || !xg_is_relaxable_insn (tinsn, 0))
11414*3d8817e4Smiod 			{
11415*3d8817e4Smiod 			  xg_add_opcode_fix (tinsn, i, fmt, slot, expr, fragP,
11416*3d8817e4Smiod 					     frag_offset - fragP->fr_literal);
11417*3d8817e4Smiod 			}
11418*3d8817e4Smiod 		      else
11419*3d8817e4Smiod 			{
11420*3d8817e4Smiod 			  if (expr->X_op != O_symbol)
11421*3d8817e4Smiod 			    as_bad (_("invalid operand"));
11422*3d8817e4Smiod 			  tinsn->symbol = expr->X_add_symbol;
11423*3d8817e4Smiod 			  tinsn->offset = expr->X_add_number;
11424*3d8817e4Smiod 			}
11425*3d8817e4Smiod 		    }
11426*3d8817e4Smiod 		  else
11427*3d8817e4Smiod 		    as_bad (_("symbolic operand not allowed"));
11428*3d8817e4Smiod 		  break;
11429*3d8817e4Smiod 
11430*3d8817e4Smiod 		case O_constant:
11431*3d8817e4Smiod 		case O_register:
11432*3d8817e4Smiod 		  break;
11433*3d8817e4Smiod 
11434*3d8817e4Smiod 		default:
11435*3d8817e4Smiod 		  as_bad (_("expression too complex"));
11436*3d8817e4Smiod 		  break;
11437*3d8817e4Smiod 		}
11438*3d8817e4Smiod 	    }
11439*3d8817e4Smiod 	}
11440*3d8817e4Smiod     }
11441*3d8817e4Smiod 
11442*3d8817e4Smiod   return has_fixup;
11443*3d8817e4Smiod }
11444*3d8817e4Smiod 
11445*3d8817e4Smiod 
11446*3d8817e4Smiod static void
vinsn_from_chars(vliw_insn * vinsn,char * f)11447*3d8817e4Smiod vinsn_from_chars (vliw_insn *vinsn, char *f)
11448*3d8817e4Smiod {
11449*3d8817e4Smiod   static xtensa_insnbuf insnbuf = NULL;
11450*3d8817e4Smiod   static xtensa_insnbuf slotbuf = NULL;
11451*3d8817e4Smiod   int i;
11452*3d8817e4Smiod   xtensa_format fmt;
11453*3d8817e4Smiod   xtensa_isa isa = xtensa_default_isa;
11454*3d8817e4Smiod 
11455*3d8817e4Smiod   if (!insnbuf)
11456*3d8817e4Smiod     {
11457*3d8817e4Smiod       insnbuf = xtensa_insnbuf_alloc (isa);
11458*3d8817e4Smiod       slotbuf = xtensa_insnbuf_alloc (isa);
11459*3d8817e4Smiod     }
11460*3d8817e4Smiod 
11461*3d8817e4Smiod   xtensa_insnbuf_from_chars (isa, insnbuf, (unsigned char *) f, 0);
11462*3d8817e4Smiod   fmt = xtensa_format_decode (isa, insnbuf);
11463*3d8817e4Smiod   if (fmt == XTENSA_UNDEFINED)
11464*3d8817e4Smiod     as_fatal (_("cannot decode instruction format"));
11465*3d8817e4Smiod   vinsn->format = fmt;
11466*3d8817e4Smiod   vinsn->num_slots = xtensa_format_num_slots (isa, fmt);
11467*3d8817e4Smiod 
11468*3d8817e4Smiod   for (i = 0; i < vinsn->num_slots; i++)
11469*3d8817e4Smiod     {
11470*3d8817e4Smiod       TInsn *tinsn = &vinsn->slots[i];
11471*3d8817e4Smiod       xtensa_format_get_slot (isa, fmt, i, insnbuf, slotbuf);
11472*3d8817e4Smiod       tinsn_from_insnbuf (tinsn, slotbuf, fmt, i);
11473*3d8817e4Smiod     }
11474*3d8817e4Smiod }
11475*3d8817e4Smiod 
11476*3d8817e4Smiod 
11477*3d8817e4Smiod /* Expression utilities.  */
11478*3d8817e4Smiod 
11479*3d8817e4Smiod /* Return TRUE if the expression is an integer constant.  */
11480*3d8817e4Smiod 
11481*3d8817e4Smiod bfd_boolean
expr_is_const(const expressionS * s)11482*3d8817e4Smiod expr_is_const (const expressionS *s)
11483*3d8817e4Smiod {
11484*3d8817e4Smiod   return (s->X_op == O_constant);
11485*3d8817e4Smiod }
11486*3d8817e4Smiod 
11487*3d8817e4Smiod 
11488*3d8817e4Smiod /* Get the expression constant.
11489*3d8817e4Smiod    Calling this is illegal if expr_is_const () returns TRUE.  */
11490*3d8817e4Smiod 
11491*3d8817e4Smiod offsetT
get_expr_const(const expressionS * s)11492*3d8817e4Smiod get_expr_const (const expressionS *s)
11493*3d8817e4Smiod {
11494*3d8817e4Smiod   assert (expr_is_const (s));
11495*3d8817e4Smiod   return s->X_add_number;
11496*3d8817e4Smiod }
11497*3d8817e4Smiod 
11498*3d8817e4Smiod 
11499*3d8817e4Smiod /* Set the expression to a constant value.  */
11500*3d8817e4Smiod 
11501*3d8817e4Smiod void
set_expr_const(expressionS * s,offsetT val)11502*3d8817e4Smiod set_expr_const (expressionS *s, offsetT val)
11503*3d8817e4Smiod {
11504*3d8817e4Smiod   s->X_op = O_constant;
11505*3d8817e4Smiod   s->X_add_number = val;
11506*3d8817e4Smiod   s->X_add_symbol = NULL;
11507*3d8817e4Smiod   s->X_op_symbol = NULL;
11508*3d8817e4Smiod }
11509*3d8817e4Smiod 
11510*3d8817e4Smiod 
11511*3d8817e4Smiod bfd_boolean
expr_is_register(const expressionS * s)11512*3d8817e4Smiod expr_is_register (const expressionS *s)
11513*3d8817e4Smiod {
11514*3d8817e4Smiod   return (s->X_op == O_register);
11515*3d8817e4Smiod }
11516*3d8817e4Smiod 
11517*3d8817e4Smiod 
11518*3d8817e4Smiod /* Get the expression constant.
11519*3d8817e4Smiod    Calling this is illegal if expr_is_const () returns TRUE.  */
11520*3d8817e4Smiod 
11521*3d8817e4Smiod offsetT
get_expr_register(const expressionS * s)11522*3d8817e4Smiod get_expr_register (const expressionS *s)
11523*3d8817e4Smiod {
11524*3d8817e4Smiod   assert (expr_is_register (s));
11525*3d8817e4Smiod   return s->X_add_number;
11526*3d8817e4Smiod }
11527*3d8817e4Smiod 
11528*3d8817e4Smiod 
11529*3d8817e4Smiod /* Set the expression to a symbol + constant offset.  */
11530*3d8817e4Smiod 
11531*3d8817e4Smiod void
set_expr_symbol_offset(expressionS * s,symbolS * sym,offsetT offset)11532*3d8817e4Smiod set_expr_symbol_offset (expressionS *s, symbolS *sym, offsetT offset)
11533*3d8817e4Smiod {
11534*3d8817e4Smiod   s->X_op = O_symbol;
11535*3d8817e4Smiod   s->X_add_symbol = sym;
11536*3d8817e4Smiod   s->X_op_symbol = NULL;	/* unused */
11537*3d8817e4Smiod   s->X_add_number = offset;
11538*3d8817e4Smiod }
11539*3d8817e4Smiod 
11540*3d8817e4Smiod 
11541*3d8817e4Smiod /* Return TRUE if the two expressions are equal.  */
11542*3d8817e4Smiod 
11543*3d8817e4Smiod bfd_boolean
expr_is_equal(expressionS * s1,expressionS * s2)11544*3d8817e4Smiod expr_is_equal (expressionS *s1, expressionS *s2)
11545*3d8817e4Smiod {
11546*3d8817e4Smiod   if (s1->X_op != s2->X_op)
11547*3d8817e4Smiod     return FALSE;
11548*3d8817e4Smiod   if (s1->X_add_symbol != s2->X_add_symbol)
11549*3d8817e4Smiod     return FALSE;
11550*3d8817e4Smiod   if (s1->X_op_symbol != s2->X_op_symbol)
11551*3d8817e4Smiod     return FALSE;
11552*3d8817e4Smiod   if (s1->X_add_number != s2->X_add_number)
11553*3d8817e4Smiod     return FALSE;
11554*3d8817e4Smiod   return TRUE;
11555*3d8817e4Smiod }
11556*3d8817e4Smiod 
11557*3d8817e4Smiod 
11558*3d8817e4Smiod static void
copy_expr(expressionS * dst,const expressionS * src)11559*3d8817e4Smiod copy_expr (expressionS *dst, const expressionS *src)
11560*3d8817e4Smiod {
11561*3d8817e4Smiod   memcpy (dst, src, sizeof (expressionS));
11562*3d8817e4Smiod }
11563*3d8817e4Smiod 
11564*3d8817e4Smiod 
11565*3d8817e4Smiod /* Support for the "--rename-section" option.  */
11566*3d8817e4Smiod 
11567*3d8817e4Smiod struct rename_section_struct
11568*3d8817e4Smiod {
11569*3d8817e4Smiod   char *old_name;
11570*3d8817e4Smiod   char *new_name;
11571*3d8817e4Smiod   struct rename_section_struct *next;
11572*3d8817e4Smiod };
11573*3d8817e4Smiod 
11574*3d8817e4Smiod static struct rename_section_struct *section_rename;
11575*3d8817e4Smiod 
11576*3d8817e4Smiod 
11577*3d8817e4Smiod /* Parse the string "oldname=new_name(:oldname2=new_name2)*" and add
11578*3d8817e4Smiod    entries to the section_rename list.  Note: Specifying multiple
11579*3d8817e4Smiod    renamings separated by colons is not documented and is retained only
11580*3d8817e4Smiod    for backward compatibility.  */
11581*3d8817e4Smiod 
11582*3d8817e4Smiod static void
build_section_rename(const char * arg)11583*3d8817e4Smiod build_section_rename (const char *arg)
11584*3d8817e4Smiod {
11585*3d8817e4Smiod   struct rename_section_struct *r;
11586*3d8817e4Smiod   char *this_arg = NULL;
11587*3d8817e4Smiod   char *next_arg = NULL;
11588*3d8817e4Smiod 
11589*3d8817e4Smiod   for (this_arg = xstrdup (arg); this_arg != NULL; this_arg = next_arg)
11590*3d8817e4Smiod     {
11591*3d8817e4Smiod       char *old_name, *new_name;
11592*3d8817e4Smiod 
11593*3d8817e4Smiod       if (this_arg)
11594*3d8817e4Smiod 	{
11595*3d8817e4Smiod 	  next_arg = strchr (this_arg, ':');
11596*3d8817e4Smiod 	  if (next_arg)
11597*3d8817e4Smiod 	    {
11598*3d8817e4Smiod 	      *next_arg = '\0';
11599*3d8817e4Smiod 	      next_arg++;
11600*3d8817e4Smiod 	    }
11601*3d8817e4Smiod 	}
11602*3d8817e4Smiod 
11603*3d8817e4Smiod       old_name = this_arg;
11604*3d8817e4Smiod       new_name = strchr (this_arg, '=');
11605*3d8817e4Smiod 
11606*3d8817e4Smiod       if (*old_name == '\0')
11607*3d8817e4Smiod 	{
11608*3d8817e4Smiod 	  as_warn (_("ignoring extra '-rename-section' delimiter ':'"));
11609*3d8817e4Smiod 	  continue;
11610*3d8817e4Smiod 	}
11611*3d8817e4Smiod       if (!new_name || new_name[1] == '\0')
11612*3d8817e4Smiod 	{
11613*3d8817e4Smiod 	  as_warn (_("ignoring invalid '-rename-section' specification: '%s'"),
11614*3d8817e4Smiod 		   old_name);
11615*3d8817e4Smiod 	  continue;
11616*3d8817e4Smiod 	}
11617*3d8817e4Smiod       *new_name = '\0';
11618*3d8817e4Smiod       new_name++;
11619*3d8817e4Smiod 
11620*3d8817e4Smiod       /* Check for invalid section renaming.  */
11621*3d8817e4Smiod       for (r = section_rename; r != NULL; r = r->next)
11622*3d8817e4Smiod 	{
11623*3d8817e4Smiod 	  if (strcmp (r->old_name, old_name) == 0)
11624*3d8817e4Smiod 	    as_bad (_("section %s renamed multiple times"), old_name);
11625*3d8817e4Smiod 	  if (strcmp (r->new_name, new_name) == 0)
11626*3d8817e4Smiod 	    as_bad (_("multiple sections remapped to output section %s"),
11627*3d8817e4Smiod 		    new_name);
11628*3d8817e4Smiod 	}
11629*3d8817e4Smiod 
11630*3d8817e4Smiod       /* Now add it.  */
11631*3d8817e4Smiod       r = (struct rename_section_struct *)
11632*3d8817e4Smiod 	xmalloc (sizeof (struct rename_section_struct));
11633*3d8817e4Smiod       r->old_name = xstrdup (old_name);
11634*3d8817e4Smiod       r->new_name = xstrdup (new_name);
11635*3d8817e4Smiod       r->next = section_rename;
11636*3d8817e4Smiod       section_rename = r;
11637*3d8817e4Smiod     }
11638*3d8817e4Smiod }
11639*3d8817e4Smiod 
11640*3d8817e4Smiod 
11641*3d8817e4Smiod char *
xtensa_section_rename(char * name)11642*3d8817e4Smiod xtensa_section_rename (char *name)
11643*3d8817e4Smiod {
11644*3d8817e4Smiod   struct rename_section_struct *r = section_rename;
11645*3d8817e4Smiod 
11646*3d8817e4Smiod   for (r = section_rename; r != NULL; r = r->next)
11647*3d8817e4Smiod     {
11648*3d8817e4Smiod       if (strcmp (r->old_name, name) == 0)
11649*3d8817e4Smiod 	return r->new_name;
11650*3d8817e4Smiod     }
11651*3d8817e4Smiod 
11652*3d8817e4Smiod   return name;
11653*3d8817e4Smiod }
11654