Add Xtensa port
[deliverable/binutils-gdb.git] / gas / config / xtensa-relax.c
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. */
89 extern 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
97 typedef struct opname_list_struct opname_list;
98 typedef opname_list opname_e;
99
100 struct opname_list_struct
101 {
102 char *opname;
103 opname_list *next;
104 };
105
106 static 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
112 typedef struct opname_map_e_struct opname_map_e;
113 typedef struct opname_map_struct opname_map;
114
115 struct 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
123 struct 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
135 typedef struct precond_e_struct precond_e;
136 typedef struct precond_list_struct precond_list;
137
138 struct 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
148 struct 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
159 typedef struct insn_templ_struct insn_templ;
160 struct 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
171 typedef struct insn_pattern_struct insn_pattern;
172 struct 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
184 typedef struct insn_repl_e_struct insn_repl_e;
185 struct insn_repl_e_struct
186 {
187 insn_templ t;
188 insn_repl_e *next;
189 };
190
191 typedef struct insn_repl_struct insn_repl;
192 struct 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
201 typedef struct split_rec_struct split_rec;
202 struct 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
211 typedef struct string_pattern_pair_struct string_pattern_pair;
212 struct 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
222 encodings. A valid transition may require mutiple 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'.
226
227 addi.n a4, 0x1010
228 => addi a4, 0x1010
229 => addmi a4, 0x1010
230 => addmi a4, 0x1000, addi a4, 0x10. */
231
232 static 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
367 string_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
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));
419
420 /* Externally visible functions. */
421
422 extern bfd_boolean xg_has_userdef_op_fn
423 PARAMS ((OpType));
424 extern long xg_apply_userdef_op_fn
425 PARAMS ((OpType, long));
426
427 /* Parsing helpers. */
428
429 static const char *enter_opname_n
430 PARAMS ((const char *, size_t));
431 static const char *enter_opname
432 PARAMS ((const char *));
433
434 /* Construction and destruction. */
435
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 *));
460
461 /* Operand and insn_templ helpers. */
462
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 *));
473
474 /* parsing helpers. */
475
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));
482
483 /* Language parsing. */
484
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 *));
499
500 /* Transition table building code. */
501
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));
506
507 \f
508 void
509 append_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;
535 return;
536 }
537
538
539 void
540 append_condition (tr, cond)
541 TransitionRule *tr;
542 Precondition *cond;
543 {
544 PreconditionList *pl =
545 (PreconditionList *) xmalloc (sizeof (PreconditionList));
546 PreconditionList *prev = tr->conditions;
547 PreconditionList *nxt;
548
549 pl->precond = cond;
550 pl->next = NULL;
551 if (prev == NULL)
552 {
553 tr->conditions = pl;
554 return;
555 }
556 nxt = prev->next;
557 while (nxt != NULL)
558 {
559 prev = nxt;
560 nxt = nxt->next;
561 }
562 prev->next = pl;
563 }
564
565
566 void
567 append_value_condition (tr, cmp, op1, op2)
568 TransitionRule *tr;
569 CmpOp cmp;
570 unsigned op1;
571 unsigned op2;
572 {
573 Precondition *cond = (Precondition *) xmalloc (sizeof (Precondition));
574
575 cond->cmp = cmp;
576 cond->op_num = op1;
577 cond->typ = OP_OPERAND;
578 cond->op_data = op2;
579 append_condition (tr, cond);
580 }
581
582
583 void
584 append_constant_value_condition (tr, cmp, op1, cnst)
585 TransitionRule *tr;
586 CmpOp cmp;
587 unsigned op1;
588 unsigned cnst;
589 {
590 Precondition *cond = (Precondition *) xmalloc (sizeof (Precondition));
591
592 cond->cmp = cmp;
593 cond->op_num = op1;
594 cond->typ = OP_CONSTANT;
595 cond->op_data = cnst;
596 append_condition (tr, cond);
597 }
598
599
600 void
601 append_build_insn (tr, bi)
602 TransitionRule *tr;
603 BuildInstr *bi;
604 {
605 BuildInstr *prev = tr->to_instr;
606 BuildInstr *nxt;
607
608 bi->next = NULL;
609 if (prev == NULL)
610 {
611 tr->to_instr = bi;
612 return;
613 }
614 nxt = prev->next;
615 while (nxt != 0)
616 {
617 prev = nxt;
618 nxt = prev->next;
619 }
620 prev->next = bi;
621 }
622
623
624 void
625 append_op (bi, b_op)
626 BuildInstr *bi;
627 BuildOp *b_op;
628 {
629 BuildOp *prev = bi->ops;
630 BuildOp *nxt;
631
632 if (prev == NULL)
633 {
634 bi->ops = b_op;
635 return;
636 }
637 nxt = prev->next;
638 while (nxt != NULL)
639 {
640 prev = nxt;
641 nxt = nxt->next;
642 }
643 prev->next = b_op;
644 }
645
646
647 void
648 append_literal_op (bi, op1, litnum)
649 BuildInstr *bi;
650 unsigned op1;
651 unsigned litnum;
652 {
653 BuildOp *b_op = (BuildOp *) xmalloc (sizeof (BuildOp));
654
655 b_op->op_num = op1;
656 b_op->typ = OP_LITERAL;
657 b_op->op_data = litnum;
658 b_op->next = NULL;
659 append_op (bi, b_op);
660 }
661
662
663 void
664 append_label_op (bi, op1, labnum)
665 BuildInstr *bi;
666 unsigned op1;
667 unsigned labnum;
668 {
669 BuildOp *b_op = (BuildOp *) xmalloc (sizeof (BuildOp));
670
671 b_op->op_num = op1;
672 b_op->typ = OP_LABEL;
673 b_op->op_data = labnum;
674 b_op->next = NULL;
675 append_op (bi, b_op);
676 }
677
678
679 void
680 append_constant_op (bi, op1, cnst)
681 BuildInstr *bi;
682 unsigned op1;
683 unsigned cnst;
684 {
685 BuildOp *b_op = (BuildOp *) xmalloc (sizeof (BuildOp));
686
687 b_op->op_num = op1;
688 b_op->typ = OP_CONSTANT;
689 b_op->op_data = cnst;
690 b_op->next = NULL;
691 append_op (bi, b_op);
692 }
693
694
695 void
696 append_field_op (bi, op1, src_op)
697 BuildInstr *bi;
698 unsigned op1;
699 unsigned src_op;
700 {
701 BuildOp *b_op = (BuildOp *) xmalloc (sizeof (BuildOp));
702
703 b_op->op_num = op1;
704 b_op->typ = OP_OPERAND;
705 b_op->op_data = src_op;
706 b_op->next = NULL;
707 append_op (bi, b_op);
708 }
709
710
711 /* These could be generated but are not currently. */
712
713 void
714 append_user_fn_field_op (bi, op1, typ, src_op)
715 BuildInstr *bi;
716 unsigned op1;
717 OpType typ;
718 unsigned src_op;
719 {
720 BuildOp *b_op = (BuildOp *) xmalloc (sizeof (BuildOp));
721
722 b_op->op_num = op1;
723 b_op->typ = typ;
724 b_op->op_data = src_op;
725 b_op->next = NULL;
726 append_op (bi, b_op);
727 }
728
729
730 /* These operand functions are the semantics of user-defined
731 operand functions. */
732
733 long
734 operand_function_HI24S (a)
735 long a;
736 {
737 if (a & 0x80)
738 return (a & (~0xff)) + 0x100;
739 else
740 return (a & (~0xff));
741 }
742
743
744 long
745 operand_function_F32MINUS (a)
746 long a;
747 {
748 return (32 - a);
749 }
750
751
752 long
753 operand_function_LOW8 (a)
754 long a;
755 {
756 if (a & 0x80)
757 return (a & 0xff) | ~0xff;
758 else
759 return (a & 0xff);
760 }
761
762
763 bfd_boolean
764 xg_has_userdef_op_fn (op)
765 OpType op;
766 {
767 switch (op)
768 {
769 case OP_OPERAND_F32MINUS:
770 case OP_OPERAND_LOW8:
771 case OP_OPERAND_HI24S:
772 return TRUE;
773 default:
774 break;
775 }
776 return FALSE;
777 }
778
779
780 long
781 xg_apply_userdef_op_fn (op, a)
782 OpType op;
783 long a;
784 {
785 switch (op)
786 {
787 case OP_OPERAND_F32MINUS:
788 return operand_function_F32MINUS (a);
789 case OP_OPERAND_LOW8:
790 return operand_function_LOW8 (a);
791 case OP_OPERAND_HI24S:
792 return operand_function_HI24S (a);
793 default:
794 break;
795 }
796 return FALSE;
797 }
798
799
800 /* Generate a transition table. */
801
802 const char *
803 enter_opname_n (name, len)
804 const char *name;
805 size_t len;
806 {
807 opname_e *op;
808
809 for (op = local_opnames; op != NULL; op = op->next)
810 {
811 if (strlen (op->opname) == len && strncmp (op->opname, name, len) == 0)
812 return op->opname;
813 }
814 op = (opname_e *) xmalloc (sizeof (opname_e));
815 op->opname = (char *) xmalloc (len + 1);
816 strncpy (op->opname, name, len);
817 op->opname[len] = '\0';
818 return op->opname;
819 }
820
821
822 static const char *
823 enter_opname (name)
824 const char *name;
825 {
826 opname_e *op;
827
828 for (op = local_opnames; op != NULL; op = op->next)
829 {
830 if (strcmp (op->opname, name) == 0)
831 return op->opname;
832 }
833 op = (opname_e *) xmalloc (sizeof (opname_e));
834 op->opname = strdup (name);
835 return op->opname;
836 }
837
838
839 void
840 init_opname_map (m)
841 opname_map *m;
842 {
843 m->head = NULL;
844 m->tail = &m->head;
845 }
846
847
848 void
849 clear_opname_map (m)
850 opname_map *m;
851 {
852 opname_map_e *e;
853
854 while (m->head != NULL)
855 {
856 e = m->head;
857 m->head = e->next;
858 free (e);
859 }
860 m->tail = &m->head;
861 }
862
863
864 static bfd_boolean
865 same_operand_name (m1, m2)
866 const opname_map_e *m1;
867 const opname_map_e *m2;
868 {
869 if (m1->operand_name == NULL || m1->operand_name == NULL)
870 return FALSE;
871 return (m1->operand_name == m2->operand_name);
872 }
873
874
875 opname_map_e *
876 get_opmatch (map, operand_name)
877 opname_map *map;
878 const char *operand_name;
879 {
880 opname_map_e *m;
881
882 for (m = map->head; m != NULL; m = m->next)
883 {
884 if (strcmp (m->operand_name, operand_name) == 0)
885 return m;
886 }
887 return NULL;
888 }
889
890
891 bfd_boolean
892 op_is_constant (m1)
893 const opname_map_e *m1;
894 {
895 return (m1->operand_name == NULL);
896 }
897
898
899 static unsigned
900 op_get_constant (m1)
901 const opname_map_e *m1;
902 {
903 assert (m1->operand_name == NULL);
904 return m1->constant_value;
905 }
906
907
908 void
909 init_precond_list (l)
910 precond_list *l;
911 {
912 l->head = NULL;
913 l->tail = &l->head;
914 }
915
916
917 void
918 clear_precond_list (l)
919 precond_list *l;
920 {
921 precond_e *e;
922
923 while (l->head != NULL)
924 {
925 e = l->head;
926 l->head = e->next;
927 free (e);
928 }
929 l->tail = &l->head;
930 }
931
932
933 void
934 init_insn_templ (t)
935 insn_templ *t;
936 {
937 t->opcode_name = NULL;
938 init_opname_map (&t->operand_map);
939 }
940
941
942 void
943 clear_insn_templ (t)
944 insn_templ *t;
945 {
946 clear_opname_map (&t->operand_map);
947 }
948
949
950 void
951 init_insn_pattern (p)
952 insn_pattern *p;
953 {
954 init_insn_templ (&p->t);
955 init_precond_list (&p->preconds);
956 }
957
958
959 void
960 clear_insn_pattern (p)
961 insn_pattern *p;
962 {
963 clear_insn_templ (&p->t);
964 clear_precond_list (&p->preconds);
965 }
966
967
968 void
969 init_insn_repl (r)
970 insn_repl *r;
971 {
972 r->head = NULL;
973 r->tail = &r->head;
974 }
975
976
977 void
978 clear_insn_repl (r)
979 insn_repl *r;
980 {
981 insn_repl_e *e;
982
983 while (r->head != NULL)
984 {
985 e = r->head;
986 r->head = e->next;
987 clear_insn_templ (&e->t);
988 }
989 r->tail = &r->head;
990 }
991
992
993 static size_t
994 insn_templ_operand_count (t)
995 const insn_templ *t;
996 {
997 size_t i = 0;
998 const opname_map_e *op;
999
1000 for (op = t->operand_map.head; op != NULL; op = op->next, ++i)
1001 ;
1002 return i;
1003 }
1004
1005
1006 /* Convert a string to a number. E.G.: parse_constant("10", &num) */
1007
1008 bfd_boolean
1009 parse_constant (in, val_p)
1010 const char *in;
1011 unsigned *val_p;
1012 {
1013 unsigned val = 0;
1014 const char *p;
1015
1016 if (in == NULL)
1017 return FALSE;
1018 p = in;
1019
1020 while (*p != '\0')
1021 {
1022 if (*p >= '0' && *p <= '9')
1023 val = val * 10 + (*p - '0');
1024 else
1025 return FALSE;
1026 ++p;
1027 }
1028 *val_p = val;
1029 return TRUE;
1030 }
1031
1032
1033 /* Match a pattern like "foo1" with
1034 parse_id_constant("foo1", "foo", &num).
1035 This may also be used to just match a number. */
1036
1037 bfd_boolean
1038 parse_id_constant (in, name, val_p)
1039 const char *in;
1040 const char *name;
1041 unsigned *val_p;
1042 {
1043 unsigned namelen = 0;
1044 const char *p;
1045
1046 if (in == NULL)
1047 return FALSE;
1048
1049 if (name != NULL)
1050 namelen = strlen (name);
1051
1052 if (name != NULL && strncmp (in, name, namelen) != 0)
1053 return FALSE;
1054
1055 p = &in[namelen];
1056 return parse_constant (p, val_p);
1057 }
1058
1059
1060 static bfd_boolean
1061 parse_special_fn (name, fn_name_p, arg_name_p)
1062 const char *name;
1063 const char **fn_name_p;
1064 const char **arg_name_p;
1065 {
1066 char *p_start;
1067 const char *p_end;
1068
1069 p_start = strchr (name, '(');
1070 if (p_start == NULL)
1071 return FALSE;
1072
1073 p_end = strchr (p_start, ')');
1074
1075 if (p_end == NULL)
1076 return FALSE;
1077
1078 if (p_end[1] != '\0')
1079 return FALSE;
1080
1081 *fn_name_p = enter_opname_n (name, p_start - name);
1082 *arg_name_p = enter_opname_n (p_start + 1, p_end - p_start - 1);
1083 return TRUE;
1084 }
1085
1086
1087 const char *
1088 skip_white (p)
1089 const char *p;
1090 {
1091 if (p == NULL)
1092 return p;
1093 while (*p == ' ')
1094 ++p;
1095 return p;
1096 }
1097
1098
1099 void
1100 trim_whitespace (in)
1101 char *in;
1102 {
1103 char *last_white = NULL;
1104 char *p = in;
1105
1106 while (p && *p != '\0')
1107 {
1108 while (*p == ' ')
1109 {
1110 if (last_white == NULL)
1111 last_white = p;
1112 p++;
1113 }
1114 if (*p != '\0')
1115 {
1116 last_white = NULL;
1117 p++;
1118 }
1119 }
1120 if (last_white)
1121 *last_white = '\0';
1122 }
1123
1124
1125 /* Split a string into component strings where "c" is the
1126 delimiter. Place the result in the split_rec. */
1127
1128 void
1129 split_string (rec, in, c, elide_whitespace)
1130 split_rec *rec;
1131 const char *in;
1132 char c;
1133 bfd_boolean elide_whitespace;
1134 {
1135 size_t cnt = 0;
1136 size_t i;
1137 const char *p = in;
1138
1139 while (p != NULL && *p != '\0')
1140 {
1141 cnt++;
1142 p = strchr (p, c);
1143 if (p)
1144 p++;
1145 }
1146 rec->count = cnt;
1147 rec->vec = NULL;
1148
1149 if (rec->count == 0)
1150 return;
1151
1152 rec->vec = (char **) xmalloc (sizeof (char *) * cnt);
1153 for (i = 0; i < cnt; i++)
1154 rec->vec[i] = 0;
1155
1156 p = in;
1157 for (i = 0; i < cnt; i++)
1158 {
1159 const char *q;
1160 size_t len;
1161
1162 q = p;
1163 if (elide_whitespace)
1164 q = skip_white (q);
1165
1166 p = strchr (q, c);
1167 if (p == NULL)
1168 rec->vec[i] = strdup (q);
1169 else
1170 {
1171 len = p - q;
1172 rec->vec[i] = (char *) xmalloc (sizeof (char) * (len + 1));
1173 strncpy (rec->vec[i], q, len);
1174 rec->vec[i][len] = '\0';
1175 p++;
1176 }
1177
1178 if (elide_whitespace)
1179 trim_whitespace (rec->vec[i]);
1180 }
1181 }
1182
1183
1184 void
1185 clear_split_rec (rec)
1186 split_rec *rec;
1187 {
1188 size_t i;
1189
1190 for (i = 0; i < rec->count; ++i)
1191 free (rec->vec[i]);
1192
1193 if (rec->count > 0)
1194 free (rec->vec);
1195 }
1196
1197
1198 void
1199 init_split_rec (rec)
1200 split_rec *rec;
1201 {
1202 rec->vec = NULL;
1203 rec->count = 0;
1204 }
1205
1206
1207 /* Parse an instruction template like "insn op1, op2, op3". */
1208
1209 bfd_boolean
1210 parse_insn_templ (s, t)
1211 const char *s;
1212 insn_templ *t;
1213 {
1214 const char *p = s;
1215 /* First find the first whitespace. */
1216 size_t insn_name_len;
1217 split_rec oprec;
1218 size_t i;
1219
1220 init_split_rec (&oprec);
1221
1222 p = skip_white (p);
1223 insn_name_len = strcspn (s, " ");
1224 if (insn_name_len == 0)
1225 return FALSE;
1226
1227 init_insn_templ (t);
1228 t->opcode_name = enter_opname_n (p, insn_name_len);
1229
1230 p = p + insn_name_len;
1231
1232 /* Split by ',' and skip beginning and trailing whitespace. */
1233 split_string (&oprec, p, ',', TRUE);
1234
1235 for (i = 0; i < oprec.count; i++)
1236 {
1237 const char *opname = oprec.vec[i];
1238 opname_map_e *e = (opname_map_e *) xmalloc (sizeof (opname_map_e));
1239 e->next = NULL;
1240 e->operand_name = NULL;
1241 e->constant_value = 0;
1242 e->operand_num = i;
1243
1244 /* If it begins with a number, assume that it is a number. */
1245 if (opname && opname[0] >= '0' && opname[0] <= '9')
1246 {
1247 unsigned val;
1248
1249 if (parse_constant (opname, &val))
1250 e->constant_value = val;
1251 else
1252 {
1253 free (e);
1254 clear_split_rec (&oprec);
1255 clear_insn_templ (t);
1256 return FALSE;
1257 }
1258 }
1259 else
1260 e->operand_name = enter_opname (oprec.vec[i]);
1261
1262 *t->operand_map.tail = e;
1263 t->operand_map.tail = &e->next;
1264 }
1265 clear_split_rec (&oprec);
1266 return TRUE;
1267 }
1268
1269
1270 bfd_boolean
1271 parse_precond (s, precond)
1272 const char *s;
1273 precond_e *precond;
1274 {
1275 /* All preconditions are currently of the form:
1276 a == b or a != b or a == k (where k is a constant).
1277 Later we may use some special functions like DENSITY == 1
1278 to identify when density is available. */
1279
1280 const char *p = s;
1281 size_t len;
1282 precond->opname1 = NULL;
1283 precond->opval1 = 0;
1284 precond->cmpop = OP_EQUAL;
1285 precond->opname2 = NULL;
1286 precond->opval2 = 0;
1287 precond->next = NULL;
1288
1289 p = skip_white (p);
1290
1291 len = strcspn (p, " !=");
1292
1293 if (len == 0)
1294 return FALSE;
1295
1296 precond->opname1 = enter_opname_n (p, len);
1297 p = p + len;
1298 p = skip_white (p);
1299
1300 /* Check for "==" and "!=". */
1301 if (strncmp (p, "==", 2) == 0)
1302 precond->cmpop = OP_EQUAL;
1303 else if (strncmp (p, "!=", 2) == 0)
1304 precond->cmpop = OP_NOTEQUAL;
1305 else
1306 return FALSE;
1307
1308 p = p + 2;
1309 p = skip_white (p);
1310
1311 /* No trailing whitespace from earlier parsing. */
1312 if (p[0] >= '0' && p[0] <= '9')
1313 {
1314 unsigned val;
1315 if (parse_constant (p, &val))
1316 precond->opval2 = val;
1317 else
1318 return FALSE;
1319 }
1320 else
1321 precond->opname2 = enter_opname (p);
1322 return TRUE;
1323 }
1324
1325
1326 /* Parse a string like:
1327 "insn op1, op2, op3, op4 | op1 != op2 | op2 == op3 | op4 == 1".
1328 I.E., instruction "insn" with 4 operands where operand 1 and 2 are not
1329 the same and operand 2 and 3 are the same and operand 4 is 1. */
1330
1331 bfd_boolean
1332 parse_insn_pattern (in, insn)
1333 const char *in;
1334 insn_pattern *insn;
1335 {
1336
1337 split_rec rec;
1338 size_t i;
1339
1340 init_split_rec (&rec);
1341 init_insn_pattern (insn);
1342
1343 split_string (&rec, in, '|', TRUE);
1344
1345 if (rec.count == 0)
1346 {
1347 clear_split_rec (&rec);
1348 return FALSE;
1349 }
1350
1351 if (!parse_insn_templ (rec.vec[0], &insn->t))
1352 {
1353 clear_split_rec (&rec);
1354 return FALSE;
1355 }
1356
1357 for (i = 1; i < rec.count; i++)
1358 {
1359 precond_e *cond = (precond_e *) xmalloc (sizeof (precond_e));
1360
1361 if (!parse_precond (rec.vec[i], cond))
1362 {
1363 clear_split_rec (&rec);
1364 clear_insn_pattern (insn);
1365 return FALSE;
1366 }
1367
1368 /* Append the condition. */
1369 *insn->preconds.tail = cond;
1370 insn->preconds.tail = &cond->next;
1371 }
1372
1373 clear_split_rec (&rec);
1374 return TRUE;
1375 }
1376
1377
1378 bfd_boolean
1379 parse_insn_repl (in, r_p)
1380 const char *in;
1381 insn_repl *r_p;
1382 {
1383 /* This is a list of instruction templates separated by ';'. */
1384 split_rec rec;
1385 size_t i;
1386
1387 split_string (&rec, in, ';', TRUE);
1388
1389 for (i = 0; i < rec.count; i++)
1390 {
1391 insn_repl_e *e = (insn_repl_e *) xmalloc (sizeof (insn_repl_e));
1392
1393 e->next = NULL;
1394
1395 if (!parse_insn_templ (rec.vec[i], &e->t))
1396 {
1397 free (e);
1398 clear_insn_repl (r_p);
1399 return FALSE;
1400 }
1401 *r_p->tail = e;
1402 r_p->tail = &e->next;
1403 }
1404 return TRUE;
1405 }
1406
1407
1408 TransitionRule *
1409 build_transition (initial_insn, replace_insns, from_string, to_string)
1410 insn_pattern *initial_insn;
1411 insn_repl *replace_insns;
1412 const char *from_string;
1413 const char *to_string;
1414 {
1415 TransitionRule *tr = NULL;
1416 xtensa_opcode opcode;
1417 xtensa_isa isa = xtensa_default_isa;
1418
1419 opname_map_e *op1;
1420 opname_map_e *op2;
1421
1422 precond_e *precond;
1423 insn_repl_e *r;
1424 unsigned label_count = 0;
1425 unsigned max_label_count = 0;
1426 bfd_boolean has_label = FALSE;
1427 unsigned literal_count = 0;
1428
1429 opcode = xtensa_opcode_lookup (isa, initial_insn->t.opcode_name);
1430 if (opcode == XTENSA_UNDEFINED)
1431 {
1432 /* It is OK to not be able to translate some of these opcodes. */
1433 #if 0
1434 as_warn (_("Invalid opcode '%s' in transition rule '%s'\n"),
1435 initial_insn->t.opcode_name, to_string);
1436 #endif
1437 return NULL;
1438 }
1439
1440
1441 if (xtensa_num_operands (isa, opcode)
1442 != (int) insn_templ_operand_count (&initial_insn->t))
1443 {
1444 /* This is also OK because there are opcodes that
1445 have different numbers of operands on different
1446 architecture variations. */
1447 #if 0
1448 as_fatal (_("opcode %s mismatched operand count %d != expected %d"),
1449 xtensa_opcode_name (isa, opcode),
1450 xtensa_num_operands (isa, opcode),
1451 insn_templ_operand_count (&initial_insn->t));
1452 #endif
1453 return NULL;
1454 }
1455
1456 tr = (TransitionRule *) xmalloc (sizeof (TransitionRule));
1457 tr->opcode = opcode;
1458 tr->conditions = NULL;
1459 tr->to_instr = NULL;
1460
1461 /* Build the conditions. First, equivalent operand condition.... */
1462 for (op1 = initial_insn->t.operand_map.head; op1 != NULL; op1 = op1->next)
1463 {
1464 for (op2 = op1->next; op2 != NULL; op2 = op2->next)
1465 {
1466 if (same_operand_name (op1, op2))
1467 {
1468 append_value_condition (tr, OP_EQUAL,
1469 op1->operand_num, op2->operand_num);
1470 }
1471 }
1472 }
1473
1474 /* Now the condition that an operand value must be a constant.... */
1475 for (op1 = initial_insn->t.operand_map.head; op1 != NULL; op1 = op1->next)
1476 {
1477 if (op_is_constant (op1))
1478 {
1479 append_constant_value_condition (tr,
1480 OP_EQUAL,
1481 op1->operand_num,
1482 op_get_constant (op1));
1483 }
1484 }
1485
1486
1487 /* Now add the explicit preconditions listed after the "|" in the spec.
1488 These are currently very limited, so we do a special case
1489 parse for them. We expect spaces, opname != opname. */
1490 for (precond = initial_insn->preconds.head;
1491 precond != NULL;
1492 precond = precond->next)
1493 {
1494 op1 = NULL;
1495 op2 = NULL;
1496
1497 if (precond->opname1)
1498 {
1499 op1 = get_opmatch (&initial_insn->t.operand_map, precond->opname1);
1500 if (op1 == NULL)
1501 {
1502 as_fatal (_("opcode '%s': no bound opname '%s' "
1503 "for precondition in '%s'"),
1504 xtensa_opcode_name (isa, opcode),
1505 precond->opname1, from_string);
1506 return NULL;
1507 }
1508 }
1509
1510 if (precond->opname2)
1511 {
1512 op2 = get_opmatch (&initial_insn->t.operand_map, precond->opname2);
1513 if (op2 == NULL)
1514 {
1515 as_fatal (_("opcode '%s': no bound opname '%s' "
1516 "for precondition in %s"),
1517 xtensa_opcode_name (isa, opcode),
1518 precond->opname2, from_string);
1519 return NULL;
1520 }
1521 }
1522
1523 if (op1 == NULL && op2 == NULL)
1524 {
1525 as_fatal (_("opcode '%s': precondition only contains "
1526 "constants in '%s'"),
1527 xtensa_opcode_name (isa, opcode), from_string);
1528 return NULL;
1529 }
1530 else if (op1 != NULL && op2 != NULL)
1531 append_value_condition (tr, precond->cmpop,
1532 op1->operand_num, op2->operand_num);
1533 else if (op2 == NULL)
1534 append_constant_value_condition (tr, precond->cmpop,
1535 op1->operand_num, precond->opval1);
1536 else
1537 append_constant_value_condition (tr, precond->cmpop,
1538 op2->operand_num, precond->opval2);
1539 }
1540
1541 /* Generate the replacement instructions. Some of these
1542 "instructions" are actually labels and literals. The literals
1543 must be defined in order 0..n and a literal must be defined
1544 (e.g., "LITERAL0 %imm") before use (e.g., "%LITERAL0"). The
1545 labels must be defined in order, but they can be used before they
1546 are defined. Also there are a number of special operands (e.g.,
1547 HI24S). */
1548
1549 for (r = replace_insns->head; r != NULL; r = r->next)
1550 {
1551 BuildInstr *bi;
1552 const char *opcode_name;
1553 size_t operand_count;
1554 opname_map_e *op;
1555 unsigned idnum = 0;
1556 const char *fn_name;
1557 const char *operand_arg_name;
1558
1559 bi = (BuildInstr *) xmalloc (sizeof (BuildInstr));
1560 append_build_insn (tr, bi);
1561
1562 bi->id = 0;
1563 bi->opcode = XTENSA_UNDEFINED;
1564 bi->ops = NULL;
1565 bi->next = NULL;
1566
1567 opcode_name = r->t.opcode_name;
1568 operand_count = insn_templ_operand_count (&r->t);
1569
1570 if (parse_id_constant (opcode_name, "LITERAL", &idnum))
1571 {
1572 bi->typ = INSTR_LITERAL_DEF;
1573 bi->id = idnum;
1574 if (idnum != literal_count)
1575 as_fatal (_("generated literals must be numbered consecutively"));
1576 ++literal_count;
1577 if (operand_count != 1)
1578 as_fatal (_("expected one operand for generated literal"));
1579
1580 }
1581 else if (parse_id_constant (opcode_name, "LABEL", &idnum))
1582 {
1583 bi->typ = INSTR_LABEL_DEF;
1584 bi->id = idnum;
1585 if (idnum != label_count)
1586 as_fatal (_("generated labels must be numbered consecutively"));
1587 ++label_count;
1588 if (operand_count != 0)
1589 as_fatal (_("expected 0 operands for generated label"));
1590 }
1591 else
1592 {
1593 bi->typ = INSTR_INSTR;
1594 bi->opcode = xtensa_opcode_lookup (isa, r->t.opcode_name);
1595 if (bi->opcode == XTENSA_UNDEFINED)
1596 return NULL;
1597 /* Check for the right number of ops. */
1598 if (xtensa_num_operands (isa, bi->opcode)
1599 != (int) operand_count)
1600 as_fatal (_("opcode '%s': replacement does not have %d ops"),
1601 opcode_name, xtensa_num_operands (isa, bi->opcode));
1602 }
1603
1604 for (op = r->t.operand_map.head; op != NULL; op = op->next)
1605 {
1606 unsigned idnum;
1607
1608 if (op_is_constant (op))
1609 append_constant_op (bi, op->operand_num, op_get_constant (op));
1610 else if (parse_id_constant (op->operand_name, "%LITERAL", &idnum))
1611 {
1612 if (idnum >= literal_count)
1613 as_fatal (_("opcode %s: replacement "
1614 "literal %d >= literal_count(%d)"),
1615 opcode_name, idnum, literal_count);
1616 append_literal_op (bi, op->operand_num, idnum);
1617 }
1618 else if (parse_id_constant (op->operand_name, "%LABEL", &idnum))
1619 {
1620 has_label = TRUE;
1621 if (idnum > max_label_count)
1622 max_label_count = idnum;
1623 append_label_op (bi, op->operand_num, idnum);
1624 }
1625 else if (parse_id_constant (op->operand_name, "a", &idnum))
1626 append_constant_op (bi, op->operand_num, idnum);
1627 else if (op->operand_name[0] == '%')
1628 {
1629 opname_map_e *orig_op;
1630 orig_op = get_opmatch (&initial_insn->t.operand_map,
1631 op->operand_name);
1632 if (orig_op == NULL)
1633 {
1634 as_fatal (_("opcode %s: unidentified operand '%s' in '%s'"),
1635 opcode_name, op->operand_name, to_string);
1636
1637 append_constant_op (bi, op->operand_num, 0);
1638 }
1639 else
1640 append_field_op (bi, op->operand_num, orig_op->operand_num);
1641 }
1642 else if (parse_special_fn (op->operand_name,
1643 &fn_name, &operand_arg_name))
1644 {
1645 opname_map_e *orig_op;
1646 OpType typ = OP_CONSTANT;
1647
1648 if (strcmp (fn_name, "LOW8") == 0)
1649 typ = OP_OPERAND_LOW8;
1650 else if (strcmp (fn_name, "HI24S") == 0)
1651 typ = OP_OPERAND_HI24S;
1652 else if (strcmp (fn_name, "F32MINUS") == 0)
1653 typ = OP_OPERAND_F32MINUS;
1654 else
1655 as_fatal (_("unknown user defined function %s"), fn_name);
1656
1657 orig_op = get_opmatch (&initial_insn->t.operand_map,
1658 operand_arg_name);
1659 if (orig_op == NULL)
1660 {
1661 as_fatal (_("opcode %s: unidentified operand '%s' in '%s'"),
1662 opcode_name, op->operand_name, to_string);
1663 append_constant_op (bi, op->operand_num, 0);
1664 }
1665 else
1666 append_user_fn_field_op (bi, op->operand_num,
1667 typ, orig_op->operand_num);
1668 }
1669 else
1670 {
1671 as_fatal (_("opcode %s: could not parse operand '%s' in '%s'"),
1672 opcode_name, op->operand_name, to_string);
1673 append_constant_op (bi, op->operand_num, 0);
1674 }
1675 }
1676 }
1677 if (has_label && max_label_count >= label_count)
1678 {
1679 as_fatal (_("opcode %s: replacement label %d >= label_count(%d)"),
1680 xtensa_opcode_name (isa, opcode),
1681 max_label_count, label_count);
1682 return NULL;
1683 }
1684
1685 return tr;
1686 }
1687
1688
1689 TransitionTable *
1690 build_transition_table (transitions, transition_count)
1691 const string_pattern_pair *transitions;
1692 size_t transition_count;
1693 {
1694 TransitionTable *table = NULL;
1695 int num_opcodes = xtensa_num_opcodes (xtensa_default_isa);
1696 int i;
1697 size_t tnum;
1698
1699 if (table != NULL)
1700 return table;
1701
1702 /* Otherwise, build it now. */
1703 table = (TransitionTable *) xmalloc (sizeof (TransitionTable));
1704 table->num_opcodes = num_opcodes;
1705 table->table =
1706 (TransitionList **) xmalloc (sizeof (TransitionTable *) * num_opcodes);
1707
1708 for (i = 0; i < num_opcodes; i++)
1709 table->table[i] = NULL;
1710
1711 for (tnum = 0; tnum < transition_count; tnum++)
1712 {
1713 const char *from_string = transitions[tnum].pattern;
1714 const char *to_string = transitions[tnum].replacement;
1715
1716 insn_pattern initial_insn;
1717 insn_repl replace_insns;
1718 TransitionRule *tr;
1719
1720 init_insn_pattern (&initial_insn);
1721 if (!parse_insn_pattern (from_string, &initial_insn))
1722 {
1723 as_fatal (_("could not parse INSN_PATTERN '%s'"), from_string);
1724 clear_insn_pattern (&initial_insn);
1725 continue;
1726 }
1727
1728 init_insn_repl (&replace_insns);
1729 if (!parse_insn_repl (to_string, &replace_insns))
1730 {
1731 as_fatal (_("could not parse INSN_REPL '%s'"), to_string);
1732 clear_insn_pattern (&initial_insn);
1733 clear_insn_repl (&replace_insns);
1734 continue;
1735 }
1736
1737 tr = build_transition (&initial_insn, &replace_insns,
1738 from_string, to_string);
1739 if (tr)
1740 append_transition (table, tr->opcode, tr);
1741
1742 clear_insn_repl (&replace_insns);
1743 clear_insn_pattern (&initial_insn);
1744 }
1745 return table;
1746 }
1747
1748 \f
1749 extern TransitionTable *
1750 xg_build_widen_table ()
1751 {
1752 static TransitionTable *table = NULL;
1753 if (table == NULL)
1754 table = build_transition_table (widen_spec_list, WIDEN_COUNT);
1755 return table;
1756 }
1757
1758
1759 extern TransitionTable *
1760 xg_build_simplify_table ()
1761 {
1762 static TransitionTable *table = NULL;
1763 if (table == NULL)
1764 table = build_transition_table (simplify_spec_list, SIMPLIFY_COUNT);
1765 return table;
1766 }
This page took 0.065345 seconds and 5 git commands to generate.