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 (C) 1996-2016 Free Software Foundation, Inc.
8 
9    This file is part of libopcodes.
10 
11    This library 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 3, or (at your option)
14    any later version.
15 
16    It is distributed in the hope that it will be useful, but WITHOUT
17    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
19    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    51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
24 
25 
26 /* ??? Eventually more and more of this stuff can go to cpu-independent files.
27    Keep that in mind.  */
28 
29 #include "sysdep.h"
30 #include <stdio.h>
31 #include "ansidecl.h"
32 #include "bfd.h"
33 #include "symcat.h"
34 #include "epiphany-desc.h"
35 #include "epiphany-opc.h"
36 #include "opintl.h"
37 #include "xregex.h"
38 #include "libiberty.h"
39 #include "safe-ctype.h"
40 
41 #undef  min
42 #define min(a,b) ((a) < (b) ? (a) : (b))
43 #undef  max
44 #define max(a,b) ((a) > (b) ? (a) : (b))
45 
46 static const char * parse_insn_normal
47   (CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *);
48 
49 /* -- assembler routines inserted here.  */
50 
51 /* -- asm.c */
52 const char *
parse_shortregs(CGEN_CPU_DESC cd,const char ** strp,CGEN_KEYWORD * keywords,long * regno)53 parse_shortregs (CGEN_CPU_DESC cd,
54 		 const char ** strp,
55 		 CGEN_KEYWORD * keywords,
56 		 long * regno)
57 {
58   const char * errmsg;
59 
60   /* Parse register.  */
61   errmsg = cgen_parse_keyword (cd, strp, keywords, regno);
62 
63   if (errmsg)
64     return errmsg;
65 
66   if (*regno > 7)
67     errmsg = _("register unavailable for short instructions");
68 
69   return errmsg;
70 }
71 
72 static const char * parse_simm_not_reg (CGEN_CPU_DESC, const char **, int,
73 					long *);
74 
75 static const char *
parse_uimm_not_reg(CGEN_CPU_DESC cd,const char ** strp,int opindex,unsigned long * valuep)76 parse_uimm_not_reg (CGEN_CPU_DESC cd,
77 		    const char ** strp,
78 		    int opindex,
79 		    unsigned long * valuep)
80 {
81   long * svalp = (void *) valuep;
82   return parse_simm_not_reg (cd, strp, opindex, svalp);
83 }
84 
85 /* Handle simm3/simm11/imm3/imm12.  */
86 
87 static const char *
parse_simm_not_reg(CGEN_CPU_DESC cd,const char ** strp,int opindex,long * valuep)88 parse_simm_not_reg (CGEN_CPU_DESC cd,
89 		   const char ** strp,
90 		   int opindex,
91 		   long * valuep)
92 {
93   const char * errmsg;
94 
95   int   sign = 0;
96   int   bits = 0;
97 
98   switch (opindex)
99     {
100     case EPIPHANY_OPERAND_SIMM3:
101       sign = 1; bits = 3; break;
102     case EPIPHANY_OPERAND_SIMM11:
103       sign = 1; bits = 11; break;
104     case EPIPHANY_OPERAND_DISP3:
105       sign = 0; bits = 3; break;
106     case EPIPHANY_OPERAND_DISP11:
107       /* Load/store displacement is a sign-magnitude 12 bit value.  */
108       sign = 0; bits = 11; break;
109     }
110 
111   /* First try to parse as a register name and reject the operand.  */
112   errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_gr_names,valuep);
113   if (!errmsg)
114     return _("register name used as immediate value");
115 
116   errmsg = (sign ? cgen_parse_signed_integer (cd, strp, opindex, valuep)
117 	    : cgen_parse_unsigned_integer (cd, strp, opindex,
118 					  (unsigned long *) valuep));
119   if (errmsg)
120     return errmsg;
121 
122   if (sign)
123     errmsg = cgen_validate_signed_integer (*valuep,
124 					  -((1L << bits) - 1), (1 << (bits - 1)) - 1);
125   else
126     errmsg = cgen_validate_unsigned_integer (*valuep, 0, (1L << bits) - 1);
127 
128   return errmsg;
129 }
130 
131 static const char *
parse_postindex(CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,const char ** strp,int opindex ATTRIBUTE_UNUSED,unsigned long * valuep)132 parse_postindex (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
133 		 const char ** strp,
134 		 int opindex ATTRIBUTE_UNUSED,
135 		 unsigned long *valuep)
136 {
137   if (**strp == '#')
138     ++*strp;			/* Skip leading hashes.  */
139 
140   if (**strp == '-')
141     {
142       *valuep = 1;
143       ++*strp;
144     }
145   else if (**strp == '+')
146     {
147       *valuep = 0;
148       ++*strp;
149     }
150   else
151     *valuep = 0;
152 
153   return NULL;
154 }
155 
156 static const char *
parse_imm8(CGEN_CPU_DESC cd,const char ** strp,int opindex,bfd_reloc_code_real_type code,enum cgen_parse_operand_result * result_type,bfd_vma * valuep)157 parse_imm8 (CGEN_CPU_DESC cd,
158 	    const char ** strp,
159 	    int opindex,
160 	    bfd_reloc_code_real_type code,
161 	    enum cgen_parse_operand_result * result_type,
162 	    bfd_vma * valuep)
163 {
164   const char * errmsg;
165   enum cgen_parse_operand_result rt;
166   long dummyval;
167 
168   if (!result_type)
169     result_type = &rt;
170 
171   code = BFD_RELOC_NONE;
172 
173   if (!cgen_parse_keyword (cd, strp, &epiphany_cgen_opval_gr_names, &dummyval)
174       || !cgen_parse_keyword (cd, strp, &epiphany_cgen_opval_cr_names,
175 			      &dummyval))
176     /* Don't treat "mov ip,ip" as a move-immediate.  */
177     return _("register source in immediate move");
178 
179   errmsg = cgen_parse_address (cd, strp, opindex, code, result_type, valuep);
180   if (errmsg)
181     return errmsg;
182 
183   if (*result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
184     errmsg = cgen_validate_unsigned_integer (*valuep, 0, 0xff);
185   else
186     errmsg = _("byte relocation unsupported");
187 
188   *valuep &= 0xff;
189   return errmsg;
190 }
191 
192 static const char * MISSING_CLOSE_PARENTHESIS = N_("missing `)'");
193 
194 static const char *
parse_imm16(CGEN_CPU_DESC cd,const char ** strp,int opindex,bfd_reloc_code_real_type code ATTRIBUTE_UNUSED,enum cgen_parse_operand_result * result_type,bfd_vma * valuep)195 parse_imm16 (CGEN_CPU_DESC cd,
196 	     const char ** strp,
197 	     int opindex,
198 	     bfd_reloc_code_real_type code ATTRIBUTE_UNUSED,
199 	     enum cgen_parse_operand_result * result_type,
200 	     bfd_vma * valuep)
201 {
202   const char * errmsg;
203   enum cgen_parse_operand_result rt;
204   long dummyval;
205 
206   if (!result_type)
207     result_type = &rt;
208 
209   if (strncasecmp (*strp, "%high(", 6) == 0)
210     {
211       *strp += 6;
212       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_EPIPHANY_HIGH,
213 				   result_type, valuep);
214       if (**strp != ')')
215 	return MISSING_CLOSE_PARENTHESIS;
216       ++*strp;
217       *valuep >>= 16;
218     }
219   else if (strncasecmp (*strp, "%low(", 5) == 0)
220     {
221       *strp += 5;
222       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_EPIPHANY_LOW,
223 				   result_type, valuep);
224       if (**strp != ')')
225 	return MISSING_CLOSE_PARENTHESIS;
226       ++*strp;
227     }
228   else if (!cgen_parse_keyword (cd, strp, &epiphany_cgen_opval_gr_names,
229 				&dummyval)
230 	   || !cgen_parse_keyword (cd, strp, &epiphany_cgen_opval_cr_names,
231 				   &dummyval))
232     /* Don't treat "mov ip,ip" as a move-immediate.  */
233     return _("register source in immediate move");
234   else
235     errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_16,
236 				 result_type, valuep);
237 
238   if (!errmsg && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
239     errmsg = cgen_validate_unsigned_integer (*valuep, 0, 0xffff);
240 
241   *valuep &= 0xffff;
242   return errmsg;
243 }
244 
245 const char *
parse_branch_addr(CGEN_CPU_DESC cd,const char ** strp,int opindex,int opinfo ATTRIBUTE_UNUSED,enum cgen_parse_operand_result * resultp ATTRIBUTE_UNUSED,bfd_vma * valuep ATTRIBUTE_UNUSED)246 parse_branch_addr (CGEN_CPU_DESC cd,
247 		   const char ** strp,
248 		   int opindex,
249 		   int opinfo ATTRIBUTE_UNUSED,
250 		   enum cgen_parse_operand_result * resultp ATTRIBUTE_UNUSED,
251 		   bfd_vma *valuep ATTRIBUTE_UNUSED)
252 {
253   const char * errmsg;
254   enum cgen_parse_operand_result result_type;
255   bfd_reloc_code_real_type code = BFD_RELOC_NONE;
256   bfd_vma value;
257 
258   switch (opindex)
259     {
260     case EPIPHANY_OPERAND_SIMM24:
261       code = BFD_RELOC_EPIPHANY_SIMM24;
262       break;
263 
264     case EPIPHANY_OPERAND_SIMM8:
265       code = BFD_RELOC_EPIPHANY_SIMM8;
266       break;
267 
268     default:
269       errmsg = _("ABORT: unknown operand");
270       return errmsg;
271     }
272 
273   errmsg = cgen_parse_address (cd, strp, opindex, code,
274 			       &result_type, &value);
275   if (errmsg == NULL)
276     {
277       if (result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
278 	{
279 	  /* Act as if we had done a PC-relative branch, ala .+num.  */
280 	  char buf[20];
281 	  const char * bufp = (const char *) buf;
282 
283 	  sprintf (buf, ".+%ld", (long) value);
284 	  errmsg = cgen_parse_address (cd, &bufp, opindex, code, &result_type,
285 				       &value);
286 	}
287 
288       if (result_type == CGEN_PARSE_OPERAND_RESULT_QUEUED)
289 	{
290 	  /* This will happen for things like (s2-s1) where s2 and s1
291 	     are labels.  */
292 	  /* Nothing further to be done.  */
293 	}
294       else
295 	errmsg = _("Not a pc-relative address.");
296     }
297   return errmsg;
298 }
299 
300 /* -- dis.c */
301 
302 const char * epiphany_cgen_parse_operand
303   (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
304 
305 /* Main entry point for operand parsing.
306 
307    This function is basically just a big switch statement.  Earlier versions
308    used tables to look up the function to use, but
309    - if the table contains both assembler and disassembler functions then
310      the disassembler contains much of the assembler and vice-versa,
311    - there's a lot of inlining possibilities as things grow,
312    - using a switch statement avoids the function call overhead.
313 
314    This function could be moved into `parse_insn_normal', but keeping it
315    separate makes clear the interface between `parse_insn_normal' and each of
316    the handlers.  */
317 
318 const char *
epiphany_cgen_parse_operand(CGEN_CPU_DESC cd,int opindex,const char ** strp,CGEN_FIELDS * fields)319 epiphany_cgen_parse_operand (CGEN_CPU_DESC cd,
320 			   int opindex,
321 			   const char ** strp,
322 			   CGEN_FIELDS * fields)
323 {
324   const char * errmsg = NULL;
325   /* Used by scalar operands that still need to be parsed.  */
326   long junk ATTRIBUTE_UNUSED;
327 
328   switch (opindex)
329     {
330     case EPIPHANY_OPERAND_DIRECTION :
331       errmsg = parse_postindex (cd, strp, EPIPHANY_OPERAND_DIRECTION, (unsigned long *) (& fields->f_addsubx));
332       break;
333     case EPIPHANY_OPERAND_DISP11 :
334       errmsg = parse_uimm_not_reg (cd, strp, EPIPHANY_OPERAND_DISP11, (unsigned long *) (& fields->f_disp11));
335       break;
336     case EPIPHANY_OPERAND_DISP3 :
337       errmsg = cgen_parse_unsigned_integer (cd, strp, EPIPHANY_OPERAND_DISP3, (unsigned long *) (& fields->f_disp3));
338       break;
339     case EPIPHANY_OPERAND_DPMI :
340       errmsg = parse_postindex (cd, strp, EPIPHANY_OPERAND_DPMI, (unsigned long *) (& fields->f_subd));
341       break;
342     case EPIPHANY_OPERAND_FRD :
343       errmsg = parse_shortregs (cd, strp, & epiphany_cgen_opval_gr_names, & fields->f_rd);
344       break;
345     case EPIPHANY_OPERAND_FRD6 :
346       errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_gr_names, & fields->f_rd6);
347       break;
348     case EPIPHANY_OPERAND_FRM :
349       errmsg = parse_shortregs (cd, strp, & epiphany_cgen_opval_gr_names, & fields->f_rm);
350       break;
351     case EPIPHANY_OPERAND_FRM6 :
352       errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_gr_names, & fields->f_rm6);
353       break;
354     case EPIPHANY_OPERAND_FRN :
355       errmsg = parse_shortregs (cd, strp, & epiphany_cgen_opval_gr_names, & fields->f_rn);
356       break;
357     case EPIPHANY_OPERAND_FRN6 :
358       errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_gr_names, & fields->f_rn6);
359       break;
360     case EPIPHANY_OPERAND_IMM16 :
361       {
362         bfd_vma value = 0;
363         errmsg = parse_imm16 (cd, strp, EPIPHANY_OPERAND_IMM16, 0, NULL,  & value);
364         fields->f_imm16 = value;
365       }
366       break;
367     case EPIPHANY_OPERAND_IMM8 :
368       {
369         bfd_vma value = 0;
370         errmsg = parse_imm8 (cd, strp, EPIPHANY_OPERAND_IMM8, 0, NULL,  & value);
371         fields->f_imm8 = value;
372       }
373       break;
374     case EPIPHANY_OPERAND_RD :
375       errmsg = parse_shortregs (cd, strp, & epiphany_cgen_opval_gr_names, & fields->f_rd);
376       break;
377     case EPIPHANY_OPERAND_RD6 :
378       errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_gr_names, & fields->f_rd6);
379       break;
380     case EPIPHANY_OPERAND_RM :
381       errmsg = parse_shortregs (cd, strp, & epiphany_cgen_opval_gr_names, & fields->f_rm);
382       break;
383     case EPIPHANY_OPERAND_RM6 :
384       errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_gr_names, & fields->f_rm6);
385       break;
386     case EPIPHANY_OPERAND_RN :
387       errmsg = parse_shortregs (cd, strp, & epiphany_cgen_opval_gr_names, & fields->f_rn);
388       break;
389     case EPIPHANY_OPERAND_RN6 :
390       errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_gr_names, & fields->f_rn6);
391       break;
392     case EPIPHANY_OPERAND_SD :
393       errmsg = parse_shortregs (cd, strp, & epiphany_cgen_opval_cr_names, & fields->f_sd);
394       break;
395     case EPIPHANY_OPERAND_SD6 :
396       errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_cr_names, & fields->f_sd6);
397       break;
398     case EPIPHANY_OPERAND_SDDMA :
399       errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_crdma_names, & fields->f_sd6);
400       break;
401     case EPIPHANY_OPERAND_SDMEM :
402       errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_crmem_names, & fields->f_sd6);
403       break;
404     case EPIPHANY_OPERAND_SDMESH :
405       errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_crmesh_names, & fields->f_sd6);
406       break;
407     case EPIPHANY_OPERAND_SHIFT :
408       errmsg = cgen_parse_unsigned_integer (cd, strp, EPIPHANY_OPERAND_SHIFT, (unsigned long *) (& fields->f_shift));
409       break;
410     case EPIPHANY_OPERAND_SIMM11 :
411       errmsg = parse_simm_not_reg (cd, strp, EPIPHANY_OPERAND_SIMM11, (long *) (& fields->f_sdisp11));
412       break;
413     case EPIPHANY_OPERAND_SIMM24 :
414       {
415         bfd_vma value = 0;
416         errmsg = parse_branch_addr (cd, strp, EPIPHANY_OPERAND_SIMM24, 0, NULL,  & value);
417         fields->f_simm24 = value;
418       }
419       break;
420     case EPIPHANY_OPERAND_SIMM3 :
421       errmsg = parse_simm_not_reg (cd, strp, EPIPHANY_OPERAND_SIMM3, (long *) (& fields->f_sdisp3));
422       break;
423     case EPIPHANY_OPERAND_SIMM8 :
424       {
425         bfd_vma value = 0;
426         errmsg = parse_branch_addr (cd, strp, EPIPHANY_OPERAND_SIMM8, 0, NULL,  & value);
427         fields->f_simm8 = value;
428       }
429       break;
430     case EPIPHANY_OPERAND_SN :
431       errmsg = parse_shortregs (cd, strp, & epiphany_cgen_opval_cr_names, & fields->f_sn);
432       break;
433     case EPIPHANY_OPERAND_SN6 :
434       errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_cr_names, & fields->f_sn6);
435       break;
436     case EPIPHANY_OPERAND_SNDMA :
437       errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_crdma_names, & fields->f_sn6);
438       break;
439     case EPIPHANY_OPERAND_SNMEM :
440       errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_crmem_names, & fields->f_sn6);
441       break;
442     case EPIPHANY_OPERAND_SNMESH :
443       errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_crmesh_names, & fields->f_sn6);
444       break;
445     case EPIPHANY_OPERAND_SWI_NUM :
446       errmsg = parse_uimm_not_reg (cd, strp, EPIPHANY_OPERAND_SWI_NUM, (unsigned long *) (& fields->f_trap_num));
447       break;
448     case EPIPHANY_OPERAND_TRAPNUM6 :
449       errmsg = cgen_parse_unsigned_integer (cd, strp, EPIPHANY_OPERAND_TRAPNUM6, (unsigned long *) (& fields->f_trap_num));
450       break;
451 
452     default :
453       /* xgettext:c-format */
454       fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
455       abort ();
456   }
457 
458   return errmsg;
459 }
460 
461 cgen_parse_fn * const epiphany_cgen_parse_handlers[] =
462 {
463   parse_insn_normal,
464 };
465 
466 void
epiphany_cgen_init_asm(CGEN_CPU_DESC cd)467 epiphany_cgen_init_asm (CGEN_CPU_DESC cd)
468 {
469   epiphany_cgen_init_opcode_table (cd);
470   epiphany_cgen_init_ibld_table (cd);
471   cd->parse_handlers = & epiphany_cgen_parse_handlers[0];
472   cd->parse_operand = epiphany_cgen_parse_operand;
473 #ifdef CGEN_ASM_INIT_HOOK
474 CGEN_ASM_INIT_HOOK
475 #endif
476 }
477 
478 
479 
480 /* Regex construction routine.
481 
482    This translates an opcode syntax string into a regex string,
483    by replacing any non-character syntax element (such as an
484    opcode) with the pattern '.*'
485 
486    It then compiles the regex and stores it in the opcode, for
487    later use by epiphany_cgen_assemble_insn
488 
489    Returns NULL for success, an error message for failure.  */
490 
491 char *
epiphany_cgen_build_insn_regex(CGEN_INSN * insn)492 epiphany_cgen_build_insn_regex (CGEN_INSN *insn)
493 {
494   CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
495   const char *mnem = CGEN_INSN_MNEMONIC (insn);
496   char rxbuf[CGEN_MAX_RX_ELEMENTS];
497   char *rx = rxbuf;
498   const CGEN_SYNTAX_CHAR_TYPE *syn;
499   int reg_err;
500 
501   syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
502 
503   /* Mnemonics come first in the syntax string.  */
504   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
505     return _("missing mnemonic in syntax string");
506   ++syn;
507 
508   /* Generate a case sensitive regular expression that emulates case
509      insensitive matching in the "C" locale.  We cannot generate a case
510      insensitive regular expression because in Turkish locales, 'i' and 'I'
511      are not equal modulo case conversion.  */
512 
513   /* Copy the literal mnemonic out of the insn.  */
514   for (; *mnem; mnem++)
515     {
516       char c = *mnem;
517 
518       if (ISALPHA (c))
519 	{
520 	  *rx++ = '[';
521 	  *rx++ = TOLOWER (c);
522 	  *rx++ = TOUPPER (c);
523 	  *rx++ = ']';
524 	}
525       else
526 	*rx++ = c;
527     }
528 
529   /* Copy any remaining literals from the syntax string into the rx.  */
530   for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
531     {
532       if (CGEN_SYNTAX_CHAR_P (* syn))
533 	{
534 	  char c = CGEN_SYNTAX_CHAR (* syn);
535 
536 	  switch (c)
537 	    {
538 	      /* Escape any regex metacharacters in the syntax.  */
539 	    case '.': case '[': case '\\':
540 	    case '*': case '^': case '$':
541 
542 #ifdef CGEN_ESCAPE_EXTENDED_REGEX
543 	    case '?': case '{': case '}':
544 	    case '(': case ')': case '*':
545 	    case '|': case '+': case ']':
546 #endif
547 	      *rx++ = '\\';
548 	      *rx++ = c;
549 	      break;
550 
551 	    default:
552 	      if (ISALPHA (c))
553 		{
554 		  *rx++ = '[';
555 		  *rx++ = TOLOWER (c);
556 		  *rx++ = TOUPPER (c);
557 		  *rx++ = ']';
558 		}
559 	      else
560 		*rx++ = c;
561 	      break;
562 	    }
563 	}
564       else
565 	{
566 	  /* Replace non-syntax fields with globs.  */
567 	  *rx++ = '.';
568 	  *rx++ = '*';
569 	}
570     }
571 
572   /* Trailing whitespace ok.  */
573   * rx++ = '[';
574   * rx++ = ' ';
575   * rx++ = '\t';
576   * rx++ = ']';
577   * rx++ = '*';
578 
579   /* But anchor it after that.  */
580   * rx++ = '$';
581   * rx = '\0';
582 
583   CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
584   reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
585 
586   if (reg_err == 0)
587     return NULL;
588   else
589     {
590       static char msg[80];
591 
592       regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
593       regfree ((regex_t *) CGEN_INSN_RX (insn));
594       free (CGEN_INSN_RX (insn));
595       (CGEN_INSN_RX (insn)) = NULL;
596       return msg;
597     }
598 }
599 
600 
601 /* Default insn parser.
602 
603    The syntax string is scanned and operands are parsed and stored in FIELDS.
604    Relocs are queued as we go via other callbacks.
605 
606    ??? Note that this is currently an all-or-nothing parser.  If we fail to
607    parse the instruction, we return 0 and the caller will start over from
608    the beginning.  Backtracking will be necessary in parsing subexpressions,
609    but that can be handled there.  Not handling backtracking here may get
610    expensive in the case of the m68k.  Deal with later.
611 
612    Returns NULL for success, an error message for failure.  */
613 
614 static const char *
parse_insn_normal(CGEN_CPU_DESC cd,const CGEN_INSN * insn,const char ** strp,CGEN_FIELDS * fields)615 parse_insn_normal (CGEN_CPU_DESC cd,
616 		   const CGEN_INSN *insn,
617 		   const char **strp,
618 		   CGEN_FIELDS *fields)
619 {
620   /* ??? Runtime added insns not handled yet.  */
621   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
622   const char *str = *strp;
623   const char *errmsg;
624   const char *p;
625   const CGEN_SYNTAX_CHAR_TYPE * syn;
626 #ifdef CGEN_MNEMONIC_OPERANDS
627   /* FIXME: wip */
628   int past_opcode_p;
629 #endif
630 
631   /* For now we assume the mnemonic is first (there are no leading operands).
632      We can parse it without needing to set up operand parsing.
633      GAS's input scrubber will ensure mnemonics are lowercase, but we may
634      not be called from GAS.  */
635   p = CGEN_INSN_MNEMONIC (insn);
636   while (*p && TOLOWER (*p) == TOLOWER (*str))
637     ++p, ++str;
638 
639   if (* p)
640     return _("unrecognized instruction");
641 
642 #ifndef CGEN_MNEMONIC_OPERANDS
643   if (* str && ! ISSPACE (* str))
644     return _("unrecognized instruction");
645 #endif
646 
647   CGEN_INIT_PARSE (cd);
648   cgen_init_parse_operand (cd);
649 #ifdef CGEN_MNEMONIC_OPERANDS
650   past_opcode_p = 0;
651 #endif
652 
653   /* We don't check for (*str != '\0') here because we want to parse
654      any trailing fake arguments in the syntax string.  */
655   syn = CGEN_SYNTAX_STRING (syntax);
656 
657   /* Mnemonics come first for now, ensure valid string.  */
658   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
659     abort ();
660 
661   ++syn;
662 
663   while (* syn != 0)
664     {
665       /* Non operand chars must match exactly.  */
666       if (CGEN_SYNTAX_CHAR_P (* syn))
667 	{
668 	  /* FIXME: While we allow for non-GAS callers above, we assume the
669 	     first char after the mnemonic part is a space.  */
670 	  /* FIXME: We also take inappropriate advantage of the fact that
671 	     GAS's input scrubber will remove extraneous blanks.  */
672 	  if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
673 	    {
674 #ifdef CGEN_MNEMONIC_OPERANDS
675 	      if (CGEN_SYNTAX_CHAR(* syn) == ' ')
676 		past_opcode_p = 1;
677 #endif
678 	      ++ syn;
679 	      ++ str;
680 	    }
681 	  else if (*str)
682 	    {
683 	      /* Syntax char didn't match.  Can't be this insn.  */
684 	      static char msg [80];
685 
686 	      /* xgettext:c-format */
687 	      sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
688 		       CGEN_SYNTAX_CHAR(*syn), *str);
689 	      return msg;
690 	    }
691 	  else
692 	    {
693 	      /* Ran out of input.  */
694 	      static char msg [80];
695 
696 	      /* xgettext:c-format */
697 	      sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
698 		       CGEN_SYNTAX_CHAR(*syn));
699 	      return msg;
700 	    }
701 	  continue;
702 	}
703 
704 #ifdef CGEN_MNEMONIC_OPERANDS
705       (void) past_opcode_p;
706 #endif
707       /* We have an operand of some sort.  */
708       errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn), &str, fields);
709       if (errmsg)
710 	return errmsg;
711 
712       /* Done with this operand, continue with next one.  */
713       ++ syn;
714     }
715 
716   /* If we're at the end of the syntax string, we're done.  */
717   if (* syn == 0)
718     {
719       /* FIXME: For the moment we assume a valid `str' can only contain
720 	 blanks now.  IE: We needn't try again with a longer version of
721 	 the insn and it is assumed that longer versions of insns appear
722 	 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
723       while (ISSPACE (* str))
724 	++ str;
725 
726       if (* str != '\0')
727 	return _("junk at end of line"); /* FIXME: would like to include `str' */
728 
729       return NULL;
730     }
731 
732   /* We couldn't parse it.  */
733   return _("unrecognized instruction");
734 }
735 
736 /* Main entry point.
737    This routine is called for each instruction to be assembled.
738    STR points to the insn to be assembled.
739    We assume all necessary tables have been initialized.
740    The assembled instruction, less any fixups, is stored in BUF.
741    Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
742    still needs to be converted to target byte order, otherwise BUF is an array
743    of bytes in target byte order.
744    The result is a pointer to the insn's entry in the opcode table,
745    or NULL if an error occured (an error message will have already been
746    printed).
747 
748    Note that when processing (non-alias) macro-insns,
749    this function recurses.
750 
751    ??? It's possible to make this cpu-independent.
752    One would have to deal with a few minor things.
753    At this point in time doing so would be more of a curiosity than useful
754    [for example this file isn't _that_ big], but keeping the possibility in
755    mind helps keep the design clean.  */
756 
757 const CGEN_INSN *
epiphany_cgen_assemble_insn(CGEN_CPU_DESC cd,const char * str,CGEN_FIELDS * fields,CGEN_INSN_BYTES_PTR buf,char ** errmsg)758 epiphany_cgen_assemble_insn (CGEN_CPU_DESC cd,
759 			   const char *str,
760 			   CGEN_FIELDS *fields,
761 			   CGEN_INSN_BYTES_PTR buf,
762 			   char **errmsg)
763 {
764   const char *start;
765   CGEN_INSN_LIST *ilist;
766   const char *parse_errmsg = NULL;
767   const char *insert_errmsg = NULL;
768   int recognized_mnemonic = 0;
769 
770   /* Skip leading white space.  */
771   while (ISSPACE (* str))
772     ++ str;
773 
774   /* The instructions are stored in hashed lists.
775      Get the first in the list.  */
776   ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
777 
778   /* Keep looking until we find a match.  */
779   start = str;
780   for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
781     {
782       const CGEN_INSN *insn = ilist->insn;
783       recognized_mnemonic = 1;
784 
785 #ifdef CGEN_VALIDATE_INSN_SUPPORTED
786       /* Not usually needed as unsupported opcodes
787 	 shouldn't be in the hash lists.  */
788       /* Is this insn supported by the selected cpu?  */
789       if (! epiphany_cgen_insn_supported (cd, insn))
790 	continue;
791 #endif
792       /* If the RELAXED attribute is set, this is an insn that shouldn't be
793 	 chosen immediately.  Instead, it is used during assembler/linker
794 	 relaxation if possible.  */
795       if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
796 	continue;
797 
798       str = start;
799 
800       /* Skip this insn if str doesn't look right lexically.  */
801       if (CGEN_INSN_RX (insn) != NULL &&
802 	  regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
803 	continue;
804 
805       /* Allow parse/insert handlers to obtain length of insn.  */
806       CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
807 
808       parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
809       if (parse_errmsg != NULL)
810 	continue;
811 
812       /* ??? 0 is passed for `pc'.  */
813       insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
814 						 (bfd_vma) 0);
815       if (insert_errmsg != NULL)
816         continue;
817 
818       /* It is up to the caller to actually output the insn and any
819          queued relocs.  */
820       return insn;
821     }
822 
823   {
824     static char errbuf[150];
825     const char *tmp_errmsg;
826 #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
827 #define be_verbose 1
828 #else
829 #define be_verbose 0
830 #endif
831 
832     if (be_verbose)
833       {
834 	/* If requesting verbose error messages, use insert_errmsg.
835 	   Failing that, use parse_errmsg.  */
836 	tmp_errmsg = (insert_errmsg ? insert_errmsg :
837 		      parse_errmsg ? parse_errmsg :
838 		      recognized_mnemonic ?
839 		      _("unrecognized form of instruction") :
840 		      _("unrecognized instruction"));
841 
842 	if (strlen (start) > 50)
843 	  /* xgettext:c-format */
844 	  sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
845 	else
846 	  /* xgettext:c-format */
847 	  sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
848       }
849     else
850       {
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       }
858 
859     *errmsg = errbuf;
860     return NULL;
861   }
862 }
863