~ubuntu-branches/ubuntu/utopic/binutils-arm64-cross/utopic

« back to all changes in this revision

Viewing changes to binutils-2.23.52.20130611/cpu/frv.opc

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2013-06-20 17:38:09 UTC
  • Revision ID: package-import@ubuntu.com-20130620173809-app8lzgvymy5fg6c
Tags: 0.7
Build-depend on binutils-source (>= 2.23.52.20130620-1~).

Show diffs side-by-side

added added

removed removed

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