source: trunk/src/binutils/opcodes/ip2k-ibld.c@ 1036

Last change on this file since 1036 was 607, checked in by bird, 22 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 26.2 KB
Line 
1/* Instruction building/extraction support for ip2k. -*- 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 "ip2k-desc.h"
34#include "ip2k-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 * ip2k_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 *
563ip2k_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 IP2K_OPERAND_ADDR16CJP :
576 errmsg = insert_normal (cd, fields->f_addr16cjp, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 12, 13, 16, total_length, buffer);
577 break;
578 case IP2K_OPERAND_ADDR16H :
579 errmsg = insert_normal (cd, fields->f_imm8, 0, 0, 7, 8, 16, total_length, buffer);
580 break;
581 case IP2K_OPERAND_ADDR16L :
582 errmsg = insert_normal (cd, fields->f_imm8, 0, 0, 7, 8, 16, total_length, buffer);
583 break;
584 case IP2K_OPERAND_ADDR16P :
585 errmsg = insert_normal (cd, fields->f_page3, 0, 0, 2, 3, 16, total_length, buffer);
586 break;
587 case IP2K_OPERAND_BITNO :
588 errmsg = insert_normal (cd, fields->f_bitno, 0, 0, 11, 3, 16, total_length, buffer);
589 break;
590 case IP2K_OPERAND_CBIT :
591 break;
592 case IP2K_OPERAND_DCBIT :
593 break;
594 case IP2K_OPERAND_FR :
595 errmsg = insert_normal (cd, fields->f_reg, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 8, 9, 16, total_length, buffer);
596 break;
597 case IP2K_OPERAND_LIT8 :
598 errmsg = insert_normal (cd, fields->f_imm8, 0, 0, 7, 8, 16, total_length, buffer);
599 break;
600 case IP2K_OPERAND_PABITS :
601 break;
602 case IP2K_OPERAND_RETI3 :
603 errmsg = insert_normal (cd, fields->f_reti3, 0, 0, 2, 3, 16, total_length, buffer);
604 break;
605 case IP2K_OPERAND_ZBIT :
606 break;
607
608 default :
609 /* xgettext:c-format */
610 fprintf (stderr, _("Unrecognized field %d while building insn.\n"),
611 opindex);
612 abort ();
613 }
614
615 return errmsg;
616}
617
618int ip2k_cgen_extract_operand
619 PARAMS ((CGEN_CPU_DESC, int, CGEN_EXTRACT_INFO *, CGEN_INSN_INT,
620 CGEN_FIELDS *, bfd_vma));
621
622/* Main entry point for operand extraction.
623 The result is <= 0 for error, >0 for success.
624 ??? Actual values aren't well defined right now.
625
626 This function is basically just a big switch statement. Earlier versions
627 used tables to look up the function to use, but
628 - if the table contains both assembler and disassembler functions then
629 the disassembler contains much of the assembler and vice-versa,
630 - there's a lot of inlining possibilities as things grow,
631 - using a switch statement avoids the function call overhead.
632
633 This function could be moved into `print_insn_normal', but keeping it
634 separate makes clear the interface between `print_insn_normal' and each of
635 the handlers. */
636
637int
638ip2k_cgen_extract_operand (cd, opindex, ex_info, insn_value, fields, pc)
639 CGEN_CPU_DESC cd;
640 int opindex;
641 CGEN_EXTRACT_INFO *ex_info;
642 CGEN_INSN_INT insn_value;
643 CGEN_FIELDS * fields;
644 bfd_vma pc;
645{
646 /* Assume success (for those operands that are nops). */
647 int length = 1;
648 unsigned int total_length = CGEN_FIELDS_BITSIZE (fields);
649
650 switch (opindex)
651 {
652 case IP2K_OPERAND_ADDR16CJP :
653 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 12, 13, 16, total_length, pc, & fields->f_addr16cjp);
654 break;
655 case IP2K_OPERAND_ADDR16H :
656 length = extract_normal (cd, ex_info, insn_value, 0, 0, 7, 8, 16, total_length, pc, & fields->f_imm8);
657 break;
658 case IP2K_OPERAND_ADDR16L :
659 length = extract_normal (cd, ex_info, insn_value, 0, 0, 7, 8, 16, total_length, pc, & fields->f_imm8);
660 break;
661 case IP2K_OPERAND_ADDR16P :
662 length = extract_normal (cd, ex_info, insn_value, 0, 0, 2, 3, 16, total_length, pc, & fields->f_page3);
663 break;
664 case IP2K_OPERAND_BITNO :
665 length = extract_normal (cd, ex_info, insn_value, 0, 0, 11, 3, 16, total_length, pc, & fields->f_bitno);
666 break;
667 case IP2K_OPERAND_CBIT :
668 break;
669 case IP2K_OPERAND_DCBIT :
670 break;
671 case IP2K_OPERAND_FR :
672 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 8, 9, 16, total_length, pc, & fields->f_reg);
673 break;
674 case IP2K_OPERAND_LIT8 :
675 length = extract_normal (cd, ex_info, insn_value, 0, 0, 7, 8, 16, total_length, pc, & fields->f_imm8);
676 break;
677 case IP2K_OPERAND_PABITS :
678 break;
679 case IP2K_OPERAND_RETI3 :
680 length = extract_normal (cd, ex_info, insn_value, 0, 0, 2, 3, 16, total_length, pc, & fields->f_reti3);
681 break;
682 case IP2K_OPERAND_ZBIT :
683 break;
684
685 default :
686 /* xgettext:c-format */
687 fprintf (stderr, _("Unrecognized field %d while decoding insn.\n"),
688 opindex);
689 abort ();
690 }
691
692 return length;
693}
694
695cgen_insert_fn * const ip2k_cgen_insert_handlers[] =
696{
697 insert_insn_normal,
698};
699
700cgen_extract_fn * const ip2k_cgen_extract_handlers[] =
701{
702 extract_insn_normal,
703};
704
705int ip2k_cgen_get_int_operand
706 PARAMS ((CGEN_CPU_DESC, int, const CGEN_FIELDS *));
707bfd_vma ip2k_cgen_get_vma_operand
708 PARAMS ((CGEN_CPU_DESC, int, const CGEN_FIELDS *));
709
710/* Getting values from cgen_fields is handled by a collection of functions.
711 They are distinguished by the type of the VALUE argument they return.
712 TODO: floating point, inlining support, remove cases where result type
713 not appropriate. */
714
715int
716ip2k_cgen_get_int_operand (cd, opindex, fields)
717 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
718 int opindex;
719 const CGEN_FIELDS * fields;
720{
721 int value;
722
723 switch (opindex)
724 {
725 case IP2K_OPERAND_ADDR16CJP :
726 value = fields->f_addr16cjp;
727 break;
728 case IP2K_OPERAND_ADDR16H :
729 value = fields->f_imm8;
730 break;
731 case IP2K_OPERAND_ADDR16L :
732 value = fields->f_imm8;
733 break;
734 case IP2K_OPERAND_ADDR16P :
735 value = fields->f_page3;
736 break;
737 case IP2K_OPERAND_BITNO :
738 value = fields->f_bitno;
739 break;
740 case IP2K_OPERAND_CBIT :
741 value = 0;
742 break;
743 case IP2K_OPERAND_DCBIT :
744 value = 0;
745 break;
746 case IP2K_OPERAND_FR :
747 value = fields->f_reg;
748 break;
749 case IP2K_OPERAND_LIT8 :
750 value = fields->f_imm8;
751 break;
752 case IP2K_OPERAND_PABITS :
753 value = 0;
754 break;
755 case IP2K_OPERAND_RETI3 :
756 value = fields->f_reti3;
757 break;
758 case IP2K_OPERAND_ZBIT :
759 value = 0;
760 break;
761
762 default :
763 /* xgettext:c-format */
764 fprintf (stderr, _("Unrecognized field %d while getting int operand.\n"),
765 opindex);
766 abort ();
767 }
768
769 return value;
770}
771
772bfd_vma
773ip2k_cgen_get_vma_operand (cd, opindex, fields)
774 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
775 int opindex;
776 const CGEN_FIELDS * fields;
777{
778 bfd_vma value;
779
780 switch (opindex)
781 {
782 case IP2K_OPERAND_ADDR16CJP :
783 value = fields->f_addr16cjp;
784 break;
785 case IP2K_OPERAND_ADDR16H :
786 value = fields->f_imm8;
787 break;
788 case IP2K_OPERAND_ADDR16L :
789 value = fields->f_imm8;
790 break;
791 case IP2K_OPERAND_ADDR16P :
792 value = fields->f_page3;
793 break;
794 case IP2K_OPERAND_BITNO :
795 value = fields->f_bitno;
796 break;
797 case IP2K_OPERAND_CBIT :
798 value = 0;
799 break;
800 case IP2K_OPERAND_DCBIT :
801 value = 0;
802 break;
803 case IP2K_OPERAND_FR :
804 value = fields->f_reg;
805 break;
806 case IP2K_OPERAND_LIT8 :
807 value = fields->f_imm8;
808 break;
809 case IP2K_OPERAND_PABITS :
810 value = 0;
811 break;
812 case IP2K_OPERAND_RETI3 :
813 value = fields->f_reti3;
814 break;
815 case IP2K_OPERAND_ZBIT :
816 value = 0;
817 break;
818
819 default :
820 /* xgettext:c-format */
821 fprintf (stderr, _("Unrecognized field %d while getting vma operand.\n"),
822 opindex);
823 abort ();
824 }
825
826 return value;
827}
828
829void ip2k_cgen_set_int_operand
830 PARAMS ((CGEN_CPU_DESC, int, CGEN_FIELDS *, int));
831void ip2k_cgen_set_vma_operand
832 PARAMS ((CGEN_CPU_DESC, int, CGEN_FIELDS *, bfd_vma));
833
834/* Stuffing values in cgen_fields is handled by a collection of functions.
835 They are distinguished by the type of the VALUE argument they accept.
836 TODO: floating point, inlining support, remove cases where argument type
837 not appropriate. */
838
839void
840ip2k_cgen_set_int_operand (cd, opindex, fields, value)
841 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
842 int opindex;
843 CGEN_FIELDS * fields;
844 int value;
845{
846 switch (opindex)
847 {
848 case IP2K_OPERAND_ADDR16CJP :
849 fields->f_addr16cjp = value;
850 break;
851 case IP2K_OPERAND_ADDR16H :
852 fields->f_imm8 = value;
853 break;
854 case IP2K_OPERAND_ADDR16L :
855 fields->f_imm8 = value;
856 break;
857 case IP2K_OPERAND_ADDR16P :
858 fields->f_page3 = value;
859 break;
860 case IP2K_OPERAND_BITNO :
861 fields->f_bitno = value;
862 break;
863 case IP2K_OPERAND_CBIT :
864 break;
865 case IP2K_OPERAND_DCBIT :
866 break;
867 case IP2K_OPERAND_FR :
868 fields->f_reg = value;
869 break;
870 case IP2K_OPERAND_LIT8 :
871 fields->f_imm8 = value;
872 break;
873 case IP2K_OPERAND_PABITS :
874 break;
875 case IP2K_OPERAND_RETI3 :
876 fields->f_reti3 = value;
877 break;
878 case IP2K_OPERAND_ZBIT :
879 break;
880
881 default :
882 /* xgettext:c-format */
883 fprintf (stderr, _("Unrecognized field %d while setting int operand.\n"),
884 opindex);
885 abort ();
886 }
887}
888
889void
890ip2k_cgen_set_vma_operand (cd, opindex, fields, value)
891 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
892 int opindex;
893 CGEN_FIELDS * fields;
894 bfd_vma value;
895{
896 switch (opindex)
897 {
898 case IP2K_OPERAND_ADDR16CJP :
899 fields->f_addr16cjp = value;
900 break;
901 case IP2K_OPERAND_ADDR16H :
902 fields->f_imm8 = value;
903 break;
904 case IP2K_OPERAND_ADDR16L :
905 fields->f_imm8 = value;
906 break;
907 case IP2K_OPERAND_ADDR16P :
908 fields->f_page3 = value;
909 break;
910 case IP2K_OPERAND_BITNO :
911 fields->f_bitno = value;
912 break;
913 case IP2K_OPERAND_CBIT :
914 break;
915 case IP2K_OPERAND_DCBIT :
916 break;
917 case IP2K_OPERAND_FR :
918 fields->f_reg = value;
919 break;
920 case IP2K_OPERAND_LIT8 :
921 fields->f_imm8 = value;
922 break;
923 case IP2K_OPERAND_PABITS :
924 break;
925 case IP2K_OPERAND_RETI3 :
926 fields->f_reti3 = value;
927 break;
928 case IP2K_OPERAND_ZBIT :
929 break;
930
931 default :
932 /* xgettext:c-format */
933 fprintf (stderr, _("Unrecognized field %d while setting vma operand.\n"),
934 opindex);
935 abort ();
936 }
937}
938
939/* Function to call before using the instruction builder tables. */
940
941void
942ip2k_cgen_init_ibld_table (cd)
943 CGEN_CPU_DESC cd;
944{
945 cd->insert_handlers = & ip2k_cgen_insert_handlers[0];
946 cd->extract_handlers = & ip2k_cgen_extract_handlers[0];
947
948 cd->insert_operand = ip2k_cgen_insert_operand;
949 cd->extract_operand = ip2k_cgen_extract_operand;
950
951 cd->get_int_operand = ip2k_cgen_get_int_operand;
952 cd->set_int_operand = ip2k_cgen_set_int_operand;
953 cd->get_vma_operand = ip2k_cgen_get_vma_operand;
954 cd->set_vma_operand = ip2k_cgen_set_vma_operand;
955}
Note: See TracBrowser for help on using the repository browser.