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