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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [binutils-2.20.1/] [cpu/] [frv.opc] - Blame information for rev 841

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

Line No. Rev Author Line
1 205 julius
/* Fujitsu FRV opcode support, for GNU Binutils.  -*- C -*-
2
 
3
   Copyright 2000, 2001, 2003, 2004, 2005, 2007, 2009
4
   Free Software Foundation, Inc.
5
 
6
   Contributed by Red Hat Inc; developed under contract from Fujitsu.
7
 
8
   This file is part of the GNU Binutils.
9
 
10
   This program is free software; you can redistribute it and/or modify
11
   it under the terms of the GNU General Public License as published by
12
   the Free Software Foundation; either version 3 of the License, or
13
   (at your option) any later version.
14
 
15
   This program is distributed in the hope that it will be useful,
16
   but WITHOUT ANY WARRANTY; without even the implied warranty of
17
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
   GNU General Public License for more details.
19
 
20
   You should have received a copy of the GNU General Public License
21
   along with this program; if not, write to the Free Software
22
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
23
   MA 02110-1301, USA.  */
24
 
25
 
26
/* This file is an addendum to frv.cpu.  Heavy use of C code isn't
27
   appropriate in .cpu files, so it resides here.  This especially applies
28
   to assembly/disassembly where parsing/printing can be quite involved.
29
   Such things aren't really part of the specification of the cpu, per se,
30
   so .cpu files provide the general framework and .opc files handle the
31
   nitty-gritty details as necessary.
32
 
33
   Each section is delimited with start and end markers.
34
 
35
   -opc.h additions use: "-- opc.h"
36
   -opc.c additions use: "-- opc.c"
37
   -asm.c additions use: "-- asm.c"
38
   -dis.c additions use: "-- dis.c"
39
   -ibd.h additions use: "-- ibd.h".  */
40
 
41
/* -- opc.h */
42
 
43
#undef  CGEN_DIS_HASH_SIZE
44
#define CGEN_DIS_HASH_SIZE 128
45
#undef  CGEN_DIS_HASH
46
#define CGEN_DIS_HASH(buffer, value) (((value) >> 18) & 127)
47
 
48
/* Allows reason codes to be output when assembler errors occur.  */
49
#define CGEN_VERBOSE_ASSEMBLER_ERRORS
50
 
51
/* Vliw support.  */
52
#define FRV_VLIW_SIZE 8 /* fr550 has largest vliw size of 8.  */
53
#define PAD_VLIW_COMBO ,UNIT_NIL,UNIT_NIL,UNIT_NIL,UNIT_NIL
54
 
55
typedef CGEN_ATTR_VALUE_ENUM_TYPE VLIW_COMBO[FRV_VLIW_SIZE];
56
 
57
typedef struct
58
{
59
  int                    next_slot;
60
  int                    constraint_violation;
61
  unsigned long          mach;
62
  unsigned long          elf_flags;
63
  CGEN_ATTR_VALUE_ENUM_TYPE * unit_mapping;
64
  VLIW_COMBO *           current_vliw;
65
  CGEN_ATTR_VALUE_ENUM_TYPE   major[FRV_VLIW_SIZE];
66
  const CGEN_INSN *      insn[FRV_VLIW_SIZE];
67
} FRV_VLIW;
68
 
69
int frv_is_branch_major (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned long);
70
int frv_is_float_major  (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned long);
71
int frv_is_media_major  (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned long);
72
int frv_is_branch_insn  (const CGEN_INSN *);
73
int frv_is_float_insn   (const CGEN_INSN *);
74
int frv_is_media_insn   (const CGEN_INSN *);
75
void frv_vliw_reset     (FRV_VLIW *, unsigned long, unsigned long);
76
int frv_vliw_add_insn   (FRV_VLIW *, const CGEN_INSN *);
77
int spr_valid           (long);
78
/* -- */
79
 
80
/* -- opc.c */
81
#include "elf/frv.h"
82
#include 
83
 
84
/* Returns TRUE if {MAJOR,MACH} is a major branch of the FRV
85
   development tree.  */
86
 
87
bfd_boolean
88
frv_is_branch_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach)
89
{
90
  switch (mach)
91
    {
92
    case bfd_mach_fr400:
93
      if (major >= FR400_MAJOR_B_1 && major <= FR400_MAJOR_B_6)
94
        return TRUE;
95
      break;
96
    case bfd_mach_fr450:
97
      if (major >= FR450_MAJOR_B_1 && major <= FR450_MAJOR_B_6)
98
        return TRUE;
99
      break;
100
    default:
101
      if (major >= FR500_MAJOR_B_1 && major <= FR500_MAJOR_B_6)
102
        return TRUE;
103
      break;
104
    }
105
 
106
  return FALSE;
107
}
108
 
109
/* Returns TRUE if {MAJOR,MACH} supports floating point insns.  */
110
 
111
bfd_boolean
112
frv_is_float_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach)
113
{
114
  switch (mach)
115
    {
116
    case bfd_mach_fr400:
117
    case bfd_mach_fr450:
118
      return FALSE;
119
    default:
120
      if (major >= FR500_MAJOR_F_1 && major <= FR500_MAJOR_F_8)
121
        return TRUE;
122
      break;
123
    }
124
 
125
  return FALSE;
126
}
127
 
128
/* Returns TRUE if {MAJOR,MACH} supports media insns.  */
129
 
130
bfd_boolean
131
frv_is_media_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach)
132
{
133
  switch (mach)
134
    {
135
    case bfd_mach_fr400:
136
      if (major >= FR400_MAJOR_M_1 && major <= FR400_MAJOR_M_2)
137
        return TRUE;
138
      break;
139
    case bfd_mach_fr450:
140
      if (major >= FR450_MAJOR_M_1 && major <= FR450_MAJOR_M_6)
141
        return TRUE;
142
      break;
143
    default:
144
      if (major >= FR500_MAJOR_M_1 && major <= FR500_MAJOR_M_8)
145
        return TRUE;
146
      break;
147
    }
148
 
149
  return FALSE;
150
}
151
 
152
bfd_boolean
153
frv_is_branch_insn (const CGEN_INSN *insn)
154
{
155
  if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
156
                           bfd_mach_fr400))
157
    return TRUE;
158
  if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
159
                           bfd_mach_fr450))
160
    return TRUE;
161
  if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
162
                           bfd_mach_fr500))
163
    return TRUE;
164
 
165
  return FALSE;
166
}
167
 
168
bfd_boolean
169
frv_is_float_insn (const CGEN_INSN *insn)
170
{
171
  if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
172
                          bfd_mach_fr400))
173
    return TRUE;
174
  if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
175
                          bfd_mach_fr450))
176
    return TRUE;
177
  if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
178
                          bfd_mach_fr500))
179
    return TRUE;
180
 
181
  return FALSE;
182
}
183
 
184
bfd_boolean
185
frv_is_media_insn (const CGEN_INSN *insn)
186
{
187
  if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
188
                          bfd_mach_fr400))
189
    return TRUE;
190
  if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
191
                          bfd_mach_fr450))
192
    return TRUE;
193
  if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
194
                          bfd_mach_fr500))
195
    return TRUE;
196
 
197
  return FALSE;
198
}
199
 
200
/* This table represents the allowable packing for vliw insns for the fr400.
201
   The fr400 has only 2 vliw slots. Represent this by not allowing any insns
202
   in the extra slots.
203
   Subsets of any given row are also allowed.  */
204
static VLIW_COMBO fr400_allowed_vliw[] =
205
{
206
  /*  slot0       slot1       slot2       slot3    */
207
  {  UNIT_I0,    UNIT_I1,    UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
208
  {  UNIT_I0,    UNIT_FM0,   UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
209
  {  UNIT_I0,    UNIT_B0,    UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
210
  {  UNIT_FM0,   UNIT_FM1,   UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
211
  {  UNIT_FM0,   UNIT_B0,    UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
212
  {  UNIT_B0,    UNIT_NIL,   UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
213
  {  UNIT_C,     UNIT_NIL,   UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
214
  {  UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO }
215
};
216
 
217
/* This table represents the allowable packing for vliw insns for the fr500.
218
   The fr500 has only 4 vliw slots. Represent this by not allowing any insns
219
   in the extra slots.
220
   Subsets of any given row are also allowed.  */
221
static VLIW_COMBO fr500_allowed_vliw[] =
222
{
223
  /*  slot0       slot1       slot2       slot3    */
224
  {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1  PAD_VLIW_COMBO },
225
  {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_B0   PAD_VLIW_COMBO },
226
  {  UNIT_I0,    UNIT_FM0,   UNIT_FM1,   UNIT_B0   PAD_VLIW_COMBO },
227
  {  UNIT_I0,    UNIT_FM0,   UNIT_B0,    UNIT_B1   PAD_VLIW_COMBO },
228
  {  UNIT_I0,    UNIT_I1,    UNIT_B0,    UNIT_B1   PAD_VLIW_COMBO },
229
  {  UNIT_I0,    UNIT_B0,    UNIT_B1,    UNIT_NIL  PAD_VLIW_COMBO },
230
  {  UNIT_FM0,   UNIT_FM1,   UNIT_B0,    UNIT_B1   PAD_VLIW_COMBO },
231
  {  UNIT_FM0,   UNIT_B0,    UNIT_B1,    UNIT_NIL  PAD_VLIW_COMBO },
232
  {  UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
233
  {  UNIT_C,     UNIT_NIL,   UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
234
  {  UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO }
235
};
236
 
237
/* This table represents the allowable packing for vliw insns for the fr550.
238
   Subsets of any given row are also allowed.  */
239
static VLIW_COMBO fr550_allowed_vliw[] =
240
{
241
  /*  slot0       slot1       slot2       slot3       slot4       slot5       slot6       slot7   */
242
  {  UNIT_I0,    UNIT_I1,    UNIT_I2,    UNIT_I3,    UNIT_B0,    UNIT_B1 ,   UNIT_NIL,   UNIT_NIL },
243
  {  UNIT_I0,    UNIT_I1,    UNIT_I2,    UNIT_B0,    UNIT_B1 ,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
244
  {  UNIT_I0,    UNIT_I1,    UNIT_B0,    UNIT_B1 ,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
245
  {  UNIT_I0,    UNIT_B0,    UNIT_B1 ,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
246
  {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_I2,    UNIT_FM2,   UNIT_I3,    UNIT_FM3 },
247
  {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_I2,    UNIT_FM2,   UNIT_I3,    UNIT_B0  },
248
  {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_I2,    UNIT_FM2,   UNIT_FM3,   UNIT_B0  },
249
  {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_I2,    UNIT_FM2,   UNIT_B0,    UNIT_B1  },
250
  {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_I2,    UNIT_I3,    UNIT_B0,    UNIT_B1  },
251
  {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_I2,    UNIT_B0,    UNIT_B1,    UNIT_NIL },
252
  {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_FM2,   UNIT_FM3,   UNIT_B0,    UNIT_B1  },
253
  {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_FM2,   UNIT_FM3,   UNIT_B0,    UNIT_B1  },
254
  {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_FM2,   UNIT_B0,    UNIT_B1,    UNIT_NIL },
255
  {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL },
256
  {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_I2,    UNIT_I3,    UNIT_B0,    UNIT_B1,    UNIT_NIL },
257
  {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_I2,    UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL },
258
  {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
259
  {  UNIT_I0,    UNIT_FM0,   UNIT_FM1,   UNIT_FM2,   UNIT_FM3,   UNIT_B0,    UNIT_B1,    UNIT_NIL },
260
  {  UNIT_I0,    UNIT_FM0,   UNIT_FM1,   UNIT_FM2,   UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL },
261
  {  UNIT_I0,    UNIT_FM0,   UNIT_FM1,   UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
262
  {  UNIT_I0,    UNIT_FM0,   UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
263
  {  UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
264
  {  UNIT_C,     UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
265
  {  UNIT_FM0,   UNIT_FM1,   UNIT_FM2,   UNIT_FM3,   UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL },
266
  {  UNIT_FM0,   UNIT_FM1,   UNIT_FM2,   UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
267
  {  UNIT_FM0,   UNIT_FM1,   UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
268
  {  UNIT_FM0,   UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
269
  {  UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL }
270
};
271
 
272
/* Some insns are assigned specialized implementation units which map to
273
   different actual implementation units on different machines.  These
274
   tables perform that mapping.  */
275
static CGEN_ATTR_VALUE_ENUM_TYPE fr400_unit_mapping[] =
276
{
277
/* unit in insn    actual unit */
278
/* NIL      */     UNIT_NIL,
279
/* I0       */     UNIT_I0,
280
/* I1       */     UNIT_I1,
281
/* I01      */     UNIT_I01,
282
/* I2       */     UNIT_NIL, /* no I2 or I3 unit */
283
/* I3       */     UNIT_NIL,
284
/* IALL     */     UNIT_I01, /* only I0 and I1 units */
285
/* FM0      */     UNIT_FM0,
286
/* FM1      */     UNIT_FM1,
287
/* FM01     */     UNIT_FM01,
288
/* FM2      */     UNIT_NIL, /* no F2 or M2 units */
289
/* FM3      */     UNIT_NIL, /* no F3 or M3 units */
290
/* FMALL    */     UNIT_FM01,/* Only F0,F1,M0,M1 units */
291
/* FMLOW    */     UNIT_FM0, /* Only F0,M0 units */
292
/* B0       */     UNIT_B0,  /* branches only in B0 unit.  */
293
/* B1       */     UNIT_B0,
294
/* B01      */     UNIT_B0,
295
/* C        */     UNIT_C,
296
/* MULT-DIV */     UNIT_I0,  /* multiply and divide only in I0  unit.  */
297
/* IACC     */     UNIT_I01, /* iacc multiply       in I0 or I1 unit.  */
298
/* LOAD     */     UNIT_I0,  /* load                only in I0  unit.  */
299
/* STORE    */     UNIT_I0,  /* store               only in I0  unit.  */
300
/* SCAN     */     UNIT_I0,  /* scan                only in I0  unit.  */
301
/* DCPL     */     UNIT_C,   /* dcpl                only in C   unit.  */
302
/* MDUALACC */     UNIT_FM0, /* media dual acc insn only in FM0 unit.  */
303
/* MDCUTSSI */     UNIT_FM0, /* mdcutssi            only in FM0 unit.  */
304
/* MCLRACC-1*/     UNIT_FM0  /* mclracc,A==1   insn only in FM0 unit.  */
305
};
306
 
307
/* Some insns are assigned specialized implementation units which map to
308
   different actual implementation units on different machines.  These
309
   tables perform that mapping.  */
310
static CGEN_ATTR_VALUE_ENUM_TYPE fr450_unit_mapping[] =
311
{
312
/* unit in insn    actual unit */
313
/* NIL      */     UNIT_NIL,
314
/* I0       */     UNIT_I0,
315
/* I1       */     UNIT_I1,
316
/* I01      */     UNIT_I01,
317
/* I2       */     UNIT_NIL, /* no I2 or I3 unit */
318
/* I3       */     UNIT_NIL,
319
/* IALL     */     UNIT_I01, /* only I0 and I1 units */
320
/* FM0      */     UNIT_FM0,
321
/* FM1      */     UNIT_FM1,
322
/* FM01     */     UNIT_FM01,
323
/* FM2      */     UNIT_NIL, /* no F2 or M2 units */
324
/* FM3      */     UNIT_NIL, /* no F3 or M3 units */
325
/* FMALL    */     UNIT_FM01,/* Only F0,F1,M0,M1 units */
326
/* FMLOW    */     UNIT_FM0, /* Only F0,M0 units */
327
/* B0       */     UNIT_B0,  /* branches only in B0 unit.  */
328
/* B1       */     UNIT_B0,
329
/* B01      */     UNIT_B0,
330
/* C        */     UNIT_C,
331
/* MULT-DIV */     UNIT_I0,  /* multiply and divide only in I0  unit.  */
332
/* IACC     */     UNIT_I01, /* iacc multiply       in I0 or I1 unit.  */
333
/* LOAD     */     UNIT_I0,  /* load                only in I0  unit.  */
334
/* STORE    */     UNIT_I0,  /* store               only in I0  unit.  */
335
/* SCAN     */     UNIT_I0,  /* scan                only in I0  unit.  */
336
/* DCPL     */     UNIT_I0,  /* dcpl                only in I0  unit.  */
337
/* MDUALACC */     UNIT_FM0, /* media dual acc insn only in FM0 unit.  */
338
/* MDCUTSSI */     UNIT_FM01, /* mdcutssi           in FM0 or FM1.  */
339
/* MCLRACC-1*/     UNIT_FM0  /* mclracc,A==1   insn only in FM0 unit.  */
340
};
341
 
342
static CGEN_ATTR_VALUE_ENUM_TYPE fr500_unit_mapping[] =
343
{
344
/* unit in insn    actual unit */
345
/* NIL      */     UNIT_NIL,
346
/* I0       */     UNIT_I0,
347
/* I1       */     UNIT_I1,
348
/* I01      */     UNIT_I01,
349
/* I2       */     UNIT_NIL, /* no I2 or I3 unit */
350
/* I3       */     UNIT_NIL,
351
/* IALL     */     UNIT_I01, /* only I0 and I1 units */
352
/* FM0      */     UNIT_FM0,
353
/* FM1      */     UNIT_FM1,
354
/* FM01     */     UNIT_FM01,
355
/* FM2      */     UNIT_NIL, /* no F2 or M2 units */
356
/* FM3      */     UNIT_NIL, /* no F3 or M2 units */
357
/* FMALL    */     UNIT_FM01,/* Only F0,F1,M0,M1 units */
358
/* FMLOW    */     UNIT_FM0, /* Only F0,M0 units */
359
/* B0       */     UNIT_B0,
360
/* B1       */     UNIT_B1,
361
/* B01      */     UNIT_B01,
362
/* C        */     UNIT_C,
363
/* MULT-DIV */     UNIT_I01, /* multiply and divide in I0 or I1 unit.  */
364
/* IACC     */     UNIT_NIL, /* iacc multiply       not implemented */
365
/* LOAD     */     UNIT_I01, /* load                in I0 or I1 unit.  */
366
/* STORE    */     UNIT_I0,  /* store               only in I0 unit.  */
367
/* SCAN     */     UNIT_I01, /* scan                in I0 or I1 unit.  */
368
/* DCPL     */     UNIT_C,   /* dcpl                only in C unit.  */
369
/* MDUALACC */     UNIT_FM0, /* media dual acc insn only in FM0 unit.  */
370
/* MDCUTSSI */     UNIT_FM0, /* mdcutssi            only in FM0 unit.  */
371
/* MCLRACC-1*/     UNIT_FM01 /* mclracc,A==1 in FM0 or FM1 unit.  */
372
};
373
 
374
static CGEN_ATTR_VALUE_ENUM_TYPE fr550_unit_mapping[] =
375
{
376
/* unit in insn    actual unit */
377
/* NIL      */     UNIT_NIL,
378
/* I0       */     UNIT_I0,
379
/* I1       */     UNIT_I1,
380
/* I01      */     UNIT_I01,
381
/* I2       */     UNIT_I2,
382
/* I3       */     UNIT_I3,
383
/* IALL     */     UNIT_IALL,
384
/* FM0      */     UNIT_FM0,
385
/* FM1      */     UNIT_FM1,
386
/* FM01     */     UNIT_FM01,
387
/* FM2      */     UNIT_FM2,
388
/* FM3      */     UNIT_FM3,
389
/* FMALL    */     UNIT_FMALL,
390
/* FMLOW    */     UNIT_FM01, /* Only F0,F1,M0,M1 units */
391
/* B0       */     UNIT_B0,
392
/* B1       */     UNIT_B1,
393
/* B01      */     UNIT_B01,
394
/* C        */     UNIT_C,
395
/* MULT-DIV */     UNIT_I01,  /* multiply and divide in I0 or I1 unit.    */
396
/* IACC     */     UNIT_NIL,  /* iacc multiply       not implemented.     */
397
/* LOAD     */     UNIT_I01,  /* load                in I0 or I1 unit.    */
398
/* STORE    */     UNIT_I01,  /* store               in I0 or I1 unit.    */
399
/* SCAN     */     UNIT_IALL, /* scan                in any integer unit. */
400
/* DCPL     */     UNIT_I0,   /* dcpl                only in I0 unit.     */
401
/* MDUALACC */     UNIT_FMALL,/* media dual acc insn in all media units   */
402
/* MDCUTSSI */     UNIT_FM01, /* mdcutssi            in FM0 or FM1 unit.  */
403
/* MCLRACC-1*/     UNIT_FM01  /* mclracc,A==1 in FM0 or FM1 unit.         */
404
};
405
 
406
void
407
frv_vliw_reset (FRV_VLIW *vliw, unsigned long mach, unsigned long elf_flags)
408
{
409
  vliw->next_slot = 0;
410
  vliw->constraint_violation = 0;
411
  vliw->mach = mach;
412
  vliw->elf_flags = elf_flags;
413
 
414
  switch (mach)
415
    {
416
    case bfd_mach_fr400:
417
      vliw->current_vliw = fr400_allowed_vliw;
418
      vliw->unit_mapping = fr400_unit_mapping;
419
      break;
420
    case bfd_mach_fr450:
421
      vliw->current_vliw = fr400_allowed_vliw;
422
      vliw->unit_mapping = fr450_unit_mapping;
423
      break;
424
    case bfd_mach_fr550:
425
      vliw->current_vliw = fr550_allowed_vliw;
426
      vliw->unit_mapping = fr550_unit_mapping;
427
      break;
428
    default:
429
      vliw->current_vliw = fr500_allowed_vliw;
430
      vliw->unit_mapping = fr500_unit_mapping;
431
      break;
432
    }
433
}
434
 
435
/* Return TRUE if unit1 is a match for unit2.
436
   Unit1 comes from the insn's UNIT attribute. unit2 comes from one of the
437
   *_allowed_vliw tables above.  */
438
static bfd_boolean
439
match_unit (FRV_VLIW *vliw,
440
            CGEN_ATTR_VALUE_ENUM_TYPE unit1, CGEN_ATTR_VALUE_ENUM_TYPE unit2)
441
{
442
  /* Map any specialized implementation units to actual ones.  */
443
  unit1 = vliw->unit_mapping[unit1];
444
 
445
  if (unit1 == unit2)
446
    return TRUE;
447
  if (unit1 < unit2)
448
    return FALSE;
449
 
450
  switch (unit1)
451
    {
452
    case UNIT_I01:
453
    case UNIT_FM01:
454
    case UNIT_B01:
455
      /* The 01 versions of these units are within 2 enums of the 0 or 1
456
         versions.  */
457
      if (unit1 - unit2 <= 2)
458
        return TRUE;
459
      break;
460
    case UNIT_IALL:
461
    case UNIT_FMALL:
462
      /* The ALL versions of these units are within 5 enums of the 0, 1, 2 or 3
463
         versions.  */
464
      if (unit1 - unit2 <= 5)
465
        return TRUE;
466
      break;
467
    default:
468
      break;
469
    }
470
 
471
  return FALSE;
472
}
473
 
474
/* Return TRUE if the vliws match, FALSE otherwise.  */
475
 
476
static bfd_boolean
477
match_vliw (VLIW_COMBO *vliw1, VLIW_COMBO *vliw2, int vliw_size)
478
{
479
  int i;
480
 
481
  for (i = 0; i < vliw_size; ++i)
482
    if ((*vliw1)[i] != (*vliw2)[i])
483
      return FALSE;
484
 
485
  return TRUE;
486
}
487
 
488
/* Find the next vliw vliw in the table that can accomodate the new insn.
489
   If one is found then return it. Otherwise return NULL.  */
490
 
491
static VLIW_COMBO *
492
add_next_to_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE unit)
493
{
494
  int           next    = vliw->next_slot;
495
  VLIW_COMBO    *current = vliw->current_vliw;
496
  VLIW_COMBO    *potential;
497
 
498
  if (next <= 0)
499
    {
500
      fprintf (stderr, "frv-opc.c line %d: bad vliw->next_slot value.\n",
501
               __LINE__);
502
      abort (); /* Should never happen.  */
503
    }
504
 
505
  /* The table is sorted by units allowed within slots, so vliws with
506
     identical starting sequences are together.  */
507
  potential = current;
508
  do
509
    {
510
      if (match_unit (vliw, unit, (*potential)[next]))
511
        return potential;
512
      ++potential;
513
    }
514
  while (match_vliw (potential, current, next));
515
 
516
  return NULL;
517
}
518
 
519
/* Look for the given major insn type in the given vliw.
520
   Returns TRUE if found, FALSE otherwise.  */
521
 
522
static bfd_boolean
523
find_major_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
524
{
525
  int i;
526
 
527
  for (i = 0; i < vliw->next_slot; ++i)
528
    if (vliw->major[i] == major)
529
      return TRUE;
530
 
531
  return FALSE;
532
}
533
 
534
/* Check for constraints between the insns in the vliw due to major insn
535
   types.  */
536
 
537
static bfd_boolean
538
fr400_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
539
{
540
  /* In the cpu file, all media insns are represented as being allowed in
541
     both media units. This makes it easier since this is the case for fr500.
542
     Catch the invalid combinations here.  Insns of major class FR400_MAJOR_M_2
543
     cannot coexist with any other media insn in a vliw.  */
544
  switch (major)
545
    {
546
    case FR400_MAJOR_M_2:
547
      return ! find_major_in_vliw (vliw, FR400_MAJOR_M_1)
548
        &&   ! find_major_in_vliw (vliw, FR400_MAJOR_M_2);
549
    case FR400_MAJOR_M_1:
550
      return ! find_major_in_vliw (vliw, FR400_MAJOR_M_2);
551
    default:
552
      break;
553
    }
554
  return TRUE;
555
}
556
 
557
static bfd_boolean
558
fr450_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
559
{
560
  CGEN_ATTR_VALUE_ENUM_TYPE other_major;
561
 
562
  /* Our caller guarantees there's at least one other instruction.  */
563
  other_major = CGEN_INSN_ATTR_VALUE (vliw->insn[0], CGEN_INSN_FR450_MAJOR);
564
 
565
  /* (M4, M5) and (M4, M6) are allowed.  */
566
  if (other_major == FR450_MAJOR_M_4)
567
    if (major == FR450_MAJOR_M_5 || major == FR450_MAJOR_M_6)
568
      return TRUE;
569
 
570
  /* Otherwise, instructions in even-numbered media categories cannot be
571
     executed in parallel with other media instructions.  */
572
  switch (major)
573
    {
574
    case FR450_MAJOR_M_2:
575
    case FR450_MAJOR_M_4:
576
    case FR450_MAJOR_M_6:
577
      return !(other_major >= FR450_MAJOR_M_1
578
               && other_major <= FR450_MAJOR_M_6);
579
 
580
    case FR450_MAJOR_M_1:
581
    case FR450_MAJOR_M_3:
582
    case FR450_MAJOR_M_5:
583
      return !(other_major == FR450_MAJOR_M_2
584
               || other_major == FR450_MAJOR_M_4
585
               || other_major == FR450_MAJOR_M_6);
586
 
587
    default:
588
      return TRUE;
589
    }
590
}
591
 
592
static bfd_boolean
593
find_unit_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE unit)
594
{
595
  int i;
596
 
597
  for (i = 0; i < vliw->next_slot; ++i)
598
    if (CGEN_INSN_ATTR_VALUE (vliw->insn[i], CGEN_INSN_UNIT) == unit)
599
      return TRUE;
600
 
601
  return FALSE; /* Not found.  */
602
}
603
 
604
static bfd_boolean
605
find_major_in_slot (FRV_VLIW *vliw,
606
                    CGEN_ATTR_VALUE_ENUM_TYPE major,
607
                    CGEN_ATTR_VALUE_ENUM_TYPE slot)
608
{
609
  int i;
610
 
611
  for (i = 0; i < vliw->next_slot; ++i)
612
    if (vliw->major[i] == major && (*vliw->current_vliw)[i] == slot)
613
      return TRUE;
614
 
615
  return FALSE;
616
}
617
 
618
static bfd_boolean
619
fr550_find_media_in_vliw (FRV_VLIW *vliw)
620
{
621
  int i;
622
 
623
  for (i = 0; i < vliw->next_slot; ++i)
624
    {
625
      if (vliw->major[i] < FR550_MAJOR_M_1 || vliw->major[i] > FR550_MAJOR_M_5)
626
        continue;
627
 
628
      /* Found a media insn, however, MNOP and MCLRACC don't count.  */
629
      if (CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MNOP
630
          || CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MCLRACC_0
631
          || CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MCLRACC_1)
632
        continue;
633
 
634
      return TRUE; /* Found one.  */
635
    }
636
 
637
  return FALSE;
638
}
639
 
640
static bfd_boolean
641
fr550_find_float_in_vliw (FRV_VLIW *vliw)
642
{
643
  int i;
644
 
645
  for (i = 0; i < vliw->next_slot; ++i)
646
    {
647
      if (vliw->major[i] < FR550_MAJOR_F_1 || vliw->major[i] > FR550_MAJOR_F_4)
648
        continue;
649
 
650
      /* Found a floating point insn, however, FNOP doesn't count.  */
651
      if (CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_FNOP)
652
        continue;
653
 
654
      return TRUE; /* Found one.  */
655
    }
656
 
657
  return FALSE;
658
}
659
 
660
static bfd_boolean
661
fr550_check_insn_major_constraints (FRV_VLIW *vliw,
662
                                    CGEN_ATTR_VALUE_ENUM_TYPE major,
663
                                    const CGEN_INSN *insn)
664
{
665
  CGEN_ATTR_VALUE_ENUM_TYPE unit;
666
  CGEN_ATTR_VALUE_ENUM_TYPE slot = (*vliw->current_vliw)[vliw->next_slot];
667
  switch (slot)
668
    {
669
    case UNIT_I2:
670
      /* If it's a store, then there must be another store in I1 */
671
      unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT);
672
      if (unit == UNIT_STORE)
673
        return find_unit_in_vliw (vliw, UNIT_STORE);
674
      break;
675
    case UNIT_FM2:
676
    case UNIT_FM3:
677
      /* Floating point insns other than FNOP in slot f2 or f3 cannot coexist
678
         with media insns.  */
679
      if (major >= FR550_MAJOR_F_1 && major <= FR550_MAJOR_F_4
680
          && CGEN_INSN_NUM (insn) != FRV_INSN_FNOP)
681
        return ! fr550_find_media_in_vliw (vliw);
682
      /* Media insns other than MNOP in slot m2 or m3 cannot coexist with
683
         floating point insns.  */
684
      if (major >= FR550_MAJOR_M_1 && major <= FR550_MAJOR_M_5
685
          && CGEN_INSN_NUM (insn) != FRV_INSN_MNOP)
686
        return ! fr550_find_float_in_vliw (vliw);
687
      /* F-2 in slot f2 or f3 cannot coexist with F-2 or F-4 in slot f1 or f2
688
         respectively.  */
689
      if (major == FR550_MAJOR_F_2)
690
        return ! find_major_in_slot (vliw, FR550_MAJOR_F_2,
691
                                     slot - (UNIT_FM2 - UNIT_FM0))
692
          &&   ! find_major_in_slot (vliw, FR550_MAJOR_F_4,
693
                                     slot - (UNIT_FM2 - UNIT_FM0));
694
      /* M-2 or M-5 in slot m2 or m3 cannot coexist with M-2 in slot m1 or m2
695
         respectively.  */
696
      if (major == FR550_MAJOR_M_2 || major == FR550_MAJOR_M_5)
697
        return ! find_major_in_slot (vliw, FR550_MAJOR_M_2,
698
                                     slot - (UNIT_FM2 - UNIT_FM0));
699
      /* M-4 in slot m2 or m3 cannot coexist with M-4 in slot m1 or m2
700
         respectively.  */
701
      if (major == FR550_MAJOR_M_4)
702
        return ! find_major_in_slot (vliw, FR550_MAJOR_M_4,
703
                                     slot - (UNIT_FM2 - UNIT_FM0));
704
      break;
705
    default:
706
      break;
707
    }
708
  return TRUE; /* All OK.  */
709
}
710
 
711
static bfd_boolean
712
fr500_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
713
{
714
  /* TODO: A table might be faster for some of the more complex instances
715
     here.  */
716
  switch (major)
717
    {
718
    case FR500_MAJOR_I_1:
719
    case FR500_MAJOR_I_4:
720
    case FR500_MAJOR_I_5:
721
    case FR500_MAJOR_I_6:
722
    case FR500_MAJOR_B_1:
723
    case FR500_MAJOR_B_2:
724
    case FR500_MAJOR_B_3:
725
    case FR500_MAJOR_B_4:
726
    case FR500_MAJOR_B_5:
727
    case FR500_MAJOR_B_6:
728
    case FR500_MAJOR_F_4:
729
    case FR500_MAJOR_F_8:
730
    case FR500_MAJOR_M_8:
731
      return TRUE; /* OK */
732
    case FR500_MAJOR_I_2:
733
      /* Cannot coexist with I-3 insn.  */
734
      return ! find_major_in_vliw (vliw, FR500_MAJOR_I_3);
735
    case FR500_MAJOR_I_3:
736
      /* Cannot coexist with I-2 insn.  */
737
      return ! find_major_in_vliw (vliw, FR500_MAJOR_I_2);
738
    case FR500_MAJOR_F_1:
739
    case FR500_MAJOR_F_2:
740
      /* Cannot coexist with F-5, F-6, or M-7 insn.  */
741
      return ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
742
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
743
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
744
    case FR500_MAJOR_F_3:
745
      /* Cannot coexist with F-7, or M-7 insn.  */
746
      return ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
747
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
748
    case FR500_MAJOR_F_5:
749
      /* Cannot coexist with F-1, F-2, F-6, F-7, or M-7 insn.  */
750
      return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
751
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
752
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
753
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
754
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
755
    case FR500_MAJOR_F_6:
756
      /* Cannot coexist with F-1, F-2, F-5, F-6, or M-7 insn.  */
757
      return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
758
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
759
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
760
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
761
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
762
    case FR500_MAJOR_F_7:
763
      /* Cannot coexist with F-3, F-5, F-7, or M-7 insn.  */
764
      return ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
765
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
766
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
767
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
768
    case FR500_MAJOR_M_1:
769
      /* Cannot coexist with M-7 insn.  */
770
      return ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
771
    case FR500_MAJOR_M_2:
772
    case FR500_MAJOR_M_3:
773
      /* Cannot coexist with M-5, M-6 or M-7 insn.  */
774
      return ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
775
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
776
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
777
    case FR500_MAJOR_M_4:
778
      /* Cannot coexist with M-6 insn.  */
779
      return ! find_major_in_vliw (vliw, FR500_MAJOR_M_6);
780
    case FR500_MAJOR_M_5:
781
      /* Cannot coexist with M-2, M-3, M-5, M-6  or M-7 insn.  */
782
      return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
783
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
784
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
785
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
786
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
787
    case FR500_MAJOR_M_6:
788
      /* Cannot coexist with M-2, M-3, M-4, M-5, M-6  or M-7 insn.  */
789
      return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
790
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
791
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_4)
792
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
793
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
794
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
795
    case FR500_MAJOR_M_7:
796
      /* Cannot coexist with M-1, M-2, M-3, M-5, M-6  or M-7 insn.  */
797
      return ! find_major_in_vliw (vliw, FR500_MAJOR_M_1)
798
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
799
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
800
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
801
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
802
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7)
803
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
804
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
805
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
806
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
807
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
808
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_7);
809
    default:
810
      fprintf (stderr, "frv-opc.c, line %d: bad major code, aborting.\n",
811
               __LINE__);
812
      abort ();
813
      break;
814
    }
815
  return TRUE;
816
}
817
 
818
static bfd_boolean
819
check_insn_major_constraints (FRV_VLIW *vliw,
820
                              CGEN_ATTR_VALUE_ENUM_TYPE major,
821
                              const CGEN_INSN *insn)
822
{
823
  switch (vliw->mach)
824
    {
825
    case bfd_mach_fr400:
826
      return fr400_check_insn_major_constraints (vliw, major);
827
 
828
    case bfd_mach_fr450:
829
      return fr450_check_insn_major_constraints (vliw, major);
830
 
831
    case bfd_mach_fr550:
832
      return fr550_check_insn_major_constraints (vliw, major, insn);
833
 
834
    default:
835
      return fr500_check_insn_major_constraints (vliw, major);
836
    }
837
}
838
 
839
/* Add in insn to the VLIW vliw if possible.
840
   Return 0 if successful, non-zero otherwise.  */
841
 
842
int
843
frv_vliw_add_insn (FRV_VLIW *vliw, const CGEN_INSN *insn)
844
{
845
  int index;
846
  CGEN_ATTR_VALUE_ENUM_TYPE major;
847
  CGEN_ATTR_VALUE_ENUM_TYPE unit;
848
  VLIW_COMBO *new_vliw;
849
 
850
  if (vliw->constraint_violation || CGEN_INSN_INVALID_P (insn))
851
    return 1;
852
 
853
  index = vliw->next_slot;
854
  if (index >= FRV_VLIW_SIZE)
855
    return 1;
856
 
857
  unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT);
858
  if (unit == UNIT_NIL)
859
    {
860
      fprintf (stderr, "frv-opc.c line %d: bad insn unit.\n",
861
               __LINE__);
862
      abort (); /* No UNIT specified for this insn in frv.cpu.  */
863
    }
864
 
865
  switch (vliw->mach)
866
    {
867
    case bfd_mach_fr400:
868
      major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR);
869
      break;
870
    case bfd_mach_fr450:
871
      major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR);
872
      break;
873
    case bfd_mach_fr550:
874
      major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR550_MAJOR);
875
      break;
876
    default:
877
      major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR);
878
      break;
879
    }
880
 
881
  if (index <= 0)
882
    {
883
      /* Any insn can be added to slot 0.  */
884
      while (! match_unit (vliw, unit, (*vliw->current_vliw)[0]))
885
        ++vliw->current_vliw;
886
      vliw->major[0] = major;
887
      vliw->insn[0] = insn;
888
      vliw->next_slot = 1;
889
      return 0;
890
    }
891
 
892
  /* If there are already insns in the vliw(s) check to see that
893
     this one can be added.  Do this by finding an allowable vliw
894
     combination that can accept the new insn.  */
895
  if (! (vliw->elf_flags & EF_FRV_NOPACK))
896
    {
897
      new_vliw = add_next_to_vliw (vliw, unit);
898
      if (new_vliw && check_insn_major_constraints (vliw, major, insn))
899
        {
900
          vliw->current_vliw = new_vliw;
901
          vliw->major[index] = major;
902
          vliw->insn[index] = insn;
903
          vliw->next_slot++;
904
          return 0;
905
        }
906
 
907
      /* The frv machine supports all packing conbinations.  If we fail,
908
         to add the insn, then it could not be handled as if it was the fr500.
909
         Just return as if it was handled ok.  */
910
      if (vliw->mach == bfd_mach_frv)
911
        return 0;
912
    }
913
 
914
  vliw->constraint_violation = 1;
915
  return 1;
916
}
917
 
918
bfd_boolean
919
spr_valid (long regno)
920
{
921
  if (regno < 0)     return FALSE;
922
  if (regno <= 4095) return TRUE;
923
  return FALSE;
924
}
925
/* -- */
926
 
927
/* -- asm.c */
928
inline static const char *
929
parse_symbolic_address (CGEN_CPU_DESC cd,
930
                        const char **strp,
931
                        int opindex,
932
                        int opinfo,
933
                        enum cgen_parse_operand_result *resultp,
934
                        bfd_vma *valuep)
935
{
936
  enum cgen_parse_operand_result result_type;
937
  const char *errmsg = (* cd->parse_operand_fn)
938
    (cd, CGEN_PARSE_OPERAND_SYMBOLIC, strp, opindex, opinfo,
939
     &result_type, valuep);
940
 
941
  if (errmsg == NULL
942
      && result_type != CGEN_PARSE_OPERAND_RESULT_QUEUED)
943
    return "symbolic expression required";
944
 
945
  if (resultp)
946
    *resultp = result_type;
947
 
948
  return errmsg;
949
}
950
 
951
static const char *
952
parse_ldd_annotation (CGEN_CPU_DESC cd,
953
                      const char **strp,
954
                      int opindex,
955
                      unsigned long *valuep)
956
{
957
  const char *errmsg;
958
  enum cgen_parse_operand_result result_type;
959
  bfd_vma value;
960
 
961
  if (**strp == '#' || **strp == '%')
962
    {
963
      if (strncasecmp (*strp + 1, "tlsdesc(", 8) == 0)
964
        {
965
          *strp += 9;
966
          errmsg = parse_symbolic_address (cd, strp, opindex,
967
                                           BFD_RELOC_FRV_TLSDESC_RELAX,
968
                                           &result_type, &value);
969
          if (**strp != ')')
970
            return "missing ')'";
971
          if (valuep)
972
            *valuep = value;
973
          ++*strp;
974
          if (errmsg)
975
            return errmsg;
976
        }
977
    }
978
 
979
  while (**strp == ' ' || **strp == '\t')
980
    ++*strp;
981
 
982
  if (**strp != '@')
983
    return "missing `@'";
984
 
985
  ++*strp;
986
 
987
  return NULL;
988
}
989
 
990
static const char *
991
parse_call_annotation (CGEN_CPU_DESC cd,
992
                       const char **strp,
993
                       int opindex,
994
                       unsigned long *valuep)
995
{
996
  const char *errmsg;
997
  enum cgen_parse_operand_result result_type;
998
  bfd_vma value;
999
 
1000
  if (**strp == '#' || **strp == '%')
1001
    {
1002
      if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0)
1003
        {
1004
          *strp += 11;
1005
          errmsg = parse_symbolic_address (cd, strp, opindex,
1006
                                           BFD_RELOC_FRV_GETTLSOFF_RELAX,
1007
                                           &result_type, &value);
1008
          if (**strp != ')')
1009
            return "missing ')'";
1010
          if (valuep)
1011
            *valuep = value;
1012
          ++*strp;
1013
          if (errmsg)
1014
            return errmsg;
1015
        }
1016
    }
1017
 
1018
  while (**strp == ' ' || **strp == '\t')
1019
    ++*strp;
1020
 
1021
  if (**strp != '@')
1022
    return "missing `@'";
1023
 
1024
  ++*strp;
1025
 
1026
  return NULL;
1027
}
1028
 
1029
static const char *
1030
parse_ld_annotation (CGEN_CPU_DESC cd,
1031
                     const char **strp,
1032
                     int opindex,
1033
                     unsigned long *valuep)
1034
{
1035
  const char *errmsg;
1036
  enum cgen_parse_operand_result result_type;
1037
  bfd_vma value;
1038
 
1039
  if (**strp == '#' || **strp == '%')
1040
    {
1041
      if (strncasecmp (*strp + 1, "tlsoff(", 7) == 0)
1042
        {
1043
          *strp += 8;
1044
          errmsg = parse_symbolic_address (cd, strp, opindex,
1045
                                           BFD_RELOC_FRV_TLSOFF_RELAX,
1046
                                           &result_type, &value);
1047
          if (**strp != ')')
1048
            return "missing ')'";
1049
          if (valuep)
1050
            *valuep = value;
1051
          ++*strp;
1052
          if (errmsg)
1053
            return errmsg;
1054
        }
1055
    }
1056
 
1057
  while (**strp == ' ' || **strp == '\t')
1058
    ++*strp;
1059
 
1060
  if (**strp != '@')
1061
    return "missing `@'";
1062
 
1063
  ++*strp;
1064
 
1065
  return NULL;
1066
}
1067
 
1068
static const char *
1069
parse_ulo16 (CGEN_CPU_DESC cd,
1070
             const char **strp,
1071
             int opindex,
1072
             unsigned long *valuep)
1073
{
1074
  const char *errmsg;
1075
  enum cgen_parse_operand_result result_type;
1076
  bfd_vma value;
1077
 
1078
  if (**strp == '#' || **strp == '%')
1079
    {
1080
      if (strncasecmp (*strp + 1, "lo(", 3) == 0)
1081
        {
1082
          *strp += 4;
1083
          errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
1084
                                       & result_type, & value);
1085
          if (**strp != ')')
1086
            return "missing `)'";
1087
          ++*strp;
1088
          if (errmsg == NULL
1089
              && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1090
            value &= 0xffff;
1091
          *valuep = value;
1092
          return errmsg;
1093
        }
1094
      if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
1095
        {
1096
          *strp += 9;
1097
          errmsg = parse_symbolic_address (cd, strp, opindex,
1098
                                           BFD_RELOC_FRV_GPRELLO,
1099
                                           & result_type, & value);
1100
          if (**strp != ')')
1101
            return "missing ')'";
1102
          ++*strp;
1103
          *valuep = value;
1104
          return errmsg;
1105
        }
1106
      else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
1107
        {
1108
          *strp += 7;
1109
          errmsg = parse_symbolic_address (cd, strp, opindex,
1110
                                           BFD_RELOC_FRV_GOTLO,
1111
                                           & result_type, & value);
1112
          if (**strp != ')')
1113
            return "missing ')'";
1114
          ++*strp;
1115
          *valuep = value;
1116
          return errmsg;
1117
        }
1118
      else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
1119
        {
1120
          *strp += 15;
1121
          errmsg = parse_symbolic_address (cd, strp, opindex,
1122
                                           BFD_RELOC_FRV_FUNCDESC_GOTLO,
1123
                                           & result_type, & value);
1124
          if (**strp != ')')
1125
            return "missing ')'";
1126
          ++*strp;
1127
          *valuep = value;
1128
          return errmsg;
1129
        }
1130
      else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
1131
        {
1132
          *strp += 10;
1133
          errmsg = parse_symbolic_address (cd, strp, opindex,
1134
                                           BFD_RELOC_FRV_GOTOFFLO,
1135
                                           & result_type, & value);
1136
          if (**strp != ')')
1137
            return "missing ')'";
1138
          ++*strp;
1139
          *valuep = value;
1140
          return errmsg;
1141
        }
1142
      else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
1143
        {
1144
          *strp += 18;
1145
          errmsg = parse_symbolic_address (cd, strp, opindex,
1146
                                           BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
1147
                                           & result_type, & value);
1148
          if (**strp != ')')
1149
            return "missing ')'";
1150
          ++*strp;
1151
          *valuep = value;
1152
          return errmsg;
1153
        }
1154
      else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0)
1155
        {
1156
          *strp += 14;
1157
          errmsg = parse_symbolic_address (cd, strp, opindex,
1158
                                           BFD_RELOC_FRV_GOTTLSDESCLO,
1159
                                           & result_type, & value);
1160
          if (**strp != ')')
1161
            return "missing ')'";
1162
          ++*strp;
1163
          *valuep = value;
1164
          return errmsg;
1165
        }
1166
      else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0)
1167
        {
1168
          *strp += 11;
1169
          errmsg = parse_symbolic_address (cd, strp, opindex,
1170
                                           BFD_RELOC_FRV_TLSMOFFLO,
1171
                                           & result_type, & value);
1172
          if (**strp != ')')
1173
            return "missing ')'";
1174
          ++*strp;
1175
          *valuep = value;
1176
          return errmsg;
1177
        }
1178
      else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0)
1179
        {
1180
          *strp += 13;
1181
          errmsg = parse_symbolic_address (cd, strp, opindex,
1182
                                           BFD_RELOC_FRV_GOTTLSOFFLO,
1183
                                           & result_type, & value);
1184
          if (**strp != ')')
1185
            return "missing ')'";
1186
          ++*strp;
1187
          *valuep = value;
1188
          return errmsg;
1189
        }
1190
    }
1191
  return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
1192
}
1193
 
1194
static const char *
1195
parse_uslo16 (CGEN_CPU_DESC cd,
1196
              const char **strp,
1197
              int opindex,
1198
              signed long *valuep)
1199
{
1200
  const char *errmsg;
1201
  enum cgen_parse_operand_result result_type;
1202
  bfd_vma value;
1203
 
1204
  if (**strp == '#' || **strp == '%')
1205
    {
1206
      if (strncasecmp (*strp + 1, "lo(", 3) == 0)
1207
        {
1208
          *strp += 4;
1209
          errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
1210
                                       & result_type, & value);
1211
          if (**strp != ')')
1212
            return "missing `)'";
1213
          ++*strp;
1214
          if (errmsg == NULL
1215
              && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1216
            value &= 0xffff;
1217
          *valuep = value;
1218
          return errmsg;
1219
        }
1220
      else if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
1221
        {
1222
          *strp += 9;
1223
          errmsg = parse_symbolic_address (cd, strp, opindex,
1224
                                           BFD_RELOC_FRV_GPRELLO,
1225
                                           & result_type, & value);
1226
          if (**strp != ')')
1227
            return "missing ')'";
1228
          ++*strp;
1229
          *valuep = value;
1230
          return errmsg;
1231
        }
1232
      else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
1233
        {
1234
          *strp += 7;
1235
          errmsg = parse_symbolic_address (cd, strp, opindex,
1236
                                           BFD_RELOC_FRV_GOTLO,
1237
                                           & result_type, & value);
1238
          if (**strp != ')')
1239
            return "missing ')'";
1240
          ++*strp;
1241
          *valuep = value;
1242
          return errmsg;
1243
        }
1244
      else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
1245
        {
1246
          *strp += 15;
1247
          errmsg = parse_symbolic_address (cd, strp, opindex,
1248
                                           BFD_RELOC_FRV_FUNCDESC_GOTLO,
1249
                                           & result_type, & value);
1250
          if (**strp != ')')
1251
            return "missing ')'";
1252
          ++*strp;
1253
          *valuep = value;
1254
          return errmsg;
1255
        }
1256
      else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
1257
        {
1258
          *strp += 10;
1259
          errmsg = parse_symbolic_address (cd, strp, opindex,
1260
                                           BFD_RELOC_FRV_GOTOFFLO,
1261
                                           & result_type, & value);
1262
          if (**strp != ')')
1263
            return "missing ')'";
1264
          ++*strp;
1265
          *valuep = value;
1266
          return errmsg;
1267
        }
1268
      else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
1269
        {
1270
          *strp += 18;
1271
          errmsg = parse_symbolic_address (cd, strp, opindex,
1272
                                           BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
1273
                                           & result_type, & value);
1274
          if (**strp != ')')
1275
            return "missing ')'";
1276
          ++*strp;
1277
          *valuep = value;
1278
          return errmsg;
1279
        }
1280
      else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0)
1281
        {
1282
          *strp += 14;
1283
          errmsg = parse_symbolic_address (cd, strp, opindex,
1284
                                           BFD_RELOC_FRV_GOTTLSDESCLO,
1285
                                           & result_type, & value);
1286
          if (**strp != ')')
1287
            return "missing ')'";
1288
          ++*strp;
1289
          *valuep = value;
1290
          return errmsg;
1291
        }
1292
      else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0)
1293
        {
1294
          *strp += 11;
1295
          errmsg = parse_symbolic_address (cd, strp, opindex,
1296
                                           BFD_RELOC_FRV_TLSMOFFLO,
1297
                                           & result_type, & value);
1298
          if (**strp != ')')
1299
            return "missing ')'";
1300
          ++*strp;
1301
          *valuep = value;
1302
          return errmsg;
1303
        }
1304
      else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0)
1305
        {
1306
          *strp += 13;
1307
          errmsg = parse_symbolic_address (cd, strp, opindex,
1308
                                           BFD_RELOC_FRV_GOTTLSOFFLO,
1309
                                           & result_type, & value);
1310
          if (**strp != ')')
1311
            return "missing ')'";
1312
          ++*strp;
1313
          *valuep = value;
1314
          return errmsg;
1315
        }
1316
    }
1317
  return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1318
}
1319
 
1320
static const char *
1321
parse_uhi16 (CGEN_CPU_DESC cd,
1322
             const char **strp,
1323
             int opindex,
1324
             unsigned long *valuep)
1325
{
1326
  const char *errmsg;
1327
  enum cgen_parse_operand_result result_type;
1328
  bfd_vma value;
1329
 
1330
  if (**strp == '#' || **strp == '%')
1331
    {
1332
      if (strncasecmp (*strp + 1, "hi(", 3) == 0)
1333
        {
1334
          *strp += 4;
1335
          errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_HI16,
1336
                                       & result_type, & value);
1337
          if (**strp != ')')
1338
            return "missing `)'";
1339
          ++*strp;
1340
          if (errmsg == NULL
1341
              && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
1342
            {
1343
              /* If bfd_vma is wider than 32 bits, but we have a sign-
1344
                 or zero-extension, truncate it.  */
1345
              if (value >= - ((bfd_vma)1 << 31)
1346
                  || value <= ((bfd_vma)1 << 31) - (bfd_vma)1)
1347
                value &= (((bfd_vma)1 << 16) << 16) - 1;
1348
              value >>= 16;
1349
            }
1350
          *valuep = value;
1351
          return errmsg;
1352
        }
1353
      else if (strncasecmp (*strp + 1, "gprelhi(", 8) == 0)
1354
        {
1355
          *strp += 9;
1356
          errmsg = parse_symbolic_address (cd, strp, opindex,
1357
                                           BFD_RELOC_FRV_GPRELHI,
1358
                                           & result_type, & value);
1359
          if (**strp != ')')
1360
            return "missing ')'";
1361
          ++*strp;
1362
          *valuep = value;
1363
          return errmsg;
1364
        }
1365
      else if (strncasecmp (*strp + 1, "gothi(", 6) == 0)
1366
        {
1367
          *strp += 7;
1368
          errmsg = parse_symbolic_address (cd, strp, opindex,
1369
                                           BFD_RELOC_FRV_GOTHI,
1370
                                           & result_type, & value);
1371
          if (**strp != ')')
1372
            return "missing ')'";
1373
          ++*strp;
1374
          *valuep = value;
1375
          return errmsg;
1376
        }
1377
      else if (strncasecmp (*strp + 1, "gotfuncdeschi(", 14) == 0)
1378
        {
1379
          *strp += 15;
1380
          errmsg = parse_symbolic_address (cd, strp, opindex,
1381
                                           BFD_RELOC_FRV_FUNCDESC_GOTHI,
1382
                                           & result_type, & value);
1383
          if (**strp != ')')
1384
            return "missing ')'";
1385
          ++*strp;
1386
          *valuep = value;
1387
          return errmsg;
1388
        }
1389
      else if (strncasecmp (*strp + 1, "gotoffhi(", 9) == 0)
1390
        {
1391
          *strp += 10;
1392
          errmsg = parse_symbolic_address (cd, strp, opindex,
1393
                                           BFD_RELOC_FRV_GOTOFFHI,
1394
                                           & result_type, & value);
1395
          if (**strp != ')')
1396
            return "missing ')'";
1397
          ++*strp;
1398
          *valuep = value;
1399
          return errmsg;
1400
        }
1401
      else if (strncasecmp (*strp + 1, "gotofffuncdeschi(", 17) == 0)
1402
        {
1403
          *strp += 18;
1404
          errmsg = parse_symbolic_address (cd, strp, opindex,
1405
                                           BFD_RELOC_FRV_FUNCDESC_GOTOFFHI,
1406
                                           & result_type, & value);
1407
          if (**strp != ')')
1408
            return "missing ')'";
1409
          ++*strp;
1410
          *valuep = value;
1411
          return errmsg;
1412
        }
1413
      else if (strncasecmp (*strp + 1, "gottlsdeschi(", 13) == 0)
1414
        {
1415
          *strp += 14;
1416
          errmsg = parse_symbolic_address (cd, strp, opindex,
1417
                                           BFD_RELOC_FRV_GOTTLSDESCHI,
1418
                                           &result_type, &value);
1419
          if (**strp != ')')
1420
            return "missing ')'";
1421
          ++*strp;
1422
          *valuep = value;
1423
          return errmsg;
1424
        }
1425
      else if (strncasecmp (*strp + 1, "tlsmoffhi(", 10) == 0)
1426
        {
1427
          *strp += 11;
1428
          errmsg = parse_symbolic_address (cd, strp, opindex,
1429
                                           BFD_RELOC_FRV_TLSMOFFHI,
1430
                                           & result_type, & value);
1431
          if (**strp != ')')
1432
            return "missing ')'";
1433
          ++*strp;
1434
          *valuep = value;
1435
          return errmsg;
1436
        }
1437
      else if (strncasecmp (*strp + 1, "gottlsoffhi(", 12) == 0)
1438
        {
1439
          *strp += 13;
1440
          errmsg = parse_symbolic_address (cd, strp, opindex,
1441
                                           BFD_RELOC_FRV_GOTTLSOFFHI,
1442
                                           & result_type, & value);
1443
          if (**strp != ')')
1444
            return "missing ')'";
1445
          ++*strp;
1446
          *valuep = value;
1447
          return errmsg;
1448
        }
1449
    }
1450
  return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
1451
}
1452
 
1453
static long
1454
parse_register_number (const char **strp)
1455
{
1456
  int regno;
1457
 
1458
  if (**strp < '0' || **strp > '9')
1459
    return -1; /* error */
1460
 
1461
  regno = **strp - '0';
1462
  for (++*strp; **strp >= '0' && **strp <= '9'; ++*strp)
1463
    regno = regno * 10 + (**strp - '0');
1464
 
1465
  return regno;
1466
}
1467
 
1468
static const char *
1469
parse_spr (CGEN_CPU_DESC cd,
1470
           const char **strp,
1471
           CGEN_KEYWORD * table,
1472
           long *valuep)
1473
{
1474
  const char *save_strp;
1475
  long regno;
1476
 
1477
  /* Check for spr index notation.  */
1478
  if (strncasecmp (*strp, "spr[", 4) == 0)
1479
    {
1480
      *strp += 4;
1481
      regno = parse_register_number (strp);
1482
      if (**strp != ']')
1483
        return _("missing `]'");
1484
      ++*strp;
1485
      if (! spr_valid (regno))
1486
        return _("Special purpose register number is out of range");
1487
      *valuep = regno;
1488
      return NULL;
1489
    }
1490
 
1491
  save_strp = *strp;
1492
  regno = parse_register_number (strp);
1493
  if (regno != -1)
1494
    {
1495
      if (! spr_valid (regno))
1496
        return _("Special purpose register number is out of range");
1497
      *valuep = regno;
1498
      return NULL;
1499
    }
1500
 
1501
  *strp = save_strp;
1502
  return cgen_parse_keyword (cd, strp, table, valuep);
1503
}
1504
 
1505
static const char *
1506
parse_d12 (CGEN_CPU_DESC cd,
1507
           const char **strp,
1508
           int opindex,
1509
           long *valuep)
1510
{
1511
  const char *errmsg;
1512
  enum cgen_parse_operand_result result_type;
1513
  bfd_vma value;
1514
 
1515
  /* Check for small data reference.  */
1516
  if (**strp == '#' || **strp == '%')
1517
    {
1518
      if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
1519
        {
1520
          *strp += 9;
1521
          errmsg = parse_symbolic_address (cd, strp, opindex,
1522
                                           BFD_RELOC_FRV_GPREL12,
1523
                                           & result_type, & value);
1524
          if (**strp != ')')
1525
            return "missing `)'";
1526
          ++*strp;
1527
          *valuep = value;
1528
          return errmsg;
1529
        }
1530
      else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
1531
        {
1532
          *strp += 7;
1533
          errmsg = parse_symbolic_address (cd, strp, opindex,
1534
                                           BFD_RELOC_FRV_GOT12,
1535
                                           & result_type, & value);
1536
          if (**strp != ')')
1537
            return "missing ')'";
1538
          ++*strp;
1539
          *valuep = value;
1540
          return errmsg;
1541
        }
1542
      else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
1543
        {
1544
          *strp += 15;
1545
          errmsg = parse_symbolic_address (cd, strp, opindex,
1546
                                           BFD_RELOC_FRV_FUNCDESC_GOT12,
1547
                                           & result_type, & value);
1548
          if (**strp != ')')
1549
            return "missing ')'";
1550
          ++*strp;
1551
          *valuep = value;
1552
          return errmsg;
1553
        }
1554
      else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
1555
        {
1556
          *strp += 10;
1557
          errmsg = parse_symbolic_address (cd, strp, opindex,
1558
                                           BFD_RELOC_FRV_GOTOFF12,
1559
                                           & result_type, & value);
1560
          if (**strp != ')')
1561
            return "missing ')'";
1562
          ++*strp;
1563
          *valuep = value;
1564
          return errmsg;
1565
        }
1566
      else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
1567
        {
1568
          *strp += 18;
1569
          errmsg = parse_symbolic_address (cd, strp, opindex,
1570
                                           BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
1571
                                           & result_type, & value);
1572
          if (**strp != ')')
1573
            return "missing ')'";
1574
          ++*strp;
1575
          *valuep = value;
1576
          return errmsg;
1577
        }
1578
      else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0)
1579
        {
1580
          *strp += 14;
1581
          errmsg = parse_symbolic_address (cd, strp, opindex,
1582
                                           BFD_RELOC_FRV_GOTTLSDESC12,
1583
                                           & result_type, & value);
1584
          if (**strp != ')')
1585
            return "missing ')'";
1586
          ++*strp;
1587
          *valuep = value;
1588
          return errmsg;
1589
        }
1590
      else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0)
1591
        {
1592
          *strp += 11;
1593
          errmsg = parse_symbolic_address (cd, strp, opindex,
1594
                                           BFD_RELOC_FRV_TLSMOFF12,
1595
                                           & result_type, & value);
1596
          if (**strp != ')')
1597
            return "missing ')'";
1598
          ++*strp;
1599
          *valuep = value;
1600
          return errmsg;
1601
        }
1602
      else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0)
1603
        {
1604
          *strp += 13;
1605
          errmsg = parse_symbolic_address (cd, strp, opindex,
1606
                                           BFD_RELOC_FRV_GOTTLSOFF12,
1607
                                           & result_type, & value);
1608
          if (**strp != ')')
1609
            return "missing ')'";
1610
          ++*strp;
1611
          *valuep = value;
1612
          return errmsg;
1613
        }
1614
    }
1615
  return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1616
}
1617
 
1618
static const char *
1619
parse_s12 (CGEN_CPU_DESC cd,
1620
           const char **strp,
1621
           int opindex,
1622
           long *valuep)
1623
{
1624
  const char *errmsg;
1625
  enum cgen_parse_operand_result result_type;
1626
  bfd_vma value;
1627
 
1628
  /* Check for small data reference.  */
1629
  if (**strp == '#' || **strp == '%')
1630
    {
1631
      if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
1632
        {
1633
          *strp += 9;
1634
          errmsg = parse_symbolic_address (cd, strp, opindex,
1635
                                           BFD_RELOC_FRV_GPREL12,
1636
                                           & result_type, & value);
1637
          if (**strp != ')')
1638
            return "missing `)'";
1639
          ++*strp;
1640
          *valuep = value;
1641
          return errmsg;
1642
        }
1643
      else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
1644
        {
1645
          *strp += 7;
1646
          errmsg = parse_symbolic_address (cd, strp, opindex,
1647
                                           BFD_RELOC_FRV_GOT12,
1648
                                           & result_type, & value);
1649
          if (**strp != ')')
1650
            return "missing ')'";
1651
          ++*strp;
1652
          *valuep = value;
1653
          return errmsg;
1654
        }
1655
      else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
1656
        {
1657
          *strp += 15;
1658
          errmsg = parse_symbolic_address (cd, strp, opindex,
1659
                                           BFD_RELOC_FRV_FUNCDESC_GOT12,
1660
                                           & result_type, & value);
1661
          if (**strp != ')')
1662
            return "missing ')'";
1663
          ++*strp;
1664
          *valuep = value;
1665
          return errmsg;
1666
        }
1667
      else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
1668
        {
1669
          *strp += 10;
1670
          errmsg = parse_symbolic_address (cd, strp, opindex,
1671
                                           BFD_RELOC_FRV_GOTOFF12,
1672
                                           & result_type, & value);
1673
          if (**strp != ')')
1674
            return "missing ')'";
1675
          ++*strp;
1676
          *valuep = value;
1677
          return errmsg;
1678
        }
1679
      else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
1680
        {
1681
          *strp += 18;
1682
          errmsg = parse_symbolic_address (cd, strp, opindex,
1683
                                           BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
1684
                                           & result_type, & value);
1685
          if (**strp != ')')
1686
            return "missing ')'";
1687
          ++*strp;
1688
          *valuep = value;
1689
          return errmsg;
1690
        }
1691
      else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0)
1692
        {
1693
          *strp += 14;
1694
          errmsg = parse_symbolic_address (cd, strp, opindex,
1695
                                           BFD_RELOC_FRV_GOTTLSDESC12,
1696
                                           & result_type, & value);
1697
          if (**strp != ')')
1698
            return "missing ')'";
1699
          ++*strp;
1700
          *valuep = value;
1701
          return errmsg;
1702
        }
1703
      else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0)
1704
        {
1705
          *strp += 11;
1706
          errmsg = parse_symbolic_address (cd, strp, opindex,
1707
                                           BFD_RELOC_FRV_TLSMOFF12,
1708
                                           & result_type, & value);
1709
          if (**strp != ')')
1710
            return "missing ')'";
1711
          ++*strp;
1712
          *valuep = value;
1713
          return errmsg;
1714
        }
1715
      else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0)
1716
        {
1717
          *strp += 13;
1718
          errmsg = parse_symbolic_address (cd, strp, opindex,
1719
                                           BFD_RELOC_FRV_GOTTLSOFF12,
1720
                                           & result_type, & value);
1721
          if (**strp != ')')
1722
            return "missing ')'";
1723
          ++*strp;
1724
          *valuep = value;
1725
          return errmsg;
1726
        }
1727
    }
1728
 
1729
  if (**strp == '#')
1730
    ++*strp;
1731
  return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1732
}
1733
 
1734
static const char *
1735
parse_u12 (CGEN_CPU_DESC cd,
1736
           const char **strp,
1737
           int opindex,
1738
           long *valuep)
1739
{
1740
  const char *errmsg;
1741
  enum cgen_parse_operand_result result_type;
1742
  bfd_vma value;
1743
 
1744
  /* Check for small data reference.  */
1745
  if ((**strp == '#' || **strp == '%')
1746
      && strncasecmp (*strp + 1, "gprel12(", 8) == 0)
1747
    {
1748
      *strp += 9;
1749
      errmsg = parse_symbolic_address (cd, strp, opindex,
1750
                                       BFD_RELOC_FRV_GPRELU12,
1751
                                       & result_type, & value);
1752
      if (**strp != ')')
1753
        return "missing `)'";
1754
      ++*strp;
1755
      *valuep = value;
1756
      return errmsg;
1757
    }
1758
  else
1759
    {
1760
      if (**strp == '#')
1761
        ++*strp;
1762
      return cgen_parse_signed_integer (cd, strp, opindex, valuep);
1763
    }
1764
}
1765
 
1766
static const char *
1767
parse_A (CGEN_CPU_DESC cd,
1768
         const char **strp,
1769
         int opindex,
1770
         unsigned long *valuep,
1771
         unsigned long A)
1772
{
1773
  const char *errmsg;
1774
 
1775
  if (**strp == '#')
1776
    ++*strp;
1777
 
1778
  errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
1779
  if (errmsg)
1780
    return errmsg;
1781
 
1782
  if (*valuep != A)
1783
    return _("Value of A operand must be 0 or 1");
1784
 
1785
  return NULL;
1786
}
1787
 
1788
static const char *
1789
parse_A0 (CGEN_CPU_DESC cd,
1790
          const char **strp,
1791
          int opindex,
1792
          unsigned long *valuep)
1793
{
1794
  return parse_A (cd, strp, opindex, valuep, 0);
1795
}
1796
 
1797
static const char *
1798
parse_A1 (CGEN_CPU_DESC cd,
1799
          const char **strp,
1800
          int opindex,
1801
          unsigned long *valuep)
1802
{
1803
  return parse_A (cd, strp, opindex, valuep, 1);
1804
}
1805
 
1806
static const char *
1807
parse_even_register (CGEN_CPU_DESC  cd,
1808
                     const char **  strP,
1809
                     CGEN_KEYWORD * tableP,
1810
                     long *         valueP)
1811
{
1812
  const char * errmsg;
1813
  const char * saved_star_strP = * strP;
1814
 
1815
  errmsg = cgen_parse_keyword (cd, strP, tableP, valueP);
1816
 
1817
  if (errmsg == NULL && ((* valueP) & 1))
1818
    {
1819
      errmsg = _("register number must be even");
1820
      * strP = saved_star_strP;
1821
    }
1822
 
1823
  return errmsg;
1824
}
1825
 
1826
static const char *
1827
parse_call_label (CGEN_CPU_DESC cd,
1828
                  const char **strp,
1829
                  int opindex,
1830
                  int opinfo,
1831
                  enum cgen_parse_operand_result *resultp,
1832
                  bfd_vma *valuep)
1833
{
1834
  const char *errmsg;
1835
  bfd_vma value;
1836
 
1837
  /* Check for small data reference.  */
1838
  if (opinfo == 0 && (**strp == '#' || **strp == '%'))
1839
    {
1840
      if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0)
1841
        {
1842
          *strp += 11;
1843
          errmsg = parse_symbolic_address (cd, strp, opindex,
1844
                                           BFD_RELOC_FRV_GETTLSOFF,
1845
                                           resultp, &value);
1846
          if (**strp != ')')
1847
            return _("missing `)'");
1848
          ++*strp;
1849
          *valuep = value;
1850
          return errmsg;
1851
        }
1852
    }
1853
 
1854
  return cgen_parse_address (cd, strp, opindex, opinfo, resultp, valuep);
1855
}
1856
 
1857
/* -- */
1858
 
1859
/* -- dis.c */
1860
static void
1861
print_at (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1862
          void * dis_info,
1863
          long reloc_ann ATTRIBUTE_UNUSED,
1864
          long value ATTRIBUTE_UNUSED,
1865
          bfd_vma pc ATTRIBUTE_UNUSED,
1866
          int length ATTRIBUTE_UNUSED)
1867
{
1868
  disassemble_info *info = (disassemble_info *) dis_info;
1869
 
1870
  (*info->fprintf_func) (info->stream, "@");
1871
}
1872
 
1873
static void
1874
print_spr (CGEN_CPU_DESC cd,
1875
           void * dis_info,
1876
           CGEN_KEYWORD *names,
1877
           long regno,
1878
           unsigned int attrs)
1879
{
1880
  /* Use the register index format for any unnamed registers.  */
1881
  if (cgen_keyword_lookup_value (names, regno) == NULL)
1882
    {
1883
      disassemble_info *info = (disassemble_info *) dis_info;
1884
      (*info->fprintf_func) (info->stream, "spr[%ld]", regno);
1885
    }
1886
  else
1887
    print_keyword (cd, dis_info, names, regno, attrs);
1888
}
1889
 
1890
static void
1891
print_hi (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1892
          void * dis_info,
1893
          long value,
1894
          unsigned int attrs ATTRIBUTE_UNUSED,
1895
          bfd_vma pc ATTRIBUTE_UNUSED,
1896
          int length ATTRIBUTE_UNUSED)
1897
{
1898
  disassemble_info *info = (disassemble_info *) dis_info;
1899
 
1900
  (*info->fprintf_func) (info->stream, value ? "0x%lx" : "hi(0x%lx)", value);
1901
}
1902
 
1903
static void
1904
print_lo (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1905
          void * dis_info,
1906
          long value,
1907
          unsigned int attrs ATTRIBUTE_UNUSED,
1908
          bfd_vma pc ATTRIBUTE_UNUSED,
1909
          int length ATTRIBUTE_UNUSED)
1910
{
1911
  disassemble_info *info = (disassemble_info *) dis_info;
1912
  if (value)
1913
    (*info->fprintf_func) (info->stream, "0x%lx", value);
1914
  else
1915
    (*info->fprintf_func) (info->stream, "lo(0x%lx)", value);
1916
}
1917
 
1918
/* -- */

powered by: WebSVN 2.1.0

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