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 "or1k-desc.h"
35 #include "or1k-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 
53 static const char * MISSING_CLOSING_PARENTHESIS = N_("missing `)'");
54 
55 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
56 
57 static const char *
parse_disp26(CGEN_CPU_DESC cd,const char ** strp,int opindex,int opinfo,enum cgen_parse_operand_result * resultp,bfd_vma * valuep)58 parse_disp26 (CGEN_CPU_DESC cd,
59 	      const char ** strp,
60 	      int opindex,
61 	      int opinfo,
62 	      enum cgen_parse_operand_result * resultp,
63 	      bfd_vma * valuep)
64 {
65   const char *errmsg = NULL;
66   enum cgen_parse_operand_result result_type;
67 
68   if (strncasecmp (*strp, "plt(", 4) == 0)
69     {
70       bfd_vma value;
71 
72       *strp += 4;
73       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_OR1K_PLT26,
74 				   & result_type, & value);
75       if (**strp != ')')
76 	return MISSING_CLOSING_PARENTHESIS;
77       ++*strp;
78       if (errmsg == NULL
79 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
80 	value = (value >> 2) & 0xffff;
81       *valuep = value;
82       return errmsg;
83     }
84   return cgen_parse_address (cd, strp, opindex, opinfo, resultp, valuep);
85 }
86 
87 static const char *
parse_simm16(CGEN_CPU_DESC cd,const char ** strp,int opindex,long * valuep)88 parse_simm16 (CGEN_CPU_DESC cd, const char ** strp, int opindex, long * valuep)
89 {
90   const char *errmsg;
91   enum cgen_parse_operand_result result_type;
92   long ret;
93 
94   if (**strp == '#')
95     ++*strp;
96 
97   if (strncasecmp (*strp, "hi(", 3) == 0)
98     {
99       bfd_vma value;
100 
101       *strp += 3;
102       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16,
103 				   & result_type, & value);
104       if (**strp != ')')
105 	errmsg = MISSING_CLOSING_PARENTHESIS;
106       ++*strp;
107 
108       ret = value;
109 
110       if (errmsg == NULL
111 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
112 	{
113 	  ret >>= 16;
114 	  ret &= 0xffff;
115 	  ret = (ret ^ 0x8000) - 0x8000;
116 	}
117     }
118   else if (strncasecmp (*strp, "lo(", 3) == 0)
119     {
120       bfd_vma value;
121 
122       *strp += 3;
123       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
124 				   & result_type, & value);
125       if (**strp != ')')
126 	return MISSING_CLOSING_PARENTHESIS;
127       ++*strp;
128 
129       ret = value;
130 
131       if (result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
132 	{
133 	  ret &= 0xffff;
134 	  ret = (ret ^ 0x8000) - 0x8000;
135 	}
136     }
137   else if (strncasecmp (*strp, "got(", 4) == 0)
138     {
139       bfd_vma value;
140 
141       *strp += 4;
142       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_OR1K_GOT16,
143 				   & result_type, & value);
144       if (**strp != ')')
145 	return MISSING_CLOSING_PARENTHESIS;
146       ++*strp;
147       if (errmsg == NULL
148 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
149 	value &= 0xffff;
150       *valuep = value;
151       return errmsg;
152     }
153   else if (strncasecmp (*strp, "gotpchi(", 8) == 0)
154     {
155       bfd_vma value;
156 
157       *strp += 8;
158       errmsg = cgen_parse_address (cd, strp, opindex,
159 				   BFD_RELOC_OR1K_GOTPC_HI16,
160 				   & result_type, & value);
161       if (**strp != ')')
162 	return MISSING_CLOSING_PARENTHESIS;
163       ++*strp;
164       if (errmsg == NULL
165 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
166 	value = (value >> 16) & 0xffff;
167       *valuep = value;
168       return errmsg;
169     }
170   else if (strncasecmp (*strp, "gotpclo(", 8) == 0)
171     {
172       bfd_vma value;
173 
174       *strp += 8;
175       errmsg = cgen_parse_address (cd, strp, opindex,
176 				   BFD_RELOC_OR1K_GOTPC_LO16,
177 				   &result_type, &value);
178       if (**strp != ')')
179 	return MISSING_CLOSING_PARENTHESIS;
180       ++*strp;
181       if (errmsg == NULL
182 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
183 	value &= 0xffff;
184       *valuep = value;
185       return errmsg;
186     }
187   else if (strncasecmp (*strp, "gotoffhi(", 9) == 0)
188     {
189       bfd_vma value;
190 
191       *strp += 9;
192       errmsg = cgen_parse_address (cd, strp, opindex,
193 				   BFD_RELOC_OR1K_GOTOFF_HI16,
194 				   & result_type, & value);
195 
196       if (**strp != ')')
197 	return MISSING_CLOSING_PARENTHESIS;
198       ++*strp;
199       if (errmsg == NULL
200 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
201 	value = (value >> 16) & 0xffff;
202       *valuep = value;
203       return errmsg;
204     }
205   else if (strncasecmp (*strp, "gotofflo(", 9) == 0)
206     {
207       bfd_vma value;
208 
209       *strp += 9;
210       errmsg = cgen_parse_address (cd, strp, opindex,
211 				   BFD_RELOC_OR1K_GOTOFF_LO16,
212 				   &result_type, &value);
213       if (**strp != ')')
214 	return MISSING_CLOSING_PARENTHESIS;
215       ++*strp;
216       if (errmsg == NULL
217 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
218 	value &= 0xffff;
219       *valuep = value;
220       return errmsg;
221     }
222   else if (strncasecmp (*strp, "tlsgdhi(", 8) == 0)
223     {
224       bfd_vma value;
225 
226       *strp += 8;
227       errmsg = cgen_parse_address (cd, strp, opindex,
228 				   BFD_RELOC_OR1K_TLS_GD_HI16,
229 				   & result_type, & value);
230 
231       if (**strp != ')')
232 	return MISSING_CLOSING_PARENTHESIS;
233       ++*strp;
234       if (errmsg == NULL
235 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
236 	value = (value >> 16) & 0xffff;
237       *valuep = value;
238       return errmsg;
239     }
240   else if (strncasecmp (*strp, "tlsgdlo(", 8) == 0)
241     {
242       bfd_vma value;
243 
244       *strp += 8;
245       errmsg = cgen_parse_address (cd, strp, opindex,
246 				   BFD_RELOC_OR1K_TLS_GD_LO16,
247 				   &result_type, &value);
248       if (**strp != ')')
249 	return MISSING_CLOSING_PARENTHESIS;
250       ++*strp;
251       if (errmsg == NULL
252 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
253 	value &= 0xffff;
254       *valuep = value;
255       return errmsg;
256     }
257   else if (strncasecmp (*strp, "tlsldmhi(", 9) == 0)
258     {
259       bfd_vma value;
260 
261       *strp += 9;
262       errmsg = cgen_parse_address (cd, strp, opindex,
263 				   BFD_RELOC_OR1K_TLS_LDM_HI16,
264 				   & result_type, & value);
265 
266       if (**strp != ')')
267 	return MISSING_CLOSING_PARENTHESIS;
268       ++*strp;
269       if (errmsg == NULL
270 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
271 	value = (value >> 16) & 0xffff;
272       *valuep = value;
273       return errmsg;
274     }
275   else if (strncasecmp (*strp, "tlsldmlo(", 9) == 0)
276     {
277       bfd_vma value;
278 
279       *strp += 9;
280       errmsg = cgen_parse_address (cd, strp, opindex,
281 				   BFD_RELOC_OR1K_TLS_LDM_LO16,
282 				   &result_type, &value);
283       if (**strp != ')')
284 	return MISSING_CLOSING_PARENTHESIS;
285       ++*strp;
286       if (errmsg == NULL
287 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
288 	value &= 0xffff;
289       *valuep = value;
290       return errmsg;
291     }
292   else if (strncasecmp (*strp, "dtpoffhi(", 9) == 0)
293     {
294       bfd_vma value;
295 
296       *strp += 9;
297       errmsg = cgen_parse_address (cd, strp, opindex,
298 				   BFD_RELOC_OR1K_TLS_LDO_HI16,
299 				   & result_type, & value);
300 
301       if (**strp != ')')
302 	return MISSING_CLOSING_PARENTHESIS;
303       ++*strp;
304       if (errmsg == NULL
305 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
306 	value = (value >> 16) & 0xffff;
307       *valuep = value;
308       return errmsg;
309     }
310   else if (strncasecmp (*strp, "dtpofflo(", 9) == 0)
311     {
312       bfd_vma value;
313 
314       *strp += 9;
315       errmsg = cgen_parse_address (cd, strp, opindex,
316 				   BFD_RELOC_OR1K_TLS_LDO_LO16,
317 				   &result_type, &value);
318       if (**strp != ')')
319 	return MISSING_CLOSING_PARENTHESIS;
320       ++*strp;
321       if (errmsg == NULL
322 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
323 	value &= 0xffff;
324       *valuep = value;
325       return errmsg;
326     }
327   else if (strncasecmp (*strp, "gottpoffhi(", 11) == 0)
328     {
329       bfd_vma value;
330 
331       *strp += 11;
332       errmsg = cgen_parse_address (cd, strp, opindex,
333 				   BFD_RELOC_OR1K_TLS_IE_HI16,
334 				   & result_type, & value);
335 
336       if (**strp != ')')
337 	return MISSING_CLOSING_PARENTHESIS;
338       ++*strp;
339       if (errmsg == NULL
340 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
341 	value = (value >> 16) & 0xffff;
342       *valuep = value;
343       return errmsg;
344     }
345   else if (strncasecmp (*strp, "gottpofflo(", 11) == 0)
346     {
347       bfd_vma value;
348 
349       *strp += 11;
350       errmsg = cgen_parse_address (cd, strp, opindex,
351 				   BFD_RELOC_OR1K_TLS_IE_LO16,
352 				   &result_type, &value);
353       if (**strp != ')')
354 	return MISSING_CLOSING_PARENTHESIS;
355       ++*strp;
356       if (errmsg == NULL
357 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
358 	value &= 0xffff;
359       *valuep = value;
360       return errmsg;
361     }
362   else if (strncasecmp (*strp, "tpoffhi(", 8) == 0)
363     {
364       bfd_vma value;
365 
366       *strp += 8;
367       errmsg = cgen_parse_address (cd, strp, opindex,
368 				   BFD_RELOC_OR1K_TLS_LE_HI16,
369 				   & result_type, & value);
370 
371       if (**strp != ')')
372 	return MISSING_CLOSING_PARENTHESIS;
373       ++*strp;
374       if (errmsg == NULL
375 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
376 	value = (value >> 16) & 0xffff;
377       *valuep = value;
378       return errmsg;
379     }
380   else if (strncasecmp (*strp, "tpofflo(", 8) == 0)
381     {
382       bfd_vma value;
383 
384       *strp += 8;
385       errmsg = cgen_parse_address (cd, strp, opindex,
386 				   BFD_RELOC_OR1K_TLS_LE_LO16,
387 				   &result_type, &value);
388       if (**strp != ')')
389 	return MISSING_CLOSING_PARENTHESIS;
390       ++*strp;
391       if (errmsg == NULL
392 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
393 	value &= 0xffff;
394       *valuep = value;
395       return errmsg;
396     }
397   else
398     {
399       long value;
400       errmsg = cgen_parse_signed_integer (cd, strp, opindex, &value);
401       ret = value;
402     }
403 
404   if (errmsg == NULL)
405     *valuep = ret;
406 
407   return errmsg;
408 }
409 
410 static const char *
parse_uimm16(CGEN_CPU_DESC cd,const char ** strp,int opindex,unsigned long * valuep)411 parse_uimm16 (CGEN_CPU_DESC cd, const char ** strp, int opindex, unsigned long * valuep)
412 {
413   const char *errmsg = parse_simm16(cd, strp, opindex, (long *) valuep);
414 
415   if (errmsg == NULL)
416     *valuep &= 0xffff;
417   return errmsg;
418 }
419 
420 /* -- */
421 
422 const char * or1k_cgen_parse_operand
423   (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
424 
425 /* Main entry point for operand parsing.
426 
427    This function is basically just a big switch statement.  Earlier versions
428    used tables to look up the function to use, but
429    - if the table contains both assembler and disassembler functions then
430      the disassembler contains much of the assembler and vice-versa,
431    - there's a lot of inlining possibilities as things grow,
432    - using a switch statement avoids the function call overhead.
433 
434    This function could be moved into `parse_insn_normal', but keeping it
435    separate makes clear the interface between `parse_insn_normal' and each of
436    the handlers.  */
437 
438 const char *
or1k_cgen_parse_operand(CGEN_CPU_DESC cd,int opindex,const char ** strp,CGEN_FIELDS * fields)439 or1k_cgen_parse_operand (CGEN_CPU_DESC cd,
440 			   int opindex,
441 			   const char ** strp,
442 			   CGEN_FIELDS * fields)
443 {
444   const char * errmsg = NULL;
445   /* Used by scalar operands that still need to be parsed.  */
446   long junk ATTRIBUTE_UNUSED;
447 
448   switch (opindex)
449     {
450     case OR1K_OPERAND_DISP26 :
451       {
452         bfd_vma value = 0;
453         errmsg = parse_disp26 (cd, strp, OR1K_OPERAND_DISP26, 0, NULL,  & value);
454         fields->f_disp26 = value;
455       }
456       break;
457     case OR1K_OPERAND_RA :
458       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r2);
459       break;
460     case OR1K_OPERAND_RADF :
461       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fdr, & fields->f_r1);
462       break;
463     case OR1K_OPERAND_RASF :
464       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r2);
465       break;
466     case OR1K_OPERAND_RB :
467       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r3);
468       break;
469     case OR1K_OPERAND_RBDF :
470       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fdr, & fields->f_r1);
471       break;
472     case OR1K_OPERAND_RBSF :
473       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r3);
474       break;
475     case OR1K_OPERAND_RD :
476       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r1);
477       break;
478     case OR1K_OPERAND_RDDF :
479       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fdr, & fields->f_r1);
480       break;
481     case OR1K_OPERAND_RDSF :
482       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r1);
483       break;
484     case OR1K_OPERAND_SIMM16 :
485       errmsg = parse_simm16 (cd, strp, OR1K_OPERAND_SIMM16, (long *) (& fields->f_simm16));
486       break;
487     case OR1K_OPERAND_SIMM16_SPLIT :
488       errmsg = parse_simm16 (cd, strp, OR1K_OPERAND_SIMM16_SPLIT, (long *) (& fields->f_simm16_split));
489       break;
490     case OR1K_OPERAND_UIMM16 :
491       errmsg = parse_uimm16 (cd, strp, OR1K_OPERAND_UIMM16, (unsigned long *) (& fields->f_uimm16));
492       break;
493     case OR1K_OPERAND_UIMM16_SPLIT :
494       errmsg = parse_uimm16 (cd, strp, OR1K_OPERAND_UIMM16_SPLIT, (unsigned long *) (& fields->f_uimm16_split));
495       break;
496     case OR1K_OPERAND_UIMM6 :
497       errmsg = cgen_parse_unsigned_integer (cd, strp, OR1K_OPERAND_UIMM6, (unsigned long *) (& fields->f_uimm6));
498       break;
499 
500     default :
501       /* xgettext:c-format */
502       fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
503       abort ();
504   }
505 
506   return errmsg;
507 }
508 
509 cgen_parse_fn * const or1k_cgen_parse_handlers[] =
510 {
511   parse_insn_normal,
512 };
513 
514 void
or1k_cgen_init_asm(CGEN_CPU_DESC cd)515 or1k_cgen_init_asm (CGEN_CPU_DESC cd)
516 {
517   or1k_cgen_init_opcode_table (cd);
518   or1k_cgen_init_ibld_table (cd);
519   cd->parse_handlers = & or1k_cgen_parse_handlers[0];
520   cd->parse_operand = or1k_cgen_parse_operand;
521 #ifdef CGEN_ASM_INIT_HOOK
522 CGEN_ASM_INIT_HOOK
523 #endif
524 }
525 
526 
527 
528 /* Regex construction routine.
529 
530    This translates an opcode syntax string into a regex string,
531    by replacing any non-character syntax element (such as an
532    opcode) with the pattern '.*'
533 
534    It then compiles the regex and stores it in the opcode, for
535    later use by or1k_cgen_assemble_insn
536 
537    Returns NULL for success, an error message for failure.  */
538 
539 char *
or1k_cgen_build_insn_regex(CGEN_INSN * insn)540 or1k_cgen_build_insn_regex (CGEN_INSN *insn)
541 {
542   CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
543   const char *mnem = CGEN_INSN_MNEMONIC (insn);
544   char rxbuf[CGEN_MAX_RX_ELEMENTS];
545   char *rx = rxbuf;
546   const CGEN_SYNTAX_CHAR_TYPE *syn;
547   int reg_err;
548 
549   syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
550 
551   /* Mnemonics come first in the syntax string.  */
552   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
553     return _("missing mnemonic in syntax string");
554   ++syn;
555 
556   /* Generate a case sensitive regular expression that emulates case
557      insensitive matching in the "C" locale.  We cannot generate a case
558      insensitive regular expression because in Turkish locales, 'i' and 'I'
559      are not equal modulo case conversion.  */
560 
561   /* Copy the literal mnemonic out of the insn.  */
562   for (; *mnem; mnem++)
563     {
564       char c = *mnem;
565 
566       if (ISALPHA (c))
567 	{
568 	  *rx++ = '[';
569 	  *rx++ = TOLOWER (c);
570 	  *rx++ = TOUPPER (c);
571 	  *rx++ = ']';
572 	}
573       else
574 	*rx++ = c;
575     }
576 
577   /* Copy any remaining literals from the syntax string into the rx.  */
578   for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
579     {
580       if (CGEN_SYNTAX_CHAR_P (* syn))
581 	{
582 	  char c = CGEN_SYNTAX_CHAR (* syn);
583 
584 	  switch (c)
585 	    {
586 	      /* Escape any regex metacharacters in the syntax.  */
587 	    case '.': case '[': case '\\':
588 	    case '*': case '^': case '$':
589 
590 #ifdef CGEN_ESCAPE_EXTENDED_REGEX
591 	    case '?': case '{': case '}':
592 	    case '(': case ')': case '*':
593 	    case '|': case '+': case ']':
594 #endif
595 	      *rx++ = '\\';
596 	      *rx++ = c;
597 	      break;
598 
599 	    default:
600 	      if (ISALPHA (c))
601 		{
602 		  *rx++ = '[';
603 		  *rx++ = TOLOWER (c);
604 		  *rx++ = TOUPPER (c);
605 		  *rx++ = ']';
606 		}
607 	      else
608 		*rx++ = c;
609 	      break;
610 	    }
611 	}
612       else
613 	{
614 	  /* Replace non-syntax fields with globs.  */
615 	  *rx++ = '.';
616 	  *rx++ = '*';
617 	}
618     }
619 
620   /* Trailing whitespace ok.  */
621   * rx++ = '[';
622   * rx++ = ' ';
623   * rx++ = '\t';
624   * rx++ = ']';
625   * rx++ = '*';
626 
627   /* But anchor it after that.  */
628   * rx++ = '$';
629   * rx = '\0';
630 
631   CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
632   reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
633 
634   if (reg_err == 0)
635     return NULL;
636   else
637     {
638       static char msg[80];
639 
640       regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
641       regfree ((regex_t *) CGEN_INSN_RX (insn));
642       free (CGEN_INSN_RX (insn));
643       (CGEN_INSN_RX (insn)) = NULL;
644       return msg;
645     }
646 }
647 
648 
649 /* Default insn parser.
650 
651    The syntax string is scanned and operands are parsed and stored in FIELDS.
652    Relocs are queued as we go via other callbacks.
653 
654    ??? Note that this is currently an all-or-nothing parser.  If we fail to
655    parse the instruction, we return 0 and the caller will start over from
656    the beginning.  Backtracking will be necessary in parsing subexpressions,
657    but that can be handled there.  Not handling backtracking here may get
658    expensive in the case of the m68k.  Deal with later.
659 
660    Returns NULL for success, an error message for failure.  */
661 
662 static const char *
parse_insn_normal(CGEN_CPU_DESC cd,const CGEN_INSN * insn,const char ** strp,CGEN_FIELDS * fields)663 parse_insn_normal (CGEN_CPU_DESC cd,
664 		   const CGEN_INSN *insn,
665 		   const char **strp,
666 		   CGEN_FIELDS *fields)
667 {
668   /* ??? Runtime added insns not handled yet.  */
669   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
670   const char *str = *strp;
671   const char *errmsg;
672   const char *p;
673   const CGEN_SYNTAX_CHAR_TYPE * syn;
674 #ifdef CGEN_MNEMONIC_OPERANDS
675   /* FIXME: wip */
676   int past_opcode_p;
677 #endif
678 
679   /* For now we assume the mnemonic is first (there are no leading operands).
680      We can parse it without needing to set up operand parsing.
681      GAS's input scrubber will ensure mnemonics are lowercase, but we may
682      not be called from GAS.  */
683   p = CGEN_INSN_MNEMONIC (insn);
684   while (*p && TOLOWER (*p) == TOLOWER (*str))
685     ++p, ++str;
686 
687   if (* p)
688     return _("unrecognized instruction");
689 
690 #ifndef CGEN_MNEMONIC_OPERANDS
691   if (* str && ! ISSPACE (* str))
692     return _("unrecognized instruction");
693 #endif
694 
695   CGEN_INIT_PARSE (cd);
696   cgen_init_parse_operand (cd);
697 #ifdef CGEN_MNEMONIC_OPERANDS
698   past_opcode_p = 0;
699 #endif
700 
701   /* We don't check for (*str != '\0') here because we want to parse
702      any trailing fake arguments in the syntax string.  */
703   syn = CGEN_SYNTAX_STRING (syntax);
704 
705   /* Mnemonics come first for now, ensure valid string.  */
706   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
707     abort ();
708 
709   ++syn;
710 
711   while (* syn != 0)
712     {
713       /* Non operand chars must match exactly.  */
714       if (CGEN_SYNTAX_CHAR_P (* syn))
715 	{
716 	  /* FIXME: While we allow for non-GAS callers above, we assume the
717 	     first char after the mnemonic part is a space.  */
718 	  /* FIXME: We also take inappropriate advantage of the fact that
719 	     GAS's input scrubber will remove extraneous blanks.  */
720 	  if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
721 	    {
722 #ifdef CGEN_MNEMONIC_OPERANDS
723 	      if (CGEN_SYNTAX_CHAR(* syn) == ' ')
724 		past_opcode_p = 1;
725 #endif
726 	      ++ syn;
727 	      ++ str;
728 	    }
729 	  else if (*str)
730 	    {
731 	      /* Syntax char didn't match.  Can't be this insn.  */
732 	      static char msg [80];
733 
734 	      /* xgettext:c-format */
735 	      sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
736 		       CGEN_SYNTAX_CHAR(*syn), *str);
737 	      return msg;
738 	    }
739 	  else
740 	    {
741 	      /* Ran out of input.  */
742 	      static char msg [80];
743 
744 	      /* xgettext:c-format */
745 	      sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
746 		       CGEN_SYNTAX_CHAR(*syn));
747 	      return msg;
748 	    }
749 	  continue;
750 	}
751 
752 #ifdef CGEN_MNEMONIC_OPERANDS
753       (void) past_opcode_p;
754 #endif
755       /* We have an operand of some sort.  */
756       errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn), &str, fields);
757       if (errmsg)
758 	return errmsg;
759 
760       /* Done with this operand, continue with next one.  */
761       ++ syn;
762     }
763 
764   /* If we're at the end of the syntax string, we're done.  */
765   if (* syn == 0)
766     {
767       /* FIXME: For the moment we assume a valid `str' can only contain
768 	 blanks now.  IE: We needn't try again with a longer version of
769 	 the insn and it is assumed that longer versions of insns appear
770 	 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
771       while (ISSPACE (* str))
772 	++ str;
773 
774       if (* str != '\0')
775 	return _("junk at end of line"); /* FIXME: would like to include `str' */
776 
777       return NULL;
778     }
779 
780   /* We couldn't parse it.  */
781   return _("unrecognized instruction");
782 }
783 
784 /* Main entry point.
785    This routine is called for each instruction to be assembled.
786    STR points to the insn to be assembled.
787    We assume all necessary tables have been initialized.
788    The assembled instruction, less any fixups, is stored in BUF.
789    Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
790    still needs to be converted to target byte order, otherwise BUF is an array
791    of bytes in target byte order.
792    The result is a pointer to the insn's entry in the opcode table,
793    or NULL if an error occured (an error message will have already been
794    printed).
795 
796    Note that when processing (non-alias) macro-insns,
797    this function recurses.
798 
799    ??? It's possible to make this cpu-independent.
800    One would have to deal with a few minor things.
801    At this point in time doing so would be more of a curiosity than useful
802    [for example this file isn't _that_ big], but keeping the possibility in
803    mind helps keep the design clean.  */
804 
805 const CGEN_INSN *
or1k_cgen_assemble_insn(CGEN_CPU_DESC cd,const char * str,CGEN_FIELDS * fields,CGEN_INSN_BYTES_PTR buf,char ** errmsg)806 or1k_cgen_assemble_insn (CGEN_CPU_DESC cd,
807 			   const char *str,
808 			   CGEN_FIELDS *fields,
809 			   CGEN_INSN_BYTES_PTR buf,
810 			   char **errmsg)
811 {
812   const char *start;
813   CGEN_INSN_LIST *ilist;
814   const char *parse_errmsg = NULL;
815   const char *insert_errmsg = NULL;
816   int recognized_mnemonic = 0;
817 
818   /* Skip leading white space.  */
819   while (ISSPACE (* str))
820     ++ str;
821 
822   /* The instructions are stored in hashed lists.
823      Get the first in the list.  */
824   ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
825 
826   /* Keep looking until we find a match.  */
827   start = str;
828   for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
829     {
830       const CGEN_INSN *insn = ilist->insn;
831       recognized_mnemonic = 1;
832 
833 #ifdef CGEN_VALIDATE_INSN_SUPPORTED
834       /* Not usually needed as unsupported opcodes
835 	 shouldn't be in the hash lists.  */
836       /* Is this insn supported by the selected cpu?  */
837       if (! or1k_cgen_insn_supported (cd, insn))
838 	continue;
839 #endif
840       /* If the RELAXED attribute is set, this is an insn that shouldn't be
841 	 chosen immediately.  Instead, it is used during assembler/linker
842 	 relaxation if possible.  */
843       if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
844 	continue;
845 
846       str = start;
847 
848       /* Skip this insn if str doesn't look right lexically.  */
849       if (CGEN_INSN_RX (insn) != NULL &&
850 	  regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
851 	continue;
852 
853       /* Allow parse/insert handlers to obtain length of insn.  */
854       CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
855 
856       parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
857       if (parse_errmsg != NULL)
858 	continue;
859 
860       /* ??? 0 is passed for `pc'.  */
861       insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
862 						 (bfd_vma) 0);
863       if (insert_errmsg != NULL)
864         continue;
865 
866       /* It is up to the caller to actually output the insn and any
867          queued relocs.  */
868       return insn;
869     }
870 
871   {
872     static char errbuf[150];
873     const char *tmp_errmsg;
874 #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
875 #define be_verbose 1
876 #else
877 #define be_verbose 0
878 #endif
879 
880     if (be_verbose)
881       {
882 	/* If requesting verbose error messages, use insert_errmsg.
883 	   Failing that, use parse_errmsg.  */
884 	tmp_errmsg = (insert_errmsg ? insert_errmsg :
885 		      parse_errmsg ? parse_errmsg :
886 		      recognized_mnemonic ?
887 		      _("unrecognized form of instruction") :
888 		      _("unrecognized instruction"));
889 
890 	if (strlen (start) > 50)
891 	  /* xgettext:c-format */
892 	  sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
893 	else
894 	  /* xgettext:c-format */
895 	  sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
896       }
897     else
898       {
899 	if (strlen (start) > 50)
900 	  /* xgettext:c-format */
901 	  sprintf (errbuf, _("bad instruction `%.50s...'"), start);
902 	else
903 	  /* xgettext:c-format */
904 	  sprintf (errbuf, _("bad instruction `%.50s'"), start);
905       }
906 
907     *errmsg = errbuf;
908     return NULL;
909   }
910 }
911