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