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 (C) 1996, 1997, 1998, 1999, 2000 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.
34 #include "@prefix@-desc.h"
35 #include "@prefix@-opc.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 PARAMS ((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 PARAMS ((CGEN_CPU_DESC, const CGEN_INSN *,
51 CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma));
53 static int extract_normal
54 PARAMS ((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 *));
57 static int extract_insn_normal
58 PARAMS ((CGEN_CPU_DESC, const CGEN_INSN *, CGEN_EXTRACT_INFO *,
59 CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma));
61 /* Operand insertion. */
65 /* Subroutine of insert_normal. */
67 static CGEN_INLINE void
68 insert_1 (cd, value, start, length, word_length, bufp)
71 int start,length,word_length;
76 int big_p = CGEN_CPU_INSN_ENDIAN (cd) == CGEN_ENDIAN_BIG;
85 x = bfd_getb16 (bufp);
87 x = bfd_getl16 (bufp);
90 /* ??? This may need reworking as these cases don't necessarily
91 want the first byte and the last two bytes handled like this. */
93 x = (bufp[0] << 16) | bfd_getb16 (bufp + 1);
95 x = bfd_getl16 (bufp) | (bufp[2] << 16);
99 x = bfd_getb32 (bufp);
101 x = bfd_getl32 (bufp);
107 /* Written this way to avoid undefined behaviour. */
108 mask = (((1L << (length - 1)) - 1) << 1) | 1;
109 if (CGEN_INSN_LSB0_P)
110 shift = (start + 1) - length;
112 shift = (word_length - (start + length));
113 x = (x & ~(mask << shift)) | ((value & mask) << shift);
122 bfd_putb16 (x, bufp);
124 bfd_putl16 (x, bufp);
127 /* ??? This may need reworking as these cases don't necessarily
128 want the first byte and the last two bytes handled like this. */
132 bfd_putb16 (x, bufp + 1);
136 bfd_putl16 (x, bufp);
142 bfd_putb32 (x, bufp);
144 bfd_putl32 (x, bufp);
151 #endif /* ! CGEN_INT_INSN_P */
153 /* Default insertion routine.
155 ATTRS is a mask of the boolean attributes.
156 WORD_OFFSET is the offset in bits from the start of the insn of the value.
157 WORD_LENGTH is the length of the word in bits in which the value resides.
158 START is the starting bit number in the word, architecture origin.
159 LENGTH is the length of VALUE in bits.
160 TOTAL_LENGTH is the total length of the insn in bits.
162 The result is an error message or NULL if success. */
164 /* ??? This duplicates functionality with bfd's howto table and
165 bfd_install_relocation. */
166 /* ??? This doesn't handle bfd_vma's. Create another function when
170 insert_normal (cd, value, attrs, word_offset, start, length, word_length,
171 total_length, buffer)
175 unsigned int word_offset, start, length, word_length, total_length;
176 CGEN_INSN_BYTES_PTR buffer;
178 static char errbuf[100];
179 /* Written this way to avoid undefined behaviour. */
180 unsigned long mask = (((1L << (length - 1)) - 1) << 1) | 1;
182 /* If LENGTH is zero, this operand doesn't contribute to the value. */
190 if (word_length > 32)
193 /* For architectures with insns smaller than the base-insn-bitsize,
194 word_length may be too big. */
195 if (cd->min_insn_bitsize < cd->base_insn_bitsize)
198 && word_length > total_length)
199 word_length = total_length;
202 /* Ensure VALUE will fit. */
203 if (! CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED))
205 unsigned long maxval = mask;
207 if ((unsigned long) value > maxval)
209 /* xgettext:c-format */
211 _("operand out of range (%lu not between 0 and %lu)"),
218 if (! cgen_signed_overflow_ok_p (cd))
220 long minval = - (1L << (length - 1));
221 long maxval = (1L << (length - 1)) - 1;
223 if (value < minval || value > maxval)
226 /* xgettext:c-format */
227 (errbuf, _("operand out of range (%ld not between %ld and %ld)"),
228 value, minval, maxval);
239 if (CGEN_INSN_LSB0_P)
240 shift = (start + 1) - length;
242 shift = word_length - (start + length);
243 *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
246 #else /* ! CGEN_INT_INSN_P */
249 unsigned char *bufp = (unsigned char *) buffer + word_offset / 8;
251 insert_1 (cd, value, start, length, word_length, bufp);
254 #endif /* ! CGEN_INT_INSN_P */
259 /* Default insn builder (insert handler).
260 The instruction is recorded in CGEN_INT_INSN_P byte order
261 (meaning that if CGEN_INT_INSN_P BUFFER is an int * and thus the value is
262 recorded in host byte order, otherwise BUFFER is an array of bytes and the
263 value is recorded in target byte order).
264 The result is an error message or NULL if success. */
267 insert_insn_normal (cd, insn, fields, buffer, pc)
269 const CGEN_INSN * insn;
270 CGEN_FIELDS * fields;
271 CGEN_INSN_BYTES_PTR buffer;
274 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
276 const unsigned char * syn;
278 CGEN_INIT_INSERT (cd);
279 value = CGEN_INSN_BASE_VALUE (insn);
281 /* If we're recording insns as numbers (rather than a string of bytes),
282 target byte order handling is deferred until later. */
290 cgen_put_insn_value (cd, buffer, min (cd->base_insn_bitsize,
291 CGEN_FIELDS_BITSIZE (fields)),
294 #endif /* ! CGEN_INT_INSN_P */
296 /* ??? It would be better to scan the format's fields.
297 Still need to be able to insert a value based on the operand though;
298 e.g. storing a branch displacement that got resolved later.
299 Needs more thought first. */
301 for (syn = CGEN_SYNTAX_STRING (syntax); * syn != '\0'; ++ syn)
305 if (CGEN_SYNTAX_CHAR_P (* syn))
308 errmsg = (* cd->insert_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
317 /* Operand extraction. */
319 #if ! CGEN_INT_INSN_P
321 /* Subroutine of extract_normal.
322 Ensure sufficient bytes are cached in EX_INFO.
323 OFFSET is the offset in bytes from the start of the insn of the value.
324 BYTES is the length of the needed value.
325 Returns 1 for success, 0 for failure. */
327 static CGEN_INLINE int
328 fill_cache (cd, ex_info, offset, bytes, pc)
330 CGEN_EXTRACT_INFO *ex_info;
334 /* It's doubtful that the middle part has already been fetched so
335 we don't optimize that case. kiss. */
337 disassemble_info *info = (disassemble_info *) ex_info->dis_info;
339 /* First do a quick check. */
340 mask = (1 << bytes) - 1;
341 if (((ex_info->valid >> offset) & mask) == mask)
344 /* Search for the first byte we need to read. */
345 for (mask = 1 << offset; bytes > 0; --bytes, ++offset, mask <<= 1)
346 if (! (mask & ex_info->valid))
354 status = (*info->read_memory_func)
355 (pc, ex_info->insn_bytes + offset, bytes, info);
359 (*info->memory_error_func) (status, pc, info);
363 ex_info->valid |= ((1 << bytes) - 1) << offset;
369 /* Subroutine of extract_normal. */
371 static CGEN_INLINE long
372 extract_1 (cd, ex_info, start, length, word_length, bufp, pc)
374 CGEN_EXTRACT_INFO *ex_info;
375 int start,length,word_length;
379 unsigned long x,mask;
381 int big_p = CGEN_CPU_INSN_ENDIAN (cd) == CGEN_ENDIAN_BIG;
390 x = bfd_getb16 (bufp);
392 x = bfd_getl16 (bufp);
395 /* ??? This may need reworking as these cases don't necessarily
396 want the first byte and the last two bytes handled like this. */
398 x = (bufp[0] << 16) | bfd_getb16 (bufp + 1);
400 x = bfd_getl16 (bufp) | (bufp[2] << 16);
404 x = bfd_getb32 (bufp);
406 x = bfd_getl32 (bufp);
412 /* Written this way to avoid undefined behaviour. */
413 mask = (((1L << (length - 1)) - 1) << 1) | 1;
414 if (CGEN_INSN_LSB0_P)
415 shift = (start + 1) - length;
417 shift = (word_length - (start + length));
418 return (x >> shift) & mask;
421 #endif /* ! CGEN_INT_INSN_P */
423 /* Default extraction routine.
425 INSN_VALUE is the first base_insn_bitsize bits of the insn in host order,
426 or sometimes less for cases like the m32r where the base insn size is 32
427 but some insns are 16 bits.
428 ATTRS is a mask of the boolean attributes. We only need `SIGNED',
429 but for generality we take a bitmask of all of them.
430 WORD_OFFSET is the offset in bits from the start of the insn of the value.
431 WORD_LENGTH is the length of the word in bits in which the value resides.
432 START is the starting bit number in the word, architecture origin.
433 LENGTH is the length of VALUE in bits.
434 TOTAL_LENGTH is the total length of the insn in bits.
436 Returns 1 for success, 0 for failure. */
438 /* ??? The return code isn't properly used. wip. */
440 /* ??? This doesn't handle bfd_vma's. Create another function when
444 extract_normal (cd, ex_info, insn_value, attrs, word_offset, start, length,
445 word_length, total_length, pc, valuep)
447 #if ! CGEN_INT_INSN_P
448 CGEN_EXTRACT_INFO *ex_info;
450 CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED;
452 CGEN_INSN_INT insn_value;
454 unsigned int word_offset, start, length, word_length, total_length;
455 #if ! CGEN_INT_INSN_P
458 bfd_vma pc ATTRIBUTE_UNUSED;
464 /* If LENGTH is zero, this operand doesn't contribute to the value
465 so give it a standard value of zero. */
476 if (word_length > 32)
479 /* For architectures with insns smaller than the insn-base-bitsize,
480 word_length may be too big. */
481 if (cd->min_insn_bitsize < cd->base_insn_bitsize)
484 && word_length > total_length)
485 word_length = total_length;
488 /* Does the value reside in INSN_VALUE? */
490 if (word_offset == 0)
492 /* Written this way to avoid undefined behaviour. */
493 CGEN_INSN_INT mask = (((1L << (length - 1)) - 1) << 1) | 1;
495 if (CGEN_INSN_LSB0_P)
496 value = insn_value >> ((start + 1) - length);
498 value = insn_value >> (word_length - (start + length));
501 if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED)
502 && (value & (1L << (length - 1))))
506 #if ! CGEN_INT_INSN_P
510 unsigned char *bufp = ex_info->insn_bytes + word_offset / 8;
512 if (word_length > 32)
515 if (fill_cache (cd, ex_info, word_offset / 8, word_length / 8, pc) == 0)
518 value = extract_1 (cd, ex_info, start, length, word_length, bufp, pc);
521 #endif /* ! CGEN_INT_INSN_P */
528 /* Default insn extractor.
530 INSN_VALUE is the first base_insn_bitsize bits, translated to host order.
531 The extracted fields are stored in FIELDS.
532 EX_INFO is used to handle reading variable length insns.
533 Return the length of the insn in bits, or 0 if no match,
534 or -1 if an error occurs fetching data (memory_error_func will have
538 extract_insn_normal (cd, insn, ex_info, insn_value, fields, pc)
540 const CGEN_INSN *insn;
541 CGEN_EXTRACT_INFO *ex_info;
542 CGEN_INSN_INT insn_value;
546 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
547 const unsigned char *syn;
549 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
551 CGEN_INIT_EXTRACT (cd);
553 for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
557 if (CGEN_SYNTAX_CHAR_P (*syn))
560 length = (* cd->extract_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
561 ex_info, insn_value, fields, pc);
566 /* We recognized and successfully extracted this insn. */
567 return CGEN_INSN_BITSIZE (insn);
570 /* machine generated code added here */