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
55typedef CGEN_ATTR_VALUE_ENUM_TYPE VLIW_COMBO[FRV_VLIW_SIZE];
56
57typedef 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
69int frv_is_branch_major (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned long);
70int frv_is_float_major  (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned long);
71int frv_is_media_major  (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned long);
72int frv_is_branch_insn  (const CGEN_INSN *);
73int frv_is_float_insn   (const CGEN_INSN *);
74int frv_is_media_insn   (const CGEN_INSN *);
75void frv_vliw_reset     (FRV_VLIW *, unsigned long, unsigned long);
76int frv_vliw_add_insn   (FRV_VLIW *, const CGEN_INSN *);
77int 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
90bfd_boolean
91frv_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
114bfd_boolean
115frv_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
133bfd_boolean
134frv_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
155bfd_boolean
156frv_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
171bfd_boolean
172frv_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
187bfd_boolean
188frv_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.  */
207static 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.  */
224static 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.  */
242static 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.  */
278static 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.  */
313static 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
345static 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
377static 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
409void
410frv_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.  */
441static bfd_boolean
442match_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
479static bfd_boolean
480match_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
494static VLIW_COMBO *
495add_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
525static bfd_boolean
526find_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
540static bfd_boolean
541fr400_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
560static bfd_boolean
561fr450_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
595static bfd_boolean
596find_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
607static bfd_boolean
608find_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
621static bfd_boolean
622fr550_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
643static bfd_boolean
644fr550_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
663static bfd_boolean
664fr550_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
714static bfd_boolean
715fr500_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
821static bfd_boolean
822check_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
845int
846frv_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
921bfd_boolean
922spr_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 */
931inline static const char *
932parse_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
954static const char *
955parse_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
993static const char *
994parse_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
1032static const char *
1033parse_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
1071static const char *
1072parse_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
1197static const char *
1198parse_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
1323static const char *
1324parse_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
1456static long
1457parse_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
1471static const char *
1472parse_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
1508static const char *
1509parse_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
1621static const char *
1622parse_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
1737static const char *
1738parse_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
1769static const char *
1770parse_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
1791static const char *
1792parse_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
1800static const char *
1801parse_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
1809static const char *
1810parse_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
1829static const char *
1830parse_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 */
1863static void
1864print_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
1876static void
1877print_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
1893static void
1894print_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
1906static void
1907print_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/* -- */
1922