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