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