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