This commit was generated by cvs2svn to track changes on a CVS vendor
[platform/upstream/binutils.git] / opcodes / ip2k-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 "ip2k-desc.h"
34 #include "ip2k-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      PARAMS ((CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *));
47 \f
48 /* -- assembler routines inserted here.  */
49
50 /* -- asm.c */
51
52 static const char *
53 parse_fr (cd, strp, opindex, valuep)
54      CGEN_CPU_DESC cd;
55      const char **strp;
56      int opindex;
57      long *valuep;
58 {
59   const char *errmsg;
60   char *old_strp;
61   char *afteroffset; 
62   enum cgen_parse_operand_result result_type;
63   bfd_vma value;
64   extern CGEN_KEYWORD ip2k_cgen_opval_register_names;
65   long tempvalue;
66
67   old_strp = *strp;
68   afteroffset = NULL; 
69
70
71   /* Check here to see if you're about to try parsing a w as the first arg */
72   /* and return an error if you are.                                       */
73   if ( (strncmp(*strp,"w",1)==0) || (strncmp(*strp,"W",1)==0) )
74   {
75      (*strp)++;
76
77      if ( (strncmp(*strp,",",1)==0) || isspace(**strp) )
78      {
79         /* We've been passed a w.  Return with an error message so that  */
80         /* cgen will try the next parsing option.                        */
81         errmsg = _("W keyword invalid in FR operand slot.");
82         return errmsg;
83      }
84      *strp = old_strp;
85   }
86
87
88   /* Attempt parse as register keyword. */
89   /* old_strp = *strp; */
90
91   errmsg = cgen_parse_keyword (cd, strp, & ip2k_cgen_opval_register_names, valuep);
92   if ( *strp != NULL )
93   if (errmsg == NULL)
94     return errmsg;
95
96   /* Attempt to parse for "(IP)" */
97   afteroffset = strstr(*strp,"(IP)");
98
99   if ( afteroffset == NULL)
100   {
101      /* Make sure it's not in lower case */
102      afteroffset = strstr(*strp,"(ip)");
103   }
104
105   if ( afteroffset != NULL )
106     {
107       if ( afteroffset != *strp )
108         {
109           /* Invalid offset present.*/
110           errmsg = _("offset(IP) is not a valid form");
111           return errmsg;
112         }
113       else
114         {
115           *strp += 4; 
116           *valuep = 0;
117           errmsg = NULL;
118           return errmsg;
119         }
120     }
121
122   /* Attempt to parse for DP. ex: mov w, offset(DP)  */
123   /*                              mov offset(DP),w   */
124
125   /* Try parsing it as an address and see what comes back */
126
127   afteroffset = strstr(*strp,"(DP)");
128
129   if ( afteroffset == NULL)
130   {
131      /* Maybe it's in lower case */
132      afteroffset = strstr(*strp,"(dp)");
133   }
134
135   if ( afteroffset != NULL )
136   {
137      if ( afteroffset == *strp )
138      {
139         /* No offset present. Use 0 by default. */
140         tempvalue = 0;
141         errmsg = NULL;
142      }
143      else
144      {
145        errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IP2K_FR_OFFSET,
146                                     & result_type, & tempvalue);
147      }
148
149      if (errmsg == NULL)
150      {
151         if ( (tempvalue >= 0) && (tempvalue <= 127) )
152         {
153            /* Value is ok.  Fix up the first 2 bits and return */       
154            *valuep = 0x0100 | tempvalue;
155            *strp += 4; /* skip over the (DP) in *strp */
156            return errmsg;
157         } else
158         {
159            /* Found something there in front of (DP) but it's out of range. */
160            errmsg = _("(DP) offset out of range.");
161            return errmsg;
162         }
163         
164      }
165   }
166
167
168   /* Attempt to parse for SP. ex: mov w, offset(SP)  */
169   /*                              mov offset(SP), w  */
170
171
172   afteroffset = strstr(*strp,"(SP)");
173
174   if (afteroffset == NULL)
175   {
176      /* Maybe it's in lower case. */
177      afteroffset = strstr(*strp, "(sp)");
178   }
179
180   if ( afteroffset != NULL )
181   {
182      if ( afteroffset ==  *strp )
183      {
184         /* No offset present. Use 0 by default. */
185         tempvalue = 0;
186         errmsg = NULL;
187      }
188      else
189      {
190        errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IP2K_FR_OFFSET,
191                                     & result_type, & tempvalue);
192      }
193      if (errmsg == NULL)
194      {
195         if ( (tempvalue >= 0) && (tempvalue <= 127) )
196         {
197            /* Value is ok.  Fix up the first 2 bits and return */
198            *valuep = 0x0180 | tempvalue;
199            *strp += 4; /* skip over the (SP) in *strp */
200            return errmsg;
201         } else
202         {
203            /* Found something there in front of (SP) but it's out of range. */
204            errmsg = _("(SP) offset out of range.");
205            return errmsg;
206         }
207         
208      }
209   }
210
211
212   /* Attempt to parse as an address. */
213   *strp = old_strp;
214   errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IP2K_FR9,
215                                & result_type, & value);
216   if (errmsg == NULL)
217     {
218       *valuep = value;
219
220       /* if a parenthesis is found, warn about invalid form */
221
222       if (**strp == '(')
223         {
224           errmsg = _("illegal use of parentheses");
225         }
226       /* if a numeric value is specified, ensure that it is between 1 and 255 */
227       else if (result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
228         {
229           if (value < 0x1 || value > 0xff)
230             errmsg = _("operand out of range (not between 1 and 255)");
231         }
232     }
233   return errmsg;
234 }
235
236 static const char *
237 parse_addr16 (cd, strp, opindex, valuep)
238      CGEN_CPU_DESC cd;
239      const char **strp;
240      int opindex;
241      long *valuep;
242 {
243   const char *errmsg;
244   enum cgen_parse_operand_result result_type;
245   bfd_reloc_code_real_type code = BFD_RELOC_NONE;
246   long value;
247
248   if ( opindex == (CGEN_OPERAND_TYPE)IP2K_OPERAND_ADDR16H )
249       code = BFD_RELOC_IP2K_HI8DATA;
250   else if ( opindex == (CGEN_OPERAND_TYPE)IP2K_OPERAND_ADDR16L )
251       code = BFD_RELOC_IP2K_LO8DATA;
252   else
253     {
254       /* Something is very wrong. opindex has to be one of the above. */
255       errmsg = _("parse_addr16: invalid opindex.");
256       return errmsg;
257     }
258   
259   errmsg = cgen_parse_address (cd, strp, opindex, code,
260                                   & result_type, & value);
261   if (errmsg == NULL)
262     {
263        /* We either have a relocation or a number now. */
264       if ( result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER )
265       {
266          /* We got a number back. */
267          if ( code == BFD_RELOC_IP2K_HI8DATA )
268             value >>= 8;
269          else    /* code = BFD_RELOC_IP2K_LOW8DATA */
270             value &= 0x00FF;
271       }   
272          *valuep = value;
273    }
274
275   return errmsg;
276 }
277
278
279  static const char *
280  parse_addr16_p (cd, strp, opindex, valuep)
281       CGEN_CPU_DESC cd;
282       const char **strp;
283       int opindex;
284       long *valuep;
285  {
286    const char *errmsg;
287    enum cgen_parse_operand_result result_type;
288    bfd_reloc_code_real_type code = BFD_RELOC_IP2K_PAGE3;
289    long value;
290  
291    errmsg = cgen_parse_address (cd, strp, opindex, code,
292                                  & result_type, & value);
293    if (errmsg == NULL)
294    {
295        if ( result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER )
296             *valuep = (value >> 13) & 0x7;
297        else if ( result_type == CGEN_PARSE_OPERAND_RESULT_QUEUED )
298             *valuep = value;
299    }
300    return errmsg; 
301  }
302
303
304  static const char *
305  parse_addr16_cjp (cd, strp, opindex, valuep)
306       CGEN_CPU_DESC cd;
307       const char **strp;
308       int opindex;
309       long *valuep;
310  {
311    const char *errmsg;
312    enum cgen_parse_operand_result result_type;
313    bfd_reloc_code_real_type code = BFD_RELOC_NONE;
314    long value;
315  
316    if ( opindex == (CGEN_OPERAND_TYPE)IP2K_OPERAND_ADDR16CJP )
317       code = BFD_RELOC_IP2K_ADDR16CJP;
318    else if ( opindex == (CGEN_OPERAND_TYPE)IP2K_OPERAND_ADDR16P )
319       code = BFD_RELOC_IP2K_PAGE3;
320
321    errmsg = cgen_parse_address (cd, strp, opindex, code,
322                                  & result_type, & value);
323    if (errmsg == NULL)
324    {
325        if ( result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER )
326        {
327          if ( (value & 0x1) == 0)  /* If the address is even .... */
328          {
329              if ( opindex == (CGEN_OPERAND_TYPE)IP2K_OPERAND_ADDR16CJP )
330                 *valuep = (value >> 1) & 0x1FFF;  /* Should mask be 1FFF? */
331              else if ( opindex == (CGEN_OPERAND_TYPE)IP2K_OPERAND_ADDR16P )
332                 *valuep = (value >> 14) & 0x7;
333           }
334           else
335             errmsg = _("Byte address required. - must be even.");
336        }else if ( result_type == CGEN_PARSE_OPERAND_RESULT_QUEUED )
337        {
338             /* This will happen for things like (s2-s1) where s2 and s1 */
339             /* are labels.                                              */
340             *valuep = value;
341         }
342       else 
343         errmsg = _("cgen_parse_address returned a symbol. Literal required.");
344    }
345    return errmsg; 
346  }
347
348
349 static const char *
350 parse_lit8 (cd, strp, opindex, valuep)
351      CGEN_CPU_DESC cd;
352      const char **strp;
353      int opindex;
354      long *valuep;
355 {
356   const char *errmsg;
357   enum cgen_parse_operand_result result_type;
358   bfd_reloc_code_real_type code = BFD_RELOC_NONE;
359   long value;
360
361   /* Parse %OP relocating operators. */
362   if (strncmp (*strp, "%bank", 5) == 0)
363     {
364       *strp += 5;
365       code = BFD_RELOC_IP2K_BANK;
366     }
367   else if (strncmp (*strp, "%lo8data", 8) == 0)
368     {
369       *strp += 8;
370       code = BFD_RELOC_IP2K_LO8DATA;
371     }
372   else if (strncmp (*strp, "%hi8data", 8) == 0)
373     {
374       *strp += 8;
375       code = BFD_RELOC_IP2K_HI8DATA;
376     }
377   else if (strncmp (*strp, "%ex8data", 8) == 0)
378     {
379       *strp += 8;
380       code = BFD_RELOC_IP2K_EX8DATA;
381     }
382   else if (strncmp (*strp, "%lo8insn", 8) == 0)
383     {
384       *strp += 8;
385       code = BFD_RELOC_IP2K_LO8INSN;
386     }
387   else if (strncmp (*strp, "%hi8insn", 8) == 0)
388     {
389       *strp += 8;
390       code = BFD_RELOC_IP2K_HI8INSN;
391     }
392   
393
394   /* Parse %op operand.  */
395   if (code != BFD_RELOC_NONE)
396     {
397       errmsg = cgen_parse_address (cd, strp, opindex, code, 
398                                    & result_type, & value);
399       if ((errmsg == NULL) &&
400           (result_type != CGEN_PARSE_OPERAND_RESULT_QUEUED))
401         errmsg = _("%operator operand is not a symbol");
402
403       *valuep = value;
404     }
405   /* Parse as a number.  */
406   else
407     {
408       errmsg = cgen_parse_signed_integer (cd, strp, opindex, valuep);
409
410       /* Truncate to eight bits to accept both signed and unsigned input. */
411       if (errmsg == NULL)
412         *valuep &= 0xFF;
413     }
414
415   return errmsg;
416 }
417
418 static const char *
419 parse_bit3 (cd, strp, opindex, valuep)
420      CGEN_CPU_DESC cd;
421      const char **strp;
422      int opindex;
423      long *valuep;
424 {
425   const char *errmsg;
426   char mode = 0;
427   long count = 0;
428   unsigned long value;
429
430   if (strncmp (*strp, "%bit", 4) == 0)
431     {
432       *strp += 4;
433       mode = 1;
434     }
435   else if (strncmp (*strp, "%msbbit", 7) == 0)
436     {
437       *strp += 7;
438       mode = 1;
439     }
440   else if (strncmp (*strp, "%lsbbit", 7) == 0)
441     {
442       *strp += 7;
443       mode = 2;
444     }
445
446   errmsg = cgen_parse_signed_integer (cd, strp, opindex, valuep);
447   if (errmsg) {
448     return errmsg;
449   }
450
451   if (mode) {
452     value = (unsigned long) *valuep;
453     if (value == 0) {
454       errmsg = _("Attempt to find bit index of 0");
455       return errmsg;
456     }
457     
458     if (mode == 1) {
459       count = 31;
460       while ((value & 0x80000000) == 0) {
461         count--;
462         value <<= 1;
463       }
464     } else if (mode == 2) {
465       count = 0;
466       while ((value & 0x00000001) == 0) {
467         count++;
468         value >>= 1;
469       }
470     }
471     
472     *valuep = count;
473   }
474
475   return errmsg;
476 }
477
478
479 /* -- dis.c */
480
481 const char * ip2k_cgen_parse_operand
482   PARAMS ((CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *));
483
484 /* Main entry point for operand parsing.
485
486    This function is basically just a big switch statement.  Earlier versions
487    used tables to look up the function to use, but
488    - if the table contains both assembler and disassembler functions then
489      the disassembler contains much of the assembler and vice-versa,
490    - there's a lot of inlining possibilities as things grow,
491    - using a switch statement avoids the function call overhead.
492
493    This function could be moved into `parse_insn_normal', but keeping it
494    separate makes clear the interface between `parse_insn_normal' and each of
495    the handlers.  */
496
497 const char *
498 ip2k_cgen_parse_operand (cd, opindex, strp, fields)
499      CGEN_CPU_DESC cd;
500      int opindex;
501      const char ** strp;
502      CGEN_FIELDS * fields;
503 {
504   const char * errmsg = NULL;
505   /* Used by scalar operands that still need to be parsed.  */
506   long junk ATTRIBUTE_UNUSED;
507
508   switch (opindex)
509     {
510     case IP2K_OPERAND_ADDR16CJP :
511       errmsg = parse_addr16_cjp (cd, strp, IP2K_OPERAND_ADDR16CJP, &fields->f_addr16cjp);
512       break;
513     case IP2K_OPERAND_ADDR16H :
514       errmsg = parse_addr16 (cd, strp, IP2K_OPERAND_ADDR16H, &fields->f_imm8);
515       break;
516     case IP2K_OPERAND_ADDR16L :
517       errmsg = parse_addr16 (cd, strp, IP2K_OPERAND_ADDR16L, &fields->f_imm8);
518       break;
519     case IP2K_OPERAND_ADDR16P :
520       errmsg = parse_addr16_cjp (cd, strp, IP2K_OPERAND_ADDR16P, &fields->f_page3);
521       break;
522     case IP2K_OPERAND_BITNO :
523       errmsg = parse_bit3 (cd, strp, IP2K_OPERAND_BITNO, &fields->f_bitno);
524       break;
525     case IP2K_OPERAND_CBIT :
526       errmsg = cgen_parse_unsigned_integer (cd, strp, IP2K_OPERAND_CBIT, &junk);
527       break;
528     case IP2K_OPERAND_DCBIT :
529       errmsg = cgen_parse_unsigned_integer (cd, strp, IP2K_OPERAND_DCBIT, &junk);
530       break;
531     case IP2K_OPERAND_FR :
532       errmsg = parse_fr (cd, strp, IP2K_OPERAND_FR, &fields->f_reg);
533       break;
534     case IP2K_OPERAND_LIT8 :
535       errmsg = parse_lit8 (cd, strp, IP2K_OPERAND_LIT8, &fields->f_imm8);
536       break;
537     case IP2K_OPERAND_PABITS :
538       errmsg = cgen_parse_unsigned_integer (cd, strp, IP2K_OPERAND_PABITS, &junk);
539       break;
540     case IP2K_OPERAND_RETI3 :
541       errmsg = cgen_parse_unsigned_integer (cd, strp, IP2K_OPERAND_RETI3, &fields->f_reti3);
542       break;
543     case IP2K_OPERAND_ZBIT :
544       errmsg = cgen_parse_unsigned_integer (cd, strp, IP2K_OPERAND_ZBIT, &junk);
545       break;
546
547     default :
548       /* xgettext:c-format */
549       fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
550       abort ();
551   }
552
553   return errmsg;
554 }
555
556 cgen_parse_fn * const ip2k_cgen_parse_handlers[] = 
557 {
558   parse_insn_normal,
559 };
560
561 void
562 ip2k_cgen_init_asm (cd)
563      CGEN_CPU_DESC cd;
564 {
565   ip2k_cgen_init_opcode_table (cd);
566   ip2k_cgen_init_ibld_table (cd);
567   cd->parse_handlers = & ip2k_cgen_parse_handlers[0];
568   cd->parse_operand = ip2k_cgen_parse_operand;
569 }
570
571 \f
572
573 /* Regex construction routine.
574
575    This translates an opcode syntax string into a regex string,
576    by replacing any non-character syntax element (such as an
577    opcode) with the pattern '.*'
578
579    It then compiles the regex and stores it in the opcode, for
580    later use by ip2k_cgen_assemble_insn
581
582    Returns NULL for success, an error message for failure.  */
583
584 char * 
585 ip2k_cgen_build_insn_regex (insn)
586      CGEN_INSN *insn;
587 {  
588   CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
589   const char *mnem = CGEN_INSN_MNEMONIC (insn);
590   char rxbuf[CGEN_MAX_RX_ELEMENTS];
591   char *rx = rxbuf;
592   const CGEN_SYNTAX_CHAR_TYPE *syn;
593   int reg_err;
594
595   syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
596
597   /* Mnemonics come first in the syntax string.  */
598   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
599     return _("missing mnemonic in syntax string");
600   ++syn;
601
602   /* Generate a case sensitive regular expression that emulates case
603      insensitive matching in the "C" locale.  We cannot generate a case
604      insensitive regular expression because in Turkish locales, 'i' and 'I'
605      are not equal modulo case conversion.  */
606
607   /* Copy the literal mnemonic out of the insn.  */
608   for (; *mnem; mnem++)
609     {
610       char c = *mnem;
611
612       if (ISALPHA (c))
613         {
614           *rx++ = '[';
615           *rx++ = TOLOWER (c);
616           *rx++ = TOUPPER (c);
617           *rx++ = ']';
618         }
619       else
620         *rx++ = c;
621     }
622
623   /* Copy any remaining literals from the syntax string into the rx.  */
624   for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
625     {
626       if (CGEN_SYNTAX_CHAR_P (* syn)) 
627         {
628           char c = CGEN_SYNTAX_CHAR (* syn);
629
630           switch (c) 
631             {
632               /* Escape any regex metacharacters in the syntax.  */
633             case '.': case '[': case '\\': 
634             case '*': case '^': case '$': 
635
636 #ifdef CGEN_ESCAPE_EXTENDED_REGEX
637             case '?': case '{': case '}': 
638             case '(': case ')': case '*':
639             case '|': case '+': case ']':
640 #endif
641               *rx++ = '\\';
642               *rx++ = c;
643               break;
644
645             default:
646               if (ISALPHA (c))
647                 {
648                   *rx++ = '[';
649                   *rx++ = TOLOWER (c);
650                   *rx++ = TOUPPER (c);
651                   *rx++ = ']';
652                 }
653               else
654                 *rx++ = c;
655               break;
656             }
657         }
658       else
659         {
660           /* Replace non-syntax fields with globs.  */
661           *rx++ = '.';
662           *rx++ = '*';
663         }
664     }
665
666   /* Trailing whitespace ok.  */
667   * rx++ = '['; 
668   * rx++ = ' '; 
669   * rx++ = '\t'; 
670   * rx++ = ']'; 
671   * rx++ = '*'; 
672
673   /* But anchor it after that.  */
674   * rx++ = '$'; 
675   * rx = '\0';
676
677   CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
678   reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
679
680   if (reg_err == 0) 
681     return NULL;
682   else
683     {
684       static char msg[80];
685
686       regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
687       regfree ((regex_t *) CGEN_INSN_RX (insn));
688       free (CGEN_INSN_RX (insn));
689       (CGEN_INSN_RX (insn)) = NULL;
690       return msg;
691     }
692 }
693
694 \f
695 /* Default insn parser.
696
697    The syntax string is scanned and operands are parsed and stored in FIELDS.
698    Relocs are queued as we go via other callbacks.
699
700    ??? Note that this is currently an all-or-nothing parser.  If we fail to
701    parse the instruction, we return 0 and the caller will start over from
702    the beginning.  Backtracking will be necessary in parsing subexpressions,
703    but that can be handled there.  Not handling backtracking here may get
704    expensive in the case of the m68k.  Deal with later.
705
706    Returns NULL for success, an error message for failure.  */
707
708 static const char *
709 parse_insn_normal (cd, insn, strp, fields)
710      CGEN_CPU_DESC cd;
711      const CGEN_INSN *insn;
712      const char **strp;
713      CGEN_FIELDS *fields;
714 {
715   /* ??? Runtime added insns not handled yet.  */
716   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
717   const char *str = *strp;
718   const char *errmsg;
719   const char *p;
720   const CGEN_SYNTAX_CHAR_TYPE * syn;
721 #ifdef CGEN_MNEMONIC_OPERANDS
722   /* FIXME: wip */
723   int past_opcode_p;
724 #endif
725
726   /* For now we assume the mnemonic is first (there are no leading operands).
727      We can parse it without needing to set up operand parsing.
728      GAS's input scrubber will ensure mnemonics are lowercase, but we may
729      not be called from GAS.  */
730   p = CGEN_INSN_MNEMONIC (insn);
731   while (*p && TOLOWER (*p) == TOLOWER (*str))
732     ++p, ++str;
733
734   if (* p)
735     return _("unrecognized instruction");
736
737 #ifndef CGEN_MNEMONIC_OPERANDS
738   if (* str && ! ISSPACE (* str))
739     return _("unrecognized instruction");
740 #endif
741
742   CGEN_INIT_PARSE (cd);
743   cgen_init_parse_operand (cd);
744 #ifdef CGEN_MNEMONIC_OPERANDS
745   past_opcode_p = 0;
746 #endif
747
748   /* We don't check for (*str != '\0') here because we want to parse
749      any trailing fake arguments in the syntax string.  */
750   syn = CGEN_SYNTAX_STRING (syntax);
751
752   /* Mnemonics come first for now, ensure valid string.  */
753   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
754     abort ();
755
756   ++syn;
757
758   while (* syn != 0)
759     {
760       /* Non operand chars must match exactly.  */
761       if (CGEN_SYNTAX_CHAR_P (* syn))
762         {
763           /* FIXME: While we allow for non-GAS callers above, we assume the
764              first char after the mnemonic part is a space.  */
765           /* FIXME: We also take inappropriate advantage of the fact that
766              GAS's input scrubber will remove extraneous blanks.  */
767           if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
768             {
769 #ifdef CGEN_MNEMONIC_OPERANDS
770               if (CGEN_SYNTAX_CHAR(* syn) == ' ')
771                 past_opcode_p = 1;
772 #endif
773               ++ syn;
774               ++ str;
775             }
776           else if (*str)
777             {
778               /* Syntax char didn't match.  Can't be this insn.  */
779               static char msg [80];
780
781               /* xgettext:c-format */
782               sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
783                        CGEN_SYNTAX_CHAR(*syn), *str);
784               return msg;
785             }
786           else
787             {
788               /* Ran out of input.  */
789               static char msg [80];
790
791               /* xgettext:c-format */
792               sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
793                        CGEN_SYNTAX_CHAR(*syn));
794               return msg;
795             }
796           continue;
797         }
798
799       /* We have an operand of some sort.  */
800       errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn),
801                                           &str, fields);
802       if (errmsg)
803         return errmsg;
804
805       /* Done with this operand, continue with next one.  */
806       ++ syn;
807     }
808
809   /* If we're at the end of the syntax string, we're done.  */
810   if (* syn == 0)
811     {
812       /* FIXME: For the moment we assume a valid `str' can only contain
813          blanks now.  IE: We needn't try again with a longer version of
814          the insn and it is assumed that longer versions of insns appear
815          before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
816       while (ISSPACE (* str))
817         ++ str;
818
819       if (* str != '\0')
820         return _("junk at end of line"); /* FIXME: would like to include `str' */
821
822       return NULL;
823     }
824
825   /* We couldn't parse it.  */
826   return _("unrecognized instruction");
827 }
828 \f
829 /* Main entry point.
830    This routine is called for each instruction to be assembled.
831    STR points to the insn to be assembled.
832    We assume all necessary tables have been initialized.
833    The assembled instruction, less any fixups, is stored in BUF.
834    Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
835    still needs to be converted to target byte order, otherwise BUF is an array
836    of bytes in target byte order.
837    The result is a pointer to the insn's entry in the opcode table,
838    or NULL if an error occured (an error message will have already been
839    printed).
840
841    Note that when processing (non-alias) macro-insns,
842    this function recurses.
843
844    ??? It's possible to make this cpu-independent.
845    One would have to deal with a few minor things.
846    At this point in time doing so would be more of a curiosity than useful
847    [for example this file isn't _that_ big], but keeping the possibility in
848    mind helps keep the design clean.  */
849
850 const CGEN_INSN *
851 ip2k_cgen_assemble_insn (cd, str, fields, buf, errmsg)
852      CGEN_CPU_DESC cd;
853      const char *str;
854      CGEN_FIELDS *fields;
855      CGEN_INSN_BYTES_PTR buf;
856      char **errmsg;
857 {
858   const char *start;
859   CGEN_INSN_LIST *ilist;
860   const char *parse_errmsg = NULL;
861   const char *insert_errmsg = NULL;
862   int recognized_mnemonic = 0;
863
864   /* Skip leading white space.  */
865   while (ISSPACE (* str))
866     ++ str;
867
868   /* The instructions are stored in hashed lists.
869      Get the first in the list.  */
870   ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
871
872   /* Keep looking until we find a match.  */
873   start = str;
874   for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
875     {
876       const CGEN_INSN *insn = ilist->insn;
877       recognized_mnemonic = 1;
878
879 #ifdef CGEN_VALIDATE_INSN_SUPPORTED 
880       /* Not usually needed as unsupported opcodes
881          shouldn't be in the hash lists.  */
882       /* Is this insn supported by the selected cpu?  */
883       if (! ip2k_cgen_insn_supported (cd, insn))
884         continue;
885 #endif
886       /* If the RELAX attribute is set, this is an insn that shouldn't be
887          chosen immediately.  Instead, it is used during assembler/linker
888          relaxation if possible.  */
889       if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAX) != 0)
890         continue;
891
892       str = start;
893
894       /* Skip this insn if str doesn't look right lexically.  */
895       if (CGEN_INSN_RX (insn) != NULL &&
896           regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
897         continue;
898
899       /* Allow parse/insert handlers to obtain length of insn.  */
900       CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
901
902       parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
903       if (parse_errmsg != NULL)
904         continue;
905
906       /* ??? 0 is passed for `pc'.  */
907       insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
908                                                  (bfd_vma) 0);
909       if (insert_errmsg != NULL)
910         continue;
911
912       /* It is up to the caller to actually output the insn and any
913          queued relocs.  */
914       return insn;
915     }
916
917   {
918     static char errbuf[150];
919 #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
920     const char *tmp_errmsg;
921
922     /* If requesting verbose error messages, use insert_errmsg.
923        Failing that, use parse_errmsg.  */
924     tmp_errmsg = (insert_errmsg ? insert_errmsg :
925                   parse_errmsg ? parse_errmsg :
926                   recognized_mnemonic ?
927                   _("unrecognized form of instruction") :
928                   _("unrecognized instruction"));
929
930     if (strlen (start) > 50)
931       /* xgettext:c-format */
932       sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
933     else 
934       /* xgettext:c-format */
935       sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
936 #else
937     if (strlen (start) > 50)
938       /* xgettext:c-format */
939       sprintf (errbuf, _("bad instruction `%.50s...'"), start);
940     else 
941       /* xgettext:c-format */
942       sprintf (errbuf, _("bad instruction `%.50s'"), start);
943 #endif
944       
945     *errmsg = errbuf;
946     return NULL;
947   }
948 }
949 \f
950 #if 0 /* This calls back to GAS which we can't do without care.  */
951
952 /* Record each member of OPVALS in the assembler's symbol table.
953    This lets GAS parse registers for us.
954    ??? Interesting idea but not currently used.  */
955
956 /* Record each member of OPVALS in the assembler's symbol table.
957    FIXME: Not currently used.  */
958
959 void
960 ip2k_cgen_asm_hash_keywords (cd, opvals)
961      CGEN_CPU_DESC cd;
962      CGEN_KEYWORD *opvals;
963 {
964   CGEN_KEYWORD_SEARCH search = cgen_keyword_search_init (opvals, NULL);
965   const CGEN_KEYWORD_ENTRY * ke;
966
967   while ((ke = cgen_keyword_search_next (& search)) != NULL)
968     {
969 #if 0 /* Unnecessary, should be done in the search routine.  */
970       if (! ip2k_cgen_opval_supported (ke))
971         continue;
972 #endif
973       cgen_asm_record_register (cd, ke->name, ke->value);
974     }
975 }
976
977 #endif /* 0 */