185815Sobrien/* Instruction building/extraction support for @arch@. -*- C -*- 285815Sobrien 3218822Sdim THIS FILE IS MACHINE GENERATED WITH CGEN: Cpu tools GENerator. 4218822Sdim - the resultant file is machine generated, cgen-ibld.in isn't 585815Sobrien 6218822Sdim Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2005, 2006 7218822Sdim Free Software Foundation, Inc. 885815Sobrien 9218822Sdim This file is part of the GNU Binutils and GDB, the GNU debugger. 1085815Sobrien 11218822Sdim This program is free software; you can redistribute it and/or modify 12218822Sdim it under the terms of the GNU General Public License as published by 13218822Sdim the Free Software Foundation; either version 2, or (at your option) 14218822Sdim any later version. 1585815Sobrien 16218822Sdim This program is distributed in the hope that it will be useful, 17218822Sdim but WITHOUT ANY WARRANTY; without even the implied warranty of 18218822Sdim MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19218822Sdim GNU General Public License for more details. 2085815Sobrien 21218822Sdim You should have received a copy of the GNU General Public License 22218822Sdim along with this program; if not, write to the Free Software Foundation, Inc., 23218822Sdim 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 2485815Sobrien 2585815Sobrien/* ??? Eventually more and more of this stuff can go to cpu-independent files. 2685815Sobrien Keep that in mind. */ 2785815Sobrien 2885815Sobrien#include "sysdep.h" 2985815Sobrien#include <stdio.h> 3085815Sobrien#include "ansidecl.h" 3185815Sobrien#include "dis-asm.h" 3285815Sobrien#include "bfd.h" 3385815Sobrien#include "symcat.h" 3485815Sobrien#include "@prefix@-desc.h" 3585815Sobrien#include "@prefix@-opc.h" 3685815Sobrien#include "opintl.h" 3789857Sobrien#include "safe-ctype.h" 3885815Sobrien 39218822Sdim#undef min 4085815Sobrien#define min(a,b) ((a) < (b) ? (a) : (b)) 41218822Sdim#undef max 4285815Sobrien#define max(a,b) ((a) > (b) ? (a) : (b)) 4385815Sobrien 4485815Sobrien/* Used by the ifield rtx function. */ 4585815Sobrien#define FLD(f) (fields->f) 4685815Sobrien 4785815Sobrienstatic const char * insert_normal 48130561Sobrien (CGEN_CPU_DESC, long, unsigned int, unsigned int, unsigned int, 49130561Sobrien unsigned int, unsigned int, unsigned int, CGEN_INSN_BYTES_PTR); 5085815Sobrienstatic const char * insert_insn_normal 51130561Sobrien (CGEN_CPU_DESC, const CGEN_INSN *, 52130561Sobrien CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma); 5385815Sobrienstatic int extract_normal 54130561Sobrien (CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, CGEN_INSN_INT, 55130561Sobrien unsigned int, unsigned int, unsigned int, unsigned int, 56130561Sobrien unsigned int, unsigned int, bfd_vma, long *); 5785815Sobrienstatic int extract_insn_normal 58130561Sobrien (CGEN_CPU_DESC, const CGEN_INSN *, CGEN_EXTRACT_INFO *, 59130561Sobrien CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma); 6089857Sobrien#if CGEN_INT_INSN_P 6185815Sobrienstatic void put_insn_int_value 62130561Sobrien (CGEN_CPU_DESC, CGEN_INSN_BYTES_PTR, int, int, CGEN_INSN_INT); 6389857Sobrien#endif 6489857Sobrien#if ! CGEN_INT_INSN_P 6589857Sobrienstatic CGEN_INLINE void insert_1 66130561Sobrien (CGEN_CPU_DESC, unsigned long, int, int, int, unsigned char *); 6789857Sobrienstatic CGEN_INLINE int fill_cache 68130561Sobrien (CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, int, int, bfd_vma); 6989857Sobrienstatic CGEN_INLINE long extract_1 70130561Sobrien (CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, int, int, int, unsigned char *, bfd_vma); 7189857Sobrien#endif 7285815Sobrien 7385815Sobrien/* Operand insertion. */ 7485815Sobrien 7585815Sobrien#if ! CGEN_INT_INSN_P 7685815Sobrien 7785815Sobrien/* Subroutine of insert_normal. */ 7885815Sobrien 7985815Sobrienstatic CGEN_INLINE void 80130561Sobrieninsert_1 (CGEN_CPU_DESC cd, 81130561Sobrien unsigned long value, 82130561Sobrien int start, 83130561Sobrien int length, 84130561Sobrien int word_length, 85130561Sobrien unsigned char *bufp) 8685815Sobrien{ 8785815Sobrien unsigned long x,mask; 8885815Sobrien int shift; 8985815Sobrien 9089857Sobrien x = cgen_get_insn_value (cd, bufp, word_length); 9185815Sobrien 9285815Sobrien /* Written this way to avoid undefined behaviour. */ 9385815Sobrien mask = (((1L << (length - 1)) - 1) << 1) | 1; 9485815Sobrien if (CGEN_INSN_LSB0_P) 9585815Sobrien shift = (start + 1) - length; 9685815Sobrien else 9785815Sobrien shift = (word_length - (start + length)); 9885815Sobrien x = (x & ~(mask << shift)) | ((value & mask) << shift); 9985815Sobrien 10089857Sobrien cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x); 10185815Sobrien} 10285815Sobrien 10385815Sobrien#endif /* ! CGEN_INT_INSN_P */ 10485815Sobrien 10585815Sobrien/* Default insertion routine. 10685815Sobrien 10785815Sobrien ATTRS is a mask of the boolean attributes. 10885815Sobrien WORD_OFFSET is the offset in bits from the start of the insn of the value. 10985815Sobrien WORD_LENGTH is the length of the word in bits in which the value resides. 11085815Sobrien START is the starting bit number in the word, architecture origin. 11185815Sobrien LENGTH is the length of VALUE in bits. 11285815Sobrien TOTAL_LENGTH is the total length of the insn in bits. 11385815Sobrien 11485815Sobrien The result is an error message or NULL if success. */ 11585815Sobrien 11685815Sobrien/* ??? This duplicates functionality with bfd's howto table and 11785815Sobrien bfd_install_relocation. */ 11885815Sobrien/* ??? This doesn't handle bfd_vma's. Create another function when 11985815Sobrien necessary. */ 12085815Sobrien 12185815Sobrienstatic const char * 122130561Sobrieninsert_normal (CGEN_CPU_DESC cd, 123130561Sobrien long value, 124130561Sobrien unsigned int attrs, 125130561Sobrien unsigned int word_offset, 126130561Sobrien unsigned int start, 127130561Sobrien unsigned int length, 128130561Sobrien unsigned int word_length, 129130561Sobrien unsigned int total_length, 130130561Sobrien CGEN_INSN_BYTES_PTR buffer) 13185815Sobrien{ 13285815Sobrien static char errbuf[100]; 13385815Sobrien /* Written this way to avoid undefined behaviour. */ 13485815Sobrien unsigned long mask = (((1L << (length - 1)) - 1) << 1) | 1; 13585815Sobrien 13685815Sobrien /* If LENGTH is zero, this operand doesn't contribute to the value. */ 13785815Sobrien if (length == 0) 13885815Sobrien return NULL; 13985815Sobrien 14085815Sobrien if (word_length > 32) 14185815Sobrien abort (); 14285815Sobrien 14385815Sobrien /* For architectures with insns smaller than the base-insn-bitsize, 14485815Sobrien word_length may be too big. */ 14585815Sobrien if (cd->min_insn_bitsize < cd->base_insn_bitsize) 14685815Sobrien { 14785815Sobrien if (word_offset == 0 14885815Sobrien && word_length > total_length) 14985815Sobrien word_length = total_length; 15085815Sobrien } 15185815Sobrien 15285815Sobrien /* Ensure VALUE will fit. */ 15389857Sobrien if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGN_OPT)) 15485815Sobrien { 15589857Sobrien long minval = - (1L << (length - 1)); 15685815Sobrien unsigned long maxval = mask; 15785815Sobrien 15889857Sobrien if ((value > 0 && (unsigned long) value > maxval) 15989857Sobrien || value < minval) 16089857Sobrien { 16189857Sobrien /* xgettext:c-format */ 16289857Sobrien sprintf (errbuf, 16389857Sobrien _("operand out of range (%ld not between %ld and %lu)"), 16489857Sobrien value, minval, maxval); 16589857Sobrien return errbuf; 16689857Sobrien } 16789857Sobrien } 16889857Sobrien else if (! CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED)) 16989857Sobrien { 17089857Sobrien unsigned long maxval = mask; 171218822Sdim unsigned long val = (unsigned long) value; 172218822Sdim 173218822Sdim /* For hosts with a word size > 32 check to see if value has been sign 174218822Sdim extended beyond 32 bits. If so then ignore these higher sign bits 175218822Sdim as the user is attempting to store a 32-bit signed value into an 176218822Sdim unsigned 32-bit field which is allowed. */ 177218822Sdim if (sizeof (unsigned long) > 4 && ((value >> 32) == -1)) 178218822Sdim val &= 0xFFFFFFFF; 179218822Sdim 180218822Sdim if (val > maxval) 18185815Sobrien { 18285815Sobrien /* xgettext:c-format */ 18385815Sobrien sprintf (errbuf, 184218822Sdim _("operand out of range (0x%lx not between 0 and 0x%lx)"), 185218822Sdim val, maxval); 18685815Sobrien return errbuf; 18785815Sobrien } 18885815Sobrien } 18985815Sobrien else 19085815Sobrien { 19185815Sobrien if (! cgen_signed_overflow_ok_p (cd)) 19285815Sobrien { 19385815Sobrien long minval = - (1L << (length - 1)); 19485815Sobrien long maxval = (1L << (length - 1)) - 1; 19585815Sobrien 19685815Sobrien if (value < minval || value > maxval) 19785815Sobrien { 19885815Sobrien sprintf 19985815Sobrien /* xgettext:c-format */ 20085815Sobrien (errbuf, _("operand out of range (%ld not between %ld and %ld)"), 20185815Sobrien value, minval, maxval); 20285815Sobrien return errbuf; 20385815Sobrien } 20485815Sobrien } 20585815Sobrien } 20685815Sobrien 20785815Sobrien#if CGEN_INT_INSN_P 20885815Sobrien 20985815Sobrien { 21085815Sobrien int shift; 21185815Sobrien 21285815Sobrien if (CGEN_INSN_LSB0_P) 21385815Sobrien shift = (word_offset + start + 1) - length; 21485815Sobrien else 21585815Sobrien shift = total_length - (word_offset + start + length); 21685815Sobrien *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift); 21785815Sobrien } 21885815Sobrien 21985815Sobrien#else /* ! CGEN_INT_INSN_P */ 22085815Sobrien 22185815Sobrien { 22285815Sobrien unsigned char *bufp = (unsigned char *) buffer + word_offset / 8; 22385815Sobrien 22485815Sobrien insert_1 (cd, value, start, length, word_length, bufp); 22585815Sobrien } 22685815Sobrien 22785815Sobrien#endif /* ! CGEN_INT_INSN_P */ 22885815Sobrien 22985815Sobrien return NULL; 23085815Sobrien} 23185815Sobrien 23285815Sobrien/* Default insn builder (insert handler). 23389857Sobrien The instruction is recorded in CGEN_INT_INSN_P byte order (meaning 23489857Sobrien that if CGEN_INSN_BYTES_PTR is an int * and thus, the value is 23589857Sobrien recorded in host byte order, otherwise BUFFER is an array of bytes 23689857Sobrien and the value is recorded in target byte order). 23785815Sobrien The result is an error message or NULL if success. */ 23885815Sobrien 23985815Sobrienstatic const char * 240130561Sobrieninsert_insn_normal (CGEN_CPU_DESC cd, 241130561Sobrien const CGEN_INSN * insn, 242130561Sobrien CGEN_FIELDS * fields, 243130561Sobrien CGEN_INSN_BYTES_PTR buffer, 244130561Sobrien bfd_vma pc) 24585815Sobrien{ 24685815Sobrien const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn); 24785815Sobrien unsigned long value; 24885815Sobrien const CGEN_SYNTAX_CHAR_TYPE * syn; 24985815Sobrien 25085815Sobrien CGEN_INIT_INSERT (cd); 25185815Sobrien value = CGEN_INSN_BASE_VALUE (insn); 25285815Sobrien 25385815Sobrien /* If we're recording insns as numbers (rather than a string of bytes), 25485815Sobrien target byte order handling is deferred until later. */ 25585815Sobrien 25685815Sobrien#if CGEN_INT_INSN_P 25785815Sobrien 25885815Sobrien put_insn_int_value (cd, buffer, cd->base_insn_bitsize, 25985815Sobrien CGEN_FIELDS_BITSIZE (fields), value); 26085815Sobrien 26185815Sobrien#else 26285815Sobrien 26389857Sobrien cgen_put_insn_value (cd, buffer, min ((unsigned) cd->base_insn_bitsize, 26489857Sobrien (unsigned) CGEN_FIELDS_BITSIZE (fields)), 26585815Sobrien value); 26685815Sobrien 26785815Sobrien#endif /* ! CGEN_INT_INSN_P */ 26885815Sobrien 26985815Sobrien /* ??? It would be better to scan the format's fields. 27085815Sobrien Still need to be able to insert a value based on the operand though; 27185815Sobrien e.g. storing a branch displacement that got resolved later. 27285815Sobrien Needs more thought first. */ 27385815Sobrien 27485815Sobrien for (syn = CGEN_SYNTAX_STRING (syntax); * syn; ++ syn) 27585815Sobrien { 27685815Sobrien const char *errmsg; 27785815Sobrien 27885815Sobrien if (CGEN_SYNTAX_CHAR_P (* syn)) 27985815Sobrien continue; 28085815Sobrien 28185815Sobrien errmsg = (* cd->insert_operand) (cd, CGEN_SYNTAX_FIELD (*syn), 28285815Sobrien fields, buffer, pc); 28385815Sobrien if (errmsg) 28485815Sobrien return errmsg; 28585815Sobrien } 28685815Sobrien 28785815Sobrien return NULL; 28885815Sobrien} 28985815Sobrien 29089857Sobrien#if CGEN_INT_INSN_P 29185815Sobrien/* Cover function to store an insn value into an integral insn. Must go here 292218822Sdim because it needs <prefix>-desc.h for CGEN_INT_INSN_P. */ 29385815Sobrien 29485815Sobrienstatic void 295130561Sobrienput_insn_int_value (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 296130561Sobrien CGEN_INSN_BYTES_PTR buf, 297130561Sobrien int length, 298130561Sobrien int insn_length, 299130561Sobrien CGEN_INSN_INT value) 30085815Sobrien{ 30185815Sobrien /* For architectures with insns smaller than the base-insn-bitsize, 30285815Sobrien length may be too big. */ 30385815Sobrien if (length > insn_length) 30485815Sobrien *buf = value; 30585815Sobrien else 30685815Sobrien { 30785815Sobrien int shift = insn_length - length; 30885815Sobrien /* Written this way to avoid undefined behaviour. */ 30985815Sobrien CGEN_INSN_INT mask = (((1L << (length - 1)) - 1) << 1) | 1; 310218822Sdim 31185815Sobrien *buf = (*buf & ~(mask << shift)) | ((value & mask) << shift); 31285815Sobrien } 31385815Sobrien} 31489857Sobrien#endif 31585815Sobrien 31685815Sobrien/* Operand extraction. */ 31785815Sobrien 31885815Sobrien#if ! CGEN_INT_INSN_P 31985815Sobrien 32085815Sobrien/* Subroutine of extract_normal. 32185815Sobrien Ensure sufficient bytes are cached in EX_INFO. 32285815Sobrien OFFSET is the offset in bytes from the start of the insn of the value. 32385815Sobrien BYTES is the length of the needed value. 32485815Sobrien Returns 1 for success, 0 for failure. */ 32585815Sobrien 32685815Sobrienstatic CGEN_INLINE int 327130561Sobrienfill_cache (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 328130561Sobrien CGEN_EXTRACT_INFO *ex_info, 329130561Sobrien int offset, 330130561Sobrien int bytes, 331130561Sobrien bfd_vma pc) 33285815Sobrien{ 33385815Sobrien /* It's doubtful that the middle part has already been fetched so 33485815Sobrien we don't optimize that case. kiss. */ 33589857Sobrien unsigned int mask; 33685815Sobrien disassemble_info *info = (disassemble_info *) ex_info->dis_info; 33785815Sobrien 33885815Sobrien /* First do a quick check. */ 33985815Sobrien mask = (1 << bytes) - 1; 34085815Sobrien if (((ex_info->valid >> offset) & mask) == mask) 34185815Sobrien return 1; 34285815Sobrien 34385815Sobrien /* Search for the first byte we need to read. */ 34485815Sobrien for (mask = 1 << offset; bytes > 0; --bytes, ++offset, mask <<= 1) 34585815Sobrien if (! (mask & ex_info->valid)) 34685815Sobrien break; 34785815Sobrien 34885815Sobrien if (bytes) 34985815Sobrien { 35085815Sobrien int status; 35185815Sobrien 35285815Sobrien pc += offset; 35385815Sobrien status = (*info->read_memory_func) 35485815Sobrien (pc, ex_info->insn_bytes + offset, bytes, info); 35585815Sobrien 35685815Sobrien if (status != 0) 35785815Sobrien { 35885815Sobrien (*info->memory_error_func) (status, pc, info); 35985815Sobrien return 0; 36085815Sobrien } 36185815Sobrien 36285815Sobrien ex_info->valid |= ((1 << bytes) - 1) << offset; 36385815Sobrien } 36485815Sobrien 36585815Sobrien return 1; 36685815Sobrien} 36785815Sobrien 36885815Sobrien/* Subroutine of extract_normal. */ 36985815Sobrien 37085815Sobrienstatic CGEN_INLINE long 371130561Sobrienextract_1 (CGEN_CPU_DESC cd, 372130561Sobrien CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED, 373130561Sobrien int start, 374130561Sobrien int length, 375130561Sobrien int word_length, 376130561Sobrien unsigned char *bufp, 377130561Sobrien bfd_vma pc ATTRIBUTE_UNUSED) 37885815Sobrien{ 37985815Sobrien unsigned long x; 38085815Sobrien int shift; 381218822Sdim 38289857Sobrien x = cgen_get_insn_value (cd, bufp, word_length); 38385815Sobrien 38485815Sobrien if (CGEN_INSN_LSB0_P) 38585815Sobrien shift = (start + 1) - length; 38685815Sobrien else 38785815Sobrien shift = (word_length - (start + length)); 38885815Sobrien return x >> shift; 38985815Sobrien} 39085815Sobrien 39185815Sobrien#endif /* ! CGEN_INT_INSN_P */ 39285815Sobrien 39385815Sobrien/* Default extraction routine. 39485815Sobrien 39585815Sobrien INSN_VALUE is the first base_insn_bitsize bits of the insn in host order, 39685815Sobrien or sometimes less for cases like the m32r where the base insn size is 32 39785815Sobrien but some insns are 16 bits. 39885815Sobrien ATTRS is a mask of the boolean attributes. We only need `SIGNED', 39985815Sobrien but for generality we take a bitmask of all of them. 40085815Sobrien WORD_OFFSET is the offset in bits from the start of the insn of the value. 40185815Sobrien WORD_LENGTH is the length of the word in bits in which the value resides. 40285815Sobrien START is the starting bit number in the word, architecture origin. 40385815Sobrien LENGTH is the length of VALUE in bits. 40485815Sobrien TOTAL_LENGTH is the total length of the insn in bits. 40585815Sobrien 40685815Sobrien Returns 1 for success, 0 for failure. */ 40785815Sobrien 40885815Sobrien/* ??? The return code isn't properly used. wip. */ 40985815Sobrien 41085815Sobrien/* ??? This doesn't handle bfd_vma's. Create another function when 41185815Sobrien necessary. */ 41285815Sobrien 41385815Sobrienstatic int 414130561Sobrienextract_normal (CGEN_CPU_DESC cd, 41585815Sobrien#if ! CGEN_INT_INSN_P 416130561Sobrien CGEN_EXTRACT_INFO *ex_info, 41785815Sobrien#else 418130561Sobrien CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED, 41985815Sobrien#endif 420130561Sobrien CGEN_INSN_INT insn_value, 421130561Sobrien unsigned int attrs, 422130561Sobrien unsigned int word_offset, 423130561Sobrien unsigned int start, 424130561Sobrien unsigned int length, 425130561Sobrien unsigned int word_length, 426130561Sobrien unsigned int total_length, 42785815Sobrien#if ! CGEN_INT_INSN_P 428130561Sobrien bfd_vma pc, 42985815Sobrien#else 430130561Sobrien bfd_vma pc ATTRIBUTE_UNUSED, 43185815Sobrien#endif 432130561Sobrien long *valuep) 43385815Sobrien{ 43489857Sobrien long value, mask; 43585815Sobrien 43685815Sobrien /* If LENGTH is zero, this operand doesn't contribute to the value 43785815Sobrien so give it a standard value of zero. */ 43885815Sobrien if (length == 0) 43985815Sobrien { 44085815Sobrien *valuep = 0; 44185815Sobrien return 1; 44285815Sobrien } 44385815Sobrien 44485815Sobrien if (word_length > 32) 44585815Sobrien abort (); 44685815Sobrien 44785815Sobrien /* For architectures with insns smaller than the insn-base-bitsize, 44885815Sobrien word_length may be too big. */ 44985815Sobrien if (cd->min_insn_bitsize < cd->base_insn_bitsize) 45085815Sobrien { 451218822Sdim if (word_offset + word_length > total_length) 452218822Sdim word_length = total_length - word_offset; 45385815Sobrien } 45485815Sobrien 45589857Sobrien /* Does the value reside in INSN_VALUE, and at the right alignment? */ 45685815Sobrien 45789857Sobrien if (CGEN_INT_INSN_P || (word_offset == 0 && word_length == total_length)) 45885815Sobrien { 45985815Sobrien if (CGEN_INSN_LSB0_P) 46085815Sobrien value = insn_value >> ((word_offset + start + 1) - length); 46185815Sobrien else 46285815Sobrien value = insn_value >> (total_length - ( word_offset + start + length)); 46385815Sobrien } 46485815Sobrien 46585815Sobrien#if ! CGEN_INT_INSN_P 46685815Sobrien 46785815Sobrien else 46885815Sobrien { 46985815Sobrien unsigned char *bufp = ex_info->insn_bytes + word_offset / 8; 47085815Sobrien 47185815Sobrien if (word_length > 32) 47285815Sobrien abort (); 47385815Sobrien 47485815Sobrien if (fill_cache (cd, ex_info, word_offset / 8, word_length / 8, pc) == 0) 47585815Sobrien return 0; 47685815Sobrien 47785815Sobrien value = extract_1 (cd, ex_info, start, length, word_length, bufp, pc); 47885815Sobrien } 47985815Sobrien 48085815Sobrien#endif /* ! CGEN_INT_INSN_P */ 48185815Sobrien 48285815Sobrien /* Written this way to avoid undefined behaviour. */ 48385815Sobrien mask = (((1L << (length - 1)) - 1) << 1) | 1; 48485815Sobrien 48585815Sobrien value &= mask; 48685815Sobrien /* sign extend? */ 48785815Sobrien if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED) 48885815Sobrien && (value & (1L << (length - 1)))) 48985815Sobrien value |= ~mask; 49085815Sobrien 49185815Sobrien *valuep = value; 49285815Sobrien 49385815Sobrien return 1; 49485815Sobrien} 49585815Sobrien 49685815Sobrien/* Default insn extractor. 49785815Sobrien 49885815Sobrien INSN_VALUE is the first base_insn_bitsize bits, translated to host order. 49985815Sobrien The extracted fields are stored in FIELDS. 50085815Sobrien EX_INFO is used to handle reading variable length insns. 50185815Sobrien Return the length of the insn in bits, or 0 if no match, 50285815Sobrien or -1 if an error occurs fetching data (memory_error_func will have 50385815Sobrien been called). */ 50485815Sobrien 50585815Sobrienstatic int 506130561Sobrienextract_insn_normal (CGEN_CPU_DESC cd, 507130561Sobrien const CGEN_INSN *insn, 508130561Sobrien CGEN_EXTRACT_INFO *ex_info, 509130561Sobrien CGEN_INSN_INT insn_value, 510130561Sobrien CGEN_FIELDS *fields, 511130561Sobrien bfd_vma pc) 51285815Sobrien{ 51385815Sobrien const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn); 51485815Sobrien const CGEN_SYNTAX_CHAR_TYPE *syn; 51585815Sobrien 51685815Sobrien CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn); 51785815Sobrien 51885815Sobrien CGEN_INIT_EXTRACT (cd); 51985815Sobrien 52085815Sobrien for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn) 52185815Sobrien { 52285815Sobrien int length; 52385815Sobrien 52485815Sobrien if (CGEN_SYNTAX_CHAR_P (*syn)) 52585815Sobrien continue; 52685815Sobrien 52785815Sobrien length = (* cd->extract_operand) (cd, CGEN_SYNTAX_FIELD (*syn), 52885815Sobrien ex_info, insn_value, fields, pc); 52985815Sobrien if (length <= 0) 53085815Sobrien return length; 53185815Sobrien } 53285815Sobrien 53385815Sobrien /* We recognized and successfully extracted this insn. */ 53485815Sobrien return CGEN_INSN_BITSIZE (insn); 53585815Sobrien} 53685815Sobrien 537218822Sdim/* Machine generated code added here. */ 538