source: vendor/binutils/current/opcodes/openrisc-ibld.c

Last change on this file was 608, checked in by (none), 22 years ago

This commit was manufactured by cvs2svn to create branch 'GNU'.

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