OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [gas/] [config/] [xtensa-relax.c] - Blame information for rev 231

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.