source: trunk/src/binutils/opcodes/m32r-ibld.c@ 86

Last change on this file since 86 was 10, checked in by bird, 22 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 34.6 KB
Line 
1/* Instruction building/extraction support for m32r. -*- C -*-
2
3THIS FILE IS MACHINE GENERATED WITH CGEN: Cpu tools GENerator.
4- the resultant file is machine generated, cgen-ibld.in isn't
5
6Copyright 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
7
8This file is part of the GNU Binutils and GDB, the GNU debugger.
9
10This program is free software; you can redistribute it and/or modify
11it under the terms of the GNU General Public License as published by
12the Free Software Foundation; either version 2, or (at your option)
13any later version.
14
15This program is distributed in the hope that it will be useful,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License
21along with this program; if not, write to the Free Software Foundation, Inc.,
2259 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
23
24/* ??? Eventually more and more of this stuff can go to cpu-independent files.
25 Keep that in mind. */
26
27#include "sysdep.h"
28#include <ctype.h>
29#include <stdio.h>
30#include "ansidecl.h"
31#include "dis-asm.h"
32#include "bfd.h"
33#include "symcat.h"
34#include "m32r-desc.h"
35#include "m32r-opc.h"
36#include "opintl.h"
37
38#undef min
39#define min(a,b) ((a) < (b) ? (a) : (b))
40#undef max
41#define max(a,b) ((a) > (b) ? (a) : (b))
42
43/* Used by the ifield rtx function. */
44#define FLD(f) (fields->f)
45
46static const char * insert_normal
47 PARAMS ((CGEN_CPU_DESC, long, unsigned int, unsigned int, unsigned int,
48 unsigned int, unsigned int, unsigned int, CGEN_INSN_BYTES_PTR));
49static const char * insert_insn_normal
50 PARAMS ((CGEN_CPU_DESC, const CGEN_INSN *,
51 CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma));
52
53static int extract_normal
54 PARAMS ((CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, CGEN_INSN_INT,
55 unsigned int, unsigned int, unsigned int, unsigned int,
56 unsigned int, unsigned int, bfd_vma, long *));
57static int extract_insn_normal
58 PARAMS ((CGEN_CPU_DESC, const CGEN_INSN *, CGEN_EXTRACT_INFO *,
59 CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma));
60static void put_insn_int_value
61 PARAMS ((CGEN_CPU_DESC, CGEN_INSN_BYTES_PTR, int, int, CGEN_INSN_INT));
62
63
64
65/* Operand insertion. */
66
67#if ! CGEN_INT_INSN_P
68
69/* Subroutine of insert_normal. */
70
71static CGEN_INLINE void
72insert_1 (cd, value, start, length, word_length, bufp)
73 CGEN_CPU_DESC cd;
74 unsigned long value;
75 int start,length,word_length;
76 unsigned char *bufp;
77{
78 unsigned long x,mask;
79 int shift;
80 int big_p = CGEN_CPU_INSN_ENDIAN (cd) == CGEN_ENDIAN_BIG;
81
82 switch (word_length)
83 {
84 case 8:
85 x = *bufp;
86 break;
87 case 16:
88 if (big_p)
89 x = bfd_getb16 (bufp);
90 else
91 x = bfd_getl16 (bufp);
92 break;
93 case 24:
94 /* ??? This may need reworking as these cases don't necessarily
95 want the first byte and the last two bytes handled like this. */
96 if (big_p)
97 x = (bufp[0] << 16) | bfd_getb16 (bufp + 1);
98 else
99 x = bfd_getl16 (bufp) | (bufp[2] << 16);
100 break;
101 case 32:
102 if (big_p)
103 x = bfd_getb32 (bufp);
104 else
105 x = bfd_getl32 (bufp);
106 break;
107 default :
108 abort ();
109 }
110
111 /* Written this way to avoid undefined behaviour. */
112 mask = (((1L << (length - 1)) - 1) << 1) | 1;
113 if (CGEN_INSN_LSB0_P)
114 shift = (start + 1) - length;
115 else
116 shift = (word_length - (start + length));
117 x = (x & ~(mask << shift)) | ((value & mask) << shift);
118
119 switch (word_length)
120 {
121 case 8:
122 *bufp = x;
123 break;
124 case 16:
125 if (big_p)
126 bfd_putb16 (x, bufp);
127 else
128 bfd_putl16 (x, bufp);
129 break;
130 case 24:
131 /* ??? This may need reworking as these cases don't necessarily
132 want the first byte and the last two bytes handled like this. */
133 if (big_p)
134 {
135 bufp[0] = x >> 16;
136 bfd_putb16 (x, bufp + 1);
137 }
138 else
139 {
140 bfd_putl16 (x, bufp);
141 bufp[2] = x >> 16;
142 }
143 break;
144 case 32:
145 if (big_p)
146 bfd_putb32 (x, bufp);
147 else
148 bfd_putl32 (x, bufp);
149 break;
150 default :
151 abort ();
152 }
153}
154
155#endif /* ! CGEN_INT_INSN_P */
156
157/* Default insertion routine.
158
159 ATTRS is a mask of the boolean attributes.
160 WORD_OFFSET is the offset in bits from the start of the insn of the value.
161 WORD_LENGTH is the length of the word in bits in which the value resides.
162 START is the starting bit number in the word, architecture origin.
163 LENGTH is the length of VALUE in bits.
164 TOTAL_LENGTH is the total length of the insn in bits.
165
166 The result is an error message or NULL if success. */
167
168/* ??? This duplicates functionality with bfd's howto table and
169 bfd_install_relocation. */
170/* ??? This doesn't handle bfd_vma's. Create another function when
171 necessary. */
172
173static const char *
174insert_normal (cd, value, attrs, word_offset, start, length, word_length,
175 total_length, buffer)
176 CGEN_CPU_DESC cd;
177 long value;
178 unsigned int attrs;
179 unsigned int word_offset, start, length, word_length, total_length;
180 CGEN_INSN_BYTES_PTR buffer;
181{
182 static char errbuf[100];
183 /* Written this way to avoid undefined behaviour. */
184 unsigned long mask = (((1L << (length - 1)) - 1) << 1) | 1;
185
186 /* If LENGTH is zero, this operand doesn't contribute to the value. */
187 if (length == 0)
188 return NULL;
189
190#if 0
191 if (CGEN_INT_INSN_P
192 && word_offset != 0)
193 abort ();
194#endif
195
196 if (word_length > 32)
197 abort ();
198
199 /* For architectures with insns smaller than the base-insn-bitsize,
200 word_length may be too big. */
201 if (cd->min_insn_bitsize < cd->base_insn_bitsize)
202 {
203 if (word_offset == 0
204 && word_length > total_length)
205 word_length = total_length;
206 }
207
208 /* Ensure VALUE will fit. */
209 if (! CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED))
210 {
211 unsigned long maxval = mask;
212
213 if ((unsigned long) value > maxval)
214 {
215 /* xgettext:c-format */
216 sprintf (errbuf,
217 _("operand out of range (%lu not between 0 and %lu)"),
218 value, maxval);
219 return errbuf;
220 }
221 }
222 else
223 {
224 if (! cgen_signed_overflow_ok_p (cd))
225 {
226 long minval = - (1L << (length - 1));
227 long maxval = (1L << (length - 1)) - 1;
228
229 if (value < minval || value > maxval)
230 {
231 sprintf
232 /* xgettext:c-format */
233 (errbuf, _("operand out of range (%ld not between %ld and %ld)"),
234 value, minval, maxval);
235 return errbuf;
236 }
237 }
238 }
239
240#if CGEN_INT_INSN_P
241
242 {
243 int shift;
244
245 if (CGEN_INSN_LSB0_P)
246 shift = (word_offset + start + 1) - length;
247 else
248 shift = total_length - (word_offset + start + length);
249 *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
250 }
251
252#else /* ! CGEN_INT_INSN_P */
253
254 {
255 unsigned char *bufp = (unsigned char *) buffer + word_offset / 8;
256
257 insert_1 (cd, value, start, length, word_length, bufp);
258 }
259
260#endif /* ! CGEN_INT_INSN_P */
261
262 return NULL;
263}
264
265/* Default insn builder (insert handler).
266 The instruction is recorded in CGEN_INT_INSN_P byte order
267 (meaning that if CGEN_INT_INSN_P BUFFER is an int * and thus the value is
268 recorded in host byte order, otherwise BUFFER is an array of bytes and the
269 value is recorded in target byte order).
270 The result is an error message or NULL if success. */
271
272static const char *
273insert_insn_normal (cd, insn, fields, buffer, pc)
274 CGEN_CPU_DESC cd;
275 const CGEN_INSN * insn;
276 CGEN_FIELDS * fields;
277 CGEN_INSN_BYTES_PTR buffer;
278 bfd_vma pc;
279{
280 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
281 unsigned long value;
282 const unsigned char * syn;
283
284 CGEN_INIT_INSERT (cd);
285 value = CGEN_INSN_BASE_VALUE (insn);
286
287 /* If we're recording insns as numbers (rather than a string of bytes),
288 target byte order handling is deferred until later. */
289
290#if CGEN_INT_INSN_P
291
292 put_insn_int_value (cd, buffer, cd->base_insn_bitsize,
293 CGEN_FIELDS_BITSIZE (fields), value);
294
295#else
296
297 cgen_put_insn_value (cd, buffer, min (cd->base_insn_bitsize,
298 CGEN_FIELDS_BITSIZE (fields)),
299 value);
300
301#endif /* ! CGEN_INT_INSN_P */
302
303 /* ??? It would be better to scan the format's fields.
304 Still need to be able to insert a value based on the operand though;
305 e.g. storing a branch displacement that got resolved later.
306 Needs more thought first. */
307
308 for (syn = CGEN_SYNTAX_STRING (syntax); * syn != '\0'; ++ syn)
309 {
310 const char *errmsg;
311
312 if (CGEN_SYNTAX_CHAR_P (* syn))
313 continue;
314
315 errmsg = (* cd->insert_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
316 fields, buffer, pc);
317 if (errmsg)
318 return errmsg;
319 }
320
321 return NULL;
322}
323
324/* Cover function to store an insn value into an integral insn. Must go here
325 because it needs <prefix>-desc.h for CGEN_INT_INSN_P. */
326
327static void
328put_insn_int_value (cd, buf, length, insn_length, value)
329 CGEN_CPU_DESC cd;
330 CGEN_INSN_BYTES_PTR buf;
331 int length;
332 int insn_length;
333 CGEN_INSN_INT value;
334{
335 /* For architectures with insns smaller than the base-insn-bitsize,
336 length may be too big. */
337 if (length > insn_length)
338 *buf = value;
339 else
340 {
341 int shift = insn_length - length;
342 /* Written this way to avoid undefined behaviour. */
343 CGEN_INSN_INT mask = (((1L << (length - 1)) - 1) << 1) | 1;
344 *buf = (*buf & ~(mask << shift)) | ((value & mask) << shift);
345 }
346}
347
348
349/* Operand extraction. */
350
351#if ! CGEN_INT_INSN_P
352
353/* Subroutine of extract_normal.
354 Ensure sufficient bytes are cached in EX_INFO.
355 OFFSET is the offset in bytes from the start of the insn of the value.
356 BYTES is the length of the needed value.
357 Returns 1 for success, 0 for failure. */
358
359static CGEN_INLINE int
360fill_cache (cd, ex_info, offset, bytes, pc)
361 CGEN_CPU_DESC cd;
362 CGEN_EXTRACT_INFO *ex_info;
363 int offset, bytes;
364 bfd_vma pc;
365{
366 /* It's doubtful that the middle part has already been fetched so
367 we don't optimize that case. kiss. */
368 int mask;
369 disassemble_info *info = (disassemble_info *) ex_info->dis_info;
370
371 /* First do a quick check. */
372 mask = (1 << bytes) - 1;
373 if (((ex_info->valid >> offset) & mask) == mask)
374 return 1;
375
376 /* Search for the first byte we need to read. */
377 for (mask = 1 << offset; bytes > 0; --bytes, ++offset, mask <<= 1)
378 if (! (mask & ex_info->valid))
379 break;
380
381 if (bytes)
382 {
383 int status;
384
385 pc += offset;
386 status = (*info->read_memory_func)
387 (pc, ex_info->insn_bytes + offset, bytes, info);
388
389 if (status != 0)
390 {
391 (*info->memory_error_func) (status, pc, info);
392 return 0;
393 }
394
395 ex_info->valid |= ((1 << bytes) - 1) << offset;
396 }
397
398 return 1;
399}
400
401/* Subroutine of extract_normal. */
402
403static CGEN_INLINE long
404extract_1 (cd, ex_info, start, length, word_length, bufp, pc)
405 CGEN_CPU_DESC cd;
406 CGEN_EXTRACT_INFO *ex_info;
407 int start,length,word_length;
408 unsigned char *bufp;
409 bfd_vma pc;
410{
411 unsigned long x,mask;
412 int shift;
413 int big_p = CGEN_CPU_INSN_ENDIAN (cd) == CGEN_ENDIAN_BIG;
414
415 switch (word_length)
416 {
417 case 8:
418 x = *bufp;
419 break;
420 case 16:
421 if (big_p)
422 x = bfd_getb16 (bufp);
423 else
424 x = bfd_getl16 (bufp);
425 break;
426 case 24:
427 /* ??? This may need reworking as these cases don't necessarily
428 want the first byte and the last two bytes handled like this. */
429 if (big_p)
430 x = (bufp[0] << 16) | bfd_getb16 (bufp + 1);
431 else
432 x = bfd_getl16 (bufp) | (bufp[2] << 16);
433 break;
434 case 32:
435 if (big_p)
436 x = bfd_getb32 (bufp);
437 else
438 x = bfd_getl32 (bufp);
439 break;
440 default :
441 abort ();
442 }
443
444 /* Written this way to avoid undefined behaviour. */
445 mask = (((1L << (length - 1)) - 1) << 1) | 1;
446 if (CGEN_INSN_LSB0_P)
447 shift = (start + 1) - length;
448 else
449 shift = (word_length - (start + length));
450 return (x >> shift) & mask;
451}
452
453#endif /* ! CGEN_INT_INSN_P */
454
455/* Default extraction routine.
456
457 INSN_VALUE is the first base_insn_bitsize bits of the insn in host order,
458 or sometimes less for cases like the m32r where the base insn size is 32
459 but some insns are 16 bits.
460 ATTRS is a mask of the boolean attributes. We only need `SIGNED',
461 but for generality we take a bitmask of all of them.
462 WORD_OFFSET is the offset in bits from the start of the insn of the value.
463 WORD_LENGTH is the length of the word in bits in which the value resides.
464 START is the starting bit number in the word, architecture origin.
465 LENGTH is the length of VALUE in bits.
466 TOTAL_LENGTH is the total length of the insn in bits.
467
468 Returns 1 for success, 0 for failure. */
469
470/* ??? The return code isn't properly used. wip. */
471
472/* ??? This doesn't handle bfd_vma's. Create another function when
473 necessary. */
474
475static int
476extract_normal (cd, ex_info, insn_value, attrs, word_offset, start, length,
477 word_length, total_length, pc, valuep)
478 CGEN_CPU_DESC cd;
479#if ! CGEN_INT_INSN_P
480 CGEN_EXTRACT_INFO *ex_info;
481#else
482 CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED;
483#endif
484 CGEN_INSN_INT insn_value;
485 unsigned int attrs;
486 unsigned int word_offset, start, length, word_length, total_length;
487#if ! CGEN_INT_INSN_P
488 bfd_vma pc;
489#else
490 bfd_vma pc ATTRIBUTE_UNUSED;
491#endif
492 long *valuep;
493{
494 CGEN_INSN_INT value;
495
496 /* If LENGTH is zero, this operand doesn't contribute to the value
497 so give it a standard value of zero. */
498 if (length == 0)
499 {
500 *valuep = 0;
501 return 1;
502 }
503
504#if 0
505 if (CGEN_INT_INSN_P
506 && word_offset != 0)
507 abort ();
508#endif
509
510 if (word_length > 32)
511 abort ();
512
513 /* For architectures with insns smaller than the insn-base-bitsize,
514 word_length may be too big. */
515 if (cd->min_insn_bitsize < cd->base_insn_bitsize)
516 {
517 if (word_offset == 0
518 && word_length > total_length)
519 word_length = total_length;
520 }
521
522 /* Does the value reside in INSN_VALUE? */
523
524 if (CGEN_INT_INSN_P || word_offset == 0)
525 {
526 /* Written this way to avoid undefined behaviour. */
527 CGEN_INSN_INT mask = (((1L << (length - 1)) - 1) << 1) | 1;
528
529 if (CGEN_INSN_LSB0_P)
530 value = insn_value >> ((word_offset + start + 1) - length);
531 else
532 value = insn_value >> (total_length - ( word_offset + start + length));
533 value &= mask;
534 /* sign extend? */
535 if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED)
536 && (value & (1L << (length - 1))))
537 value |= ~mask;
538 }
539
540#if ! CGEN_INT_INSN_P
541
542 else
543 {
544 unsigned char *bufp = ex_info->insn_bytes + word_offset / 8;
545
546 if (word_length > 32)
547 abort ();
548
549 if (fill_cache (cd, ex_info, word_offset / 8, word_length / 8, pc) == 0)
550 return 0;
551
552 value = extract_1 (cd, ex_info, start, length, word_length, bufp, pc);
553 }
554
555#endif /* ! CGEN_INT_INSN_P */
556
557 *valuep = value;
558
559 return 1;
560}
561
562/* Default insn extractor.
563
564 INSN_VALUE is the first base_insn_bitsize bits, translated to host order.
565 The extracted fields are stored in FIELDS.
566 EX_INFO is used to handle reading variable length insns.
567 Return the length of the insn in bits, or 0 if no match,
568 or -1 if an error occurs fetching data (memory_error_func will have
569 been called). */
570
571static int
572extract_insn_normal (cd, insn, ex_info, insn_value, fields, pc)
573 CGEN_CPU_DESC cd;
574 const CGEN_INSN *insn;
575 CGEN_EXTRACT_INFO *ex_info;
576 CGEN_INSN_INT insn_value;
577 CGEN_FIELDS *fields;
578 bfd_vma pc;
579{
580 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
581 const unsigned char *syn;
582
583 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
584
585 CGEN_INIT_EXTRACT (cd);
586
587 for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
588 {
589 int length;
590
591 if (CGEN_SYNTAX_CHAR_P (*syn))
592 continue;
593
594 length = (* cd->extract_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
595 ex_info, insn_value, fields, pc);
596 if (length <= 0)
597 return length;
598 }
599
600 /* We recognized and successfully extracted this insn. */
601 return CGEN_INSN_BITSIZE (insn);
602}
603
604
605/* machine generated code added here */
606
607/* Main entry point for operand insertion.
608
609 This function is basically just a big switch statement. Earlier versions
610 used tables to look up the function to use, but
611 - if the table contains both assembler and disassembler functions then
612 the disassembler contains much of the assembler and vice-versa,
613 - there's a lot of inlining possibilities as things grow,
614 - using a switch statement avoids the function call overhead.
615
616 This function could be moved into `parse_insn_normal', but keeping it
617 separate makes clear the interface between `parse_insn_normal' and each of
618 the handlers. It's also needed by GAS to insert operands that couldn't be
619 resolved during parsing.
620*/
621
622const char *
623m32r_cgen_insert_operand (cd, opindex, fields, buffer, pc)
624 CGEN_CPU_DESC cd;
625 int opindex;
626 CGEN_FIELDS * fields;
627 CGEN_INSN_BYTES_PTR buffer;
628 bfd_vma pc;
629{
630 const char * errmsg = NULL;
631 unsigned int total_length = CGEN_FIELDS_BITSIZE (fields);
632
633 switch (opindex)
634 {
635 case M32R_OPERAND_ACC :
636 errmsg = insert_normal (cd, fields->f_acc, 0, 0, 8, 1, 32, total_length, buffer);
637 break;
638 case M32R_OPERAND_ACCD :
639 errmsg = insert_normal (cd, fields->f_accd, 0, 0, 4, 2, 32, total_length, buffer);
640 break;
641 case M32R_OPERAND_ACCS :
642 errmsg = insert_normal (cd, fields->f_accs, 0, 0, 12, 2, 32, total_length, buffer);
643 break;
644 case M32R_OPERAND_DCR :
645 errmsg = insert_normal (cd, fields->f_r1, 0, 0, 4, 4, 32, total_length, buffer);
646 break;
647 case M32R_OPERAND_DISP16 :
648 {
649 long value = fields->f_disp16;
650 value = ((int) (((value) - (pc))) >> (2));
651 errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_RELOC)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 16, 16, 32, total_length, buffer);
652 }
653 break;
654 case M32R_OPERAND_DISP24 :
655 {
656 long value = fields->f_disp24;
657 value = ((int) (((value) - (pc))) >> (2));
658 errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_RELOC)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 8, 24, 32, total_length, buffer);
659 }
660 break;
661 case M32R_OPERAND_DISP8 :
662 {
663 long value = fields->f_disp8;
664 value = ((int) (((value) - (((pc) & (-4))))) >> (2));
665 errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_RELOC)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 8, 8, 32, total_length, buffer);
666 }
667 break;
668 case M32R_OPERAND_DR :
669 errmsg = insert_normal (cd, fields->f_r1, 0, 0, 4, 4, 32, total_length, buffer);
670 break;
671 case M32R_OPERAND_HASH :
672 break;
673 case M32R_OPERAND_HI16 :
674 errmsg = insert_normal (cd, fields->f_hi16, 0|(1<<CGEN_IFLD_SIGN_OPT), 0, 16, 16, 32, total_length, buffer);
675 break;
676 case M32R_OPERAND_IMM1 :
677 {
678 long value = fields->f_imm1;
679 value = ((value) - (1));
680 errmsg = insert_normal (cd, value, 0, 0, 15, 1, 32, total_length, buffer);
681 }
682 break;
683 case M32R_OPERAND_SCR :
684 errmsg = insert_normal (cd, fields->f_r2, 0, 0, 12, 4, 32, total_length, buffer);
685 break;
686 case M32R_OPERAND_SIMM16 :
687 errmsg = insert_normal (cd, fields->f_simm16, 0|(1<<CGEN_IFLD_SIGNED), 0, 16, 16, 32, total_length, buffer);
688 break;
689 case M32R_OPERAND_SIMM8 :
690 errmsg = insert_normal (cd, fields->f_simm8, 0|(1<<CGEN_IFLD_SIGNED), 0, 8, 8, 32, total_length, buffer);
691 break;
692 case M32R_OPERAND_SLO16 :
693 errmsg = insert_normal (cd, fields->f_simm16, 0|(1<<CGEN_IFLD_SIGNED), 0, 16, 16, 32, total_length, buffer);
694 break;
695 case M32R_OPERAND_SR :
696 errmsg = insert_normal (cd, fields->f_r2, 0, 0, 12, 4, 32, total_length, buffer);
697 break;
698 case M32R_OPERAND_SRC1 :
699 errmsg = insert_normal (cd, fields->f_r1, 0, 0, 4, 4, 32, total_length, buffer);
700 break;
701 case M32R_OPERAND_SRC2 :
702 errmsg = insert_normal (cd, fields->f_r2, 0, 0, 12, 4, 32, total_length, buffer);
703 break;
704 case M32R_OPERAND_UIMM16 :
705 errmsg = insert_normal (cd, fields->f_uimm16, 0, 0, 16, 16, 32, total_length, buffer);
706 break;
707 case M32R_OPERAND_UIMM24 :
708 errmsg = insert_normal (cd, fields->f_uimm24, 0|(1<<CGEN_IFLD_RELOC)|(1<<CGEN_IFLD_ABS_ADDR), 0, 8, 24, 32, total_length, buffer);
709 break;
710 case M32R_OPERAND_UIMM4 :
711 errmsg = insert_normal (cd, fields->f_uimm4, 0, 0, 12, 4, 32, total_length, buffer);
712 break;
713 case M32R_OPERAND_UIMM5 :
714 errmsg = insert_normal (cd, fields->f_uimm5, 0, 0, 11, 5, 32, total_length, buffer);
715 break;
716 case M32R_OPERAND_ULO16 :
717 errmsg = insert_normal (cd, fields->f_uimm16, 0, 0, 16, 16, 32, total_length, buffer);
718 break;
719
720 default :
721 /* xgettext:c-format */
722 fprintf (stderr, _("Unrecognized field %d while building insn.\n"),
723 opindex);
724 abort ();
725 }
726
727 return errmsg;
728}
729
730/* Main entry point for operand extraction.
731 The result is <= 0 for error, >0 for success.
732 ??? Actual values aren't well defined right now.
733
734 This function is basically just a big switch statement. Earlier versions
735 used tables to look up the function to use, but
736 - if the table contains both assembler and disassembler functions then
737 the disassembler contains much of the assembler and vice-versa,
738 - there's a lot of inlining possibilities as things grow,
739 - using a switch statement avoids the function call overhead.
740
741 This function could be moved into `print_insn_normal', but keeping it
742 separate makes clear the interface between `print_insn_normal' and each of
743 the handlers.
744*/
745
746int
747m32r_cgen_extract_operand (cd, opindex, ex_info, insn_value, fields, pc)
748 CGEN_CPU_DESC cd;
749 int opindex;
750 CGEN_EXTRACT_INFO *ex_info;
751 CGEN_INSN_INT insn_value;
752 CGEN_FIELDS * fields;
753 bfd_vma pc;
754{
755 /* Assume success (for those operands that are nops). */
756 int length = 1;
757 unsigned int total_length = CGEN_FIELDS_BITSIZE (fields);
758
759 switch (opindex)
760 {
761 case M32R_OPERAND_ACC :
762 length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 1, 32, total_length, pc, & fields->f_acc);
763 break;
764 case M32R_OPERAND_ACCD :
765 length = extract_normal (cd, ex_info, insn_value, 0, 0, 4, 2, 32, total_length, pc, & fields->f_accd);
766 break;
767 case M32R_OPERAND_ACCS :
768 length = extract_normal (cd, ex_info, insn_value, 0, 0, 12, 2, 32, total_length, pc, & fields->f_accs);
769 break;
770 case M32R_OPERAND_DCR :
771 length = extract_normal (cd, ex_info, insn_value, 0, 0, 4, 4, 32, total_length, pc, & fields->f_r1);
772 break;
773 case M32R_OPERAND_DISP16 :
774 {
775 long value;
776 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_RELOC)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 16, 16, 32, total_length, pc, & value);
777 value = ((((value) << (2))) + (pc));
778 fields->f_disp16 = value;
779 }
780 break;
781 case M32R_OPERAND_DISP24 :
782 {
783 long value;
784 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_RELOC)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 8, 24, 32, total_length, pc, & value);
785 value = ((((value) << (2))) + (pc));
786 fields->f_disp24 = value;
787 }
788 break;
789 case M32R_OPERAND_DISP8 :
790 {
791 long value;
792 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_RELOC)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 8, 8, 32, total_length, pc, & value);
793 value = ((((value) << (2))) + (((pc) & (-4))));
794 fields->f_disp8 = value;
795 }
796 break;
797 case M32R_OPERAND_DR :
798 length = extract_normal (cd, ex_info, insn_value, 0, 0, 4, 4, 32, total_length, pc, & fields->f_r1);
799 break;
800 case M32R_OPERAND_HASH :
801 break;
802 case M32R_OPERAND_HI16 :
803 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGN_OPT), 0, 16, 16, 32, total_length, pc, & fields->f_hi16);
804 break;
805 case M32R_OPERAND_IMM1 :
806 {
807 long value;
808 length = extract_normal (cd, ex_info, insn_value, 0, 0, 15, 1, 32, total_length, pc, & value);
809 value = ((value) + (1));
810 fields->f_imm1 = value;
811 }
812 break;
813 case M32R_OPERAND_SCR :
814 length = extract_normal (cd, ex_info, insn_value, 0, 0, 12, 4, 32, total_length, pc, & fields->f_r2);
815 break;
816 case M32R_OPERAND_SIMM16 :
817 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED), 0, 16, 16, 32, total_length, pc, & fields->f_simm16);
818 break;
819 case M32R_OPERAND_SIMM8 :
820 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED), 0, 8, 8, 32, total_length, pc, & fields->f_simm8);
821 break;
822 case M32R_OPERAND_SLO16 :
823 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED), 0, 16, 16, 32, total_length, pc, & fields->f_simm16);
824 break;
825 case M32R_OPERAND_SR :
826 length = extract_normal (cd, ex_info, insn_value, 0, 0, 12, 4, 32, total_length, pc, & fields->f_r2);
827 break;
828 case M32R_OPERAND_SRC1 :
829 length = extract_normal (cd, ex_info, insn_value, 0, 0, 4, 4, 32, total_length, pc, & fields->f_r1);
830 break;
831 case M32R_OPERAND_SRC2 :
832 length = extract_normal (cd, ex_info, insn_value, 0, 0, 12, 4, 32, total_length, pc, & fields->f_r2);
833 break;
834 case M32R_OPERAND_UIMM16 :
835 length = extract_normal (cd, ex_info, insn_value, 0, 0, 16, 16, 32, total_length, pc, & fields->f_uimm16);
836 break;
837 case M32R_OPERAND_UIMM24 :
838 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_RELOC)|(1<<CGEN_IFLD_ABS_ADDR), 0, 8, 24, 32, total_length, pc, & fields->f_uimm24);
839 break;
840 case M32R_OPERAND_UIMM4 :
841 length = extract_normal (cd, ex_info, insn_value, 0, 0, 12, 4, 32, total_length, pc, & fields->f_uimm4);
842 break;
843 case M32R_OPERAND_UIMM5 :
844 length = extract_normal (cd, ex_info, insn_value, 0, 0, 11, 5, 32, total_length, pc, & fields->f_uimm5);
845 break;
846 case M32R_OPERAND_ULO16 :
847 length = extract_normal (cd, ex_info, insn_value, 0, 0, 16, 16, 32, total_length, pc, & fields->f_uimm16);
848 break;
849
850 default :
851 /* xgettext:c-format */
852 fprintf (stderr, _("Unrecognized field %d while decoding insn.\n"),
853 opindex);
854 abort ();
855 }
856
857 return length;
858}
859
860cgen_insert_fn * const m32r_cgen_insert_handlers[] =
861{
862 insert_insn_normal,
863};
864
865cgen_extract_fn * const m32r_cgen_extract_handlers[] =
866{
867 extract_insn_normal,
868};
869
870/* Getting values from cgen_fields is handled by a collection of functions.
871 They are distinguished by the type of the VALUE argument they return.
872 TODO: floating point, inlining support, remove cases where result type
873 not appropriate. */
874
875int
876m32r_cgen_get_int_operand (cd, opindex, fields)
877 CGEN_CPU_DESC cd;
878 int opindex;
879 const CGEN_FIELDS * fields;
880{
881 int value;
882
883 switch (opindex)
884 {
885 case M32R_OPERAND_ACC :
886 value = fields->f_acc;
887 break;
888 case M32R_OPERAND_ACCD :
889 value = fields->f_accd;
890 break;
891 case M32R_OPERAND_ACCS :
892 value = fields->f_accs;
893 break;
894 case M32R_OPERAND_DCR :
895 value = fields->f_r1;
896 break;
897 case M32R_OPERAND_DISP16 :
898 value = fields->f_disp16;
899 break;
900 case M32R_OPERAND_DISP24 :
901 value = fields->f_disp24;
902 break;
903 case M32R_OPERAND_DISP8 :
904 value = fields->f_disp8;
905 break;
906 case M32R_OPERAND_DR :
907 value = fields->f_r1;
908 break;
909 case M32R_OPERAND_HASH :
910 value = 0;
911 break;
912 case M32R_OPERAND_HI16 :
913 value = fields->f_hi16;
914 break;
915 case M32R_OPERAND_IMM1 :
916 value = fields->f_imm1;
917 break;
918 case M32R_OPERAND_SCR :
919 value = fields->f_r2;
920 break;
921 case M32R_OPERAND_SIMM16 :
922 value = fields->f_simm16;
923 break;
924 case M32R_OPERAND_SIMM8 :
925 value = fields->f_simm8;
926 break;
927 case M32R_OPERAND_SLO16 :
928 value = fields->f_simm16;
929 break;
930 case M32R_OPERAND_SR :
931 value = fields->f_r2;
932 break;
933 case M32R_OPERAND_SRC1 :
934 value = fields->f_r1;
935 break;
936 case M32R_OPERAND_SRC2 :
937 value = fields->f_r2;
938 break;
939 case M32R_OPERAND_UIMM16 :
940 value = fields->f_uimm16;
941 break;
942 case M32R_OPERAND_UIMM24 :
943 value = fields->f_uimm24;
944 break;
945 case M32R_OPERAND_UIMM4 :
946 value = fields->f_uimm4;
947 break;
948 case M32R_OPERAND_UIMM5 :
949 value = fields->f_uimm5;
950 break;
951 case M32R_OPERAND_ULO16 :
952 value = fields->f_uimm16;
953 break;
954
955 default :
956 /* xgettext:c-format */
957 fprintf (stderr, _("Unrecognized field %d while getting int operand.\n"),
958 opindex);
959 abort ();
960 }
961
962 return value;
963}
964
965bfd_vma
966m32r_cgen_get_vma_operand (cd, opindex, fields)
967 CGEN_CPU_DESC cd;
968 int opindex;
969 const CGEN_FIELDS * fields;
970{
971 bfd_vma value;
972
973 switch (opindex)
974 {
975 case M32R_OPERAND_ACC :
976 value = fields->f_acc;
977 break;
978 case M32R_OPERAND_ACCD :
979 value = fields->f_accd;
980 break;
981 case M32R_OPERAND_ACCS :
982 value = fields->f_accs;
983 break;
984 case M32R_OPERAND_DCR :
985 value = fields->f_r1;
986 break;
987 case M32R_OPERAND_DISP16 :
988 value = fields->f_disp16;
989 break;
990 case M32R_OPERAND_DISP24 :
991 value = fields->f_disp24;
992 break;
993 case M32R_OPERAND_DISP8 :
994 value = fields->f_disp8;
995 break;
996 case M32R_OPERAND_DR :
997 value = fields->f_r1;
998 break;
999 case M32R_OPERAND_HASH :
1000 value = 0;
1001 break;
1002 case M32R_OPERAND_HI16 :
1003 value = fields->f_hi16;
1004 break;
1005 case M32R_OPERAND_IMM1 :
1006 value = fields->f_imm1;
1007 break;
1008 case M32R_OPERAND_SCR :
1009 value = fields->f_r2;
1010 break;
1011 case M32R_OPERAND_SIMM16 :
1012 value = fields->f_simm16;
1013 break;
1014 case M32R_OPERAND_SIMM8 :
1015 value = fields->f_simm8;
1016 break;
1017 case M32R_OPERAND_SLO16 :
1018 value = fields->f_simm16;
1019 break;
1020 case M32R_OPERAND_SR :
1021 value = fields->f_r2;
1022 break;
1023 case M32R_OPERAND_SRC1 :
1024 value = fields->f_r1;
1025 break;
1026 case M32R_OPERAND_SRC2 :
1027 value = fields->f_r2;
1028 break;
1029 case M32R_OPERAND_UIMM16 :
1030 value = fields->f_uimm16;
1031 break;
1032 case M32R_OPERAND_UIMM24 :
1033 value = fields->f_uimm24;
1034 break;
1035 case M32R_OPERAND_UIMM4 :
1036 value = fields->f_uimm4;
1037 break;
1038 case M32R_OPERAND_UIMM5 :
1039 value = fields->f_uimm5;
1040 break;
1041 case M32R_OPERAND_ULO16 :
1042 value = fields->f_uimm16;
1043 break;
1044
1045 default :
1046 /* xgettext:c-format */
1047 fprintf (stderr, _("Unrecognized field %d while getting vma operand.\n"),
1048 opindex);
1049 abort ();
1050 }
1051
1052 return value;
1053}
1054
1055/* Stuffing values in cgen_fields is handled by a collection of functions.
1056 They are distinguished by the type of the VALUE argument they accept.
1057 TODO: floating point, inlining support, remove cases where argument type
1058 not appropriate. */
1059
1060void
1061m32r_cgen_set_int_operand (cd, opindex, fields, value)
1062 CGEN_CPU_DESC cd;
1063 int opindex;
1064 CGEN_FIELDS * fields;
1065 int value;
1066{
1067 switch (opindex)
1068 {
1069 case M32R_OPERAND_ACC :
1070 fields->f_acc = value;
1071 break;
1072 case M32R_OPERAND_ACCD :
1073 fields->f_accd = value;
1074 break;
1075 case M32R_OPERAND_ACCS :
1076 fields->f_accs = value;
1077 break;
1078 case M32R_OPERAND_DCR :
1079 fields->f_r1 = value;
1080 break;
1081 case M32R_OPERAND_DISP16 :
1082 fields->f_disp16 = value;
1083 break;
1084 case M32R_OPERAND_DISP24 :
1085 fields->f_disp24 = value;
1086 break;
1087 case M32R_OPERAND_DISP8 :
1088 fields->f_disp8 = value;
1089 break;
1090 case M32R_OPERAND_DR :
1091 fields->f_r1 = value;
1092 break;
1093 case M32R_OPERAND_HASH :
1094 break;
1095 case M32R_OPERAND_HI16 :
1096 fields->f_hi16 = value;
1097 break;
1098 case M32R_OPERAND_IMM1 :
1099 fields->f_imm1 = value;
1100 break;
1101 case M32R_OPERAND_SCR :
1102 fields->f_r2 = value;
1103 break;
1104 case M32R_OPERAND_SIMM16 :
1105 fields->f_simm16 = value;
1106 break;
1107 case M32R_OPERAND_SIMM8 :
1108 fields->f_simm8 = value;
1109 break;
1110 case M32R_OPERAND_SLO16 :
1111 fields->f_simm16 = value;
1112 break;
1113 case M32R_OPERAND_SR :
1114 fields->f_r2 = value;
1115 break;
1116 case M32R_OPERAND_SRC1 :
1117 fields->f_r1 = value;
1118 break;
1119 case M32R_OPERAND_SRC2 :
1120 fields->f_r2 = value;
1121 break;
1122 case M32R_OPERAND_UIMM16 :
1123 fields->f_uimm16 = value;
1124 break;
1125 case M32R_OPERAND_UIMM24 :
1126 fields->f_uimm24 = value;
1127 break;
1128 case M32R_OPERAND_UIMM4 :
1129 fields->f_uimm4 = value;
1130 break;
1131 case M32R_OPERAND_UIMM5 :
1132 fields->f_uimm5 = value;
1133 break;
1134 case M32R_OPERAND_ULO16 :
1135 fields->f_uimm16 = value;
1136 break;
1137
1138 default :
1139 /* xgettext:c-format */
1140 fprintf (stderr, _("Unrecognized field %d while setting int operand.\n"),
1141 opindex);
1142 abort ();
1143 }
1144}
1145
1146void
1147m32r_cgen_set_vma_operand (cd, opindex, fields, value)
1148 CGEN_CPU_DESC cd;
1149 int opindex;
1150 CGEN_FIELDS * fields;
1151 bfd_vma value;
1152{
1153 switch (opindex)
1154 {
1155 case M32R_OPERAND_ACC :
1156 fields->f_acc = value;
1157 break;
1158 case M32R_OPERAND_ACCD :
1159 fields->f_accd = value;
1160 break;
1161 case M32R_OPERAND_ACCS :
1162 fields->f_accs = value;
1163 break;
1164 case M32R_OPERAND_DCR :
1165 fields->f_r1 = value;
1166 break;
1167 case M32R_OPERAND_DISP16 :
1168 fields->f_disp16 = value;
1169 break;
1170 case M32R_OPERAND_DISP24 :
1171 fields->f_disp24 = value;
1172 break;
1173 case M32R_OPERAND_DISP8 :
1174 fields->f_disp8 = value;
1175 break;
1176 case M32R_OPERAND_DR :
1177 fields->f_r1 = value;
1178 break;
1179 case M32R_OPERAND_HASH :
1180 break;
1181 case M32R_OPERAND_HI16 :
1182 fields->f_hi16 = value;
1183 break;
1184 case M32R_OPERAND_IMM1 :
1185 fields->f_imm1 = value;
1186 break;
1187 case M32R_OPERAND_SCR :
1188 fields->f_r2 = value;
1189 break;
1190 case M32R_OPERAND_SIMM16 :
1191 fields->f_simm16 = value;
1192 break;
1193 case M32R_OPERAND_SIMM8 :
1194 fields->f_simm8 = value;
1195 break;
1196 case M32R_OPERAND_SLO16 :
1197 fields->f_simm16 = value;
1198 break;
1199 case M32R_OPERAND_SR :
1200 fields->f_r2 = value;
1201 break;
1202 case M32R_OPERAND_SRC1 :
1203 fields->f_r1 = value;
1204 break;
1205 case M32R_OPERAND_SRC2 :
1206 fields->f_r2 = value;
1207 break;
1208 case M32R_OPERAND_UIMM16 :
1209 fields->f_uimm16 = value;
1210 break;
1211 case M32R_OPERAND_UIMM24 :
1212 fields->f_uimm24 = value;
1213 break;
1214 case M32R_OPERAND_UIMM4 :
1215 fields->f_uimm4 = value;
1216 break;
1217 case M32R_OPERAND_UIMM5 :
1218 fields->f_uimm5 = value;
1219 break;
1220 case M32R_OPERAND_ULO16 :
1221 fields->f_uimm16 = value;
1222 break;
1223
1224 default :
1225 /* xgettext:c-format */
1226 fprintf (stderr, _("Unrecognized field %d while setting vma operand.\n"),
1227 opindex);
1228 abort ();
1229 }
1230}
1231
1232/* Function to call before using the instruction builder tables. */
1233
1234void
1235m32r_cgen_init_ibld_table (cd)
1236 CGEN_CPU_DESC cd;
1237{
1238 cd->insert_handlers = & m32r_cgen_insert_handlers[0];
1239 cd->extract_handlers = & m32r_cgen_extract_handlers[0];
1240
1241 cd->insert_operand = m32r_cgen_insert_operand;
1242 cd->extract_operand = m32r_cgen_extract_operand;
1243
1244 cd->get_int_operand = m32r_cgen_get_int_operand;
1245 cd->set_int_operand = m32r_cgen_set_int_operand;
1246 cd->get_vma_operand = m32r_cgen_get_vma_operand;
1247 cd->set_vma_operand = m32r_cgen_set_vma_operand;
1248}
Note: See TracBrowser for help on using the repository browser.