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