* elf64-ppc.c (ppc_get_stub_entry): Change third param to a
[binutils.git] / gas / config / xtensa-relax.c
blob49a93b20e053adb28def6f1eb4eb18bf6eb9bc43
1 /* Table of relaxations for Xtensa assembly.
2 Copyright 2003 Free Software Foundation, Inc.
4 This file is part of GAS, the GNU Assembler.
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GAS is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GAS; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
19 MA 02111-1307, USA. */
21 /* This file contains the code for generating runtime data structures
22 for relaxation pattern matching from statically specified strings.
23 Each action contains an instruction pattern to match and
24 preconditions for the match as well as an expansion if the pattern
25 matches. The preconditions can specify that two operands are the
26 same or an operand is a specific constant. 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.
30 The patterns match a language like:
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 ::= '==' | '!='
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
47 The operands in a PRECOND must be constants or variables bound by
48 the INSN_PATTERN.
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.
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.
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.
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.
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"}
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. */
83 #include "as.h"
84 #include "xtensa-isa.h"
85 #include "xtensa-relax.h"
86 #include <stddef.h>
88 /* Imported from bfd. */
89 extern xtensa_isa xtensa_default_isa;
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. */
97 typedef struct opname_list_struct opname_list;
98 typedef opname_list opname_e;
100 struct opname_list_struct
102 char *opname;
103 opname_list *next;
106 static opname_list *local_opnames = NULL;
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. */
112 typedef struct opname_map_e_struct opname_map_e;
113 typedef struct opname_map_struct opname_map;
115 struct opname_map_e_struct
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;
123 struct opname_map_struct
125 opname_map_e *head;
126 opname_map_e **tail;
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". */
135 typedef struct precond_e_struct precond_e;
136 typedef struct precond_list_struct precond_list;
138 struct precond_e_struct
140 const char *opname1;
141 unsigned opval1;
142 CmpOp cmpop;
143 const char *opname2;
144 unsigned opval2;
145 precond_e *next;
148 struct precond_list_struct
150 precond_e *head;
151 precond_e **tail;
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. */
159 typedef struct insn_templ_struct insn_templ;
160 struct insn_templ_struct
162 const char *opcode_name;
163 opname_map operand_map;
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. */
171 typedef struct insn_pattern_struct insn_pattern;
172 struct insn_pattern_struct
174 insn_templ t;
175 precond_list preconds;
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. */
184 typedef struct insn_repl_e_struct insn_repl_e;
185 struct insn_repl_e_struct
187 insn_templ t;
188 insn_repl_e *next;
191 typedef struct insn_repl_struct insn_repl;
192 struct insn_repl_struct
194 insn_repl_e *head;
195 insn_repl_e **tail;
199 /* The split_rec is a vector of allocated char * pointers. */
201 typedef struct split_rec_struct split_rec;
202 struct split_rec_struct
204 char **vec;
205 size_t count;
208 /* The "string_pattern_pair" is a set of pairs containing instruction
209 patterns and replacement strings. */
211 typedef struct string_pattern_pair_struct string_pattern_pair;
212 struct string_pattern_pair_struct
214 const char *pattern;
215 const char *replacement;
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
222 encodings. A valid transition may require multiple steps of
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'.
227 addi.n a4, 0x1010
228 => addi a4, 0x1010
229 => addmi a4, 0x1010
230 => addmi a4, 0x1000, addi a4, 0x10. */
232 static string_pattern_pair widen_spec_list[] =
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"},
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"},
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"},
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
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"}
354 #define WIDEN_COUNT (sizeof (widen_spec_list) / sizeof (string_pattern_pair))
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. */
367 string_pattern_pair simplify_spec_list[] =
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"}
385 #define SIMPLIFY_COUNT \
386 (sizeof (simplify_spec_list) / sizeof (string_pattern_pair))
389 /* Transition generation helpers. */
391 static void append_transition
392 PARAMS ((TransitionTable *, xtensa_opcode, TransitionRule *));
393 static void append_condition
394 PARAMS ((TransitionRule *, Precondition *));
395 static void append_value_condition
396 PARAMS ((TransitionRule *, CmpOp, unsigned, unsigned));
397 static void append_constant_value_condition
398 PARAMS ((TransitionRule *, CmpOp, unsigned, unsigned));
399 static void append_build_insn
400 PARAMS ((TransitionRule *, BuildInstr *));
401 static void append_op
402 PARAMS ((BuildInstr *, BuildOp *));
403 static void append_literal_op
404 PARAMS ((BuildInstr *, unsigned, unsigned));
405 static void append_label_op
406 PARAMS ((BuildInstr *, unsigned, unsigned));
407 static void append_constant_op
408 PARAMS ((BuildInstr *, unsigned, unsigned));
409 static void append_field_op
410 PARAMS ((BuildInstr *, unsigned, unsigned));
411 static void append_user_fn_field_op
412 PARAMS ((BuildInstr *, unsigned, OpType, unsigned));
413 static long operand_function_HI24S
414 PARAMS ((long));
415 static long operand_function_F32MINUS
416 PARAMS ((long));
417 static long operand_function_LOW8
418 PARAMS ((long));
420 /* Externally visible functions. */
422 extern bfd_boolean xg_has_userdef_op_fn
423 PARAMS ((OpType));
424 extern long xg_apply_userdef_op_fn
425 PARAMS ((OpType, long));
427 /* Parsing helpers. */
429 static const char *enter_opname_n
430 PARAMS ((const char *, size_t));
431 static const char *enter_opname
432 PARAMS ((const char *));
434 /* Construction and destruction. */
436 static void init_opname_map
437 PARAMS ((opname_map *));
438 static void clear_opname_map
439 PARAMS ((opname_map *));
440 static void init_precond_list
441 PARAMS ((precond_list *));
442 static void clear_precond_list
443 PARAMS ((precond_list *));
444 static void init_insn_templ
445 PARAMS ((insn_templ *));
446 static void clear_insn_templ
447 PARAMS ((insn_templ *));
448 static void init_insn_pattern
449 PARAMS ((insn_pattern *));
450 static void clear_insn_pattern
451 PARAMS ((insn_pattern *));
452 static void init_insn_repl
453 PARAMS ((insn_repl *));
454 static void clear_insn_repl
455 PARAMS ((insn_repl *));
456 static void init_split_rec
457 PARAMS ((split_rec *));
458 static void clear_split_rec
459 PARAMS ((split_rec *));
461 /* Operand and insn_templ helpers. */
463 static bfd_boolean same_operand_name
464 PARAMS ((const opname_map_e *, const opname_map_e *));
465 static opname_map_e *get_opmatch
466 PARAMS ((opname_map *, const char *));
467 static bfd_boolean op_is_constant
468 PARAMS ((const opname_map_e *));
469 static unsigned op_get_constant
470 PARAMS ((const opname_map_e *));
471 static size_t insn_templ_operand_count
472 PARAMS ((const insn_templ *));
474 /* parsing helpers. */
476 static const char *skip_white
477 PARAMS ((const char *));
478 static void trim_whitespace
479 PARAMS ((char *));
480 static void split_string
481 PARAMS ((split_rec *, const char *, char, bfd_boolean));
483 /* Language parsing. */
485 static bfd_boolean parse_insn_pattern
486 PARAMS ((const char *, insn_pattern *));
487 static bfd_boolean parse_insn_repl
488 PARAMS ((const char *, insn_repl *));
489 static bfd_boolean parse_insn_templ
490 PARAMS ((const char *, insn_templ *));
491 static bfd_boolean parse_special_fn
492 PARAMS ((const char *, const char **, const char **));
493 static bfd_boolean parse_precond
494 PARAMS ((const char *, precond_e *));
495 static bfd_boolean parse_constant
496 PARAMS ((const char *, unsigned *));
497 static bfd_boolean parse_id_constant
498 PARAMS ((const char *, const char *, unsigned *));
500 /* Transition table building code. */
502 static TransitionRule *build_transition
503 PARAMS ((insn_pattern *, insn_repl *, const char *, const char *));
504 static TransitionTable *build_transition_table
505 PARAMS ((const string_pattern_pair *, size_t));
508 void
509 append_transition (tt, opcode, t)
510 TransitionTable *tt;
511 xtensa_opcode opcode;
512 TransitionRule *t;
514 TransitionList *tl = (TransitionList *) xmalloc (sizeof (TransitionList));
515 TransitionList *prev;
516 TransitionList *nxt;
517 assert (tt != NULL);
518 assert (opcode < tt->num_opcodes);
520 prev = tt->table[opcode];
521 tl->rule = t;
522 tl->next = NULL;
523 if (prev == NULL)
525 tt->table[opcode] = tl;
526 return;
528 nxt = prev->next;
529 while (nxt != NULL)
531 prev = nxt;
532 nxt = nxt->next;
534 prev->next = tl;
538 void
539 append_condition (tr, cond)
540 TransitionRule *tr;
541 Precondition *cond;
543 PreconditionList *pl =
544 (PreconditionList *) xmalloc (sizeof (PreconditionList));
545 PreconditionList *prev = tr->conditions;
546 PreconditionList *nxt;
548 pl->precond = cond;
549 pl->next = NULL;
550 if (prev == NULL)
552 tr->conditions = pl;
553 return;
555 nxt = prev->next;
556 while (nxt != NULL)
558 prev = nxt;
559 nxt = nxt->next;
561 prev->next = pl;
565 void
566 append_value_condition (tr, cmp, op1, op2)
567 TransitionRule *tr;
568 CmpOp cmp;
569 unsigned op1;
570 unsigned op2;
572 Precondition *cond = (Precondition *) xmalloc (sizeof (Precondition));
574 cond->cmp = cmp;
575 cond->op_num = op1;
576 cond->typ = OP_OPERAND;
577 cond->op_data = op2;
578 append_condition (tr, cond);
582 void
583 append_constant_value_condition (tr, cmp, op1, cnst)
584 TransitionRule *tr;
585 CmpOp cmp;
586 unsigned op1;
587 unsigned cnst;
589 Precondition *cond = (Precondition *) xmalloc (sizeof (Precondition));
591 cond->cmp = cmp;
592 cond->op_num = op1;
593 cond->typ = OP_CONSTANT;
594 cond->op_data = cnst;
595 append_condition (tr, cond);
599 void
600 append_build_insn (tr, bi)
601 TransitionRule *tr;
602 BuildInstr *bi;
604 BuildInstr *prev = tr->to_instr;
605 BuildInstr *nxt;
607 bi->next = NULL;
608 if (prev == NULL)
610 tr->to_instr = bi;
611 return;
613 nxt = prev->next;
614 while (nxt != 0)
616 prev = nxt;
617 nxt = prev->next;
619 prev->next = bi;
623 void
624 append_op (bi, b_op)
625 BuildInstr *bi;
626 BuildOp *b_op;
628 BuildOp *prev = bi->ops;
629 BuildOp *nxt;
631 if (prev == NULL)
633 bi->ops = b_op;
634 return;
636 nxt = prev->next;
637 while (nxt != NULL)
639 prev = nxt;
640 nxt = nxt->next;
642 prev->next = b_op;
646 void
647 append_literal_op (bi, op1, litnum)
648 BuildInstr *bi;
649 unsigned op1;
650 unsigned litnum;
652 BuildOp *b_op = (BuildOp *) xmalloc (sizeof (BuildOp));
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);
662 void
663 append_label_op (bi, op1, labnum)
664 BuildInstr *bi;
665 unsigned op1;
666 unsigned labnum;
668 BuildOp *b_op = (BuildOp *) xmalloc (sizeof (BuildOp));
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);
678 void
679 append_constant_op (bi, op1, cnst)
680 BuildInstr *bi;
681 unsigned op1;
682 unsigned cnst;
684 BuildOp *b_op = (BuildOp *) xmalloc (sizeof (BuildOp));
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);
694 void
695 append_field_op (bi, op1, src_op)
696 BuildInstr *bi;
697 unsigned op1;
698 unsigned src_op;
700 BuildOp *b_op = (BuildOp *) xmalloc (sizeof (BuildOp));
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);
710 /* These could be generated but are not currently. */
712 void
713 append_user_fn_field_op (bi, op1, typ, src_op)
714 BuildInstr *bi;
715 unsigned op1;
716 OpType typ;
717 unsigned src_op;
719 BuildOp *b_op = (BuildOp *) xmalloc (sizeof (BuildOp));
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);
729 /* These operand functions are the semantics of user-defined
730 operand functions. */
732 long
733 operand_function_HI24S (a)
734 long a;
736 if (a & 0x80)
737 return (a & (~0xff)) + 0x100;
738 else
739 return (a & (~0xff));
743 long
744 operand_function_F32MINUS (a)
745 long a;
747 return (32 - a);
751 long
752 operand_function_LOW8 (a)
753 long a;
755 if (a & 0x80)
756 return (a & 0xff) | ~0xff;
757 else
758 return (a & 0xff);
762 bfd_boolean
763 xg_has_userdef_op_fn (op)
764 OpType op;
766 switch (op)
768 case OP_OPERAND_F32MINUS:
769 case OP_OPERAND_LOW8:
770 case OP_OPERAND_HI24S:
771 return TRUE;
772 default:
773 break;
775 return FALSE;
779 long
780 xg_apply_userdef_op_fn (op, a)
781 OpType op;
782 long a;
784 switch (op)
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;
795 return FALSE;
799 /* Generate a transition table. */
801 const char *
802 enter_opname_n (name, len)
803 const char *name;
804 size_t len;
806 opname_e *op;
808 for (op = local_opnames; op != NULL; op = op->next)
810 if (strlen (op->opname) == len && strncmp (op->opname, name, len) == 0)
811 return op->opname;
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;
821 static const char *
822 enter_opname (name)
823 const char *name;
825 opname_e *op;
827 for (op = local_opnames; op != NULL; op = op->next)
829 if (strcmp (op->opname, name) == 0)
830 return op->opname;
832 op = (opname_e *) xmalloc (sizeof (opname_e));
833 op->opname = strdup (name);
834 return op->opname;
838 void
839 init_opname_map (m)
840 opname_map *m;
842 m->head = NULL;
843 m->tail = &m->head;
847 void
848 clear_opname_map (m)
849 opname_map *m;
851 opname_map_e *e;
853 while (m->head != NULL)
855 e = m->head;
856 m->head = e->next;
857 free (e);
859 m->tail = &m->head;
863 static bfd_boolean
864 same_operand_name (m1, m2)
865 const opname_map_e *m1;
866 const opname_map_e *m2;
868 if (m1->operand_name == NULL || m1->operand_name == NULL)
869 return FALSE;
870 return (m1->operand_name == m2->operand_name);
874 opname_map_e *
875 get_opmatch (map, operand_name)
876 opname_map *map;
877 const char *operand_name;
879 opname_map_e *m;
881 for (m = map->head; m != NULL; m = m->next)
883 if (strcmp (m->operand_name, operand_name) == 0)
884 return m;
886 return NULL;
890 bfd_boolean
891 op_is_constant (m1)
892 const opname_map_e *m1;
894 return (m1->operand_name == NULL);
898 static unsigned
899 op_get_constant (m1)
900 const opname_map_e *m1;
902 assert (m1->operand_name == NULL);
903 return m1->constant_value;
907 void
908 init_precond_list (l)
909 precond_list *l;
911 l->head = NULL;
912 l->tail = &l->head;
916 void
917 clear_precond_list (l)
918 precond_list *l;
920 precond_e *e;
922 while (l->head != NULL)
924 e = l->head;
925 l->head = e->next;
926 free (e);
928 l->tail = &l->head;
932 void
933 init_insn_templ (t)
934 insn_templ *t;
936 t->opcode_name = NULL;
937 init_opname_map (&t->operand_map);
941 void
942 clear_insn_templ (t)
943 insn_templ *t;
945 clear_opname_map (&t->operand_map);
949 void
950 init_insn_pattern (p)
951 insn_pattern *p;
953 init_insn_templ (&p->t);
954 init_precond_list (&p->preconds);
958 void
959 clear_insn_pattern (p)
960 insn_pattern *p;
962 clear_insn_templ (&p->t);
963 clear_precond_list (&p->preconds);
967 void
968 init_insn_repl (r)
969 insn_repl *r;
971 r->head = NULL;
972 r->tail = &r->head;
976 void
977 clear_insn_repl (r)
978 insn_repl *r;
980 insn_repl_e *e;
982 while (r->head != NULL)
984 e = r->head;
985 r->head = e->next;
986 clear_insn_templ (&e->t);
988 r->tail = &r->head;
992 static size_t
993 insn_templ_operand_count (t)
994 const insn_templ *t;
996 size_t i = 0;
997 const opname_map_e *op;
999 for (op = t->operand_map.head; op != NULL; op = op->next, ++i)
1001 return i;
1005 /* Convert a string to a number. E.G.: parse_constant("10", &num) */
1007 bfd_boolean
1008 parse_constant (in, val_p)
1009 const char *in;
1010 unsigned *val_p;
1012 unsigned val = 0;
1013 const char *p;
1015 if (in == NULL)
1016 return FALSE;
1017 p = in;
1019 while (*p != '\0')
1021 if (*p >= '0' && *p <= '9')
1022 val = val * 10 + (*p - '0');
1023 else
1024 return FALSE;
1025 ++p;
1027 *val_p = val;
1028 return TRUE;
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. */
1036 bfd_boolean
1037 parse_id_constant (in, name, val_p)
1038 const char *in;
1039 const char *name;
1040 unsigned *val_p;
1042 unsigned namelen = 0;
1043 const char *p;
1045 if (in == NULL)
1046 return FALSE;
1048 if (name != NULL)
1049 namelen = strlen (name);
1051 if (name != NULL && strncmp (in, name, namelen) != 0)
1052 return FALSE;
1054 p = &in[namelen];
1055 return parse_constant (p, val_p);
1059 static bfd_boolean
1060 parse_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;
1065 char *p_start;
1066 const char *p_end;
1068 p_start = strchr (name, '(');
1069 if (p_start == NULL)
1070 return FALSE;
1072 p_end = strchr (p_start, ')');
1074 if (p_end == NULL)
1075 return FALSE;
1077 if (p_end[1] != '\0')
1078 return FALSE;
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;
1086 const char *
1087 skip_white (p)
1088 const char *p;
1090 if (p == NULL)
1091 return p;
1092 while (*p == ' ')
1093 ++p;
1094 return p;
1098 void
1099 trim_whitespace (in)
1100 char *in;
1102 char *last_white = NULL;
1103 char *p = in;
1105 while (p && *p != '\0')
1107 while (*p == ' ')
1109 if (last_white == NULL)
1110 last_white = p;
1111 p++;
1113 if (*p != '\0')
1115 last_white = NULL;
1116 p++;
1119 if (last_white)
1120 *last_white = '\0';
1124 /* Split a string into component strings where "c" is the
1125 delimiter. Place the result in the split_rec. */
1127 void
1128 split_string (rec, in, c, elide_whitespace)
1129 split_rec *rec;
1130 const char *in;
1131 char c;
1132 bfd_boolean elide_whitespace;
1134 size_t cnt = 0;
1135 size_t i;
1136 const char *p = in;
1138 while (p != NULL && *p != '\0')
1140 cnt++;
1141 p = strchr (p, c);
1142 if (p)
1143 p++;
1145 rec->count = cnt;
1146 rec->vec = NULL;
1148 if (rec->count == 0)
1149 return;
1151 rec->vec = (char **) xmalloc (sizeof (char *) * cnt);
1152 for (i = 0; i < cnt; i++)
1153 rec->vec[i] = 0;
1155 p = in;
1156 for (i = 0; i < cnt; i++)
1158 const char *q;
1159 size_t len;
1161 q = p;
1162 if (elide_whitespace)
1163 q = skip_white (q);
1165 p = strchr (q, c);
1166 if (p == NULL)
1167 rec->vec[i] = strdup (q);
1168 else
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++;
1177 if (elide_whitespace)
1178 trim_whitespace (rec->vec[i]);
1183 void
1184 clear_split_rec (rec)
1185 split_rec *rec;
1187 size_t i;
1189 for (i = 0; i < rec->count; ++i)
1190 free (rec->vec[i]);
1192 if (rec->count > 0)
1193 free (rec->vec);
1197 void
1198 init_split_rec (rec)
1199 split_rec *rec;
1201 rec->vec = NULL;
1202 rec->count = 0;
1206 /* Parse an instruction template like "insn op1, op2, op3". */
1208 bfd_boolean
1209 parse_insn_templ (s, t)
1210 const char *s;
1211 insn_templ *t;
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;
1219 init_split_rec (&oprec);
1221 p = skip_white (p);
1222 insn_name_len = strcspn (s, " ");
1223 if (insn_name_len == 0)
1224 return FALSE;
1226 init_insn_templ (t);
1227 t->opcode_name = enter_opname_n (p, insn_name_len);
1229 p = p + insn_name_len;
1231 /* Split by ',' and skip beginning and trailing whitespace. */
1232 split_string (&oprec, p, ',', TRUE);
1234 for (i = 0; i < oprec.count; i++)
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;
1243 /* If it begins with a number, assume that it is a number. */
1244 if (opname && opname[0] >= '0' && opname[0] <= '9')
1246 unsigned val;
1248 if (parse_constant (opname, &val))
1249 e->constant_value = val;
1250 else
1252 free (e);
1253 clear_split_rec (&oprec);
1254 clear_insn_templ (t);
1255 return FALSE;
1258 else
1259 e->operand_name = enter_opname (oprec.vec[i]);
1261 *t->operand_map.tail = e;
1262 t->operand_map.tail = &e->next;
1264 clear_split_rec (&oprec);
1265 return TRUE;
1269 bfd_boolean
1270 parse_precond (s, precond)
1271 const char *s;
1272 precond_e *precond;
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. */
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;
1288 p = skip_white (p);
1290 len = strcspn (p, " !=");
1292 if (len == 0)
1293 return FALSE;
1295 precond->opname1 = enter_opname_n (p, len);
1296 p = p + len;
1297 p = skip_white (p);
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;
1307 p = p + 2;
1308 p = skip_white (p);
1310 /* No trailing whitespace from earlier parsing. */
1311 if (p[0] >= '0' && p[0] <= '9')
1313 unsigned val;
1314 if (parse_constant (p, &val))
1315 precond->opval2 = val;
1316 else
1317 return FALSE;
1319 else
1320 precond->opname2 = enter_opname (p);
1321 return TRUE;
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. */
1330 bfd_boolean
1331 parse_insn_pattern (in, insn)
1332 const char *in;
1333 insn_pattern *insn;
1336 split_rec rec;
1337 size_t i;
1339 init_split_rec (&rec);
1340 init_insn_pattern (insn);
1342 split_string (&rec, in, '|', TRUE);
1344 if (rec.count == 0)
1346 clear_split_rec (&rec);
1347 return FALSE;
1350 if (!parse_insn_templ (rec.vec[0], &insn->t))
1352 clear_split_rec (&rec);
1353 return FALSE;
1356 for (i = 1; i < rec.count; i++)
1358 precond_e *cond = (precond_e *) xmalloc (sizeof (precond_e));
1360 if (!parse_precond (rec.vec[i], cond))
1362 clear_split_rec (&rec);
1363 clear_insn_pattern (insn);
1364 return FALSE;
1367 /* Append the condition. */
1368 *insn->preconds.tail = cond;
1369 insn->preconds.tail = &cond->next;
1372 clear_split_rec (&rec);
1373 return TRUE;
1377 bfd_boolean
1378 parse_insn_repl (in, r_p)
1379 const char *in;
1380 insn_repl *r_p;
1382 /* This is a list of instruction templates separated by ';'. */
1383 split_rec rec;
1384 size_t i;
1386 split_string (&rec, in, ';', TRUE);
1388 for (i = 0; i < rec.count; i++)
1390 insn_repl_e *e = (insn_repl_e *) xmalloc (sizeof (insn_repl_e));
1392 e->next = NULL;
1394 if (!parse_insn_templ (rec.vec[i], &e->t))
1396 free (e);
1397 clear_insn_repl (r_p);
1398 return FALSE;
1400 *r_p->tail = e;
1401 r_p->tail = &e->next;
1403 return TRUE;
1407 TransitionRule *
1408 build_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;
1414 TransitionRule *tr = NULL;
1415 xtensa_opcode opcode;
1416 xtensa_isa isa = xtensa_default_isa;
1418 opname_map_e *op1;
1419 opname_map_e *op2;
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;
1428 opcode = xtensa_opcode_lookup (isa, initial_insn->t.opcode_name);
1429 if (opcode == XTENSA_UNDEFINED)
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;
1440 if (xtensa_num_operands (isa, opcode)
1441 != (int) insn_templ_operand_count (&initial_insn->t))
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;
1455 tr = (TransitionRule *) xmalloc (sizeof (TransitionRule));
1456 tr->opcode = opcode;
1457 tr->conditions = NULL;
1458 tr->to_instr = NULL;
1460 /* Build the conditions. First, equivalent operand condition.... */
1461 for (op1 = initial_insn->t.operand_map.head; op1 != NULL; op1 = op1->next)
1463 for (op2 = op1->next; op2 != NULL; op2 = op2->next)
1465 if (same_operand_name (op1, op2))
1467 append_value_condition (tr, OP_EQUAL,
1468 op1->operand_num, op2->operand_num);
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)
1476 if (op_is_constant (op1))
1478 append_constant_value_condition (tr,
1479 OP_EQUAL,
1480 op1->operand_num,
1481 op_get_constant (op1));
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)
1493 op1 = NULL;
1494 op2 = NULL;
1496 if (precond->opname1)
1498 op1 = get_opmatch (&initial_insn->t.operand_map, precond->opname1);
1499 if (op1 == NULL)
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;
1509 if (precond->opname2)
1511 op2 = get_opmatch (&initial_insn->t.operand_map, precond->opname2);
1512 if (op2 == NULL)
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;
1522 if (op1 == NULL && op2 == NULL)
1524 as_fatal (_("opcode '%s': precondition only contains "
1525 "constants in '%s'"),
1526 xtensa_opcode_name (isa, opcode), from_string);
1527 return NULL;
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);
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). */
1548 for (r = replace_insns->head; r != NULL; r = r->next)
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;
1558 bi = (BuildInstr *) xmalloc (sizeof (BuildInstr));
1559 append_build_insn (tr, bi);
1561 bi->id = 0;
1562 bi->opcode = XTENSA_UNDEFINED;
1563 bi->ops = NULL;
1564 bi->next = NULL;
1566 opcode_name = r->t.opcode_name;
1567 operand_count = insn_templ_operand_count (&r->t);
1569 if (parse_id_constant (opcode_name, "LITERAL", &idnum))
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"));
1580 else if (parse_id_constant (opcode_name, "LABEL", &idnum))
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"));
1590 else
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));
1603 for (op = r->t.operand_map.head; op != NULL; op = op->next)
1605 unsigned idnum;
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))
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);
1617 else if (parse_id_constant (op->operand_name, "%LABEL", &idnum))
1619 has_label = TRUE;
1620 if (idnum > max_label_count)
1621 max_label_count = idnum;
1622 append_label_op (bi, op->operand_num, idnum);
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] == '%')
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)
1633 as_fatal (_("opcode %s: unidentified operand '%s' in '%s'"),
1634 opcode_name, op->operand_name, to_string);
1636 append_constant_op (bi, op->operand_num, 0);
1638 else
1639 append_field_op (bi, op->operand_num, orig_op->operand_num);
1641 else if (parse_special_fn (op->operand_name,
1642 &fn_name, &operand_arg_name))
1644 opname_map_e *orig_op;
1645 OpType typ = OP_CONSTANT;
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);
1656 orig_op = get_opmatch (&initial_insn->t.operand_map,
1657 operand_arg_name);
1658 if (orig_op == NULL)
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);
1664 else
1665 append_user_fn_field_op (bi, op->operand_num,
1666 typ, orig_op->operand_num);
1668 else
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);
1676 if (has_label && max_label_count >= label_count)
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;
1684 return tr;
1688 TransitionTable *
1689 build_transition_table (transitions, transition_count)
1690 const string_pattern_pair *transitions;
1691 size_t transition_count;
1693 TransitionTable *table = NULL;
1694 int num_opcodes = xtensa_num_opcodes (xtensa_default_isa);
1695 int i;
1696 size_t tnum;
1698 if (table != NULL)
1699 return table;
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);
1707 for (i = 0; i < num_opcodes; i++)
1708 table->table[i] = NULL;
1710 for (tnum = 0; tnum < transition_count; tnum++)
1712 const char *from_string = transitions[tnum].pattern;
1713 const char *to_string = transitions[tnum].replacement;
1715 insn_pattern initial_insn;
1716 insn_repl replace_insns;
1717 TransitionRule *tr;
1719 init_insn_pattern (&initial_insn);
1720 if (!parse_insn_pattern (from_string, &initial_insn))
1722 as_fatal (_("could not parse INSN_PATTERN '%s'"), from_string);
1723 clear_insn_pattern (&initial_insn);
1724 continue;
1727 init_insn_repl (&replace_insns);
1728 if (!parse_insn_repl (to_string, &replace_insns))
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;
1736 tr = build_transition (&initial_insn, &replace_insns,
1737 from_string, to_string);
1738 if (tr)
1739 append_transition (table, tr->opcode, tr);
1741 clear_insn_repl (&replace_insns);
1742 clear_insn_pattern (&initial_insn);
1744 return table;
1748 extern TransitionTable *
1749 xg_build_widen_table ()
1751 static TransitionTable *table = NULL;
1752 if (table == NULL)
1753 table = build_transition_table (widen_spec_list, WIDEN_COUNT);
1754 return table;
1758 extern TransitionTable *
1759 xg_build_simplify_table ()
1761 static TransitionTable *table = NULL;
1762 if (table == NULL)
1763 table = build_transition_table (simplify_spec_list, SIMPLIFY_COUNT);
1764 return table;