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