xref: /openbsd-src/gnu/usr.bin/binutils/opcodes/iq2000-asm.c (revision cf2f2c5620d6d9a4fd01930983c4b9a1f76d7aa3)
1d2201f2fSdrahn /* Assembler interface for targets using CGEN. -*- C -*-
2d2201f2fSdrahn    CGEN: Cpu tools GENerator
3d2201f2fSdrahn 
4d2201f2fSdrahn THIS FILE IS MACHINE GENERATED WITH CGEN.
5d2201f2fSdrahn - the resultant file is machine generated, cgen-asm.in isn't
6d2201f2fSdrahn 
7d2201f2fSdrahn Copyright 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
8d2201f2fSdrahn 
9d2201f2fSdrahn This file is part of the GNU Binutils and GDB, the GNU debugger.
10d2201f2fSdrahn 
11d2201f2fSdrahn This program is free software; you can redistribute it and/or modify
12d2201f2fSdrahn it under the terms of the GNU General Public License as published by
13d2201f2fSdrahn the Free Software Foundation; either version 2, or (at your option)
14d2201f2fSdrahn any later version.
15d2201f2fSdrahn 
16d2201f2fSdrahn This program is distributed in the hope that it will be useful,
17d2201f2fSdrahn but WITHOUT ANY WARRANTY; without even the implied warranty of
18d2201f2fSdrahn MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19d2201f2fSdrahn GNU General Public License for more details.
20d2201f2fSdrahn 
21d2201f2fSdrahn You should have received a copy of the GNU General Public License
22d2201f2fSdrahn along with this program; if not, write to the Free Software Foundation, Inc.,
23d2201f2fSdrahn 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
24d2201f2fSdrahn 
25d2201f2fSdrahn /* ??? Eventually more and more of this stuff can go to cpu-independent files.
26d2201f2fSdrahn    Keep that in mind.  */
27d2201f2fSdrahn 
28d2201f2fSdrahn #include "sysdep.h"
29d2201f2fSdrahn #include <stdio.h>
30d2201f2fSdrahn #include "ansidecl.h"
31d2201f2fSdrahn #include "bfd.h"
32d2201f2fSdrahn #include "symcat.h"
33d2201f2fSdrahn #include "iq2000-desc.h"
34d2201f2fSdrahn #include "iq2000-opc.h"
35d2201f2fSdrahn #include "opintl.h"
36d2201f2fSdrahn #include "xregex.h"
37d2201f2fSdrahn #include "libiberty.h"
38d2201f2fSdrahn #include "safe-ctype.h"
39d2201f2fSdrahn 
40d2201f2fSdrahn #undef  min
41d2201f2fSdrahn #define min(a,b) ((a) < (b) ? (a) : (b))
42d2201f2fSdrahn #undef  max
43d2201f2fSdrahn #define max(a,b) ((a) > (b) ? (a) : (b))
44d2201f2fSdrahn 
45d2201f2fSdrahn static const char * parse_insn_normal
46*cf2f2c56Smiod   (CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *);
47d2201f2fSdrahn 
48d2201f2fSdrahn /* -- assembler routines inserted here.  */
49d2201f2fSdrahn 
50d2201f2fSdrahn /* -- asm.c */
51d2201f2fSdrahn static const char * parse_mimm PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
52d2201f2fSdrahn static const char * parse_imm  PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
53d2201f2fSdrahn static const char * parse_hi16 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
54d2201f2fSdrahn static const char * parse_lo16 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
55d2201f2fSdrahn 
56d2201f2fSdrahn /* Special check to ensure that instruction exists for given machine */
57d2201f2fSdrahn int
iq2000_cgen_insn_supported(cd,insn)58d2201f2fSdrahn iq2000_cgen_insn_supported (cd, insn)
59d2201f2fSdrahn      CGEN_CPU_DESC cd;
60d2201f2fSdrahn      CGEN_INSN *insn;
61d2201f2fSdrahn {
62d2201f2fSdrahn   int machs = cd->machs;
63d2201f2fSdrahn 
64d2201f2fSdrahn   return ((CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH) & machs) != 0);
65d2201f2fSdrahn }
66d2201f2fSdrahn 
iq2000_cgen_isa_register(strp)67d2201f2fSdrahn static int iq2000_cgen_isa_register (strp)
68d2201f2fSdrahn      const char **strp;
69d2201f2fSdrahn {
70d2201f2fSdrahn   int len;
71d2201f2fSdrahn   int ch1, ch2;
72d2201f2fSdrahn   if (**strp == 'r' || **strp == 'R')
73d2201f2fSdrahn     {
74d2201f2fSdrahn       len = strlen (*strp);
75d2201f2fSdrahn       if (len == 2)
76d2201f2fSdrahn         {
77d2201f2fSdrahn           ch1 = (*strp)[1];
78d2201f2fSdrahn           if ('0' <= ch1 && ch1 <= '9')
79d2201f2fSdrahn             return 1;
80d2201f2fSdrahn         }
81d2201f2fSdrahn       else if (len == 3)
82d2201f2fSdrahn         {
83d2201f2fSdrahn 	  ch1 = (*strp)[1];
84d2201f2fSdrahn           ch2 = (*strp)[2];
85d2201f2fSdrahn           if (('1' <= ch1 && ch1 <= '2') && ('0' <= ch2 && ch2 <= '9'))
86d2201f2fSdrahn             return 1;
87d2201f2fSdrahn           if ('3' == ch1 && (ch2 == '0' || ch2 == '1'))
88d2201f2fSdrahn             return 1;
89d2201f2fSdrahn         }
90d2201f2fSdrahn     }
91d2201f2fSdrahn   if (**strp == '%' && tolower((*strp)[1]) != 'l' && tolower((*strp)[1]) != 'h')
92d2201f2fSdrahn     return 1;
93d2201f2fSdrahn   return 0;
94d2201f2fSdrahn }
95d2201f2fSdrahn 
96d2201f2fSdrahn /* Handle negated literal.  */
97d2201f2fSdrahn 
98d2201f2fSdrahn static const char *
parse_mimm(cd,strp,opindex,valuep)99d2201f2fSdrahn parse_mimm (cd, strp, opindex, valuep)
100d2201f2fSdrahn      CGEN_CPU_DESC cd;
101d2201f2fSdrahn      const char **strp;
102d2201f2fSdrahn      int opindex;
103d2201f2fSdrahn      long *valuep;
104d2201f2fSdrahn {
105d2201f2fSdrahn   const char *errmsg;
106d2201f2fSdrahn   long value;
107d2201f2fSdrahn 
108d2201f2fSdrahn   /* Verify this isn't a register */
109d2201f2fSdrahn   if (iq2000_cgen_isa_register (strp))
110d2201f2fSdrahn     errmsg = _("immediate value cannot be register");
111d2201f2fSdrahn   else
112d2201f2fSdrahn     {
113d2201f2fSdrahn       long value;
114d2201f2fSdrahn 
115d2201f2fSdrahn       errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
116d2201f2fSdrahn       if (errmsg == NULL)
117d2201f2fSdrahn 	{
118d2201f2fSdrahn 	  long x = (-value) & 0xFFFF0000;
119d2201f2fSdrahn 	  if (x != 0 && x != 0xFFFF0000)
120d2201f2fSdrahn 	    errmsg = _("immediate value out of range");
121d2201f2fSdrahn 	  else
122d2201f2fSdrahn 	    *valuep = (-value & 0xFFFF);
123d2201f2fSdrahn 	}
124d2201f2fSdrahn     }
125d2201f2fSdrahn   return errmsg;
126d2201f2fSdrahn }
127d2201f2fSdrahn 
128d2201f2fSdrahn /* Handle signed/unsigned literal.  */
129d2201f2fSdrahn 
130d2201f2fSdrahn static const char *
parse_imm(cd,strp,opindex,valuep)131d2201f2fSdrahn parse_imm (cd, strp, opindex, valuep)
132d2201f2fSdrahn      CGEN_CPU_DESC cd;
133d2201f2fSdrahn      const char **strp;
134d2201f2fSdrahn      int opindex;
135d2201f2fSdrahn      unsigned long *valuep;
136d2201f2fSdrahn {
137d2201f2fSdrahn   const char *errmsg;
138d2201f2fSdrahn   long value;
139d2201f2fSdrahn 
140d2201f2fSdrahn   if (iq2000_cgen_isa_register (strp))
141d2201f2fSdrahn     errmsg = _("immediate value cannot be register");
142d2201f2fSdrahn   else
143d2201f2fSdrahn     {
144d2201f2fSdrahn       long value;
145d2201f2fSdrahn 
146d2201f2fSdrahn       errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
147d2201f2fSdrahn       if (errmsg == NULL)
148d2201f2fSdrahn 	{
149d2201f2fSdrahn 	  long x = value & 0xFFFF0000;
150d2201f2fSdrahn 	  if (x != 0 && x != 0xFFFF0000)
151d2201f2fSdrahn 	    errmsg = _("immediate value out of range");
152d2201f2fSdrahn 	  else
153d2201f2fSdrahn 	    *valuep = (value & 0xFFFF);
154d2201f2fSdrahn 	}
155d2201f2fSdrahn     }
156d2201f2fSdrahn   return errmsg;
157d2201f2fSdrahn }
158d2201f2fSdrahn 
159d2201f2fSdrahn /* Handle iq10 21-bit jmp offset.  */
160d2201f2fSdrahn 
161d2201f2fSdrahn static const char *
parse_jtargq10(cd,strp,opindex,reloc,type_addr,valuep)162d2201f2fSdrahn parse_jtargq10 (cd, strp, opindex, reloc, type_addr, valuep)
163d2201f2fSdrahn      CGEN_CPU_DESC cd;
164d2201f2fSdrahn      const char **strp;
165d2201f2fSdrahn      int opindex;
166d2201f2fSdrahn      int reloc;
167d2201f2fSdrahn      enum cgen_parse_operand_result *type_addr;
168d2201f2fSdrahn      unsigned long *valuep;
169d2201f2fSdrahn {
170d2201f2fSdrahn   const char *errmsg;
171d2201f2fSdrahn   bfd_vma value;
172d2201f2fSdrahn   enum cgen_parse_operand_result result_type = CGEN_PARSE_OPERAND_RESULT_NUMBER;
173d2201f2fSdrahn 
174d2201f2fSdrahn   errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IQ2000_OFFSET_21,
175d2201f2fSdrahn 			       &result_type, &value);
176d2201f2fSdrahn   if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
177d2201f2fSdrahn     {
178d2201f2fSdrahn       /* check value is within 23-bits (remembering that 2-bit shift right will occur) */
179d2201f2fSdrahn       if (value > 0x7fffff)
180d2201f2fSdrahn         return _("21-bit offset out of range");
181d2201f2fSdrahn     }
182d2201f2fSdrahn   *valuep = (value & 0x7FFFFF);
183d2201f2fSdrahn   return errmsg;
184d2201f2fSdrahn }
185d2201f2fSdrahn 
186d2201f2fSdrahn /* Handle high().  */
187d2201f2fSdrahn 
188d2201f2fSdrahn static const char *
parse_hi16(cd,strp,opindex,valuep)189d2201f2fSdrahn parse_hi16 (cd, strp, opindex, valuep)
190d2201f2fSdrahn      CGEN_CPU_DESC cd;
191d2201f2fSdrahn      const char **strp;
192d2201f2fSdrahn      int opindex;
193d2201f2fSdrahn      unsigned long *valuep;
194d2201f2fSdrahn {
195d2201f2fSdrahn   if (strncasecmp (*strp, "%hi(", 4) == 0)
196d2201f2fSdrahn     {
197d2201f2fSdrahn       enum cgen_parse_operand_result result_type;
198d2201f2fSdrahn       bfd_vma value;
199d2201f2fSdrahn       const char *errmsg;
200d2201f2fSdrahn 
201d2201f2fSdrahn       *strp += 4;
202d2201f2fSdrahn       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16,
203d2201f2fSdrahn 				   &result_type, &value);
204d2201f2fSdrahn       if (**strp != ')')
205d2201f2fSdrahn 	return _("missing `)'");
206d2201f2fSdrahn 
207d2201f2fSdrahn       ++*strp;
208d2201f2fSdrahn       if (errmsg == NULL
209d2201f2fSdrahn   	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
210d2201f2fSdrahn 	{
211d2201f2fSdrahn 	  /* if value has top-bit of %lo on, then it will
212d2201f2fSdrahn 	     sign-propagate and so we compensate by adding
213d2201f2fSdrahn 	     1 to the resultant %hi value */
214d2201f2fSdrahn 	  if (value & 0x8000)
215d2201f2fSdrahn 	    value += 0x10000;
216d2201f2fSdrahn 	  value >>= 16;
217d2201f2fSdrahn 	}
218d2201f2fSdrahn       *valuep = value;
219d2201f2fSdrahn 
220d2201f2fSdrahn       return errmsg;
221d2201f2fSdrahn     }
222d2201f2fSdrahn 
223d2201f2fSdrahn   /* we add %uhi in case a user just wants the high 16-bits or is using
224d2201f2fSdrahn      an insn like ori for %lo which does not sign-propagate */
225d2201f2fSdrahn   if (strncasecmp (*strp, "%uhi(", 5) == 0)
226d2201f2fSdrahn     {
227d2201f2fSdrahn       enum cgen_parse_operand_result result_type;
228d2201f2fSdrahn       bfd_vma value;
229d2201f2fSdrahn       const char *errmsg;
230d2201f2fSdrahn 
231d2201f2fSdrahn       *strp += 5;
232d2201f2fSdrahn       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IQ2000_UHI16,
233d2201f2fSdrahn 				   &result_type, &value);
234d2201f2fSdrahn       if (**strp != ')')
235d2201f2fSdrahn 	return _("missing `)'");
236d2201f2fSdrahn 
237d2201f2fSdrahn       ++*strp;
238d2201f2fSdrahn       if (errmsg == NULL
239d2201f2fSdrahn   	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
240d2201f2fSdrahn 	{
241d2201f2fSdrahn 	  value >>= 16;
242d2201f2fSdrahn 	}
243d2201f2fSdrahn       *valuep = value;
244d2201f2fSdrahn 
245d2201f2fSdrahn       return errmsg;
246d2201f2fSdrahn     }
247d2201f2fSdrahn 
248d2201f2fSdrahn   return parse_imm (cd, strp, opindex, valuep);
249d2201f2fSdrahn }
250d2201f2fSdrahn 
251d2201f2fSdrahn /* Handle %lo in a signed context.
252d2201f2fSdrahn    The signedness of the value doesn't matter to %lo(), but this also
253d2201f2fSdrahn    handles the case where %lo() isn't present.  */
254d2201f2fSdrahn 
255d2201f2fSdrahn static const char *
parse_lo16(cd,strp,opindex,valuep)256d2201f2fSdrahn parse_lo16 (cd, strp, opindex, valuep)
257d2201f2fSdrahn      CGEN_CPU_DESC cd;
258d2201f2fSdrahn      const char **strp;
259d2201f2fSdrahn      int opindex;
260d2201f2fSdrahn      long *valuep;
261d2201f2fSdrahn {
262d2201f2fSdrahn   if (strncasecmp (*strp, "%lo(", 4) == 0)
263d2201f2fSdrahn     {
264d2201f2fSdrahn       const char *errmsg;
265d2201f2fSdrahn       enum cgen_parse_operand_result result_type;
266d2201f2fSdrahn       bfd_vma value;
267d2201f2fSdrahn 
268d2201f2fSdrahn       *strp += 4;
269d2201f2fSdrahn       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
270d2201f2fSdrahn 				   &result_type, &value);
271d2201f2fSdrahn       if (**strp != ')')
272d2201f2fSdrahn 	return _("missing `)'");
273d2201f2fSdrahn       ++*strp;
274d2201f2fSdrahn       if (errmsg == NULL
275d2201f2fSdrahn 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
276d2201f2fSdrahn 	value &= 0xffff;
277d2201f2fSdrahn       *valuep = value;
278d2201f2fSdrahn       return errmsg;
279d2201f2fSdrahn     }
280d2201f2fSdrahn 
281d2201f2fSdrahn   return parse_imm (cd, strp, opindex, valuep);
282d2201f2fSdrahn }
283d2201f2fSdrahn 
284d2201f2fSdrahn /* Handle %lo in a negated signed context.
285d2201f2fSdrahn    The signedness of the value doesn't matter to %lo(), but this also
286d2201f2fSdrahn    handles the case where %lo() isn't present.  */
287d2201f2fSdrahn 
288d2201f2fSdrahn static const char *
parse_mlo16(cd,strp,opindex,valuep)289d2201f2fSdrahn parse_mlo16 (cd, strp, opindex, valuep)
290d2201f2fSdrahn      CGEN_CPU_DESC cd;
291d2201f2fSdrahn      const char **strp;
292d2201f2fSdrahn      int opindex;
293d2201f2fSdrahn      long *valuep;
294d2201f2fSdrahn {
295d2201f2fSdrahn   if (strncasecmp (*strp, "%lo(", 4) == 0)
296d2201f2fSdrahn     {
297d2201f2fSdrahn       const char *errmsg;
298d2201f2fSdrahn       enum cgen_parse_operand_result result_type;
299d2201f2fSdrahn       bfd_vma value;
300d2201f2fSdrahn 
301d2201f2fSdrahn       *strp += 4;
302d2201f2fSdrahn       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
303d2201f2fSdrahn 				   &result_type, &value);
304d2201f2fSdrahn       if (**strp != ')')
305d2201f2fSdrahn 	return _("missing `)'");
306d2201f2fSdrahn       ++*strp;
307d2201f2fSdrahn       if (errmsg == NULL
308d2201f2fSdrahn 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
309d2201f2fSdrahn 	value = (-value) & 0xffff;
310d2201f2fSdrahn       *valuep = value;
311d2201f2fSdrahn       return errmsg;
312d2201f2fSdrahn     }
313d2201f2fSdrahn 
314d2201f2fSdrahn   return parse_mimm (cd, strp, opindex, valuep);
315d2201f2fSdrahn }
316d2201f2fSdrahn 
317d2201f2fSdrahn /* -- */
318d2201f2fSdrahn 
319d2201f2fSdrahn const char * iq2000_cgen_parse_operand
320d2201f2fSdrahn   PARAMS ((CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *));
321d2201f2fSdrahn 
322d2201f2fSdrahn /* Main entry point for operand parsing.
323d2201f2fSdrahn 
324d2201f2fSdrahn    This function is basically just a big switch statement.  Earlier versions
325d2201f2fSdrahn    used tables to look up the function to use, but
326d2201f2fSdrahn    - if the table contains both assembler and disassembler functions then
327d2201f2fSdrahn      the disassembler contains much of the assembler and vice-versa,
328d2201f2fSdrahn    - there's a lot of inlining possibilities as things grow,
329d2201f2fSdrahn    - using a switch statement avoids the function call overhead.
330d2201f2fSdrahn 
331d2201f2fSdrahn    This function could be moved into `parse_insn_normal', but keeping it
332d2201f2fSdrahn    separate makes clear the interface between `parse_insn_normal' and each of
333d2201f2fSdrahn    the handlers.  */
334d2201f2fSdrahn 
335d2201f2fSdrahn const char *
iq2000_cgen_parse_operand(cd,opindex,strp,fields)336d2201f2fSdrahn iq2000_cgen_parse_operand (cd, opindex, strp, fields)
337d2201f2fSdrahn      CGEN_CPU_DESC cd;
338d2201f2fSdrahn      int opindex;
339d2201f2fSdrahn      const char ** strp;
340d2201f2fSdrahn      CGEN_FIELDS * fields;
341d2201f2fSdrahn {
342d2201f2fSdrahn   const char * errmsg = NULL;
343d2201f2fSdrahn   /* Used by scalar operands that still need to be parsed.  */
344d2201f2fSdrahn   long junk ATTRIBUTE_UNUSED;
345d2201f2fSdrahn 
346d2201f2fSdrahn   switch (opindex)
347d2201f2fSdrahn     {
348d2201f2fSdrahn     case IQ2000_OPERAND_BASE :
349d2201f2fSdrahn       errmsg = cgen_parse_keyword (cd, strp, & iq2000_cgen_opval_gr_names, & fields->f_rs);
350d2201f2fSdrahn       break;
351d2201f2fSdrahn     case IQ2000_OPERAND_BASEOFF :
352d2201f2fSdrahn       {
353d2201f2fSdrahn         bfd_vma value;
354d2201f2fSdrahn         errmsg = cgen_parse_address (cd, strp, IQ2000_OPERAND_BASEOFF, 0, NULL,  & value);
355d2201f2fSdrahn         fields->f_imm = value;
356d2201f2fSdrahn       }
357d2201f2fSdrahn       break;
358d2201f2fSdrahn     case IQ2000_OPERAND_BITNUM :
359d2201f2fSdrahn       errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_BITNUM, &fields->f_rt);
360d2201f2fSdrahn       break;
361d2201f2fSdrahn     case IQ2000_OPERAND_BYTECOUNT :
362d2201f2fSdrahn       errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_BYTECOUNT, &fields->f_bytecount);
363d2201f2fSdrahn       break;
364d2201f2fSdrahn     case IQ2000_OPERAND_CAM_Y :
365d2201f2fSdrahn       errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_CAM_Y, &fields->f_cam_y);
366d2201f2fSdrahn       break;
367d2201f2fSdrahn     case IQ2000_OPERAND_CAM_Z :
368d2201f2fSdrahn       errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_CAM_Z, &fields->f_cam_z);
369d2201f2fSdrahn       break;
370d2201f2fSdrahn     case IQ2000_OPERAND_CM_3FUNC :
371d2201f2fSdrahn       errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_CM_3FUNC, &fields->f_cm_3func);
372d2201f2fSdrahn       break;
373d2201f2fSdrahn     case IQ2000_OPERAND_CM_3Z :
374d2201f2fSdrahn       errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_CM_3Z, &fields->f_cm_3z);
375d2201f2fSdrahn       break;
376d2201f2fSdrahn     case IQ2000_OPERAND_CM_4FUNC :
377d2201f2fSdrahn       errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_CM_4FUNC, &fields->f_cm_4func);
378d2201f2fSdrahn       break;
379d2201f2fSdrahn     case IQ2000_OPERAND_CM_4Z :
380d2201f2fSdrahn       errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_CM_4Z, &fields->f_cm_4z);
381d2201f2fSdrahn       break;
382d2201f2fSdrahn     case IQ2000_OPERAND_COUNT :
383d2201f2fSdrahn       errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_COUNT, &fields->f_count);
384d2201f2fSdrahn       break;
385d2201f2fSdrahn     case IQ2000_OPERAND_EXECODE :
386d2201f2fSdrahn       errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_EXECODE, &fields->f_excode);
387d2201f2fSdrahn       break;
388*cf2f2c56Smiod     case IQ2000_OPERAND_F_INDEX :
389*cf2f2c56Smiod       errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_F_INDEX, &fields->f_index);
390*cf2f2c56Smiod       break;
391d2201f2fSdrahn     case IQ2000_OPERAND_HI16 :
392d2201f2fSdrahn       errmsg = parse_hi16 (cd, strp, IQ2000_OPERAND_HI16, &fields->f_imm);
393d2201f2fSdrahn       break;
394d2201f2fSdrahn     case IQ2000_OPERAND_IMM :
395d2201f2fSdrahn       errmsg = parse_imm (cd, strp, IQ2000_OPERAND_IMM, &fields->f_imm);
396d2201f2fSdrahn       break;
397d2201f2fSdrahn     case IQ2000_OPERAND_JMPTARG :
398d2201f2fSdrahn       {
399d2201f2fSdrahn         bfd_vma value;
400d2201f2fSdrahn         errmsg = cgen_parse_address (cd, strp, IQ2000_OPERAND_JMPTARG, 0, NULL,  & value);
401d2201f2fSdrahn         fields->f_jtarg = value;
402d2201f2fSdrahn       }
403d2201f2fSdrahn       break;
404d2201f2fSdrahn     case IQ2000_OPERAND_JMPTARGQ10 :
405d2201f2fSdrahn       {
406d2201f2fSdrahn         bfd_vma value;
407d2201f2fSdrahn         errmsg = parse_jtargq10 (cd, strp, IQ2000_OPERAND_JMPTARGQ10, 0, NULL,  & value);
408d2201f2fSdrahn         fields->f_jtargq10 = value;
409d2201f2fSdrahn       }
410d2201f2fSdrahn       break;
411d2201f2fSdrahn     case IQ2000_OPERAND_LO16 :
412d2201f2fSdrahn       errmsg = parse_lo16 (cd, strp, IQ2000_OPERAND_LO16, &fields->f_imm);
413d2201f2fSdrahn       break;
414d2201f2fSdrahn     case IQ2000_OPERAND_MASK :
415d2201f2fSdrahn       errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_MASK, &fields->f_mask);
416d2201f2fSdrahn       break;
417d2201f2fSdrahn     case IQ2000_OPERAND_MASKL :
418d2201f2fSdrahn       errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_MASKL, &fields->f_maskl);
419d2201f2fSdrahn       break;
420d2201f2fSdrahn     case IQ2000_OPERAND_MASKQ10 :
421d2201f2fSdrahn       errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_MASKQ10, &fields->f_maskq10);
422d2201f2fSdrahn       break;
423d2201f2fSdrahn     case IQ2000_OPERAND_MASKR :
424d2201f2fSdrahn       errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_MASKR, &fields->f_rs);
425d2201f2fSdrahn       break;
426d2201f2fSdrahn     case IQ2000_OPERAND_MLO16 :
427d2201f2fSdrahn       errmsg = parse_mlo16 (cd, strp, IQ2000_OPERAND_MLO16, &fields->f_imm);
428d2201f2fSdrahn       break;
429d2201f2fSdrahn     case IQ2000_OPERAND_OFFSET :
430d2201f2fSdrahn       {
431d2201f2fSdrahn         bfd_vma value;
432d2201f2fSdrahn         errmsg = cgen_parse_address (cd, strp, IQ2000_OPERAND_OFFSET, 0, NULL,  & value);
433d2201f2fSdrahn         fields->f_offset = value;
434d2201f2fSdrahn       }
435d2201f2fSdrahn       break;
436d2201f2fSdrahn     case IQ2000_OPERAND_RD :
437d2201f2fSdrahn       errmsg = cgen_parse_keyword (cd, strp, & iq2000_cgen_opval_gr_names, & fields->f_rd);
438d2201f2fSdrahn       break;
439d2201f2fSdrahn     case IQ2000_OPERAND_RD_RS :
440d2201f2fSdrahn       errmsg = cgen_parse_keyword (cd, strp, & iq2000_cgen_opval_gr_names, & fields->f_rd_rs);
441d2201f2fSdrahn       break;
442d2201f2fSdrahn     case IQ2000_OPERAND_RD_RT :
443d2201f2fSdrahn       errmsg = cgen_parse_keyword (cd, strp, & iq2000_cgen_opval_gr_names, & fields->f_rd_rt);
444d2201f2fSdrahn       break;
445d2201f2fSdrahn     case IQ2000_OPERAND_RS :
446d2201f2fSdrahn       errmsg = cgen_parse_keyword (cd, strp, & iq2000_cgen_opval_gr_names, & fields->f_rs);
447d2201f2fSdrahn       break;
448d2201f2fSdrahn     case IQ2000_OPERAND_RT :
449d2201f2fSdrahn       errmsg = cgen_parse_keyword (cd, strp, & iq2000_cgen_opval_gr_names, & fields->f_rt);
450d2201f2fSdrahn       break;
451d2201f2fSdrahn     case IQ2000_OPERAND_RT_RS :
452d2201f2fSdrahn       errmsg = cgen_parse_keyword (cd, strp, & iq2000_cgen_opval_gr_names, & fields->f_rt_rs);
453d2201f2fSdrahn       break;
454d2201f2fSdrahn     case IQ2000_OPERAND_SHAMT :
455d2201f2fSdrahn       errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_SHAMT, &fields->f_shamt);
456d2201f2fSdrahn       break;
457d2201f2fSdrahn 
458d2201f2fSdrahn     default :
459d2201f2fSdrahn       /* xgettext:c-format */
460d2201f2fSdrahn       fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
461d2201f2fSdrahn       abort ();
462d2201f2fSdrahn   }
463d2201f2fSdrahn 
464d2201f2fSdrahn   return errmsg;
465d2201f2fSdrahn }
466d2201f2fSdrahn 
467d2201f2fSdrahn cgen_parse_fn * const iq2000_cgen_parse_handlers[] =
468d2201f2fSdrahn {
469d2201f2fSdrahn   parse_insn_normal,
470d2201f2fSdrahn };
471d2201f2fSdrahn 
472d2201f2fSdrahn void
iq2000_cgen_init_asm(cd)473d2201f2fSdrahn iq2000_cgen_init_asm (cd)
474d2201f2fSdrahn      CGEN_CPU_DESC cd;
475d2201f2fSdrahn {
476d2201f2fSdrahn   iq2000_cgen_init_opcode_table (cd);
477d2201f2fSdrahn   iq2000_cgen_init_ibld_table (cd);
478d2201f2fSdrahn   cd->parse_handlers = & iq2000_cgen_parse_handlers[0];
479d2201f2fSdrahn   cd->parse_operand = iq2000_cgen_parse_operand;
480d2201f2fSdrahn }
481d2201f2fSdrahn 
482d2201f2fSdrahn 
483d2201f2fSdrahn 
484d2201f2fSdrahn /* Regex construction routine.
485d2201f2fSdrahn 
486d2201f2fSdrahn    This translates an opcode syntax string into a regex string,
487d2201f2fSdrahn    by replacing any non-character syntax element (such as an
488d2201f2fSdrahn    opcode) with the pattern '.*'
489d2201f2fSdrahn 
490d2201f2fSdrahn    It then compiles the regex and stores it in the opcode, for
491d2201f2fSdrahn    later use by iq2000_cgen_assemble_insn
492d2201f2fSdrahn 
493d2201f2fSdrahn    Returns NULL for success, an error message for failure.  */
494d2201f2fSdrahn 
495d2201f2fSdrahn char *
iq2000_cgen_build_insn_regex(CGEN_INSN * insn)496*cf2f2c56Smiod iq2000_cgen_build_insn_regex (CGEN_INSN *insn)
497d2201f2fSdrahn {
498d2201f2fSdrahn   CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
499d2201f2fSdrahn   const char *mnem = CGEN_INSN_MNEMONIC (insn);
500d2201f2fSdrahn   char rxbuf[CGEN_MAX_RX_ELEMENTS];
501d2201f2fSdrahn   char *rx = rxbuf;
502d2201f2fSdrahn   const CGEN_SYNTAX_CHAR_TYPE *syn;
503d2201f2fSdrahn   int reg_err;
504d2201f2fSdrahn 
505d2201f2fSdrahn   syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
506d2201f2fSdrahn 
507d2201f2fSdrahn   /* Mnemonics come first in the syntax string.  */
508d2201f2fSdrahn   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
509d2201f2fSdrahn     return _("missing mnemonic in syntax string");
510d2201f2fSdrahn   ++syn;
511d2201f2fSdrahn 
512d2201f2fSdrahn   /* Generate a case sensitive regular expression that emulates case
513d2201f2fSdrahn      insensitive matching in the "C" locale.  We cannot generate a case
514d2201f2fSdrahn      insensitive regular expression because in Turkish locales, 'i' and 'I'
515d2201f2fSdrahn      are not equal modulo case conversion.  */
516d2201f2fSdrahn 
517d2201f2fSdrahn   /* Copy the literal mnemonic out of the insn.  */
518d2201f2fSdrahn   for (; *mnem; mnem++)
519d2201f2fSdrahn     {
520d2201f2fSdrahn       char c = *mnem;
521d2201f2fSdrahn 
522d2201f2fSdrahn       if (ISALPHA (c))
523d2201f2fSdrahn 	{
524d2201f2fSdrahn 	  *rx++ = '[';
525d2201f2fSdrahn 	  *rx++ = TOLOWER (c);
526d2201f2fSdrahn 	  *rx++ = TOUPPER (c);
527d2201f2fSdrahn 	  *rx++ = ']';
528d2201f2fSdrahn 	}
529d2201f2fSdrahn       else
530d2201f2fSdrahn 	*rx++ = c;
531d2201f2fSdrahn     }
532d2201f2fSdrahn 
533d2201f2fSdrahn   /* Copy any remaining literals from the syntax string into the rx.  */
534d2201f2fSdrahn   for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
535d2201f2fSdrahn     {
536d2201f2fSdrahn       if (CGEN_SYNTAX_CHAR_P (* syn))
537d2201f2fSdrahn 	{
538d2201f2fSdrahn 	  char c = CGEN_SYNTAX_CHAR (* syn);
539d2201f2fSdrahn 
540d2201f2fSdrahn 	  switch (c)
541d2201f2fSdrahn 	    {
542d2201f2fSdrahn 	      /* Escape any regex metacharacters in the syntax.  */
543d2201f2fSdrahn 	    case '.': case '[': case '\\':
544d2201f2fSdrahn 	    case '*': case '^': case '$':
545d2201f2fSdrahn 
546d2201f2fSdrahn #ifdef CGEN_ESCAPE_EXTENDED_REGEX
547d2201f2fSdrahn 	    case '?': case '{': case '}':
548d2201f2fSdrahn 	    case '(': case ')': case '*':
549d2201f2fSdrahn 	    case '|': case '+': case ']':
550d2201f2fSdrahn #endif
551d2201f2fSdrahn 	      *rx++ = '\\';
552d2201f2fSdrahn 	      *rx++ = c;
553d2201f2fSdrahn 	      break;
554d2201f2fSdrahn 
555d2201f2fSdrahn 	    default:
556d2201f2fSdrahn 	      if (ISALPHA (c))
557d2201f2fSdrahn 		{
558d2201f2fSdrahn 		  *rx++ = '[';
559d2201f2fSdrahn 		  *rx++ = TOLOWER (c);
560d2201f2fSdrahn 		  *rx++ = TOUPPER (c);
561d2201f2fSdrahn 		  *rx++ = ']';
562d2201f2fSdrahn 		}
563d2201f2fSdrahn 	      else
564d2201f2fSdrahn 		*rx++ = c;
565d2201f2fSdrahn 	      break;
566d2201f2fSdrahn 	    }
567d2201f2fSdrahn 	}
568d2201f2fSdrahn       else
569d2201f2fSdrahn 	{
570d2201f2fSdrahn 	  /* Replace non-syntax fields with globs.  */
571d2201f2fSdrahn 	  *rx++ = '.';
572d2201f2fSdrahn 	  *rx++ = '*';
573d2201f2fSdrahn 	}
574d2201f2fSdrahn     }
575d2201f2fSdrahn 
576d2201f2fSdrahn   /* Trailing whitespace ok.  */
577d2201f2fSdrahn   * rx++ = '[';
578d2201f2fSdrahn   * rx++ = ' ';
579d2201f2fSdrahn   * rx++ = '\t';
580d2201f2fSdrahn   * rx++ = ']';
581d2201f2fSdrahn   * rx++ = '*';
582d2201f2fSdrahn 
583d2201f2fSdrahn   /* But anchor it after that.  */
584d2201f2fSdrahn   * rx++ = '$';
585d2201f2fSdrahn   * rx = '\0';
586d2201f2fSdrahn 
587d2201f2fSdrahn   CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
588d2201f2fSdrahn   reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
589d2201f2fSdrahn 
590d2201f2fSdrahn   if (reg_err == 0)
591d2201f2fSdrahn     return NULL;
592d2201f2fSdrahn   else
593d2201f2fSdrahn     {
594d2201f2fSdrahn       static char msg[80];
595d2201f2fSdrahn 
596d2201f2fSdrahn       regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
597d2201f2fSdrahn       regfree ((regex_t *) CGEN_INSN_RX (insn));
598d2201f2fSdrahn       free (CGEN_INSN_RX (insn));
599d2201f2fSdrahn       (CGEN_INSN_RX (insn)) = NULL;
600d2201f2fSdrahn       return msg;
601d2201f2fSdrahn     }
602d2201f2fSdrahn }
603d2201f2fSdrahn 
604d2201f2fSdrahn 
605d2201f2fSdrahn /* Default insn parser.
606d2201f2fSdrahn 
607d2201f2fSdrahn    The syntax string is scanned and operands are parsed and stored in FIELDS.
608d2201f2fSdrahn    Relocs are queued as we go via other callbacks.
609d2201f2fSdrahn 
610d2201f2fSdrahn    ??? Note that this is currently an all-or-nothing parser.  If we fail to
611d2201f2fSdrahn    parse the instruction, we return 0 and the caller will start over from
612d2201f2fSdrahn    the beginning.  Backtracking will be necessary in parsing subexpressions,
613d2201f2fSdrahn    but that can be handled there.  Not handling backtracking here may get
614d2201f2fSdrahn    expensive in the case of the m68k.  Deal with later.
615d2201f2fSdrahn 
616d2201f2fSdrahn    Returns NULL for success, an error message for failure.  */
617d2201f2fSdrahn 
618d2201f2fSdrahn static const char *
parse_insn_normal(CGEN_CPU_DESC cd,const CGEN_INSN * insn,const char ** strp,CGEN_FIELDS * fields)619*cf2f2c56Smiod parse_insn_normal (CGEN_CPU_DESC cd,
620*cf2f2c56Smiod 		   const CGEN_INSN *insn,
621*cf2f2c56Smiod 		   const char **strp,
622*cf2f2c56Smiod 		   CGEN_FIELDS *fields)
623d2201f2fSdrahn {
624d2201f2fSdrahn   /* ??? Runtime added insns not handled yet.  */
625d2201f2fSdrahn   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
626d2201f2fSdrahn   const char *str = *strp;
627d2201f2fSdrahn   const char *errmsg;
628d2201f2fSdrahn   const char *p;
629d2201f2fSdrahn   const CGEN_SYNTAX_CHAR_TYPE * syn;
630d2201f2fSdrahn #ifdef CGEN_MNEMONIC_OPERANDS
631d2201f2fSdrahn   /* FIXME: wip */
632d2201f2fSdrahn   int past_opcode_p;
633d2201f2fSdrahn #endif
634d2201f2fSdrahn 
635d2201f2fSdrahn   /* For now we assume the mnemonic is first (there are no leading operands).
636d2201f2fSdrahn      We can parse it without needing to set up operand parsing.
637d2201f2fSdrahn      GAS's input scrubber will ensure mnemonics are lowercase, but we may
638d2201f2fSdrahn      not be called from GAS.  */
639d2201f2fSdrahn   p = CGEN_INSN_MNEMONIC (insn);
640d2201f2fSdrahn   while (*p && TOLOWER (*p) == TOLOWER (*str))
641d2201f2fSdrahn     ++p, ++str;
642d2201f2fSdrahn 
643d2201f2fSdrahn   if (* p)
644d2201f2fSdrahn     return _("unrecognized instruction");
645d2201f2fSdrahn 
646d2201f2fSdrahn #ifndef CGEN_MNEMONIC_OPERANDS
647d2201f2fSdrahn   if (* str && ! ISSPACE (* str))
648d2201f2fSdrahn     return _("unrecognized instruction");
649d2201f2fSdrahn #endif
650d2201f2fSdrahn 
651d2201f2fSdrahn   CGEN_INIT_PARSE (cd);
652d2201f2fSdrahn   cgen_init_parse_operand (cd);
653d2201f2fSdrahn #ifdef CGEN_MNEMONIC_OPERANDS
654d2201f2fSdrahn   past_opcode_p = 0;
655d2201f2fSdrahn #endif
656d2201f2fSdrahn 
657d2201f2fSdrahn   /* We don't check for (*str != '\0') here because we want to parse
658d2201f2fSdrahn      any trailing fake arguments in the syntax string.  */
659d2201f2fSdrahn   syn = CGEN_SYNTAX_STRING (syntax);
660d2201f2fSdrahn 
661d2201f2fSdrahn   /* Mnemonics come first for now, ensure valid string.  */
662d2201f2fSdrahn   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
663d2201f2fSdrahn     abort ();
664d2201f2fSdrahn 
665d2201f2fSdrahn   ++syn;
666d2201f2fSdrahn 
667d2201f2fSdrahn   while (* syn != 0)
668d2201f2fSdrahn     {
669d2201f2fSdrahn       /* Non operand chars must match exactly.  */
670d2201f2fSdrahn       if (CGEN_SYNTAX_CHAR_P (* syn))
671d2201f2fSdrahn 	{
672d2201f2fSdrahn 	  /* FIXME: While we allow for non-GAS callers above, we assume the
673d2201f2fSdrahn 	     first char after the mnemonic part is a space.  */
674d2201f2fSdrahn 	  /* FIXME: We also take inappropriate advantage of the fact that
675d2201f2fSdrahn 	     GAS's input scrubber will remove extraneous blanks.  */
676d2201f2fSdrahn 	  if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
677d2201f2fSdrahn 	    {
678d2201f2fSdrahn #ifdef CGEN_MNEMONIC_OPERANDS
679d2201f2fSdrahn 	      if (CGEN_SYNTAX_CHAR(* syn) == ' ')
680d2201f2fSdrahn 		past_opcode_p = 1;
681d2201f2fSdrahn #endif
682d2201f2fSdrahn 	      ++ syn;
683d2201f2fSdrahn 	      ++ str;
684d2201f2fSdrahn 	    }
685d2201f2fSdrahn 	  else if (*str)
686d2201f2fSdrahn 	    {
687d2201f2fSdrahn 	      /* Syntax char didn't match.  Can't be this insn.  */
688d2201f2fSdrahn 	      static char msg [80];
689d2201f2fSdrahn 
690d2201f2fSdrahn 	      /* xgettext:c-format */
691d2201f2fSdrahn 	      sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
692d2201f2fSdrahn 		       CGEN_SYNTAX_CHAR(*syn), *str);
693d2201f2fSdrahn 	      return msg;
694d2201f2fSdrahn 	    }
695d2201f2fSdrahn 	  else
696d2201f2fSdrahn 	    {
697d2201f2fSdrahn 	      /* Ran out of input.  */
698d2201f2fSdrahn 	      static char msg [80];
699d2201f2fSdrahn 
700d2201f2fSdrahn 	      /* xgettext:c-format */
701d2201f2fSdrahn 	      sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
702d2201f2fSdrahn 		       CGEN_SYNTAX_CHAR(*syn));
703d2201f2fSdrahn 	      return msg;
704d2201f2fSdrahn 	    }
705d2201f2fSdrahn 	  continue;
706d2201f2fSdrahn 	}
707d2201f2fSdrahn 
708d2201f2fSdrahn       /* We have an operand of some sort.  */
709d2201f2fSdrahn       errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn),
710d2201f2fSdrahn 					  &str, fields);
711d2201f2fSdrahn       if (errmsg)
712d2201f2fSdrahn 	return errmsg;
713d2201f2fSdrahn 
714d2201f2fSdrahn       /* Done with this operand, continue with next one.  */
715d2201f2fSdrahn       ++ syn;
716d2201f2fSdrahn     }
717d2201f2fSdrahn 
718d2201f2fSdrahn   /* If we're at the end of the syntax string, we're done.  */
719d2201f2fSdrahn   if (* syn == 0)
720d2201f2fSdrahn     {
721d2201f2fSdrahn       /* FIXME: For the moment we assume a valid `str' can only contain
722d2201f2fSdrahn 	 blanks now.  IE: We needn't try again with a longer version of
723d2201f2fSdrahn 	 the insn and it is assumed that longer versions of insns appear
724d2201f2fSdrahn 	 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
725d2201f2fSdrahn       while (ISSPACE (* str))
726d2201f2fSdrahn 	++ str;
727d2201f2fSdrahn 
728d2201f2fSdrahn       if (* str != '\0')
729d2201f2fSdrahn 	return _("junk at end of line"); /* FIXME: would like to include `str' */
730d2201f2fSdrahn 
731d2201f2fSdrahn       return NULL;
732d2201f2fSdrahn     }
733d2201f2fSdrahn 
734d2201f2fSdrahn   /* We couldn't parse it.  */
735d2201f2fSdrahn   return _("unrecognized instruction");
736d2201f2fSdrahn }
737d2201f2fSdrahn 
738d2201f2fSdrahn /* Main entry point.
739d2201f2fSdrahn    This routine is called for each instruction to be assembled.
740d2201f2fSdrahn    STR points to the insn to be assembled.
741d2201f2fSdrahn    We assume all necessary tables have been initialized.
742d2201f2fSdrahn    The assembled instruction, less any fixups, is stored in BUF.
743d2201f2fSdrahn    Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
744d2201f2fSdrahn    still needs to be converted to target byte order, otherwise BUF is an array
745d2201f2fSdrahn    of bytes in target byte order.
746d2201f2fSdrahn    The result is a pointer to the insn's entry in the opcode table,
747d2201f2fSdrahn    or NULL if an error occured (an error message will have already been
748d2201f2fSdrahn    printed).
749d2201f2fSdrahn 
750d2201f2fSdrahn    Note that when processing (non-alias) macro-insns,
751d2201f2fSdrahn    this function recurses.
752d2201f2fSdrahn 
753d2201f2fSdrahn    ??? It's possible to make this cpu-independent.
754d2201f2fSdrahn    One would have to deal with a few minor things.
755d2201f2fSdrahn    At this point in time doing so would be more of a curiosity than useful
756d2201f2fSdrahn    [for example this file isn't _that_ big], but keeping the possibility in
757d2201f2fSdrahn    mind helps keep the design clean.  */
758d2201f2fSdrahn 
759d2201f2fSdrahn const CGEN_INSN *
iq2000_cgen_assemble_insn(CGEN_CPU_DESC cd,const char * str,CGEN_FIELDS * fields,CGEN_INSN_BYTES_PTR buf,char ** errmsg)760*cf2f2c56Smiod iq2000_cgen_assemble_insn (CGEN_CPU_DESC cd,
761*cf2f2c56Smiod 			   const char *str,
762*cf2f2c56Smiod 			   CGEN_FIELDS *fields,
763*cf2f2c56Smiod 			   CGEN_INSN_BYTES_PTR buf,
764*cf2f2c56Smiod 			   char **errmsg)
765d2201f2fSdrahn {
766d2201f2fSdrahn   const char *start;
767d2201f2fSdrahn   CGEN_INSN_LIST *ilist;
768d2201f2fSdrahn   const char *parse_errmsg = NULL;
769d2201f2fSdrahn   const char *insert_errmsg = NULL;
770d2201f2fSdrahn   int recognized_mnemonic = 0;
771d2201f2fSdrahn 
772d2201f2fSdrahn   /* Skip leading white space.  */
773d2201f2fSdrahn   while (ISSPACE (* str))
774d2201f2fSdrahn     ++ str;
775d2201f2fSdrahn 
776d2201f2fSdrahn   /* The instructions are stored in hashed lists.
777d2201f2fSdrahn      Get the first in the list.  */
778d2201f2fSdrahn   ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
779d2201f2fSdrahn 
780d2201f2fSdrahn   /* Keep looking until we find a match.  */
781d2201f2fSdrahn   start = str;
782d2201f2fSdrahn   for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
783d2201f2fSdrahn     {
784d2201f2fSdrahn       const CGEN_INSN *insn = ilist->insn;
785d2201f2fSdrahn       recognized_mnemonic = 1;
786d2201f2fSdrahn 
787d2201f2fSdrahn #ifdef CGEN_VALIDATE_INSN_SUPPORTED
788d2201f2fSdrahn       /* Not usually needed as unsupported opcodes
789d2201f2fSdrahn 	 shouldn't be in the hash lists.  */
790d2201f2fSdrahn       /* Is this insn supported by the selected cpu?  */
791d2201f2fSdrahn       if (! iq2000_cgen_insn_supported (cd, insn))
792d2201f2fSdrahn 	continue;
793d2201f2fSdrahn #endif
794*cf2f2c56Smiod       /* If the RELAXED attribute is set, this is an insn that shouldn't be
795d2201f2fSdrahn 	 chosen immediately.  Instead, it is used during assembler/linker
796d2201f2fSdrahn 	 relaxation if possible.  */
797*cf2f2c56Smiod       if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
798d2201f2fSdrahn 	continue;
799d2201f2fSdrahn 
800d2201f2fSdrahn       str = start;
801d2201f2fSdrahn 
802d2201f2fSdrahn       /* Skip this insn if str doesn't look right lexically.  */
803d2201f2fSdrahn       if (CGEN_INSN_RX (insn) != NULL &&
804d2201f2fSdrahn 	  regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
805d2201f2fSdrahn 	continue;
806d2201f2fSdrahn 
807d2201f2fSdrahn       /* Allow parse/insert handlers to obtain length of insn.  */
808d2201f2fSdrahn       CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
809d2201f2fSdrahn 
810d2201f2fSdrahn       parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
811d2201f2fSdrahn       if (parse_errmsg != NULL)
812d2201f2fSdrahn 	continue;
813d2201f2fSdrahn 
814d2201f2fSdrahn       /* ??? 0 is passed for `pc'.  */
815d2201f2fSdrahn       insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
816d2201f2fSdrahn 						 (bfd_vma) 0);
817d2201f2fSdrahn       if (insert_errmsg != NULL)
818d2201f2fSdrahn         continue;
819d2201f2fSdrahn 
820d2201f2fSdrahn       /* It is up to the caller to actually output the insn and any
821d2201f2fSdrahn          queued relocs.  */
822d2201f2fSdrahn       return insn;
823d2201f2fSdrahn     }
824d2201f2fSdrahn 
825d2201f2fSdrahn   {
826d2201f2fSdrahn     static char errbuf[150];
827d2201f2fSdrahn #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
828d2201f2fSdrahn     const char *tmp_errmsg;
829d2201f2fSdrahn 
830d2201f2fSdrahn     /* If requesting verbose error messages, use insert_errmsg.
831d2201f2fSdrahn        Failing that, use parse_errmsg.  */
832d2201f2fSdrahn     tmp_errmsg = (insert_errmsg ? insert_errmsg :
833d2201f2fSdrahn 		  parse_errmsg ? parse_errmsg :
834d2201f2fSdrahn 		  recognized_mnemonic ?
835d2201f2fSdrahn 		  _("unrecognized form of instruction") :
836d2201f2fSdrahn 		  _("unrecognized instruction"));
837d2201f2fSdrahn 
838d2201f2fSdrahn     if (strlen (start) > 50)
839d2201f2fSdrahn       /* xgettext:c-format */
840d2201f2fSdrahn       sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
841d2201f2fSdrahn     else
842d2201f2fSdrahn       /* xgettext:c-format */
843d2201f2fSdrahn       sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
844d2201f2fSdrahn #else
845d2201f2fSdrahn     if (strlen (start) > 50)
846d2201f2fSdrahn       /* xgettext:c-format */
847d2201f2fSdrahn       sprintf (errbuf, _("bad instruction `%.50s...'"), start);
848d2201f2fSdrahn     else
849d2201f2fSdrahn       /* xgettext:c-format */
850d2201f2fSdrahn       sprintf (errbuf, _("bad instruction `%.50s'"), start);
851d2201f2fSdrahn #endif
852d2201f2fSdrahn 
853d2201f2fSdrahn     *errmsg = errbuf;
854d2201f2fSdrahn     return NULL;
855d2201f2fSdrahn   }
856d2201f2fSdrahn }
857d2201f2fSdrahn 
858d2201f2fSdrahn #if 0 /* This calls back to GAS which we can't do without care.  */
859d2201f2fSdrahn 
860d2201f2fSdrahn /* Record each member of OPVALS in the assembler's symbol table.
861d2201f2fSdrahn    This lets GAS parse registers for us.
862d2201f2fSdrahn    ??? Interesting idea but not currently used.  */
863d2201f2fSdrahn 
864d2201f2fSdrahn /* Record each member of OPVALS in the assembler's symbol table.
865d2201f2fSdrahn    FIXME: Not currently used.  */
866d2201f2fSdrahn 
867d2201f2fSdrahn void
868*cf2f2c56Smiod iq2000_cgen_asm_hash_keywords (CGEN_CPU_DESC cd, CGEN_KEYWORD *opvals)
869d2201f2fSdrahn {
870d2201f2fSdrahn   CGEN_KEYWORD_SEARCH search = cgen_keyword_search_init (opvals, NULL);
871d2201f2fSdrahn   const CGEN_KEYWORD_ENTRY * ke;
872d2201f2fSdrahn 
873d2201f2fSdrahn   while ((ke = cgen_keyword_search_next (& search)) != NULL)
874d2201f2fSdrahn     {
875d2201f2fSdrahn #if 0 /* Unnecessary, should be done in the search routine.  */
876d2201f2fSdrahn       if (! iq2000_cgen_opval_supported (ke))
877d2201f2fSdrahn 	continue;
878d2201f2fSdrahn #endif
879d2201f2fSdrahn       cgen_asm_record_register (cd, ke->name, ke->value);
880d2201f2fSdrahn     }
881d2201f2fSdrahn }
882d2201f2fSdrahn 
883d2201f2fSdrahn #endif /* 0 */
884