Thu Nov 12 19:24:18 1998 Dave Brolley <brolley@cygnus.com>
[external/binutils.git] / opcodes / fr30-asm.c
1 /* Assembler interface for targets using CGEN. -*- C -*-
2    CGEN: Cpu tools GENerator
3
4 THIS FILE IS USED TO GENERATE fr30-asm.c.
5
6 Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
7
8 This file is part of the GNU Binutils and GDB, the GNU debugger.
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
13 any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software Foundation, Inc.,
22 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
23
24 #include "sysdep.h"
25 #include <ctype.h>
26 #include <stdio.h>
27 #include "ansidecl.h"
28 #include "bfd.h"
29 #include "symcat.h"
30 #include "fr30-opc.h"
31 #include "opintl.h"
32
33 #undef min
34 #define min(a,b) ((a) < (b) ? (a) : (b))
35 #undef max
36 #define max(a,b) ((a) > (b) ? (a) : (b))
37
38 #undef INLINE
39 #ifdef __GNUC__
40 #define INLINE __inline__
41 #else
42 #define INLINE
43 #endif
44
45 static const char * insert_normal
46      PARAMS ((CGEN_OPCODE_DESC, long, unsigned int, int, int, int,
47               CGEN_INSN_BYTES_PTR));
48 static const char * parse_insn_normal
49      PARAMS ((CGEN_OPCODE_DESC, const CGEN_INSN *,
50               const char **, CGEN_FIELDS *));
51 static const char * insert_insn_normal
52      PARAMS ((CGEN_OPCODE_DESC, const CGEN_INSN *,
53               CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma));
54 \f
55 /* -- assembler routines inserted here */
56
57 /* Main entry point for operand parsing.
58
59    This function is basically just a big switch statement.  Earlier versions
60    used tables to look up the function to use, but
61    - if the table contains both assembler and disassembler functions then
62      the disassembler contains much of the assembler and vice-versa,
63    - there's a lot of inlining possibilities as things grow,
64    - using a switch statement avoids the function call overhead.
65
66    This function could be moved into `parse_insn_normal', but keeping it
67    separate makes clear the interface between `parse_insn_normal' and each of
68    the handlers.
69 */
70
71 const char *
72 fr30_cgen_parse_operand (od, opindex, strp, fields)
73      CGEN_OPCODE_DESC od;
74      int opindex;
75      const char ** strp;
76      CGEN_FIELDS * fields;
77 {
78   const char * errmsg;
79
80   switch (opindex)
81     {
82     case FR30_OPERAND_RI :
83       errmsg = cgen_parse_keyword (od, strp, & fr30_cgen_opval_h_gr, & fields->f_Ri);
84       break;
85     case FR30_OPERAND_RJ :
86       errmsg = cgen_parse_keyword (od, strp, & fr30_cgen_opval_h_gr, & fields->f_Rj);
87       break;
88     case FR30_OPERAND_RS1 :
89       errmsg = cgen_parse_keyword (od, strp, & fr30_cgen_opval_h_dr, & fields->f_Rs1);
90       break;
91     case FR30_OPERAND_RS2 :
92       errmsg = cgen_parse_keyword (od, strp, & fr30_cgen_opval_h_dr, & fields->f_Rs2);
93       break;
94     case FR30_OPERAND_U4 :
95       errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_U4, &fields->f_u4);
96       break;
97     case FR30_OPERAND_M4 :
98       errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_M4, &fields->f_m4);
99       break;
100     case FR30_OPERAND_I8 :
101       errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_I8, &fields->f_i8);
102       break;
103     case FR30_OPERAND_U8 :
104       errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_U8, &fields->f_u8);
105       break;
106     case FR30_OPERAND_O8 :
107       errmsg = cgen_parse_signed_integer (od, strp, FR30_OPERAND_O8, &fields->f_o8);
108       break;
109     case FR30_OPERAND_S10 :
110       errmsg = cgen_parse_signed_integer (od, strp, FR30_OPERAND_S10, &fields->f_s10);
111       break;
112     case FR30_OPERAND_U10 :
113       errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_U10, &fields->f_u10);
114       break;
115     case FR30_OPERAND_DIR8 :
116       errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_DIR8, &fields->f_dir8);
117       break;
118     case FR30_OPERAND_DIR9 :
119       errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_DIR9, &fields->f_dir9);
120       break;
121     case FR30_OPERAND_DIR10 :
122       errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_DIR10, &fields->f_dir10);
123       break;
124     case FR30_OPERAND_LABEL9 :
125       errmsg = cgen_parse_signed_integer (od, strp, FR30_OPERAND_LABEL9, &fields->f_rel8);
126       break;
127     case FR30_OPERAND_LABEL12 :
128       errmsg = cgen_parse_signed_integer (od, strp, FR30_OPERAND_LABEL12, &fields->f_rel11);
129       break;
130     case FR30_OPERAND_CC :
131       errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_CC, &fields->f_cc);
132       break;
133
134     default :
135       /* xgettext:c-format */
136       fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
137       abort ();
138   }
139
140   return errmsg;
141 }
142
143 /* Main entry point for operand insertion.
144
145    This function is basically just a big switch statement.  Earlier versions
146    used tables to look up the function to use, but
147    - if the table contains both assembler and disassembler functions then
148      the disassembler contains much of the assembler and vice-versa,
149    - there's a lot of inlining possibilities as things grow,
150    - using a switch statement avoids the function call overhead.
151
152    This function could be moved into `parse_insn_normal', but keeping it
153    separate makes clear the interface between `parse_insn_normal' and each of
154    the handlers.  It's also needed by GAS to insert operands that couldn't be
155    resolved during parsing.
156 */
157
158 const char *
159 fr30_cgen_insert_operand (od, opindex, fields, buffer, pc)
160      CGEN_OPCODE_DESC od;
161      int opindex;
162      CGEN_FIELDS * fields;
163      CGEN_INSN_BYTES_PTR buffer;
164      bfd_vma pc;
165 {
166   const char * errmsg;
167
168   switch (opindex)
169     {
170     case FR30_OPERAND_RI :
171       errmsg = insert_normal (od, fields->f_Ri, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
172       break;
173     case FR30_OPERAND_RJ :
174       errmsg = insert_normal (od, fields->f_Rj, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
175       break;
176     case FR30_OPERAND_RS1 :
177       errmsg = insert_normal (od, fields->f_Rs1, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
178       break;
179     case FR30_OPERAND_RS2 :
180       errmsg = insert_normal (od, fields->f_Rs2, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
181       break;
182     case FR30_OPERAND_U4 :
183       errmsg = insert_normal (od, fields->f_u4, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 8, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
184       break;
185     case FR30_OPERAND_M4 :
186       {
187         long value = fields->f_m4;
188         value = ((value) & (15));
189         errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 8, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
190       }
191       break;
192     case FR30_OPERAND_I8 :
193       errmsg = insert_normal (od, fields->f_i8, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 4, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
194       break;
195     case FR30_OPERAND_U8 :
196       errmsg = insert_normal (od, fields->f_u8, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
197       break;
198     case FR30_OPERAND_O8 :
199       errmsg = insert_normal (od, fields->f_o8, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 4, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
200       break;
201     case FR30_OPERAND_S10 :
202       {
203         long value = fields->f_s10;
204         value = ((((unsigned int) (value) >> (2))) & (255));
205         errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
206       }
207       break;
208     case FR30_OPERAND_U10 :
209       {
210         long value = fields->f_u10;
211         value = ((((unsigned int) (value) >> (2))) & (255));
212         errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
213       }
214       break;
215     case FR30_OPERAND_DIR8 :
216       errmsg = insert_normal (od, fields->f_dir8, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
217       break;
218     case FR30_OPERAND_DIR9 :
219       {
220         long value = fields->f_dir9;
221         value = ((((unsigned int) (value) >> (1))) & (255));
222         errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
223       }
224       break;
225     case FR30_OPERAND_DIR10 :
226       {
227         long value = fields->f_dir10;
228         value = ((((unsigned int) (value) >> (2))) & (255));
229         errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
230       }
231       break;
232     case FR30_OPERAND_LABEL9 :
233       {
234         long value = fields->f_rel8;
235         value = ((((unsigned int) (value) >> (1))) & (255));
236         errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_SIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
237       }
238       break;
239     case FR30_OPERAND_LABEL12 :
240       {
241         long value = fields->f_rel11;
242         value = ((((unsigned int) (value) >> (1))) & (2047));
243         errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_SIGNED), 5, 11, CGEN_FIELDS_BITSIZE (fields), buffer);
244       }
245       break;
246     case FR30_OPERAND_CC :
247       errmsg = insert_normal (od, fields->f_cc, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
248       break;
249
250     default :
251       /* xgettext:c-format */
252       fprintf (stderr, _("Unrecognized field %d while building insn.\n"),
253                opindex);
254       abort ();
255   }
256
257   return errmsg;
258 }
259
260 cgen_parse_fn * const fr30_cgen_parse_handlers[] = 
261 {
262   0, /* default */
263   parse_insn_normal,
264 };
265
266 cgen_insert_fn * const fr30_cgen_insert_handlers[] = 
267 {
268   0, /* default */
269   insert_insn_normal,
270 };
271
272 void
273 fr30_cgen_init_asm (od)
274      CGEN_OPCODE_DESC od;
275 {
276 }
277
278 \f
279 #if ! CGEN_INT_INSN_P
280
281 /* Subroutine of insert_normal.  */
282
283 static INLINE void
284 insert_1 (od, value, start, length, word_length, bufp)
285      CGEN_OPCODE_DESC od;
286      unsigned long value;
287      int start,length,word_length;
288      unsigned char *bufp;
289 {
290   unsigned long x,mask;
291   int shift;
292   int big_p = CGEN_OPCODE_INSN_ENDIAN (od) == CGEN_ENDIAN_BIG;
293
294   switch (word_length)
295     {
296     case 8:
297       x = *bufp;
298       break;
299     case 16:
300       if (big_p)
301         x = bfd_getb16 (bufp);
302       else
303         x = bfd_getl16 (bufp);
304       break;
305     case 24:
306       /* ??? This may need reworking as these cases don't necessarily
307          want the first byte and the last two bytes handled like this.  */
308       if (big_p)
309         x = (bfd_getb8 (bufp) << 16) | bfd_getb16 (bufp + 1);
310       else
311         x = bfd_getl16 (bufp) | (bfd_getb8 (bufp + 2) << 16);
312       break;
313     case 32:
314       if (big_p)
315         x = bfd_getb32 (bufp);
316       else
317         x = bfd_getl32 (bufp);
318       break;
319     default :
320       abort ();
321     }
322
323   /* Written this way to avoid undefined behaviour.  */
324   mask = (((1L << (length - 1)) - 1) << 1) | 1;
325   if (CGEN_INSN_LSB0_P)
326     shift = start;
327   else
328     shift = (word_length - (start + length));
329   x = (x & ~(mask << shift)) | ((value & mask) << shift);
330
331   switch (word_length)
332     {
333     case 8:
334       *bufp = x;
335       break;
336     case 16:
337       if (big_p)
338         bfd_putb16 (x, bufp);
339       else
340         bfd_putl16 (x, bufp);
341       break;
342     case 24:
343       /* ??? This may need reworking as these cases don't necessarily
344          want the first byte and the last two bytes handled like this.  */
345       if (big_p)
346         {
347           bfd_putb8 (x >> 16, bufp);
348           bfd_putb16 (x, bufp + 1);
349         }
350       else
351         {
352           bfd_putl16 (x, bufp);
353           bfd_putb8 (x >> 16, bufp + 2);
354         }
355       break;
356     case 32:
357       if (big_p)
358         bfd_putb32 (x, bufp);
359       else
360         bfd_putl32 (x, bufp);
361       break;
362     default :
363       abort ();
364     }
365 }
366
367 #endif /* ! CGEN_INT_INSN_P */
368
369 /* Default insertion routine.
370
371    ATTRS is a mask of the boolean attributes.
372    START is the starting bit number, architecture origin.
373    LENGTH is the length of VALUE in bits.
374    TOTAL_LENGTH is the total length of the insn.
375
376    The result is an error message or NULL if success.  */
377
378 /* ??? May need to know word length in order to properly place values as
379    an insn may be made of multiple words and the current bit number handling
380    may be insufficient.  Word length is an architectural attribute and thus
381    methinks the way to go [if needed] is to fetch this value from OD or
382    define a macro in <arch>-opc.h rather than adding an extra argument -
383    after all that's how endianness is handled.  */
384 /* ??? This duplicates functionality with bfd's howto table and
385    bfd_install_relocation.  */
386 /* ??? For architectures where insns can be representable as ints,
387    store insn in `field' struct and add registers, etc. while parsing?  */
388 /* ??? This doesn't handle bfd_vma's.  Create another function when
389    necessary.  */
390
391 static const char *
392 insert_normal (od, value, attrs, start, length, total_length, buffer)
393      CGEN_OPCODE_DESC od;
394      long value;
395      unsigned int attrs;
396      int start;
397      int length;
398      int total_length;
399      CGEN_INSN_BYTES_PTR buffer;
400 {
401   static char errbuf[100];
402   /* Written this way to avoid undefined behaviour.  */
403   unsigned long mask = (((1L << (length - 1)) - 1) << 1) | 1;
404
405   /* If LENGTH is zero, this operand doesn't contribute to the value.  */
406   if (length == 0)
407     return NULL;
408
409   /* Ensure VALUE will fit.  */
410   if ((attrs & CGEN_ATTR_MASK (CGEN_OPERAND_UNSIGNED)) != 0)
411     {
412       unsigned long maxval = mask;
413       if ((unsigned long) value > maxval)
414         {
415           /* xgettext:c-format */
416           sprintf (errbuf,
417                    _("operand out of range (%lu not between 0 and %lu)"),
418                    value, maxval);
419           return errbuf;
420         }
421     }
422   else
423     {
424       long minval = - (1L << (length - 1));
425       long maxval = (1L << (length - 1)) - 1;
426       if (value < minval || value > maxval)
427         {
428           sprintf
429             /* xgettext:c-format */
430             (errbuf, _("operand out of range (%ld not between %ld and %ld)"),
431              value, minval, maxval);
432           return errbuf;
433         }
434     }
435
436 #if CGEN_INT_INSN_P
437
438   if (total_length > 32)
439     abort ();
440   {
441     int shift;
442
443     if (CGEN_INSN_LSB0_P)
444       shift = start;
445     else
446       shift = total_length - (start + length);
447     *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
448   }
449
450 #else
451
452   /* FIXME: unfinished and untested */
453
454 /* ??? To be defined in <arch>-opc.h as necessary.  */
455 #ifndef CGEN_WORD_ENDIAN
456 #define CGEN_WORD_ENDIAN(od) CGEN_OPCODE_ENDIAN (od)
457 #endif
458 #ifndef CGEN_INSN_WORD_ENDIAN
459 #define CGEN_INSN_WORD_ENDIAN(od) CGEN_WORD_ENDIAN (od)
460 #endif
461
462   /* The hard case is probably too slow for the normal cases.
463      It's certainly more difficult to understand than the normal case.
464      Thus this is split into two.  Keep it that way.  The hard case is defined
465      to be when a field straddles a (loosely defined) word boundary
466      (??? which may require target specific help to determine).  */
467
468 #if 0 /*wip*/
469
470 #define HARD_CASE_P 0 /* FIXME:wip */
471
472   if (HARD_CASE_P)
473     {
474       unsigned char *bufp = (unsigned char *) buffer;
475       int insn_length_left = total_length;
476
477       if (CGEN_INSN_LSB0_P)
478         {
479           int word_offset = (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG
480                              ? ...
481                              : start / CGEN_BASE_INSN_BITSIZE);
482           bufp += word_offset * (CGEN_BASE_INSN_BITSIZE / 8);
483           if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG)
484           else
485             start -= word_offset * CGEN_BASE_INSN_BITSIZE;
486         }
487       else
488         {
489           int word_offset = (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG
490                              ? start / CGEN_BASE_INSN_BITSIZE
491                              : ...);
492           bufp += word_offset * (CGEN_BASE_INSN_BITSIZE / 8);
493           if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG)
494             start -= word_offset * CGEN_BASE_INSN_BITSIZE;
495           else
496         }
497
498       /* Loop so we handle a field straddling an insn word boundary
499          (remember, "insn word boundary" is loosely defined here).  */
500
501       while (length > 0)
502         {
503           int this_pass_length = length;
504           int this_pass_start = start;
505           int this_pass_word_length = min (insn_length_left,
506                                            (CGEN_BASE_INSN_BITSIZE == 8
507                                             ? 32
508                                             : CGEN_BASE_INSN_BITSIZE));
509
510           insert_1 (od, value, attrs,
511                     this_pass_start, this_pass_length, this_pass_word_length,
512                     bufp);
513
514           length -= this_pass_length;
515           insn_length_left -= this_pass_word_length;
516           if (???)
517             {
518               value >>= ???;
519               start += ???;
520             }
521           else
522             {
523               value >>= ???;
524               start += ???;
525             }
526           bufp += this_pass_word_length / 8;
527         }
528     }
529   else
530 #endif /* 0 */
531     {
532       unsigned char *bufp = (unsigned char *) buffer;
533
534       if (length > 32)
535         abort ();
536
537       /* Adjust start,total_length,bufp to point to the pseudo-word that holds
538          the value.  For example in a 48 bit insn where the value to insert
539          (say an immediate value) is the last 16 bits then word_length here
540          would be 16.  To handle a 24 bit insn with an 18 bit immediate,
541          insert_1 handles 24 bits (using a combination of bfd_get8,16).  */
542
543       if (total_length > 32)
544         {
545           int needed_width = start % 8 + length;
546           int fetch_length = (needed_width <= 8 ? 8
547                               : needed_width <= 16 ? 16
548                               : 32);
549
550           if (CGEN_INSN_LSB0_P)
551             {
552               if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG)
553                 {
554                   abort (); /* wip */
555                 }
556               else
557                 {
558                   int offset = start & ~7;
559
560                   bufp += offset / 8;
561                   start -= offset;
562                   total_length -= offset;
563                 }
564             }
565           else
566             {
567               if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG)
568                 {
569                   int offset = start & ~7;
570
571                   bufp += offset / 8;
572                   start -= offset;
573                   total_length -= offset;
574                 }
575               else
576                 {
577                   abort (); /* wip */
578                 }
579             }
580         }
581
582       insert_1 (od, value, start, length, total_length, bufp);
583     }
584
585 #endif /* ! CGEN_INT_INSN_P */
586
587   return NULL;
588 }
589 \f
590 /* Default insn parser.
591
592    The syntax string is scanned and operands are parsed and stored in FIELDS.
593    Relocs are queued as we go via other callbacks.
594
595    ??? Note that this is currently an all-or-nothing parser.  If we fail to
596    parse the instruction, we return 0 and the caller will start over from
597    the beginning.  Backtracking will be necessary in parsing subexpressions,
598    but that can be handled there.  Not handling backtracking here may get
599    expensive in the case of the m68k.  Deal with later.
600
601    Returns NULL for success, an error message for failure.
602 */
603
604 static const char *
605 parse_insn_normal (od, insn, strp, fields)
606      CGEN_OPCODE_DESC od;
607      const CGEN_INSN * insn;
608      const char ** strp;
609      CGEN_FIELDS * fields;
610 {
611   const CGEN_SYNTAX * syntax = CGEN_INSN_SYNTAX (insn);
612   const char * str = *strp;
613   const char * errmsg;
614   const char * p;
615   const unsigned char * syn;
616 #ifdef CGEN_MNEMONIC_OPERANDS
617   /* FIXME: wip */
618   int past_opcode_p;
619 #endif
620
621   /* For now we assume the mnemonic is first (there are no leading operands).
622      We can parse it without needing to set up operand parsing.
623      GAS's input scrubber will ensure mnemonics are lowercase, but we may
624      not be called from GAS.  */
625   p = CGEN_INSN_MNEMONIC (insn);
626   while (*p && tolower (*p) == tolower (*str))
627     ++p, ++str;
628   
629   if (* p || (* str && !isspace (* str)))
630     return _("unrecognized instruction");
631
632   CGEN_INIT_PARSE (od);
633   cgen_init_parse_operand (od);
634 #ifdef CGEN_MNEMONIC_OPERANDS
635   past_opcode_p = 0;
636 #endif
637
638   /* We don't check for (*str != '\0') here because we want to parse
639      any trailing fake arguments in the syntax string.  */
640   syn = CGEN_SYNTAX_STRING (syntax);
641
642   /* Mnemonics come first for now, ensure valid string.  */
643   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
644     abort ();
645
646   ++syn;
647
648   while (* syn != 0)
649     {
650       /* Non operand chars must match exactly.  */
651       if (CGEN_SYNTAX_CHAR_P (* syn))
652         {
653           if (*str == CGEN_SYNTAX_CHAR (* syn))
654             {
655 #ifdef CGEN_MNEMONIC_OPERANDS
656               if (* syn == ' ')
657                 past_opcode_p = 1;
658 #endif
659               ++ syn;
660               ++ str;
661             }
662           else
663             {
664               /* Syntax char didn't match.  Can't be this insn.  */
665               /* FIXME: would like to return something like
666                  "expected char `c'" */
667               return _("syntax error");
668             }
669           continue;
670         }
671
672       /* We have an operand of some sort.  */
673       errmsg = fr30_cgen_parse_operand (od, CGEN_SYNTAX_FIELD (*syn),
674                                           &str, fields);
675       if (errmsg)
676         return errmsg;
677
678       /* Done with this operand, continue with next one.  */
679       ++ syn;
680     }
681
682   /* If we're at the end of the syntax string, we're done.  */
683   if (* syn == '\0')
684     {
685       /* FIXME: For the moment we assume a valid `str' can only contain
686          blanks now.  IE: We needn't try again with a longer version of
687          the insn and it is assumed that longer versions of insns appear
688          before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
689       while (isspace (* str))
690         ++ str;
691
692       if (* str != '\0')
693         return _("junk at end of line"); /* FIXME: would like to include `str' */
694
695       return NULL;
696     }
697
698   /* We couldn't parse it.  */
699   return _("unrecognized instruction");
700 }
701
702 /* Default insn builder (insert handler).
703    The instruction is recorded in CGEN_INT_INSN_P byte order
704    (meaning that if CGEN_INT_INSN_P BUFFER is an int * and thus the value is
705    recorded in host byte order, otherwise BUFFER is an array of bytes and the
706    value is recorded in target byte order).
707    The result is an error message or NULL if success.  */
708
709 static const char *
710 insert_insn_normal (od, insn, fields, buffer, pc)
711      CGEN_OPCODE_DESC od;
712      const CGEN_INSN * insn;
713      CGEN_FIELDS * fields;
714      CGEN_INSN_BYTES_PTR buffer;
715      bfd_vma pc;
716 {
717   const CGEN_SYNTAX * syntax = CGEN_INSN_SYNTAX (insn);
718   unsigned long value;
719   const unsigned char * syn;
720
721   CGEN_INIT_INSERT (od);
722   value = CGEN_INSN_VALUE (insn);
723
724   /* If we're recording insns as numbers (rather than a string of bytes),
725      target byte order handling is deferred until later.  */
726
727 #if CGEN_INT_INSN_P
728
729   *buffer = value;
730
731 #else
732
733   cgen_insn_put_value (od, buffer, min (CGEN_BASE_INSN_BITSIZE,
734                                         CGEN_FIELDS_BITSIZE (fields)),
735                        value);
736
737 #endif /* ! CGEN_INT_INSN_P */
738
739   /* ??? Rather than scanning the syntax string again, we could store
740      in `fields' a null terminated list of the fields that are present.  */
741
742   for (syn = CGEN_SYNTAX_STRING (syntax); * syn != '\0'; ++ syn)
743     {
744       const char *errmsg;
745
746       if (CGEN_SYNTAX_CHAR_P (* syn))
747         continue;
748
749       errmsg = fr30_cgen_insert_operand (od, CGEN_SYNTAX_FIELD (*syn),
750                                            fields, buffer, pc);
751       if (errmsg)
752         return errmsg;
753     }
754
755   return NULL;
756 }
757 \f
758 /* Main entry point.
759    This routine is called for each instruction to be assembled.
760    STR points to the insn to be assembled.
761    We assume all necessary tables have been initialized.
762    The assembled instruction, less any fixups, is stored in BUF.
763    Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
764    still needs to be converted to target byte order, otherwise BUF is an array
765    of bytes in target byte order.
766    The result is a pointer to the insn's entry in the opcode table,
767    or NULL if an error occured (an error message will have already been
768    printed).
769
770    Note that when processing (non-alias) macro-insns,
771    this function recurses.  */
772
773 const CGEN_INSN *
774 fr30_cgen_assemble_insn (od, str, fields, buf, errmsg)
775      CGEN_OPCODE_DESC od;
776      const char * str;
777      CGEN_FIELDS * fields;
778      CGEN_INSN_BYTES_PTR buf;
779      char ** errmsg;
780 {
781   const char * start;
782   CGEN_INSN_LIST * ilist;
783
784   /* Skip leading white space.  */
785   while (isspace (* str))
786     ++ str;
787
788   /* The instructions are stored in hashed lists.
789      Get the first in the list.  */
790   ilist = CGEN_ASM_LOOKUP_INSN (od, str);
791
792   /* Keep looking until we find a match.  */
793
794   start = str;
795   for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
796     {
797       const CGEN_INSN *insn = ilist->insn;
798
799 #if 0 /* not needed as unsupported opcodes shouldn't be in the hash lists */
800       /* Is this insn supported by the selected cpu?  */
801       if (! fr30_cgen_insn_supported (od, insn))
802         continue;
803 #endif
804
805       /* If the RELAX attribute is set, this is an insn that shouldn't be
806          chosen immediately.  Instead, it is used during assembler/linker
807          relaxation if possible.  */
808       if (CGEN_INSN_ATTR (insn, CGEN_INSN_RELAX) != 0)
809         continue;
810
811       str = start;
812
813       /* Record a default length for the insn.  This will get set to the
814          correct value while parsing.  */
815       /* FIXME: wip */
816       CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
817
818       if (! CGEN_PARSE_FN (insn) (od, insn, & str, fields))
819         {
820           /* ??? 0 is passed for `pc' */
821           if (CGEN_INSERT_FN (insn) (od, insn, fields, buf, (bfd_vma) 0) != NULL)
822             continue;
823           /* It is up to the caller to actually output the insn and any
824              queued relocs.  */
825           return insn;
826         }
827
828       /* Try the next entry.  */
829     }
830
831   /* FIXME: We can return a better error message than this.
832      Need to track why it failed and pick the right one.  */
833   {
834     static char errbuf[100];
835     if (strlen (start) > 50)
836       /* xgettext:c-format */
837       sprintf (errbuf, _("bad instruction `%.50s...'"), start);
838     else 
839       /* xgettext:c-format */
840       sprintf (errbuf, _("bad instruction `%.50s'"), start);
841       
842     *errmsg = errbuf;
843     return NULL;
844   }
845 }
846 \f
847 #if 0 /* This calls back to GAS which we can't do without care.  */
848
849 /* Record each member of OPVALS in the assembler's symbol table.
850    This lets GAS parse registers for us.
851    ??? Interesting idea but not currently used.  */
852
853 /* Record each member of OPVALS in the assembler's symbol table.
854    FIXME: Not currently used.  */
855
856 void
857 fr30_cgen_asm_hash_keywords (od, opvals)
858      CGEN_OPCODE_DESC od;
859      CGEN_KEYWORD * opvals;
860 {
861   CGEN_KEYWORD_SEARCH search = cgen_keyword_search_init (opvals, NULL);
862   const CGEN_KEYWORD_ENTRY * ke;
863
864   while ((ke = cgen_keyword_search_next (& search)) != NULL)
865     {
866 #if 0 /* Unnecessary, should be done in the search routine.  */
867       if (! fr30_cgen_opval_supported (ke))
868         continue;
869 #endif
870       cgen_asm_record_register (od, ke->name, ke->value);
871     }
872 }
873
874 #endif /* 0 */