xref: /trueos/contrib/binutils/opcodes/mep-asm.c (revision 8fe640108653f13042f1b15213769e338aa524f6)
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, 2005
8    Free Software Foundation, Inc.
9 
10    This file is part of the GNU Binutils and GDB, the GNU debugger.
11 
12    This program is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General Public License as published by
14    the Free Software Foundation; either version 2, or (at your option)
15    any later version.
16 
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21 
22    You should have received a copy of the GNU General Public License
23    along with this program; if not, write to the Free Software Foundation, Inc.,
24    51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
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 "mep-desc.h"
35 #include "mep-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 #define CGEN_VALIDATE_INSN_SUPPORTED
54 
55        const char * parse_csrn       (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *);
56        const char * parse_tpreg      (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *);
57        const char * parse_spreg      (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *);
58        const char * parse_mep_align  (CGEN_CPU_DESC, const char **, enum cgen_operand_type, long *);
59        const char * parse_mep_alignu (CGEN_CPU_DESC, const char **, enum cgen_operand_type, unsigned long *);
60 static const char * parse_signed16   (CGEN_CPU_DESC, const char **, int, long *);
61 static const char * parse_unsigned16 (CGEN_CPU_DESC, const char **, int, unsigned long *);
62 static const char * parse_lo16       (CGEN_CPU_DESC, const char **, int, long *, long);
63 static const char * parse_unsigned7  (CGEN_CPU_DESC, const char **, enum cgen_operand_type, unsigned long *);
64 static const char * parse_zero       (CGEN_CPU_DESC, const char **, int, long *);
65 
66 const char *
parse_csrn(CGEN_CPU_DESC cd,const char ** strp,CGEN_KEYWORD * keyword_table,long * field)67 parse_csrn (CGEN_CPU_DESC cd, const char **strp,
68 	    CGEN_KEYWORD *keyword_table, long *field)
69 {
70   const char *err;
71   unsigned long value;
72 
73   err = cgen_parse_keyword (cd, strp, keyword_table, field);
74   if (!err)
75     return NULL;
76 
77   err = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_CSRN_IDX, & value);
78   if (err)
79     return err;
80   *field = value;
81   return NULL;
82 }
83 
84 /* begin-cop-ip-parse-handlers */
85 static const char *
parse_fmax_cr(CGEN_CPU_DESC cd,const char ** strp,CGEN_KEYWORD * keyword_table ATTRIBUTE_UNUSED,long * field)86 parse_fmax_cr (CGEN_CPU_DESC cd,
87 	const char **strp,
88 	CGEN_KEYWORD *keyword_table  ATTRIBUTE_UNUSED,
89 	long *field)
90 {
91   return cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_cr_fmax, field);
92 }
93 static const char *
parse_fmax_ccr(CGEN_CPU_DESC cd,const char ** strp,CGEN_KEYWORD * keyword_table ATTRIBUTE_UNUSED,long * field)94 parse_fmax_ccr (CGEN_CPU_DESC cd,
95 	const char **strp,
96 	CGEN_KEYWORD *keyword_table  ATTRIBUTE_UNUSED,
97 	long *field)
98 {
99   return cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_ccr_fmax, field);
100 }
101 /* end-cop-ip-parse-handlers */
102 
103 const char *
parse_tpreg(CGEN_CPU_DESC cd,const char ** strp,CGEN_KEYWORD * keyword_table,long * field)104 parse_tpreg (CGEN_CPU_DESC cd, const char ** strp,
105 	     CGEN_KEYWORD *keyword_table, long *field)
106 {
107   const char *err;
108 
109   err = cgen_parse_keyword (cd, strp, keyword_table, field);
110   if (err)
111     return err;
112   if (*field != 13)
113     return _("Only $tp or $13 allowed for this opcode");
114   return NULL;
115 }
116 
117 const char *
parse_spreg(CGEN_CPU_DESC cd,const char ** strp,CGEN_KEYWORD * keyword_table,long * field)118 parse_spreg (CGEN_CPU_DESC cd, const char ** strp,
119 	     CGEN_KEYWORD *keyword_table, long *field)
120 {
121   const char *err;
122 
123   err = cgen_parse_keyword (cd, strp, keyword_table, field);
124   if (err)
125     return err;
126   if (*field != 15)
127     return _("Only $sp or $15 allowed for this opcode");
128   return NULL;
129 }
130 
131 const char *
parse_mep_align(CGEN_CPU_DESC cd,const char ** strp,enum cgen_operand_type type,long * field)132 parse_mep_align (CGEN_CPU_DESC cd, const char ** strp,
133 		 enum cgen_operand_type type, long *field)
134 {
135   long lsbs = 0;
136   const char *err;
137 
138   switch (type)
139     {
140     case MEP_OPERAND_PCREL8A2:
141     case MEP_OPERAND_PCREL12A2:
142     case MEP_OPERAND_PCREL17A2:
143     case MEP_OPERAND_PCREL24A2:
144     case MEP_OPERAND_CDISP8A2:
145     case MEP_OPERAND_CDISP8A4:
146     case MEP_OPERAND_CDISP8A8:
147       err = cgen_parse_signed_integer   (cd, strp, type, field);
148       break;
149     case MEP_OPERAND_PCABS24A2:
150     case MEP_OPERAND_UDISP7:
151     case MEP_OPERAND_UDISP7A2:
152     case MEP_OPERAND_UDISP7A4:
153     case MEP_OPERAND_UIMM7A4:
154     case MEP_OPERAND_ADDR24A4:
155       err = cgen_parse_unsigned_integer (cd, strp, type, (unsigned long *) field);
156       break;
157     default:
158       abort();
159     }
160   if (err)
161     return err;
162   switch (type)
163     {
164     case MEP_OPERAND_UDISP7:
165       lsbs = 0;
166       break;
167     case MEP_OPERAND_PCREL8A2:
168     case MEP_OPERAND_PCREL12A2:
169     case MEP_OPERAND_PCREL17A2:
170     case MEP_OPERAND_PCREL24A2:
171     case MEP_OPERAND_PCABS24A2:
172     case MEP_OPERAND_UDISP7A2:
173     case MEP_OPERAND_CDISP8A2:
174       lsbs = *field & 1;
175       break;
176     case MEP_OPERAND_UDISP7A4:
177     case MEP_OPERAND_UIMM7A4:
178     case MEP_OPERAND_ADDR24A4:
179     case MEP_OPERAND_CDISP8A4:
180       lsbs = *field & 3;
181       break;
182     case MEP_OPERAND_CDISP8A8:
183       lsbs = *field & 7;
184       break;
185     default:
186       /* Safe assumption?  */
187       abort ();
188     }
189   if (lsbs)
190     return "Value is not aligned enough";
191   return NULL;
192 }
193 
194 const char *
parse_mep_alignu(CGEN_CPU_DESC cd,const char ** strp,enum cgen_operand_type type,unsigned long * field)195 parse_mep_alignu (CGEN_CPU_DESC cd, const char ** strp,
196 		 enum cgen_operand_type type, unsigned long *field)
197 {
198   return parse_mep_align (cd, strp, type, (long *) field);
199 }
200 
201 
202 /* Handle %lo(), %tpoff(), %sdaoff(), %hi(), and other signed
203    constants in a signed context.  */
204 
205 static const char *
parse_signed16(CGEN_CPU_DESC cd,const char ** strp,int opindex,long * valuep)206 parse_signed16 (CGEN_CPU_DESC cd,
207 		const char **strp,
208 		int opindex,
209 		long *valuep)
210 {
211   return parse_lo16 (cd, strp, opindex, valuep, 1);
212 }
213 
214 static const char *
parse_lo16(CGEN_CPU_DESC cd,const char ** strp,int opindex,long * valuep,long signedp)215 parse_lo16 (CGEN_CPU_DESC cd,
216 	    const char **strp,
217 	    int opindex,
218 	    long *valuep,
219 	    long signedp)
220 {
221   const char *errmsg;
222   enum cgen_parse_operand_result result_type;
223   bfd_vma value;
224 
225   if (strncasecmp (*strp, "%lo(", 4) == 0)
226     {
227       *strp += 4;
228       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_LOW16,
229 				   & result_type, & value);
230       if (**strp != ')')
231 	return _("missing `)'");
232       ++*strp;
233       if (errmsg == NULL
234 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
235 	value &= 0xffff;
236       if (signedp)
237 	*valuep = (long)(short) value;
238       else
239 	*valuep = value;
240       return errmsg;
241     }
242 
243   if (strncasecmp (*strp, "%hi(", 4) == 0)
244     {
245       *strp += 4;
246       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16S,
247 				   & result_type, & value);
248       if (**strp != ')')
249 	return _("missing `)'");
250       ++*strp;
251       if (errmsg == NULL
252 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
253 	value = (value + 0x8000) >> 16;
254       *valuep = value;
255       return errmsg;
256     }
257 
258   if (strncasecmp (*strp, "%uhi(", 5) == 0)
259     {
260       *strp += 5;
261       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16U,
262 				   & result_type, & value);
263       if (**strp != ')')
264 	return _("missing `)'");
265       ++*strp;
266       if (errmsg == NULL
267 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
268 	value = value >> 16;
269       *valuep = value;
270       return errmsg;
271     }
272 
273   if (strncasecmp (*strp, "%sdaoff(", 8) == 0)
274     {
275       *strp += 8;
276       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_GPREL,
277 				   NULL, & value);
278       if (**strp != ')')
279 	return _("missing `)'");
280       ++*strp;
281       *valuep = value;
282       return errmsg;
283     }
284 
285   if (strncasecmp (*strp, "%tpoff(", 7) == 0)
286     {
287       *strp += 7;
288       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_TPREL,
289 				   NULL, & value);
290       if (**strp != ')')
291 	return _("missing `)'");
292       ++*strp;
293       *valuep = value;
294       return errmsg;
295     }
296 
297   if (**strp == '%')
298     return _("invalid %function() here");
299 
300   return cgen_parse_signed_integer (cd, strp, opindex, valuep);
301 }
302 
303 static const char *
parse_unsigned16(CGEN_CPU_DESC cd,const char ** strp,int opindex,unsigned long * valuep)304 parse_unsigned16 (CGEN_CPU_DESC cd,
305 		  const char **strp,
306 		  int opindex,
307 		  unsigned long *valuep)
308 {
309   return parse_lo16 (cd, strp, opindex, (long *) valuep, 0);
310 }
311 
312 /* A special case of parse_signed16 which accepts only the value zero.  */
313 
314 static const char *
parse_zero(CGEN_CPU_DESC cd,const char ** strp,int opindex,long * valuep)315 parse_zero (CGEN_CPU_DESC cd, const char **strp, int opindex, long *valuep)
316 {
317   const char *errmsg;
318   enum cgen_parse_operand_result result_type;
319   bfd_vma value;
320 
321   /*fprintf(stderr, "dj: signed parse opindex `%s'\n", *strp);*/
322 
323   /* Prevent ($ry) from being attempted as an expression on 'sw $rx,($ry)'.
324      It will fail and cause ry to be listed as an undefined symbol in the
325      listing.  */
326   if (strncmp (*strp, "($", 2) == 0)
327     return "not zero"; /* any string will do -- will never be seen.  */
328 
329   if (strncasecmp (*strp, "%lo(", 4) == 0)
330     {
331       *strp += 4;
332       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_LOW16,
333 				   &result_type, &value);
334       if (**strp != ')')
335 	return "missing `)'";
336       ++*strp;
337       if (errmsg == NULL
338 	  && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
339 	return "not zero"; /* any string will do -- will never be seen.  */
340       *valuep = value;
341       return errmsg;
342     }
343 
344   if (strncasecmp (*strp, "%hi(", 4) == 0)
345     {
346       *strp += 4;
347       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16S,
348 				   &result_type, &value);
349       if (**strp != ')')
350 	return "missing `)'";
351       ++*strp;
352       if (errmsg == NULL
353 	  && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
354 	return "not zero"; /* any string will do -- will never be seen.  */
355       *valuep = value;
356       return errmsg;
357     }
358 
359   if (strncasecmp (*strp, "%uhi(", 5) == 0)
360     {
361       *strp += 5;
362       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16U,
363 				   &result_type, &value);
364       if (**strp != ')')
365 	return "missing `)'";
366       ++*strp;
367       if (errmsg == NULL
368 	  && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
369 	return "not zero"; /* any string will do -- will never be seen.  */
370       *valuep = value;
371       return errmsg;
372     }
373 
374   if (strncasecmp (*strp, "%sdaoff(", 8) == 0)
375     {
376       *strp += 8;
377       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_GPREL,
378 				   &result_type, &value);
379       if (**strp != ')')
380 	return "missing `)'";
381       ++*strp;
382       if (errmsg == NULL
383 	  && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
384 	return "not zero"; /* any string will do -- will never be seen.  */
385       *valuep = value;
386       return errmsg;
387     }
388 
389   if (strncasecmp (*strp, "%tpoff(", 7) == 0)
390     {
391       *strp += 7;
392       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_TPREL,
393 				   &result_type, &value);
394       if (**strp != ')')
395 	return "missing `)'";
396       ++*strp;
397       if (errmsg == NULL
398 	  && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
399 	return "not zero"; /* any string will do -- will never be seen.  */
400       *valuep = value;
401       return errmsg;
402     }
403 
404   if (**strp == '%')
405     return "invalid %function() here";
406 
407   errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_NONE,
408 			       &result_type, &value);
409   if (errmsg == NULL
410       && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
411     return "not zero"; /* any string will do -- will never be seen.  */
412 
413   return errmsg;
414 }
415 
416 static const char *
parse_unsigned7(CGEN_CPU_DESC cd,const char ** strp,enum cgen_operand_type opindex,unsigned long * valuep)417 parse_unsigned7 (CGEN_CPU_DESC cd, const char **strp,
418 		 enum cgen_operand_type opindex, unsigned long *valuep)
419 {
420   const char *errmsg;
421   bfd_vma value;
422 
423   /* fprintf(stderr, "dj: unsigned7 parse `%s'\n", *strp); */
424 
425   if (strncasecmp (*strp, "%tpoff(", 7) == 0)
426     {
427       int reloc;
428       *strp += 7;
429       switch (opindex)
430 	{
431 	case MEP_OPERAND_UDISP7:
432 	  reloc = BFD_RELOC_MEP_TPREL7;
433 	  break;
434 	case MEP_OPERAND_UDISP7A2:
435 	  reloc = BFD_RELOC_MEP_TPREL7A2;
436 	  break;
437 	case MEP_OPERAND_UDISP7A4:
438 	  reloc = BFD_RELOC_MEP_TPREL7A4;
439 	  break;
440 	default:
441 	  /* Safe assumption?  */
442 	  abort ();
443 	}
444       errmsg = cgen_parse_address (cd, strp, opindex, reloc,
445 				   NULL, &value);
446       if (**strp != ')')
447 	return "missing `)'";
448       ++*strp;
449       *valuep = value;
450       return errmsg;
451     }
452 
453   if (**strp == '%')
454     return _("invalid %function() here");
455 
456   return parse_mep_alignu (cd, strp, opindex, valuep);
457 }
458 
459 /* BEGIN LIGHTWEIGHT MACRO PROCESSOR.  */
460 
461 #define MAXARGS 9
462 
463 typedef struct
464 {
465   char *name;
466   char *expansion;
467 }  macro;
468 
469 typedef struct
470 {
471   const char *start;
472   int len;
473 } arg;
474 
475 macro macros[] =
476 {
477   { "sizeof", "(`1.end + (- `1))"},
478   { "startof", "(`1 | 0)" },
479   { "align4", "(`1&(~3))"},
480 /*{ "hi", "(((`1+0x8000)>>16) & 0xffff)" },  */
481 /*{ "lo", "(`1 & 0xffff)" },  */
482 /*{ "sdaoff", "((`1-__sdabase) & 0x7f)"},  */
483 /*{ "tpoff", "((`1-__tpbase) & 0x7f)"},  */
484   { 0,0 }
485 };
486 
487 static char  * expand_string    (const char *, int);
488 
489 static const char *
490 mep_cgen_expand_macros_and_parse_operand
491   (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
492 
493 static char *
str_append(char * dest,const char * input,int len)494 str_append (char *dest, const char *input, int len)
495 {
496   char *new_dest;
497   int oldlen;
498 
499   if (len == 0)
500     return dest;
501   /* printf("str_append: <<%s>>, <<%s>>, %d\n", dest, input, len); */
502   oldlen = (dest ? strlen(dest) : 0);
503   new_dest = realloc (dest, oldlen + len + 1);
504   memset (new_dest + oldlen, 0, len + 1);
505   return strncat (new_dest, input, len);
506 }
507 
508 static macro *
lookup_macro(const char * name)509 lookup_macro (const char *name)
510 {
511   macro *m;
512 
513   for (m = macros; m->name; ++m)
514     if (strncmp (m->name, name, strlen(m->name)) == 0)
515       return m;
516 
517   return 0;
518 }
519 
520 static char *
expand_macro(arg * args,int narg,macro * mac)521 expand_macro (arg *args, int narg, macro *mac)
522 {
523   char *result = 0, *rescanned_result = 0;
524   char *e = mac->expansion;
525   char *mark = e;
526   int arg = 0;
527 
528   /*  printf("expanding macro %s with %d args\n", mac->name, narg + 1); */
529   while (*e)
530     {
531       if (*e == '`' &&
532 	  (*e+1) &&
533 	  ((*(e + 1) - '1') <= MAXARGS) &&
534 	  ((*(e + 1) - '1') <= narg))
535 	{
536 	  result = str_append (result, mark, e - mark);
537 	  arg = (*(e + 1) - '1');
538 	  /* printf("replacing `%d with %s\n", arg+1, args[arg].start); */
539 	  result = str_append (result, args[arg].start, args[arg].len);
540 	  ++e;
541 	  mark = e+1;
542 	}
543       ++e;
544     }
545 
546   if (mark != e)
547     result = str_append (result, mark, e - mark);
548 
549   if (result)
550     {
551       rescanned_result = expand_string (result, 0);
552       free (result);
553       return rescanned_result;
554     }
555   else
556     return result;
557 }
558 
559 #define IN_TEXT 0
560 #define IN_ARGS 1
561 
562 static char *
expand_string(const char * in,int first_only)563 expand_string (const char *in, int first_only)
564 {
565   int num_expansions = 0;
566   int depth = 0;
567   int narg = -1;
568   arg args[MAXARGS];
569   int state = IN_TEXT;
570   const char *mark = in;
571   macro *macro = 0;
572 
573   char *expansion = 0;
574   char *result = 0;
575 
576   while (*in)
577     {
578       switch (state)
579 	{
580 	case IN_TEXT:
581 	  if (*in == '%' && *(in + 1) && (!first_only || num_expansions == 0))
582 	    {
583 	      macro = lookup_macro (in + 1);
584 	      if (macro)
585 		{
586 		  /* printf("entering state %d at '%s'...\n", state, in); */
587 		  result = str_append (result, mark, in - mark);
588 		  mark = in;
589 		  in += 1 + strlen (macro->name);
590 		  while (*in == ' ') ++in;
591 		  if (*in != '(')
592 		    {
593 		      state = IN_TEXT;
594 		      macro = 0;
595 		    }
596 		  else
597 		    {
598 		      state = IN_ARGS;
599 		      narg = 0;
600 		      args[narg].start = in + 1;
601 		      args[narg].len = 0;
602 		      mark = in + 1;
603 		    }
604 		}
605 	    }
606 	  break;
607 	case IN_ARGS:
608 	  if (depth == 0)
609 	    {
610 	      switch (*in)
611 		{
612 		case ',':
613 		  narg++;
614 		  args[narg].start = (in + 1);
615 		  args[narg].len = 0;
616 		  break;
617 		case ')':
618 		  state = IN_TEXT;
619 		  /* printf("entering state %d at '%s'...\n", state, in); */
620 		  if (macro)
621 		    {
622 		      expansion = 0;
623 		      expansion = expand_macro (args, narg, macro);
624 		      num_expansions++;
625 		      if (expansion)
626 			{
627 			  result = str_append (result, expansion, strlen (expansion));
628 			  free (expansion);
629 			}
630 		    }
631 		  else
632 		    {
633 		      result = str_append (result, mark, in - mark);
634 		    }
635 		  macro = 0;
636 		  mark = in + 1;
637 		  break;
638 		case '(':
639 		  depth++;
640 		default:
641 		  args[narg].len++;
642 		  break;
643 		}
644 	    }
645 	  else
646 	    {
647 	      if (*in == ')')
648 		depth--;
649 	      if (narg > -1)
650 		args[narg].len++;
651 	    }
652 
653 	}
654       ++in;
655     }
656 
657   if (mark != in)
658     result = str_append (result, mark, in - mark);
659 
660   return result;
661 }
662 
663 #undef IN_ARGS
664 #undef IN_TEXT
665 #undef MAXARGS
666 
667 
668 /* END LIGHTWEIGHT MACRO PROCESSOR.  */
669 
670 const char * mep_cgen_parse_operand
671   (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
672 
673 const char *
mep_cgen_expand_macros_and_parse_operand(CGEN_CPU_DESC cd,int opindex,const char ** strp_in,CGEN_FIELDS * fields)674 mep_cgen_expand_macros_and_parse_operand (CGEN_CPU_DESC cd, int opindex,
675 					  const char ** strp_in, CGEN_FIELDS * fields)
676 {
677   const char * errmsg = NULL;
678   char *str = 0, *hold = 0;
679   const char **strp = 0;
680 
681   /* Set up a new pointer to macro-expanded string.  */
682   str = expand_string (*strp_in, 1);
683   /* fprintf (stderr, " expanded <<%s>> to <<%s>>\n", *strp_in, str); */
684 
685   hold = str;
686   strp = (const char **)(&str);
687 
688   errmsg = mep_cgen_parse_operand (cd, opindex, strp, fields);
689 
690   /* Now work out the advance.  */
691   if (strlen (str) == 0)
692     *strp_in += strlen (*strp_in);
693 
694   else
695     {
696       if (strstr (*strp_in, str))
697 	/* A macro-expansion was pulled off the front.  */
698 	*strp_in = strstr (*strp_in, str);
699       else
700 	/* A non-macro-expansion was pulled off the front.  */
701 	*strp_in += (str - hold);
702     }
703 
704   if (hold)
705     free (hold);
706 
707   return errmsg;
708 }
709 
710 #define CGEN_ASM_INIT_HOOK (cd->parse_operand = mep_cgen_expand_macros_and_parse_operand);
711 
712 /* -- dis.c */
713 
714 const char * mep_cgen_parse_operand
715   (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
716 
717 /* Main entry point for operand parsing.
718 
719    This function is basically just a big switch statement.  Earlier versions
720    used tables to look up the function to use, but
721    - if the table contains both assembler and disassembler functions then
722      the disassembler contains much of the assembler and vice-versa,
723    - there's a lot of inlining possibilities as things grow,
724    - using a switch statement avoids the function call overhead.
725 
726    This function could be moved into `parse_insn_normal', but keeping it
727    separate makes clear the interface between `parse_insn_normal' and each of
728    the handlers.  */
729 
730 const char *
mep_cgen_parse_operand(CGEN_CPU_DESC cd,int opindex,const char ** strp,CGEN_FIELDS * fields)731 mep_cgen_parse_operand (CGEN_CPU_DESC cd,
732 			   int opindex,
733 			   const char ** strp,
734 			   CGEN_FIELDS * fields)
735 {
736   const char * errmsg = NULL;
737   /* Used by scalar operands that still need to be parsed.  */
738   long junk ATTRIBUTE_UNUSED;
739 
740   switch (opindex)
741     {
742     case MEP_OPERAND_ADDR24A4 :
743       errmsg = parse_mep_alignu (cd, strp, MEP_OPERAND_ADDR24A4, (unsigned long *) (& fields->f_24u8a4n));
744       break;
745     case MEP_OPERAND_CALLNUM :
746       errmsg = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_CALLNUM, (unsigned long *) (& fields->f_callnum));
747       break;
748     case MEP_OPERAND_CCCC :
749       errmsg = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_CCCC, (unsigned long *) (& fields->f_rm));
750       break;
751     case MEP_OPERAND_CCRN :
752       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_ccr, & fields->f_ccrn);
753       break;
754     case MEP_OPERAND_CDISP8 :
755       errmsg = cgen_parse_signed_integer (cd, strp, MEP_OPERAND_CDISP8, (long *) (& fields->f_8s24));
756       break;
757     case MEP_OPERAND_CDISP8A2 :
758       errmsg = parse_mep_align (cd, strp, MEP_OPERAND_CDISP8A2, (long *) (& fields->f_8s24a2));
759       break;
760     case MEP_OPERAND_CDISP8A4 :
761       errmsg = parse_mep_align (cd, strp, MEP_OPERAND_CDISP8A4, (long *) (& fields->f_8s24a4));
762       break;
763     case MEP_OPERAND_CDISP8A8 :
764       errmsg = parse_mep_align (cd, strp, MEP_OPERAND_CDISP8A8, (long *) (& fields->f_8s24a8));
765       break;
766     case MEP_OPERAND_CIMM4 :
767       errmsg = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_CIMM4, (unsigned long *) (& fields->f_rn));
768       break;
769     case MEP_OPERAND_CIMM5 :
770       errmsg = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_CIMM5, (unsigned long *) (& fields->f_5u24));
771       break;
772     case MEP_OPERAND_CODE16 :
773       errmsg = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_CODE16, (unsigned long *) (& fields->f_16u16));
774       break;
775     case MEP_OPERAND_CODE24 :
776       errmsg = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_CODE24, (unsigned long *) (& fields->f_24u4n));
777       break;
778     case MEP_OPERAND_CP_FLAG :
779       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_ccr, & junk);
780       break;
781     case MEP_OPERAND_CRN :
782       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_cr, & fields->f_crn);
783       break;
784     case MEP_OPERAND_CRN64 :
785       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_cr64, & fields->f_crn);
786       break;
787     case MEP_OPERAND_CRNX :
788       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_cr, & fields->f_crnx);
789       break;
790     case MEP_OPERAND_CRNX64 :
791       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_cr64, & fields->f_crnx);
792       break;
793     case MEP_OPERAND_CSRN :
794       errmsg = parse_csrn (cd, strp, & mep_cgen_opval_h_csr, & fields->f_csrn);
795       break;
796     case MEP_OPERAND_CSRN_IDX :
797       errmsg = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_CSRN_IDX, (unsigned long *) (& fields->f_csrn));
798       break;
799     case MEP_OPERAND_DBG :
800       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk);
801       break;
802     case MEP_OPERAND_DEPC :
803       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk);
804       break;
805     case MEP_OPERAND_EPC :
806       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk);
807       break;
808     case MEP_OPERAND_EXC :
809       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk);
810       break;
811     case MEP_OPERAND_FMAX_CCRN :
812       errmsg = parse_fmax_ccr (cd, strp, & mep_cgen_opval_h_ccr, & fields->f_fmax_4_4);
813       break;
814     case MEP_OPERAND_FMAX_FRD :
815       errmsg = parse_fmax_cr (cd, strp, & mep_cgen_opval_h_cr, & fields->f_fmax_frd);
816       break;
817     case MEP_OPERAND_FMAX_FRD_INT :
818       errmsg = parse_fmax_cr (cd, strp, & mep_cgen_opval_h_cr, & fields->f_fmax_frd);
819       break;
820     case MEP_OPERAND_FMAX_FRM :
821       errmsg = parse_fmax_cr (cd, strp, & mep_cgen_opval_h_cr, & fields->f_fmax_frm);
822       break;
823     case MEP_OPERAND_FMAX_FRN :
824       errmsg = parse_fmax_cr (cd, strp, & mep_cgen_opval_h_cr, & fields->f_fmax_frn);
825       break;
826     case MEP_OPERAND_FMAX_FRN_INT :
827       errmsg = parse_fmax_cr (cd, strp, & mep_cgen_opval_h_cr, & fields->f_fmax_frn);
828       break;
829     case MEP_OPERAND_FMAX_RM :
830       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_fmax_rm);
831       break;
832     case MEP_OPERAND_HI :
833       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk);
834       break;
835     case MEP_OPERAND_LO :
836       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk);
837       break;
838     case MEP_OPERAND_LP :
839       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk);
840       break;
841     case MEP_OPERAND_MB0 :
842       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk);
843       break;
844     case MEP_OPERAND_MB1 :
845       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk);
846       break;
847     case MEP_OPERAND_ME0 :
848       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk);
849       break;
850     case MEP_OPERAND_ME1 :
851       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk);
852       break;
853     case MEP_OPERAND_NPC :
854       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk);
855       break;
856     case MEP_OPERAND_OPT :
857       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk);
858       break;
859     case MEP_OPERAND_PCABS24A2 :
860       errmsg = parse_mep_alignu (cd, strp, MEP_OPERAND_PCABS24A2, (unsigned long *) (& fields->f_24u5a2n));
861       break;
862     case MEP_OPERAND_PCREL12A2 :
863       errmsg = parse_mep_align (cd, strp, MEP_OPERAND_PCREL12A2, (long *) (& fields->f_12s4a2));
864       break;
865     case MEP_OPERAND_PCREL17A2 :
866       errmsg = parse_mep_align (cd, strp, MEP_OPERAND_PCREL17A2, (long *) (& fields->f_17s16a2));
867       break;
868     case MEP_OPERAND_PCREL24A2 :
869       errmsg = parse_mep_align (cd, strp, MEP_OPERAND_PCREL24A2, (long *) (& fields->f_24s5a2n));
870       break;
871     case MEP_OPERAND_PCREL8A2 :
872       errmsg = parse_mep_align (cd, strp, MEP_OPERAND_PCREL8A2, (long *) (& fields->f_8s8a2));
873       break;
874     case MEP_OPERAND_PSW :
875       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk);
876       break;
877     case MEP_OPERAND_R0 :
878       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & junk);
879       break;
880     case MEP_OPERAND_R1 :
881       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & junk);
882       break;
883     case MEP_OPERAND_RL :
884       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rl);
885       break;
886     case MEP_OPERAND_RM :
887       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rm);
888       break;
889     case MEP_OPERAND_RMA :
890       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rm);
891       break;
892     case MEP_OPERAND_RN :
893       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn);
894       break;
895     case MEP_OPERAND_RN3 :
896       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn3);
897       break;
898     case MEP_OPERAND_RN3C :
899       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn3);
900       break;
901     case MEP_OPERAND_RN3L :
902       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn3);
903       break;
904     case MEP_OPERAND_RN3S :
905       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn3);
906       break;
907     case MEP_OPERAND_RN3UC :
908       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn3);
909       break;
910     case MEP_OPERAND_RN3UL :
911       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn3);
912       break;
913     case MEP_OPERAND_RN3US :
914       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn3);
915       break;
916     case MEP_OPERAND_RNC :
917       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn);
918       break;
919     case MEP_OPERAND_RNL :
920       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn);
921       break;
922     case MEP_OPERAND_RNS :
923       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn);
924       break;
925     case MEP_OPERAND_RNUC :
926       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn);
927       break;
928     case MEP_OPERAND_RNUL :
929       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn);
930       break;
931     case MEP_OPERAND_RNUS :
932       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn);
933       break;
934     case MEP_OPERAND_SAR :
935       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk);
936       break;
937     case MEP_OPERAND_SDISP16 :
938       errmsg = parse_signed16 (cd, strp, MEP_OPERAND_SDISP16, (long *) (& fields->f_16s16));
939       break;
940     case MEP_OPERAND_SIMM16 :
941       errmsg = parse_signed16 (cd, strp, MEP_OPERAND_SIMM16, (long *) (& fields->f_16s16));
942       break;
943     case MEP_OPERAND_SIMM6 :
944       errmsg = cgen_parse_signed_integer (cd, strp, MEP_OPERAND_SIMM6, (long *) (& fields->f_6s8));
945       break;
946     case MEP_OPERAND_SIMM8 :
947       errmsg = cgen_parse_signed_integer (cd, strp, MEP_OPERAND_SIMM8, (long *) (& fields->f_8s8));
948       break;
949     case MEP_OPERAND_SP :
950       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & junk);
951       break;
952     case MEP_OPERAND_SPR :
953       errmsg = parse_spreg (cd, strp, & mep_cgen_opval_h_gpr, & junk);
954       break;
955     case MEP_OPERAND_TP :
956       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & junk);
957       break;
958     case MEP_OPERAND_TPR :
959       errmsg = parse_tpreg (cd, strp, & mep_cgen_opval_h_gpr, & junk);
960       break;
961     case MEP_OPERAND_UDISP2 :
962       errmsg = cgen_parse_signed_integer (cd, strp, MEP_OPERAND_UDISP2, (long *) (& fields->f_2u6));
963       break;
964     case MEP_OPERAND_UDISP7 :
965       errmsg = parse_unsigned7 (cd, strp, MEP_OPERAND_UDISP7, (unsigned long *) (& fields->f_7u9));
966       break;
967     case MEP_OPERAND_UDISP7A2 :
968       errmsg = parse_unsigned7 (cd, strp, MEP_OPERAND_UDISP7A2, (unsigned long *) (& fields->f_7u9a2));
969       break;
970     case MEP_OPERAND_UDISP7A4 :
971       errmsg = parse_unsigned7 (cd, strp, MEP_OPERAND_UDISP7A4, (unsigned long *) (& fields->f_7u9a4));
972       break;
973     case MEP_OPERAND_UIMM16 :
974       errmsg = parse_unsigned16 (cd, strp, MEP_OPERAND_UIMM16, (unsigned long *) (& fields->f_16u16));
975       break;
976     case MEP_OPERAND_UIMM2 :
977       errmsg = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_UIMM2, (unsigned long *) (& fields->f_2u10));
978       break;
979     case MEP_OPERAND_UIMM24 :
980       errmsg = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_UIMM24, (unsigned long *) (& fields->f_24u8n));
981       break;
982     case MEP_OPERAND_UIMM3 :
983       errmsg = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_UIMM3, (unsigned long *) (& fields->f_3u5));
984       break;
985     case MEP_OPERAND_UIMM4 :
986       errmsg = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_UIMM4, (unsigned long *) (& fields->f_4u8));
987       break;
988     case MEP_OPERAND_UIMM5 :
989       errmsg = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_UIMM5, (unsigned long *) (& fields->f_5u8));
990       break;
991     case MEP_OPERAND_UIMM7A4 :
992       errmsg = parse_mep_alignu (cd, strp, MEP_OPERAND_UIMM7A4, (unsigned long *) (& fields->f_7u9a4));
993       break;
994     case MEP_OPERAND_ZERO :
995       errmsg = parse_zero (cd, strp, MEP_OPERAND_ZERO, (long *) (& junk));
996       break;
997 
998     default :
999       /* xgettext:c-format */
1000       fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
1001       abort ();
1002   }
1003 
1004   return errmsg;
1005 }
1006 
1007 cgen_parse_fn * const mep_cgen_parse_handlers[] =
1008 {
1009   parse_insn_normal,
1010 };
1011 
1012 void
mep_cgen_init_asm(CGEN_CPU_DESC cd)1013 mep_cgen_init_asm (CGEN_CPU_DESC cd)
1014 {
1015   mep_cgen_init_opcode_table (cd);
1016   mep_cgen_init_ibld_table (cd);
1017   cd->parse_handlers = & mep_cgen_parse_handlers[0];
1018   cd->parse_operand = mep_cgen_parse_operand;
1019 #ifdef CGEN_ASM_INIT_HOOK
1020 CGEN_ASM_INIT_HOOK
1021 #endif
1022 }
1023 
1024 
1025 
1026 /* Regex construction routine.
1027 
1028    This translates an opcode syntax string into a regex string,
1029    by replacing any non-character syntax element (such as an
1030    opcode) with the pattern '.*'
1031 
1032    It then compiles the regex and stores it in the opcode, for
1033    later use by mep_cgen_assemble_insn
1034 
1035    Returns NULL for success, an error message for failure.  */
1036 
1037 char *
mep_cgen_build_insn_regex(CGEN_INSN * insn)1038 mep_cgen_build_insn_regex (CGEN_INSN *insn)
1039 {
1040   CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
1041   const char *mnem = CGEN_INSN_MNEMONIC (insn);
1042   char rxbuf[CGEN_MAX_RX_ELEMENTS];
1043   char *rx = rxbuf;
1044   const CGEN_SYNTAX_CHAR_TYPE *syn;
1045   int reg_err;
1046 
1047   syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
1048 
1049   /* Mnemonics come first in the syntax string.  */
1050   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
1051     return _("missing mnemonic in syntax string");
1052   ++syn;
1053 
1054   /* Generate a case sensitive regular expression that emulates case
1055      insensitive matching in the "C" locale.  We cannot generate a case
1056      insensitive regular expression because in Turkish locales, 'i' and 'I'
1057      are not equal modulo case conversion.  */
1058 
1059   /* Copy the literal mnemonic out of the insn.  */
1060   for (; *mnem; mnem++)
1061     {
1062       char c = *mnem;
1063 
1064       if (ISALPHA (c))
1065 	{
1066 	  *rx++ = '[';
1067 	  *rx++ = TOLOWER (c);
1068 	  *rx++ = TOUPPER (c);
1069 	  *rx++ = ']';
1070 	}
1071       else
1072 	*rx++ = c;
1073     }
1074 
1075   /* Copy any remaining literals from the syntax string into the rx.  */
1076   for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
1077     {
1078       if (CGEN_SYNTAX_CHAR_P (* syn))
1079 	{
1080 	  char c = CGEN_SYNTAX_CHAR (* syn);
1081 
1082 	  switch (c)
1083 	    {
1084 	      /* Escape any regex metacharacters in the syntax.  */
1085 	    case '.': case '[': case '\\':
1086 	    case '*': case '^': case '$':
1087 
1088 #ifdef CGEN_ESCAPE_EXTENDED_REGEX
1089 	    case '?': case '{': case '}':
1090 	    case '(': case ')': case '*':
1091 	    case '|': case '+': case ']':
1092 #endif
1093 	      *rx++ = '\\';
1094 	      *rx++ = c;
1095 	      break;
1096 
1097 	    default:
1098 	      if (ISALPHA (c))
1099 		{
1100 		  *rx++ = '[';
1101 		  *rx++ = TOLOWER (c);
1102 		  *rx++ = TOUPPER (c);
1103 		  *rx++ = ']';
1104 		}
1105 	      else
1106 		*rx++ = c;
1107 	      break;
1108 	    }
1109 	}
1110       else
1111 	{
1112 	  /* Replace non-syntax fields with globs.  */
1113 	  *rx++ = '.';
1114 	  *rx++ = '*';
1115 	}
1116     }
1117 
1118   /* Trailing whitespace ok.  */
1119   * rx++ = '[';
1120   * rx++ = ' ';
1121   * rx++ = '\t';
1122   * rx++ = ']';
1123   * rx++ = '*';
1124 
1125   /* But anchor it after that.  */
1126   * rx++ = '$';
1127   * rx = '\0';
1128 
1129   CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
1130   reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
1131 
1132   if (reg_err == 0)
1133     return NULL;
1134   else
1135     {
1136       static char msg[80];
1137 
1138       regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
1139       regfree ((regex_t *) CGEN_INSN_RX (insn));
1140       free (CGEN_INSN_RX (insn));
1141       (CGEN_INSN_RX (insn)) = NULL;
1142       return msg;
1143     }
1144 }
1145 
1146 
1147 /* Default insn parser.
1148 
1149    The syntax string is scanned and operands are parsed and stored in FIELDS.
1150    Relocs are queued as we go via other callbacks.
1151 
1152    ??? Note that this is currently an all-or-nothing parser.  If we fail to
1153    parse the instruction, we return 0 and the caller will start over from
1154    the beginning.  Backtracking will be necessary in parsing subexpressions,
1155    but that can be handled there.  Not handling backtracking here may get
1156    expensive in the case of the m68k.  Deal with later.
1157 
1158    Returns NULL for success, an error message for failure.  */
1159 
1160 static const char *
parse_insn_normal(CGEN_CPU_DESC cd,const CGEN_INSN * insn,const char ** strp,CGEN_FIELDS * fields)1161 parse_insn_normal (CGEN_CPU_DESC cd,
1162 		   const CGEN_INSN *insn,
1163 		   const char **strp,
1164 		   CGEN_FIELDS *fields)
1165 {
1166   /* ??? Runtime added insns not handled yet.  */
1167   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
1168   const char *str = *strp;
1169   const char *errmsg;
1170   const char *p;
1171   const CGEN_SYNTAX_CHAR_TYPE * syn;
1172 #ifdef CGEN_MNEMONIC_OPERANDS
1173   /* FIXME: wip */
1174   int past_opcode_p;
1175 #endif
1176 
1177   /* For now we assume the mnemonic is first (there are no leading operands).
1178      We can parse it without needing to set up operand parsing.
1179      GAS's input scrubber will ensure mnemonics are lowercase, but we may
1180      not be called from GAS.  */
1181   p = CGEN_INSN_MNEMONIC (insn);
1182   while (*p && TOLOWER (*p) == TOLOWER (*str))
1183     ++p, ++str;
1184 
1185   if (* p)
1186     return _("unrecognized instruction");
1187 
1188 #ifndef CGEN_MNEMONIC_OPERANDS
1189   if (* str && ! ISSPACE (* str))
1190     return _("unrecognized instruction");
1191 #endif
1192 
1193   CGEN_INIT_PARSE (cd);
1194   cgen_init_parse_operand (cd);
1195 #ifdef CGEN_MNEMONIC_OPERANDS
1196   past_opcode_p = 0;
1197 #endif
1198 
1199   /* We don't check for (*str != '\0') here because we want to parse
1200      any trailing fake arguments in the syntax string.  */
1201   syn = CGEN_SYNTAX_STRING (syntax);
1202 
1203   /* Mnemonics come first for now, ensure valid string.  */
1204   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
1205     abort ();
1206 
1207   ++syn;
1208 
1209   while (* syn != 0)
1210     {
1211       /* Non operand chars must match exactly.  */
1212       if (CGEN_SYNTAX_CHAR_P (* syn))
1213 	{
1214 	  /* FIXME: While we allow for non-GAS callers above, we assume the
1215 	     first char after the mnemonic part is a space.  */
1216 	  /* FIXME: We also take inappropriate advantage of the fact that
1217 	     GAS's input scrubber will remove extraneous blanks.  */
1218 	  if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
1219 	    {
1220 #ifdef CGEN_MNEMONIC_OPERANDS
1221 	      if (CGEN_SYNTAX_CHAR(* syn) == ' ')
1222 		past_opcode_p = 1;
1223 #endif
1224 	      ++ syn;
1225 	      ++ str;
1226 	    }
1227 	  else if (*str)
1228 	    {
1229 	      /* Syntax char didn't match.  Can't be this insn.  */
1230 	      static char msg [80];
1231 
1232 	      /* xgettext:c-format */
1233 	      sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
1234 		       CGEN_SYNTAX_CHAR(*syn), *str);
1235 	      return msg;
1236 	    }
1237 	  else
1238 	    {
1239 	      /* Ran out of input.  */
1240 	      static char msg [80];
1241 
1242 	      /* xgettext:c-format */
1243 	      sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
1244 		       CGEN_SYNTAX_CHAR(*syn));
1245 	      return msg;
1246 	    }
1247 	  continue;
1248 	}
1249 
1250       /* We have an operand of some sort.  */
1251       errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn),
1252 					  &str, fields);
1253       if (errmsg)
1254 	return errmsg;
1255 
1256       /* Done with this operand, continue with next one.  */
1257       ++ syn;
1258     }
1259 
1260   /* If we're at the end of the syntax string, we're done.  */
1261   if (* syn == 0)
1262     {
1263       /* FIXME: For the moment we assume a valid `str' can only contain
1264 	 blanks now.  IE: We needn't try again with a longer version of
1265 	 the insn and it is assumed that longer versions of insns appear
1266 	 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
1267       while (ISSPACE (* str))
1268 	++ str;
1269 
1270       if (* str != '\0')
1271 	return _("junk at end of line"); /* FIXME: would like to include `str' */
1272 
1273       return NULL;
1274     }
1275 
1276   /* We couldn't parse it.  */
1277   return _("unrecognized instruction");
1278 }
1279 
1280 /* Main entry point.
1281    This routine is called for each instruction to be assembled.
1282    STR points to the insn to be assembled.
1283    We assume all necessary tables have been initialized.
1284    The assembled instruction, less any fixups, is stored in BUF.
1285    Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
1286    still needs to be converted to target byte order, otherwise BUF is an array
1287    of bytes in target byte order.
1288    The result is a pointer to the insn's entry in the opcode table,
1289    or NULL if an error occured (an error message will have already been
1290    printed).
1291 
1292    Note that when processing (non-alias) macro-insns,
1293    this function recurses.
1294 
1295    ??? It's possible to make this cpu-independent.
1296    One would have to deal with a few minor things.
1297    At this point in time doing so would be more of a curiosity than useful
1298    [for example this file isn't _that_ big], but keeping the possibility in
1299    mind helps keep the design clean.  */
1300 
1301 const CGEN_INSN *
mep_cgen_assemble_insn(CGEN_CPU_DESC cd,const char * str,CGEN_FIELDS * fields,CGEN_INSN_BYTES_PTR buf,char ** errmsg)1302 mep_cgen_assemble_insn (CGEN_CPU_DESC cd,
1303 			   const char *str,
1304 			   CGEN_FIELDS *fields,
1305 			   CGEN_INSN_BYTES_PTR buf,
1306 			   char **errmsg)
1307 {
1308   const char *start;
1309   CGEN_INSN_LIST *ilist;
1310   const char *parse_errmsg = NULL;
1311   const char *insert_errmsg = NULL;
1312   int recognized_mnemonic = 0;
1313 
1314   /* Skip leading white space.  */
1315   while (ISSPACE (* str))
1316     ++ str;
1317 
1318   /* The instructions are stored in hashed lists.
1319      Get the first in the list.  */
1320   ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
1321 
1322   /* Keep looking until we find a match.  */
1323   start = str;
1324   for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
1325     {
1326       const CGEN_INSN *insn = ilist->insn;
1327       recognized_mnemonic = 1;
1328 
1329 #ifdef CGEN_VALIDATE_INSN_SUPPORTED
1330       /* Not usually needed as unsupported opcodes
1331 	 shouldn't be in the hash lists.  */
1332       /* Is this insn supported by the selected cpu?  */
1333       if (! mep_cgen_insn_supported (cd, insn))
1334 	continue;
1335 #endif
1336       /* If the RELAXED attribute is set, this is an insn that shouldn't be
1337 	 chosen immediately.  Instead, it is used during assembler/linker
1338 	 relaxation if possible.  */
1339       if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
1340 	continue;
1341 
1342       str = start;
1343 
1344       /* Skip this insn if str doesn't look right lexically.  */
1345       if (CGEN_INSN_RX (insn) != NULL &&
1346 	  regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
1347 	continue;
1348 
1349       /* Allow parse/insert handlers to obtain length of insn.  */
1350       CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
1351 
1352       parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
1353       if (parse_errmsg != NULL)
1354 	continue;
1355 
1356       /* ??? 0 is passed for `pc'.  */
1357       insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
1358 						 (bfd_vma) 0);
1359       if (insert_errmsg != NULL)
1360         continue;
1361 
1362       /* It is up to the caller to actually output the insn and any
1363          queued relocs.  */
1364       return insn;
1365     }
1366 
1367   {
1368     static char errbuf[150];
1369 #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
1370     const char *tmp_errmsg;
1371 
1372     /* If requesting verbose error messages, use insert_errmsg.
1373        Failing that, use parse_errmsg.  */
1374     tmp_errmsg = (insert_errmsg ? insert_errmsg :
1375 		  parse_errmsg ? parse_errmsg :
1376 		  recognized_mnemonic ?
1377 		  _("unrecognized form of instruction") :
1378 		  _("unrecognized instruction"));
1379 
1380     if (strlen (start) > 50)
1381       /* xgettext:c-format */
1382       sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
1383     else
1384       /* xgettext:c-format */
1385       sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
1386 #else
1387     if (strlen (start) > 50)
1388       /* xgettext:c-format */
1389       sprintf (errbuf, _("bad instruction `%.50s...'"), start);
1390     else
1391       /* xgettext:c-format */
1392       sprintf (errbuf, _("bad instruction `%.50s'"), start);
1393 #endif
1394 
1395     *errmsg = errbuf;
1396     return NULL;
1397   }
1398 }
1399