1 /* Instruction building/extraction support for @arch@. -*- C -*-
3 THIS FILE IS MACHINE GENERATED WITH CGEN: Cpu tools GENerator.
4 - the resultant file is machine generated, cgen-ibld.in isn't
6 Copyright 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
8 This file is part of the GNU Binutils and GDB, the GNU debugger.
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software Foundation, Inc.,
22 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
24 /* ??? Eventually more and more of this stuff can go to cpu-independent files.
33 #include "@prefix@-desc.h"
34 #include "@prefix@-opc.h"
36 #include "safe-ctype.h"
39 #define min(a,b) ((a) < (b) ? (a) : (b))
41 #define max(a,b) ((a) > (b) ? (a) : (b))
43 /* Used by the ifield rtx function. */
44 #define FLD(f) (fields->f)
46 static const char * insert_normal
47 (CGEN_CPU_DESC, long, unsigned int, unsigned int, unsigned int,
48 unsigned int, unsigned int, unsigned int, CGEN_INSN_BYTES_PTR);
49 static const char * insert_insn_normal
50 (CGEN_CPU_DESC, const CGEN_INSN *,
51 CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma);
52 static int extract_normal
53 (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 *);
56 static int extract_insn_normal
57 (CGEN_CPU_DESC, const CGEN_INSN *, CGEN_EXTRACT_INFO *,
58 CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma);
60 static void put_insn_int_value
61 (CGEN_CPU_DESC, CGEN_INSN_BYTES_PTR, int, int, CGEN_INSN_INT);
64 static CGEN_INLINE void insert_1
65 (CGEN_CPU_DESC, unsigned long, int, int, int, unsigned char *);
66 static CGEN_INLINE int fill_cache
67 (CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, int, int, bfd_vma);
68 static CGEN_INLINE long extract_1
69 (CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, int, int, int, unsigned char *, bfd_vma);
72 /* Operand insertion. */
76 /* Subroutine of insert_normal. */
78 static CGEN_INLINE void
79 insert_1 (CGEN_CPU_DESC cd,
81 int start,length,word_length,
87 x = cgen_get_insn_value (cd, bufp, word_length);
89 /* Written this way to avoid undefined behaviour. */
90 mask = (((1L << (length - 1)) - 1) << 1) | 1;
92 shift = (start + 1) - length;
94 shift = (word_length - (start + length));
95 x = (x & ~(mask << shift)) | ((value & mask) << shift);
97 cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x);
100 #endif /* ! CGEN_INT_INSN_P */
102 /* Default insertion routine.
104 ATTRS is a mask of the boolean attributes.
105 WORD_OFFSET is the offset in bits from the start of the insn of the value.
106 WORD_LENGTH is the length of the word in bits in which the value resides.
107 START is the starting bit number in the word, architecture origin.
108 LENGTH is the length of VALUE in bits.
109 TOTAL_LENGTH is the total length of the insn in bits.
111 The result is an error message or NULL if success. */
113 /* ??? This duplicates functionality with bfd's howto table and
114 bfd_install_relocation. */
115 /* ??? This doesn't handle bfd_vma's. Create another function when
119 insert_normal (CGEN_CPU_DESC cd,
122 unsigned int word_offset,
125 unsigned int word_length,
126 unsigned int total_length,
127 CGEN_INSN_BYTES_PTR buffer)
129 static char errbuf[100];
130 /* Written this way to avoid undefined behaviour. */
131 unsigned long mask = (((1L << (length - 1)) - 1) << 1) | 1;
133 /* If LENGTH is zero, this operand doesn't contribute to the value. */
143 if (word_length > 32)
146 /* For architectures with insns smaller than the base-insn-bitsize,
147 word_length may be too big. */
148 if (cd->min_insn_bitsize < cd->base_insn_bitsize)
151 && word_length > total_length)
152 word_length = total_length;
155 /* Ensure VALUE will fit. */
156 if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGN_OPT))
158 long minval = - (1L << (length - 1));
159 unsigned long maxval = mask;
161 if ((value > 0 && (unsigned long) value > maxval)
164 /* xgettext:c-format */
166 _("operand out of range (%ld not between %ld and %lu)"),
167 value, minval, maxval);
171 else if (! CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED))
173 unsigned long maxval = mask;
175 if ((unsigned long) value > maxval)
177 /* xgettext:c-format */
179 _("operand out of range (%lu not between 0 and %lu)"),
186 if (! cgen_signed_overflow_ok_p (cd))
188 long minval = - (1L << (length - 1));
189 long maxval = (1L << (length - 1)) - 1;
191 if (value < minval || value > maxval)
194 /* xgettext:c-format */
195 (errbuf, _("operand out of range (%ld not between %ld and %ld)"),
196 value, minval, maxval);
207 if (CGEN_INSN_LSB0_P)
208 shift = (word_offset + start + 1) - length;
210 shift = total_length - (word_offset + start + length);
211 *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
214 #else /* ! CGEN_INT_INSN_P */
217 unsigned char *bufp = (unsigned char *) buffer + word_offset / 8;
219 insert_1 (cd, value, start, length, word_length, bufp);
222 #endif /* ! CGEN_INT_INSN_P */
227 /* Default insn builder (insert handler).
228 The instruction is recorded in CGEN_INT_INSN_P byte order (meaning
229 that if CGEN_INSN_BYTES_PTR is an int * and thus, the value is
230 recorded in host byte order, otherwise BUFFER is an array of bytes
231 and the value is recorded in target byte order).
232 The result is an error message or NULL if success. */
235 insert_insn_normal (CGEN_CPU_DESC cd,
236 const CGEN_INSN * insn,
237 CGEN_FIELDS * fields,
238 CGEN_INSN_BYTES_PTR buffer,
241 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
243 const CGEN_SYNTAX_CHAR_TYPE * syn;
245 CGEN_INIT_INSERT (cd);
246 value = CGEN_INSN_BASE_VALUE (insn);
248 /* If we're recording insns as numbers (rather than a string of bytes),
249 target byte order handling is deferred until later. */
253 put_insn_int_value (cd, buffer, cd->base_insn_bitsize,
254 CGEN_FIELDS_BITSIZE (fields), value);
258 cgen_put_insn_value (cd, buffer, min ((unsigned) cd->base_insn_bitsize,
259 (unsigned) CGEN_FIELDS_BITSIZE (fields)),
262 #endif /* ! CGEN_INT_INSN_P */
264 /* ??? It would be better to scan the format's fields.
265 Still need to be able to insert a value based on the operand though;
266 e.g. storing a branch displacement that got resolved later.
267 Needs more thought first. */
269 for (syn = CGEN_SYNTAX_STRING (syntax); * syn; ++ syn)
273 if (CGEN_SYNTAX_CHAR_P (* syn))
276 errmsg = (* cd->insert_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
286 /* Cover function to store an insn value into an integral insn. Must go here
287 because it needs <prefix>-desc.h for CGEN_INT_INSN_P. */
290 put_insn_int_value (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
291 CGEN_INSN_BYTES_PTR buf,
296 /* For architectures with insns smaller than the base-insn-bitsize,
297 length may be too big. */
298 if (length > insn_length)
302 int shift = insn_length - length;
303 /* Written this way to avoid undefined behaviour. */
304 CGEN_INSN_INT mask = (((1L << (length - 1)) - 1) << 1) | 1;
305 *buf = (*buf & ~(mask << shift)) | ((value & mask) << shift);
310 /* Operand extraction. */
312 #if ! CGEN_INT_INSN_P
314 /* Subroutine of extract_normal.
315 Ensure sufficient bytes are cached in EX_INFO.
316 OFFSET is the offset in bytes from the start of the insn of the value.
317 BYTES is the length of the needed value.
318 Returns 1 for success, 0 for failure. */
320 static CGEN_INLINE int
321 fill_cache (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
322 CGEN_EXTRACT_INFO *ex_info,
326 /* It's doubtful that the middle part has already been fetched so
327 we don't optimize that case. kiss. */
329 disassemble_info *info = (disassemble_info *) ex_info->dis_info;
331 /* First do a quick check. */
332 mask = (1 << bytes) - 1;
333 if (((ex_info->valid >> offset) & mask) == mask)
336 /* Search for the first byte we need to read. */
337 for (mask = 1 << offset; bytes > 0; --bytes, ++offset, mask <<= 1)
338 if (! (mask & ex_info->valid))
346 status = (*info->read_memory_func)
347 (pc, ex_info->insn_bytes + offset, bytes, info);
351 (*info->memory_error_func) (status, pc, info);
355 ex_info->valid |= ((1 << bytes) - 1) << offset;
361 /* Subroutine of extract_normal. */
363 static CGEN_INLINE long
364 extract_1 (CGEN_CPU_DESC cd,
365 CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED,
370 bfd_vma pc ATTRIBUTE_UNUSED)
375 int big_p = CGEN_CPU_INSN_ENDIAN (cd) == CGEN_ENDIAN_BIG;
377 x = cgen_get_insn_value (cd, bufp, word_length);
379 if (CGEN_INSN_LSB0_P)
380 shift = (start + 1) - length;
382 shift = (word_length - (start + length));
386 #endif /* ! CGEN_INT_INSN_P */
388 /* Default extraction routine.
390 INSN_VALUE is the first base_insn_bitsize bits of the insn in host order,
391 or sometimes less for cases like the m32r where the base insn size is 32
392 but some insns are 16 bits.
393 ATTRS is a mask of the boolean attributes. We only need `SIGNED',
394 but for generality we take a bitmask of all of them.
395 WORD_OFFSET is the offset in bits from the start of the insn of the value.
396 WORD_LENGTH is the length of the word in bits in which the value resides.
397 START is the starting bit number in the word, architecture origin.
398 LENGTH is the length of VALUE in bits.
399 TOTAL_LENGTH is the total length of the insn in bits.
401 Returns 1 for success, 0 for failure. */
403 /* ??? The return code isn't properly used. wip. */
405 /* ??? This doesn't handle bfd_vma's. Create another function when
409 extract_normal (CGEN_CPU_DESC cd;
410 #if ! CGEN_INT_INSN_P
411 CGEN_EXTRACT_INFO *ex_info,
413 CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED,
415 CGEN_INSN_INT insn_value,
417 unsigned int word_offset,
420 unsigned int word_length,
421 unsigned int total_length,
422 #if ! CGEN_INT_INSN_P
425 bfd_vma pc ATTRIBUTE_UNUSED,
431 /* If LENGTH is zero, this operand doesn't contribute to the value
432 so give it a standard value of zero. */
445 if (word_length > 32)
448 /* For architectures with insns smaller than the insn-base-bitsize,
449 word_length may be too big. */
450 if (cd->min_insn_bitsize < cd->base_insn_bitsize)
453 && word_length > total_length)
454 word_length = total_length;
457 /* Does the value reside in INSN_VALUE, and at the right alignment? */
459 if (CGEN_INT_INSN_P || (word_offset == 0 && word_length == total_length))
461 if (CGEN_INSN_LSB0_P)
462 value = insn_value >> ((word_offset + start + 1) - length);
464 value = insn_value >> (total_length - ( word_offset + start + length));
467 #if ! CGEN_INT_INSN_P
471 unsigned char *bufp = ex_info->insn_bytes + word_offset / 8;
473 if (word_length > 32)
476 if (fill_cache (cd, ex_info, word_offset / 8, word_length / 8, pc) == 0)
479 value = extract_1 (cd, ex_info, start, length, word_length, bufp, pc);
482 #endif /* ! CGEN_INT_INSN_P */
484 /* Written this way to avoid undefined behaviour. */
485 mask = (((1L << (length - 1)) - 1) << 1) | 1;
489 if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED)
490 && (value & (1L << (length - 1))))
498 /* Default insn extractor.
500 INSN_VALUE is the first base_insn_bitsize bits, translated to host order.
501 The extracted fields are stored in FIELDS.
502 EX_INFO is used to handle reading variable length insns.
503 Return the length of the insn in bits, or 0 if no match,
504 or -1 if an error occurs fetching data (memory_error_func will have
508 extract_insn_normal (CGEN_CPU_DESC cd,
509 const CGEN_INSN *insn,
510 CGEN_EXTRACT_INFO *ex_info,
511 CGEN_INSN_INT insn_value,
515 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
516 const CGEN_SYNTAX_CHAR_TYPE *syn;
518 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
520 CGEN_INIT_EXTRACT (cd);
522 for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
526 if (CGEN_SYNTAX_CHAR_P (*syn))
529 length = (* cd->extract_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
530 ex_info, insn_value, fields, pc);
535 /* We recognized and successfully extracted this insn. */
536 return CGEN_INSN_BITSIZE (insn);
539 /* machine generated code added here */