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