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