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