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