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