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