source: trunk/binutils/opcodes/xstormy16-ibld.c@ 3442

Last change on this file since 3442 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: 36.8 KB
Line 
1/* Instruction building/extraction support for xstormy16. -*- 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 "xstormy16-desc.h"
34#include "xstormy16-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 * xstormy16_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 *
563xstormy16_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 XSTORMY16_OPERAND_RB :
576 errmsg = insert_normal (cd, fields->f_Rb, 0, 0, 17, 3, 32, total_length, buffer);
577 break;
578 case XSTORMY16_OPERAND_RBJ :
579 errmsg = insert_normal (cd, fields->f_Rbj, 0, 0, 11, 1, 32, total_length, buffer);
580 break;
581 case XSTORMY16_OPERAND_RD :
582 errmsg = insert_normal (cd, fields->f_Rd, 0, 0, 12, 4, 32, total_length, buffer);
583 break;
584 case XSTORMY16_OPERAND_RDM :
585 errmsg = insert_normal (cd, fields->f_Rdm, 0, 0, 13, 3, 32, total_length, buffer);
586 break;
587 case XSTORMY16_OPERAND_RM :
588 errmsg = insert_normal (cd, fields->f_Rm, 0, 0, 4, 3, 32, total_length, buffer);
589 break;
590 case XSTORMY16_OPERAND_RS :
591 errmsg = insert_normal (cd, fields->f_Rs, 0, 0, 8, 4, 32, total_length, buffer);
592 break;
593 case XSTORMY16_OPERAND_ABS24 :
594 {
595{
596 FLD (f_abs24_1) = ((FLD (f_abs24)) & (255));
597 FLD (f_abs24_2) = ((unsigned int) (FLD (f_abs24)) >> (8));
598}
599 errmsg = insert_normal (cd, fields->f_abs24_1, 0, 0, 8, 8, 32, total_length, buffer);
600 if (errmsg)
601 break;
602 errmsg = insert_normal (cd, fields->f_abs24_2, 0, 0, 16, 16, 32, total_length, buffer);
603 if (errmsg)
604 break;
605 }
606 break;
607 case XSTORMY16_OPERAND_BCOND2 :
608 errmsg = insert_normal (cd, fields->f_op2, 0, 0, 4, 4, 32, total_length, buffer);
609 break;
610 case XSTORMY16_OPERAND_BCOND5 :
611 errmsg = insert_normal (cd, fields->f_op5, 0, 0, 16, 4, 32, total_length, buffer);
612 break;
613 case XSTORMY16_OPERAND_HMEM8 :
614 {
615 long value = fields->f_hmem8;
616 value = ((value) - (32512));
617 errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 8, 8, 32, total_length, buffer);
618 }
619 break;
620 case XSTORMY16_OPERAND_IMM12 :
621 errmsg = insert_normal (cd, fields->f_imm12, 0|(1<<CGEN_IFLD_SIGNED), 0, 20, 12, 32, total_length, buffer);
622 break;
623 case XSTORMY16_OPERAND_IMM16 :
624 errmsg = insert_normal (cd, fields->f_imm16, 0|(1<<CGEN_IFLD_SIGN_OPT), 0, 16, 16, 32, total_length, buffer);
625 break;
626 case XSTORMY16_OPERAND_IMM2 :
627 errmsg = insert_normal (cd, fields->f_imm2, 0, 0, 10, 2, 32, total_length, buffer);
628 break;
629 case XSTORMY16_OPERAND_IMM3 :
630 errmsg = insert_normal (cd, fields->f_imm3, 0, 0, 4, 3, 32, total_length, buffer);
631 break;
632 case XSTORMY16_OPERAND_IMM3B :
633 errmsg = insert_normal (cd, fields->f_imm3b, 0, 0, 17, 3, 32, total_length, buffer);
634 break;
635 case XSTORMY16_OPERAND_IMM4 :
636 errmsg = insert_normal (cd, fields->f_imm4, 0, 0, 8, 4, 32, total_length, buffer);
637 break;
638 case XSTORMY16_OPERAND_IMM8 :
639 errmsg = insert_normal (cd, fields->f_imm8, 0, 0, 8, 8, 32, total_length, buffer);
640 break;
641 case XSTORMY16_OPERAND_IMM8SMALL :
642 errmsg = insert_normal (cd, fields->f_imm8, 0, 0, 8, 8, 32, total_length, buffer);
643 break;
644 case XSTORMY16_OPERAND_LMEM8 :
645 errmsg = insert_normal (cd, fields->f_lmem8, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 8, 8, 32, total_length, buffer);
646 break;
647 case XSTORMY16_OPERAND_REL12 :
648 {
649 long value = fields->f_rel12;
650 value = ((value) - (((pc) + (4))));
651 errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 20, 12, 32, total_length, buffer);
652 }
653 break;
654 case XSTORMY16_OPERAND_REL12A :
655 {
656 long value = fields->f_rel12a;
657 value = ((int) (((value) - (((pc) + (2))))) >> (1));
658 errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 4, 11, 32, total_length, buffer);
659 }
660 break;
661 case XSTORMY16_OPERAND_REL8_2 :
662 {
663 long value = fields->f_rel8_2;
664 value = ((value) - (((pc) + (2))));
665 errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 8, 8, 32, total_length, buffer);
666 }
667 break;
668 case XSTORMY16_OPERAND_REL8_4 :
669 {
670 long value = fields->f_rel8_4;
671 value = ((value) - (((pc) + (4))));
672 errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 8, 8, 32, total_length, buffer);
673 }
674 break;
675 case XSTORMY16_OPERAND_WS2 :
676 errmsg = insert_normal (cd, fields->f_op2m, 0, 0, 7, 1, 32, total_length, buffer);
677 break;
678
679 default :
680 /* xgettext:c-format */
681 fprintf (stderr, _("Unrecognized field %d while building insn.\n"),
682 opindex);
683 abort ();
684 }
685
686 return errmsg;
687}
688
689int xstormy16_cgen_extract_operand
690 PARAMS ((CGEN_CPU_DESC, int, CGEN_EXTRACT_INFO *, CGEN_INSN_INT,
691 CGEN_FIELDS *, bfd_vma));
692
693/* Main entry point for operand extraction.
694 The result is <= 0 for error, >0 for success.
695 ??? Actual values aren't well defined right now.
696
697 This function is basically just a big switch statement. Earlier versions
698 used tables to look up the function to use, but
699 - if the table contains both assembler and disassembler functions then
700 the disassembler contains much of the assembler and vice-versa,
701 - there's a lot of inlining possibilities as things grow,
702 - using a switch statement avoids the function call overhead.
703
704 This function could be moved into `print_insn_normal', but keeping it
705 separate makes clear the interface between `print_insn_normal' and each of
706 the handlers. */
707
708int
709xstormy16_cgen_extract_operand (cd, opindex, ex_info, insn_value, fields, pc)
710 CGEN_CPU_DESC cd;
711 int opindex;
712 CGEN_EXTRACT_INFO *ex_info;
713 CGEN_INSN_INT insn_value;
714 CGEN_FIELDS * fields;
715 bfd_vma pc;
716{
717 /* Assume success (for those operands that are nops). */
718 int length = 1;
719 unsigned int total_length = CGEN_FIELDS_BITSIZE (fields);
720
721 switch (opindex)
722 {
723 case XSTORMY16_OPERAND_RB :
724 length = extract_normal (cd, ex_info, insn_value, 0, 0, 17, 3, 32, total_length, pc, & fields->f_Rb);
725 break;
726 case XSTORMY16_OPERAND_RBJ :
727 length = extract_normal (cd, ex_info, insn_value, 0, 0, 11, 1, 32, total_length, pc, & fields->f_Rbj);
728 break;
729 case XSTORMY16_OPERAND_RD :
730 length = extract_normal (cd, ex_info, insn_value, 0, 0, 12, 4, 32, total_length, pc, & fields->f_Rd);
731 break;
732 case XSTORMY16_OPERAND_RDM :
733 length = extract_normal (cd, ex_info, insn_value, 0, 0, 13, 3, 32, total_length, pc, & fields->f_Rdm);
734 break;
735 case XSTORMY16_OPERAND_RM :
736 length = extract_normal (cd, ex_info, insn_value, 0, 0, 4, 3, 32, total_length, pc, & fields->f_Rm);
737 break;
738 case XSTORMY16_OPERAND_RS :
739 length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 4, 32, total_length, pc, & fields->f_Rs);
740 break;
741 case XSTORMY16_OPERAND_ABS24 :
742 {
743 length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 8, 32, total_length, pc, & fields->f_abs24_1);
744 if (length <= 0) break;
745 length = extract_normal (cd, ex_info, insn_value, 0, 0, 16, 16, 32, total_length, pc, & fields->f_abs24_2);
746 if (length <= 0) break;
747 FLD (f_abs24) = ((((FLD (f_abs24_2)) << (8))) | (FLD (f_abs24_1)));
748 }
749 break;
750 case XSTORMY16_OPERAND_BCOND2 :
751 length = extract_normal (cd, ex_info, insn_value, 0, 0, 4, 4, 32, total_length, pc, & fields->f_op2);
752 break;
753 case XSTORMY16_OPERAND_BCOND5 :
754 length = extract_normal (cd, ex_info, insn_value, 0, 0, 16, 4, 32, total_length, pc, & fields->f_op5);
755 break;
756 case XSTORMY16_OPERAND_HMEM8 :
757 {
758 long value;
759 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 8, 8, 32, total_length, pc, & value);
760 value = ((value) + (32512));
761 fields->f_hmem8 = value;
762 }
763 break;
764 case XSTORMY16_OPERAND_IMM12 :
765 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED), 0, 20, 12, 32, total_length, pc, & fields->f_imm12);
766 break;
767 case XSTORMY16_OPERAND_IMM16 :
768 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGN_OPT), 0, 16, 16, 32, total_length, pc, & fields->f_imm16);
769 break;
770 case XSTORMY16_OPERAND_IMM2 :
771 length = extract_normal (cd, ex_info, insn_value, 0, 0, 10, 2, 32, total_length, pc, & fields->f_imm2);
772 break;
773 case XSTORMY16_OPERAND_IMM3 :
774 length = extract_normal (cd, ex_info, insn_value, 0, 0, 4, 3, 32, total_length, pc, & fields->f_imm3);
775 break;
776 case XSTORMY16_OPERAND_IMM3B :
777 length = extract_normal (cd, ex_info, insn_value, 0, 0, 17, 3, 32, total_length, pc, & fields->f_imm3b);
778 break;
779 case XSTORMY16_OPERAND_IMM4 :
780 length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 4, 32, total_length, pc, & fields->f_imm4);
781 break;
782 case XSTORMY16_OPERAND_IMM8 :
783 length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 8, 32, total_length, pc, & fields->f_imm8);
784 break;
785 case XSTORMY16_OPERAND_IMM8SMALL :
786 length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 8, 32, total_length, pc, & fields->f_imm8);
787 break;
788 case XSTORMY16_OPERAND_LMEM8 :
789 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 8, 8, 32, total_length, pc, & fields->f_lmem8);
790 break;
791 case XSTORMY16_OPERAND_REL12 :
792 {
793 long value;
794 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 20, 12, 32, total_length, pc, & value);
795 value = ((value) + (((pc) + (4))));
796 fields->f_rel12 = value;
797 }
798 break;
799 case XSTORMY16_OPERAND_REL12A :
800 {
801 long value;
802 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 4, 11, 32, total_length, pc, & value);
803 value = ((((value) << (1))) + (((pc) + (2))));
804 fields->f_rel12a = value;
805 }
806 break;
807 case XSTORMY16_OPERAND_REL8_2 :
808 {
809 long value;
810 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 8, 8, 32, total_length, pc, & value);
811 value = ((value) + (((pc) + (2))));
812 fields->f_rel8_2 = value;
813 }
814 break;
815 case XSTORMY16_OPERAND_REL8_4 :
816 {
817 long value;
818 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 8, 8, 32, total_length, pc, & value);
819 value = ((value) + (((pc) + (4))));
820 fields->f_rel8_4 = value;
821 }
822 break;
823 case XSTORMY16_OPERAND_WS2 :
824 length = extract_normal (cd, ex_info, insn_value, 0, 0, 7, 1, 32, total_length, pc, & fields->f_op2m);
825 break;
826
827 default :
828 /* xgettext:c-format */
829 fprintf (stderr, _("Unrecognized field %d while decoding insn.\n"),
830 opindex);
831 abort ();
832 }
833
834 return length;
835}
836
837cgen_insert_fn * const xstormy16_cgen_insert_handlers[] =
838{
839 insert_insn_normal,
840};
841
842cgen_extract_fn * const xstormy16_cgen_extract_handlers[] =
843{
844 extract_insn_normal,
845};
846
847int xstormy16_cgen_get_int_operand
848 PARAMS ((CGEN_CPU_DESC, int, const CGEN_FIELDS *));
849bfd_vma xstormy16_cgen_get_vma_operand
850 PARAMS ((CGEN_CPU_DESC, int, const CGEN_FIELDS *));
851
852/* Getting values from cgen_fields is handled by a collection of functions.
853 They are distinguished by the type of the VALUE argument they return.
854 TODO: floating point, inlining support, remove cases where result type
855 not appropriate. */
856
857int
858xstormy16_cgen_get_int_operand (cd, opindex, fields)
859 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
860 int opindex;
861 const CGEN_FIELDS * fields;
862{
863 int value;
864
865 switch (opindex)
866 {
867 case XSTORMY16_OPERAND_RB :
868 value = fields->f_Rb;
869 break;
870 case XSTORMY16_OPERAND_RBJ :
871 value = fields->f_Rbj;
872 break;
873 case XSTORMY16_OPERAND_RD :
874 value = fields->f_Rd;
875 break;
876 case XSTORMY16_OPERAND_RDM :
877 value = fields->f_Rdm;
878 break;
879 case XSTORMY16_OPERAND_RM :
880 value = fields->f_Rm;
881 break;
882 case XSTORMY16_OPERAND_RS :
883 value = fields->f_Rs;
884 break;
885 case XSTORMY16_OPERAND_ABS24 :
886 value = fields->f_abs24;
887 break;
888 case XSTORMY16_OPERAND_BCOND2 :
889 value = fields->f_op2;
890 break;
891 case XSTORMY16_OPERAND_BCOND5 :
892 value = fields->f_op5;
893 break;
894 case XSTORMY16_OPERAND_HMEM8 :
895 value = fields->f_hmem8;
896 break;
897 case XSTORMY16_OPERAND_IMM12 :
898 value = fields->f_imm12;
899 break;
900 case XSTORMY16_OPERAND_IMM16 :
901 value = fields->f_imm16;
902 break;
903 case XSTORMY16_OPERAND_IMM2 :
904 value = fields->f_imm2;
905 break;
906 case XSTORMY16_OPERAND_IMM3 :
907 value = fields->f_imm3;
908 break;
909 case XSTORMY16_OPERAND_IMM3B :
910 value = fields->f_imm3b;
911 break;
912 case XSTORMY16_OPERAND_IMM4 :
913 value = fields->f_imm4;
914 break;
915 case XSTORMY16_OPERAND_IMM8 :
916 value = fields->f_imm8;
917 break;
918 case XSTORMY16_OPERAND_IMM8SMALL :
919 value = fields->f_imm8;
920 break;
921 case XSTORMY16_OPERAND_LMEM8 :
922 value = fields->f_lmem8;
923 break;
924 case XSTORMY16_OPERAND_REL12 :
925 value = fields->f_rel12;
926 break;
927 case XSTORMY16_OPERAND_REL12A :
928 value = fields->f_rel12a;
929 break;
930 case XSTORMY16_OPERAND_REL8_2 :
931 value = fields->f_rel8_2;
932 break;
933 case XSTORMY16_OPERAND_REL8_4 :
934 value = fields->f_rel8_4;
935 break;
936 case XSTORMY16_OPERAND_WS2 :
937 value = fields->f_op2m;
938 break;
939
940 default :
941 /* xgettext:c-format */
942 fprintf (stderr, _("Unrecognized field %d while getting int operand.\n"),
943 opindex);
944 abort ();
945 }
946
947 return value;
948}
949
950bfd_vma
951xstormy16_cgen_get_vma_operand (cd, opindex, fields)
952 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
953 int opindex;
954 const CGEN_FIELDS * fields;
955{
956 bfd_vma value;
957
958 switch (opindex)
959 {
960 case XSTORMY16_OPERAND_RB :
961 value = fields->f_Rb;
962 break;
963 case XSTORMY16_OPERAND_RBJ :
964 value = fields->f_Rbj;
965 break;
966 case XSTORMY16_OPERAND_RD :
967 value = fields->f_Rd;
968 break;
969 case XSTORMY16_OPERAND_RDM :
970 value = fields->f_Rdm;
971 break;
972 case XSTORMY16_OPERAND_RM :
973 value = fields->f_Rm;
974 break;
975 case XSTORMY16_OPERAND_RS :
976 value = fields->f_Rs;
977 break;
978 case XSTORMY16_OPERAND_ABS24 :
979 value = fields->f_abs24;
980 break;
981 case XSTORMY16_OPERAND_BCOND2 :
982 value = fields->f_op2;
983 break;
984 case XSTORMY16_OPERAND_BCOND5 :
985 value = fields->f_op5;
986 break;
987 case XSTORMY16_OPERAND_HMEM8 :
988 value = fields->f_hmem8;
989 break;
990 case XSTORMY16_OPERAND_IMM12 :
991 value = fields->f_imm12;
992 break;
993 case XSTORMY16_OPERAND_IMM16 :
994 value = fields->f_imm16;
995 break;
996 case XSTORMY16_OPERAND_IMM2 :
997 value = fields->f_imm2;
998 break;
999 case XSTORMY16_OPERAND_IMM3 :
1000 value = fields->f_imm3;
1001 break;
1002 case XSTORMY16_OPERAND_IMM3B :
1003 value = fields->f_imm3b;
1004 break;
1005 case XSTORMY16_OPERAND_IMM4 :
1006 value = fields->f_imm4;
1007 break;
1008 case XSTORMY16_OPERAND_IMM8 :
1009 value = fields->f_imm8;
1010 break;
1011 case XSTORMY16_OPERAND_IMM8SMALL :
1012 value = fields->f_imm8;
1013 break;
1014 case XSTORMY16_OPERAND_LMEM8 :
1015 value = fields->f_lmem8;
1016 break;
1017 case XSTORMY16_OPERAND_REL12 :
1018 value = fields->f_rel12;
1019 break;
1020 case XSTORMY16_OPERAND_REL12A :
1021 value = fields->f_rel12a;
1022 break;
1023 case XSTORMY16_OPERAND_REL8_2 :
1024 value = fields->f_rel8_2;
1025 break;
1026 case XSTORMY16_OPERAND_REL8_4 :
1027 value = fields->f_rel8_4;
1028 break;
1029 case XSTORMY16_OPERAND_WS2 :
1030 value = fields->f_op2m;
1031 break;
1032
1033 default :
1034 /* xgettext:c-format */
1035 fprintf (stderr, _("Unrecognized field %d while getting vma operand.\n"),
1036 opindex);
1037 abort ();
1038 }
1039
1040 return value;
1041}
1042
1043void xstormy16_cgen_set_int_operand
1044 PARAMS ((CGEN_CPU_DESC, int, CGEN_FIELDS *, int));
1045void xstormy16_cgen_set_vma_operand
1046 PARAMS ((CGEN_CPU_DESC, int, CGEN_FIELDS *, bfd_vma));
1047
1048/* Stuffing values in cgen_fields is handled by a collection of functions.
1049 They are distinguished by the type of the VALUE argument they accept.
1050 TODO: floating point, inlining support, remove cases where argument type
1051 not appropriate. */
1052
1053void
1054xstormy16_cgen_set_int_operand (cd, opindex, fields, value)
1055 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
1056 int opindex;
1057 CGEN_FIELDS * fields;
1058 int value;
1059{
1060 switch (opindex)
1061 {
1062 case XSTORMY16_OPERAND_RB :
1063 fields->f_Rb = value;
1064 break;
1065 case XSTORMY16_OPERAND_RBJ :
1066 fields->f_Rbj = value;
1067 break;
1068 case XSTORMY16_OPERAND_RD :
1069 fields->f_Rd = value;
1070 break;
1071 case XSTORMY16_OPERAND_RDM :
1072 fields->f_Rdm = value;
1073 break;
1074 case XSTORMY16_OPERAND_RM :
1075 fields->f_Rm = value;
1076 break;
1077 case XSTORMY16_OPERAND_RS :
1078 fields->f_Rs = value;
1079 break;
1080 case XSTORMY16_OPERAND_ABS24 :
1081 fields->f_abs24 = value;
1082 break;
1083 case XSTORMY16_OPERAND_BCOND2 :
1084 fields->f_op2 = value;
1085 break;
1086 case XSTORMY16_OPERAND_BCOND5 :
1087 fields->f_op5 = value;
1088 break;
1089 case XSTORMY16_OPERAND_HMEM8 :
1090 fields->f_hmem8 = value;
1091 break;
1092 case XSTORMY16_OPERAND_IMM12 :
1093 fields->f_imm12 = value;
1094 break;
1095 case XSTORMY16_OPERAND_IMM16 :
1096 fields->f_imm16 = value;
1097 break;
1098 case XSTORMY16_OPERAND_IMM2 :
1099 fields->f_imm2 = value;
1100 break;
1101 case XSTORMY16_OPERAND_IMM3 :
1102 fields->f_imm3 = value;
1103 break;
1104 case XSTORMY16_OPERAND_IMM3B :
1105 fields->f_imm3b = value;
1106 break;
1107 case XSTORMY16_OPERAND_IMM4 :
1108 fields->f_imm4 = value;
1109 break;
1110 case XSTORMY16_OPERAND_IMM8 :
1111 fields->f_imm8 = value;
1112 break;
1113 case XSTORMY16_OPERAND_IMM8SMALL :
1114 fields->f_imm8 = value;
1115 break;
1116 case XSTORMY16_OPERAND_LMEM8 :
1117 fields->f_lmem8 = value;
1118 break;
1119 case XSTORMY16_OPERAND_REL12 :
1120 fields->f_rel12 = value;
1121 break;
1122 case XSTORMY16_OPERAND_REL12A :
1123 fields->f_rel12a = value;
1124 break;
1125 case XSTORMY16_OPERAND_REL8_2 :
1126 fields->f_rel8_2 = value;
1127 break;
1128 case XSTORMY16_OPERAND_REL8_4 :
1129 fields->f_rel8_4 = value;
1130 break;
1131 case XSTORMY16_OPERAND_WS2 :
1132 fields->f_op2m = value;
1133 break;
1134
1135 default :
1136 /* xgettext:c-format */
1137 fprintf (stderr, _("Unrecognized field %d while setting int operand.\n"),
1138 opindex);
1139 abort ();
1140 }
1141}
1142
1143void
1144xstormy16_cgen_set_vma_operand (cd, opindex, fields, value)
1145 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
1146 int opindex;
1147 CGEN_FIELDS * fields;
1148 bfd_vma value;
1149{
1150 switch (opindex)
1151 {
1152 case XSTORMY16_OPERAND_RB :
1153 fields->f_Rb = value;
1154 break;
1155 case XSTORMY16_OPERAND_RBJ :
1156 fields->f_Rbj = value;
1157 break;
1158 case XSTORMY16_OPERAND_RD :
1159 fields->f_Rd = value;
1160 break;
1161 case XSTORMY16_OPERAND_RDM :
1162 fields->f_Rdm = value;
1163 break;
1164 case XSTORMY16_OPERAND_RM :
1165 fields->f_Rm = value;
1166 break;
1167 case XSTORMY16_OPERAND_RS :
1168 fields->f_Rs = value;
1169 break;
1170 case XSTORMY16_OPERAND_ABS24 :
1171 fields->f_abs24 = value;
1172 break;
1173 case XSTORMY16_OPERAND_BCOND2 :
1174 fields->f_op2 = value;
1175 break;
1176 case XSTORMY16_OPERAND_BCOND5 :
1177 fields->f_op5 = value;
1178 break;
1179 case XSTORMY16_OPERAND_HMEM8 :
1180 fields->f_hmem8 = value;
1181 break;
1182 case XSTORMY16_OPERAND_IMM12 :
1183 fields->f_imm12 = value;
1184 break;
1185 case XSTORMY16_OPERAND_IMM16 :
1186 fields->f_imm16 = value;
1187 break;
1188 case XSTORMY16_OPERAND_IMM2 :
1189 fields->f_imm2 = value;
1190 break;
1191 case XSTORMY16_OPERAND_IMM3 :
1192 fields->f_imm3 = value;
1193 break;
1194 case XSTORMY16_OPERAND_IMM3B :
1195 fields->f_imm3b = value;
1196 break;
1197 case XSTORMY16_OPERAND_IMM4 :
1198 fields->f_imm4 = value;
1199 break;
1200 case XSTORMY16_OPERAND_IMM8 :
1201 fields->f_imm8 = value;
1202 break;
1203 case XSTORMY16_OPERAND_IMM8SMALL :
1204 fields->f_imm8 = value;
1205 break;
1206 case XSTORMY16_OPERAND_LMEM8 :
1207 fields->f_lmem8 = value;
1208 break;
1209 case XSTORMY16_OPERAND_REL12 :
1210 fields->f_rel12 = value;
1211 break;
1212 case XSTORMY16_OPERAND_REL12A :
1213 fields->f_rel12a = value;
1214 break;
1215 case XSTORMY16_OPERAND_REL8_2 :
1216 fields->f_rel8_2 = value;
1217 break;
1218 case XSTORMY16_OPERAND_REL8_4 :
1219 fields->f_rel8_4 = value;
1220 break;
1221 case XSTORMY16_OPERAND_WS2 :
1222 fields->f_op2m = value;
1223 break;
1224
1225 default :
1226 /* xgettext:c-format */
1227 fprintf (stderr, _("Unrecognized field %d while setting vma operand.\n"),
1228 opindex);
1229 abort ();
1230 }
1231}
1232
1233/* Function to call before using the instruction builder tables. */
1234
1235void
1236xstormy16_cgen_init_ibld_table (cd)
1237 CGEN_CPU_DESC cd;
1238{
1239 cd->insert_handlers = & xstormy16_cgen_insert_handlers[0];
1240 cd->extract_handlers = & xstormy16_cgen_extract_handlers[0];
1241
1242 cd->insert_operand = xstormy16_cgen_insert_operand;
1243 cd->extract_operand = xstormy16_cgen_extract_operand;
1244
1245 cd->get_int_operand = xstormy16_cgen_get_int_operand;
1246 cd->set_int_operand = xstormy16_cgen_set_int_operand;
1247 cd->get_vma_operand = xstormy16_cgen_get_vma_operand;
1248 cd->set_vma_operand = xstormy16_cgen_set_vma_operand;
1249}
Note: See TracBrowser for help on using the repository browser.