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