OSDN Git Service

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