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