backout m32rx stuff, not ready to be checked in
[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 { 0, /* default */
506 parse_insn_normal,
507 };
508
509 cgen_insert_fn * m32r_cgen_insert_handlers[] =
510 { 0, /* default */
511 insert_insn_normal,
512 };
513
514 void
515 m32r_cgen_init_asm (mach, endian)
516 int mach;
517 enum cgen_endian endian;
518 {
519 m32r_cgen_init_tables (mach);
520 cgen_set_cpu (& m32r_cgen_opcode_data, mach, endian);
521 cgen_asm_init ();
522 }
523
524 \f
525 /* Default insn parser.
526
527 The syntax string is scanned and operands are parsed and stored in FIELDS.
528 Relocs are queued as we go via other callbacks.
529
530 ??? Note that this is currently an all-or-nothing parser. If we fail to
531 parse the instruction, we return 0 and the caller will start over from
532 the beginning. Backtracking will be necessary in parsing subexpressions,
533 but that can be handled there. Not handling backtracking here may get
534 expensive in the case of the m68k. Deal with later.
535
536 Returns NULL for success, an error message for failure.
537 */
538
539 static const char *
540 parse_insn_normal (insn, strp, fields)
541 const CGEN_INSN * insn;
542 const char ** strp;
543 CGEN_FIELDS * fields;
544 {
545 const CGEN_SYNTAX * syntax = CGEN_INSN_SYNTAX (insn);
546 const char * str = *strp;
547 const char * errmsg;
548 const char * p;
549 const unsigned char * syn;
550 #ifdef CGEN_MNEMONIC_OPERANDS
551 int past_opcode_p;
552 #endif
553
554 /* For now we assume the mnemonic is first (there are no leading operands).
555 We can parse it without needing to set up operand parsing. */
556 p = CGEN_INSN_MNEMONIC (insn);
557 while (* p && * p == * str)
558 ++ p, ++ str;
559 if (* p || (* str && !isspace (* str)))
560 return "unrecognized instruction";
561
562 CGEN_INIT_PARSE ();
563 cgen_init_parse_operand ();
564 #ifdef CGEN_MNEMONIC_OPERANDS
565 past_opcode_p = 0;
566 #endif
567
568 /* We don't check for (*str != '\0') here because we want to parse
569 any trailing fake arguments in the syntax string. */
570 syn = CGEN_SYNTAX_STRING (CGEN_INSN_SYNTAX (insn));
571
572 /* Mnemonics come first for now, ensure valid string. */
573 if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
574 abort ();
575
576 ++syn;
577
578 while (* syn != 0)
579 {
580 /* Non operand chars must match exactly. */
581 /* FIXME: Need to better handle whitespace. */
582 if (CGEN_SYNTAX_CHAR_P (* syn))
583 {
584 if (*str == CGEN_SYNTAX_CHAR (* syn))
585 {
586 #ifdef CGEN_MNEMONIC_OPERANDS
587 if (* syn == ' ')
588 past_opcode_p = 1;
589 #endif
590 ++ syn;
591 ++ str;
592 }
593 else
594 {
595 /* Syntax char didn't match. Can't be this insn. */
596 /* FIXME: would like to return "expected char `c'" */
597 return "syntax error";
598 }
599 continue;
600 }
601
602 /* We have an operand of some sort. */
603 errmsg = m32r_cgen_parse_operand (CGEN_SYNTAX_FIELD (*syn),
604 &str, fields);
605 if (errmsg)
606 return errmsg;
607
608 /* Done with this operand, continue with next one. */
609 ++ syn;
610 }
611
612 /* If we're at the end of the syntax string, we're done. */
613 if (* syn == '\0')
614 {
615 /* FIXME: For the moment we assume a valid `str' can only contain
616 blanks now. IE: We needn't try again with a longer version of
617 the insn and it is assumed that longer versions of insns appear
618 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */
619 while (isspace (* str))
620 ++ str;
621
622 if (* str != '\0')
623 return "junk at end of line"; /* FIXME: would like to include `str' */
624
625 return NULL;
626 }
627
628 /* We couldn't parse it. */
629 return "unrecognized instruction";
630 }
631
632 /* Default insn builder (insert handler).
633 The instruction is recorded in target byte order. */
634
635 static void
636 insert_insn_normal (insn, fields, buffer)
637 const CGEN_INSN * insn;
638 CGEN_FIELDS * fields;
639 cgen_insn_t * buffer;
640 {
641 const CGEN_SYNTAX * syntax = CGEN_INSN_SYNTAX (insn);
642 bfd_vma value;
643 const unsigned char * syn;
644
645 CGEN_INIT_INSERT ();
646 value = CGEN_INSN_VALUE (insn);
647
648 /* If we're recording insns as numbers (rather than a string of bytes),
649 target byte order handling is deferred until later. */
650 #undef min
651 #define min(a,b) ((a) < (b) ? (a) : (b))
652 #if 0 /*def CGEN_INT_INSN*/
653 *buffer = value;
654 #else
655 switch (min (CGEN_BASE_INSN_BITSIZE, CGEN_FIELDS_BITSIZE (fields)))
656 {
657 case 8:
658 * buffer = value;
659 break;
660 case 16:
661 if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG)
662 bfd_putb16 (value, (char *) buffer);
663 else
664 bfd_putl16 (value, (char *) buffer);
665 break;
666 case 32:
667 if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG)
668 bfd_putb32 (value, (char *) buffer);
669 else
670 bfd_putl32 (value, (char *) buffer);
671 break;
672 default:
673 abort ();
674 }
675 #endif
676
677 /* ??? Rather than scanning the syntax string again, we could store
678 in `fields' a null terminated list of the fields that are present. */
679
680 for (syn = CGEN_SYNTAX_STRING (syntax); * syn != '\0'; ++ syn)
681 {
682 if (CGEN_SYNTAX_CHAR_P (* syn))
683 continue;
684
685 m32r_cgen_insert_operand (CGEN_SYNTAX_FIELD (*syn), fields, buffer);
686 }
687 }
688 \f
689 /* Main entry point.
690 This routine is called for each instruction to be assembled.
691 STR points to the insn to be assembled.
692 We assume all necessary tables have been initialized.
693 The result is a pointer to the insn's entry in the opcode table,
694 or NULL if an error occured (an error message will have already been
695 printed). */
696
697 const CGEN_INSN *
698 m32r_cgen_assemble_insn (str, fields, buf, errmsg)
699 const char * str;
700 CGEN_FIELDS * fields;
701 cgen_insn_t * buf;
702 char ** errmsg;
703 {
704 const char * start;
705 CGEN_INSN_LIST * ilist;
706
707 /* Skip leading white space. */
708 while (isspace (* str))
709 ++ str;
710
711 /* The instructions are stored in hashed lists.
712 Get the first in the list. */
713 ilist = CGEN_ASM_LOOKUP_INSN (str);
714
715 /* Keep looking until we find a match. */
716
717 start = str;
718 for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
719 {
720 const CGEN_INSN *insn = ilist->insn;
721
722 #if 0 /* not needed as unsupported opcodes shouldn't be in the hash lists */
723 /* Is this insn supported by the selected cpu? */
724 if (! m32r_cgen_insn_supported (insn))
725 continue;
726 #endif
727
728 #if 1 /* FIXME: wip */
729 /* If the RELAX attribute is set, this is an insn that shouldn't be
730 chosen immediately. Instead, it is used during assembler/linker
731 relaxation if possible. */
732 if (CGEN_INSN_ATTR (insn, CGEN_INSN_RELAX) != 0)
733 continue;
734 #endif
735
736 str = start;
737
738 /* Record a default length for the insn. This will get set to the
739 correct value while parsing. */
740 /* FIXME: wip */
741 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
742
743 /* ??? The extent to which moving the parse and insert handlers into
744 this function (thus removing the function call) will speed things up
745 is unclear. The simplicity and flexibility of the current scheme is
746 appropriate for now. One could have the best of both worlds with
747 inline functions but of course that would only work for gcc. Since
748 we're machine generating some code we could do that here too. Maybe
749 later. */
750 if (! CGEN_PARSE_FN (insn) (insn, & str, fields))
751 {
752 CGEN_INSERT_FN (insn) (insn, fields, buf);
753 /* It is up to the caller to actually output the insn and any
754 queued relocs. */
755 return insn;
756 }
757
758 /* Try the next entry. */
759 }
760
761 /* FIXME: We can return a better error message than this.
762 Need to track why it failed and pick the right one. */
763 {
764 static char errbuf[100];
765 sprintf (errbuf, "bad instruction `%.50s%s'",
766 start, strlen (start) > 50 ? "..." : "");
767 *errmsg = errbuf;
768 return NULL;
769 }
770 }
771 \f
772 #if 0 /* This calls back to GAS which we can't do without care. */
773
774 /* Record each member of OPVALS in the assembler's symbol table.
775 This lets GAS parse registers for us.
776 ??? Interesting idea but not currently used. */
777
778 /* Record each member of OPVALS in the assembler's symbol table.
779 FIXME: Not currently used. */
780
781 void
782 m32r_cgen_asm_hash_keywords (opvals)
783 CGEN_KEYWORD * opvals;
784 {
785 CGEN_KEYWORD_SEARCH search = cgen_keyword_search_init (opvals, NULL);
786 const CGEN_KEYWORD_ENTRY * ke;
787
788 while ((ke = cgen_keyword_search_next (& search)) != NULL)
789 {
790 #if 0 /* Unnecessary, should be done in the search routine. */
791 if (! m32r_cgen_opval_supported (ke))
792 continue;
793 #endif
794 cgen_asm_record_register (ke->name, ke->value);
795 }
796 }
797
798 #endif /* 0 */
This page took 0.069309 seconds and 5 git commands to generate.