1 /* Table of relaxations for Xtensa assembly.
2 Copyright 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
4 This file is part of GAS, the GNU Assembler.
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
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.
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
18 the Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
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
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
28 operands from the pattern should be used in the result.
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
35 The patterns match a language like:
37 INSN_PATTERN ::= INSN_TEMPL ( '|' PRECOND )* ( '?' OPTIONPRED )*
38 INSN_TEMPL ::= OPCODE ' ' [ OPERAND (',' OPERAND)* ]
40 OPERAND ::= CONSTANT | VARIABLE | SPECIALFN '(' VARIABLE ')'
41 SPECIALFN ::= 'HI24S' | 'F32MINUS' | 'LOW8'
44 PRECOND ::= OPERAND CMPOP OPERAND
46 OPTIONPRED ::= OPTIONNAME ('+' OPTIONNAME)
47 OPTIONNAME ::= '"' id '"'
49 The replacement language
50 INSN_REPL ::= INSN_LABEL_LIT ( ';' INSN_LABEL_LIT )*
51 INSN_LABEL_LIT ::= INSN_TEMPL
55 The operands in a PRECOND must be constants or variables bound by
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.
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.
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.
74 A more complex example of a branch around:
75 {"beqz %as,%label", "bnez %as,%LABEL;j %label;LABEL"}
76 would convert a branch to a negated branch to the following instruction
77 with a jump to the original label.
79 An Xtensa-specific example that generates a literal:
80 {"movi %at,%imm", "LITERAL %imm; l32r %at,%LITERAL"}
81 will convert a movi instruction to an l32r of a literal
82 literal defined in the literal pool.
84 Even more complex is a conversion of a load with immediate offset
85 to a load of a freshly generated literal, an explicit add and
86 a load with 0 offset. This transformation is only valid, though
87 when the first and second operands are not the same as specified
88 by the "| %at!=%as" precondition clause.
89 {"l32i %at,%as,%imm | %at!=%as",
90 "LITERAL %imm; l32r %at,%LITERAL; add %at,%at,%as; l32i %at,%at,0"}
92 There is special case for loop instructions here, but because we do
93 not currently have the ability to represent the difference of two
94 symbols, the conversion requires special code in the assembler to
95 write the operands of the addi/addmi pair representing the
96 difference of the old and new loop end label. */
99 #include "xtensa-isa.h"
100 #include "xtensa-relax.h"
102 #include "xtensa-config.h"
104 #ifndef XCHAL_HAVE_WIDE_BRANCHES
105 #define XCHAL_HAVE_WIDE_BRANCHES 0
108 /* Imported from bfd. */
109 extern xtensa_isa xtensa_default_isa
;
111 /* The opname_list is a small list of names that we use for opcode and
112 operand variable names to simplify ownership of these commonly used
113 strings. Strings entered in the table can be compared by pointer
116 typedef struct opname_list_struct opname_list
;
117 typedef opname_list opname_e
;
119 struct opname_list_struct
125 static opname_list
*local_opnames
= NULL
;
128 /* The "opname_map" and its element structure "opname_map_e" are used
129 for binding an operand number to a name or a constant. */
131 typedef struct opname_map_e_struct opname_map_e
;
132 typedef struct opname_map_struct opname_map
;
134 struct opname_map_e_struct
136 const char *operand_name
; /* If null, then use constant_value. */
138 unsigned constant_value
;
142 struct opname_map_struct
148 /* The "precond_list" and its element structure "precond_e" represents
149 explicit preconditions comparing operand variables and constants.
150 In the "precond_e" structure, a variable is identified by the name
151 in the "opname" field. If that field is NULL, then the operand
152 is the constant in field "opval". */
154 typedef struct precond_e_struct precond_e
;
155 typedef struct precond_list_struct precond_list
;
157 struct precond_e_struct
167 struct precond_list_struct
174 /* The insn_templ represents the INSN_TEMPL instruction template. It
175 is an opcode name with a list of operands. These are used for
176 instruction patterns and replacement patterns. */
178 typedef struct insn_templ_struct insn_templ
;
179 struct insn_templ_struct
181 const char *opcode_name
;
182 opname_map operand_map
;
186 /* The insn_pattern represents an INSN_PATTERN instruction pattern.
187 It is an instruction template with preconditions that specify when
188 it actually matches a given instruction. */
190 typedef struct insn_pattern_struct insn_pattern
;
191 struct insn_pattern_struct
194 precond_list preconds
;
195 ReqOptionList
*options
;
199 /* The "insn_repl" and associated element structure "insn_repl_e"
200 instruction replacement list is a list of
201 instructions/LITERALS/LABELS with constant operands or operands
202 with names bound to the operand names in the associated pattern. */
204 typedef struct insn_repl_e_struct insn_repl_e
;
205 struct insn_repl_e_struct
211 typedef struct insn_repl_struct insn_repl
;
212 struct insn_repl_struct
219 /* The split_rec is a vector of allocated char * pointers. */
221 typedef struct split_rec_struct split_rec
;
222 struct split_rec_struct
228 /* The "string_pattern_pair" is a set of pairs containing instruction
229 patterns and replacement strings. */
231 typedef struct string_pattern_pair_struct string_pattern_pair
;
232 struct string_pattern_pair_struct
235 const char *replacement
;
239 /* The widen_spec_list is a list of valid substitutions that generate
240 wider representations. These are generally used to specify
241 replacements for instructions whose immediates do not fit their
242 encodings. A valid transition may require multiple steps of
243 one-to-one instruction replacements with a final multiple
244 instruction replacement. As an example, here are the transitions
245 required to replace an 'addi.n' with an 'addi', 'addmi'.
250 => addmi a4, 0x1000, addi a4, 0x10.
252 See the comments in xg_assembly_relax for some important details
253 regarding how these chains must be built. */
255 static string_pattern_pair widen_spec_list
[] =
257 {"add.n %ar,%as,%at ? IsaUseDensityInstruction", "add %ar,%as,%at"},
258 {"addi.n %ar,%as,%imm ? IsaUseDensityInstruction", "addi %ar,%as,%imm"},
259 {"beqz.n %as,%label ? IsaUseDensityInstruction", "beqz %as,%label"},
260 {"bnez.n %as,%label ? IsaUseDensityInstruction", "bnez %as,%label"},
261 {"l32i.n %at,%as,%imm ? IsaUseDensityInstruction", "l32i %at,%as,%imm"},
262 {"mov.n %at,%as ? IsaUseDensityInstruction", "or %at,%as,%as"},
263 {"movi.n %as,%imm ? IsaUseDensityInstruction", "movi %as,%imm"},
264 {"nop.n ? IsaUseDensityInstruction ? realnop", "nop"},
265 {"nop.n ? IsaUseDensityInstruction ? no-realnop", "or 1,1,1"},
266 {"ret.n %as ? IsaUseDensityInstruction", "ret %as"},
267 {"retw.n %as ? IsaUseDensityInstruction", "retw %as"},
268 {"s32i.n %at,%as,%imm ? IsaUseDensityInstruction", "s32i %at,%as,%imm"},
269 {"srli %at,%as,%imm", "extui %at,%as,%imm,F32MINUS(%imm)"},
270 {"slli %ar,%as,0", "or %ar,%as,%as"},
272 /* Widening with literals or const16. */
273 {"movi %at,%imm ? IsaUseL32R ",
274 "LITERAL %imm; l32r %at,%LITERAL"},
275 {"movi %at,%imm ? IsaUseConst16",
276 "const16 %at,HI16U(%imm); const16 %at,LOW16U(%imm)"},
278 {"addi %ar,%as,%imm", "addmi %ar,%as,%imm"},
279 /* LOW8 is the low 8 bits of the Immed
280 MID8S is the middle 8 bits of the Immed */
281 {"addmi %ar,%as,%imm", "addmi %ar,%as,HI24S(%imm); addi %ar,%ar,LOW8(%imm)"},
283 /* In the end convert to either an l32r or const16. */
284 {"addmi %ar,%as,%imm | %ar!=%as ? IsaUseL32R",
285 "LITERAL %imm; l32r %ar,%LITERAL; add %ar,%as,%ar"},
286 {"addmi %ar,%as,%imm | %ar!=%as ? IsaUseConst16",
287 "const16 %ar,HI16U(%imm); const16 %ar,LOW16U(%imm); add %ar,%as,%ar"},
289 /* Widening the load instructions with too-large immediates */
290 {"l8ui %at,%as,%imm | %at!=%as ? IsaUseL32R",
291 "LITERAL %imm; l32r %at,%LITERAL; add %at,%at,%as; l8ui %at,%at,0"},
292 {"l16si %at,%as,%imm | %at!=%as ? IsaUseL32R",
293 "LITERAL %imm; l32r %at,%LITERAL; add %at,%at,%as; l16si %at,%at,0"},
294 {"l16ui %at,%as,%imm | %at!=%as ? IsaUseL32R",
295 "LITERAL %imm; l32r %at,%LITERAL; add %at,%at,%as; l16ui %at,%at,0"},
296 {"l32i %at,%as,%imm | %at!=%as ? IsaUseL32R",
297 "LITERAL %imm; l32r %at,%LITERAL; add %at,%at,%as; l32i %at,%at,0"},
299 /* Widening load instructions with const16s. */
300 {"l8ui %at,%as,%imm | %at!=%as ? IsaUseConst16",
301 "const16 %at,HI16U(%imm); const16 %at,LOW16U(%imm); add %at,%at,%as; l8ui %at,%at,0"},
302 {"l16si %at,%as,%imm | %at!=%as ? IsaUseConst16",
303 "const16 %at,HI16U(%imm); const16 %at,LOW16U(%imm); add %at,%at,%as; l16si %at,%at,0"},
304 {"l16ui %at,%as,%imm | %at!=%as ? IsaUseConst16",
305 "const16 %at,HI16U(%imm); const16 %at,LOW16U(%imm); add %at,%at,%as; l16ui %at,%at,0"},
306 {"l32i %at,%as,%imm | %at!=%as ? IsaUseConst16",
307 "const16 %at,HI16U(%imm); const16 %at,LOW16U(%imm); add %at,%at,%as; l32i %at,%at,0"},
309 /* This is only PART of the loop instruction. In addition,
310 hardcoded into its use is a modification of the final operand in
311 the instruction in bytes 9 and 12. */
312 {"loop %as,%label | %as!=1 ? IsaUseLoops",
314 "rsr.lend %as;" /* LEND */
315 "wsr.lbeg %as;" /* LBEG */
316 "addi %as, %as, 0;" /* lo8(%label-%LABEL1) */
317 "addmi %as, %as, 0;" /* mid8(%label-%LABEL1) */
320 "rsr.lcount %as;" /* LCOUNT */
321 "addi %as, %as, 1;" /* density -> addi.n %as, %as, 1 */
323 {"loopgtz %as,%label | %as!=1 ? IsaUseLoops",
326 "loopgtz %as,%LABEL;"
327 "rsr.lend %as;" /* LEND */
328 "wsr.lbeg %as;" /* LBEG */
329 "addi %as, %as, 0;" /* lo8(%label-%LABEL1) */
330 "addmi %as, %as, 0;" /* mid8(%label-%LABEL1) */
333 "rsr.lcount %as;" /* LCOUNT */
334 "addi %as, %as, 1;" /* density -> addi.n %as, %as, 1 */
336 {"loopnez %as,%label | %as!=1 ? IsaUseLoops",
338 "loopnez %as,%LABEL;"
339 "rsr.lend %as;" /* LEND */
340 "wsr.lbeg %as;" /* LBEG */
341 "addi %as, %as, 0;" /* lo8(%label-%LABEL1) */
342 "addmi %as, %as, 0;" /* mid8(%label-%LABEL1) */
345 "rsr.lcount %as;" /* LCOUNT */
346 "addi %as, %as, 1;" /* density -> addi.n %as, %as, 1 */
349 /* Relaxing to wide branches. Order is important here. With wide
350 branches, there is more than one correct relaxation for an
351 out-of-range branch. Put the wide branch relaxations first in the
352 table since they are more efficient than the branch-around
355 {"beqz %as,%label ? IsaUseWideBranches", "WIDE.beqz %as,%label"},
356 {"bnez %as,%label ? IsaUseWideBranches", "WIDE.bnez %as,%label"},
357 {"bgez %as,%label ? IsaUseWideBranches", "WIDE.bgez %as,%label"},
358 {"bltz %as,%label ? IsaUseWideBranches", "WIDE.bltz %as,%label"},
359 {"beqi %as,%imm,%label ? IsaUseWideBranches", "WIDE.beqi %as,%imm,%label"},
360 {"bnei %as,%imm,%label ? IsaUseWideBranches", "WIDE.bnei %as,%imm,%label"},
361 {"bgei %as,%imm,%label ? IsaUseWideBranches", "WIDE.bgei %as,%imm,%label"},
362 {"blti %as,%imm,%label ? IsaUseWideBranches", "WIDE.blti %as,%imm,%label"},
363 {"bgeui %as,%imm,%label ? IsaUseWideBranches", "WIDE.bgeui %as,%imm,%label"},
364 {"bltui %as,%imm,%label ? IsaUseWideBranches", "WIDE.bltui %as,%imm,%label"},
365 {"bbci %as,%imm,%label ? IsaUseWideBranches", "WIDE.bbci %as,%imm,%label"},
366 {"bbsi %as,%imm,%label ? IsaUseWideBranches", "WIDE.bbsi %as,%imm,%label"},
367 {"beq %as,%at,%label ? IsaUseWideBranches", "WIDE.beq %as,%at,%label"},
368 {"bne %as,%at,%label ? IsaUseWideBranches", "WIDE.bne %as,%at,%label"},
369 {"bge %as,%at,%label ? IsaUseWideBranches", "WIDE.bge %as,%at,%label"},
370 {"blt %as,%at,%label ? IsaUseWideBranches", "WIDE.blt %as,%at,%label"},
371 {"bgeu %as,%at,%label ? IsaUseWideBranches", "WIDE.bgeu %as,%at,%label"},
372 {"bltu %as,%at,%label ? IsaUseWideBranches", "WIDE.bltu %as,%at,%label"},
373 {"bany %as,%at,%label ? IsaUseWideBranches", "WIDE.bany %as,%at,%label"},
374 {"bnone %as,%at,%label ? IsaUseWideBranches", "WIDE.bnone %as,%at,%label"},
375 {"ball %as,%at,%label ? IsaUseWideBranches", "WIDE.ball %as,%at,%label"},
376 {"bnall %as,%at,%label ? IsaUseWideBranches", "WIDE.bnall %as,%at,%label"},
377 {"bbc %as,%at,%label ? IsaUseWideBranches", "WIDE.bbc %as,%at,%label"},
378 {"bbs %as,%at,%label ? IsaUseWideBranches", "WIDE.bbs %as,%at,%label"},
380 /* Widening branch comparisons eq/ne to zero. Prefer relaxing to narrow
381 branches if the density option is available. */
382 {"beqz %as,%label ? IsaUseDensityInstruction", "bnez.n %as,%LABEL;j %label;LABEL"},
383 {"bnez %as,%label ? IsaUseDensityInstruction", "beqz.n %as,%LABEL;j %label;LABEL"},
384 {"beqz %as,%label", "bnez %as,%LABEL;j %label;LABEL"},
385 {"bnez %as,%label", "beqz %as,%LABEL;j %label;LABEL"},
386 {"WIDE.beqz %as,%label ? IsaUseDensityInstruction", "bnez.n %as,%LABEL;j %label;LABEL"},
387 {"WIDE.bnez %as,%label ? IsaUseDensityInstruction", "beqz.n %as,%LABEL;j %label;LABEL"},
388 {"WIDE.beqz %as,%label", "bnez %as,%LABEL;j %label;LABEL"},
389 {"WIDE.bnez %as,%label", "beqz %as,%LABEL;j %label;LABEL"},
391 /* Widening expect-taken branches. */
392 {"beqzt %as,%label ? IsaUsePredictedBranches", "bnez %as,%LABEL;j %label;LABEL"},
393 {"bnezt %as,%label ? IsaUsePredictedBranches", "beqz %as,%LABEL;j %label;LABEL"},
394 {"beqt %as,%at,%label ? IsaUsePredictedBranches", "bne %as,%at,%LABEL;j %label;LABEL"},
395 {"bnet %as,%at,%label ? IsaUsePredictedBranches", "beq %as,%at,%LABEL;j %label;LABEL"},
397 /* Widening branches from the Xtensa boolean option. */
398 {"bt %bs,%label ? IsaUseBooleans", "bf %bs,%LABEL;j %label;LABEL"},
399 {"bf %bs,%label ? IsaUseBooleans", "bt %bs,%LABEL;j %label;LABEL"},
401 /* Other branch-around-jump widenings. */
402 {"bgez %as,%label", "bltz %as,%LABEL;j %label;LABEL"},
403 {"bltz %as,%label", "bgez %as,%LABEL;j %label;LABEL"},
404 {"beqi %as,%imm,%label", "bnei %as,%imm,%LABEL;j %label;LABEL"},
405 {"bnei %as,%imm,%label", "beqi %as,%imm,%LABEL;j %label;LABEL"},
406 {"bgei %as,%imm,%label", "blti %as,%imm,%LABEL;j %label;LABEL"},
407 {"blti %as,%imm,%label", "bgei %as,%imm,%LABEL;j %label;LABEL"},
408 {"bgeui %as,%imm,%label", "bltui %as,%imm,%LABEL;j %label;LABEL"},
409 {"bltui %as,%imm,%label", "bgeui %as,%imm,%LABEL;j %label;LABEL"},
410 {"bbci %as,%imm,%label", "bbsi %as,%imm,%LABEL;j %label;LABEL"},
411 {"bbsi %as,%imm,%label", "bbci %as,%imm,%LABEL;j %label;LABEL"},
412 {"beq %as,%at,%label", "bne %as,%at,%LABEL;j %label;LABEL"},
413 {"bne %as,%at,%label", "beq %as,%at,%LABEL;j %label;LABEL"},
414 {"bge %as,%at,%label", "blt %as,%at,%LABEL;j %label;LABEL"},
415 {"blt %as,%at,%label", "bge %as,%at,%LABEL;j %label;LABEL"},
416 {"bgeu %as,%at,%label", "bltu %as,%at,%LABEL;j %label;LABEL"},
417 {"bltu %as,%at,%label", "bgeu %as,%at,%LABEL;j %label;LABEL"},
418 {"bany %as,%at,%label", "bnone %as,%at,%LABEL;j %label;LABEL"},
419 {"bnone %as,%at,%label", "bany %as,%at,%LABEL;j %label;LABEL"},
420 {"ball %as,%at,%label", "bnall %as,%at,%LABEL;j %label;LABEL"},
421 {"bnall %as,%at,%label", "ball %as,%at,%LABEL;j %label;LABEL"},
422 {"bbc %as,%at,%label", "bbs %as,%at,%LABEL;j %label;LABEL"},
423 {"bbs %as,%at,%label", "bbc %as,%at,%LABEL;j %label;LABEL"},
425 {"WIDE.bgez %as,%label", "bltz %as,%LABEL;j %label;LABEL"},
426 {"WIDE.bltz %as,%label", "bgez %as,%LABEL;j %label;LABEL"},
427 {"WIDE.beqi %as,%imm,%label", "bnei %as,%imm,%LABEL;j %label;LABEL"},
428 {"WIDE.bnei %as,%imm,%label", "beqi %as,%imm,%LABEL;j %label;LABEL"},
429 {"WIDE.bgei %as,%imm,%label", "blti %as,%imm,%LABEL;j %label;LABEL"},
430 {"WIDE.blti %as,%imm,%label", "bgei %as,%imm,%LABEL;j %label;LABEL"},
431 {"WIDE.bgeui %as,%imm,%label", "bltui %as,%imm,%LABEL;j %label;LABEL"},
432 {"WIDE.bltui %as,%imm,%label", "bgeui %as,%imm,%LABEL;j %label;LABEL"},
433 {"WIDE.bbci %as,%imm,%label", "bbsi %as,%imm,%LABEL;j %label;LABEL"},
434 {"WIDE.bbsi %as,%imm,%label", "bbci %as,%imm,%LABEL;j %label;LABEL"},
435 {"WIDE.beq %as,%at,%label", "bne %as,%at,%LABEL;j %label;LABEL"},
436 {"WIDE.bne %as,%at,%label", "beq %as,%at,%LABEL;j %label;LABEL"},
437 {"WIDE.bge %as,%at,%label", "blt %as,%at,%LABEL;j %label;LABEL"},
438 {"WIDE.blt %as,%at,%label", "bge %as,%at,%LABEL;j %label;LABEL"},
439 {"WIDE.bgeu %as,%at,%label", "bltu %as,%at,%LABEL;j %label;LABEL"},
440 {"WIDE.bltu %as,%at,%label", "bgeu %as,%at,%LABEL;j %label;LABEL"},
441 {"WIDE.bany %as,%at,%label", "bnone %as,%at,%LABEL;j %label;LABEL"},
442 {"WIDE.bnone %as,%at,%label", "bany %as,%at,%LABEL;j %label;LABEL"},
443 {"WIDE.ball %as,%at,%label", "bnall %as,%at,%LABEL;j %label;LABEL"},
444 {"WIDE.bnall %as,%at,%label", "ball %as,%at,%LABEL;j %label;LABEL"},
445 {"WIDE.bbc %as,%at,%label", "bbs %as,%at,%LABEL;j %label;LABEL"},
446 {"WIDE.bbs %as,%at,%label", "bbc %as,%at,%LABEL;j %label;LABEL"},
448 /* Expanding calls with literals. */
449 {"call0 %label,%ar0 ? IsaUseL32R",
450 "LITERAL %label; l32r a0,%LITERAL; callx0 a0,%ar0"},
451 {"call4 %label,%ar4 ? IsaUseL32R",
452 "LITERAL %label; l32r a4,%LITERAL; callx4 a4,%ar4"},
453 {"call8 %label,%ar8 ? IsaUseL32R",
454 "LITERAL %label; l32r a8,%LITERAL; callx8 a8,%ar8"},
455 {"call12 %label,%ar12 ? IsaUseL32R",
456 "LITERAL %label; l32r a12,%LITERAL; callx12 a12,%ar12"},
458 /* Expanding calls with const16. */
459 {"call0 %label,%ar0 ? IsaUseConst16",
460 "const16 a0,HI16U(%label); const16 a0,LOW16U(%label); callx0 a0,%ar0"},
461 {"call4 %label,%ar4 ? IsaUseConst16",
462 "const16 a4,HI16U(%label); const16 a4,LOW16U(%label); callx4 a4,%ar4"},
463 {"call8 %label,%ar8 ? IsaUseConst16",
464 "const16 a8,HI16U(%label); const16 a8,LOW16U(%label); callx8 a8,%ar8"},
465 {"call12 %label,%ar12 ? IsaUseConst16",
466 "const16 a12,HI16U(%label); const16 a12,LOW16U(%label); callx12 a12,%ar12"}
469 #define WIDEN_COUNT (sizeof (widen_spec_list) / sizeof (string_pattern_pair))
472 /* The simplify_spec_list specifies simplifying transformations that
473 will reduce the instruction width or otherwise simplify an
474 instruction. These are usually applied before relaxation in the
475 assembler. It is always legal to simplify. Even for "addi as, 0",
476 the "addi.n as, 0" will eventually be widened back to an "addi 0"
477 after the widening table is applied. Note: The usage of this table
478 has changed somewhat so that it is entirely specific to "narrowing"
479 instructions to use the density option. This table is not used at
480 all when the density option is not available. */
482 string_pattern_pair simplify_spec_list
[] =
484 {"add %ar,%as,%at ? IsaUseDensityInstruction", "add.n %ar,%as,%at"},
485 {"addi.n %ar,%as,0 ? IsaUseDensityInstruction", "mov.n %ar,%as"},
486 {"addi %ar,%as,0 ? IsaUseDensityInstruction", "mov.n %ar,%as"},
487 {"addi %ar,%as,%imm ? IsaUseDensityInstruction", "addi.n %ar,%as,%imm"},
488 {"addmi %ar,%as,%imm ? IsaUseDensityInstruction", "addi.n %ar,%as,%imm"},
489 {"beqz %as,%label ? IsaUseDensityInstruction", "beqz.n %as,%label"},
490 {"bnez %as,%label ? IsaUseDensityInstruction", "bnez.n %as,%label"},
491 {"l32i %at,%as,%imm ? IsaUseDensityInstruction", "l32i.n %at,%as,%imm"},
492 {"movi %as,%imm ? IsaUseDensityInstruction", "movi.n %as,%imm"},
493 {"nop ? realnop ? IsaUseDensityInstruction", "nop.n"},
494 {"or %ar,%as,%at | %ar==%as | %as==%at ? IsaUseDensityInstruction", "nop.n"},
495 {"or %ar,%as,%at | %ar!=%as | %as==%at ? IsaUseDensityInstruction", "mov.n %ar,%as"},
496 {"ret %as ? IsaUseDensityInstruction", "ret.n %as"},
497 {"retw %as ? IsaUseDensityInstruction", "retw.n %as"},
498 {"s32i %at,%as,%imm ? IsaUseDensityInstruction", "s32i.n %at,%as,%imm"},
499 {"slli %ar,%as,0 ? IsaUseDensityInstruction", "mov.n %ar,%as"}
502 #define SIMPLIFY_COUNT \
503 (sizeof (simplify_spec_list) / sizeof (string_pattern_pair))
506 /* Externally visible functions. */
508 extern bfd_boolean
xg_has_userdef_op_fn (OpType
);
509 extern long xg_apply_userdef_op_fn (OpType
, long);
513 append_transition (TransitionTable
*tt
,
514 xtensa_opcode opcode
,
516 transition_cmp_fn cmp
)
518 TransitionList
*tl
= (TransitionList
*) xmalloc (sizeof (TransitionList
));
519 TransitionList
*prev
;
520 TransitionList
**t_p
;
522 assert (opcode
< tt
->num_opcodes
);
524 prev
= tt
->table
[opcode
];
529 tt
->table
[opcode
] = tl
;
533 for (t_p
= &tt
->table
[opcode
]; (*t_p
) != NULL
; t_p
= &(*t_p
)->next
)
535 if (cmp
&& cmp (t
, (*t_p
)->rule
) < 0)
537 /* Insert it here. */
548 append_condition (TransitionRule
*tr
, Precondition
*cond
)
550 PreconditionList
*pl
=
551 (PreconditionList
*) xmalloc (sizeof (PreconditionList
));
552 PreconditionList
*prev
= tr
->conditions
;
553 PreconditionList
*nxt
;
573 append_value_condition (TransitionRule
*tr
,
578 Precondition
*cond
= (Precondition
*) xmalloc (sizeof (Precondition
));
582 cond
->typ
= OP_OPERAND
;
584 append_condition (tr
, cond
);
589 append_constant_value_condition (TransitionRule
*tr
,
594 Precondition
*cond
= (Precondition
*) xmalloc (sizeof (Precondition
));
598 cond
->typ
= OP_CONSTANT
;
599 cond
->op_data
= cnst
;
600 append_condition (tr
, cond
);
605 append_build_insn (TransitionRule
*tr
, BuildInstr
*bi
)
607 BuildInstr
*prev
= tr
->to_instr
;
627 append_op (BuildInstr
*bi
, BuildOp
*b_op
)
629 BuildOp
*prev
= bi
->ops
;
648 append_literal_op (BuildInstr
*bi
, unsigned op1
)
650 BuildOp
*b_op
= (BuildOp
*) xmalloc (sizeof (BuildOp
));
653 b_op
->typ
= OP_LITERAL
;
656 append_op (bi
, b_op
);
661 append_label_op (BuildInstr
*bi
, unsigned op1
)
663 BuildOp
*b_op
= (BuildOp
*) xmalloc (sizeof (BuildOp
));
666 b_op
->typ
= OP_LABEL
;
669 append_op (bi
, b_op
);
674 append_constant_op (BuildInstr
*bi
, unsigned op1
, unsigned cnst
)
676 BuildOp
*b_op
= (BuildOp
*) xmalloc (sizeof (BuildOp
));
679 b_op
->typ
= OP_CONSTANT
;
680 b_op
->op_data
= cnst
;
682 append_op (bi
, b_op
);
687 append_field_op (BuildInstr
*bi
, unsigned op1
, unsigned src_op
)
689 BuildOp
*b_op
= (BuildOp
*) xmalloc (sizeof (BuildOp
));
692 b_op
->typ
= OP_OPERAND
;
693 b_op
->op_data
= src_op
;
695 append_op (bi
, b_op
);
699 /* These could be generated but are not currently. */
702 append_user_fn_field_op (BuildInstr
*bi
,
707 BuildOp
*b_op
= (BuildOp
*) xmalloc (sizeof (BuildOp
));
711 b_op
->op_data
= src_op
;
713 append_op (bi
, b_op
);
717 /* These operand functions are the semantics of user-defined
718 operand functions. */
721 operand_function_HI24S (long a
)
724 return (a
& (~0xff)) + 0x100;
726 return (a
& (~0xff));
731 operand_function_F32MINUS (long a
)
738 operand_function_LOW8 (long a
)
741 return (a
& 0xff) | ~0xff;
748 operand_function_LOW16U (long a
)
755 operand_function_HI16U (long a
)
757 unsigned long b
= a
& 0xffff0000;
758 return (long) (b
>> 16);
763 xg_has_userdef_op_fn (OpType op
)
767 case OP_OPERAND_F32MINUS
:
768 case OP_OPERAND_LOW8
:
769 case OP_OPERAND_HI24S
:
770 case OP_OPERAND_LOW16U
:
771 case OP_OPERAND_HI16U
:
781 xg_apply_userdef_op_fn (OpType op
, long a
)
785 case OP_OPERAND_F32MINUS
:
786 return operand_function_F32MINUS (a
);
787 case OP_OPERAND_LOW8
:
788 return operand_function_LOW8 (a
);
789 case OP_OPERAND_HI24S
:
790 return operand_function_HI24S (a
);
791 case OP_OPERAND_LOW16U
:
792 return operand_function_LOW16U (a
);
793 case OP_OPERAND_HI16U
:
794 return operand_function_HI16U (a
);
802 /* Generate a transition table. */
805 enter_opname_n (const char *name
, int len
)
809 for (op
= local_opnames
; op
!= NULL
; op
= op
->next
)
811 if (strlen (op
->opname
) == (unsigned) len
812 && strncmp (op
->opname
, name
, len
) == 0)
815 op
= (opname_e
*) xmalloc (sizeof (opname_e
));
816 op
->opname
= (char *) xmalloc (len
+ 1);
817 strncpy (op
->opname
, name
, len
);
818 op
->opname
[len
] = '\0';
824 enter_opname (const char *name
)
828 for (op
= local_opnames
; op
!= NULL
; op
= op
->next
)
830 if (strcmp (op
->opname
, name
) == 0)
833 op
= (opname_e
*) xmalloc (sizeof (opname_e
));
834 op
->opname
= xstrdup (name
);
840 init_opname_map (opname_map
*m
)
848 clear_opname_map (opname_map
*m
)
852 while (m
->head
!= NULL
)
863 same_operand_name (const opname_map_e
*m1
, const opname_map_e
*m2
)
865 if (m1
->operand_name
== NULL
|| m1
->operand_name
== NULL
)
867 return (m1
->operand_name
== m2
->operand_name
);
871 static opname_map_e
*
872 get_opmatch (opname_map
*map
, const char *operand_name
)
876 for (m
= map
->head
; m
!= NULL
; m
= m
->next
)
878 if (strcmp (m
->operand_name
, operand_name
) == 0)
886 op_is_constant (const opname_map_e
*m1
)
888 return (m1
->operand_name
== NULL
);
893 op_get_constant (const opname_map_e
*m1
)
895 assert (m1
->operand_name
== NULL
);
896 return m1
->constant_value
;
901 init_precond_list (precond_list
*l
)
909 clear_precond_list (precond_list
*l
)
913 while (l
->head
!= NULL
)
924 init_insn_templ (insn_templ
*t
)
926 t
->opcode_name
= NULL
;
927 init_opname_map (&t
->operand_map
);
932 clear_insn_templ (insn_templ
*t
)
934 clear_opname_map (&t
->operand_map
);
939 init_insn_pattern (insn_pattern
*p
)
941 init_insn_templ (&p
->t
);
942 init_precond_list (&p
->preconds
);
948 clear_insn_pattern (insn_pattern
*p
)
950 clear_insn_templ (&p
->t
);
951 clear_precond_list (&p
->preconds
);
956 init_insn_repl (insn_repl
*r
)
964 clear_insn_repl (insn_repl
*r
)
968 while (r
->head
!= NULL
)
972 clear_insn_templ (&e
->t
);
979 insn_templ_operand_count (const insn_templ
*t
)
982 const opname_map_e
*op
;
984 for (op
= t
->operand_map
.head
; op
!= NULL
; op
= op
->next
, i
++)
990 /* Convert a string to a number. E.G.: parse_constant("10", &num) */
993 parse_constant (const char *in
, unsigned *val_p
)
1004 if (*p
>= '0' && *p
<= '9')
1005 val
= val
* 10 + (*p
- '0');
1016 parse_special_fn (const char *name
,
1017 const char **fn_name_p
,
1018 const char **arg_name_p
)
1023 p_start
= strchr (name
, '(');
1024 if (p_start
== NULL
)
1027 p_end
= strchr (p_start
, ')');
1032 if (p_end
[1] != '\0')
1035 *fn_name_p
= enter_opname_n (name
, p_start
- name
);
1036 *arg_name_p
= enter_opname_n (p_start
+ 1, p_end
- p_start
- 1);
1042 skip_white (const char *p
)
1053 trim_whitespace (char *in
)
1055 char *last_white
= NULL
;
1058 while (p
&& *p
!= '\0')
1062 if (last_white
== NULL
)
1077 /* Split a string into component strings where "c" is the
1078 delimiter. Place the result in the split_rec. */
1081 split_string (split_rec
*rec
,
1084 bfd_boolean elide_whitespace
)
1090 while (p
!= NULL
&& *p
!= '\0')
1100 if (rec
->count
== 0)
1103 rec
->vec
= (char **) xmalloc (sizeof (char *) * cnt
);
1104 for (i
= 0; i
< cnt
; i
++)
1108 for (i
= 0; i
< cnt
; i
++)
1114 if (elide_whitespace
)
1119 rec
->vec
[i
] = xstrdup (q
);
1123 rec
->vec
[i
] = (char *) xmalloc (sizeof (char) * (len
+ 1));
1124 strncpy (rec
->vec
[i
], q
, len
);
1125 rec
->vec
[i
][len
] = '\0';
1129 if (elide_whitespace
)
1130 trim_whitespace (rec
->vec
[i
]);
1136 clear_split_rec (split_rec
*rec
)
1140 for (i
= 0; i
< rec
->count
; i
++)
1148 /* Initialize a split record. The split record must be initialized
1149 before split_string is called. */
1152 init_split_rec (split_rec
*rec
)
1159 /* Parse an instruction template like "insn op1, op2, op3". */
1162 parse_insn_templ (const char *s
, insn_templ
*t
)
1169 /* First find the first whitespace. */
1171 init_split_rec (&oprec
);
1174 insn_name_len
= strcspn (s
, " ");
1175 if (insn_name_len
== 0)
1178 init_insn_templ (t
);
1179 t
->opcode_name
= enter_opname_n (p
, insn_name_len
);
1181 p
= p
+ insn_name_len
;
1183 /* Split by ',' and skip beginning and trailing whitespace. */
1184 split_string (&oprec
, p
, ',', TRUE
);
1186 for (i
= 0; i
< oprec
.count
; i
++)
1188 const char *opname
= oprec
.vec
[i
];
1189 opname_map_e
*e
= (opname_map_e
*) xmalloc (sizeof (opname_map_e
));
1191 e
->operand_name
= NULL
;
1192 e
->constant_value
= 0;
1195 /* If it begins with a number, assume that it is a number. */
1196 if (opname
&& opname
[0] >= '0' && opname
[0] <= '9')
1200 if (parse_constant (opname
, &val
))
1201 e
->constant_value
= val
;
1205 clear_split_rec (&oprec
);
1206 clear_insn_templ (t
);
1211 e
->operand_name
= enter_opname (oprec
.vec
[i
]);
1213 *t
->operand_map
.tail
= e
;
1214 t
->operand_map
.tail
= &e
->next
;
1216 clear_split_rec (&oprec
);
1222 parse_precond (const char *s
, precond_e
*precond
)
1224 /* All preconditions are currently of the form:
1225 a == b or a != b or a == k (where k is a constant).
1226 Later we may use some special functions like DENSITY == 1
1227 to identify when density is available. */
1231 precond
->opname1
= NULL
;
1232 precond
->opval1
= 0;
1233 precond
->cmpop
= OP_EQUAL
;
1234 precond
->opname2
= NULL
;
1235 precond
->opval2
= 0;
1236 precond
->next
= NULL
;
1240 len
= strcspn (p
, " !=");
1245 precond
->opname1
= enter_opname_n (p
, len
);
1249 /* Check for "==" and "!=". */
1250 if (strncmp (p
, "==", 2) == 0)
1251 precond
->cmpop
= OP_EQUAL
;
1252 else if (strncmp (p
, "!=", 2) == 0)
1253 precond
->cmpop
= OP_NOTEQUAL
;
1260 /* No trailing whitespace from earlier parsing. */
1261 if (p
[0] >= '0' && p
[0] <= '9')
1264 if (parse_constant (p
, &val
))
1265 precond
->opval2
= val
;
1270 precond
->opname2
= enter_opname (p
);
1276 clear_req_or_option_list (ReqOrOption
**r_p
)
1281 free ((*r_p
)->option_name
);
1282 clear_req_or_option_list (&(*r_p
)->next
);
1288 clear_req_option_list (ReqOption
**r_p
)
1293 clear_req_or_option_list (&(*r_p
)->or_option_terms
);
1294 clear_req_option_list (&(*r_p
)->next
);
1299 static ReqOrOption
*
1300 clone_req_or_option_list (ReqOrOption
*req_or_option
)
1302 ReqOrOption
*new_req_or_option
;
1304 if (req_or_option
== NULL
)
1307 new_req_or_option
= (ReqOrOption
*) xmalloc (sizeof (ReqOrOption
));
1308 new_req_or_option
->option_name
= xstrdup (req_or_option
->option_name
);
1309 new_req_or_option
->is_true
= req_or_option
->is_true
;
1310 new_req_or_option
->next
= NULL
;
1311 new_req_or_option
->next
= clone_req_or_option_list (req_or_option
->next
);
1312 return new_req_or_option
;
1317 clone_req_option_list (ReqOption
*req_option
)
1319 ReqOption
*new_req_option
;
1321 if (req_option
== NULL
)
1324 new_req_option
= (ReqOption
*) xmalloc (sizeof (ReqOption
));
1325 new_req_option
->or_option_terms
= NULL
;
1326 new_req_option
->next
= NULL
;
1327 new_req_option
->or_option_terms
=
1328 clone_req_or_option_list (req_option
->or_option_terms
);
1329 new_req_option
->next
= clone_req_option_list (req_option
->next
);
1330 return new_req_option
;
1335 parse_option_cond (const char *s
, ReqOption
*option
)
1338 split_rec option_term_rec
;
1340 /* All option or conditions are of the form:
1341 optionA + no-optionB + ...
1342 "Ands" are divided by "?". */
1344 init_split_rec (&option_term_rec
);
1345 split_string (&option_term_rec
, s
, '+', TRUE
);
1347 if (option_term_rec
.count
== 0)
1349 clear_split_rec (&option_term_rec
);
1353 for (i
= 0; i
< option_term_rec
.count
; i
++)
1355 char *option_name
= option_term_rec
.vec
[i
];
1356 bfd_boolean is_true
= TRUE
;
1360 if (strncmp (option_name
, "no-", 3) == 0)
1362 option_name
= xstrdup (&option_name
[3]);
1366 option_name
= xstrdup (option_name
);
1368 req
= (ReqOrOption
*) xmalloc (sizeof (ReqOrOption
));
1369 req
->option_name
= option_name
;
1370 req
->is_true
= is_true
;
1373 /* Append to list. */
1374 for (r_p
= &option
->or_option_terms
; (*r_p
) != NULL
;
1375 r_p
= &(*r_p
)->next
)
1383 /* Parse a string like:
1384 "insn op1, op2, op3, op4 | op1 != op2 | op2 == op3 | op4 == 1".
1385 I.E., instruction "insn" with 4 operands where operand 1 and 2 are not
1386 the same and operand 2 and 3 are the same and operand 4 is 1.
1390 "insn op1 | op1 == 1 / density + boolean / no-useroption".
1391 i.e. instruction "insn" with 1 operands where operand 1 is 1
1392 when "density" or "boolean" options are available and
1393 "useroption" is not available.
1395 Because the current implementation of this parsing scheme uses
1396 split_string, it requires that '|' and '?' are only used as
1397 delimiters for predicates and required options. */
1400 parse_insn_pattern (const char *in
, insn_pattern
*insn
)
1403 split_rec optionrec
;
1406 init_insn_pattern (insn
);
1408 init_split_rec (&optionrec
);
1409 split_string (&optionrec
, in
, '?', TRUE
);
1410 if (optionrec
.count
== 0)
1412 clear_split_rec (&optionrec
);
1416 init_split_rec (&rec
);
1418 split_string (&rec
, optionrec
.vec
[0], '|', TRUE
);
1422 clear_split_rec (&rec
);
1423 clear_split_rec (&optionrec
);
1427 if (!parse_insn_templ (rec
.vec
[0], &insn
->t
))
1429 clear_split_rec (&rec
);
1430 clear_split_rec (&optionrec
);
1434 for (i
= 1; i
< rec
.count
; i
++)
1436 precond_e
*cond
= (precond_e
*) xmalloc (sizeof (precond_e
));
1438 if (!parse_precond (rec
.vec
[i
], cond
))
1440 clear_split_rec (&rec
);
1441 clear_split_rec (&optionrec
);
1442 clear_insn_pattern (insn
);
1446 /* Append the condition. */
1447 *insn
->preconds
.tail
= cond
;
1448 insn
->preconds
.tail
= &cond
->next
;
1451 for (i
= 1; i
< optionrec
.count
; i
++)
1453 /* Handle the option conditions. */
1455 ReqOption
*req_option
= (ReqOption
*) xmalloc (sizeof (ReqOption
));
1456 req_option
->or_option_terms
= NULL
;
1457 req_option
->next
= NULL
;
1459 if (!parse_option_cond (optionrec
.vec
[i
], req_option
))
1461 clear_split_rec (&rec
);
1462 clear_split_rec (&optionrec
);
1463 clear_insn_pattern (insn
);
1464 clear_req_option_list (&req_option
);
1468 /* Append the condition. */
1469 for (r_p
= &insn
->options
; (*r_p
) != NULL
; r_p
= &(*r_p
)->next
)
1472 (*r_p
) = req_option
;
1475 clear_split_rec (&rec
);
1476 clear_split_rec (&optionrec
);
1482 parse_insn_repl (const char *in
, insn_repl
*r_p
)
1484 /* This is a list of instruction templates separated by ';'. */
1488 split_string (&rec
, in
, ';', TRUE
);
1490 for (i
= 0; i
< rec
.count
; i
++)
1492 insn_repl_e
*e
= (insn_repl_e
*) xmalloc (sizeof (insn_repl_e
));
1496 if (!parse_insn_templ (rec
.vec
[i
], &e
->t
))
1499 clear_insn_repl (r_p
);
1503 r_p
->tail
= &e
->next
;
1510 transition_applies (insn_pattern
*initial_insn
,
1511 const char *from_string ATTRIBUTE_UNUSED
,
1512 const char *to_string ATTRIBUTE_UNUSED
)
1514 ReqOption
*req_option
;
1516 for (req_option
= initial_insn
->options
;
1518 req_option
= req_option
->next
)
1520 ReqOrOption
*req_or_option
= req_option
->or_option_terms
;
1522 if (req_or_option
== NULL
1523 || req_or_option
->next
!= NULL
)
1526 if (strncmp (req_or_option
->option_name
, "IsaUse", 6) == 0)
1528 bfd_boolean option_available
= FALSE
;
1529 char *option_name
= req_or_option
->option_name
+ 6;
1530 if (!strcmp (option_name
, "DensityInstruction"))
1531 option_available
= (XCHAL_HAVE_DENSITY
== 1);
1532 else if (!strcmp (option_name
, "L32R"))
1533 option_available
= (XCHAL_HAVE_L32R
== 1);
1534 else if (!strcmp (option_name
, "Const16"))
1535 option_available
= (XCHAL_HAVE_CONST16
== 1);
1536 else if (!strcmp (option_name
, "Loops"))
1537 option_available
= (XCHAL_HAVE_LOOPS
== 1);
1538 else if (!strcmp (option_name
, "WideBranches"))
1539 option_available
= (XCHAL_HAVE_WIDE_BRANCHES
== 1);
1540 else if (!strcmp (option_name
, "PredictedBranches"))
1541 option_available
= (XCHAL_HAVE_PREDICTED_BRANCHES
== 1);
1542 else if (!strcmp (option_name
, "Booleans"))
1543 option_available
= (XCHAL_HAVE_BOOLEANS
== 1);
1545 as_warn (_("invalid configuration option '%s' in transition rule '%s'"),
1546 req_or_option
->option_name
, from_string
);
1547 if ((option_available
^ req_or_option
->is_true
) != 0)
1550 else if (strcmp (req_or_option
->option_name
, "realnop") == 0)
1552 bfd_boolean nop_available
=
1553 (xtensa_opcode_lookup (xtensa_default_isa
, "nop")
1554 != XTENSA_UNDEFINED
);
1555 if ((nop_available
^ req_or_option
->is_true
) != 0)
1564 wide_branch_opcode (const char *opcode_name
,
1566 xtensa_opcode
*popcode
)
1568 xtensa_isa isa
= xtensa_default_isa
;
1569 xtensa_opcode opcode
;
1570 static char wbr_name_buf
[20];
1572 if (strncmp (opcode_name
, "WIDE.", 5) != 0)
1575 strcpy (wbr_name_buf
, opcode_name
+ 5);
1576 strcat (wbr_name_buf
, suffix
);
1577 opcode
= xtensa_opcode_lookup (isa
, wbr_name_buf
);
1578 if (opcode
!= XTENSA_UNDEFINED
)
1588 static TransitionRule
*
1589 build_transition (insn_pattern
*initial_insn
,
1590 insn_repl
*replace_insns
,
1591 const char *from_string
,
1592 const char *to_string
)
1594 TransitionRule
*tr
= NULL
;
1595 xtensa_opcode opcode
;
1596 xtensa_isa isa
= xtensa_default_isa
;
1604 if (!wide_branch_opcode (initial_insn
->t
.opcode_name
, ".w18", &opcode
)
1605 && !wide_branch_opcode (initial_insn
->t
.opcode_name
, ".w15", &opcode
))
1606 opcode
= xtensa_opcode_lookup (isa
, initial_insn
->t
.opcode_name
);
1608 if (opcode
== XTENSA_UNDEFINED
)
1610 /* It is OK to not be able to translate some of these opcodes. */
1615 if (xtensa_opcode_num_operands (isa
, opcode
)
1616 != insn_templ_operand_count (&initial_insn
->t
))
1618 /* This is also OK because there are opcodes that
1619 have different numbers of operands on different
1620 architecture variations. */
1624 tr
= (TransitionRule
*) xmalloc (sizeof (TransitionRule
));
1625 tr
->opcode
= opcode
;
1626 tr
->conditions
= NULL
;
1627 tr
->to_instr
= NULL
;
1629 /* Build the conditions. First, equivalent operand condition.... */
1630 for (op1
= initial_insn
->t
.operand_map
.head
; op1
!= NULL
; op1
= op1
->next
)
1632 for (op2
= op1
->next
; op2
!= NULL
; op2
= op2
->next
)
1634 if (same_operand_name (op1
, op2
))
1636 append_value_condition (tr
, OP_EQUAL
,
1637 op1
->operand_num
, op2
->operand_num
);
1642 /* Now the condition that an operand value must be a constant.... */
1643 for (op1
= initial_insn
->t
.operand_map
.head
; op1
!= NULL
; op1
= op1
->next
)
1645 if (op_is_constant (op1
))
1647 append_constant_value_condition (tr
,
1650 op_get_constant (op1
));
1655 /* Now add the explicit preconditions listed after the "|" in the spec.
1656 These are currently very limited, so we do a special case
1657 parse for them. We expect spaces, opname != opname. */
1658 for (precond
= initial_insn
->preconds
.head
;
1660 precond
= precond
->next
)
1665 if (precond
->opname1
)
1667 op1
= get_opmatch (&initial_insn
->t
.operand_map
, precond
->opname1
);
1669 as_fatal (_("opcode '%s': no bound opname '%s' "
1670 "for precondition in '%s'"),
1671 xtensa_opcode_name (isa
, opcode
),
1672 precond
->opname1
, from_string
);
1675 if (precond
->opname2
)
1677 op2
= get_opmatch (&initial_insn
->t
.operand_map
, precond
->opname2
);
1679 as_fatal (_("opcode '%s': no bound opname '%s' "
1680 "for precondition in %s"),
1681 xtensa_opcode_name (isa
, opcode
),
1682 precond
->opname2
, from_string
);
1685 if (op1
== NULL
&& op2
== NULL
)
1686 as_fatal (_("opcode '%s': precondition only contains "
1687 "constants in '%s'"),
1688 xtensa_opcode_name (isa
, opcode
), from_string
);
1689 else if (op1
!= NULL
&& op2
!= NULL
)
1690 append_value_condition (tr
, precond
->cmpop
,
1691 op1
->operand_num
, op2
->operand_num
);
1692 else if (op2
== NULL
)
1693 append_constant_value_condition (tr
, precond
->cmpop
,
1694 op1
->operand_num
, precond
->opval2
);
1696 append_constant_value_condition (tr
, precond
->cmpop
,
1697 op2
->operand_num
, precond
->opval1
);
1700 tr
->options
= clone_req_option_list (initial_insn
->options
);
1702 /* Generate the replacement instructions. Some of these
1703 "instructions" are actually labels and literals. There can be at
1704 most one literal and at most one label. A literal must be defined
1705 (e.g., "LITERAL %imm") before use (e.g., "%LITERAL"). The labels
1706 can be used before they are defined. Also there are a number of
1707 special operands (e.g., HI24S). */
1709 for (r
= replace_insns
->head
; r
!= NULL
; r
= r
->next
)
1712 const char *opcode_name
;
1715 const char *fn_name
;
1716 const char *operand_arg_name
;
1718 bi
= (BuildInstr
*) xmalloc (sizeof (BuildInstr
));
1719 append_build_insn (tr
, bi
);
1721 bi
->opcode
= XTENSA_UNDEFINED
;
1725 opcode_name
= r
->t
.opcode_name
;
1726 operand_count
= insn_templ_operand_count (&r
->t
);
1728 if (strcmp (opcode_name
, "LITERAL") == 0)
1730 bi
->typ
= INSTR_LITERAL_DEF
;
1731 if (operand_count
!= 1)
1732 as_fatal (_("expected one operand for generated literal"));
1734 else if (strcmp (opcode_name
, "LABEL") == 0)
1736 bi
->typ
= INSTR_LABEL_DEF
;
1737 if (operand_count
!= 0)
1738 as_fatal (_("expected 0 operands for generated label"));
1742 bi
->typ
= INSTR_INSTR
;
1743 if (wide_branch_opcode (opcode_name
, ".w18", &bi
->opcode
)
1744 || wide_branch_opcode (opcode_name
, ".w15", &bi
->opcode
))
1745 opcode_name
= xtensa_opcode_name (isa
, bi
->opcode
);
1747 bi
->opcode
= xtensa_opcode_lookup (isa
, opcode_name
);
1749 if (bi
->opcode
== XTENSA_UNDEFINED
)
1751 as_warn (_("invalid opcode '%s' in transition rule '%s'"),
1752 opcode_name
, to_string
);
1756 /* Check for the right number of ops. */
1757 if (xtensa_opcode_num_operands (isa
, bi
->opcode
)
1758 != (int) operand_count
)
1759 as_fatal (_("opcode '%s': replacement does not have %d ops"),
1761 xtensa_opcode_num_operands (isa
, bi
->opcode
));
1764 for (op
= r
->t
.operand_map
.head
; op
!= NULL
; op
= op
->next
)
1768 if (op_is_constant (op
))
1769 append_constant_op (bi
, op
->operand_num
, op_get_constant (op
));
1770 else if (strcmp (op
->operand_name
, "%LITERAL") == 0)
1771 append_literal_op (bi
, op
->operand_num
);
1772 else if (strcmp (op
->operand_name
, "%LABEL") == 0)
1773 append_label_op (bi
, op
->operand_num
);
1774 else if (op
->operand_name
[0] == 'a'
1775 && parse_constant (op
->operand_name
+ 1, &idnum
))
1776 append_constant_op (bi
, op
->operand_num
, idnum
);
1777 else if (op
->operand_name
[0] == '%')
1779 opname_map_e
*orig_op
;
1780 orig_op
= get_opmatch (&initial_insn
->t
.operand_map
,
1782 if (orig_op
== NULL
)
1783 as_fatal (_("opcode %s: unidentified operand '%s' in '%s'"),
1784 opcode_name
, op
->operand_name
, to_string
);
1785 append_field_op (bi
, op
->operand_num
, orig_op
->operand_num
);
1787 else if (parse_special_fn (op
->operand_name
,
1788 &fn_name
, &operand_arg_name
))
1790 opname_map_e
*orig_op
;
1791 OpType typ
= OP_CONSTANT
;
1793 if (strcmp (fn_name
, "LOW8") == 0)
1794 typ
= OP_OPERAND_LOW8
;
1795 else if (strcmp (fn_name
, "HI24S") == 0)
1796 typ
= OP_OPERAND_HI24S
;
1797 else if (strcmp (fn_name
, "F32MINUS") == 0)
1798 typ
= OP_OPERAND_F32MINUS
;
1799 else if (strcmp (fn_name
, "LOW16U") == 0)
1800 typ
= OP_OPERAND_LOW16U
;
1801 else if (strcmp (fn_name
, "HI16U") == 0)
1802 typ
= OP_OPERAND_HI16U
;
1804 as_fatal (_("unknown user-defined function %s"), fn_name
);
1806 orig_op
= get_opmatch (&initial_insn
->t
.operand_map
,
1808 if (orig_op
== NULL
)
1809 as_fatal (_("opcode %s: unidentified operand '%s' in '%s'"),
1810 opcode_name
, op
->operand_name
, to_string
);
1811 append_user_fn_field_op (bi
, op
->operand_num
,
1812 typ
, orig_op
->operand_num
);
1815 as_fatal (_("opcode %s: could not parse operand '%s' in '%s'"),
1816 opcode_name
, op
->operand_name
, to_string
);
1824 static TransitionTable
*
1825 build_transition_table (const string_pattern_pair
*transitions
,
1826 int transition_count
,
1827 transition_cmp_fn cmp
)
1829 TransitionTable
*table
= NULL
;
1830 int num_opcodes
= xtensa_isa_num_opcodes (xtensa_default_isa
);
1836 /* Otherwise, build it now. */
1837 table
= (TransitionTable
*) xmalloc (sizeof (TransitionTable
));
1838 table
->num_opcodes
= num_opcodes
;
1840 (TransitionList
**) xmalloc (sizeof (TransitionTable
*) * num_opcodes
);
1842 for (i
= 0; i
< num_opcodes
; i
++)
1843 table
->table
[i
] = NULL
;
1845 for (tnum
= 0; tnum
< transition_count
; tnum
++)
1847 const char *from_string
= transitions
[tnum
].pattern
;
1848 const char *to_string
= transitions
[tnum
].replacement
;
1850 insn_pattern initial_insn
;
1851 insn_repl replace_insns
;
1854 init_insn_pattern (&initial_insn
);
1855 if (!parse_insn_pattern (from_string
, &initial_insn
))
1856 as_fatal (_("could not parse INSN_PATTERN '%s'"), from_string
);
1858 init_insn_repl (&replace_insns
);
1859 if (!parse_insn_repl (to_string
, &replace_insns
))
1860 as_fatal (_("could not parse INSN_REPL '%s'"), to_string
);
1862 if (transition_applies (&initial_insn
, from_string
, to_string
))
1864 tr
= build_transition (&initial_insn
, &replace_insns
,
1865 from_string
, to_string
);
1867 append_transition (table
, tr
->opcode
, tr
, cmp
);
1871 as_warn (_("could not build transition for %s => %s"),
1872 from_string
, to_string
);
1877 clear_insn_repl (&replace_insns
);
1878 clear_insn_pattern (&initial_insn
);
1884 extern TransitionTable
*
1885 xg_build_widen_table (transition_cmp_fn cmp
)
1887 static TransitionTable
*table
= NULL
;
1889 table
= build_transition_table (widen_spec_list
, WIDEN_COUNT
, cmp
);
1894 extern TransitionTable
*
1895 xg_build_simplify_table (transition_cmp_fn cmp
)
1897 static TransitionTable
*table
= NULL
;
1899 table
= build_transition_table (simplify_spec_list
, SIMPLIFY_COUNT
, cmp
);