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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [cpu/] [frv.opc] - Blame information for rev 856

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

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

powered by: WebSVN 2.1.0

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