* sun build fix for thinko (?)
[binutils-gdb.git] / opcodes / fr30-asm.c
blob22f452cf0438243806adb0432f3b33acb46e52ab
1 /* Assembler interface for targets using CGEN. -*- C -*-
2 CGEN: Cpu tools GENerator
4 THIS FILE IS USED TO GENERATE fr30-asm.c.
6 Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
8 This file is part of the GNU Binutils and GDB, the GNU debugger.
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.
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.
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. */
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"
33 #undef min
34 #define min(a,b) ((a) < (b) ? (a) : (b))
35 #undef max
36 #define max(a,b) ((a) > (b) ? (a) : (b))
38 #undef INLINE
39 #ifdef __GNUC__
40 #define INLINE __inline__
41 #else
42 #define INLINE
43 #endif
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));
55 /* -- assembler routines inserted here */
57 /* Main entry point for operand parsing.
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.
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.
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;
78 const char * errmsg;
80 switch (opindex)
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;
134 default :
135 /* xgettext:c-format */
136 fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
137 abort ();
140 return errmsg;
143 /* Main entry point for operand insertion.
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.
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.
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;
166 const char * errmsg;
168 switch (opindex)
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 :
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);
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 :
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);
207 break;
208 case FR30_OPERAND_U10 :
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);
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 :
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);
224 break;
225 case FR30_OPERAND_DIR10 :
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);
231 break;
232 case FR30_OPERAND_LABEL9 :
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);
238 break;
239 case FR30_OPERAND_LABEL12 :
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);
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;
250 default :
251 /* xgettext:c-format */
252 fprintf (stderr, _("Unrecognized field %d while building insn.\n"),
253 opindex);
254 abort ();
257 return errmsg;
260 cgen_parse_fn * const fr30_cgen_parse_handlers[] =
262 0, /* default */
263 parse_insn_normal,
266 cgen_insert_fn * const fr30_cgen_insert_handlers[] =
268 0, /* default */
269 insert_insn_normal,
272 void
273 fr30_cgen_init_asm (od)
274 CGEN_OPCODE_DESC od;
279 #if ! CGEN_INT_INSN_P
281 /* Subroutine of insert_normal. */
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;
290 unsigned long x,mask;
291 int shift;
292 int big_p = CGEN_OPCODE_INSN_ENDIAN (od) == CGEN_ENDIAN_BIG;
294 switch (word_length)
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 ();
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);
331 switch (word_length)
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)
347 bfd_putb8 (x >> 16, bufp);
348 bfd_putb16 (x, bufp + 1);
350 else
352 bfd_putl16 (x, bufp);
353 bfd_putb8 (x >> 16, bufp + 2);
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 ();
367 #endif /* ! CGEN_INT_INSN_P */
369 /* Default insertion routine.
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.
376 The result is an error message or NULL if success. */
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. */
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;
401 static char errbuf[100];
402 /* Written this way to avoid undefined behaviour. */
403 unsigned long mask = (((1L << (length - 1)) - 1) << 1) | 1;
405 /* If LENGTH is zero, this operand doesn't contribute to the value. */
406 if (length == 0)
407 return NULL;
409 /* Ensure VALUE will fit. */
410 if ((attrs & CGEN_ATTR_MASK (CGEN_OPERAND_UNSIGNED)) != 0)
412 unsigned long maxval = mask;
413 if ((unsigned long) value > maxval)
415 /* xgettext:c-format */
416 sprintf (errbuf,
417 _("operand out of range (%lu not between 0 and %lu)"),
418 value, maxval);
419 return errbuf;
422 else
424 long minval = - (1L << (length - 1));
425 long maxval = (1L << (length - 1)) - 1;
426 if (value < minval || value > maxval)
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;
436 #if CGEN_INT_INSN_P
438 if (total_length > 32)
439 abort ();
441 int shift;
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);
450 #else
452 /* FIXME: unfinished and untested */
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
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). */
468 #if 0 /*wip*/
470 #define HARD_CASE_P 0 /* FIXME:wip */
472 if (HARD_CASE_P)
474 unsigned char *bufp = (unsigned char *) buffer;
475 int insn_length_left = total_length;
477 if (CGEN_INSN_LSB0_P)
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;
487 else
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
498 /* Loop so we handle a field straddling an insn word boundary
499 (remember, "insn word boundary" is loosely defined here). */
501 while (length > 0)
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));
510 insert_1 (od, value, attrs,
511 this_pass_start, this_pass_length, this_pass_word_length,
512 bufp);
514 length -= this_pass_length;
515 insn_length_left -= this_pass_word_length;
516 if (???)
518 value >>= ???;
519 start += ???;
521 else
523 value >>= ???;
524 start += ???;
526 bufp += this_pass_word_length / 8;
529 else
530 #endif /* 0 */
532 unsigned char *bufp = (unsigned char *) buffer;
534 if (length > 32)
535 abort ();
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). */
543 if (total_length > 32)
545 int needed_width = start % 8 + length;
546 int fetch_length = (needed_width <= 8 ? 8
547 : needed_width <= 16 ? 16
548 : 32);
550 if (CGEN_INSN_LSB0_P)
552 if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG)
554 abort (); /* wip */
556 else
558 int offset = start & ~7;
560 bufp += offset / 8;
561 start -= offset;
562 total_length -= offset;
565 else
567 if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG)
569 int offset = start & ~7;
571 bufp += offset / 8;
572 start -= offset;
573 total_length -= offset;
575 else
577 abort (); /* wip */
582 insert_1 (od, value, start, length, total_length, bufp);
585 #endif /* ! CGEN_INT_INSN_P */
587 return NULL;
590 /* Default insn parser.
592 The syntax string is scanned and operands are parsed and stored in FIELDS.
593 Relocs are queued as we go via other callbacks.
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.
601 Returns NULL for success, an error message for failure.
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;
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
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;
629 if (* p || (* str && !isspace (* str)))
630 return _("unrecognized instruction");
632 CGEN_INIT_PARSE (od);
633 cgen_init_parse_operand (od);
634 #ifdef CGEN_MNEMONIC_OPERANDS
635 past_opcode_p = 0;
636 #endif
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);
642 /* Mnemonics come first for now, ensure valid string. */
643 if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
644 abort ();
646 ++syn;
648 while (* syn != 0)
650 /* Non operand chars must match exactly. */
651 if (CGEN_SYNTAX_CHAR_P (* syn))
653 if (*str == CGEN_SYNTAX_CHAR (* syn))
655 #ifdef CGEN_MNEMONIC_OPERANDS
656 if (* syn == ' ')
657 past_opcode_p = 1;
658 #endif
659 ++ syn;
660 ++ str;
662 else
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");
669 continue;
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;
678 /* Done with this operand, continue with next one. */
679 ++ syn;
682 /* If we're at the end of the syntax string, we're done. */
683 if (* syn == '\0')
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;
692 if (* str != '\0')
693 return _("junk at end of line"); /* FIXME: would like to include `str' */
695 return NULL;
698 /* We couldn't parse it. */
699 return _("unrecognized instruction");
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. */
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;
717 const CGEN_SYNTAX * syntax = CGEN_INSN_SYNTAX (insn);
718 unsigned long value;
719 const unsigned char * syn;
721 CGEN_INIT_INSERT (od);
722 value = CGEN_INSN_VALUE (insn);
724 /* If we're recording insns as numbers (rather than a string of bytes),
725 target byte order handling is deferred until later. */
727 #if CGEN_INT_INSN_P
729 *buffer = value;
731 #else
733 cgen_insn_put_value (od, buffer, min (CGEN_BASE_INSN_BITSIZE,
734 CGEN_FIELDS_BITSIZE (fields)),
735 value);
737 #endif /* ! CGEN_INT_INSN_P */
739 /* ??? Rather than scanning the syntax string again, we could store
740 in `fields' a null terminated list of the fields that are present. */
742 for (syn = CGEN_SYNTAX_STRING (syntax); * syn != '\0'; ++ syn)
744 const char *errmsg;
746 if (CGEN_SYNTAX_CHAR_P (* syn))
747 continue;
749 errmsg = fr30_cgen_insert_operand (od, CGEN_SYNTAX_FIELD (*syn),
750 fields, buffer, pc);
751 if (errmsg)
752 return errmsg;
755 return NULL;
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).
770 Note that when processing (non-alias) macro-insns,
771 this function recurses. */
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;
781 const char * start;
782 CGEN_INSN_LIST * ilist;
784 /* Skip leading white space. */
785 while (isspace (* str))
786 ++ str;
788 /* The instructions are stored in hashed lists.
789 Get the first in the list. */
790 ilist = CGEN_ASM_LOOKUP_INSN (od, str);
792 /* Keep looking until we find a match. */
794 start = str;
795 for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
797 const CGEN_INSN *insn = ilist->insn;
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
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;
811 str = start;
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);
818 if (! CGEN_PARSE_FN (insn) (od, insn, & str, fields))
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;
828 /* Try the next entry. */
831 /* FIXME: We can return a better error message than this.
832 Need to track why it failed and pick the right one. */
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);
842 *errmsg = errbuf;
843 return NULL;
847 #if 0 /* This calls back to GAS which we can't do without care. */
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. */
853 /* Record each member of OPVALS in the assembler's symbol table.
854 FIXME: Not currently used. */
856 void
857 fr30_cgen_asm_hash_keywords (od, opvals)
858 CGEN_OPCODE_DESC od;
859 CGEN_KEYWORD * opvals;
861 CGEN_KEYWORD_SEARCH search = cgen_keyword_search_init (opvals, NULL);
862 const CGEN_KEYWORD_ENTRY * ke;
864 while ((ke = cgen_keyword_search_next (& search)) != NULL)
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);
874 #endif /* 0 */