1 /* DO NOT EDIT! -*- buffer-read-only: t -*- vi:set ro: */
2 /* Instruction building/extraction support for fr30. -*- C -*-
3
4 THIS FILE IS MACHINE GENERATED WITH CGEN: Cpu tools GENerator.
5 - the resultant file is machine generated, cgen-ibld.in isn't
6
7 Copyright (C) 1996-2021 Free Software Foundation, Inc.
8
9 This file is part of libopcodes.
10
11 This library is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3, or (at your option)
14 any later version.
15
16 It is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
19 License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software Foundation, Inc.,
23 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
24
25 /* ??? Eventually more and more of this stuff can go to cpu-independent files.
26 Keep that in mind. */
27
28 #include "sysdep.h"
29 #include <stdio.h>
30 #include "ansidecl.h"
31 #include "dis-asm.h"
32 #include "bfd.h"
33 #include "symcat.h"
34 #include "fr30-desc.h"
35 #include "fr30-opc.h"
36 #include "cgen/basic-modes.h"
37 #include "opintl.h"
38 #include "safe-ctype.h"
39
40 #undef min
41 #define min(a,b) ((a) < (b) ? (a) : (b))
42 #undef max
43 #define max(a,b) ((a) > (b) ? (a) : (b))
44
45 /* Used by the ifield rtx function. */
46 #define FLD(f) (fields->f)
47
48 static const char * insert_normal
49 (CGEN_CPU_DESC, long, unsigned int, unsigned int, unsigned int,
50 unsigned int, unsigned int, unsigned int, CGEN_INSN_BYTES_PTR);
51 static const char * insert_insn_normal
52 (CGEN_CPU_DESC, const CGEN_INSN *,
53 CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma);
54 static int extract_normal
55 (CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, CGEN_INSN_INT,
56 unsigned int, unsigned int, unsigned int, unsigned int,
57 unsigned int, unsigned int, bfd_vma, long *);
58 static int extract_insn_normal
59 (CGEN_CPU_DESC, const CGEN_INSN *, CGEN_EXTRACT_INFO *,
60 CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma);
61 #if CGEN_INT_INSN_P
62 static void put_insn_int_value
63 (CGEN_CPU_DESC, CGEN_INSN_BYTES_PTR, int, int, CGEN_INSN_INT);
64 #endif
65 #if ! CGEN_INT_INSN_P
66 static CGEN_INLINE void insert_1
67 (CGEN_CPU_DESC, unsigned long, int, int, int, unsigned char *);
68 static CGEN_INLINE int fill_cache
69 (CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, int, int, bfd_vma);
70 static CGEN_INLINE long extract_1
71 (CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, int, int, int, unsigned char *, bfd_vma);
72 #endif
73
74 /* Operand insertion. */
75
76 #if ! CGEN_INT_INSN_P
77
78 /* Subroutine of insert_normal. */
79
80 static CGEN_INLINE void
insert_1(CGEN_CPU_DESC cd,unsigned long value,int start,int length,int word_length,unsigned char * bufp)81 insert_1 (CGEN_CPU_DESC cd,
82 unsigned long value,
83 int start,
84 int length,
85 int word_length,
86 unsigned char *bufp)
87 {
88 unsigned long x, mask;
89 int shift;
90
91 x = cgen_get_insn_value (cd, bufp, word_length, cd->endian);
92
93 /* Written this way to avoid undefined behaviour. */
94 mask = (1UL << (length - 1) << 1) - 1;
95 if (CGEN_INSN_LSB0_P)
96 shift = (start + 1) - length;
97 else
98 shift = (word_length - (start + length));
99 x = (x & ~(mask << shift)) | ((value & mask) << shift);
100
101 cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x, cd->endian);
102 }
103
104 #endif /* ! CGEN_INT_INSN_P */
105
106 /* Default insertion routine.
107
108 ATTRS is a mask of the boolean attributes.
109 WORD_OFFSET is the offset in bits from the start of the insn of the value.
110 WORD_LENGTH is the length of the word in bits in which the value resides.
111 START is the starting bit number in the word, architecture origin.
112 LENGTH is the length of VALUE in bits.
113 TOTAL_LENGTH is the total length of the insn in bits.
114
115 The result is an error message or NULL if success. */
116
117 /* ??? This duplicates functionality with bfd's howto table and
118 bfd_install_relocation. */
119 /* ??? This doesn't handle bfd_vma's. Create another function when
120 necessary. */
121
122 static const char *
insert_normal(CGEN_CPU_DESC cd,long value,unsigned int attrs,unsigned int word_offset,unsigned int start,unsigned int length,unsigned int word_length,unsigned int total_length,CGEN_INSN_BYTES_PTR buffer)123 insert_normal (CGEN_CPU_DESC cd,
124 long value,
125 unsigned int attrs,
126 unsigned int word_offset,
127 unsigned int start,
128 unsigned int length,
129 unsigned int word_length,
130 unsigned int total_length,
131 CGEN_INSN_BYTES_PTR buffer)
132 {
133 static char errbuf[100];
134 unsigned long mask;
135
136 /* If LENGTH is zero, this operand doesn't contribute to the value. */
137 if (length == 0)
138 return NULL;
139
140 /* Written this way to avoid undefined behaviour. */
141 mask = (1UL << (length - 1) << 1) - 1;
142
143 if (word_length > 8 * sizeof (CGEN_INSN_INT))
144 abort ();
145
146 /* For architectures with insns smaller than the base-insn-bitsize,
147 word_length may be too big. */
148 if (cd->min_insn_bitsize < cd->base_insn_bitsize)
149 {
150 if (word_offset == 0
151 && word_length > total_length)
152 word_length = total_length;
153 }
154
155 /* Ensure VALUE will fit. */
156 if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGN_OPT))
157 {
158 long minval = - (1UL << (length - 1));
159 unsigned long maxval = mask;
160
161 if ((value > 0 && (unsigned long) value > maxval)
162 || value < minval)
163 {
164 /* xgettext:c-format */
165 sprintf (errbuf,
166 _("operand out of range (%ld not between %ld and %lu)"),
167 value, minval, maxval);
168 return errbuf;
169 }
170 }
171 else if (! CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED))
172 {
173 unsigned long maxval = mask;
174 unsigned long val = (unsigned long) value;
175
176 /* For hosts with a word size > 32 check to see if value has been sign
177 extended beyond 32 bits. If so then ignore these higher sign bits
178 as the user is attempting to store a 32-bit signed value into an
179 unsigned 32-bit field which is allowed. */
180 if (sizeof (unsigned long) > 4 && ((value >> 32) == -1))
181 val &= 0xFFFFFFFF;
182
183 if (val > maxval)
184 {
185 /* xgettext:c-format */
186 sprintf (errbuf,
187 _("operand out of range (0x%lx not between 0 and 0x%lx)"),
188 val, maxval);
189 return errbuf;
190 }
191 }
192 else
193 {
194 if (! cgen_signed_overflow_ok_p (cd))
195 {
196 long minval = - (1UL << (length - 1));
197 long maxval = (1UL << (length - 1)) - 1;
198
199 if (value < minval || value > maxval)
200 {
201 sprintf
202 /* xgettext:c-format */
203 (errbuf, _("operand out of range (%ld not between %ld and %ld)"),
204 value, minval, maxval);
205 return errbuf;
206 }
207 }
208 }
209
210 #if CGEN_INT_INSN_P
211
212 {
213 int shift_within_word, shift_to_word, shift;
214
215 /* How to shift the value to BIT0 of the word. */
216 shift_to_word = total_length - (word_offset + word_length);
217
218 /* How to shift the value to the field within the word. */
219 if (CGEN_INSN_LSB0_P)
220 shift_within_word = start + 1 - length;
221 else
222 shift_within_word = word_length - start - length;
223
224 /* The total SHIFT, then mask in the value. */
225 shift = shift_to_word + shift_within_word;
226 *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
227 }
228
229 #else /* ! CGEN_INT_INSN_P */
230
231 {
232 unsigned char *bufp = (unsigned char *) buffer + word_offset / 8;
233
234 insert_1 (cd, value, start, length, word_length, bufp);
235 }
236
237 #endif /* ! CGEN_INT_INSN_P */
238
239 return NULL;
240 }
241
242 /* Default insn builder (insert handler).
243 The instruction is recorded in CGEN_INT_INSN_P byte order (meaning
244 that if CGEN_INSN_BYTES_PTR is an int * and thus, the value is
245 recorded in host byte order, otherwise BUFFER is an array of bytes
246 and the value is recorded in target byte order).
247 The result is an error message or NULL if success. */
248
249 static const char *
insert_insn_normal(CGEN_CPU_DESC cd,const CGEN_INSN * insn,CGEN_FIELDS * fields,CGEN_INSN_BYTES_PTR buffer,bfd_vma pc)250 insert_insn_normal (CGEN_CPU_DESC cd,
251 const CGEN_INSN * insn,
252 CGEN_FIELDS * fields,
253 CGEN_INSN_BYTES_PTR buffer,
254 bfd_vma pc)
255 {
256 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
257 unsigned long value;
258 const CGEN_SYNTAX_CHAR_TYPE * syn;
259
260 CGEN_INIT_INSERT (cd);
261 value = CGEN_INSN_BASE_VALUE (insn);
262
263 /* If we're recording insns as numbers (rather than a string of bytes),
264 target byte order handling is deferred until later. */
265
266 #if CGEN_INT_INSN_P
267
268 put_insn_int_value (cd, buffer, cd->base_insn_bitsize,
269 CGEN_FIELDS_BITSIZE (fields), value);
270
271 #else
272
273 cgen_put_insn_value (cd, buffer, min ((unsigned) cd->base_insn_bitsize,
274 (unsigned) CGEN_FIELDS_BITSIZE (fields)),
275 value, cd->insn_endian);
276
277 #endif /* ! CGEN_INT_INSN_P */
278
279 /* ??? It would be better to scan the format's fields.
280 Still need to be able to insert a value based on the operand though;
281 e.g. storing a branch displacement that got resolved later.
282 Needs more thought first. */
283
284 for (syn = CGEN_SYNTAX_STRING (syntax); * syn; ++ syn)
285 {
286 const char *errmsg;
287
288 if (CGEN_SYNTAX_CHAR_P (* syn))
289 continue;
290
291 errmsg = (* cd->insert_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
292 fields, buffer, pc);
293 if (errmsg)
294 return errmsg;
295 }
296
297 return NULL;
298 }
299
300 #if CGEN_INT_INSN_P
301 /* Cover function to store an insn value into an integral insn. Must go here
302 because it needs <prefix>-desc.h for CGEN_INT_INSN_P. */
303
304 static void
put_insn_int_value(CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,CGEN_INSN_BYTES_PTR buf,int length,int insn_length,CGEN_INSN_INT value)305 put_insn_int_value (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
306 CGEN_INSN_BYTES_PTR buf,
307 int length,
308 int insn_length,
309 CGEN_INSN_INT value)
310 {
311 /* For architectures with insns smaller than the base-insn-bitsize,
312 length may be too big. */
313 if (length > insn_length)
314 *buf = value;
315 else
316 {
317 int shift = insn_length - length;
318 /* Written this way to avoid undefined behaviour. */
319 CGEN_INSN_INT mask = length == 0 ? 0 : (1UL << (length - 1) << 1) - 1;
320
321 *buf = (*buf & ~(mask << shift)) | ((value & mask) << shift);
322 }
323 }
324 #endif
325
326 /* Operand extraction. */
327
328 #if ! CGEN_INT_INSN_P
329
330 /* Subroutine of extract_normal.
331 Ensure sufficient bytes are cached in EX_INFO.
332 OFFSET is the offset in bytes from the start of the insn of the value.
333 BYTES is the length of the needed value.
334 Returns 1 for success, 0 for failure. */
335
336 static CGEN_INLINE int
fill_cache(CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,CGEN_EXTRACT_INFO * ex_info,int offset,int bytes,bfd_vma pc)337 fill_cache (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
338 CGEN_EXTRACT_INFO *ex_info,
339 int offset,
340 int bytes,
341 bfd_vma pc)
342 {
343 /* It's doubtful that the middle part has already been fetched so
344 we don't optimize that case. kiss. */
345 unsigned int mask;
346 disassemble_info *info = (disassemble_info *) ex_info->dis_info;
347
348 /* First do a quick check. */
349 mask = (1 << bytes) - 1;
350 if (((ex_info->valid >> offset) & mask) == mask)
351 return 1;
352
353 /* Search for the first byte we need to read. */
354 for (mask = 1 << offset; bytes > 0; --bytes, ++offset, mask <<= 1)
355 if (! (mask & ex_info->valid))
356 break;
357
358 if (bytes)
359 {
360 int status;
361
362 pc += offset;
363 status = (*info->read_memory_func)
364 (pc, ex_info->insn_bytes + offset, bytes, info);
365
366 if (status != 0)
367 {
368 (*info->memory_error_func) (status, pc, info);
369 return 0;
370 }
371
372 ex_info->valid |= ((1 << bytes) - 1) << offset;
373 }
374
375 return 1;
376 }
377
378 /* Subroutine of extract_normal. */
379
380 static CGEN_INLINE long
extract_1(CGEN_CPU_DESC cd,CGEN_EXTRACT_INFO * ex_info ATTRIBUTE_UNUSED,int start,int length,int word_length,unsigned char * bufp,bfd_vma pc ATTRIBUTE_UNUSED)381 extract_1 (CGEN_CPU_DESC cd,
382 CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED,
383 int start,
384 int length,
385 int word_length,
386 unsigned char *bufp,
387 bfd_vma pc ATTRIBUTE_UNUSED)
388 {
389 unsigned long x;
390 int shift;
391
392 x = cgen_get_insn_value (cd, bufp, word_length, cd->endian);
393
394 if (CGEN_INSN_LSB0_P)
395 shift = (start + 1) - length;
396 else
397 shift = (word_length - (start + length));
398 return x >> shift;
399 }
400
401 #endif /* ! CGEN_INT_INSN_P */
402
403 /* Default extraction routine.
404
405 INSN_VALUE is the first base_insn_bitsize bits of the insn in host order,
406 or sometimes less for cases like the m32r where the base insn size is 32
407 but some insns are 16 bits.
408 ATTRS is a mask of the boolean attributes. We only need `SIGNED',
409 but for generality we take a bitmask of all of them.
410 WORD_OFFSET is the offset in bits from the start of the insn of the value.
411 WORD_LENGTH is the length of the word in bits in which the value resides.
412 START is the starting bit number in the word, architecture origin.
413 LENGTH is the length of VALUE in bits.
414 TOTAL_LENGTH is the total length of the insn in bits.
415
416 Returns 1 for success, 0 for failure. */
417
418 /* ??? The return code isn't properly used. wip. */
419
420 /* ??? This doesn't handle bfd_vma's. Create another function when
421 necessary. */
422
423 static int
extract_normal(CGEN_CPU_DESC cd,CGEN_EXTRACT_INFO * ex_info,CGEN_INSN_INT insn_value,unsigned int attrs,unsigned int word_offset,unsigned int start,unsigned int length,unsigned int word_length,unsigned int total_length,bfd_vma pc,long * valuep)424 extract_normal (CGEN_CPU_DESC cd,
425 #if ! CGEN_INT_INSN_P
426 CGEN_EXTRACT_INFO *ex_info,
427 #else
428 CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED,
429 #endif
430 CGEN_INSN_INT insn_value,
431 unsigned int attrs,
432 unsigned int word_offset,
433 unsigned int start,
434 unsigned int length,
435 unsigned int word_length,
436 unsigned int total_length,
437 #if ! CGEN_INT_INSN_P
438 bfd_vma pc,
439 #else
440 bfd_vma pc ATTRIBUTE_UNUSED,
441 #endif
442 long *valuep)
443 {
444 long value, mask;
445
446 /* If LENGTH is zero, this operand doesn't contribute to the value
447 so give it a standard value of zero. */
448 if (length == 0)
449 {
450 *valuep = 0;
451 return 1;
452 }
453
454 if (word_length > 8 * sizeof (CGEN_INSN_INT))
455 abort ();
456
457 /* For architectures with insns smaller than the insn-base-bitsize,
458 word_length may be too big. */
459 if (cd->min_insn_bitsize < cd->base_insn_bitsize)
460 {
461 if (word_offset + word_length > total_length)
462 word_length = total_length - word_offset;
463 }
464
465 /* Does the value reside in INSN_VALUE, and at the right alignment? */
466
467 if (CGEN_INT_INSN_P || (word_offset == 0 && word_length == total_length))
468 {
469 if (CGEN_INSN_LSB0_P)
470 value = insn_value >> ((word_offset + start + 1) - length);
471 else
472 value = insn_value >> (total_length - ( word_offset + start + length));
473 }
474
475 #if ! CGEN_INT_INSN_P
476
477 else
478 {
479 unsigned char *bufp = ex_info->insn_bytes + word_offset / 8;
480
481 if (word_length > 8 * sizeof (CGEN_INSN_INT))
482 abort ();
483
484 if (fill_cache (cd, ex_info, word_offset / 8, word_length / 8, pc) == 0)
485 {
486 *valuep = 0;
487 return 0;
488 }
489
490 value = extract_1 (cd, ex_info, start, length, word_length, bufp, pc);
491 }
492
493 #endif /* ! CGEN_INT_INSN_P */
494
495 /* Written this way to avoid undefined behaviour. */
496 mask = (1UL << (length - 1) << 1) - 1;
497
498 value &= mask;
499 /* sign extend? */
500 if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED)
501 && (value & (1UL << (length - 1))))
502 value |= ~mask;
503
504 *valuep = value;
505
506 return 1;
507 }
508
509 /* Default insn extractor.
510
511 INSN_VALUE is the first base_insn_bitsize bits, translated to host order.
512 The extracted fields are stored in FIELDS.
513 EX_INFO is used to handle reading variable length insns.
514 Return the length of the insn in bits, or 0 if no match,
515 or -1 if an error occurs fetching data (memory_error_func will have
516 been called). */
517
518 static int
extract_insn_normal(CGEN_CPU_DESC cd,const CGEN_INSN * insn,CGEN_EXTRACT_INFO * ex_info,CGEN_INSN_INT insn_value,CGEN_FIELDS * fields,bfd_vma pc)519 extract_insn_normal (CGEN_CPU_DESC cd,
520 const CGEN_INSN *insn,
521 CGEN_EXTRACT_INFO *ex_info,
522 CGEN_INSN_INT insn_value,
523 CGEN_FIELDS *fields,
524 bfd_vma pc)
525 {
526 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
527 const CGEN_SYNTAX_CHAR_TYPE *syn;
528
529 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
530
531 CGEN_INIT_EXTRACT (cd);
532
533 for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
534 {
535 int length;
536
537 if (CGEN_SYNTAX_CHAR_P (*syn))
538 continue;
539
540 length = (* cd->extract_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
541 ex_info, insn_value, fields, pc);
542 if (length <= 0)
543 return length;
544 }
545
546 /* We recognized and successfully extracted this insn. */
547 return CGEN_INSN_BITSIZE (insn);
548 }
549
550 /* Machine generated code added here. */
551
552 const char * fr30_cgen_insert_operand
553 (CGEN_CPU_DESC, int, CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma);
554
555 /* Main entry point for operand insertion.
556
557 This function is basically just a big switch statement. Earlier versions
558 used tables to look up the function to use, but
559 - if the table contains both assembler and disassembler functions then
560 the disassembler contains much of the assembler and vice-versa,
561 - there's a lot of inlining possibilities as things grow,
562 - using a switch statement avoids the function call overhead.
563
564 This function could be moved into `parse_insn_normal', but keeping it
565 separate makes clear the interface between `parse_insn_normal' and each of
566 the handlers. It's also needed by GAS to insert operands that couldn't be
567 resolved during parsing. */
568
569 const char *
fr30_cgen_insert_operand(CGEN_CPU_DESC cd,int opindex,CGEN_FIELDS * fields,CGEN_INSN_BYTES_PTR buffer,bfd_vma pc ATTRIBUTE_UNUSED)570 fr30_cgen_insert_operand (CGEN_CPU_DESC cd,
571 int opindex,
572 CGEN_FIELDS * fields,
573 CGEN_INSN_BYTES_PTR buffer,
574 bfd_vma pc ATTRIBUTE_UNUSED)
575 {
576 const char * errmsg = NULL;
577 unsigned int total_length = CGEN_FIELDS_BITSIZE (fields);
578
579 switch (opindex)
580 {
581 case FR30_OPERAND_CRI :
582 errmsg = insert_normal (cd, fields->f_CRi, 0, 16, 12, 4, 16, total_length, buffer);
583 break;
584 case FR30_OPERAND_CRJ :
585 errmsg = insert_normal (cd, fields->f_CRj, 0, 16, 8, 4, 16, total_length, buffer);
586 break;
587 case FR30_OPERAND_R13 :
588 break;
589 case FR30_OPERAND_R14 :
590 break;
591 case FR30_OPERAND_R15 :
592 break;
593 case FR30_OPERAND_RI :
594 errmsg = insert_normal (cd, fields->f_Ri, 0, 0, 12, 4, 16, total_length, buffer);
595 break;
596 case FR30_OPERAND_RIC :
597 errmsg = insert_normal (cd, fields->f_Ric, 0, 16, 12, 4, 16, total_length, buffer);
598 break;
599 case FR30_OPERAND_RJ :
600 errmsg = insert_normal (cd, fields->f_Rj, 0, 0, 8, 4, 16, total_length, buffer);
601 break;
602 case FR30_OPERAND_RJC :
603 errmsg = insert_normal (cd, fields->f_Rjc, 0, 16, 8, 4, 16, total_length, buffer);
604 break;
605 case FR30_OPERAND_RS1 :
606 errmsg = insert_normal (cd, fields->f_Rs1, 0, 0, 8, 4, 16, total_length, buffer);
607 break;
608 case FR30_OPERAND_RS2 :
609 errmsg = insert_normal (cd, fields->f_Rs2, 0, 0, 12, 4, 16, total_length, buffer);
610 break;
611 case FR30_OPERAND_CC :
612 errmsg = insert_normal (cd, fields->f_cc, 0, 0, 4, 4, 16, total_length, buffer);
613 break;
614 case FR30_OPERAND_CCC :
615 errmsg = insert_normal (cd, fields->f_ccc, 0, 16, 0, 8, 16, total_length, buffer);
616 break;
617 case FR30_OPERAND_DIR10 :
618 {
619 long value = fields->f_dir10;
620 value = ((USI) (value) >> (2));
621 errmsg = insert_normal (cd, value, 0, 0, 8, 8, 16, total_length, buffer);
622 }
623 break;
624 case FR30_OPERAND_DIR8 :
625 errmsg = insert_normal (cd, fields->f_dir8, 0, 0, 8, 8, 16, total_length, buffer);
626 break;
627 case FR30_OPERAND_DIR9 :
628 {
629 long value = fields->f_dir9;
630 value = ((USI) (value) >> (1));
631 errmsg = insert_normal (cd, value, 0, 0, 8, 8, 16, total_length, buffer);
632 }
633 break;
634 case FR30_OPERAND_DISP10 :
635 {
636 long value = fields->f_disp10;
637 value = ((SI) (value) >> (2));
638 errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED), 0, 4, 8, 16, total_length, buffer);
639 }
640 break;
641 case FR30_OPERAND_DISP8 :
642 errmsg = insert_normal (cd, fields->f_disp8, 0|(1<<CGEN_IFLD_SIGNED), 0, 4, 8, 16, total_length, buffer);
643 break;
644 case FR30_OPERAND_DISP9 :
645 {
646 long value = fields->f_disp9;
647 value = ((SI) (value) >> (1));
648 errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED), 0, 4, 8, 16, total_length, buffer);
649 }
650 break;
651 case FR30_OPERAND_I20 :
652 {
653 {
654 FLD (f_i20_4) = ((UINT) (FLD (f_i20)) >> (16));
655 FLD (f_i20_16) = ((FLD (f_i20)) & (65535));
656 }
657 errmsg = insert_normal (cd, fields->f_i20_4, 0, 0, 8, 4, 16, total_length, buffer);
658 if (errmsg)
659 break;
660 errmsg = insert_normal (cd, fields->f_i20_16, 0, 16, 0, 16, 16, total_length, buffer);
661 if (errmsg)
662 break;
663 }
664 break;
665 case FR30_OPERAND_I32 :
666 errmsg = insert_normal (cd, fields->f_i32, 0|(1<<CGEN_IFLD_SIGN_OPT), 16, 0, 32, 32, total_length, buffer);
667 break;
668 case FR30_OPERAND_I8 :
669 errmsg = insert_normal (cd, fields->f_i8, 0, 0, 4, 8, 16, total_length, buffer);
670 break;
671 case FR30_OPERAND_LABEL12 :
672 {
673 long value = fields->f_rel12;
674 value = ((SI) (((value) - (((pc) + (2))))) >> (1));
675 errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 5, 11, 16, total_length, buffer);
676 }
677 break;
678 case FR30_OPERAND_LABEL9 :
679 {
680 long value = fields->f_rel9;
681 value = ((SI) (((value) - (((pc) + (2))))) >> (1));
682 errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 8, 8, 16, total_length, buffer);
683 }
684 break;
685 case FR30_OPERAND_M4 :
686 {
687 long value = fields->f_m4;
688 value = ((value) & (15));
689 errmsg = insert_normal (cd, value, 0, 0, 8, 4, 16, total_length, buffer);
690 }
691 break;
692 case FR30_OPERAND_PS :
693 break;
694 case FR30_OPERAND_REGLIST_HI_LD :
695 errmsg = insert_normal (cd, fields->f_reglist_hi_ld, 0, 0, 8, 8, 16, total_length, buffer);
696 break;
697 case FR30_OPERAND_REGLIST_HI_ST :
698 errmsg = insert_normal (cd, fields->f_reglist_hi_st, 0, 0, 8, 8, 16, total_length, buffer);
699 break;
700 case FR30_OPERAND_REGLIST_LOW_LD :
701 errmsg = insert_normal (cd, fields->f_reglist_low_ld, 0, 0, 8, 8, 16, total_length, buffer);
702 break;
703 case FR30_OPERAND_REGLIST_LOW_ST :
704 errmsg = insert_normal (cd, fields->f_reglist_low_st, 0, 0, 8, 8, 16, total_length, buffer);
705 break;
706 case FR30_OPERAND_S10 :
707 {
708 long value = fields->f_s10;
709 value = ((SI) (value) >> (2));
710 errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED), 0, 8, 8, 16, total_length, buffer);
711 }
712 break;
713 case FR30_OPERAND_U10 :
714 {
715 long value = fields->f_u10;
716 value = ((USI) (value) >> (2));
717 errmsg = insert_normal (cd, value, 0, 0, 8, 8, 16, total_length, buffer);
718 }
719 break;
720 case FR30_OPERAND_U4 :
721 errmsg = insert_normal (cd, fields->f_u4, 0, 0, 8, 4, 16, total_length, buffer);
722 break;
723 case FR30_OPERAND_U4C :
724 errmsg = insert_normal (cd, fields->f_u4c, 0, 0, 12, 4, 16, total_length, buffer);
725 break;
726 case FR30_OPERAND_U8 :
727 errmsg = insert_normal (cd, fields->f_u8, 0, 0, 8, 8, 16, total_length, buffer);
728 break;
729 case FR30_OPERAND_UDISP6 :
730 {
731 long value = fields->f_udisp6;
732 value = ((USI) (value) >> (2));
733 errmsg = insert_normal (cd, value, 0, 0, 8, 4, 16, total_length, buffer);
734 }
735 break;
736
737 default :
738 /* xgettext:c-format */
739 opcodes_error_handler
740 (_("internal error: unrecognized field %d while building insn"),
741 opindex);
742 abort ();
743 }
744
745 return errmsg;
746 }
747
748 int fr30_cgen_extract_operand
749 (CGEN_CPU_DESC, int, CGEN_EXTRACT_INFO *, CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma);
750
751 /* Main entry point for operand extraction.
752 The result is <= 0 for error, >0 for success.
753 ??? Actual values aren't well defined right now.
754
755 This function is basically just a big switch statement. Earlier versions
756 used tables to look up the function to use, but
757 - if the table contains both assembler and disassembler functions then
758 the disassembler contains much of the assembler and vice-versa,
759 - there's a lot of inlining possibilities as things grow,
760 - using a switch statement avoids the function call overhead.
761
762 This function could be moved into `print_insn_normal', but keeping it
763 separate makes clear the interface between `print_insn_normal' and each of
764 the handlers. */
765
766 int
fr30_cgen_extract_operand(CGEN_CPU_DESC cd,int opindex,CGEN_EXTRACT_INFO * ex_info,CGEN_INSN_INT insn_value,CGEN_FIELDS * fields,bfd_vma pc)767 fr30_cgen_extract_operand (CGEN_CPU_DESC cd,
768 int opindex,
769 CGEN_EXTRACT_INFO *ex_info,
770 CGEN_INSN_INT insn_value,
771 CGEN_FIELDS * fields,
772 bfd_vma pc)
773 {
774 /* Assume success (for those operands that are nops). */
775 int length = 1;
776 unsigned int total_length = CGEN_FIELDS_BITSIZE (fields);
777
778 switch (opindex)
779 {
780 case FR30_OPERAND_CRI :
781 length = extract_normal (cd, ex_info, insn_value, 0, 16, 12, 4, 16, total_length, pc, & fields->f_CRi);
782 break;
783 case FR30_OPERAND_CRJ :
784 length = extract_normal (cd, ex_info, insn_value, 0, 16, 8, 4, 16, total_length, pc, & fields->f_CRj);
785 break;
786 case FR30_OPERAND_R13 :
787 break;
788 case FR30_OPERAND_R14 :
789 break;
790 case FR30_OPERAND_R15 :
791 break;
792 case FR30_OPERAND_RI :
793 length = extract_normal (cd, ex_info, insn_value, 0, 0, 12, 4, 16, total_length, pc, & fields->f_Ri);
794 break;
795 case FR30_OPERAND_RIC :
796 length = extract_normal (cd, ex_info, insn_value, 0, 16, 12, 4, 16, total_length, pc, & fields->f_Ric);
797 break;
798 case FR30_OPERAND_RJ :
799 length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 4, 16, total_length, pc, & fields->f_Rj);
800 break;
801 case FR30_OPERAND_RJC :
802 length = extract_normal (cd, ex_info, insn_value, 0, 16, 8, 4, 16, total_length, pc, & fields->f_Rjc);
803 break;
804 case FR30_OPERAND_RS1 :
805 length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 4, 16, total_length, pc, & fields->f_Rs1);
806 break;
807 case FR30_OPERAND_RS2 :
808 length = extract_normal (cd, ex_info, insn_value, 0, 0, 12, 4, 16, total_length, pc, & fields->f_Rs2);
809 break;
810 case FR30_OPERAND_CC :
811 length = extract_normal (cd, ex_info, insn_value, 0, 0, 4, 4, 16, total_length, pc, & fields->f_cc);
812 break;
813 case FR30_OPERAND_CCC :
814 length = extract_normal (cd, ex_info, insn_value, 0, 16, 0, 8, 16, total_length, pc, & fields->f_ccc);
815 break;
816 case FR30_OPERAND_DIR10 :
817 {
818 long value;
819 length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 8, 16, total_length, pc, & value);
820 value = ((value) << (2));
821 fields->f_dir10 = value;
822 }
823 break;
824 case FR30_OPERAND_DIR8 :
825 length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 8, 16, total_length, pc, & fields->f_dir8);
826 break;
827 case FR30_OPERAND_DIR9 :
828 {
829 long value;
830 length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 8, 16, total_length, pc, & value);
831 value = ((value) << (1));
832 fields->f_dir9 = value;
833 }
834 break;
835 case FR30_OPERAND_DISP10 :
836 {
837 long value;
838 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED), 0, 4, 8, 16, total_length, pc, & value);
839 value = ((value) * (4));
840 fields->f_disp10 = value;
841 }
842 break;
843 case FR30_OPERAND_DISP8 :
844 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED), 0, 4, 8, 16, total_length, pc, & fields->f_disp8);
845 break;
846 case FR30_OPERAND_DISP9 :
847 {
848 long value;
849 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED), 0, 4, 8, 16, total_length, pc, & value);
850 value = ((value) * (2));
851 fields->f_disp9 = value;
852 }
853 break;
854 case FR30_OPERAND_I20 :
855 {
856 length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 4, 16, total_length, pc, & fields->f_i20_4);
857 if (length <= 0) break;
858 length = extract_normal (cd, ex_info, insn_value, 0, 16, 0, 16, 16, total_length, pc, & fields->f_i20_16);
859 if (length <= 0) break;
860 {
861 FLD (f_i20) = ((((FLD (f_i20_4)) << (16))) | (FLD (f_i20_16)));
862 }
863 }
864 break;
865 case FR30_OPERAND_I32 :
866 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGN_OPT), 16, 0, 32, 32, total_length, pc, & fields->f_i32);
867 break;
868 case FR30_OPERAND_I8 :
869 length = extract_normal (cd, ex_info, insn_value, 0, 0, 4, 8, 16, total_length, pc, & fields->f_i8);
870 break;
871 case FR30_OPERAND_LABEL12 :
872 {
873 long value;
874 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 5, 11, 16, total_length, pc, & value);
875 value = ((((value) * (2))) + (((pc) + (2))));
876 fields->f_rel12 = value;
877 }
878 break;
879 case FR30_OPERAND_LABEL9 :
880 {
881 long value;
882 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 8, 8, 16, total_length, pc, & value);
883 value = ((((value) * (2))) + (((pc) + (2))));
884 fields->f_rel9 = value;
885 }
886 break;
887 case FR30_OPERAND_M4 :
888 {
889 long value;
890 length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 4, 16, total_length, pc, & value);
891 value = ((value) | (-16));
892 fields->f_m4 = value;
893 }
894 break;
895 case FR30_OPERAND_PS :
896 break;
897 case FR30_OPERAND_REGLIST_HI_LD :
898 length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 8, 16, total_length, pc, & fields->f_reglist_hi_ld);
899 break;
900 case FR30_OPERAND_REGLIST_HI_ST :
901 length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 8, 16, total_length, pc, & fields->f_reglist_hi_st);
902 break;
903 case FR30_OPERAND_REGLIST_LOW_LD :
904 length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 8, 16, total_length, pc, & fields->f_reglist_low_ld);
905 break;
906 case FR30_OPERAND_REGLIST_LOW_ST :
907 length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 8, 16, total_length, pc, & fields->f_reglist_low_st);
908 break;
909 case FR30_OPERAND_S10 :
910 {
911 long value;
912 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED), 0, 8, 8, 16, total_length, pc, & value);
913 value = ((value) * (4));
914 fields->f_s10 = value;
915 }
916 break;
917 case FR30_OPERAND_U10 :
918 {
919 long value;
920 length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 8, 16, total_length, pc, & value);
921 value = ((value) << (2));
922 fields->f_u10 = value;
923 }
924 break;
925 case FR30_OPERAND_U4 :
926 length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 4, 16, total_length, pc, & fields->f_u4);
927 break;
928 case FR30_OPERAND_U4C :
929 length = extract_normal (cd, ex_info, insn_value, 0, 0, 12, 4, 16, total_length, pc, & fields->f_u4c);
930 break;
931 case FR30_OPERAND_U8 :
932 length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 8, 16, total_length, pc, & fields->f_u8);
933 break;
934 case FR30_OPERAND_UDISP6 :
935 {
936 long value;
937 length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 4, 16, total_length, pc, & value);
938 value = ((value) << (2));
939 fields->f_udisp6 = value;
940 }
941 break;
942
943 default :
944 /* xgettext:c-format */
945 opcodes_error_handler
946 (_("internal error: unrecognized field %d while decoding insn"),
947 opindex);
948 abort ();
949 }
950
951 return length;
952 }
953
954 cgen_insert_fn * const fr30_cgen_insert_handlers[] =
955 {
956 insert_insn_normal,
957 };
958
959 cgen_extract_fn * const fr30_cgen_extract_handlers[] =
960 {
961 extract_insn_normal,
962 };
963
964 int fr30_cgen_get_int_operand (CGEN_CPU_DESC, int, const CGEN_FIELDS *);
965 bfd_vma fr30_cgen_get_vma_operand (CGEN_CPU_DESC, int, const CGEN_FIELDS *);
966
967 /* Getting values from cgen_fields is handled by a collection of functions.
968 They are distinguished by the type of the VALUE argument they return.
969 TODO: floating point, inlining support, remove cases where result type
970 not appropriate. */
971
972 int
fr30_cgen_get_int_operand(CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,int opindex,const CGEN_FIELDS * fields)973 fr30_cgen_get_int_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
974 int opindex,
975 const CGEN_FIELDS * fields)
976 {
977 int value;
978
979 switch (opindex)
980 {
981 case FR30_OPERAND_CRI :
982 value = fields->f_CRi;
983 break;
984 case FR30_OPERAND_CRJ :
985 value = fields->f_CRj;
986 break;
987 case FR30_OPERAND_R13 :
988 value = 0;
989 break;
990 case FR30_OPERAND_R14 :
991 value = 0;
992 break;
993 case FR30_OPERAND_R15 :
994 value = 0;
995 break;
996 case FR30_OPERAND_RI :
997 value = fields->f_Ri;
998 break;
999 case FR30_OPERAND_RIC :
1000 value = fields->f_Ric;
1001 break;
1002 case FR30_OPERAND_RJ :
1003 value = fields->f_Rj;
1004 break;
1005 case FR30_OPERAND_RJC :
1006 value = fields->f_Rjc;
1007 break;
1008 case FR30_OPERAND_RS1 :
1009 value = fields->f_Rs1;
1010 break;
1011 case FR30_OPERAND_RS2 :
1012 value = fields->f_Rs2;
1013 break;
1014 case FR30_OPERAND_CC :
1015 value = fields->f_cc;
1016 break;
1017 case FR30_OPERAND_CCC :
1018 value = fields->f_ccc;
1019 break;
1020 case FR30_OPERAND_DIR10 :
1021 value = fields->f_dir10;
1022 break;
1023 case FR30_OPERAND_DIR8 :
1024 value = fields->f_dir8;
1025 break;
1026 case FR30_OPERAND_DIR9 :
1027 value = fields->f_dir9;
1028 break;
1029 case FR30_OPERAND_DISP10 :
1030 value = fields->f_disp10;
1031 break;
1032 case FR30_OPERAND_DISP8 :
1033 value = fields->f_disp8;
1034 break;
1035 case FR30_OPERAND_DISP9 :
1036 value = fields->f_disp9;
1037 break;
1038 case FR30_OPERAND_I20 :
1039 value = fields->f_i20;
1040 break;
1041 case FR30_OPERAND_I32 :
1042 value = fields->f_i32;
1043 break;
1044 case FR30_OPERAND_I8 :
1045 value = fields->f_i8;
1046 break;
1047 case FR30_OPERAND_LABEL12 :
1048 value = fields->f_rel12;
1049 break;
1050 case FR30_OPERAND_LABEL9 :
1051 value = fields->f_rel9;
1052 break;
1053 case FR30_OPERAND_M4 :
1054 value = fields->f_m4;
1055 break;
1056 case FR30_OPERAND_PS :
1057 value = 0;
1058 break;
1059 case FR30_OPERAND_REGLIST_HI_LD :
1060 value = fields->f_reglist_hi_ld;
1061 break;
1062 case FR30_OPERAND_REGLIST_HI_ST :
1063 value = fields->f_reglist_hi_st;
1064 break;
1065 case FR30_OPERAND_REGLIST_LOW_LD :
1066 value = fields->f_reglist_low_ld;
1067 break;
1068 case FR30_OPERAND_REGLIST_LOW_ST :
1069 value = fields->f_reglist_low_st;
1070 break;
1071 case FR30_OPERAND_S10 :
1072 value = fields->f_s10;
1073 break;
1074 case FR30_OPERAND_U10 :
1075 value = fields->f_u10;
1076 break;
1077 case FR30_OPERAND_U4 :
1078 value = fields->f_u4;
1079 break;
1080 case FR30_OPERAND_U4C :
1081 value = fields->f_u4c;
1082 break;
1083 case FR30_OPERAND_U8 :
1084 value = fields->f_u8;
1085 break;
1086 case FR30_OPERAND_UDISP6 :
1087 value = fields->f_udisp6;
1088 break;
1089
1090 default :
1091 /* xgettext:c-format */
1092 opcodes_error_handler
1093 (_("internal error: unrecognized field %d while getting int operand"),
1094 opindex);
1095 abort ();
1096 }
1097
1098 return value;
1099 }
1100
1101 bfd_vma
fr30_cgen_get_vma_operand(CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,int opindex,const CGEN_FIELDS * fields)1102 fr30_cgen_get_vma_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1103 int opindex,
1104 const CGEN_FIELDS * fields)
1105 {
1106 bfd_vma value;
1107
1108 switch (opindex)
1109 {
1110 case FR30_OPERAND_CRI :
1111 value = fields->f_CRi;
1112 break;
1113 case FR30_OPERAND_CRJ :
1114 value = fields->f_CRj;
1115 break;
1116 case FR30_OPERAND_R13 :
1117 value = 0;
1118 break;
1119 case FR30_OPERAND_R14 :
1120 value = 0;
1121 break;
1122 case FR30_OPERAND_R15 :
1123 value = 0;
1124 break;
1125 case FR30_OPERAND_RI :
1126 value = fields->f_Ri;
1127 break;
1128 case FR30_OPERAND_RIC :
1129 value = fields->f_Ric;
1130 break;
1131 case FR30_OPERAND_RJ :
1132 value = fields->f_Rj;
1133 break;
1134 case FR30_OPERAND_RJC :
1135 value = fields->f_Rjc;
1136 break;
1137 case FR30_OPERAND_RS1 :
1138 value = fields->f_Rs1;
1139 break;
1140 case FR30_OPERAND_RS2 :
1141 value = fields->f_Rs2;
1142 break;
1143 case FR30_OPERAND_CC :
1144 value = fields->f_cc;
1145 break;
1146 case FR30_OPERAND_CCC :
1147 value = fields->f_ccc;
1148 break;
1149 case FR30_OPERAND_DIR10 :
1150 value = fields->f_dir10;
1151 break;
1152 case FR30_OPERAND_DIR8 :
1153 value = fields->f_dir8;
1154 break;
1155 case FR30_OPERAND_DIR9 :
1156 value = fields->f_dir9;
1157 break;
1158 case FR30_OPERAND_DISP10 :
1159 value = fields->f_disp10;
1160 break;
1161 case FR30_OPERAND_DISP8 :
1162 value = fields->f_disp8;
1163 break;
1164 case FR30_OPERAND_DISP9 :
1165 value = fields->f_disp9;
1166 break;
1167 case FR30_OPERAND_I20 :
1168 value = fields->f_i20;
1169 break;
1170 case FR30_OPERAND_I32 :
1171 value = fields->f_i32;
1172 break;
1173 case FR30_OPERAND_I8 :
1174 value = fields->f_i8;
1175 break;
1176 case FR30_OPERAND_LABEL12 :
1177 value = fields->f_rel12;
1178 break;
1179 case FR30_OPERAND_LABEL9 :
1180 value = fields->f_rel9;
1181 break;
1182 case FR30_OPERAND_M4 :
1183 value = fields->f_m4;
1184 break;
1185 case FR30_OPERAND_PS :
1186 value = 0;
1187 break;
1188 case FR30_OPERAND_REGLIST_HI_LD :
1189 value = fields->f_reglist_hi_ld;
1190 break;
1191 case FR30_OPERAND_REGLIST_HI_ST :
1192 value = fields->f_reglist_hi_st;
1193 break;
1194 case FR30_OPERAND_REGLIST_LOW_LD :
1195 value = fields->f_reglist_low_ld;
1196 break;
1197 case FR30_OPERAND_REGLIST_LOW_ST :
1198 value = fields->f_reglist_low_st;
1199 break;
1200 case FR30_OPERAND_S10 :
1201 value = fields->f_s10;
1202 break;
1203 case FR30_OPERAND_U10 :
1204 value = fields->f_u10;
1205 break;
1206 case FR30_OPERAND_U4 :
1207 value = fields->f_u4;
1208 break;
1209 case FR30_OPERAND_U4C :
1210 value = fields->f_u4c;
1211 break;
1212 case FR30_OPERAND_U8 :
1213 value = fields->f_u8;
1214 break;
1215 case FR30_OPERAND_UDISP6 :
1216 value = fields->f_udisp6;
1217 break;
1218
1219 default :
1220 /* xgettext:c-format */
1221 opcodes_error_handler
1222 (_("internal error: unrecognized field %d while getting vma operand"),
1223 opindex);
1224 abort ();
1225 }
1226
1227 return value;
1228 }
1229
1230 void fr30_cgen_set_int_operand (CGEN_CPU_DESC, int, CGEN_FIELDS *, int);
1231 void fr30_cgen_set_vma_operand (CGEN_CPU_DESC, int, CGEN_FIELDS *, bfd_vma);
1232
1233 /* Stuffing values in cgen_fields is handled by a collection of functions.
1234 They are distinguished by the type of the VALUE argument they accept.
1235 TODO: floating point, inlining support, remove cases where argument type
1236 not appropriate. */
1237
1238 void
fr30_cgen_set_int_operand(CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,int opindex,CGEN_FIELDS * fields,int value)1239 fr30_cgen_set_int_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1240 int opindex,
1241 CGEN_FIELDS * fields,
1242 int value)
1243 {
1244 switch (opindex)
1245 {
1246 case FR30_OPERAND_CRI :
1247 fields->f_CRi = value;
1248 break;
1249 case FR30_OPERAND_CRJ :
1250 fields->f_CRj = value;
1251 break;
1252 case FR30_OPERAND_R13 :
1253 break;
1254 case FR30_OPERAND_R14 :
1255 break;
1256 case FR30_OPERAND_R15 :
1257 break;
1258 case FR30_OPERAND_RI :
1259 fields->f_Ri = value;
1260 break;
1261 case FR30_OPERAND_RIC :
1262 fields->f_Ric = value;
1263 break;
1264 case FR30_OPERAND_RJ :
1265 fields->f_Rj = value;
1266 break;
1267 case FR30_OPERAND_RJC :
1268 fields->f_Rjc = value;
1269 break;
1270 case FR30_OPERAND_RS1 :
1271 fields->f_Rs1 = value;
1272 break;
1273 case FR30_OPERAND_RS2 :
1274 fields->f_Rs2 = value;
1275 break;
1276 case FR30_OPERAND_CC :
1277 fields->f_cc = value;
1278 break;
1279 case FR30_OPERAND_CCC :
1280 fields->f_ccc = value;
1281 break;
1282 case FR30_OPERAND_DIR10 :
1283 fields->f_dir10 = value;
1284 break;
1285 case FR30_OPERAND_DIR8 :
1286 fields->f_dir8 = value;
1287 break;
1288 case FR30_OPERAND_DIR9 :
1289 fields->f_dir9 = value;
1290 break;
1291 case FR30_OPERAND_DISP10 :
1292 fields->f_disp10 = value;
1293 break;
1294 case FR30_OPERAND_DISP8 :
1295 fields->f_disp8 = value;
1296 break;
1297 case FR30_OPERAND_DISP9 :
1298 fields->f_disp9 = value;
1299 break;
1300 case FR30_OPERAND_I20 :
1301 fields->f_i20 = value;
1302 break;
1303 case FR30_OPERAND_I32 :
1304 fields->f_i32 = value;
1305 break;
1306 case FR30_OPERAND_I8 :
1307 fields->f_i8 = value;
1308 break;
1309 case FR30_OPERAND_LABEL12 :
1310 fields->f_rel12 = value;
1311 break;
1312 case FR30_OPERAND_LABEL9 :
1313 fields->f_rel9 = value;
1314 break;
1315 case FR30_OPERAND_M4 :
1316 fields->f_m4 = value;
1317 break;
1318 case FR30_OPERAND_PS :
1319 break;
1320 case FR30_OPERAND_REGLIST_HI_LD :
1321 fields->f_reglist_hi_ld = value;
1322 break;
1323 case FR30_OPERAND_REGLIST_HI_ST :
1324 fields->f_reglist_hi_st = value;
1325 break;
1326 case FR30_OPERAND_REGLIST_LOW_LD :
1327 fields->f_reglist_low_ld = value;
1328 break;
1329 case FR30_OPERAND_REGLIST_LOW_ST :
1330 fields->f_reglist_low_st = value;
1331 break;
1332 case FR30_OPERAND_S10 :
1333 fields->f_s10 = value;
1334 break;
1335 case FR30_OPERAND_U10 :
1336 fields->f_u10 = value;
1337 break;
1338 case FR30_OPERAND_U4 :
1339 fields->f_u4 = value;
1340 break;
1341 case FR30_OPERAND_U4C :
1342 fields->f_u4c = value;
1343 break;
1344 case FR30_OPERAND_U8 :
1345 fields->f_u8 = value;
1346 break;
1347 case FR30_OPERAND_UDISP6 :
1348 fields->f_udisp6 = value;
1349 break;
1350
1351 default :
1352 /* xgettext:c-format */
1353 opcodes_error_handler
1354 (_("internal error: unrecognized field %d while setting int operand"),
1355 opindex);
1356 abort ();
1357 }
1358 }
1359
1360 void
fr30_cgen_set_vma_operand(CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,int opindex,CGEN_FIELDS * fields,bfd_vma value)1361 fr30_cgen_set_vma_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1362 int opindex,
1363 CGEN_FIELDS * fields,
1364 bfd_vma value)
1365 {
1366 switch (opindex)
1367 {
1368 case FR30_OPERAND_CRI :
1369 fields->f_CRi = value;
1370 break;
1371 case FR30_OPERAND_CRJ :
1372 fields->f_CRj = value;
1373 break;
1374 case FR30_OPERAND_R13 :
1375 break;
1376 case FR30_OPERAND_R14 :
1377 break;
1378 case FR30_OPERAND_R15 :
1379 break;
1380 case FR30_OPERAND_RI :
1381 fields->f_Ri = value;
1382 break;
1383 case FR30_OPERAND_RIC :
1384 fields->f_Ric = value;
1385 break;
1386 case FR30_OPERAND_RJ :
1387 fields->f_Rj = value;
1388 break;
1389 case FR30_OPERAND_RJC :
1390 fields->f_Rjc = value;
1391 break;
1392 case FR30_OPERAND_RS1 :
1393 fields->f_Rs1 = value;
1394 break;
1395 case FR30_OPERAND_RS2 :
1396 fields->f_Rs2 = value;
1397 break;
1398 case FR30_OPERAND_CC :
1399 fields->f_cc = value;
1400 break;
1401 case FR30_OPERAND_CCC :
1402 fields->f_ccc = value;
1403 break;
1404 case FR30_OPERAND_DIR10 :
1405 fields->f_dir10 = value;
1406 break;
1407 case FR30_OPERAND_DIR8 :
1408 fields->f_dir8 = value;
1409 break;
1410 case FR30_OPERAND_DIR9 :
1411 fields->f_dir9 = value;
1412 break;
1413 case FR30_OPERAND_DISP10 :
1414 fields->f_disp10 = value;
1415 break;
1416 case FR30_OPERAND_DISP8 :
1417 fields->f_disp8 = value;
1418 break;
1419 case FR30_OPERAND_DISP9 :
1420 fields->f_disp9 = value;
1421 break;
1422 case FR30_OPERAND_I20 :
1423 fields->f_i20 = value;
1424 break;
1425 case FR30_OPERAND_I32 :
1426 fields->f_i32 = value;
1427 break;
1428 case FR30_OPERAND_I8 :
1429 fields->f_i8 = value;
1430 break;
1431 case FR30_OPERAND_LABEL12 :
1432 fields->f_rel12 = value;
1433 break;
1434 case FR30_OPERAND_LABEL9 :
1435 fields->f_rel9 = value;
1436 break;
1437 case FR30_OPERAND_M4 :
1438 fields->f_m4 = value;
1439 break;
1440 case FR30_OPERAND_PS :
1441 break;
1442 case FR30_OPERAND_REGLIST_HI_LD :
1443 fields->f_reglist_hi_ld = value;
1444 break;
1445 case FR30_OPERAND_REGLIST_HI_ST :
1446 fields->f_reglist_hi_st = value;
1447 break;
1448 case FR30_OPERAND_REGLIST_LOW_LD :
1449 fields->f_reglist_low_ld = value;
1450 break;
1451 case FR30_OPERAND_REGLIST_LOW_ST :
1452 fields->f_reglist_low_st = value;
1453 break;
1454 case FR30_OPERAND_S10 :
1455 fields->f_s10 = value;
1456 break;
1457 case FR30_OPERAND_U10 :
1458 fields->f_u10 = value;
1459 break;
1460 case FR30_OPERAND_U4 :
1461 fields->f_u4 = value;
1462 break;
1463 case FR30_OPERAND_U4C :
1464 fields->f_u4c = value;
1465 break;
1466 case FR30_OPERAND_U8 :
1467 fields->f_u8 = value;
1468 break;
1469 case FR30_OPERAND_UDISP6 :
1470 fields->f_udisp6 = value;
1471 break;
1472
1473 default :
1474 /* xgettext:c-format */
1475 opcodes_error_handler
1476 (_("internal error: unrecognized field %d while setting vma operand"),
1477 opindex);
1478 abort ();
1479 }
1480 }
1481
1482 /* Function to call before using the instruction builder tables. */
1483
1484 void
fr30_cgen_init_ibld_table(CGEN_CPU_DESC cd)1485 fr30_cgen_init_ibld_table (CGEN_CPU_DESC cd)
1486 {
1487 cd->insert_handlers = & fr30_cgen_insert_handlers[0];
1488 cd->extract_handlers = & fr30_cgen_extract_handlers[0];
1489
1490 cd->insert_operand = fr30_cgen_insert_operand;
1491 cd->extract_operand = fr30_cgen_extract_operand;
1492
1493 cd->get_int_operand = fr30_cgen_get_int_operand;
1494 cd->set_int_operand = fr30_cgen_set_int_operand;
1495 cd->get_vma_operand = fr30_cgen_get_vma_operand;
1496 cd->set_vma_operand = fr30_cgen_set_vma_operand;
1497 }
1498