OSDN Git Service

Use safe-ctype.h not ctype.h
[pf3gnuchains/pf3gnuchains3x.git] / opcodes / openrisc-asm.c
1 /* Assembler interface for targets using CGEN. -*- C -*-
2    CGEN: Cpu tools GENerator
3
4 THIS FILE IS MACHINE GENERATED WITH CGEN.
5 - the resultant file is machine generated, cgen-asm.in isn't
6
7 Copyright 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
8
9 This file is part of the GNU Binutils and GDB, the GNU debugger.
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software Foundation, Inc.,
23 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
24
25 /* ??? Eventually more and more of this stuff can go to cpu-independent files.
26    Keep that in mind.  */
27
28 #include "sysdep.h"
29 #include <stdio.h>
30 #include "ansidecl.h"
31 #include "bfd.h"
32 #include "symcat.h"
33 #include "openrisc-desc.h"
34 #include "openrisc-opc.h"
35 #include "opintl.h"
36 #include "xregex.h"
37 #include "libiberty.h"
38 #include "safe-ctype.h"
39
40 #undef  min
41 #define min(a,b) ((a) < (b) ? (a) : (b))
42 #undef  max
43 #define max(a,b) ((a) > (b) ? (a) : (b))
44
45 static const char * parse_insn_normal
46      PARAMS ((CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *));
47 \f
48 /* -- assembler routines inserted here.  */
49
50 /* -- asm.c */
51
52 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
53
54 static const char * parse_hi16
55   PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
56 static const char * parse_lo16
57   PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
58
59 long
60 openrisc_sign_extend_16bit (value)
61      long value;
62 {
63   return (long) (short) value;
64 }
65
66 /* Handle hi().  */
67
68 static const char *
69 parse_hi16 (cd, strp, opindex, valuep)
70      CGEN_CPU_DESC cd;
71      const char **strp;
72      int opindex;
73      unsigned long *valuep;
74 {
75   const char *errmsg;
76   enum cgen_parse_operand_result result_type;
77   bfd_vma value;
78
79   if (**strp == '#')
80     ++*strp;
81
82   if (strncasecmp (*strp, "hi(", 3) == 0)
83     {
84       *strp += 3;
85
86 #if 0
87       errmsg = cgen_parse_signed_integer (cd, strp, opindex, valuep);
88       if (errmsg != NULL)
89         fprintf (stderr, "parse_hi: %s\n", errmsg);
90       if (errmsg != NULL)
91 #endif
92         errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16,
93                                      &result_type, &value);
94       if (**strp != ')')
95         return "missing `)'";
96       ++*strp;
97       if (errmsg == NULL
98           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
99         value >>= 16;
100       *valuep = (long) (short) value;
101
102       return errmsg;
103     }
104   else
105     {
106       if (**strp == '-')
107         errmsg = cgen_parse_signed_integer (cd, strp, opindex, (long *) &value);
108       else
109         errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, (unsigned long *) &value);
110     }
111   *valuep = (long) (short) (value & 0xffff);
112   return errmsg;
113 }
114
115 /* Handle lo().  */
116
117 static const char *
118 parse_lo16 (cd, strp, opindex, valuep)
119      CGEN_CPU_DESC cd;
120      const char **strp;
121      int opindex;
122      unsigned long *valuep;
123 {
124   const char *errmsg;
125   enum cgen_parse_operand_result result_type;
126   bfd_vma value;
127
128   if (**strp == '#')
129     ++*strp;
130
131   if (strncasecmp (*strp, "lo(", 3) == 0)
132     {
133       *strp += 3;
134
135 #if 0 
136       errmsg = cgen_parse_signed_integer (cd, strp, opindex, valuep);
137       if (errmsg != NULL)
138         fprintf (stderr, "parse_lo: %s\n", errmsg);
139
140       if (errmsg != NULL)
141 #endif
142         errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
143                                      &result_type, &value);
144       if (**strp != ')')
145         return "missing `)'";
146       ++*strp;
147       if (errmsg == NULL
148           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
149         value &= 0xffff;
150       *valuep = (long) (short) value;
151
152       return errmsg;
153     }
154
155   if (**strp == '-')
156     errmsg = cgen_parse_signed_integer (cd, strp, opindex, (long *) &value);
157   else
158     errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, (unsigned long *) &value);
159   *valuep = (long) (short) (value & 0xffff);
160   return errmsg;
161 }
162
163 /* -- */
164
165 const char * openrisc_cgen_parse_operand
166   PARAMS ((CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *));
167
168 /* Main entry point for operand parsing.
169
170    This function is basically just a big switch statement.  Earlier versions
171    used tables to look up the function to use, but
172    - if the table contains both assembler and disassembler functions then
173      the disassembler contains much of the assembler and vice-versa,
174    - there's a lot of inlining possibilities as things grow,
175    - using a switch statement avoids the function call overhead.
176
177    This function could be moved into `parse_insn_normal', but keeping it
178    separate makes clear the interface between `parse_insn_normal' and each of
179    the handlers.
180 */
181
182 const char *
183 openrisc_cgen_parse_operand (cd, opindex, strp, fields)
184      CGEN_CPU_DESC cd;
185      int opindex;
186      const char ** strp;
187      CGEN_FIELDS * fields;
188 {
189   const char * errmsg = NULL;
190   /* Used by scalar operands that still need to be parsed.  */
191   long junk ATTRIBUTE_UNUSED;
192
193   switch (opindex)
194     {
195     case OPENRISC_OPERAND_ABS_26 :
196       {
197         bfd_vma value;
198         errmsg = cgen_parse_address (cd, strp, OPENRISC_OPERAND_ABS_26, 0, NULL,  & value);
199         fields->f_abs26 = value;
200       }
201       break;
202     case OPENRISC_OPERAND_DISP_26 :
203       {
204         bfd_vma value;
205         errmsg = cgen_parse_address (cd, strp, OPENRISC_OPERAND_DISP_26, 0, NULL,  & value);
206         fields->f_disp26 = value;
207       }
208       break;
209     case OPENRISC_OPERAND_HI16 :
210       errmsg = parse_hi16 (cd, strp, OPENRISC_OPERAND_HI16, &fields->f_simm16);
211       break;
212     case OPENRISC_OPERAND_LO16 :
213       errmsg = parse_lo16 (cd, strp, OPENRISC_OPERAND_LO16, &fields->f_lo16);
214       break;
215     case OPENRISC_OPERAND_OP_F_23 :
216       errmsg = cgen_parse_unsigned_integer (cd, strp, OPENRISC_OPERAND_OP_F_23, &fields->f_op4);
217       break;
218     case OPENRISC_OPERAND_OP_F_3 :
219       errmsg = cgen_parse_unsigned_integer (cd, strp, OPENRISC_OPERAND_OP_F_3, &fields->f_op5);
220       break;
221     case OPENRISC_OPERAND_RA :
222       errmsg = cgen_parse_keyword (cd, strp, & openrisc_cgen_opval_h_gr, & fields->f_r2);
223       break;
224     case OPENRISC_OPERAND_RB :
225       errmsg = cgen_parse_keyword (cd, strp, & openrisc_cgen_opval_h_gr, & fields->f_r3);
226       break;
227     case OPENRISC_OPERAND_RD :
228       errmsg = cgen_parse_keyword (cd, strp, & openrisc_cgen_opval_h_gr, & fields->f_r1);
229       break;
230     case OPENRISC_OPERAND_SIMM_16 :
231       errmsg = cgen_parse_signed_integer (cd, strp, OPENRISC_OPERAND_SIMM_16, &fields->f_simm16);
232       break;
233     case OPENRISC_OPERAND_UI16NC :
234       errmsg = parse_lo16 (cd, strp, OPENRISC_OPERAND_UI16NC, &fields->f_i16nc);
235       break;
236     case OPENRISC_OPERAND_UIMM_16 :
237       errmsg = cgen_parse_unsigned_integer (cd, strp, OPENRISC_OPERAND_UIMM_16, &fields->f_uimm16);
238       break;
239     case OPENRISC_OPERAND_UIMM_5 :
240       errmsg = cgen_parse_unsigned_integer (cd, strp, OPENRISC_OPERAND_UIMM_5, &fields->f_uimm5);
241       break;
242
243     default :
244       /* xgettext:c-format */
245       fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
246       abort ();
247   }
248
249   return errmsg;
250 }
251
252 cgen_parse_fn * const openrisc_cgen_parse_handlers[] = 
253 {
254   parse_insn_normal,
255 };
256
257 void
258 openrisc_cgen_init_asm (cd)
259      CGEN_CPU_DESC cd;
260 {
261   openrisc_cgen_init_opcode_table (cd);
262   openrisc_cgen_init_ibld_table (cd);
263   cd->parse_handlers = & openrisc_cgen_parse_handlers[0];
264   cd->parse_operand = openrisc_cgen_parse_operand;
265 }
266
267 \f
268
269 /* Regex construction routine.
270
271    This translates an opcode syntax string into a regex string,
272    by replacing any non-character syntax element (such as an
273    opcode) with the pattern '.*'
274
275    It then compiles the regex and stores it in the opcode, for
276    later use by openrisc_cgen_assemble_insn
277
278    Returns NULL for success, an error message for failure.  */
279
280 char * 
281 openrisc_cgen_build_insn_regex (insn)
282      CGEN_INSN *insn;
283 {  
284   CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
285   const char *mnem = CGEN_INSN_MNEMONIC (insn);
286   char rxbuf[CGEN_MAX_RX_ELEMENTS];
287   char *rx = rxbuf;
288   const CGEN_SYNTAX_CHAR_TYPE *syn;
289   int reg_err;
290
291   syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
292
293   /* Mnemonics come first in the syntax string.  */
294   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
295     return _("missing mnemonic in syntax string");
296   ++syn;
297
298   /* Generate a case sensitive regular expression that emulates case
299      insensitive matching in the "C" locale.  We cannot generate a case
300      insensitive regular expression because in Turkish locales, 'i' and 'I'
301      are not equal modulo case conversion.  */
302
303   /* Copy the literal mnemonic out of the insn.  */
304   for (; *mnem; mnem++)
305     {
306       char c = *mnem;
307
308       if (ISALPHA (c))
309         {
310           *rx++ = '[';
311           *rx++ = TOLOWER (c);
312           *rx++ = TOUPPER (c);
313           *rx++ = ']';
314         }
315       else
316         *rx++ = c;
317     }
318
319   /* Copy any remaining literals from the syntax string into the rx.  */
320   for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
321     {
322       if (CGEN_SYNTAX_CHAR_P (* syn)) 
323         {
324           char c = CGEN_SYNTAX_CHAR (* syn);
325
326           switch (c) 
327             {
328               /* Escape any regex metacharacters in the syntax.  */
329             case '.': case '[': case '\\': 
330             case '*': case '^': case '$': 
331
332 #ifdef CGEN_ESCAPE_EXTENDED_REGEX
333             case '?': case '{': case '}': 
334             case '(': case ')': case '*':
335             case '|': case '+': case ']':
336 #endif
337               *rx++ = '\\';
338               *rx++ = c;
339               break;
340
341             default:
342               if (ISALPHA (c))
343                 {
344                   *rx++ = '[';
345                   *rx++ = TOLOWER (c);
346                   *rx++ = TOUPPER (c);
347                   *rx++ = ']';
348                 }
349               else
350                 *rx++ = c;
351               break;
352             }
353         }
354       else
355         {
356           /* Replace non-syntax fields with globs.  */
357           *rx++ = '.';
358           *rx++ = '*';
359         }
360     }
361
362   /* Trailing whitespace ok.  */
363   * rx++ = '['; 
364   * rx++ = ' '; 
365   * rx++ = '\t'; 
366   * rx++ = ']'; 
367   * rx++ = '*'; 
368
369   /* But anchor it after that.  */
370   * rx++ = '$'; 
371   * rx = '\0';
372
373   CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
374   reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
375
376   if (reg_err == 0) 
377     return NULL;
378   else
379     {
380       static char msg[80];
381
382       regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
383       regfree ((regex_t *) CGEN_INSN_RX (insn));
384       free (CGEN_INSN_RX (insn));
385       (CGEN_INSN_RX (insn)) = NULL;
386       return msg;
387     }
388 }
389
390 \f
391 /* Default insn parser.
392
393    The syntax string is scanned and operands are parsed and stored in FIELDS.
394    Relocs are queued as we go via other callbacks.
395
396    ??? Note that this is currently an all-or-nothing parser.  If we fail to
397    parse the instruction, we return 0 and the caller will start over from
398    the beginning.  Backtracking will be necessary in parsing subexpressions,
399    but that can be handled there.  Not handling backtracking here may get
400    expensive in the case of the m68k.  Deal with later.
401
402    Returns NULL for success, an error message for failure.  */
403
404 static const char *
405 parse_insn_normal (cd, insn, strp, fields)
406      CGEN_CPU_DESC cd;
407      const CGEN_INSN *insn;
408      const char **strp;
409      CGEN_FIELDS *fields;
410 {
411   /* ??? Runtime added insns not handled yet.  */
412   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
413   const char *str = *strp;
414   const char *errmsg;
415   const char *p;
416   const CGEN_SYNTAX_CHAR_TYPE * syn;
417 #ifdef CGEN_MNEMONIC_OPERANDS
418   /* FIXME: wip */
419   int past_opcode_p;
420 #endif
421
422   /* For now we assume the mnemonic is first (there are no leading operands).
423      We can parse it without needing to set up operand parsing.
424      GAS's input scrubber will ensure mnemonics are lowercase, but we may
425      not be called from GAS.  */
426   p = CGEN_INSN_MNEMONIC (insn);
427   while (*p && TOLOWER (*p) == TOLOWER (*str))
428     ++p, ++str;
429
430   if (* p)
431     return _("unrecognized instruction");
432
433 #ifndef CGEN_MNEMONIC_OPERANDS
434   if (* str && ! ISSPACE (* str))
435     return _("unrecognized instruction");
436 #endif
437
438   CGEN_INIT_PARSE (cd);
439   cgen_init_parse_operand (cd);
440 #ifdef CGEN_MNEMONIC_OPERANDS
441   past_opcode_p = 0;
442 #endif
443
444   /* We don't check for (*str != '\0') here because we want to parse
445      any trailing fake arguments in the syntax string.  */
446   syn = CGEN_SYNTAX_STRING (syntax);
447
448   /* Mnemonics come first for now, ensure valid string.  */
449   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
450     abort ();
451
452   ++syn;
453
454   while (* syn != 0)
455     {
456       /* Non operand chars must match exactly.  */
457       if (CGEN_SYNTAX_CHAR_P (* syn))
458         {
459           /* FIXME: While we allow for non-GAS callers above, we assume the
460              first char after the mnemonic part is a space.  */
461           /* FIXME: We also take inappropriate advantage of the fact that
462              GAS's input scrubber will remove extraneous blanks.  */
463           if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
464             {
465 #ifdef CGEN_MNEMONIC_OPERANDS
466               if (CGEN_SYNTAX_CHAR(* syn) == ' ')
467                 past_opcode_p = 1;
468 #endif
469               ++ syn;
470               ++ str;
471             }
472           else if (*str)
473             {
474               /* Syntax char didn't match.  Can't be this insn.  */
475               static char msg [80];
476
477               /* xgettext:c-format */
478               sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
479                        CGEN_SYNTAX_CHAR(*syn), *str);
480               return msg;
481             }
482           else
483             {
484               /* Ran out of input.  */
485               static char msg [80];
486
487               /* xgettext:c-format */
488               sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
489                        CGEN_SYNTAX_CHAR(*syn));
490               return msg;
491             }
492           continue;
493         }
494
495       /* We have an operand of some sort.  */
496       errmsg = openrisc_cgen_parse_operand (cd, CGEN_SYNTAX_FIELD (*syn),
497                                           &str, fields);
498       if (errmsg)
499         return errmsg;
500
501       /* Done with this operand, continue with next one.  */
502       ++ syn;
503     }
504
505   /* If we're at the end of the syntax string, we're done.  */
506   if (* syn == 0)
507     {
508       /* FIXME: For the moment we assume a valid `str' can only contain
509          blanks now.  IE: We needn't try again with a longer version of
510          the insn and it is assumed that longer versions of insns appear
511          before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
512       while (ISSPACE (* str))
513         ++ str;
514
515       if (* str != '\0')
516         return _("junk at end of line"); /* FIXME: would like to include `str' */
517
518       return NULL;
519     }
520
521   /* We couldn't parse it.  */
522   return _("unrecognized instruction");
523 }
524 \f
525 /* Main entry point.
526    This routine is called for each instruction to be assembled.
527    STR points to the insn to be assembled.
528    We assume all necessary tables have been initialized.
529    The assembled instruction, less any fixups, is stored in BUF.
530    Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
531    still needs to be converted to target byte order, otherwise BUF is an array
532    of bytes in target byte order.
533    The result is a pointer to the insn's entry in the opcode table,
534    or NULL if an error occured (an error message will have already been
535    printed).
536
537    Note that when processing (non-alias) macro-insns,
538    this function recurses.
539
540    ??? It's possible to make this cpu-independent.
541    One would have to deal with a few minor things.
542    At this point in time doing so would be more of a curiosity than useful
543    [for example this file isn't _that_ big], but keeping the possibility in
544    mind helps keep the design clean.  */
545
546 const CGEN_INSN *
547 openrisc_cgen_assemble_insn (cd, str, fields, buf, errmsg)
548      CGEN_CPU_DESC cd;
549      const char *str;
550      CGEN_FIELDS *fields;
551      CGEN_INSN_BYTES_PTR buf;
552      char **errmsg;
553 {
554   const char *start;
555   CGEN_INSN_LIST *ilist;
556   const char *parse_errmsg = NULL;
557   const char *insert_errmsg = NULL;
558   int recognized_mnemonic = 0;
559
560   /* Skip leading white space.  */
561   while (ISSPACE (* str))
562     ++ str;
563
564   /* The instructions are stored in hashed lists.
565      Get the first in the list.  */
566   ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
567
568   /* Keep looking until we find a match.  */
569   start = str;
570   for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
571     {
572       const CGEN_INSN *insn = ilist->insn;
573       recognized_mnemonic = 1;
574
575 #ifdef CGEN_VALIDATE_INSN_SUPPORTED 
576       /* Not usually needed as unsupported opcodes
577          shouldn't be in the hash lists.  */
578       /* Is this insn supported by the selected cpu?  */
579       if (! openrisc_cgen_insn_supported (cd, insn))
580         continue;
581 #endif
582       /* If the RELAX attribute is set, this is an insn that shouldn't be
583          chosen immediately.  Instead, it is used during assembler/linker
584          relaxation if possible.  */
585       if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAX) != 0)
586         continue;
587
588       str = start;
589
590       /* Skip this insn if str doesn't look right lexically.  */
591       if (CGEN_INSN_RX (insn) != NULL &&
592           regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
593         continue;
594
595       /* Allow parse/insert handlers to obtain length of insn.  */
596       CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
597
598       parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
599       if (parse_errmsg != NULL)
600         continue;
601
602       /* ??? 0 is passed for `pc'.  */
603       insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
604                                                  (bfd_vma) 0);
605       if (insert_errmsg != NULL)
606         continue;
607
608       /* It is up to the caller to actually output the insn and any
609          queued relocs.  */
610       return insn;
611     }
612
613   {
614     static char errbuf[150];
615 #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
616     const char *tmp_errmsg;
617
618     /* If requesting verbose error messages, use insert_errmsg.
619        Failing that, use parse_errmsg.  */
620     tmp_errmsg = (insert_errmsg ? insert_errmsg :
621                   parse_errmsg ? parse_errmsg :
622                   recognized_mnemonic ?
623                   _("unrecognized form of instruction") :
624                   _("unrecognized instruction"));
625
626     if (strlen (start) > 50)
627       /* xgettext:c-format */
628       sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
629     else 
630       /* xgettext:c-format */
631       sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
632 #else
633     if (strlen (start) > 50)
634       /* xgettext:c-format */
635       sprintf (errbuf, _("bad instruction `%.50s...'"), start);
636     else 
637       /* xgettext:c-format */
638       sprintf (errbuf, _("bad instruction `%.50s'"), start);
639 #endif
640       
641     *errmsg = errbuf;
642     return NULL;
643   }
644 }
645 \f
646 #if 0 /* This calls back to GAS which we can't do without care.  */
647
648 /* Record each member of OPVALS in the assembler's symbol table.
649    This lets GAS parse registers for us.
650    ??? Interesting idea but not currently used.  */
651
652 /* Record each member of OPVALS in the assembler's symbol table.
653    FIXME: Not currently used.  */
654
655 void
656 openrisc_cgen_asm_hash_keywords (cd, opvals)
657      CGEN_CPU_DESC cd;
658      CGEN_KEYWORD *opvals;
659 {
660   CGEN_KEYWORD_SEARCH search = cgen_keyword_search_init (opvals, NULL);
661   const CGEN_KEYWORD_ENTRY * ke;
662
663   while ((ke = cgen_keyword_search_next (& search)) != NULL)
664     {
665 #if 0 /* Unnecessary, should be done in the search routine.  */
666       if (! openrisc_cgen_opval_supported (ke))
667         continue;
668 #endif
669       cgen_asm_record_register (cd, ke->name, ke->value);
670     }
671 }
672
673 #endif /* 0 */