source: trunk/binutils/gas/config/xtensa-relax.c@ 2562

Last change on this file since 2562 was 607, checked in by bird, 22 years ago

Initial revision

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