75e20fb0d6a8a71713556679a957d34ff96b17af
[deliverable/binutils-gdb.git] / opcodes / fr30-asm.c
1 /* Assembler interface for targets using CGEN. -*- C -*-
2 CGEN: Cpu tools GENerator
3
4 THIS FILE IS USED TO GENERATE fr30-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 Foundation, Inc.,
22 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 "fr30-opc.h"
31 #include "opintl.h"
32
33 #undef min
34 #define min(a,b) ((a) < (b) ? (a) : (b))
35 #undef max
36 #define max(a,b) ((a) > (b) ? (a) : (b))
37
38 #undef INLINE
39 #ifdef __GNUC__
40 #define INLINE __inline__
41 #else
42 #define INLINE
43 #endif
44
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));
54 \f
55 /* -- assembler routines inserted here */
56
57 /* Main entry point for operand parsing.
58
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.
65
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.
69 */
70
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;
77 {
78 const char * errmsg;
79
80 switch (opindex)
81 {
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_R13 :
95 errmsg = cgen_parse_keyword (od, strp, & fr30_cgen_opval_h_r13, & fields->f_nil);
96 break;
97 case FR30_OPERAND_R14 :
98 errmsg = cgen_parse_keyword (od, strp, & fr30_cgen_opval_h_r14, & fields->f_nil);
99 break;
100 case FR30_OPERAND_R15 :
101 errmsg = cgen_parse_keyword (od, strp, & fr30_cgen_opval_h_r15, & fields->f_nil);
102 break;
103 case FR30_OPERAND_PS :
104 errmsg = cgen_parse_keyword (od, strp, & fr30_cgen_opval_h_ps, & fields->f_nil);
105 break;
106 case FR30_OPERAND_U4 :
107 errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_U4, &fields->f_u4);
108 break;
109 case FR30_OPERAND_M4 :
110 errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_M4, &fields->f_m4);
111 break;
112 case FR30_OPERAND_U8 :
113 errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_U8, &fields->f_u8);
114 break;
115 case FR30_OPERAND_I8 :
116 errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_I8, &fields->f_i8);
117 break;
118 case FR30_OPERAND_UDISP6 :
119 errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_UDISP6, &fields->f_udisp6);
120 break;
121 case FR30_OPERAND_DISP8 :
122 errmsg = cgen_parse_signed_integer (od, strp, FR30_OPERAND_DISP8, &fields->f_disp8);
123 break;
124 case FR30_OPERAND_DISP9 :
125 errmsg = cgen_parse_signed_integer (od, strp, FR30_OPERAND_DISP9, &fields->f_disp9);
126 break;
127 case FR30_OPERAND_DISP10 :
128 errmsg = cgen_parse_signed_integer (od, strp, FR30_OPERAND_DISP10, &fields->f_disp10);
129 break;
130 case FR30_OPERAND_S10 :
131 errmsg = cgen_parse_signed_integer (od, strp, FR30_OPERAND_S10, &fields->f_s10);
132 break;
133 case FR30_OPERAND_U10 :
134 errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_U10, &fields->f_u10);
135 break;
136 case FR30_OPERAND_DIR8 :
137 errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_DIR8, &fields->f_dir8);
138 break;
139 case FR30_OPERAND_DIR9 :
140 errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_DIR9, &fields->f_dir9);
141 break;
142 case FR30_OPERAND_DIR10 :
143 errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_DIR10, &fields->f_dir10);
144 break;
145 case FR30_OPERAND_LABEL9 :
146 errmsg = cgen_parse_signed_integer (od, strp, FR30_OPERAND_LABEL9, &fields->f_rel9);
147 break;
148 case FR30_OPERAND_LABEL12 :
149 errmsg = cgen_parse_signed_integer (od, strp, FR30_OPERAND_LABEL12, &fields->f_rel12);
150 break;
151 case FR30_OPERAND_CC :
152 errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_CC, &fields->f_cc);
153 break;
154
155 default :
156 /* xgettext:c-format */
157 fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
158 abort ();
159 }
160
161 return errmsg;
162 }
163
164 /* Main entry point for operand insertion.
165
166 This function is basically just a big switch statement. Earlier versions
167 used tables to look up the function to use, but
168 - if the table contains both assembler and disassembler functions then
169 the disassembler contains much of the assembler and vice-versa,
170 - there's a lot of inlining possibilities as things grow,
171 - using a switch statement avoids the function call overhead.
172
173 This function could be moved into `parse_insn_normal', but keeping it
174 separate makes clear the interface between `parse_insn_normal' and each of
175 the handlers. It's also needed by GAS to insert operands that couldn't be
176 resolved during parsing.
177 */
178
179 const char *
180 fr30_cgen_insert_operand (od, opindex, fields, buffer, pc)
181 CGEN_OPCODE_DESC od;
182 int opindex;
183 CGEN_FIELDS * fields;
184 CGEN_INSN_BYTES_PTR buffer;
185 bfd_vma pc;
186 {
187 const char * errmsg;
188
189 switch (opindex)
190 {
191 case FR30_OPERAND_RI :
192 errmsg = insert_normal (od, fields->f_Ri, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
193 break;
194 case FR30_OPERAND_RJ :
195 errmsg = insert_normal (od, fields->f_Rj, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
196 break;
197 case FR30_OPERAND_RS1 :
198 errmsg = insert_normal (od, fields->f_Rs1, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
199 break;
200 case FR30_OPERAND_RS2 :
201 errmsg = insert_normal (od, fields->f_Rs2, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
202 break;
203 case FR30_OPERAND_R13 :
204 errmsg = insert_normal (od, fields->f_nil, 0, 0, 0, CGEN_FIELDS_BITSIZE (fields), buffer);
205 break;
206 case FR30_OPERAND_R14 :
207 errmsg = insert_normal (od, fields->f_nil, 0, 0, 0, CGEN_FIELDS_BITSIZE (fields), buffer);
208 break;
209 case FR30_OPERAND_R15 :
210 errmsg = insert_normal (od, fields->f_nil, 0, 0, 0, CGEN_FIELDS_BITSIZE (fields), buffer);
211 break;
212 case FR30_OPERAND_PS :
213 errmsg = insert_normal (od, fields->f_nil, 0, 0, 0, CGEN_FIELDS_BITSIZE (fields), buffer);
214 break;
215 case FR30_OPERAND_U4 :
216 errmsg = insert_normal (od, fields->f_u4, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 8, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
217 break;
218 case FR30_OPERAND_M4 :
219 {
220 long value = fields->f_m4;
221 value = ((value) & (15));
222 errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 8, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
223 }
224 break;
225 case FR30_OPERAND_U8 :
226 errmsg = insert_normal (od, fields->f_u8, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
227 break;
228 case FR30_OPERAND_I8 :
229 errmsg = insert_normal (od, fields->f_i8, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 4, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
230 break;
231 case FR30_OPERAND_UDISP6 :
232 {
233 long value = fields->f_udisp6;
234 value = ((unsigned int) (value) >> (2));
235 errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 8, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
236 }
237 break;
238 case FR30_OPERAND_DISP8 :
239 errmsg = insert_normal (od, fields->f_disp8, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), 4, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
240 break;
241 case FR30_OPERAND_DISP9 :
242 {
243 long value = fields->f_disp9;
244 value = ((int) (value) >> (1));
245 errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), 4, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
246 }
247 break;
248 case FR30_OPERAND_DISP10 :
249 {
250 long value = fields->f_disp10;
251 value = ((int) (value) >> (2));
252 errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), 4, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
253 }
254 break;
255 case FR30_OPERAND_S10 :
256 {
257 long value = fields->f_s10;
258 value = ((int) (value) >> (2));
259 errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
260 }
261 break;
262 case FR30_OPERAND_U10 :
263 {
264 long value = fields->f_u10;
265 value = ((unsigned int) (value) >> (2));
266 errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
267 }
268 break;
269 case FR30_OPERAND_DIR8 :
270 errmsg = insert_normal (od, fields->f_dir8, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
271 break;
272 case FR30_OPERAND_DIR9 :
273 {
274 long value = fields->f_dir9;
275 value = ((unsigned int) (value) >> (1));
276 errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
277 }
278 break;
279 case FR30_OPERAND_DIR10 :
280 {
281 long value = fields->f_dir10;
282 value = ((unsigned int) (value) >> (2));
283 errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
284 }
285 break;
286 case FR30_OPERAND_LABEL9 :
287 {
288 long value = fields->f_rel9;
289 value = ((int) (((value) - (((pc) & (-2))))) >> (1));
290 errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_SIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
291 }
292 break;
293 case FR30_OPERAND_LABEL12 :
294 {
295 long value = fields->f_rel12;
296 value = ((int) (((value) - (((pc) & (-2))))) >> (1));
297 errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_SIGNED), 5, 11, CGEN_FIELDS_BITSIZE (fields), buffer);
298 }
299 break;
300 case FR30_OPERAND_CC :
301 errmsg = insert_normal (od, fields->f_cc, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
302 break;
303
304 default :
305 /* xgettext:c-format */
306 fprintf (stderr, _("Unrecognized field %d while building insn.\n"),
307 opindex);
308 abort ();
309 }
310
311 return errmsg;
312 }
313
314 cgen_parse_fn * const fr30_cgen_parse_handlers[] =
315 {
316 0, /* default */
317 parse_insn_normal,
318 };
319
320 cgen_insert_fn * const fr30_cgen_insert_handlers[] =
321 {
322 0, /* default */
323 insert_insn_normal,
324 };
325
326 void
327 fr30_cgen_init_asm (od)
328 CGEN_OPCODE_DESC od;
329 {
330 }
331
332 \f
333 #if ! CGEN_INT_INSN_P
334
335 /* Subroutine of insert_normal. */
336
337 static INLINE void
338 insert_1 (od, value, start, length, word_length, bufp)
339 CGEN_OPCODE_DESC od;
340 unsigned long value;
341 int start,length,word_length;
342 unsigned char *bufp;
343 {
344 unsigned long x,mask;
345 int shift;
346 int big_p = CGEN_OPCODE_INSN_ENDIAN (od) == CGEN_ENDIAN_BIG;
347
348 switch (word_length)
349 {
350 case 8:
351 x = *bufp;
352 break;
353 case 16:
354 if (big_p)
355 x = bfd_getb16 (bufp);
356 else
357 x = bfd_getl16 (bufp);
358 break;
359 case 24:
360 /* ??? This may need reworking as these cases don't necessarily
361 want the first byte and the last two bytes handled like this. */
362 if (big_p)
363 x = (bfd_getb8 (bufp) << 16) | bfd_getb16 (bufp + 1);
364 else
365 x = bfd_getl16 (bufp) | (bfd_getb8 (bufp + 2) << 16);
366 break;
367 case 32:
368 if (big_p)
369 x = bfd_getb32 (bufp);
370 else
371 x = bfd_getl32 (bufp);
372 break;
373 default :
374 abort ();
375 }
376
377 /* Written this way to avoid undefined behaviour. */
378 mask = (((1L << (length - 1)) - 1) << 1) | 1;
379 if (CGEN_INSN_LSB0_P)
380 shift = start;
381 else
382 shift = (word_length - (start + length));
383 x = (x & ~(mask << shift)) | ((value & mask) << shift);
384
385 switch (word_length)
386 {
387 case 8:
388 *bufp = x;
389 break;
390 case 16:
391 if (big_p)
392 bfd_putb16 (x, bufp);
393 else
394 bfd_putl16 (x, bufp);
395 break;
396 case 24:
397 /* ??? This may need reworking as these cases don't necessarily
398 want the first byte and the last two bytes handled like this. */
399 if (big_p)
400 {
401 bfd_putb8 (x >> 16, bufp);
402 bfd_putb16 (x, bufp + 1);
403 }
404 else
405 {
406 bfd_putl16 (x, bufp);
407 bfd_putb8 (x >> 16, bufp + 2);
408 }
409 break;
410 case 32:
411 if (big_p)
412 bfd_putb32 (x, bufp);
413 else
414 bfd_putl32 (x, bufp);
415 break;
416 default :
417 abort ();
418 }
419 }
420
421 #endif /* ! CGEN_INT_INSN_P */
422
423 /* Default insertion routine.
424
425 ATTRS is a mask of the boolean attributes.
426 START is the starting bit number, architecture origin.
427 LENGTH is the length of VALUE in bits.
428 TOTAL_LENGTH is the total length of the insn.
429
430 The result is an error message or NULL if success. */
431
432 /* ??? May need to know word length in order to properly place values as
433 an insn may be made of multiple words and the current bit number handling
434 may be insufficient. Word length is an architectural attribute and thus
435 methinks the way to go [if needed] is to fetch this value from OD or
436 define a macro in <arch>-opc.h rather than adding an extra argument -
437 after all that's how endianness is handled. */
438 /* ??? This duplicates functionality with bfd's howto table and
439 bfd_install_relocation. */
440 /* ??? For architectures where insns can be representable as ints,
441 store insn in `field' struct and add registers, etc. while parsing? */
442 /* ??? This doesn't handle bfd_vma's. Create another function when
443 necessary. */
444
445 static const char *
446 insert_normal (od, value, attrs, start, length, total_length, buffer)
447 CGEN_OPCODE_DESC od;
448 long value;
449 unsigned int attrs;
450 int start;
451 int length;
452 int total_length;
453 CGEN_INSN_BYTES_PTR buffer;
454 {
455 static char errbuf[100];
456 /* Written this way to avoid undefined behaviour. */
457 unsigned long mask = (((1L << (length - 1)) - 1) << 1) | 1;
458
459 /* If LENGTH is zero, this operand doesn't contribute to the value. */
460 if (length == 0)
461 return NULL;
462
463 /* Ensure VALUE will fit. */
464 if ((attrs & CGEN_ATTR_MASK (CGEN_OPERAND_UNSIGNED)) != 0)
465 {
466 unsigned long maxval = mask;
467 if ((unsigned long) value > maxval)
468 {
469 /* xgettext:c-format */
470 sprintf (errbuf,
471 _("operand out of range (%lu not between 0 and %lu)"),
472 value, maxval);
473 return errbuf;
474 }
475 }
476 else
477 {
478 long minval = - (1L << (length - 1));
479 long maxval = (1L << (length - 1)) - 1;
480 if (value < minval || value > maxval)
481 {
482 sprintf
483 /* xgettext:c-format */
484 (errbuf, _("operand out of range (%ld not between %ld and %ld)"),
485 value, minval, maxval);
486 return errbuf;
487 }
488 }
489
490 #if CGEN_INT_INSN_P
491
492 if (total_length > 32)
493 abort ();
494 {
495 int shift;
496
497 if (CGEN_INSN_LSB0_P)
498 shift = start;
499 else
500 shift = total_length - (start + length);
501 *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
502 }
503
504 #else
505
506 /* FIXME: unfinished and untested */
507
508 /* ??? To be defined in <arch>-opc.h as necessary. */
509 #ifndef CGEN_WORD_ENDIAN
510 #define CGEN_WORD_ENDIAN(od) CGEN_OPCODE_ENDIAN (od)
511 #endif
512 #ifndef CGEN_INSN_WORD_ENDIAN
513 #define CGEN_INSN_WORD_ENDIAN(od) CGEN_WORD_ENDIAN (od)
514 #endif
515
516 /* The hard case is probably too slow for the normal cases.
517 It's certainly more difficult to understand than the normal case.
518 Thus this is split into two. Keep it that way. The hard case is defined
519 to be when a field straddles a (loosely defined) word boundary
520 (??? which may require target specific help to determine). */
521
522 #if 0 /*wip*/
523
524 #define HARD_CASE_P 0 /* FIXME:wip */
525
526 if (HARD_CASE_P)
527 {
528 unsigned char *bufp = (unsigned char *) buffer;
529 int insn_length_left = total_length;
530
531 if (CGEN_INSN_LSB0_P)
532 {
533 int word_offset = (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG
534 ? ...
535 : start / CGEN_BASE_INSN_BITSIZE);
536 bufp += word_offset * (CGEN_BASE_INSN_BITSIZE / 8);
537 if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG)
538 else
539 start -= word_offset * CGEN_BASE_INSN_BITSIZE;
540 }
541 else
542 {
543 int word_offset = (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG
544 ? start / CGEN_BASE_INSN_BITSIZE
545 : ...);
546 bufp += word_offset * (CGEN_BASE_INSN_BITSIZE / 8);
547 if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG)
548 start -= word_offset * CGEN_BASE_INSN_BITSIZE;
549 else
550 }
551
552 /* Loop so we handle a field straddling an insn word boundary
553 (remember, "insn word boundary" is loosely defined here). */
554
555 while (length > 0)
556 {
557 int this_pass_length = length;
558 int this_pass_start = start;
559 int this_pass_word_length = min (insn_length_left,
560 (CGEN_BASE_INSN_BITSIZE == 8
561 ? 32
562 : CGEN_BASE_INSN_BITSIZE));
563
564 insert_1 (od, value, attrs,
565 this_pass_start, this_pass_length, this_pass_word_length,
566 bufp);
567
568 length -= this_pass_length;
569 insn_length_left -= this_pass_word_length;
570 if (???)
571 {
572 value >>= ???;
573 start += ???;
574 }
575 else
576 {
577 value >>= ???;
578 start += ???;
579 }
580 bufp += this_pass_word_length / 8;
581 }
582 }
583 else
584 #endif /* 0 */
585 {
586 unsigned char *bufp = (unsigned char *) buffer;
587
588 if (length > 32)
589 abort ();
590
591 /* Adjust start,total_length,bufp to point to the pseudo-word that holds
592 the value. For example in a 48 bit insn where the value to insert
593 (say an immediate value) is the last 16 bits then word_length here
594 would be 16. To handle a 24 bit insn with an 18 bit immediate,
595 insert_1 handles 24 bits (using a combination of bfd_get8,16). */
596
597 if (total_length > 32)
598 {
599 int needed_width = start % 8 + length;
600 int fetch_length = (needed_width <= 8 ? 8
601 : needed_width <= 16 ? 16
602 : 32);
603
604 if (CGEN_INSN_LSB0_P)
605 {
606 if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG)
607 {
608 abort (); /* wip */
609 }
610 else
611 {
612 int offset = start & ~7;
613
614 bufp += offset / 8;
615 start -= offset;
616 total_length -= offset;
617 }
618 }
619 else
620 {
621 if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG)
622 {
623 int offset = start & ~7;
624
625 bufp += offset / 8;
626 start -= offset;
627 total_length -= offset;
628 }
629 else
630 {
631 abort (); /* wip */
632 }
633 }
634 }
635
636 insert_1 (od, value, start, length, total_length, bufp);
637 }
638
639 #endif /* ! CGEN_INT_INSN_P */
640
641 return NULL;
642 }
643 \f
644 /* Default insn parser.
645
646 The syntax string is scanned and operands are parsed and stored in FIELDS.
647 Relocs are queued as we go via other callbacks.
648
649 ??? Note that this is currently an all-or-nothing parser. If we fail to
650 parse the instruction, we return 0 and the caller will start over from
651 the beginning. Backtracking will be necessary in parsing subexpressions,
652 but that can be handled there. Not handling backtracking here may get
653 expensive in the case of the m68k. Deal with later.
654
655 Returns NULL for success, an error message for failure.
656 */
657
658 static const char *
659 parse_insn_normal (od, insn, strp, fields)
660 CGEN_OPCODE_DESC od;
661 const CGEN_INSN * insn;
662 const char ** strp;
663 CGEN_FIELDS * fields;
664 {
665 const CGEN_SYNTAX * syntax = CGEN_INSN_SYNTAX (insn);
666 const char * str = *strp;
667 const char * errmsg;
668 const char * p;
669 const unsigned char * syn;
670 #ifdef CGEN_MNEMONIC_OPERANDS
671 /* FIXME: wip */
672 int past_opcode_p;
673 #endif
674
675 /* For now we assume the mnemonic is first (there are no leading operands).
676 We can parse it without needing to set up operand parsing.
677 GAS's input scrubber will ensure mnemonics are lowercase, but we may
678 not be called from GAS. */
679 p = CGEN_INSN_MNEMONIC (insn);
680 while (*p && tolower (*p) == tolower (*str))
681 ++p, ++str;
682
683 if (* p || (* str && !isspace (* str)))
684 return _("unrecognized instruction");
685
686 CGEN_INIT_PARSE (od);
687 cgen_init_parse_operand (od);
688 #ifdef CGEN_MNEMONIC_OPERANDS
689 past_opcode_p = 0;
690 #endif
691
692 /* We don't check for (*str != '\0') here because we want to parse
693 any trailing fake arguments in the syntax string. */
694 syn = CGEN_SYNTAX_STRING (syntax);
695
696 /* Mnemonics come first for now, ensure valid string. */
697 if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
698 abort ();
699
700 ++syn;
701
702 while (* syn != 0)
703 {
704 /* Non operand chars must match exactly. */
705 if (CGEN_SYNTAX_CHAR_P (* syn))
706 {
707 if (*str == CGEN_SYNTAX_CHAR (* syn))
708 {
709 #ifdef CGEN_MNEMONIC_OPERANDS
710 if (* syn == ' ')
711 past_opcode_p = 1;
712 #endif
713 ++ syn;
714 ++ str;
715 }
716 else
717 {
718 /* Syntax char didn't match. Can't be this insn. */
719 /* FIXME: would like to return something like
720 "expected char `c'" */
721 return _("syntax error");
722 }
723 continue;
724 }
725
726 /* We have an operand of some sort. */
727 errmsg = fr30_cgen_parse_operand (od, CGEN_SYNTAX_FIELD (*syn),
728 &str, fields);
729 if (errmsg)
730 return errmsg;
731
732 /* Done with this operand, continue with next one. */
733 ++ syn;
734 }
735
736 /* If we're at the end of the syntax string, we're done. */
737 if (* syn == '\0')
738 {
739 /* FIXME: For the moment we assume a valid `str' can only contain
740 blanks now. IE: We needn't try again with a longer version of
741 the insn and it is assumed that longer versions of insns appear
742 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */
743 while (isspace (* str))
744 ++ str;
745
746 if (* str != '\0')
747 return _("junk at end of line"); /* FIXME: would like to include `str' */
748
749 return NULL;
750 }
751
752 /* We couldn't parse it. */
753 return _("unrecognized instruction");
754 }
755
756 /* Default insn builder (insert handler).
757 The instruction is recorded in CGEN_INT_INSN_P byte order
758 (meaning that if CGEN_INT_INSN_P BUFFER is an int * and thus the value is
759 recorded in host byte order, otherwise BUFFER is an array of bytes and the
760 value is recorded in target byte order).
761 The result is an error message or NULL if success. */
762
763 static const char *
764 insert_insn_normal (od, insn, fields, buffer, pc)
765 CGEN_OPCODE_DESC od;
766 const CGEN_INSN * insn;
767 CGEN_FIELDS * fields;
768 CGEN_INSN_BYTES_PTR buffer;
769 bfd_vma pc;
770 {
771 const CGEN_SYNTAX * syntax = CGEN_INSN_SYNTAX (insn);
772 unsigned long value;
773 const unsigned char * syn;
774
775 CGEN_INIT_INSERT (od);
776 value = CGEN_INSN_VALUE (insn);
777
778 /* If we're recording insns as numbers (rather than a string of bytes),
779 target byte order handling is deferred until later. */
780
781 #if CGEN_INT_INSN_P
782
783 *buffer = value;
784
785 #else
786
787 cgen_insn_put_value (od, buffer, min (CGEN_BASE_INSN_BITSIZE,
788 CGEN_FIELDS_BITSIZE (fields)),
789 value);
790
791 #endif /* ! CGEN_INT_INSN_P */
792
793 /* ??? Rather than scanning the syntax string again, we could store
794 in `fields' a null terminated list of the fields that are present. */
795
796 for (syn = CGEN_SYNTAX_STRING (syntax); * syn != '\0'; ++ syn)
797 {
798 const char *errmsg;
799
800 if (CGEN_SYNTAX_CHAR_P (* syn))
801 continue;
802
803 errmsg = fr30_cgen_insert_operand (od, CGEN_SYNTAX_FIELD (*syn),
804 fields, buffer, pc);
805 if (errmsg)
806 return errmsg;
807 }
808
809 return NULL;
810 }
811 \f
812 /* Main entry point.
813 This routine is called for each instruction to be assembled.
814 STR points to the insn to be assembled.
815 We assume all necessary tables have been initialized.
816 The assembled instruction, less any fixups, is stored in BUF.
817 Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
818 still needs to be converted to target byte order, otherwise BUF is an array
819 of bytes in target byte order.
820 The result is a pointer to the insn's entry in the opcode table,
821 or NULL if an error occured (an error message will have already been
822 printed).
823
824 Note that when processing (non-alias) macro-insns,
825 this function recurses. */
826
827 const CGEN_INSN *
828 fr30_cgen_assemble_insn (od, str, fields, buf, errmsg)
829 CGEN_OPCODE_DESC od;
830 const char * str;
831 CGEN_FIELDS * fields;
832 CGEN_INSN_BYTES_PTR buf;
833 char ** errmsg;
834 {
835 const char * start;
836 CGEN_INSN_LIST * ilist;
837
838 /* Skip leading white space. */
839 while (isspace (* str))
840 ++ str;
841
842 /* The instructions are stored in hashed lists.
843 Get the first in the list. */
844 ilist = CGEN_ASM_LOOKUP_INSN (od, str);
845
846 /* Keep looking until we find a match. */
847
848 start = str;
849 for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
850 {
851 const CGEN_INSN *insn = ilist->insn;
852
853 #if 0 /* not needed as unsupported opcodes shouldn't be in the hash lists */
854 /* Is this insn supported by the selected cpu? */
855 if (! fr30_cgen_insn_supported (od, insn))
856 continue;
857 #endif
858
859 /* If the RELAX attribute is set, this is an insn that shouldn't be
860 chosen immediately. Instead, it is used during assembler/linker
861 relaxation if possible. */
862 if (CGEN_INSN_ATTR (insn, CGEN_INSN_RELAX) != 0)
863 continue;
864
865 str = start;
866
867 /* Record a default length for the insn. This will get set to the
868 correct value while parsing. */
869 /* FIXME: wip */
870 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
871
872 if (! CGEN_PARSE_FN (insn) (od, insn, & str, fields))
873 {
874 /* ??? 0 is passed for `pc' */
875 if (CGEN_INSERT_FN (insn) (od, insn, fields, buf, (bfd_vma) 0) != NULL)
876 continue;
877 /* It is up to the caller to actually output the insn and any
878 queued relocs. */
879 return insn;
880 }
881
882 /* Try the next entry. */
883 }
884
885 /* FIXME: We can return a better error message than this.
886 Need to track why it failed and pick the right one. */
887 {
888 static char errbuf[100];
889 if (strlen (start) > 50)
890 /* xgettext:c-format */
891 sprintf (errbuf, _("bad instruction `%.50s...'"), start);
892 else
893 /* xgettext:c-format */
894 sprintf (errbuf, _("bad instruction `%.50s'"), start);
895
896 *errmsg = errbuf;
897 return NULL;
898 }
899 }
900 \f
901 #if 0 /* This calls back to GAS which we can't do without care. */
902
903 /* Record each member of OPVALS in the assembler's symbol table.
904 This lets GAS parse registers for us.
905 ??? Interesting idea but not currently used. */
906
907 /* Record each member of OPVALS in the assembler's symbol table.
908 FIXME: Not currently used. */
909
910 void
911 fr30_cgen_asm_hash_keywords (od, opvals)
912 CGEN_OPCODE_DESC od;
913 CGEN_KEYWORD * opvals;
914 {
915 CGEN_KEYWORD_SEARCH search = cgen_keyword_search_init (opvals, NULL);
916 const CGEN_KEYWORD_ENTRY * ke;
917
918 while ((ke = cgen_keyword_search_next (& search)) != NULL)
919 {
920 #if 0 /* Unnecessary, should be done in the search routine. */
921 if (! fr30_cgen_opval_supported (ke))
922 continue;
923 #endif
924 cgen_asm_record_register (od, ke->name, ke->value);
925 }
926 }
927
928 #endif /* 0 */
This page took 0.048853 seconds and 3 git commands to generate.