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