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