Add -z noextern-protected-data to ld for ELF/x86
[deliverable/binutils-gdb.git] / gas / config / xtensa-relax.c
CommitLineData
e0001a05 1/* Table of relaxations for Xtensa assembly.
b90efa5b 2 Copyright (C) 2003-2015 Free Software Foundation, Inc.
e0001a05
NC
3
4 This file is part of GAS, the GNU Assembler.
5
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
ec2655a6 8 the Free Software Foundation; either version 3, or (at your option)
e0001a05
NC
9 any later version.
10
11 GAS is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GAS; see the file COPYING. If not, write to
c138bc38 18 the Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
4b4da160 19 MA 02110-1301, USA. */
e0001a05
NC
20
21/* This file contains the code for generating runtime data structures
22 for relaxation pattern matching from statically specified strings.
23 Each action contains an instruction pattern to match and
24 preconditions for the match as well as an expansion if the pattern
25 matches. The preconditions can specify that two operands are the
43cd72b9
BW
26 same or an operand is a specific constant or register. The expansion
27 uses the bound variables from the pattern to specify that specific
c138bc38 28 operands from the pattern should be used in the result.
43cd72b9
BW
29
30 The code determines whether the condition applies to a constant or
31 a register depending on the type of the operand. You may get
32 unexpected results if you don't match the rule against the operand
33 type correctly.
e0001a05
NC
34
35 The patterns match a language like:
36
43cd72b9 37 INSN_PATTERN ::= INSN_TEMPL ( '|' PRECOND )* ( '?' OPTIONPRED )*
e0001a05
NC
38 INSN_TEMPL ::= OPCODE ' ' [ OPERAND (',' OPERAND)* ]
39 OPCODE ::= id
40 OPERAND ::= CONSTANT | VARIABLE | SPECIALFN '(' VARIABLE ')'
41 SPECIALFN ::= 'HI24S' | 'F32MINUS' | 'LOW8'
43cd72b9 42 | 'HI16' | 'LOW16'
e0001a05
NC
43 VARIABLE ::= '%' id
44 PRECOND ::= OPERAND CMPOP OPERAND
45 CMPOP ::= '==' | '!='
43cd72b9
BW
46 OPTIONPRED ::= OPTIONNAME ('+' OPTIONNAME)
47 OPTIONNAME ::= '"' id '"'
e0001a05 48
c138bc38 49 The replacement language
e0001a05 50 INSN_REPL ::= INSN_LABEL_LIT ( ';' INSN_LABEL_LIT )*
c138bc38 51 INSN_LABEL_LIT ::= INSN_TEMPL
61376837
BW
52 | 'LABEL'
53 | 'LITERAL' VARIABLE
e0001a05
NC
54
55 The operands in a PRECOND must be constants or variables bound by
56 the INSN_PATTERN.
57
43cd72b9
BW
58 The configuration options define a predicate on the availability of
59 options which must be TRUE for this rule to be valid. Examples are
60 requiring "density" for replacements with density instructions,
61 requiring "const16" for replacements that require const16
62 instructions, etc. The names are interpreted by the assembler to a
63 truth value for a particular frag.
64
e0001a05
NC
65 The operands in the INSN_REPL must be constants, variables bound in
66 the associated INSN_PATTERN, special variables that are bound in
67 the INSN_REPL by LABEL or LITERAL definitions, or special value
68 manipulation functions.
69
70 A simple example of a replacement pattern:
71 {"movi.n %as,%imm", "movi %as,%imm"} would convert the narrow
72 movi.n instruction to the wide movi instruction.
73
74 A more complex example of a branch around:
61376837 75 {"beqz %as,%label", "bnez %as,%LABEL;j %label;LABEL"}
e0001a05
NC
76 would convert a branch to a negated branch to the following instruction
77 with a jump to the original label.
c138bc38 78
e0001a05 79 An Xtensa-specific example that generates a literal:
61376837 80 {"movi %at,%imm", "LITERAL %imm; l32r %at,%LITERAL"}
e0001a05
NC
81 will convert a movi instruction to an l32r of a literal
82 literal defined in the literal pool.
83
84 Even more complex is a conversion of a load with immediate offset
85 to a load of a freshly generated literal, an explicit add and
86 a load with 0 offset. This transformation is only valid, though
87 when the first and second operands are not the same as specified
88 by the "| %at!=%as" precondition clause.
89 {"l32i %at,%as,%imm | %at!=%as",
61376837 90 "LITERAL %imm; l32r %at,%LITERAL; add %at,%at,%as; l32i %at,%at,0"}
e0001a05
NC
91
92 There is special case for loop instructions here, but because we do
93 not currently have the ability to represent the difference of two
94 symbols, the conversion requires special code in the assembler to
95 write the operands of the addi/addmi pair representing the
96 difference of the old and new loop end label. */
97
98#include "as.h"
99#include "xtensa-isa.h"
100#include "xtensa-relax.h"
101#include <stddef.h>
43cd72b9 102#include "xtensa-config.h"
e0001a05 103
395fa56f
BW
104#ifndef XCHAL_HAVE_WIDE_BRANCHES
105#define XCHAL_HAVE_WIDE_BRANCHES 0
106#endif
107
e0001a05
NC
108/* Imported from bfd. */
109extern xtensa_isa xtensa_default_isa;
110
e0001a05
NC
111/* The opname_list is a small list of names that we use for opcode and
112 operand variable names to simplify ownership of these commonly used
113 strings. Strings entered in the table can be compared by pointer
114 equality. */
115
116typedef struct opname_list_struct opname_list;
117typedef opname_list opname_e;
118
119struct opname_list_struct
120{
121 char *opname;
122 opname_list *next;
123};
124
125static opname_list *local_opnames = NULL;
126
127
128/* The "opname_map" and its element structure "opname_map_e" are used
129 for binding an operand number to a name or a constant. */
130
131typedef struct opname_map_e_struct opname_map_e;
132typedef struct opname_map_struct opname_map;
133
134struct opname_map_e_struct
135{
136 const char *operand_name; /* If null, then use constant_value. */
43cd72b9 137 int operand_num;
e0001a05
NC
138 unsigned constant_value;
139 opname_map_e *next;
140};
141
142struct opname_map_struct
143{
144 opname_map_e *head;
145 opname_map_e **tail;
146};
147
148/* The "precond_list" and its element structure "precond_e" represents
149 explicit preconditions comparing operand variables and constants.
150 In the "precond_e" structure, a variable is identified by the name
151 in the "opname" field. If that field is NULL, then the operand
152 is the constant in field "opval". */
153
154typedef struct precond_e_struct precond_e;
155typedef struct precond_list_struct precond_list;
156
157struct precond_e_struct
158{
159 const char *opname1;
160 unsigned opval1;
161 CmpOp cmpop;
162 const char *opname2;
163 unsigned opval2;
164 precond_e *next;
165};
166
167struct precond_list_struct
168{
169 precond_e *head;
170 precond_e **tail;
171};
172
173
174/* The insn_templ represents the INSN_TEMPL instruction template. It
175 is an opcode name with a list of operands. These are used for
176 instruction patterns and replacement patterns. */
177
178typedef struct insn_templ_struct insn_templ;
179struct insn_templ_struct
180{
181 const char *opcode_name;
182 opname_map operand_map;
183};
184
185
186/* The insn_pattern represents an INSN_PATTERN instruction pattern.
187 It is an instruction template with preconditions that specify when
188 it actually matches a given instruction. */
189
190typedef struct insn_pattern_struct insn_pattern;
191struct insn_pattern_struct
192{
193 insn_templ t;
194 precond_list preconds;
43cd72b9 195 ReqOptionList *options;
e0001a05
NC
196};
197
198
199/* The "insn_repl" and associated element structure "insn_repl_e"
200 instruction replacement list is a list of
201 instructions/LITERALS/LABELS with constant operands or operands
202 with names bound to the operand names in the associated pattern. */
203
204typedef struct insn_repl_e_struct insn_repl_e;
205struct insn_repl_e_struct
206{
207 insn_templ t;
208 insn_repl_e *next;
209};
210
211typedef struct insn_repl_struct insn_repl;
212struct insn_repl_struct
213{
214 insn_repl_e *head;
215 insn_repl_e **tail;
216};
217
218
219/* The split_rec is a vector of allocated char * pointers. */
220
221typedef struct split_rec_struct split_rec;
222struct split_rec_struct
223{
224 char **vec;
43cd72b9 225 int count;
e0001a05
NC
226};
227
228/* The "string_pattern_pair" is a set of pairs containing instruction
229 patterns and replacement strings. */
230
231typedef struct string_pattern_pair_struct string_pattern_pair;
232struct string_pattern_pair_struct
233{
234 const char *pattern;
235 const char *replacement;
236};
237
238\f
239/* The widen_spec_list is a list of valid substitutions that generate
240 wider representations. These are generally used to specify
241 replacements for instructions whose immediates do not fit their
33b7f697 242 encodings. A valid transition may require multiple steps of
e0001a05
NC
243 one-to-one instruction replacements with a final multiple
244 instruction replacement. As an example, here are the transitions
245 required to replace an 'addi.n' with an 'addi', 'addmi'.
246
247 addi.n a4, 0x1010
248 => addi a4, 0x1010
249 => addmi a4, 0x1010
b81bf389
BW
250 => addmi a4, 0x1000, addi a4, 0x10.
251
252 See the comments in xg_assembly_relax for some important details
253 regarding how these chains must be built. */
e0001a05
NC
254
255static string_pattern_pair widen_spec_list[] =
256{
43cd72b9
BW
257 {"add.n %ar,%as,%at ? IsaUseDensityInstruction", "add %ar,%as,%at"},
258 {"addi.n %ar,%as,%imm ? IsaUseDensityInstruction", "addi %ar,%as,%imm"},
259 {"beqz.n %as,%label ? IsaUseDensityInstruction", "beqz %as,%label"},
260 {"bnez.n %as,%label ? IsaUseDensityInstruction", "bnez %as,%label"},
261 {"l32i.n %at,%as,%imm ? IsaUseDensityInstruction", "l32i %at,%as,%imm"},
262 {"mov.n %at,%as ? IsaUseDensityInstruction", "or %at,%as,%as"},
263 {"movi.n %as,%imm ? IsaUseDensityInstruction", "movi %as,%imm"},
264 {"nop.n ? IsaUseDensityInstruction ? realnop", "nop"},
265 {"nop.n ? IsaUseDensityInstruction ? no-realnop", "or 1,1,1"},
266 {"ret.n %as ? IsaUseDensityInstruction", "ret %as"},
267 {"retw.n %as ? IsaUseDensityInstruction", "retw %as"},
268 {"s32i.n %at,%as,%imm ? IsaUseDensityInstruction", "s32i %at,%as,%imm"},
e0001a05
NC
269 {"srli %at,%as,%imm", "extui %at,%as,%imm,F32MINUS(%imm)"},
270 {"slli %ar,%as,0", "or %ar,%as,%as"},
43cd72b9
BW
271
272 /* Widening with literals or const16. */
c138bc38 273 {"movi %at,%imm ? IsaUseL32R ",
61376837 274 "LITERAL %imm; l32r %at,%LITERAL"},
c138bc38 275 {"movi %at,%imm ? IsaUseConst16",
43cd72b9
BW
276 "const16 %at,HI16U(%imm); const16 %at,LOW16U(%imm)"},
277
e0001a05
NC
278 {"addi %ar,%as,%imm", "addmi %ar,%as,%imm"},
279 /* LOW8 is the low 8 bits of the Immed
280 MID8S is the middle 8 bits of the Immed */
281 {"addmi %ar,%as,%imm", "addmi %ar,%as,HI24S(%imm); addi %ar,%ar,LOW8(%imm)"},
43cd72b9
BW
282
283 /* In the end convert to either an l32r or const16. */
284 {"addmi %ar,%as,%imm | %ar!=%as ? IsaUseL32R",
61376837 285 "LITERAL %imm; l32r %ar,%LITERAL; add %ar,%as,%ar"},
43cd72b9
BW
286 {"addmi %ar,%as,%imm | %ar!=%as ? IsaUseConst16",
287 "const16 %ar,HI16U(%imm); const16 %ar,LOW16U(%imm); add %ar,%as,%ar"},
e0001a05
NC
288
289 /* Widening the load instructions with too-large immediates */
43cd72b9 290 {"l8ui %at,%as,%imm | %at!=%as ? IsaUseL32R",
61376837 291 "LITERAL %imm; l32r %at,%LITERAL; add %at,%at,%as; l8ui %at,%at,0"},
43cd72b9 292 {"l16si %at,%as,%imm | %at!=%as ? IsaUseL32R",
61376837 293 "LITERAL %imm; l32r %at,%LITERAL; add %at,%at,%as; l16si %at,%at,0"},
43cd72b9 294 {"l16ui %at,%as,%imm | %at!=%as ? IsaUseL32R",
61376837 295 "LITERAL %imm; l32r %at,%LITERAL; add %at,%at,%as; l16ui %at,%at,0"},
43cd72b9 296 {"l32i %at,%as,%imm | %at!=%as ? IsaUseL32R",
61376837 297 "LITERAL %imm; l32r %at,%LITERAL; add %at,%at,%as; l32i %at,%at,0"},
43cd72b9
BW
298
299 /* Widening load instructions with const16s. */
300 {"l8ui %at,%as,%imm | %at!=%as ? IsaUseConst16",
301 "const16 %at,HI16U(%imm); const16 %at,LOW16U(%imm); add %at,%at,%as; l8ui %at,%at,0"},
302 {"l16si %at,%as,%imm | %at!=%as ? IsaUseConst16",
303 "const16 %at,HI16U(%imm); const16 %at,LOW16U(%imm); add %at,%at,%as; l16si %at,%at,0"},
304 {"l16ui %at,%as,%imm | %at!=%as ? IsaUseConst16",
305 "const16 %at,HI16U(%imm); const16 %at,LOW16U(%imm); add %at,%at,%as; l16ui %at,%at,0"},
306 {"l32i %at,%as,%imm | %at!=%as ? IsaUseConst16",
307 "const16 %at,HI16U(%imm); const16 %at,LOW16U(%imm); add %at,%at,%as; l32i %at,%at,0"},
308
43cd72b9
BW
309 /* This is only PART of the loop instruction. In addition,
310 hardcoded into its use is a modification of the final operand in
311 the instruction in bytes 9 and 12. */
312 {"loop %as,%label | %as!=1 ? IsaUseLoops",
61376837 313 "loop %as,%LABEL;"
43cd72b9
BW
314 "rsr.lend %as;" /* LEND */
315 "wsr.lbeg %as;" /* LBEG */
e0001a05
NC
316 "addi %as, %as, 0;" /* lo8(%label-%LABEL1) */
317 "addmi %as, %as, 0;" /* mid8(%label-%LABEL1) */
43cd72b9 318 "wsr.lend %as;"
e0001a05 319 "isync;"
43cd72b9 320 "rsr.lcount %as;" /* LCOUNT */
e0001a05 321 "addi %as, %as, 1;" /* density -> addi.n %as, %as, 1 */
61376837 322 "LABEL"},
43cd72b9
BW
323 {"loopgtz %as,%label | %as!=1 ? IsaUseLoops",
324 "beqz %as,%label;"
325 "bltz %as,%label;"
61376837 326 "loopgtz %as,%LABEL;"
43cd72b9
BW
327 "rsr.lend %as;" /* LEND */
328 "wsr.lbeg %as;" /* LBEG */
e0001a05
NC
329 "addi %as, %as, 0;" /* lo8(%label-%LABEL1) */
330 "addmi %as, %as, 0;" /* mid8(%label-%LABEL1) */
43cd72b9 331 "wsr.lend %as;"
e0001a05 332 "isync;"
43cd72b9 333 "rsr.lcount %as;" /* LCOUNT */
e0001a05 334 "addi %as, %as, 1;" /* density -> addi.n %as, %as, 1 */
61376837 335 "LABEL"},
43cd72b9 336 {"loopnez %as,%label | %as!=1 ? IsaUseLoops",
e0001a05 337 "beqz %as,%label;"
61376837 338 "loopnez %as,%LABEL;"
43cd72b9
BW
339 "rsr.lend %as;" /* LEND */
340 "wsr.lbeg %as;" /* LBEG */
e0001a05
NC
341 "addi %as, %as, 0;" /* lo8(%label-%LABEL1) */
342 "addmi %as, %as, 0;" /* mid8(%label-%LABEL1) */
43cd72b9 343 "wsr.lend %as;"
e0001a05 344 "isync;"
43cd72b9 345 "rsr.lcount %as;" /* LCOUNT */
e0001a05 346 "addi %as, %as, 1;" /* density -> addi.n %as, %as, 1 */
61376837 347 "LABEL"},
e0001a05 348
b2d179be
BW
349 /* Relaxing to wide branches. Order is important here. With wide
350 branches, there is more than one correct relaxation for an
351 out-of-range branch. Put the wide branch relaxations first in the
352 table since they are more efficient than the branch-around
353 relaxations. */
354
1946c96e
BW
355 {"beqz %as,%label ? IsaUseWideBranches", "WIDE.beqz %as,%label"},
356 {"bnez %as,%label ? IsaUseWideBranches", "WIDE.bnez %as,%label"},
357 {"bgez %as,%label ? IsaUseWideBranches", "WIDE.bgez %as,%label"},
358 {"bltz %as,%label ? IsaUseWideBranches", "WIDE.bltz %as,%label"},
359 {"beqi %as,%imm,%label ? IsaUseWideBranches", "WIDE.beqi %as,%imm,%label"},
360 {"bnei %as,%imm,%label ? IsaUseWideBranches", "WIDE.bnei %as,%imm,%label"},
361 {"bgei %as,%imm,%label ? IsaUseWideBranches", "WIDE.bgei %as,%imm,%label"},
362 {"blti %as,%imm,%label ? IsaUseWideBranches", "WIDE.blti %as,%imm,%label"},
363 {"bgeui %as,%imm,%label ? IsaUseWideBranches", "WIDE.bgeui %as,%imm,%label"},
364 {"bltui %as,%imm,%label ? IsaUseWideBranches", "WIDE.bltui %as,%imm,%label"},
365 {"bbci %as,%imm,%label ? IsaUseWideBranches", "WIDE.bbci %as,%imm,%label"},
366 {"bbsi %as,%imm,%label ? IsaUseWideBranches", "WIDE.bbsi %as,%imm,%label"},
367 {"beq %as,%at,%label ? IsaUseWideBranches", "WIDE.beq %as,%at,%label"},
368 {"bne %as,%at,%label ? IsaUseWideBranches", "WIDE.bne %as,%at,%label"},
369 {"bge %as,%at,%label ? IsaUseWideBranches", "WIDE.bge %as,%at,%label"},
370 {"blt %as,%at,%label ? IsaUseWideBranches", "WIDE.blt %as,%at,%label"},
371 {"bgeu %as,%at,%label ? IsaUseWideBranches", "WIDE.bgeu %as,%at,%label"},
372 {"bltu %as,%at,%label ? IsaUseWideBranches", "WIDE.bltu %as,%at,%label"},
373 {"bany %as,%at,%label ? IsaUseWideBranches", "WIDE.bany %as,%at,%label"},
374 {"bnone %as,%at,%label ? IsaUseWideBranches", "WIDE.bnone %as,%at,%label"},
375 {"ball %as,%at,%label ? IsaUseWideBranches", "WIDE.ball %as,%at,%label"},
376 {"bnall %as,%at,%label ? IsaUseWideBranches", "WIDE.bnall %as,%at,%label"},
377 {"bbc %as,%at,%label ? IsaUseWideBranches", "WIDE.bbc %as,%at,%label"},
378 {"bbs %as,%at,%label ? IsaUseWideBranches", "WIDE.bbs %as,%at,%label"},
b2d179be
BW
379
380 /* Widening branch comparisons eq/ne to zero. Prefer relaxing to narrow
381 branches if the density option is available. */
61376837
BW
382 {"beqz %as,%label ? IsaUseDensityInstruction", "bnez.n %as,%LABEL;j %label;LABEL"},
383 {"bnez %as,%label ? IsaUseDensityInstruction", "beqz.n %as,%LABEL;j %label;LABEL"},
384 {"beqz %as,%label", "bnez %as,%LABEL;j %label;LABEL"},
385 {"bnez %as,%label", "beqz %as,%LABEL;j %label;LABEL"},
b81bf389
BW
386 {"WIDE.beqz %as,%label ? IsaUseDensityInstruction", "bnez.n %as,%LABEL;j %label;LABEL"},
387 {"WIDE.bnez %as,%label ? IsaUseDensityInstruction", "beqz.n %as,%LABEL;j %label;LABEL"},
388 {"WIDE.beqz %as,%label", "bnez %as,%LABEL;j %label;LABEL"},
389 {"WIDE.bnez %as,%label", "beqz %as,%LABEL;j %label;LABEL"},
b2d179be
BW
390
391 /* Widening expect-taken branches. */
61376837
BW
392 {"beqzt %as,%label ? IsaUsePredictedBranches", "bnez %as,%LABEL;j %label;LABEL"},
393 {"bnezt %as,%label ? IsaUsePredictedBranches", "beqz %as,%LABEL;j %label;LABEL"},
394 {"beqt %as,%at,%label ? IsaUsePredictedBranches", "bne %as,%at,%LABEL;j %label;LABEL"},
395 {"bnet %as,%at,%label ? IsaUsePredictedBranches", "beq %as,%at,%LABEL;j %label;LABEL"},
b2d179be
BW
396
397 /* Widening branches from the Xtensa boolean option. */
61376837
BW
398 {"bt %bs,%label ? IsaUseBooleans", "bf %bs,%LABEL;j %label;LABEL"},
399 {"bf %bs,%label ? IsaUseBooleans", "bt %bs,%LABEL;j %label;LABEL"},
e0001a05 400
b2d179be 401 /* Other branch-around-jump widenings. */
61376837
BW
402 {"bgez %as,%label", "bltz %as,%LABEL;j %label;LABEL"},
403 {"bltz %as,%label", "bgez %as,%LABEL;j %label;LABEL"},
404 {"beqi %as,%imm,%label", "bnei %as,%imm,%LABEL;j %label;LABEL"},
405 {"bnei %as,%imm,%label", "beqi %as,%imm,%LABEL;j %label;LABEL"},
406 {"bgei %as,%imm,%label", "blti %as,%imm,%LABEL;j %label;LABEL"},
407 {"blti %as,%imm,%label", "bgei %as,%imm,%LABEL;j %label;LABEL"},
408 {"bgeui %as,%imm,%label", "bltui %as,%imm,%LABEL;j %label;LABEL"},
409 {"bltui %as,%imm,%label", "bgeui %as,%imm,%LABEL;j %label;LABEL"},
410 {"bbci %as,%imm,%label", "bbsi %as,%imm,%LABEL;j %label;LABEL"},
411 {"bbsi %as,%imm,%label", "bbci %as,%imm,%LABEL;j %label;LABEL"},
412 {"beq %as,%at,%label", "bne %as,%at,%LABEL;j %label;LABEL"},
413 {"bne %as,%at,%label", "beq %as,%at,%LABEL;j %label;LABEL"},
414 {"bge %as,%at,%label", "blt %as,%at,%LABEL;j %label;LABEL"},
415 {"blt %as,%at,%label", "bge %as,%at,%LABEL;j %label;LABEL"},
416 {"bgeu %as,%at,%label", "bltu %as,%at,%LABEL;j %label;LABEL"},
417 {"bltu %as,%at,%label", "bgeu %as,%at,%LABEL;j %label;LABEL"},
418 {"bany %as,%at,%label", "bnone %as,%at,%LABEL;j %label;LABEL"},
419 {"bnone %as,%at,%label", "bany %as,%at,%LABEL;j %label;LABEL"},
420 {"ball %as,%at,%label", "bnall %as,%at,%LABEL;j %label;LABEL"},
421 {"bnall %as,%at,%label", "ball %as,%at,%LABEL;j %label;LABEL"},
422 {"bbc %as,%at,%label", "bbs %as,%at,%LABEL;j %label;LABEL"},
423 {"bbs %as,%at,%label", "bbc %as,%at,%LABEL;j %label;LABEL"},
43cd72b9 424
b81bf389
BW
425 {"WIDE.bgez %as,%label", "bltz %as,%LABEL;j %label;LABEL"},
426 {"WIDE.bltz %as,%label", "bgez %as,%LABEL;j %label;LABEL"},
427 {"WIDE.beqi %as,%imm,%label", "bnei %as,%imm,%LABEL;j %label;LABEL"},
428 {"WIDE.bnei %as,%imm,%label", "beqi %as,%imm,%LABEL;j %label;LABEL"},
429 {"WIDE.bgei %as,%imm,%label", "blti %as,%imm,%LABEL;j %label;LABEL"},
430 {"WIDE.blti %as,%imm,%label", "bgei %as,%imm,%LABEL;j %label;LABEL"},
431 {"WIDE.bgeui %as,%imm,%label", "bltui %as,%imm,%LABEL;j %label;LABEL"},
432 {"WIDE.bltui %as,%imm,%label", "bgeui %as,%imm,%LABEL;j %label;LABEL"},
433 {"WIDE.bbci %as,%imm,%label", "bbsi %as,%imm,%LABEL;j %label;LABEL"},
434 {"WIDE.bbsi %as,%imm,%label", "bbci %as,%imm,%LABEL;j %label;LABEL"},
435 {"WIDE.beq %as,%at,%label", "bne %as,%at,%LABEL;j %label;LABEL"},
436 {"WIDE.bne %as,%at,%label", "beq %as,%at,%LABEL;j %label;LABEL"},
437 {"WIDE.bge %as,%at,%label", "blt %as,%at,%LABEL;j %label;LABEL"},
438 {"WIDE.blt %as,%at,%label", "bge %as,%at,%LABEL;j %label;LABEL"},
439 {"WIDE.bgeu %as,%at,%label", "bltu %as,%at,%LABEL;j %label;LABEL"},
440 {"WIDE.bltu %as,%at,%label", "bgeu %as,%at,%LABEL;j %label;LABEL"},
441 {"WIDE.bany %as,%at,%label", "bnone %as,%at,%LABEL;j %label;LABEL"},
442 {"WIDE.bnone %as,%at,%label", "bany %as,%at,%LABEL;j %label;LABEL"},
443 {"WIDE.ball %as,%at,%label", "bnall %as,%at,%LABEL;j %label;LABEL"},
444 {"WIDE.bnall %as,%at,%label", "ball %as,%at,%LABEL;j %label;LABEL"},
445 {"WIDE.bbc %as,%at,%label", "bbs %as,%at,%LABEL;j %label;LABEL"},
446 {"WIDE.bbs %as,%at,%label", "bbc %as,%at,%LABEL;j %label;LABEL"},
447
43cd72b9
BW
448 /* Expanding calls with literals. */
449 {"call0 %label,%ar0 ? IsaUseL32R",
61376837 450 "LITERAL %label; l32r a0,%LITERAL; callx0 a0,%ar0"},
43cd72b9 451 {"call4 %label,%ar4 ? IsaUseL32R",
61376837 452 "LITERAL %label; l32r a4,%LITERAL; callx4 a4,%ar4"},
43cd72b9 453 {"call8 %label,%ar8 ? IsaUseL32R",
61376837 454 "LITERAL %label; l32r a8,%LITERAL; callx8 a8,%ar8"},
43cd72b9 455 {"call12 %label,%ar12 ? IsaUseL32R",
61376837 456 "LITERAL %label; l32r a12,%LITERAL; callx12 a12,%ar12"},
43cd72b9
BW
457
458 /* Expanding calls with const16. */
459 {"call0 %label,%ar0 ? IsaUseConst16",
460 "const16 a0,HI16U(%label); const16 a0,LOW16U(%label); callx0 a0,%ar0"},
461 {"call4 %label,%ar4 ? IsaUseConst16",
462 "const16 a4,HI16U(%label); const16 a4,LOW16U(%label); callx4 a4,%ar4"},
463 {"call8 %label,%ar8 ? IsaUseConst16",
464 "const16 a8,HI16U(%label); const16 a8,LOW16U(%label); callx8 a8,%ar8"},
465 {"call12 %label,%ar12 ? IsaUseConst16",
19e8f41a
BW
466 "const16 a12,HI16U(%label); const16 a12,LOW16U(%label); callx12 a12,%ar12"},
467
468 /* Expanding j.l with literals. */
469 {"j %label ? FREEREG ? IsaUseL32R",
470 "LITERAL %label; l32r FREEREG,%LITERAL; jx FREEREG"},
471 /* Expanding j.l with const16. */
472 {"j %label ? FREEREG ? IsaUseConst16",
473 "const16 FREEREG,HI16U(%label); const16 FREEREG,LOW16U(%label); jx FREEREG"},
e0001a05
NC
474};
475
476#define WIDEN_COUNT (sizeof (widen_spec_list) / sizeof (string_pattern_pair))
477
478
479/* The simplify_spec_list specifies simplifying transformations that
480 will reduce the instruction width or otherwise simplify an
481 instruction. These are usually applied before relaxation in the
482 assembler. It is always legal to simplify. Even for "addi as, 0",
483 the "addi.n as, 0" will eventually be widened back to an "addi 0"
484 after the widening table is applied. Note: The usage of this table
485 has changed somewhat so that it is entirely specific to "narrowing"
486 instructions to use the density option. This table is not used at
487 all when the density option is not available. */
488
489string_pattern_pair simplify_spec_list[] =
490{
43cd72b9
BW
491 {"add %ar,%as,%at ? IsaUseDensityInstruction", "add.n %ar,%as,%at"},
492 {"addi.n %ar,%as,0 ? IsaUseDensityInstruction", "mov.n %ar,%as"},
493 {"addi %ar,%as,0 ? IsaUseDensityInstruction", "mov.n %ar,%as"},
494 {"addi %ar,%as,%imm ? IsaUseDensityInstruction", "addi.n %ar,%as,%imm"},
495 {"addmi %ar,%as,%imm ? IsaUseDensityInstruction", "addi.n %ar,%as,%imm"},
496 {"beqz %as,%label ? IsaUseDensityInstruction", "beqz.n %as,%label"},
497 {"bnez %as,%label ? IsaUseDensityInstruction", "bnez.n %as,%label"},
498 {"l32i %at,%as,%imm ? IsaUseDensityInstruction", "l32i.n %at,%as,%imm"},
499 {"movi %as,%imm ? IsaUseDensityInstruction", "movi.n %as,%imm"},
500 {"nop ? realnop ? IsaUseDensityInstruction", "nop.n"},
501 {"or %ar,%as,%at | %ar==%as | %as==%at ? IsaUseDensityInstruction", "nop.n"},
502 {"or %ar,%as,%at | %ar!=%as | %as==%at ? IsaUseDensityInstruction", "mov.n %ar,%as"},
503 {"ret %as ? IsaUseDensityInstruction", "ret.n %as"},
504 {"retw %as ? IsaUseDensityInstruction", "retw.n %as"},
505 {"s32i %at,%as,%imm ? IsaUseDensityInstruction", "s32i.n %at,%as,%imm"},
506 {"slli %ar,%as,0 ? IsaUseDensityInstruction", "mov.n %ar,%as"}
e0001a05
NC
507};
508
509#define SIMPLIFY_COUNT \
510 (sizeof (simplify_spec_list) / sizeof (string_pattern_pair))
511
512\f
e0001a05
NC
513/* Externally visible functions. */
514
7fa3d080
BW
515extern bfd_boolean xg_has_userdef_op_fn (OpType);
516extern long xg_apply_userdef_op_fn (OpType, long);
e0001a05 517
7fa3d080
BW
518
519static void
520append_transition (TransitionTable *tt,
521 xtensa_opcode opcode,
522 TransitionRule *t,
523 transition_cmp_fn cmp)
e0001a05
NC
524{
525 TransitionList *tl = (TransitionList *) xmalloc (sizeof (TransitionList));
526 TransitionList *prev;
43cd72b9 527 TransitionList **t_p;
9c2799c2
NC
528 gas_assert (tt != NULL);
529 gas_assert (opcode < tt->num_opcodes);
e0001a05
NC
530
531 prev = tt->table[opcode];
532 tl->rule = t;
533 tl->next = NULL;
534 if (prev == NULL)
535 {
536 tt->table[opcode] = tl;
537 return;
538 }
43cd72b9
BW
539
540 for (t_p = &tt->table[opcode]; (*t_p) != NULL; t_p = &(*t_p)->next)
e0001a05 541 {
43cd72b9
BW
542 if (cmp && cmp (t, (*t_p)->rule) < 0)
543 {
544 /* Insert it here. */
545 tl->next = *t_p;
546 *t_p = tl;
547 return;
548 }
e0001a05 549 }
43cd72b9 550 (*t_p) = tl;
e0001a05
NC
551}
552
553
7fa3d080
BW
554static void
555append_condition (TransitionRule *tr, Precondition *cond)
e0001a05
NC
556{
557 PreconditionList *pl =
558 (PreconditionList *) xmalloc (sizeof (PreconditionList));
559 PreconditionList *prev = tr->conditions;
560 PreconditionList *nxt;
561
562 pl->precond = cond;
563 pl->next = NULL;
564 if (prev == NULL)
565 {
566 tr->conditions = pl;
567 return;
568 }
569 nxt = prev->next;
570 while (nxt != NULL)
571 {
572 prev = nxt;
573 nxt = nxt->next;
574 }
575 prev->next = pl;
576}
577
578
7fa3d080
BW
579static void
580append_value_condition (TransitionRule *tr,
581 CmpOp cmp,
582 unsigned op1,
583 unsigned op2)
e0001a05
NC
584{
585 Precondition *cond = (Precondition *) xmalloc (sizeof (Precondition));
586
587 cond->cmp = cmp;
588 cond->op_num = op1;
589 cond->typ = OP_OPERAND;
590 cond->op_data = op2;
591 append_condition (tr, cond);
592}
593
594
7fa3d080
BW
595static void
596append_constant_value_condition (TransitionRule *tr,
597 CmpOp cmp,
598 unsigned op1,
599 unsigned cnst)
e0001a05
NC
600{
601 Precondition *cond = (Precondition *) xmalloc (sizeof (Precondition));
602
603 cond->cmp = cmp;
604 cond->op_num = op1;
605 cond->typ = OP_CONSTANT;
606 cond->op_data = cnst;
607 append_condition (tr, cond);
608}
609
610
7fa3d080
BW
611static void
612append_build_insn (TransitionRule *tr, BuildInstr *bi)
e0001a05
NC
613{
614 BuildInstr *prev = tr->to_instr;
615 BuildInstr *nxt;
616
617 bi->next = NULL;
618 if (prev == NULL)
619 {
620 tr->to_instr = bi;
621 return;
622 }
623 nxt = prev->next;
624 while (nxt != 0)
625 {
626 prev = nxt;
627 nxt = prev->next;
628 }
629 prev->next = bi;
630}
631
632
7fa3d080
BW
633static void
634append_op (BuildInstr *bi, BuildOp *b_op)
e0001a05
NC
635{
636 BuildOp *prev = bi->ops;
637 BuildOp *nxt;
638
639 if (prev == NULL)
640 {
641 bi->ops = b_op;
642 return;
643 }
644 nxt = prev->next;
645 while (nxt != NULL)
646 {
647 prev = nxt;
648 nxt = nxt->next;
649 }
650 prev->next = b_op;
651}
652
653
7fa3d080 654static void
28dbbc02 655append_literal_op (BuildInstr *bi, unsigned op1, unsigned src_op)
e0001a05
NC
656{
657 BuildOp *b_op = (BuildOp *) xmalloc (sizeof (BuildOp));
658
659 b_op->op_num = op1;
660 b_op->typ = OP_LITERAL;
28dbbc02 661 b_op->op_data = src_op;
e0001a05
NC
662 b_op->next = NULL;
663 append_op (bi, b_op);
664}
665
666
7fa3d080 667static void
61376837 668append_label_op (BuildInstr *bi, unsigned op1)
e0001a05
NC
669{
670 BuildOp *b_op = (BuildOp *) xmalloc (sizeof (BuildOp));
671
672 b_op->op_num = op1;
673 b_op->typ = OP_LABEL;
61376837 674 b_op->op_data = 0;
e0001a05
NC
675 b_op->next = NULL;
676 append_op (bi, b_op);
677}
678
679
7fa3d080
BW
680static void
681append_constant_op (BuildInstr *bi, unsigned op1, unsigned cnst)
e0001a05
NC
682{
683 BuildOp *b_op = (BuildOp *) xmalloc (sizeof (BuildOp));
684
685 b_op->op_num = op1;
686 b_op->typ = OP_CONSTANT;
687 b_op->op_data = cnst;
688 b_op->next = NULL;
689 append_op (bi, b_op);
690}
691
692
7fa3d080
BW
693static void
694append_field_op (BuildInstr *bi, unsigned op1, unsigned src_op)
e0001a05
NC
695{
696 BuildOp *b_op = (BuildOp *) xmalloc (sizeof (BuildOp));
697
698 b_op->op_num = op1;
699 b_op->typ = OP_OPERAND;
700 b_op->op_data = src_op;
701 b_op->next = NULL;
702 append_op (bi, b_op);
703}
704
705
706/* These could be generated but are not currently. */
707
7fa3d080
BW
708static void
709append_user_fn_field_op (BuildInstr *bi,
710 unsigned op1,
711 OpType typ,
712 unsigned src_op)
e0001a05
NC
713{
714 BuildOp *b_op = (BuildOp *) xmalloc (sizeof (BuildOp));
715
716 b_op->op_num = op1;
717 b_op->typ = typ;
718 b_op->op_data = src_op;
719 b_op->next = NULL;
720 append_op (bi, b_op);
721}
722
723
724/* These operand functions are the semantics of user-defined
725 operand functions. */
726
7fa3d080
BW
727static long
728operand_function_HI24S (long a)
e0001a05
NC
729{
730 if (a & 0x80)
731 return (a & (~0xff)) + 0x100;
732 else
733 return (a & (~0xff));
734}
735
736
7fa3d080
BW
737static long
738operand_function_F32MINUS (long a)
e0001a05
NC
739{
740 return (32 - a);
741}
742
743
7fa3d080
BW
744static long
745operand_function_LOW8 (long a)
e0001a05
NC
746{
747 if (a & 0x80)
748 return (a & 0xff) | ~0xff;
749 else
750 return (a & 0xff);
751}
752
753
7fa3d080
BW
754static long
755operand_function_LOW16U (long a)
43cd72b9
BW
756{
757 return (a & 0xffff);
758}
759
760
7fa3d080
BW
761static long
762operand_function_HI16U (long a)
43cd72b9
BW
763{
764 unsigned long b = a & 0xffff0000;
765 return (long) (b >> 16);
766}
767
768
e0001a05 769bfd_boolean
7fa3d080 770xg_has_userdef_op_fn (OpType op)
e0001a05
NC
771{
772 switch (op)
773 {
774 case OP_OPERAND_F32MINUS:
775 case OP_OPERAND_LOW8:
776 case OP_OPERAND_HI24S:
43cd72b9
BW
777 case OP_OPERAND_LOW16U:
778 case OP_OPERAND_HI16U:
e0001a05
NC
779 return TRUE;
780 default:
781 break;
782 }
783 return FALSE;
784}
785
786
787long
7fa3d080 788xg_apply_userdef_op_fn (OpType op, long a)
e0001a05
NC
789{
790 switch (op)
791 {
792 case OP_OPERAND_F32MINUS:
793 return operand_function_F32MINUS (a);
794 case OP_OPERAND_LOW8:
795 return operand_function_LOW8 (a);
796 case OP_OPERAND_HI24S:
797 return operand_function_HI24S (a);
43cd72b9
BW
798 case OP_OPERAND_LOW16U:
799 return operand_function_LOW16U (a);
800 case OP_OPERAND_HI16U:
801 return operand_function_HI16U (a);
e0001a05
NC
802 default:
803 break;
804 }
805 return FALSE;
806}
807
808
809/* Generate a transition table. */
810
7fa3d080
BW
811static const char *
812enter_opname_n (const char *name, int len)
e0001a05
NC
813{
814 opname_e *op;
815
816 for (op = local_opnames; op != NULL; op = op->next)
817 {
43cd72b9
BW
818 if (strlen (op->opname) == (unsigned) len
819 && strncmp (op->opname, name, len) == 0)
e0001a05
NC
820 return op->opname;
821 }
822 op = (opname_e *) xmalloc (sizeof (opname_e));
823 op->opname = (char *) xmalloc (len + 1);
824 strncpy (op->opname, name, len);
825 op->opname[len] = '\0';
826 return op->opname;
827}
828
829
830static const char *
7fa3d080 831enter_opname (const char *name)
e0001a05
NC
832{
833 opname_e *op;
834
835 for (op = local_opnames; op != NULL; op = op->next)
836 {
837 if (strcmp (op->opname, name) == 0)
838 return op->opname;
839 }
840 op = (opname_e *) xmalloc (sizeof (opname_e));
43cd72b9 841 op->opname = xstrdup (name);
e0001a05
NC
842 return op->opname;
843}
844
845
7fa3d080
BW
846static void
847init_opname_map (opname_map *m)
e0001a05
NC
848{
849 m->head = NULL;
850 m->tail = &m->head;
851}
852
853
7fa3d080
BW
854static void
855clear_opname_map (opname_map *m)
e0001a05
NC
856{
857 opname_map_e *e;
858
859 while (m->head != NULL)
860 {
861 e = m->head;
862 m->head = e->next;
863 free (e);
864 }
865 m->tail = &m->head;
866}
867
868
869static bfd_boolean
7fa3d080 870same_operand_name (const opname_map_e *m1, const opname_map_e *m2)
e0001a05
NC
871{
872 if (m1->operand_name == NULL || m1->operand_name == NULL)
873 return FALSE;
874 return (m1->operand_name == m2->operand_name);
875}
876
877
7fa3d080
BW
878static opname_map_e *
879get_opmatch (opname_map *map, const char *operand_name)
e0001a05
NC
880{
881 opname_map_e *m;
882
883 for (m = map->head; m != NULL; m = m->next)
884 {
885 if (strcmp (m->operand_name, operand_name) == 0)
886 return m;
887 }
888 return NULL;
889}
890
891
7fa3d080
BW
892static bfd_boolean
893op_is_constant (const opname_map_e *m1)
e0001a05
NC
894{
895 return (m1->operand_name == NULL);
896}
897
898
899static unsigned
7fa3d080 900op_get_constant (const opname_map_e *m1)
e0001a05 901{
9c2799c2 902 gas_assert (m1->operand_name == NULL);
e0001a05
NC
903 return m1->constant_value;
904}
905
906
7fa3d080
BW
907static void
908init_precond_list (precond_list *l)
e0001a05
NC
909{
910 l->head = NULL;
911 l->tail = &l->head;
912}
913
914
7fa3d080
BW
915static void
916clear_precond_list (precond_list *l)
e0001a05
NC
917{
918 precond_e *e;
919
920 while (l->head != NULL)
921 {
922 e = l->head;
923 l->head = e->next;
924 free (e);
925 }
926 l->tail = &l->head;
927}
928
929
7fa3d080
BW
930static void
931init_insn_templ (insn_templ *t)
e0001a05
NC
932{
933 t->opcode_name = NULL;
934 init_opname_map (&t->operand_map);
935}
936
937
7fa3d080
BW
938static void
939clear_insn_templ (insn_templ *t)
e0001a05
NC
940{
941 clear_opname_map (&t->operand_map);
942}
943
944
7fa3d080
BW
945static void
946init_insn_pattern (insn_pattern *p)
e0001a05
NC
947{
948 init_insn_templ (&p->t);
949 init_precond_list (&p->preconds);
43cd72b9 950 p->options = NULL;
e0001a05
NC
951}
952
953
7fa3d080
BW
954static void
955clear_insn_pattern (insn_pattern *p)
e0001a05
NC
956{
957 clear_insn_templ (&p->t);
958 clear_precond_list (&p->preconds);
959}
960
961
7fa3d080
BW
962static void
963init_insn_repl (insn_repl *r)
e0001a05
NC
964{
965 r->head = NULL;
966 r->tail = &r->head;
967}
968
969
7fa3d080
BW
970static void
971clear_insn_repl (insn_repl *r)
e0001a05
NC
972{
973 insn_repl_e *e;
974
975 while (r->head != NULL)
976 {
977 e = r->head;
978 r->head = e->next;
979 clear_insn_templ (&e->t);
980 }
981 r->tail = &r->head;
982}
983
984
43cd72b9 985static int
7fa3d080 986insn_templ_operand_count (const insn_templ *t)
e0001a05 987{
43cd72b9 988 int i = 0;
e0001a05
NC
989 const opname_map_e *op;
990
43cd72b9 991 for (op = t->operand_map.head; op != NULL; op = op->next, i++)
e0001a05
NC
992 ;
993 return i;
994}
995
996
997/* Convert a string to a number. E.G.: parse_constant("10", &num) */
998
7fa3d080
BW
999static bfd_boolean
1000parse_constant (const char *in, unsigned *val_p)
e0001a05
NC
1001{
1002 unsigned val = 0;
1003 const char *p;
1004
1005 if (in == NULL)
1006 return FALSE;
1007 p = in;
1008
1009 while (*p != '\0')
1010 {
1011 if (*p >= '0' && *p <= '9')
1012 val = val * 10 + (*p - '0');
1013 else
1014 return FALSE;
1015 ++p;
1016 }
1017 *val_p = val;
1018 return TRUE;
1019}
1020
1021
e0001a05 1022static bfd_boolean
7fa3d080
BW
1023parse_special_fn (const char *name,
1024 const char **fn_name_p,
1025 const char **arg_name_p)
e0001a05
NC
1026{
1027 char *p_start;
1028 const char *p_end;
1029
1030 p_start = strchr (name, '(');
1031 if (p_start == NULL)
1032 return FALSE;
1033
1034 p_end = strchr (p_start, ')');
1035
1036 if (p_end == NULL)
1037 return FALSE;
1038
1039 if (p_end[1] != '\0')
1040 return FALSE;
1041
1042 *fn_name_p = enter_opname_n (name, p_start - name);
1043 *arg_name_p = enter_opname_n (p_start + 1, p_end - p_start - 1);
1044 return TRUE;
1045}
1046
1047
7fa3d080
BW
1048static const char *
1049skip_white (const char *p)
e0001a05
NC
1050{
1051 if (p == NULL)
1052 return p;
1053 while (*p == ' ')
1054 ++p;
1055 return p;
1056}
1057
1058
7fa3d080
BW
1059static void
1060trim_whitespace (char *in)
e0001a05
NC
1061{
1062 char *last_white = NULL;
1063 char *p = in;
1064
1065 while (p && *p != '\0')
1066 {
1067 while (*p == ' ')
1068 {
1069 if (last_white == NULL)
1070 last_white = p;
1071 p++;
1072 }
1073 if (*p != '\0')
1074 {
1075 last_white = NULL;
1076 p++;
1077 }
1078 }
1079 if (last_white)
1080 *last_white = '\0';
1081}
1082
1083
1084/* Split a string into component strings where "c" is the
1085 delimiter. Place the result in the split_rec. */
1086
7fa3d080
BW
1087static void
1088split_string (split_rec *rec,
1089 const char *in,
1090 char c,
1091 bfd_boolean elide_whitespace)
e0001a05 1092{
43cd72b9
BW
1093 int cnt = 0;
1094 int i;
e0001a05
NC
1095 const char *p = in;
1096
1097 while (p != NULL && *p != '\0')
1098 {
1099 cnt++;
1100 p = strchr (p, c);
1101 if (p)
1102 p++;
1103 }
1104 rec->count = cnt;
1105 rec->vec = NULL;
1106
1107 if (rec->count == 0)
1108 return;
1109
1110 rec->vec = (char **) xmalloc (sizeof (char *) * cnt);
1111 for (i = 0; i < cnt; i++)
1112 rec->vec[i] = 0;
1113
1114 p = in;
1115 for (i = 0; i < cnt; i++)
1116 {
1117 const char *q;
43cd72b9 1118 int len;
e0001a05
NC
1119
1120 q = p;
1121 if (elide_whitespace)
1122 q = skip_white (q);
1123
1124 p = strchr (q, c);
1125 if (p == NULL)
43cd72b9 1126 rec->vec[i] = xstrdup (q);
e0001a05
NC
1127 else
1128 {
1129 len = p - q;
1130 rec->vec[i] = (char *) xmalloc (sizeof (char) * (len + 1));
1131 strncpy (rec->vec[i], q, len);
1132 rec->vec[i][len] = '\0';
1133 p++;
1134 }
1135
1136 if (elide_whitespace)
1137 trim_whitespace (rec->vec[i]);
1138 }
1139}
1140
1141
7fa3d080
BW
1142static void
1143clear_split_rec (split_rec *rec)
e0001a05 1144{
43cd72b9 1145 int i;
e0001a05 1146
43cd72b9 1147 for (i = 0; i < rec->count; i++)
e0001a05
NC
1148 free (rec->vec[i]);
1149
1150 if (rec->count > 0)
1151 free (rec->vec);
1152}
1153
1154
43cd72b9
BW
1155/* Initialize a split record. The split record must be initialized
1156 before split_string is called. */
1157
7fa3d080
BW
1158static void
1159init_split_rec (split_rec *rec)
e0001a05
NC
1160{
1161 rec->vec = NULL;
1162 rec->count = 0;
1163}
1164
1165
1166/* Parse an instruction template like "insn op1, op2, op3". */
1167
7fa3d080
BW
1168static bfd_boolean
1169parse_insn_templ (const char *s, insn_templ *t)
e0001a05
NC
1170{
1171 const char *p = s;
43cd72b9 1172 int insn_name_len;
e0001a05 1173 split_rec oprec;
43cd72b9
BW
1174 int i;
1175
1176 /* First find the first whitespace. */
e0001a05
NC
1177
1178 init_split_rec (&oprec);
1179
1180 p = skip_white (p);
1181 insn_name_len = strcspn (s, " ");
1182 if (insn_name_len == 0)
1183 return FALSE;
1184
1185 init_insn_templ (t);
1186 t->opcode_name = enter_opname_n (p, insn_name_len);
1187
1188 p = p + insn_name_len;
1189
1190 /* Split by ',' and skip beginning and trailing whitespace. */
1191 split_string (&oprec, p, ',', TRUE);
1192
1193 for (i = 0; i < oprec.count; i++)
1194 {
1195 const char *opname = oprec.vec[i];
1196 opname_map_e *e = (opname_map_e *) xmalloc (sizeof (opname_map_e));
1197 e->next = NULL;
1198 e->operand_name = NULL;
1199 e->constant_value = 0;
1200 e->operand_num = i;
1201
1202 /* If it begins with a number, assume that it is a number. */
1203 if (opname && opname[0] >= '0' && opname[0] <= '9')
1204 {
1205 unsigned val;
1206
1207 if (parse_constant (opname, &val))
1208 e->constant_value = val;
1209 else
1210 {
1211 free (e);
1212 clear_split_rec (&oprec);
1213 clear_insn_templ (t);
1214 return FALSE;
1215 }
1216 }
1217 else
1218 e->operand_name = enter_opname (oprec.vec[i]);
1219
1220 *t->operand_map.tail = e;
1221 t->operand_map.tail = &e->next;
1222 }
1223 clear_split_rec (&oprec);
1224 return TRUE;
1225}
1226
1227
7fa3d080
BW
1228static bfd_boolean
1229parse_precond (const char *s, precond_e *precond)
e0001a05
NC
1230{
1231 /* All preconditions are currently of the form:
1232 a == b or a != b or a == k (where k is a constant).
1233 Later we may use some special functions like DENSITY == 1
1234 to identify when density is available. */
1235
1236 const char *p = s;
43cd72b9 1237 int len;
e0001a05
NC
1238 precond->opname1 = NULL;
1239 precond->opval1 = 0;
1240 precond->cmpop = OP_EQUAL;
1241 precond->opname2 = NULL;
1242 precond->opval2 = 0;
1243 precond->next = NULL;
1244
1245 p = skip_white (p);
1246
1247 len = strcspn (p, " !=");
1248
1249 if (len == 0)
1250 return FALSE;
1251
1252 precond->opname1 = enter_opname_n (p, len);
1253 p = p + len;
1254 p = skip_white (p);
1255
1256 /* Check for "==" and "!=". */
1257 if (strncmp (p, "==", 2) == 0)
1258 precond->cmpop = OP_EQUAL;
1259 else if (strncmp (p, "!=", 2) == 0)
1260 precond->cmpop = OP_NOTEQUAL;
1261 else
1262 return FALSE;
1263
1264 p = p + 2;
1265 p = skip_white (p);
1266
1267 /* No trailing whitespace from earlier parsing. */
1268 if (p[0] >= '0' && p[0] <= '9')
1269 {
1270 unsigned val;
1271 if (parse_constant (p, &val))
1272 precond->opval2 = val;
1273 else
1274 return FALSE;
1275 }
1276 else
1277 precond->opname2 = enter_opname (p);
1278 return TRUE;
1279}
1280
1281
7fa3d080
BW
1282static void
1283clear_req_or_option_list (ReqOrOption **r_p)
43cd72b9
BW
1284{
1285 if (*r_p == NULL)
1286 return;
1287
1288 free ((*r_p)->option_name);
1289 clear_req_or_option_list (&(*r_p)->next);
1290 *r_p = NULL;
1291}
1292
1293
7fa3d080
BW
1294static void
1295clear_req_option_list (ReqOption **r_p)
43cd72b9
BW
1296{
1297 if (*r_p == NULL)
1298 return;
1299
1300 clear_req_or_option_list (&(*r_p)->or_option_terms);
1301 clear_req_option_list (&(*r_p)->next);
1302 *r_p = NULL;
1303}
1304
1305
7fa3d080
BW
1306static ReqOrOption *
1307clone_req_or_option_list (ReqOrOption *req_or_option)
43cd72b9
BW
1308{
1309 ReqOrOption *new_req_or_option;
1310
1311 if (req_or_option == NULL)
1312 return NULL;
1313
1314 new_req_or_option = (ReqOrOption *) xmalloc (sizeof (ReqOrOption));
1315 new_req_or_option->option_name = xstrdup (req_or_option->option_name);
1316 new_req_or_option->is_true = req_or_option->is_true;
1317 new_req_or_option->next = NULL;
1318 new_req_or_option->next = clone_req_or_option_list (req_or_option->next);
1319 return new_req_or_option;
1320}
1321
1322
7fa3d080
BW
1323static ReqOption *
1324clone_req_option_list (ReqOption *req_option)
43cd72b9
BW
1325{
1326 ReqOption *new_req_option;
1327
1328 if (req_option == NULL)
1329 return NULL;
1330
1331 new_req_option = (ReqOption *) xmalloc (sizeof (ReqOption));
1332 new_req_option->or_option_terms = NULL;
1333 new_req_option->next = NULL;
c138bc38 1334 new_req_option->or_option_terms =
43cd72b9
BW
1335 clone_req_or_option_list (req_option->or_option_terms);
1336 new_req_option->next = clone_req_option_list (req_option->next);
1337 return new_req_option;
1338}
1339
1340
7fa3d080
BW
1341static bfd_boolean
1342parse_option_cond (const char *s, ReqOption *option)
43cd72b9
BW
1343{
1344 int i;
1345 split_rec option_term_rec;
1346
1347 /* All option or conditions are of the form:
1348 optionA + no-optionB + ...
1349 "Ands" are divided by "?". */
1350
1351 init_split_rec (&option_term_rec);
1352 split_string (&option_term_rec, s, '+', TRUE);
1353
1354 if (option_term_rec.count == 0)
1355 {
1356 clear_split_rec (&option_term_rec);
1357 return FALSE;
1358 }
1359
1360 for (i = 0; i < option_term_rec.count; i++)
1361 {
1362 char *option_name = option_term_rec.vec[i];
1363 bfd_boolean is_true = TRUE;
1364 ReqOrOption *req;
1365 ReqOrOption **r_p;
1366
1367 if (strncmp (option_name, "no-", 3) == 0)
1368 {
1369 option_name = xstrdup (&option_name[3]);
1370 is_true = FALSE;
1371 }
1372 else
1373 option_name = xstrdup (option_name);
1374
1375 req = (ReqOrOption *) xmalloc (sizeof (ReqOrOption));
1376 req->option_name = option_name;
1377 req->is_true = is_true;
1378 req->next = NULL;
1379
1380 /* Append to list. */
c138bc38 1381 for (r_p = &option->or_option_terms; (*r_p) != NULL;
43cd72b9
BW
1382 r_p = &(*r_p)->next)
1383 ;
1384 (*r_p) = req;
1385 }
1386 return TRUE;
1387}
1388
1389
e0001a05
NC
1390/* Parse a string like:
1391 "insn op1, op2, op3, op4 | op1 != op2 | op2 == op3 | op4 == 1".
1392 I.E., instruction "insn" with 4 operands where operand 1 and 2 are not
43cd72b9
BW
1393 the same and operand 2 and 3 are the same and operand 4 is 1.
1394
1395 or:
1396
1397 "insn op1 | op1 == 1 / density + boolean / no-useroption".
1398 i.e. instruction "insn" with 1 operands where operand 1 is 1
1399 when "density" or "boolean" options are available and
1400 "useroption" is not available.
1401
1402 Because the current implementation of this parsing scheme uses
1403 split_string, it requires that '|' and '?' are only used as
1404 delimiters for predicates and required options. */
e0001a05 1405
7fa3d080
BW
1406static bfd_boolean
1407parse_insn_pattern (const char *in, insn_pattern *insn)
e0001a05 1408{
e0001a05 1409 split_rec rec;
43cd72b9
BW
1410 split_rec optionrec;
1411 int i;
e0001a05 1412
e0001a05
NC
1413 init_insn_pattern (insn);
1414
43cd72b9
BW
1415 init_split_rec (&optionrec);
1416 split_string (&optionrec, in, '?', TRUE);
1417 if (optionrec.count == 0)
1418 {
1419 clear_split_rec (&optionrec);
1420 return FALSE;
1421 }
c138bc38 1422
43cd72b9
BW
1423 init_split_rec (&rec);
1424
1425 split_string (&rec, optionrec.vec[0], '|', TRUE);
e0001a05
NC
1426
1427 if (rec.count == 0)
1428 {
1429 clear_split_rec (&rec);
43cd72b9 1430 clear_split_rec (&optionrec);
e0001a05
NC
1431 return FALSE;
1432 }
1433
1434 if (!parse_insn_templ (rec.vec[0], &insn->t))
1435 {
1436 clear_split_rec (&rec);
43cd72b9 1437 clear_split_rec (&optionrec);
e0001a05
NC
1438 return FALSE;
1439 }
1440
1441 for (i = 1; i < rec.count; i++)
1442 {
1443 precond_e *cond = (precond_e *) xmalloc (sizeof (precond_e));
1444
1445 if (!parse_precond (rec.vec[i], cond))
1446 {
1447 clear_split_rec (&rec);
43cd72b9 1448 clear_split_rec (&optionrec);
e0001a05
NC
1449 clear_insn_pattern (insn);
1450 return FALSE;
1451 }
1452
1453 /* Append the condition. */
1454 *insn->preconds.tail = cond;
1455 insn->preconds.tail = &cond->next;
1456 }
1457
43cd72b9
BW
1458 for (i = 1; i < optionrec.count; i++)
1459 {
1460 /* Handle the option conditions. */
1461 ReqOption **r_p;
1462 ReqOption *req_option = (ReqOption *) xmalloc (sizeof (ReqOption));
1463 req_option->or_option_terms = NULL;
1464 req_option->next = NULL;
c138bc38 1465
43cd72b9
BW
1466 if (!parse_option_cond (optionrec.vec[i], req_option))
1467 {
1468 clear_split_rec (&rec);
1469 clear_split_rec (&optionrec);
1470 clear_insn_pattern (insn);
1471 clear_req_option_list (&req_option);
1472 return FALSE;
1473 }
1474
1475 /* Append the condition. */
1476 for (r_p = &insn->options; (*r_p) != NULL; r_p = &(*r_p)->next)
1477 ;
1478
1479 (*r_p) = req_option;
1480 }
1481
e0001a05 1482 clear_split_rec (&rec);
43cd72b9 1483 clear_split_rec (&optionrec);
e0001a05
NC
1484 return TRUE;
1485}
1486
1487
7fa3d080
BW
1488static bfd_boolean
1489parse_insn_repl (const char *in, insn_repl *r_p)
e0001a05
NC
1490{
1491 /* This is a list of instruction templates separated by ';'. */
1492 split_rec rec;
43cd72b9 1493 int i;
e0001a05
NC
1494
1495 split_string (&rec, in, ';', TRUE);
1496
1497 for (i = 0; i < rec.count; i++)
1498 {
1499 insn_repl_e *e = (insn_repl_e *) xmalloc (sizeof (insn_repl_e));
1500
1501 e->next = NULL;
1502
1503 if (!parse_insn_templ (rec.vec[i], &e->t))
1504 {
1505 free (e);
1506 clear_insn_repl (r_p);
1507 return FALSE;
1508 }
1509 *r_p->tail = e;
1510 r_p->tail = &e->next;
1511 }
1512 return TRUE;
1513}
1514
1515
7fa3d080
BW
1516static bfd_boolean
1517transition_applies (insn_pattern *initial_insn,
1518 const char *from_string ATTRIBUTE_UNUSED,
1519 const char *to_string ATTRIBUTE_UNUSED)
43cd72b9
BW
1520{
1521 ReqOption *req_option;
1522
1523 for (req_option = initial_insn->options;
1524 req_option != NULL;
1525 req_option = req_option->next)
1526 {
1527 ReqOrOption *req_or_option = req_option->or_option_terms;
1528
1529 if (req_or_option == NULL
1530 || req_or_option->next != NULL)
1531 continue;
1532
c138bc38 1533 if (strncmp (req_or_option->option_name, "IsaUse", 6) == 0)
43cd72b9
BW
1534 {
1535 bfd_boolean option_available = FALSE;
1536 char *option_name = req_or_option->option_name + 6;
1537 if (!strcmp (option_name, "DensityInstruction"))
1538 option_available = (XCHAL_HAVE_DENSITY == 1);
1539 else if (!strcmp (option_name, "L32R"))
1540 option_available = (XCHAL_HAVE_L32R == 1);
1541 else if (!strcmp (option_name, "Const16"))
1542 option_available = (XCHAL_HAVE_CONST16 == 1);
1543 else if (!strcmp (option_name, "Loops"))
1544 option_available = (XCHAL_HAVE_LOOPS == 1);
b2d179be 1545 else if (!strcmp (option_name, "WideBranches"))
19fc3723
SA
1546 option_available
1547 = (XCHAL_HAVE_WIDE_BRANCHES == 1 && produce_flix == FLIX_ALL);
43cd72b9 1548 else if (!strcmp (option_name, "PredictedBranches"))
19fc3723
SA
1549 option_available
1550 = (XCHAL_HAVE_PREDICTED_BRANCHES == 1
1551 && produce_flix == FLIX_ALL);
43cd72b9
BW
1552 else if (!strcmp (option_name, "Booleans"))
1553 option_available = (XCHAL_HAVE_BOOLEANS == 1);
1554 else
1555 as_warn (_("invalid configuration option '%s' in transition rule '%s'"),
1556 req_or_option->option_name, from_string);
1557 if ((option_available ^ req_or_option->is_true) != 0)
1558 return FALSE;
1559 }
1560 else if (strcmp (req_or_option->option_name, "realnop") == 0)
1561 {
c138bc38 1562 bfd_boolean nop_available =
43cd72b9
BW
1563 (xtensa_opcode_lookup (xtensa_default_isa, "nop")
1564 != XTENSA_UNDEFINED);
1565 if ((nop_available ^ req_or_option->is_true) != 0)
1566 return FALSE;
1567 }
1568 }
1569 return TRUE;
1570}
1571
1572
1946c96e
BW
1573static bfd_boolean
1574wide_branch_opcode (const char *opcode_name,
1575 char *suffix,
1576 xtensa_opcode *popcode)
1577{
1578 xtensa_isa isa = xtensa_default_isa;
1579 xtensa_opcode opcode;
1580 static char wbr_name_buf[20];
1581
1582 if (strncmp (opcode_name, "WIDE.", 5) != 0)
1583 return FALSE;
1584
1585 strcpy (wbr_name_buf, opcode_name + 5);
1586 strcat (wbr_name_buf, suffix);
1587 opcode = xtensa_opcode_lookup (isa, wbr_name_buf);
1588 if (opcode != XTENSA_UNDEFINED)
1589 {
1590 *popcode = opcode;
1591 return TRUE;
1592 }
1593
1594 return FALSE;
1595}
1596
1597
7fa3d080
BW
1598static TransitionRule *
1599build_transition (insn_pattern *initial_insn,
1600 insn_repl *replace_insns,
1601 const char *from_string,
1602 const char *to_string)
e0001a05
NC
1603{
1604 TransitionRule *tr = NULL;
1605 xtensa_opcode opcode;
1606 xtensa_isa isa = xtensa_default_isa;
28dbbc02 1607 BuildInstr *literal_bi;
e0001a05
NC
1608
1609 opname_map_e *op1;
1610 opname_map_e *op2;
1611
1612 precond_e *precond;
1613 insn_repl_e *r;
e0001a05 1614
b81bf389
BW
1615 if (!wide_branch_opcode (initial_insn->t.opcode_name, ".w18", &opcode)
1616 && !wide_branch_opcode (initial_insn->t.opcode_name, ".w15", &opcode))
1617 opcode = xtensa_opcode_lookup (isa, initial_insn->t.opcode_name);
1618
e0001a05
NC
1619 if (opcode == XTENSA_UNDEFINED)
1620 {
1621 /* It is OK to not be able to translate some of these opcodes. */
e0001a05
NC
1622 return NULL;
1623 }
1624
1625
43cd72b9
BW
1626 if (xtensa_opcode_num_operands (isa, opcode)
1627 != insn_templ_operand_count (&initial_insn->t))
e0001a05
NC
1628 {
1629 /* This is also OK because there are opcodes that
1630 have different numbers of operands on different
1631 architecture variations. */
e0001a05
NC
1632 return NULL;
1633 }
1634
1635 tr = (TransitionRule *) xmalloc (sizeof (TransitionRule));
1636 tr->opcode = opcode;
1637 tr->conditions = NULL;
1638 tr->to_instr = NULL;
1639
1640 /* Build the conditions. First, equivalent operand condition.... */
1641 for (op1 = initial_insn->t.operand_map.head; op1 != NULL; op1 = op1->next)
1642 {
1643 for (op2 = op1->next; op2 != NULL; op2 = op2->next)
1644 {
1645 if (same_operand_name (op1, op2))
1646 {
1647 append_value_condition (tr, OP_EQUAL,
1648 op1->operand_num, op2->operand_num);
1649 }
1650 }
1651 }
1652
1653 /* Now the condition that an operand value must be a constant.... */
1654 for (op1 = initial_insn->t.operand_map.head; op1 != NULL; op1 = op1->next)
1655 {
1656 if (op_is_constant (op1))
1657 {
1658 append_constant_value_condition (tr,
1659 OP_EQUAL,
1660 op1->operand_num,
1661 op_get_constant (op1));
1662 }
1663 }
1664
1665
1666 /* Now add the explicit preconditions listed after the "|" in the spec.
1667 These are currently very limited, so we do a special case
1668 parse for them. We expect spaces, opname != opname. */
1669 for (precond = initial_insn->preconds.head;
1670 precond != NULL;
1671 precond = precond->next)
1672 {
1673 op1 = NULL;
1674 op2 = NULL;
1675
1676 if (precond->opname1)
1677 {
1678 op1 = get_opmatch (&initial_insn->t.operand_map, precond->opname1);
1679 if (op1 == NULL)
bc447904
BW
1680 as_fatal (_("opcode '%s': no bound opname '%s' "
1681 "for precondition in '%s'"),
1682 xtensa_opcode_name (isa, opcode),
1683 precond->opname1, from_string);
e0001a05
NC
1684 }
1685
1686 if (precond->opname2)
1687 {
1688 op2 = get_opmatch (&initial_insn->t.operand_map, precond->opname2);
1689 if (op2 == NULL)
bc447904
BW
1690 as_fatal (_("opcode '%s': no bound opname '%s' "
1691 "for precondition in %s"),
1692 xtensa_opcode_name (isa, opcode),
1693 precond->opname2, from_string);
e0001a05
NC
1694 }
1695
1696 if (op1 == NULL && op2 == NULL)
bc447904
BW
1697 as_fatal (_("opcode '%s': precondition only contains "
1698 "constants in '%s'"),
1699 xtensa_opcode_name (isa, opcode), from_string);
e0001a05
NC
1700 else if (op1 != NULL && op2 != NULL)
1701 append_value_condition (tr, precond->cmpop,
1702 op1->operand_num, op2->operand_num);
1703 else if (op2 == NULL)
1704 append_constant_value_condition (tr, precond->cmpop,
43cd72b9 1705 op1->operand_num, precond->opval2);
e0001a05
NC
1706 else
1707 append_constant_value_condition (tr, precond->cmpop,
43cd72b9 1708 op2->operand_num, precond->opval1);
e0001a05
NC
1709 }
1710
43cd72b9
BW
1711 tr->options = clone_req_option_list (initial_insn->options);
1712
e0001a05 1713 /* Generate the replacement instructions. Some of these
61376837
BW
1714 "instructions" are actually labels and literals. There can be at
1715 most one literal and at most one label. A literal must be defined
1716 (e.g., "LITERAL %imm") before use (e.g., "%LITERAL"). The labels
1717 can be used before they are defined. Also there are a number of
1718 special operands (e.g., HI24S). */
e0001a05 1719
28dbbc02 1720 literal_bi = NULL;
e0001a05
NC
1721 for (r = replace_insns->head; r != NULL; r = r->next)
1722 {
1723 BuildInstr *bi;
1724 const char *opcode_name;
43cd72b9 1725 int operand_count;
e0001a05 1726 opname_map_e *op;
e0001a05
NC
1727 const char *fn_name;
1728 const char *operand_arg_name;
1729
1730 bi = (BuildInstr *) xmalloc (sizeof (BuildInstr));
1731 append_build_insn (tr, bi);
1732
e0001a05
NC
1733 bi->opcode = XTENSA_UNDEFINED;
1734 bi->ops = NULL;
1735 bi->next = NULL;
1736
1737 opcode_name = r->t.opcode_name;
1738 operand_count = insn_templ_operand_count (&r->t);
1739
61376837 1740 if (strcmp (opcode_name, "LITERAL") == 0)
e0001a05
NC
1741 {
1742 bi->typ = INSTR_LITERAL_DEF;
e0001a05
NC
1743 if (operand_count != 1)
1744 as_fatal (_("expected one operand for generated literal"));
28dbbc02 1745 literal_bi = bi;
e0001a05 1746 }
61376837 1747 else if (strcmp (opcode_name, "LABEL") == 0)
e0001a05
NC
1748 {
1749 bi->typ = INSTR_LABEL_DEF;
e0001a05
NC
1750 if (operand_count != 0)
1751 as_fatal (_("expected 0 operands for generated label"));
1752 }
1753 else
1754 {
1755 bi->typ = INSTR_INSTR;
1946c96e
BW
1756 if (wide_branch_opcode (opcode_name, ".w18", &bi->opcode)
1757 || wide_branch_opcode (opcode_name, ".w15", &bi->opcode))
1758 opcode_name = xtensa_opcode_name (isa, bi->opcode);
1759 else
1760 bi->opcode = xtensa_opcode_lookup (isa, opcode_name);
1761
e0001a05 1762 if (bi->opcode == XTENSA_UNDEFINED)
43cd72b9
BW
1763 {
1764 as_warn (_("invalid opcode '%s' in transition rule '%s'"),
1946c96e 1765 opcode_name, to_string);
43cd72b9
BW
1766 return NULL;
1767 }
1946c96e 1768
e0001a05 1769 /* Check for the right number of ops. */
c138bc38 1770 if (xtensa_opcode_num_operands (isa, bi->opcode)
e0001a05
NC
1771 != (int) operand_count)
1772 as_fatal (_("opcode '%s': replacement does not have %d ops"),
43cd72b9
BW
1773 opcode_name,
1774 xtensa_opcode_num_operands (isa, bi->opcode));
e0001a05
NC
1775 }
1776
1777 for (op = r->t.operand_map.head; op != NULL; op = op->next)
1778 {
1779 unsigned idnum;
1780
1781 if (op_is_constant (op))
1782 append_constant_op (bi, op->operand_num, op_get_constant (op));
61376837 1783 else if (strcmp (op->operand_name, "%LITERAL") == 0)
28dbbc02
BW
1784 {
1785 if (! literal_bi || ! literal_bi->ops || literal_bi->ops->next)
1786 as_fatal (_("opcode '%s': cannot find literal definition"),
1787 opcode_name);
1788 append_literal_op (bi, op->operand_num,
1789 literal_bi->ops->op_data);
1790 }
61376837
BW
1791 else if (strcmp (op->operand_name, "%LABEL") == 0)
1792 append_label_op (bi, op->operand_num);
1793 else if (op->operand_name[0] == 'a'
1794 && parse_constant (op->operand_name + 1, &idnum))
e0001a05
NC
1795 append_constant_op (bi, op->operand_num, idnum);
1796 else if (op->operand_name[0] == '%')
1797 {
1798 opname_map_e *orig_op;
1799 orig_op = get_opmatch (&initial_insn->t.operand_map,
1800 op->operand_name);
1801 if (orig_op == NULL)
bc447904
BW
1802 as_fatal (_("opcode %s: unidentified operand '%s' in '%s'"),
1803 opcode_name, op->operand_name, to_string);
1804 append_field_op (bi, op->operand_num, orig_op->operand_num);
e0001a05 1805 }
19e8f41a
BW
1806 else if (strcmp (op->operand_name, "FREEREG") == 0)
1807 {
1808 append_user_fn_field_op (bi, op->operand_num, OP_FREEREG, 0);
1809 }
e0001a05
NC
1810 else if (parse_special_fn (op->operand_name,
1811 &fn_name, &operand_arg_name))
1812 {
1813 opname_map_e *orig_op;
1814 OpType typ = OP_CONSTANT;
1815
1816 if (strcmp (fn_name, "LOW8") == 0)
1817 typ = OP_OPERAND_LOW8;
1818 else if (strcmp (fn_name, "HI24S") == 0)
1819 typ = OP_OPERAND_HI24S;
1820 else if (strcmp (fn_name, "F32MINUS") == 0)
1821 typ = OP_OPERAND_F32MINUS;
43cd72b9
BW
1822 else if (strcmp (fn_name, "LOW16U") == 0)
1823 typ = OP_OPERAND_LOW16U;
1824 else if (strcmp (fn_name, "HI16U") == 0)
1825 typ = OP_OPERAND_HI16U;
e0001a05 1826 else
43cd72b9 1827 as_fatal (_("unknown user-defined function %s"), fn_name);
e0001a05
NC
1828
1829 orig_op = get_opmatch (&initial_insn->t.operand_map,
1830 operand_arg_name);
1831 if (orig_op == NULL)
bc447904
BW
1832 as_fatal (_("opcode %s: unidentified operand '%s' in '%s'"),
1833 opcode_name, op->operand_name, to_string);
1834 append_user_fn_field_op (bi, op->operand_num,
1835 typ, orig_op->operand_num);
e0001a05
NC
1836 }
1837 else
bc447904
BW
1838 as_fatal (_("opcode %s: could not parse operand '%s' in '%s'"),
1839 opcode_name, op->operand_name, to_string);
e0001a05
NC
1840 }
1841 }
e0001a05
NC
1842
1843 return tr;
1844}
1845
1846
7fa3d080
BW
1847static TransitionTable *
1848build_transition_table (const string_pattern_pair *transitions,
1849 int transition_count,
1850 transition_cmp_fn cmp)
e0001a05
NC
1851{
1852 TransitionTable *table = NULL;
43cd72b9
BW
1853 int num_opcodes = xtensa_isa_num_opcodes (xtensa_default_isa);
1854 int i, tnum;
e0001a05
NC
1855
1856 if (table != NULL)
1857 return table;
1858
1859 /* Otherwise, build it now. */
1860 table = (TransitionTable *) xmalloc (sizeof (TransitionTable));
1861 table->num_opcodes = num_opcodes;
1862 table->table =
1863 (TransitionList **) xmalloc (sizeof (TransitionTable *) * num_opcodes);
1864
1865 for (i = 0; i < num_opcodes; i++)
1866 table->table[i] = NULL;
1867
1868 for (tnum = 0; tnum < transition_count; tnum++)
1869 {
1870 const char *from_string = transitions[tnum].pattern;
1871 const char *to_string = transitions[tnum].replacement;
1872
1873 insn_pattern initial_insn;
1874 insn_repl replace_insns;
1875 TransitionRule *tr;
1876
1877 init_insn_pattern (&initial_insn);
1878 if (!parse_insn_pattern (from_string, &initial_insn))
bc447904 1879 as_fatal (_("could not parse INSN_PATTERN '%s'"), from_string);
e0001a05
NC
1880
1881 init_insn_repl (&replace_insns);
1882 if (!parse_insn_repl (to_string, &replace_insns))
bc447904 1883 as_fatal (_("could not parse INSN_REPL '%s'"), to_string);
e0001a05 1884
43cd72b9
BW
1885 if (transition_applies (&initial_insn, from_string, to_string))
1886 {
1887 tr = build_transition (&initial_insn, &replace_insns,
1888 from_string, to_string);
1889 if (tr)
1890 append_transition (table, tr->opcode, tr, cmp);
1891 else
1892 {
1893#if TENSILICA_DEBUG
1894 as_warn (_("could not build transition for %s => %s"),
1895 from_string, to_string);
1896#endif
1897 }
1898 }
e0001a05
NC
1899
1900 clear_insn_repl (&replace_insns);
1901 clear_insn_pattern (&initial_insn);
1902 }
1903 return table;
1904}
1905
1906\f
1907extern TransitionTable *
7fa3d080 1908xg_build_widen_table (transition_cmp_fn cmp)
e0001a05
NC
1909{
1910 static TransitionTable *table = NULL;
1911 if (table == NULL)
43cd72b9 1912 table = build_transition_table (widen_spec_list, WIDEN_COUNT, cmp);
e0001a05
NC
1913 return table;
1914}
1915
1916
1917extern TransitionTable *
7fa3d080 1918xg_build_simplify_table (transition_cmp_fn cmp)
e0001a05
NC
1919{
1920 static TransitionTable *table = NULL;
1921 if (table == NULL)
43cd72b9 1922 table = build_transition_table (simplify_spec_list, SIMPLIFY_COUNT, cmp);
e0001a05
NC
1923 return table;
1924}
This page took 0.953142 seconds and 4 git commands to generate.