OSDN Git Service

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