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