source: branches/libc-0.6/src/binutils/opcodes/m32r-ibld.c

Last change on this file was 610, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r609,
which included commits to RCS files with non-trunk default branches.

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