From 9c87d6c7e4d127af8701b80157edbcdddb7b01b6 Mon Sep 17 00:00:00 2001 From: Svein Seldal Date: Mon, 18 Nov 2002 09:09:35 +0000 Subject: * gas/config/tc-tic4x.c: Fixed proper commandline parameters. Added support for new opcode-list format. General error message fixups. (c4x_inst_add): Reject insn not for our CPU (md_begin): Added matrix for setting the proper opcode-level & device-flags according to cpu type and revision. Rewrite the opcode hasher. (c4x_operand_parse): Fix opcode bug (c4x_operands_match): New function argument. Added dry-run mechanism, that is optional error generation. Added constraint 'i' and 'j'. (c4x_insn_check): Added new function for post-verification of the generated insn. (md_assemble): Check all opcodes before croaking because of an argument mismatch. Need this to be able to fully support ortogonally arguments. (md_parse_options): Revised commandprompt swicthes and added new ones. (md_show_usage): Complete rewrite of printout. * gas/testsuite/gas/tic4x/addressing.s: Fix bug in one insn * gas/testsuite/gas/tic4x/addressing_c3x.d: Update thereafter * gas/testsuite/gas/tic4x/addressing_c4x.d: Update thereafter * gas/testsuite/gas/tic4x/allopcodes.S: Add support for new opclass.h changes * gas/testsuite/gas/tic4x/opclasses.h: Added testsuites for the new enhanced opcodes. * gas/testsuite/gas/tic4x/opcodes.s: Regenerate * gas/testsuite/gas/tic4x/opcodes_c3x.d: Update from above * gas/testsuite/gas/tic4x/opcodes_c4x.d: Update from above * gas/testsuite/gas/tic4x/opcodes_new.d: Added new testsuite for the enhanced and special insns. * gas/testsuite/gas/tic4x/tic4x.exp: Added the opcodes_new testsuite * include/opcode/tic4x.h: File reordering. Added enhanced opcodes. * opcodes/tic4x-dis.c: Added support for enhanced and special insn. (c4x_print_op): Added insn class 'i' and 'j' (c4x_hash_opcode_special): Add to support special insn (c4x_hash_opcode): Update to support the new opcode-list format. Add support for the new special insns. (c4x_disassemble): New opcode-list support. --- opcodes/tic4x-dis.c | 158 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 127 insertions(+), 31 deletions(-) (limited to 'opcodes/tic4x-dis.c') diff --git a/opcodes/tic4x-dis.c b/opcodes/tic4x-dis.c index ff1770e..b991693 100644 --- a/opcodes/tic4x-dis.c +++ b/opcodes/tic4x-dis.c @@ -25,7 +25,8 @@ #define C4X_DEBUG 0 -#define C4X_HASH_SIZE 11 /* 11 and above should give unique entries. */ +#define C4X_HASH_SIZE 11 /* 11 (bits) and above should give unique entries. */ +#define C4X_SPESOP_SIZE 8 /* Max 8. ops for special instructions */ typedef enum { @@ -50,35 +51,37 @@ static int c4x_version = 0; static int c4x_dp = 0; static int c4x_pc_offset - PARAMS ((unsigned int)); + PARAMS ((unsigned int)); static int c4x_print_char - PARAMS ((struct disassemble_info *, char)); + PARAMS ((struct disassemble_info *, char)); static int c4x_print_str - PARAMS ((struct disassemble_info *, char *)); + PARAMS ((struct disassemble_info *, char *)); static int c4x_print_register - PARAMS ((struct disassemble_info *, unsigned long)); + PARAMS ((struct disassemble_info *, unsigned long)); static int c4x_print_addr - PARAMS ((struct disassemble_info *, unsigned long)); + PARAMS ((struct disassemble_info *, unsigned long)); static int c4x_print_relative - PARAMS ((struct disassemble_info *, unsigned long, long, unsigned long)); + PARAMS ((struct disassemble_info *, unsigned long, long, unsigned long)); void c4x_print_ftoa - PARAMS ((unsigned int, FILE *, fprintf_ftype)); + PARAMS ((unsigned int, FILE *, fprintf_ftype)); static int c4x_print_direct - PARAMS ((struct disassemble_info *, unsigned long)); + PARAMS ((struct disassemble_info *, unsigned long)); static int c4x_print_immed - PARAMS ((struct disassemble_info *, immed_t, unsigned long)); + PARAMS ((struct disassemble_info *, immed_t, unsigned long)); static int c4x_print_cond - PARAMS ((struct disassemble_info *, unsigned int)); + PARAMS ((struct disassemble_info *, unsigned int)); static int c4x_print_indirect - PARAMS ((struct disassemble_info *, indirect_t, unsigned long)); + PARAMS ((struct disassemble_info *, indirect_t, unsigned long)); static int c4x_print_op - PARAMS ((struct disassemble_info *, unsigned long, c4x_inst_t *, unsigned long)); + PARAMS ((struct disassemble_info *, unsigned long, c4x_inst_t *, unsigned long)); +static void c4x_hash_opcode_special + PARAMS ((c4x_inst_t **, const c4x_inst_t *)); static void c4x_hash_opcode - PARAMS ((c4x_inst_t **, const c4x_inst_t *)); + PARAMS ((c4x_inst_t **, c4x_inst_t **, const c4x_inst_t *, unsigned long)); static int c4x_disassemble - PARAMS ((unsigned long, unsigned long, struct disassemble_info *)); + PARAMS ((unsigned long, unsigned long, struct disassemble_info *)); int print_insn_tic4x - PARAMS ((bfd_vma, struct disassemble_info *)); + PARAMS ((bfd_vma, struct disassemble_info *)); static int @@ -489,12 +492,29 @@ c4x_print_op (info, instruction, p, pc) EXTRU (instruction, 15, 0)); break; + case 'i': /* Extended indirect 0--7 */ + if ( EXTRU (instruction, 7, 5) == 7 ) + { + if( !c4x_print_register (info, EXTRU (instruction, 4, 0)) ) + return 0; + break; + } + /* Fallthrough */ + case 'I': /* indirect (short) 0--7 */ if (! c4x_print_indirect (info, INDIRECT_SHORT, EXTRU (instruction, 7, 0))) return 0; break; + case 'j': /* Extended indirect 8--15 */ + if ( EXTRU (instruction, 15, 13) == 7 ) + { + if( !c4x_print_register (info, EXTRU (instruction, 12, 8)) ) + return 0; + break; + } + case 'J': /* indirect (short) 8--15 */ if (! c4x_print_indirect (info, INDIRECT_SHORT, EXTRU (instruction, 15, 8))) @@ -629,9 +649,43 @@ c4x_print_op (info, instruction, p, pc) } static void -c4x_hash_opcode (optable, inst) +c4x_hash_opcode_special (optable_special, inst) + c4x_inst_t **optable_special; + const c4x_inst_t *inst; +{ + int i; + + for( i=0; iopcode == inst->opcode ) + { + /* Collision (we have it already) - overwrite */ + optable_special[i] = (void *)inst; + return; + } + + for( i=0; iopcode >> (32 - C4X_HASH_SIZE); @@ -641,7 +695,8 @@ c4x_hash_opcode (optable, inst) have unique entries so there's no point having a linked list for each entry? */ for (j = opcode; j < opmask; j++) - if ((j & opmask) == opcode) + if ( (j & opmask) == opcode + && inst->oplevel & c4x_oplevel ) { #if C4X_DEBUG /* We should only have collisions for synonyms like @@ -650,7 +705,21 @@ c4x_hash_opcode (optable, inst) printf("Collision at index %d, %s and %s\n", j, optable[j]->name, inst->name); #endif - optable[j] = (void *)inst; + /* Catch those ops that collide with others already inside the + hash, and have a opmask greater than the one we use in the + hash. Store them in a special-list, that will handle full + 32-bit INSN, not only the first 11-bit (or so). */ + if ( optable[j] != NULL + && inst->opmask & ~(opmask << (32 - C4X_HASH_SIZE)) ) + { + /* Add the instruction already on the list */ + c4x_hash_opcode_special(optable_special, optable[j]); + + /* Add the new instruction */ + c4x_hash_opcode_special(optable_special, inst); + } + + optable[j] = (void *)inst; } } @@ -667,36 +736,63 @@ c4x_disassemble (pc, instruction, info) struct disassemble_info *info; { static c4x_inst_t **optable = NULL; + static c4x_inst_t **optable_special = NULL; c4x_inst_t *p; int i; + unsigned long c4x_oplevel; c4x_version = info->mach; + + c4x_oplevel = (IS_CPU_C4X (c4x_version)) ? OP_C4X : 0; + c4x_oplevel |= OP_C3X|OP_LPWR|OP_IDLE2|OP_ENH; if (optable == NULL) { optable = (c4x_inst_t **) xcalloc (sizeof (c4x_inst_t *), (1 << C4X_HASH_SIZE)); + + optable_special = (c4x_inst_t **) + xcalloc (sizeof (c4x_inst_t *), C4X_SPESOP_SIZE ); + /* Install opcodes in reverse order so that preferred forms overwrite synonyms. */ - for (i = c3x_num_insts - 1; i >= 0; i--) - c4x_hash_opcode (optable, &c3x_insts[i]); - if (IS_CPU_C4X (c4x_version)) - { - for (i = c4x_num_insts - 1; i >= 0; i--) - c4x_hash_opcode (optable, &c4x_insts[i]); - } + for (i = c4x_num_insts - 1; i >= 0; i--) + c4x_hash_opcode (optable, optable_special, &c4x_insts[i], c4x_oplevel); + + /* We now need to remove the insn that are special from the + "normal" optable, to make the disasm search this extra list + for them. + */ + for (i=0; iopcode >> (32 - C4X_HASH_SIZE)] = NULL; } /* See if we can pick up any loading of the DP register... */ if ((instruction >> 16) == 0x5070 || (instruction >> 16) == 0x1f70) c4x_dp = EXTRU (instruction, 15, 0); - + p = optable[instruction >> (32 - C4X_HASH_SIZE)]; - if (p != NULL && ((instruction & p->opmask) == p->opcode) - && c4x_print_op (NULL, instruction, p, pc)) - c4x_print_op (info, instruction, p, pc); + if ( p != NULL ) + { + if ( ((instruction & p->opmask) == p->opcode) + && c4x_print_op (NULL, instruction, p, pc) ) + c4x_print_op (info, instruction, p, pc); + else + (*info->fprintf_func) (info->stream, "%08x", instruction); + } else - (*info->fprintf_func) (info->stream, "%08x", instruction); + { + for (i = 0; iopcode == instruction ) + { + (*info->fprintf_func)(info->stream, "%s", optable_special[i]->name); + break; + } + if (i==C4X_SPESOP_SIZE) + (*info->fprintf_func) (info->stream, "%08x", instruction); + } /* Return size of insn in words. */ return 1; -- cgit v1.1