X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=opcodes%2Ffr30-dis.c;h=c42915b8fe39e529c2916d82e95a5994f608d268;hb=0ed4f623e67138e6119a6ec85524f595d2b8306a;hp=f171395cbeafe912ab53b62c98743f21b65a8548;hpb=5730d39d2cd1974c77899555dac466babc316589;p=deliverable%2Fbinutils-gdb.git diff --git a/opcodes/fr30-dis.c b/opcodes/fr30-dis.c index f171395cbe..c42915b8fe 100644 --- a/opcodes/fr30-dis.c +++ b/opcodes/fr30-dis.c @@ -1,9 +1,10 @@ /* Disassembler interface for targets using CGEN. -*- C -*- CGEN: Cpu tools GENerator -THIS FILE IS USED TO GENERATE fr30-dis.c. +THIS FILE IS MACHINE GENERATED WITH CGEN. +- the resultant file is machine generated, cgen-dis.in isn't -Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. +Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU Binutils and GDB, the GNU debugger. @@ -21,50 +22,38 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* ??? Eventually more and more of this stuff can go to cpu-independent files. + Keep that in mind. */ + #include "sysdep.h" #include #include "ansidecl.h" #include "dis-asm.h" #include "bfd.h" #include "symcat.h" +#include "fr30-desc.h" #include "fr30-opc.h" #include "opintl.h" -#undef INLINE -#ifdef __GNUC__ -#define INLINE __inline__ -#else -#define INLINE -#endif - /* Default text to print if an instruction isn't recognized. */ #define UNKNOWN_INSN_MSG _("*unknown*") -/* Used by the ifield rtx function. */ -#define FLD(f) (fields->f) - -static int extract_normal - PARAMS ((CGEN_OPCODE_DESC, CGEN_EXTRACT_INFO *, CGEN_INSN_INT, - unsigned int, unsigned int, unsigned int, unsigned int, - unsigned int, unsigned int, bfd_vma, long *)); static void print_normal - PARAMS ((CGEN_OPCODE_DESC, PTR, long, unsigned int, bfd_vma, int)); + PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned int, bfd_vma, int)); static void print_address - PARAMS ((CGEN_OPCODE_DESC, PTR, bfd_vma, unsigned int, bfd_vma, int)); + PARAMS ((CGEN_CPU_DESC, PTR, bfd_vma, unsigned int, bfd_vma, int)); static void print_keyword - PARAMS ((CGEN_OPCODE_DESC, PTR, CGEN_KEYWORD *, long, unsigned int)); -static int extract_insn_normal - PARAMS ((CGEN_OPCODE_DESC, const CGEN_INSN *, CGEN_EXTRACT_INFO *, - CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma)); + PARAMS ((CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned int)); static void print_insn_normal - PARAMS ((CGEN_OPCODE_DESC, PTR, const CGEN_INSN *, CGEN_FIELDS *, + PARAMS ((CGEN_CPU_DESC, PTR, const CGEN_INSN *, CGEN_FIELDS *, bfd_vma, int)); -static int print_insn PARAMS ((CGEN_OPCODE_DESC, bfd_vma, +static int print_insn PARAMS ((CGEN_CPU_DESC, bfd_vma, disassemble_info *, char *, int)); static int default_print_insn - PARAMS ((CGEN_OPCODE_DESC, bfd_vma, disassemble_info *)); + PARAMS ((CGEN_CPU_DESC, bfd_vma, disassemble_info *)); /* -- disassembler routines inserted here */ + /* -- dis.c */ static void @@ -106,8 +95,8 @@ print_register_list (dis_info, value, offset, load_store) } static void -print_hi_register_list_ld (od, dis_info, value, attrs, pc, length) - CGEN_OPCODE_DESC od; +print_hi_register_list_ld (cd, dis_info, value, attrs, pc, length) + CGEN_CPU_DESC cd; PTR dis_info; long value; unsigned int attrs; @@ -118,8 +107,8 @@ print_hi_register_list_ld (od, dis_info, value, attrs, pc, length) } static void -print_low_register_list_ld (od, dis_info, value, attrs, pc, length) - CGEN_OPCODE_DESC od; +print_low_register_list_ld (cd, dis_info, value, attrs, pc, length) + CGEN_CPU_DESC cd; PTR dis_info; long value; unsigned int attrs; @@ -130,8 +119,8 @@ print_low_register_list_ld (od, dis_info, value, attrs, pc, length) } static void -print_hi_register_list_st (od, dis_info, value, attrs, pc, length) - CGEN_OPCODE_DESC od; +print_hi_register_list_st (cd, dis_info, value, attrs, pc, length) + CGEN_CPU_DESC cd; PTR dis_info; long value; unsigned int attrs; @@ -142,8 +131,8 @@ print_hi_register_list_st (od, dis_info, value, attrs, pc, length) } static void -print_low_register_list_st (od, dis_info, value, attrs, pc, length) - CGEN_OPCODE_DESC od; +print_low_register_list_st (cd, dis_info, value, attrs, pc, length) + CGEN_CPU_DESC cd; PTR dis_info; long value; unsigned int attrs; @@ -154,8 +143,8 @@ print_low_register_list_st (od, dis_info, value, attrs, pc, length) } static void -print_m4 (od, dis_info, value, attrs, pc, length) - CGEN_OPCODE_DESC od; +print_m4 (cd, dis_info, value, attrs, pc, length) + CGEN_CPU_DESC cd; PTR dis_info; long value; unsigned int attrs; @@ -167,7 +156,9 @@ print_m4 (od, dis_info, value, attrs, pc, length) } /* -- */ -/* Main entry point for operand extraction. +/* Main entry point for printing operands. + XINFO is a `void *' and not a `disassemble_info *' to not put a requirement + of dis-asm.h on cgen.h. This function is basically just a big switch statement. Earlier versions used tables to look up the function to use, but @@ -181,328 +172,127 @@ print_m4 (od, dis_info, value, attrs, pc, length) the handlers. */ -int -fr30_cgen_extract_operand (od, opindex, ex_info, insn_value, fields, pc) - CGEN_OPCODE_DESC od; +void +fr30_cgen_print_operand (cd, opindex, xinfo, fields, attrs, pc, length) + CGEN_CPU_DESC cd; int opindex; - CGEN_EXTRACT_INFO *ex_info; - CGEN_INSN_INT insn_value; - CGEN_FIELDS * fields; + PTR xinfo; + CGEN_FIELDS *fields; + void const *attrs; bfd_vma pc; + int length; { - int length; - unsigned int total_length = CGEN_FIELDS_BITSIZE (fields); + disassemble_info *info = (disassemble_info *) xinfo; switch (opindex) { - case FR30_OPERAND_RI : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_Ri); - break; - case FR30_OPERAND_RJ : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_Rj); - break; - case FR30_OPERAND_RIC : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_Ric); - break; - case FR30_OPERAND_RJC : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_Rjc); - break; case FR30_OPERAND_CRI : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_CRi); + print_keyword (cd, info, & fr30_cgen_opval_cr_names, fields->f_CRi, 0); break; case FR30_OPERAND_CRJ : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_CRj); - break; - case FR30_OPERAND_RS1 : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_Rs1); - break; - case FR30_OPERAND_RS2 : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_Rs2); + print_keyword (cd, info, & fr30_cgen_opval_cr_names, fields->f_CRj, 0); break; case FR30_OPERAND_R13 : - length = extract_normal (od, ex_info, insn_value, 0, 0, 0, 0, 0, total_length, pc, & fields->f_nil); + print_keyword (cd, info, & fr30_cgen_opval_h_r13, 0, 0); break; case FR30_OPERAND_R14 : - length = extract_normal (od, ex_info, insn_value, 0, 0, 0, 0, 0, total_length, pc, & fields->f_nil); + print_keyword (cd, info, & fr30_cgen_opval_h_r14, 0, 0); break; case FR30_OPERAND_R15 : - length = extract_normal (od, ex_info, insn_value, 0, 0, 0, 0, 0, total_length, pc, & fields->f_nil); + print_keyword (cd, info, & fr30_cgen_opval_h_r15, 0, 0); break; - case FR30_OPERAND_PS : - length = extract_normal (od, ex_info, insn_value, 0, 0, 0, 0, 0, total_length, pc, & fields->f_nil); + case FR30_OPERAND_RI : + print_keyword (cd, info, & fr30_cgen_opval_gr_names, fields->f_Ri, 0); break; - case FR30_OPERAND_U4 : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_u4); + case FR30_OPERAND_RIC : + print_keyword (cd, info, & fr30_cgen_opval_gr_names, fields->f_Ric, 0); break; - case FR30_OPERAND_U4C : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_u4c); + case FR30_OPERAND_RJ : + print_keyword (cd, info, & fr30_cgen_opval_gr_names, fields->f_Rj, 0); break; - case FR30_OPERAND_U8 : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_u8); + case FR30_OPERAND_RJC : + print_keyword (cd, info, & fr30_cgen_opval_gr_names, fields->f_Rjc, 0); break; - case FR30_OPERAND_I8 : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_i8); + case FR30_OPERAND_RS1 : + print_keyword (cd, info, & fr30_cgen_opval_dr_names, fields->f_Rs1, 0); break; - case FR30_OPERAND_UDISP6 : - { - long value; - length = extract_normal (od, ex_info, insn_value, 0|(1<f_udisp6 = value; - } + case FR30_OPERAND_RS2 : + print_keyword (cd, info, & fr30_cgen_opval_dr_names, fields->f_Rs2, 0); break; - case FR30_OPERAND_DISP8 : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_disp8); + case FR30_OPERAND_CC : + print_normal (cd, info, fields->f_cc, 0, pc, length); break; - case FR30_OPERAND_DISP9 : - { - long value; - length = extract_normal (od, ex_info, insn_value, 0|(1<f_disp9 = value; - } + case FR30_OPERAND_CCC : + print_normal (cd, info, fields->f_ccc, 0|(1<f_disp10 = value; - } + case FR30_OPERAND_DIR10 : + print_normal (cd, info, fields->f_dir10, 0, pc, length); break; - case FR30_OPERAND_S10 : - { - long value; - length = extract_normal (od, ex_info, insn_value, 0|(1<f_s10 = value; - } + case FR30_OPERAND_DIR8 : + print_normal (cd, info, fields->f_dir8, 0, pc, length); break; - case FR30_OPERAND_U10 : - { - long value; - length = extract_normal (od, ex_info, insn_value, 0|(1<f_u10 = value; - } + case FR30_OPERAND_DIR9 : + print_normal (cd, info, fields->f_dir9, 0, pc, length); break; - case FR30_OPERAND_I32 : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_i32); + case FR30_OPERAND_DISP10 : + print_normal (cd, info, fields->f_disp10, 0|(1<f_m4 = value; - } + case FR30_OPERAND_DISP8 : + print_normal (cd, info, fields->f_disp8, 0|(1<f_disp9, 0|(1<f_i20_4); - length = extract_normal (od, ex_info, insn_value, 0|(1<f_i20_16); -do { - FLD (f_i20) = ((((FLD (f_i20_4)) << (16))) | (FLD (f_i20_16))); -} while (0); - } + print_normal (cd, info, fields->f_i20, 0|(1<f_dir8); + case FR30_OPERAND_I32 : + print_normal (cd, info, fields->f_i32, 0|(1<f_dir9 = value; - } + case FR30_OPERAND_I8 : + print_normal (cd, info, fields->f_i8, 0|(1<f_dir10 = value; - } + case FR30_OPERAND_LABEL12 : + print_address (cd, info, fields->f_rel12, 0|(1<f_rel9 = value; - } + print_address (cd, info, fields->f_rel9, 0|(1<f_rel12 = value; - } + case FR30_OPERAND_M4 : + print_m4 (cd, info, fields->f_m4, 0|(1<f_reglist_low_ld); + case FR30_OPERAND_PS : + print_keyword (cd, info, & fr30_cgen_opval_h_ps, 0, 0); break; case FR30_OPERAND_REGLIST_HI_LD : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_reglist_hi_ld); - break; - case FR30_OPERAND_REGLIST_LOW_ST : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_reglist_low_st); + print_hi_register_list_ld (cd, info, fields->f_reglist_hi_ld, 0, pc, length); break; case FR30_OPERAND_REGLIST_HI_ST : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_reglist_hi_st); - break; - case FR30_OPERAND_CC : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_cc); - break; - case FR30_OPERAND_CCC : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_ccc); - break; - - default : - /* xgettext:c-format */ - fprintf (stderr, _("Unrecognized field %d while decoding insn.\n"), - opindex); - abort (); - } - - return length; -} - -/* Main entry point for printing operands. - - This function is basically just a big switch statement. Earlier versions - used tables to look up the function to use, but - - if the table contains both assembler and disassembler functions then - the disassembler contains much of the assembler and vice-versa, - - there's a lot of inlining possibilities as things grow, - - using a switch statement avoids the function call overhead. - - This function could be moved into `print_insn_normal', but keeping it - separate makes clear the interface between `print_insn_normal' and each of - the handlers. -*/ - -void -fr30_cgen_print_operand (od, opindex, info, fields, attrs, pc, length) - CGEN_OPCODE_DESC od; - int opindex; - disassemble_info * info; - CGEN_FIELDS * fields; - void const * attrs; - bfd_vma pc; - int length; -{ - switch (opindex) - { - case FR30_OPERAND_RI : - print_keyword (od, info, & fr30_cgen_opval_h_gr, fields->f_Ri, 0|(1<f_reglist_hi_st, 0, pc, length); break; - case FR30_OPERAND_RJ : - print_keyword (od, info, & fr30_cgen_opval_h_gr, fields->f_Rj, 0|(1<f_Ric, 0|(1<f_Rjc, 0|(1<f_CRi, 0|(1<f_CRj, 0|(1<f_Rs1, 0|(1<f_Rs2, 0|(1<f_nil, 0); + case FR30_OPERAND_REGLIST_LOW_LD : + print_low_register_list_ld (cd, info, fields->f_reglist_low_ld, 0, pc, length); break; - case FR30_OPERAND_R14 : - print_keyword (od, info, & fr30_cgen_opval_h_r14, fields->f_nil, 0); + case FR30_OPERAND_REGLIST_LOW_ST : + print_low_register_list_st (cd, info, fields->f_reglist_low_st, 0, pc, length); break; - case FR30_OPERAND_R15 : - print_keyword (od, info, & fr30_cgen_opval_h_r15, fields->f_nil, 0); + case FR30_OPERAND_S10 : + print_normal (cd, info, fields->f_s10, 0|(1<f_nil, 0); + case FR30_OPERAND_U10 : + print_normal (cd, info, fields->f_u10, 0|(1<f_u4, 0|(1<f_u4, 0|(1<f_u4c, 0|(1<f_u4c, 0|(1<f_u8, 0|(1<f_i8, 0|(1<f_u8, 0|(1<f_udisp6, 0|(1<f_disp8, 0|(1<f_disp9, 0|(1<f_disp10, 0|(1<f_s10, 0|(1<f_u10, 0|(1<f_i32, 0|(1<f_m4, 0|(1<f_i20, 0|(1<f_dir8, 0|(1<f_dir9, 0|(1<f_dir10, 0|(1<f_rel9, 0|(1<f_rel12, 0|(1<f_reglist_low_ld, 0|(1<f_reglist_hi_ld, 0|(1<f_reglist_low_st, 0|(1<f_reglist_hi_st, 0|(1<f_cc, 0|(1<f_ccc, 0|(1<f_udisp6, 0|(1<print_handlers = & fr30_cgen_print_handlers[0]; + cd->print_operand = fr30_cgen_print_operand; } -#if ! CGEN_INT_INSN_P - -/* Subroutine of extract_normal. - Ensure sufficient bytes are cached in EX_INFO. - OFFSET is the offset in bytes from the start of the insn of the value. - BYTES is the length of the needed value. - Returns 1 for success, 0 for failure. */ - -static INLINE int -fill_cache (od, ex_info, offset, bytes, pc) - CGEN_OPCODE_DESC od; - CGEN_EXTRACT_INFO *ex_info; - int offset, bytes; - bfd_vma pc; -{ - /* It's doubtful that the middle part has already been fetched so - we don't optimize that case. kiss. */ - int mask; - disassemble_info *info = (disassemble_info *) ex_info->dis_info; - - /* First do a quick check. */ - mask = (1 << bytes) - 1; - if (((ex_info->valid >> offset) & mask) == mask) - return 1; - - /* Search for the first byte we need to read. */ - for (mask = 1 << offset; bytes > 0; --bytes, ++offset, mask <<= 1) - if (! (mask & ex_info->valid)) - break; - - if (bytes) - { - int status; - - pc += offset; - status = (*info->read_memory_func) - (pc, ex_info->insn_bytes + offset, bytes, info); - - if (status != 0) - { - (*info->memory_error_func) (status, pc, info); - return 0; - } - - ex_info->valid |= ((1 << bytes) - 1) << offset; - } - - return 1; -} - -/* Subroutine of extract_normal. */ - -static INLINE long -extract_1 (od, ex_info, start, length, word_length, bufp, pc) - CGEN_OPCODE_DESC od; - CGEN_EXTRACT_INFO *ex_info; - int start,length,word_length; - unsigned char *bufp; - bfd_vma pc; -{ - unsigned long x,mask; - int shift; - int big_p = CGEN_OPCODE_INSN_ENDIAN (od) == CGEN_ENDIAN_BIG; - - switch (word_length) - { - case 8: - x = *bufp; - break; - case 16: - if (big_p) - x = bfd_getb16 (bufp); - else - x = bfd_getl16 (bufp); - break; - case 24: - /* ??? This may need reworking as these cases don't necessarily - want the first byte and the last two bytes handled like this. */ - if (big_p) - x = (bufp[0] << 16) | bfd_getb16 (bufp + 1); - else - x = bfd_getl16 (bufp) | (bufp[2] << 16); - break; - case 32: - if (big_p) - x = bfd_getb32 (bufp); - else - x = bfd_getl32 (bufp); - break; - default : - abort (); - } - - /* Written this way to avoid undefined behaviour. */ - mask = (((1L << (length - 1)) - 1) << 1) | 1; - if (CGEN_INSN_LSB0_P) - shift = (start + 1) - length; - else - shift = (word_length - (start + length)); - return (x >> shift) & mask; -} - -#endif /* ! CGEN_INT_INSN_P */ - -/* Default extraction routine. - - INSN_VALUE is the first CGEN_BASE_INSN_SIZE bits of the insn in host order, - or sometimes less for cases like the m32r where the base insn size is 32 - but some insns are 16 bits. - ATTRS is a mask of the boolean attributes. We only need `UNSIGNED', - but for generality we take a bitmask of all of them. - WORD_OFFSET is the offset in bits from the start of the insn of the value. - WORD_LENGTH is the length of the word in bits in which the value resides. - START is the starting bit number in the word, architecture origin. - LENGTH is the length of VALUE in bits. - TOTAL_LENGTH is the total length of the insn in bits. - - Returns 1 for success, 0 for failure. */ - -/* ??? The return code isn't properly used. wip. */ - -/* ??? This doesn't handle bfd_vma's. Create another function when - necessary. */ - -static int -extract_normal (od, ex_info, insn_value, attrs, word_offset, start, length, - word_length, total_length, pc, valuep) - CGEN_OPCODE_DESC od; - CGEN_EXTRACT_INFO *ex_info; - CGEN_INSN_INT insn_value; - unsigned int attrs; - unsigned int word_offset, start, length, word_length, total_length; - bfd_vma pc; - long *valuep; -{ - CGEN_INSN_INT value; - - /* If LENGTH is zero, this operand doesn't contribute to the value - so give it a standard value of zero. */ - if (length == 0) - { - *valuep = 0; - return 1; - } - - if (CGEN_INT_INSN_P - && word_offset != 0) - abort (); - - if (word_length > 32) - abort (); - - /* For architectures with insns smaller than the insn-base-bitsize, - word_length may be too big. */ -#if CGEN_MIN_INSN_BITSIZE < CGEN_BASE_INSN_BITSIZE - if (word_offset == 0 - && word_length > total_length) - word_length = total_length; -#endif - - /* Does the value reside in INSN_VALUE? */ - - if (word_offset == 0) - { - /* Written this way to avoid undefined behaviour. */ - CGEN_INSN_INT mask = (((1L << (length - 1)) - 1) << 1) | 1; - - if (CGEN_INSN_LSB0_P) - value = insn_value >> ((start + 1) - length); - else - value = insn_value >> (word_length - (start + length)); - value &= mask; - /* sign extend? */ - if (! CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED) - && (value & (1L << (length - 1)))) - value |= ~mask; - } - -#if ! CGEN_INT_INSN_P - - else - { - unsigned char *bufp = ex_info->insn_bytes + word_offset / 8; - - if (word_length > 32) - abort (); - - if (fill_cache (od, ex_info, word_offset / 8, word_length / 8, pc) == 0) - return 0; - - value = extract_1 (od, ex_info, start, length, word_length, bufp, pc); - } - -#endif /* ! CGEN_INT_INSN_P */ - - *valuep = value; - - return 1; -} - /* Default print handler. */ static void -print_normal (od, dis_info, value, attrs, pc, length) - CGEN_OPCODE_DESC od; +print_normal (cd, dis_info, value, attrs, pc, length) + CGEN_CPU_DESC cd; PTR dis_info; long value; unsigned int attrs; @@ -747,23 +334,23 @@ print_normal (od, dis_info, value, attrs, pc, length) disassemble_info *info = (disassemble_info *) dis_info; #ifdef CGEN_PRINT_NORMAL - CGEN_PRINT_NORMAL (od, info, value, attrs, pc, length); + CGEN_PRINT_NORMAL (cd, info, value, attrs, pc, length); #endif /* Print the operand as directed by the attributes. */ if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY)) ; /* nothing to do */ - else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED)) - (*info->fprintf_func) (info->stream, "0x%lx", value); - else + else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED)) (*info->fprintf_func) (info->stream, "%ld", value); + else + (*info->fprintf_func) (info->stream, "0x%lx", value); } /* Default address handler. */ static void -print_address (od, dis_info, value, attrs, pc, length) - CGEN_OPCODE_DESC od; +print_address (cd, dis_info, value, attrs, pc, length) + CGEN_CPU_DESC cd; PTR dis_info; bfd_vma value; unsigned int attrs; @@ -773,7 +360,7 @@ print_address (od, dis_info, value, attrs, pc, length) disassemble_info *info = (disassemble_info *) dis_info; #ifdef CGEN_PRINT_ADDRESS - CGEN_PRINT_ADDRESS (od, info, value, attrs, pc, length); + CGEN_PRINT_ADDRESS (cd, info, value, attrs, pc, length); #endif /* Print the operand as directed by the attributes. */ @@ -783,17 +370,17 @@ print_address (od, dis_info, value, attrs, pc, length) (*info->print_address_func) (value, info); else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR)) (*info->print_address_func) (value, info); - else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED)) - (*info->fprintf_func) (info->stream, "0x%lx", (long) value); - else + else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED)) (*info->fprintf_func) (info->stream, "%ld", (long) value); + else + (*info->fprintf_func) (info->stream, "0x%lx", (long) value); } /* Keyword print handler. */ static void -print_keyword (od, dis_info, keyword_table, value, attrs) - CGEN_OPCODE_DESC od; +print_keyword (cd, dis_info, keyword_table, value, attrs) + CGEN_CPU_DESC cd; PTR dis_info; CGEN_KEYWORD *keyword_table; long value; @@ -809,56 +396,14 @@ print_keyword (od, dis_info, keyword_table, value, attrs) (*info->fprintf_func) (info->stream, "???"); } -/* Default insn extractor. - - INSN_VALUE is the first CGEN_BASE_INSN_SIZE bytes, translated to host order. - The extracted fields are stored in FIELDS. - EX_INFO is used to handle reading variable length insns. - Return the length of the insn in bits, or 0 if no match, - or -1 if an error occurs fetching data (memory_error_func will have - been called). */ - -static int -extract_insn_normal (od, insn, ex_info, insn_value, fields, pc) - CGEN_OPCODE_DESC od; - const CGEN_INSN *insn; - CGEN_EXTRACT_INFO *ex_info; - CGEN_INSN_INT insn_value; - CGEN_FIELDS *fields; - bfd_vma pc; -{ - const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn); - const unsigned char *syn; - - CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn); - - CGEN_INIT_EXTRACT (od); - - for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn) - { - int length; - - if (CGEN_SYNTAX_CHAR_P (*syn)) - continue; - - length = fr30_cgen_extract_operand (od, CGEN_SYNTAX_FIELD (*syn), - ex_info, insn_value, fields, pc); - if (length <= 0) - return length; - } - - /* We recognized and successfully extracted this insn. */ - return CGEN_INSN_BITSIZE (insn); -} - /* Default insn printer. DIS_INFO is defined as `PTR' so the disassembler needn't know anything about disassemble_info. */ static void -print_insn_normal (od, dis_info, insn, fields, pc, length) - CGEN_OPCODE_DESC od; +print_insn_normal (cd, dis_info, insn, fields, pc, length) + CGEN_CPU_DESC cd; PTR dis_info; const CGEN_INSN *insn; CGEN_FIELDS *fields; @@ -869,7 +414,7 @@ print_insn_normal (od, dis_info, insn, fields, pc, length) disassemble_info *info = (disassemble_info *) dis_info; const unsigned char *syn; - CGEN_INIT_PRINT (od); + CGEN_INIT_PRINT (cd); for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn) { @@ -885,7 +430,7 @@ print_insn_normal (od, dis_info, insn, fields, pc, length) } /* We have an operand. */ - fr30_cgen_print_operand (od, CGEN_SYNTAX_FIELD (*syn), info, + fr30_cgen_print_operand (cd, CGEN_SYNTAX_FIELD (*syn), info, fields, CGEN_INSN_ATTRS (insn), pc, length); } } @@ -897,8 +442,8 @@ print_insn_normal (od, dis_info, insn, fields, pc, length) been called). */ static int -print_insn (od, pc, info, buf, buflen) - CGEN_OPCODE_DESC od; +print_insn (cd, pc, info, buf, buflen) + CGEN_CPU_DESC cd; bfd_vma pc; disassemble_info *info; char *buf; @@ -909,7 +454,7 @@ print_insn (od, pc, info, buf, buflen) CGEN_EXTRACT_INFO ex_info; ex_info.dis_info = info; - ex_info.valid = (1 << CGEN_BASE_INSN_SIZE) - 1; + ex_info.valid = (1 << (cd->base_insn_bitsize / 8)) - 1; ex_info.insn_bytes = buf; switch (buflen) @@ -930,7 +475,7 @@ print_insn (od, pc, info, buf, buflen) /* The instructions are stored in hash lists. Pick the first one and keep trying until we find the right one. */ - insn_list = CGEN_DIS_LOOKUP_INSN (od, buf, insn_value); + insn_list = CGEN_DIS_LOOKUP_INSN (cd, buf, insn_value); while (insn_list != NULL) { const CGEN_INSN *insn = insn_list->insn; @@ -939,7 +484,7 @@ print_insn (od, pc, info, buf, buflen) #if 0 /* not needed as insn shouldn't be in hash lists if not supported */ /* Supported by this cpu? */ - if (! fr30_cgen_insn_supported (od, insn)) + if (! fr30_cgen_insn_supported (cd, insn)) continue; #endif @@ -953,14 +498,14 @@ print_insn (od, pc, info, buf, buflen) machine insn and extracts the fields. The second pass prints them. */ - length = (*CGEN_EXTRACT_FN (insn)) (od, insn, &ex_info, insn_value, - &fields, pc); + length = CGEN_EXTRACT_FN (cd, insn) + (cd, insn, &ex_info, insn_value, &fields, pc); /* length < 0 -> error */ if (length < 0) return length; if (length > 0) { - (*CGEN_PRINT_FN (insn)) (od, info, insn, &fields, pc, length); + CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length); /* length is in bits, result is in bytes */ return length / 8; } @@ -981,8 +526,8 @@ print_insn (od, pc, info, buf, buflen) #endif static int -default_print_insn (od, pc, info) - CGEN_OPCODE_DESC od; +default_print_insn (cd, pc, info) + CGEN_CPU_DESC cd; bfd_vma pc; disassemble_info *info; { @@ -991,14 +536,14 @@ default_print_insn (od, pc, info) /* Read the base part of the insn. */ - status = (*info->read_memory_func) (pc, buf, CGEN_BASE_INSN_SIZE, info); + status = (*info->read_memory_func) (pc, buf, cd->base_insn_bitsize / 8, info); if (status != 0) { (*info->memory_error_func) (status, pc, info); return -1; } - return print_insn (od, pc, info, buf, CGEN_BASE_INSN_SIZE); + return print_insn (cd, pc, info, buf, cd->base_insn_bitsize / 8); } /* Main entry point. @@ -1010,27 +555,63 @@ print_insn_fr30 (pc, info) bfd_vma pc; disassemble_info *info; { + static CGEN_CPU_DESC cd = 0; + static prev_isa,prev_mach,prev_endian; int length; - static CGEN_OPCODE_DESC od = 0; - int mach = info->mach; - int big_p = info->endian == BFD_ENDIAN_BIG; + int isa,mach; + int endian = (info->endian == BFD_ENDIAN_BIG + ? CGEN_ENDIAN_BIG + : CGEN_ENDIAN_LITTLE); + enum bfd_architecture arch; + + /* ??? gdb will set mach but leave the architecture as "unknown" */ +#ifndef CGEN_BFD_ARCH +#define CGEN_BFD_ARCH bfd_arch_fr30 +#endif + arch = info->arch; + if (arch == bfd_arch_unknown) + arch = CGEN_BFD_ARCH; + + /* There's no standard way to compute the isa number (e.g. for arm thumb) + so we leave it to the target. */ +#ifdef CGEN_COMPUTE_ISA + isa = CGEN_COMPUTE_ISA (info); +#else + isa = 0; +#endif - /* If we haven't initialized yet, initialize the opcode table. */ - if (! od) + mach = info->mach; + + /* If we've switched cpu's, close the current table and open a new one. */ + if (cd + && (isa != prev_isa + || mach != prev_mach + || endian != prev_endian)) { - od = fr30_cgen_opcode_open (mach, - big_p ? - CGEN_ENDIAN_BIG - : CGEN_ENDIAN_LITTLE); - fr30_cgen_init_dis (od); + fr30_cgen_cpu_close (cd); + cd = 0; } - /* If we've switched cpu's, re-initialize. */ - /* ??? Perhaps we should use BFD_ENDIAN. */ - else if (mach != CGEN_OPCODE_MACH (od) - || (CGEN_OPCODE_ENDIAN (od) - != (big_p ? CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE))) + + /* If we haven't initialized yet, initialize the opcode table. */ + if (! cd) { - cgen_set_cpu (od, mach, big_p ? CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE); + const bfd_arch_info_type *arch_type = bfd_lookup_arch (arch, mach); + const char *mach_name; + + if (!arch_type) + abort (); + mach_name = arch_type->printable_name; + + prev_isa = isa; + prev_mach = mach; + prev_endian = endian; + cd = fr30_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa, + CGEN_CPU_OPEN_BFDMACH, mach_name, + CGEN_CPU_OPEN_ENDIAN, prev_endian, + CGEN_CPU_OPEN_END); + if (!cd) + abort (); + fr30_cgen_init_dis (cd); } /* We try to have as much common code as possible. @@ -1038,12 +619,12 @@ print_insn_fr30 (pc, info) /* ??? Some targets may need a hook elsewhere. Try to avoid this, but if not possible try to move this hook elsewhere rather than have two hooks. */ - length = CGEN_PRINT_INSN (od, pc, info); + length = CGEN_PRINT_INSN (cd, pc, info); if (length > 0) return length; if (length < 0) return -1; (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG); - return CGEN_DEFAULT_INSN_SIZE; + return cd->default_insn_bitsize / 8; }