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