* m32r-opc.h,m32r-opc.c,m32r-asm.c,m32r-dis.c: 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, 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 */
This page took 0.061955 seconds and 5 git commands to generate.