4e5911a549004eaee2ea17cfc7e6c94ac60d1163
[platform/upstream/binutils.git] / opcodes / m32r-asm.c
1 /* Assembler interface for targets using CGEN. -*- C -*-
2    CGEN: Cpu tools GENerator
3
4 This file is used to generate m32r-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
22 Foundation, Inc., 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 "m32r-opc.h"
31
32 /* ??? The layout of this stuff is still work in progress.
33    For speed in assembly/disassembly, we use inline functions.  That of course
34    will only work for GCC.  When this stuff is finished, we can decide whether
35    to keep the inline functions (and only get the performance increase when
36    compiled with GCC), or switch to macros, or use something else.
37 */
38
39 static const char * insert_normal
40      PARAMS ((long, unsigned int, int, int, int, char *));
41 static const char * parse_insn_normal
42      PARAMS ((const CGEN_INSN *, const char **, CGEN_FIELDS *));
43 static const char * insert_insn_normal
44      PARAMS ((const CGEN_INSN *, CGEN_FIELDS *, cgen_insn_t *));
45 \f
46 /* -- assembler routines inserted here */
47 /* -- asm.c */
48
49 /* Handle '#' prefixes (i.e. skip over them).  */
50
51 static const char *
52 parse_hash (strp, opindex, valuep)
53      const char **strp;
54      int opindex;
55      unsigned long *valuep;
56 {
57   if (**strp == '#')
58     ++*strp;
59   return NULL;
60 }
61
62 /* Handle shigh(), high().  */
63
64 static const char *
65 parse_hi16 (strp, opindex, valuep)
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
73   if (**strp == '#')
74     ++*strp;
75
76   if (strncmp (*strp, "high(", 5) == 0)
77     {
78       *strp += 5;
79       errmsg = cgen_parse_address (strp, opindex, BFD_RELOC_M32R_HI16_ULO,
80                                    &result_type, valuep);
81       if (**strp != ')')
82         return "missing `)'";
83       ++*strp;
84       if (errmsg == NULL
85           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
86         *valuep >>= 16;
87       return errmsg;
88     }
89   else if (strncmp (*strp, "shigh(", 6) == 0)
90     {
91       *strp += 6;
92       errmsg = cgen_parse_address (strp, opindex, BFD_RELOC_M32R_HI16_SLO,
93                                    &result_type, valuep);
94       if (**strp != ')')
95         return "missing `)'";
96       ++*strp;
97       if (errmsg == NULL
98           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
99         *valuep = (*valuep >> 16) + ((*valuep) & 0x8000 ? 1 : 0);
100       return errmsg;
101     }
102
103   return cgen_parse_unsigned_integer (strp, opindex, valuep);
104 }
105
106 /* Handle low() in a signed context.  Also handle sda().
107    The signedness of the value doesn't matter to low(), but this also
108    handles the case where low() isn't present.  */
109
110 static const char *
111 parse_slo16 (strp, opindex, valuep)
112      const char **strp;
113      int opindex;
114      long *valuep;
115 {
116   const char *errmsg;
117   enum cgen_parse_operand_result result_type;
118
119   if (**strp == '#')
120     ++*strp;
121
122   if (strncmp (*strp, "low(", 4) == 0)
123     {
124       *strp += 4;
125       errmsg = cgen_parse_address (strp, opindex, BFD_RELOC_M32R_LO16,
126                                    &result_type, valuep);
127       if (**strp != ')')
128         return "missing `)'";
129       ++*strp;
130       if (errmsg == NULL
131           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
132         *valuep &= 0xffff;
133       return errmsg;
134     }
135
136   if (strncmp (*strp, "sda(", 4) == 0)
137     {
138       *strp += 4;
139       errmsg = cgen_parse_address (strp, opindex, BFD_RELOC_M32R_SDA16, NULL, valuep);
140       if (**strp != ')')
141         return "missing `)'";
142       ++*strp;
143       return errmsg;
144     }
145
146   return cgen_parse_signed_integer (strp, opindex, valuep);
147 }
148
149 /* Handle low() in an unsigned context.
150    The signedness of the value doesn't matter to low(), but this also
151    handles the case where low() isn't present.  */
152
153 static const char *
154 parse_ulo16 (strp, opindex, valuep)
155      const char **strp;
156      int opindex;
157      unsigned long *valuep;
158 {
159   const char *errmsg;
160   enum cgen_parse_operand_result result_type;
161
162   if (**strp == '#')
163     ++*strp;
164
165   if (strncmp (*strp, "low(", 4) == 0)
166     {
167       *strp += 4;
168       errmsg = cgen_parse_address (strp, opindex, BFD_RELOC_M32R_LO16,
169                                    &result_type, valuep);
170       if (**strp != ')')
171         return "missing `)'";
172       ++*strp;
173       if (errmsg == NULL
174           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
175         *valuep &= 0xffff;
176       return errmsg;
177     }
178
179   return cgen_parse_unsigned_integer (strp, opindex, valuep);
180 }
181
182 /* -- */
183
184 /* Main entry point for operand parsing.
185
186    This function is basically just a big switch statement.  Earlier versions
187    used tables to look up the function to use, but
188    - if the table contains both assembler and disassembler functions then
189      the disassembler contains much of the assembler and vice-versa,
190    - there's a lot of inlining possibilities as things grow,
191    - using a switch statement avoids the function call overhead.
192
193    This function could be moved into `parse_insn_normal', but keeping it
194    separate makes clear the interface between `parse_insn_normal' and each of
195    the handlers.
196 */
197
198 const char *
199 m32r_cgen_parse_operand (opindex, strp, fields)
200      int opindex;
201      const char ** strp;
202      CGEN_FIELDS * fields;
203 {
204   const char * errmsg;
205
206   switch (opindex)
207     {
208     case M32R_OPERAND_SR :
209       errmsg = cgen_parse_keyword (strp, & m32r_cgen_opval_h_gr, & fields->f_r2);
210       break;
211     case M32R_OPERAND_DR :
212       errmsg = cgen_parse_keyword (strp, & m32r_cgen_opval_h_gr, & fields->f_r1);
213       break;
214     case M32R_OPERAND_SRC1 :
215       errmsg = cgen_parse_keyword (strp, & m32r_cgen_opval_h_gr, & fields->f_r1);
216       break;
217     case M32R_OPERAND_SRC2 :
218       errmsg = cgen_parse_keyword (strp, & m32r_cgen_opval_h_gr, & fields->f_r2);
219       break;
220     case M32R_OPERAND_SCR :
221       errmsg = cgen_parse_keyword (strp, & m32r_cgen_opval_h_cr, & fields->f_r2);
222       break;
223     case M32R_OPERAND_DCR :
224       errmsg = cgen_parse_keyword (strp, & m32r_cgen_opval_h_cr, & fields->f_r1);
225       break;
226     case M32R_OPERAND_SIMM8 :
227       errmsg = cgen_parse_signed_integer (strp, M32R_OPERAND_SIMM8, &fields->f_simm8);
228       break;
229     case M32R_OPERAND_SIMM16 :
230       errmsg = cgen_parse_signed_integer (strp, M32R_OPERAND_SIMM16, &fields->f_simm16);
231       break;
232     case M32R_OPERAND_UIMM4 :
233       errmsg = cgen_parse_unsigned_integer (strp, M32R_OPERAND_UIMM4, &fields->f_uimm4);
234       break;
235     case M32R_OPERAND_UIMM5 :
236       errmsg = cgen_parse_unsigned_integer (strp, M32R_OPERAND_UIMM5, &fields->f_uimm5);
237       break;
238     case M32R_OPERAND_UIMM16 :
239       errmsg = cgen_parse_unsigned_integer (strp, M32R_OPERAND_UIMM16, &fields->f_uimm16);
240       break;
241 /* start-sanitize-m32rx */
242     case M32R_OPERAND_IMM1 :
243       errmsg = cgen_parse_unsigned_integer (strp, M32R_OPERAND_IMM1, &fields->f_imm1);
244       break;
245 /* end-sanitize-m32rx */
246 /* start-sanitize-m32rx */
247     case M32R_OPERAND_ACCD :
248       errmsg = cgen_parse_keyword (strp, & m32r_cgen_opval_h_accums, & fields->f_accd);
249       break;
250 /* end-sanitize-m32rx */
251 /* start-sanitize-m32rx */
252     case M32R_OPERAND_ACCS :
253       errmsg = cgen_parse_keyword (strp, & m32r_cgen_opval_h_accums, & fields->f_accs);
254       break;
255 /* end-sanitize-m32rx */
256 /* start-sanitize-m32rx */
257     case M32R_OPERAND_ACC :
258       errmsg = cgen_parse_keyword (strp, & m32r_cgen_opval_h_accums, & fields->f_acc);
259       break;
260 /* end-sanitize-m32rx */
261     case M32R_OPERAND_HASH :
262       errmsg = parse_hash (strp, M32R_OPERAND_HASH, &fields->f_nil);
263       break;
264     case M32R_OPERAND_HI16 :
265       errmsg = parse_hi16 (strp, M32R_OPERAND_HI16, &fields->f_hi16);
266       break;
267     case M32R_OPERAND_SLO16 :
268       errmsg = parse_slo16 (strp, M32R_OPERAND_SLO16, &fields->f_simm16);
269       break;
270     case M32R_OPERAND_ULO16 :
271       errmsg = parse_ulo16 (strp, M32R_OPERAND_ULO16, &fields->f_uimm16);
272       break;
273     case M32R_OPERAND_UIMM24 :
274       errmsg = cgen_parse_address (strp, M32R_OPERAND_UIMM24, 0, NULL, & fields->f_uimm24);
275       break;
276     case M32R_OPERAND_DISP8 :
277       errmsg = cgen_parse_address (strp, M32R_OPERAND_DISP8, 0, NULL, & fields->f_disp8);
278       break;
279     case M32R_OPERAND_DISP16 :
280       errmsg = cgen_parse_address (strp, M32R_OPERAND_DISP16, 0, NULL, & fields->f_disp16);
281       break;
282     case M32R_OPERAND_DISP24 :
283       errmsg = cgen_parse_address (strp, M32R_OPERAND_DISP24, 0, NULL, & fields->f_disp24);
284       break;
285
286     default :
287       fprintf (stderr, "Unrecognized field %d while parsing.\n", opindex);
288       abort ();
289   }
290
291   return errmsg;
292 }
293
294 /* Main entry point for operand insertion.
295
296    This function is basically just a big switch statement.  Earlier versions
297    used tables to look up the function to use, but
298    - if the table contains both assembler and disassembler functions then
299      the disassembler contains much of the assembler and vice-versa,
300    - there's a lot of inlining possibilities as things grow,
301    - using a switch statement avoids the function call overhead.
302
303    This function could be moved into `parse_insn_normal', but keeping it
304    separate makes clear the interface between `parse_insn_normal' and each of
305    the handlers.  It's also needed by GAS to insert operands that couldn't be
306    resolved during parsing.
307 */
308
309 const char *
310 m32r_cgen_insert_operand (opindex, fields, buffer)
311      int opindex;
312      CGEN_FIELDS * fields;
313      char * buffer;
314 {
315   const char * errmsg;
316
317   switch (opindex)
318     {
319     case M32R_OPERAND_SR :
320       errmsg = insert_normal (fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
321       break;
322     case M32R_OPERAND_DR :
323       errmsg = insert_normal (fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
324       break;
325     case M32R_OPERAND_SRC1 :
326       errmsg = insert_normal (fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
327       break;
328     case M32R_OPERAND_SRC2 :
329       errmsg = insert_normal (fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
330       break;
331     case M32R_OPERAND_SCR :
332       errmsg = insert_normal (fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
333       break;
334     case M32R_OPERAND_DCR :
335       errmsg = insert_normal (fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
336       break;
337     case M32R_OPERAND_SIMM8 :
338       errmsg = insert_normal (fields->f_simm8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), 8, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
339       break;
340     case M32R_OPERAND_SIMM16 :
341       errmsg = insert_normal (fields->f_simm16, 0|(1<<CGEN_OPERAND_HASH_PREFIX), 16, 16, CGEN_FIELDS_BITSIZE (fields), buffer);
342       break;
343     case M32R_OPERAND_UIMM4 :
344       errmsg = insert_normal (fields->f_uimm4, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
345       break;
346     case M32R_OPERAND_UIMM5 :
347       errmsg = insert_normal (fields->f_uimm5, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 11, 5, CGEN_FIELDS_BITSIZE (fields), buffer);
348       break;
349     case M32R_OPERAND_UIMM16 :
350       errmsg = insert_normal (fields->f_uimm16, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, CGEN_FIELDS_BITSIZE (fields), buffer);
351       break;
352 /* start-sanitize-m32rx */
353     case M32R_OPERAND_IMM1 :
354       {
355         long value = ((fields->f_imm1) - (1));
356         errmsg = insert_normal (value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 15, 1, CGEN_FIELDS_BITSIZE (fields), buffer);
357       }
358       break;
359 /* end-sanitize-m32rx */
360 /* start-sanitize-m32rx */
361     case M32R_OPERAND_ACCD :
362       errmsg = insert_normal (fields->f_accd, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 2, CGEN_FIELDS_BITSIZE (fields), buffer);
363       break;
364 /* end-sanitize-m32rx */
365 /* start-sanitize-m32rx */
366     case M32R_OPERAND_ACCS :
367       errmsg = insert_normal (fields->f_accs, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 2, CGEN_FIELDS_BITSIZE (fields), buffer);
368       break;
369 /* end-sanitize-m32rx */
370 /* start-sanitize-m32rx */
371     case M32R_OPERAND_ACC :
372       errmsg = insert_normal (fields->f_acc, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 1, CGEN_FIELDS_BITSIZE (fields), buffer);
373       break;
374 /* end-sanitize-m32rx */
375     case M32R_OPERAND_HASH :
376       errmsg = insert_normal (fields->f_nil, 0, 0, 0, CGEN_FIELDS_BITSIZE (fields), buffer);
377       break;
378     case M32R_OPERAND_HI16 :
379       errmsg = insert_normal (fields->f_hi16, 0|(1<<CGEN_OPERAND_SIGN_OPT)|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, CGEN_FIELDS_BITSIZE (fields), buffer);
380       break;
381     case M32R_OPERAND_SLO16 :
382       errmsg = insert_normal (fields->f_simm16, 0, 16, 16, CGEN_FIELDS_BITSIZE (fields), buffer);
383       break;
384     case M32R_OPERAND_ULO16 :
385       errmsg = insert_normal (fields->f_uimm16, 0|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, CGEN_FIELDS_BITSIZE (fields), buffer);
386       break;
387     case M32R_OPERAND_UIMM24 :
388       errmsg = insert_normal (fields->f_uimm24, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR)|(1<<CGEN_OPERAND_UNSIGNED), 8, 24, CGEN_FIELDS_BITSIZE (fields), buffer);
389       break;
390     case M32R_OPERAND_DISP8 :
391       {
392         long value = ((fields->f_disp8) >> (2));
393         errmsg = insert_normal (value, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 8, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
394       }
395       break;
396     case M32R_OPERAND_DISP16 :
397       {
398         long value = ((fields->f_disp16) >> (2));
399         errmsg = insert_normal (value, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 16, 16, CGEN_FIELDS_BITSIZE (fields), buffer);
400       }
401       break;
402     case M32R_OPERAND_DISP24 :
403       {
404         long value = ((fields->f_disp24) >> (2));
405         errmsg = insert_normal (value, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 8, 24, CGEN_FIELDS_BITSIZE (fields), buffer);
406       }
407       break;
408
409     default :
410       fprintf (stderr, "Unrecognized field %d while building insn.\n",
411                opindex);
412       abort ();
413   }
414
415   return errmsg;
416 }
417
418 cgen_parse_fn * m32r_cgen_parse_handlers[] = 
419 {
420   0, /* default */
421   parse_insn_normal,
422 };
423
424 cgen_insert_fn * m32r_cgen_insert_handlers[] = 
425 {
426   0, /* default */
427   insert_insn_normal,
428 };
429
430 void
431 m32r_cgen_init_asm (mach, endian)
432      int mach;
433      enum cgen_endian endian;
434 {
435   m32r_cgen_init_tables (mach);
436   cgen_set_cpu (& m32r_cgen_opcode_table, mach, endian);
437   cgen_asm_init ();
438 }
439
440 \f
441 /* Default insertion routine.
442
443    ATTRS is a mask of the boolean attributes.
444    LENGTH is the length of VALUE in bits.
445    TOTAL_LENGTH is the total length of the insn (currently 8,16,32).
446
447    The result is an error message or NULL if success.  */
448
449 /* ??? This duplicates functionality with bfd's howto table and
450    bfd_install_relocation.  */
451 /* ??? For architectures where insns can be representable as ints,
452    store insn in `field' struct and add registers, etc. while parsing?  */
453
454 static const char *
455 insert_normal (value, attrs, start, length, total_length, buffer)
456      long value;
457      unsigned int attrs;
458      int start;
459      int length;
460      int total_length;
461      char * buffer;
462 {
463   bfd_vma x;
464   static char buf[100];
465
466   /* Ensure VALUE will fit.  */
467   if ((attrs & (1 << CGEN_OPERAND_UNSIGNED)) != 0)
468     {
469       unsigned long max = (1 << length) - 1;
470       if ((unsigned long) value > max)
471         {
472           const char *err = "operand out of range (%lu not between 0 and %lu)";
473
474           sprintf (buf, err, value, max);
475           return buf;
476         }
477     }
478   else
479     {
480       long min = - (1 << (length - 1));
481       long max = (1 << (length - 1)) - 1;
482       if (value < min || value > max)
483         {
484           const char *err = "operand out of range (%ld not between %ld and %ld)";
485
486           sprintf (buf, err, value, min, max);
487           return buf;
488         }
489     }
490
491 #if 0 /*def CGEN_INT_INSN*/
492   *buffer |= ((value & ((1 << length) - 1))
493               << (total_length - (start + length)));
494 #else
495   switch (total_length)
496     {
497     case 8:
498       x = * (unsigned char *) buffer;
499       break;
500     case 16:
501       if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG)
502         x = bfd_getb16 (buffer);
503       else
504         x = bfd_getl16 (buffer);
505       break;
506     case 32:
507       if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG)
508         x = bfd_getb32 (buffer);
509       else
510         x = bfd_getl32 (buffer);
511       break;
512     default :
513       abort ();
514     }
515
516   x |= ((value & ((1 << length) - 1))
517         << (total_length - (start + length)));
518
519   switch (total_length)
520     {
521     case 8:
522       * buffer = value;
523       break;
524     case 16:
525       if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG)
526         bfd_putb16 (x, buffer);
527       else
528         bfd_putl16 (x, buffer);
529       break;
530     case 32:
531       if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG)
532         bfd_putb32 (x, buffer);
533       else
534         bfd_putl32 (x, buffer);
535       break;
536     default :
537       abort ();
538     }
539 #endif
540
541   return NULL;
542 }
543 \f
544 /* Default insn parser.
545
546    The syntax string is scanned and operands are parsed and stored in FIELDS.
547    Relocs are queued as we go via other callbacks.
548
549    ??? Note that this is currently an all-or-nothing parser.  If we fail to
550    parse the instruction, we return 0 and the caller will start over from
551    the beginning.  Backtracking will be necessary in parsing subexpressions,
552    but that can be handled there.  Not handling backtracking here may get
553    expensive in the case of the m68k.  Deal with later.
554
555    Returns NULL for success, an error message for failure.
556 */
557
558 static const char *
559 parse_insn_normal (insn, strp, fields)
560      const CGEN_INSN * insn;
561      const char ** strp;
562      CGEN_FIELDS * fields;
563 {
564   const CGEN_SYNTAX * syntax = CGEN_INSN_SYNTAX (insn);
565   const char * str = *strp;
566   const char * errmsg;
567   const char * p;
568   const unsigned char * syn;
569 #ifdef CGEN_MNEMONIC_OPERANDS
570   int past_opcode_p;
571 #endif
572
573   /* For now we assume the mnemonic is first (there are no leading operands).
574      We can parse it without needing to set up operand parsing.  */
575   p = CGEN_INSN_MNEMONIC (insn);
576   while (* p && * p == * str)
577     ++ p, ++ str;
578   if (* p || (* str && !isspace (* str)))
579     return "unrecognized instruction";
580
581   CGEN_INIT_PARSE ();
582   cgen_init_parse_operand ();
583 #ifdef CGEN_MNEMONIC_OPERANDS
584   past_opcode_p = 0;
585 #endif
586
587   /* We don't check for (*str != '\0') here because we want to parse
588      any trailing fake arguments in the syntax string.  */
589   syn = CGEN_SYNTAX_STRING (CGEN_INSN_SYNTAX (insn));
590
591   /* Mnemonics come first for now, ensure valid string.  */
592   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
593     abort ();
594
595   ++syn;
596
597   while (* syn != 0)
598     {
599       /* Non operand chars must match exactly.  */
600       /* FIXME: Need to better handle whitespace.  */
601       if (CGEN_SYNTAX_CHAR_P (* syn))
602         {
603           if (*str == CGEN_SYNTAX_CHAR (* syn))
604             {
605 #ifdef CGEN_MNEMONIC_OPERANDS
606               if (* syn == ' ')
607                 past_opcode_p = 1;
608 #endif
609               ++ syn;
610               ++ str;
611             }
612           else
613             {
614               /* Syntax char didn't match.  Can't be this insn.  */
615               /* FIXME: would like to return something like
616                  "expected char `c'" */
617               return "syntax error";
618             }
619           continue;
620         }
621
622       /* We have an operand of some sort.  */
623       errmsg = m32r_cgen_parse_operand (CGEN_SYNTAX_FIELD (*syn),
624                                          &str, fields);
625       if (errmsg)
626         return errmsg;
627
628       /* Done with this operand, continue with next one.  */
629       ++ syn;
630     }
631
632   /* If we're at the end of the syntax string, we're done.  */
633   if (* syn == '\0')
634     {
635       /* FIXME: For the moment we assume a valid `str' can only contain
636          blanks now.  IE: We needn't try again with a longer version of
637          the insn and it is assumed that longer versions of insns appear
638          before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
639       while (isspace (* str))
640         ++ str;
641
642       if (* str != '\0')
643         return "junk at end of line"; /* FIXME: would like to include `str' */
644
645       return NULL;
646     }
647
648   /* We couldn't parse it.  */
649   return "unrecognized instruction";
650 }
651
652 /* Default insn builder (insert handler).
653    The instruction is recorded in target byte order.
654    The result is an error message or NULL if success.  */
655 /* FIXME: change buffer to char *?  */
656
657 static const char *
658 insert_insn_normal (insn, fields, buffer)
659      const CGEN_INSN * insn;
660      CGEN_FIELDS * fields;
661      cgen_insn_t * buffer;
662 {
663   const CGEN_SYNTAX * syntax = CGEN_INSN_SYNTAX (insn);
664   bfd_vma value;
665   const unsigned char * syn;
666
667   CGEN_INIT_INSERT ();
668   value = CGEN_INSN_VALUE (insn);
669
670   /* If we're recording insns as numbers (rather than a string of bytes),
671      target byte order handling is deferred until later.  */
672 #undef min
673 #define min(a,b) ((a) < (b) ? (a) : (b))
674 #if 0 /*def CGEN_INT_INSN*/
675   *buffer = value;
676 #else
677   switch (min (CGEN_BASE_INSN_BITSIZE, CGEN_FIELDS_BITSIZE (fields)))
678     {
679     case 8:
680       * buffer = value;
681       break;
682     case 16:
683       if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG)
684         bfd_putb16 (value, (char *) buffer);
685       else
686         bfd_putl16 (value, (char *) buffer);
687       break;
688     case 32:
689       if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG)
690         bfd_putb32 (value, (char *) buffer);
691       else
692         bfd_putl32 (value, (char *) buffer);
693       break;
694     default:
695       abort ();
696     }
697 #endif
698
699   /* ??? Rather than scanning the syntax string again, we could store
700      in `fields' a null terminated list of the fields that are present.  */
701
702   for (syn = CGEN_SYNTAX_STRING (syntax); * syn != '\0'; ++ syn)
703     {
704       const char *errmsg;
705
706       if (CGEN_SYNTAX_CHAR_P (* syn))
707         continue;
708
709       errmsg = m32r_cgen_insert_operand (CGEN_SYNTAX_FIELD (*syn), fields,
710                                            (char *) buffer);
711       if (errmsg)
712         return errmsg;
713     }
714
715   return NULL;
716 }
717 \f
718 /* Main entry point.
719    This routine is called for each instruction to be assembled.
720    STR points to the insn to be assembled.
721    We assume all necessary tables have been initialized.
722    The assembled instruction, less any fixups, is stored in buf.
723    [??? What byte order?]
724    The result is a pointer to the insn's entry in the opcode table,
725    or NULL if an error occured (an error message will have already been
726    printed).
727
728    Note that when processing (non-alias) macro-insns,
729    this function recurses.  */
730
731 const CGEN_INSN *
732 m32r_cgen_assemble_insn (str, fields, buf, errmsg)
733      const char * str;
734      CGEN_FIELDS * fields;
735      cgen_insn_t * buf;
736      char ** errmsg;
737 {
738   const char * start;
739   CGEN_INSN_LIST * ilist;
740
741   /* Skip leading white space.  */
742   while (isspace (* str))
743     ++ str;
744
745   /* The instructions are stored in hashed lists.
746      Get the first in the list.  */
747   ilist = CGEN_ASM_LOOKUP_INSN (str);
748
749   /* Keep looking until we find a match.  */
750
751   start = str;
752   for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
753     {
754       const CGEN_INSN *insn = ilist->insn;
755
756 #if 0 /* not needed as unsupported opcodes shouldn't be in the hash lists */
757       /* Is this insn supported by the selected cpu?  */
758       if (! m32r_cgen_insn_supported (insn))
759         continue;
760 #endif
761
762 #if 1 /* FIXME: wip */
763       /* If the RELAX attribute is set, this is an insn that shouldn't be
764          chosen immediately.  Instead, it is used during assembler/linker
765          relaxation if possible.  */
766       if (CGEN_INSN_ATTR (insn, CGEN_INSN_RELAX) != 0)
767         continue;
768 #endif
769
770       str = start;
771
772       /* Record a default length for the insn.  This will get set to the
773          correct value while parsing.  */
774       /* FIXME: wip */
775       CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
776
777       if (! CGEN_PARSE_FN (insn) (insn, & str, fields))
778         {
779           if (CGEN_INSERT_FN (insn) (insn, fields, buf) != NULL)
780             continue;
781           /* It is up to the caller to actually output the insn and any
782              queued relocs.  */
783           return insn;
784         }
785
786       /* Try the next entry.  */
787     }
788
789   /* FIXME: We can return a better error message than this.
790      Need to track why it failed and pick the right one.  */
791   {
792     static char errbuf[100];
793     sprintf (errbuf, "bad instruction `%.50s%s'",
794              start, strlen (start) > 50 ? "..." : "");
795     *errmsg = errbuf;
796     return NULL;
797   }
798 }
799 \f
800 #if 0 /* This calls back to GAS which we can't do without care.  */
801
802 /* Record each member of OPVALS in the assembler's symbol table.
803    This lets GAS parse registers for us.
804    ??? Interesting idea but not currently used.  */
805
806 /* Record each member of OPVALS in the assembler's symbol table.
807    FIXME: Not currently used.  */
808
809 void
810 m32r_cgen_asm_hash_keywords (opvals)
811      CGEN_KEYWORD * opvals;
812 {
813   CGEN_KEYWORD_SEARCH search = cgen_keyword_search_init (opvals, NULL);
814   const CGEN_KEYWORD_ENTRY * ke;
815
816   while ((ke = cgen_keyword_search_next (& search)) != NULL)
817     {
818 #if 0 /* Unnecessary, should be done in the search routine.  */
819       if (! m32r_cgen_opval_supported (ke))
820         continue;
821 #endif
822       cgen_asm_record_register (ke->name, ke->value);
823     }
824 }
825
826 #endif /* 0 */