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