X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=opcodes%2Ftic30-dis.c;h=82154715e2dfd808f8daeb8e4d820f2a0f6db766;hb=8cd0e5e93145699736a370b271ff03f3f41670b0;hp=8373403f875b049986bcfef18504f86b13658e89;hpb=f4321104139af96b8cc3d4946b4e5233d9fa1eab;p=deliverable%2Fbinutils-gdb.git diff --git a/opcodes/tic30-dis.c b/opcodes/tic30-dis.c index 8373403f87..82154715e2 100644 --- a/opcodes/tic30-dis.c +++ b/opcodes/tic30-dis.c @@ -1,26 +1,28 @@ /* Disassembly routines for TMS320C30 architecture - Copyright 1998, 1999, 2000, 2002 Free Software Foundation, Inc. + Copyright (C) 1998-2020 Free Software Foundation, Inc. Contributed by Steven Haworth (steve@pm.cse.rmit.edu.au) - This program is free software; you can redistribute it and/or modify + This file is part of the GNU opcodes library. + + This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + the Free Software Foundation; either version 3, or (at your option) + any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + It is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. 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., 51 Franklin Street - Fifth Floor, Boston, MA - 02110-1301, USA. */ + along with this file; see the file COPYING. If not, write to the + Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ +#include "sysdep.h" #include #include -#include "sysdep.h" -#include "dis-asm.h" +#include "disassemble.h" #include "opcode/tic30.h" #define NORMAL_INSN 1 @@ -62,67 +64,12 @@ static unsigned int _pc; struct instruction { int type; - template *tm; + insn_template *tm; partemplate *ptm; }; -int get_tic30_instruction PARAMS ((unsigned long, struct instruction *)); -int print_two_operand - PARAMS ((disassemble_info *, unsigned long, struct instruction *)); -int print_three_operand - PARAMS ((disassemble_info *, unsigned long, struct instruction *)); -int print_par_insn - PARAMS ((disassemble_info *, unsigned long, struct instruction *)); -int print_branch - PARAMS ((disassemble_info *, unsigned long, struct instruction *)); -int get_indirect_operand PARAMS ((unsigned short, int, char *)); -int get_register_operand PARAMS ((unsigned char, char *)); -int cnvt_tmsfloat_ieee PARAMS ((unsigned long, int, float *)); - -int -print_insn_tic30 (pc, info) - bfd_vma pc; - disassemble_info *info; -{ - unsigned long insn_word; - struct instruction insn = { 0, NULL, NULL }; - bfd_vma bufaddr = pc - info->buffer_vma; - /* Obtain the current instruction word from the buffer. */ - insn_word = (*(info->buffer + bufaddr) << 24) | (*(info->buffer + bufaddr + 1) << 16) | - (*(info->buffer + bufaddr + 2) << 8) | *(info->buffer + bufaddr + 3); - _pc = pc / 4; - /* Get the instruction refered to by the current instruction word - and print it out based on its type. */ - if (!get_tic30_instruction (insn_word, &insn)) - return -1; - switch (GET_TYPE (insn_word)) - { - case TWO_OPERAND_1: - case TWO_OPERAND_2: - if (!print_two_operand (info, insn_word, &insn)) - return -1; - break; - case THREE_OPERAND: - if (!print_three_operand (info, insn_word, &insn)) - return -1; - break; - case PAR_STORE: - case MUL_ADDS: - if (!print_par_insn (info, insn_word, &insn)) - return -1; - break; - case BRANCHES: - if (!print_branch (info, insn_word, &insn)) - return -1; - break; - } - return 4; -} - -int -get_tic30_instruction (insn_word, insn) - unsigned long insn_word; - struct instruction *insn; +static int +get_tic30_instruction (unsigned long insn_word, struct instruction *insn) { switch (GET_TYPE (insn_word)) { @@ -131,7 +78,8 @@ get_tic30_instruction (insn_word, insn) case THREE_OPERAND: insn->type = NORMAL_INSN; { - template *current_optab = (template *) tic30_optab; + insn_template *current_optab = (insn_template *) tic30_optab; + for (; current_optab < tic30_optab_end; current_optab++) { if (GET_TYPE (current_optab->base_opcode) == GET_TYPE (insn_word)) @@ -153,15 +101,18 @@ get_tic30_instruction (insn_word, insn) } } break; + case PAR_STORE: insn->type = PARALLEL_INSN; { partemplate *current_optab = (partemplate *) tic30_paroptab; + for (; current_optab < tic30_paroptab_end; current_optab++) { if (GET_TYPE (current_optab->base_opcode) == GET_TYPE (insn_word)) { - if ((current_optab->base_opcode & PAR_STORE_IDEN) == (insn_word & PAR_STORE_IDEN)) + if ((current_optab->base_opcode & PAR_STORE_IDEN) + == (insn_word & PAR_STORE_IDEN)) { insn->ptm = current_optab; break; @@ -170,15 +121,18 @@ get_tic30_instruction (insn_word, insn) } } break; + case MUL_ADDS: insn->type = PARALLEL_INSN; { partemplate *current_optab = (partemplate *) tic30_paroptab; + for (; current_optab < tic30_paroptab_end; current_optab++) { if (GET_TYPE (current_optab->base_opcode) == GET_TYPE (insn_word)) { - if ((current_optab->base_opcode & MUL_ADD_IDEN) == (insn_word & MUL_ADD_IDEN)) + if ((current_optab->base_opcode & MUL_ADD_IDEN) + == (insn_word & MUL_ADD_IDEN)) { insn->ptm = current_optab; break; @@ -187,17 +141,20 @@ get_tic30_instruction (insn_word, insn) } } break; + case BRANCHES: insn->type = NORMAL_INSN; { - template *current_optab = (template *) tic30_optab; + insn_template *current_optab = (insn_template *) tic30_optab; + for (; current_optab < tic30_optab_end; current_optab++) { if (GET_TYPE (current_optab->base_opcode) == GET_TYPE (insn_word)) { if (current_optab->operand_types[0] & Imm24) { - if ((current_optab->base_opcode & BR_IMM_IDEN) == (insn_word & BR_IMM_IDEN)) + if ((current_optab->base_opcode & BR_IMM_IDEN) + == (insn_word & BR_IMM_IDEN)) { insn->tm = current_optab; break; @@ -205,7 +162,8 @@ get_tic30_instruction (insn_word, insn) } else if (current_optab->operands > 0) { - if ((current_optab->base_opcode & BR_COND_IDEN) == (insn_word & BR_COND_IDEN)) + if ((current_optab->base_opcode & BR_COND_IDEN) + == (insn_word & BR_COND_IDEN)) { insn->tm = current_optab; break; @@ -213,7 +171,8 @@ get_tic30_instruction (insn_word, insn) } else { - if ((current_optab->base_opcode & (BR_COND_IDEN | 0x00800000)) == (insn_word & (BR_COND_IDEN | 0x00800000))) + if ((current_optab->base_opcode & (BR_COND_IDEN | 0x00800000)) + == (insn_word & (BR_COND_IDEN | 0x00800000))) { insn->tm = current_optab; break; @@ -229,17 +188,175 @@ get_tic30_instruction (insn_word, insn) return 1; } -int -print_two_operand (info, insn_word, insn) - disassemble_info *info; - unsigned long insn_word; - struct instruction *insn; +#define OPERAND_BUFFER_LEN 15 + +static int +get_register_operand (unsigned char fragment, char *buffer) +{ + const reg *current_reg = tic30_regtab; + + if (buffer == NULL) + return 0; + for (; current_reg < tic30_regtab_end; current_reg++) + { + if ((fragment & 0x1F) == current_reg->opcode) + { + strncpy (buffer, current_reg->name, OPERAND_BUFFER_LEN); + buffer[OPERAND_BUFFER_LEN - 1] = 0; + return 1; + } + } + return 0; +} + +static int +get_indirect_operand (unsigned short fragment, + int size, + char *buffer) +{ + unsigned char mod; + unsigned arnum; + unsigned char disp; + + if (buffer == NULL) + return 0; + /* Determine which bits identify the sections of the indirect + operand based on the size in bytes. */ + switch (size) + { + case 1: + mod = (fragment & 0x00F8) >> 3; + arnum = (fragment & 0x0007); + disp = 0; + break; + case 2: + mod = (fragment & 0xF800) >> 11; + arnum = (fragment & 0x0700) >> 8; + disp = (fragment & 0x00FF); + break; + default: + return 0; + } + { + const ind_addr_type *current_ind = tic30_indaddr_tab; + + for (; current_ind < tic30_indaddrtab_end; current_ind++) + { + if (current_ind->modfield == mod) + { + if (current_ind->displacement == IMPLIED_DISP && size == 2) + continue; + + else + { + size_t i, len; + int bufcnt; + + len = strlen (current_ind->syntax); + + for (i = 0, bufcnt = 0; i < len; i++, bufcnt++) + { + buffer[bufcnt] = current_ind->syntax[i]; + + if (bufcnt > 0 + && bufcnt < OPERAND_BUFFER_LEN - 1 + && buffer[bufcnt - 1] == 'a' + && buffer[bufcnt] == 'r') + buffer[++bufcnt] = arnum + '0'; + + if (bufcnt < OPERAND_BUFFER_LEN - 1 + && buffer[bufcnt] == '(' + && current_ind->displacement == DISP_REQUIRED) + { + snprintf (buffer + (bufcnt + 1), + OPERAND_BUFFER_LEN - (bufcnt + 1), + "%u", disp); + bufcnt += strlen (buffer + (bufcnt + 1)); + } + } + buffer[bufcnt + 1] = '\0'; + break; + } + } + } + } + return 1; +} + +static int +cnvt_tmsfloat_ieee (unsigned long tmsfloat, int size, float *ieeefloat) +{ + unsigned long exponent, sign, mant; + union + { + unsigned long l; + float f; + } val; + + if (size == 2) + { + if ((tmsfloat & 0x0000F000) == 0x00008000) + tmsfloat = 0x80000000; + else + { + tmsfloat <<= 16; + tmsfloat = (long) tmsfloat >> 4; + } + } + exponent = tmsfloat & 0xFF000000; + if (exponent == 0x80000000) + { + *ieeefloat = 0.0; + return 1; + } + exponent += 0x7F000000; + sign = (tmsfloat & 0x00800000) << 8; + mant = tmsfloat & 0x007FFFFF; + if (exponent == 0xFF000000) + { + if (mant == 0) + *ieeefloat = ERANGE; +#ifdef HUGE_VALF + if (sign == 0) + *ieeefloat = HUGE_VALF; + else + *ieeefloat = -HUGE_VALF; +#else + if (sign == 0) + *ieeefloat = 1.0 / 0.0; + else + *ieeefloat = -1.0 / 0.0; +#endif + return 1; + } + exponent >>= 1; + if (sign) + { + mant = (~mant) & 0x007FFFFF; + mant += 1; + exponent += mant & 0x00800000; + exponent &= 0x7F800000; + mant &= 0x007FFFFF; + } + if (tmsfloat == 0x80000000) + sign = mant = exponent = 0; + tmsfloat = sign | exponent | mant; + val.l = tmsfloat; + *ieeefloat = val.f; + return 1; +} + +static int +print_two_operand (disassemble_info *info, + unsigned long insn_word, + struct instruction *insn) { char name[12]; - char operand[2][13] = + char operand[2][OPERAND_BUFFER_LEN] = { {0}, - {0}}; + {0} + }; float f_number; if (insn->tm == NULL) @@ -249,7 +366,8 @@ print_two_operand (info, insn_word, insn) { int src_op, dest_op; /* Determine whether instruction is a store or a normal instruction. */ - if ((insn->tm->operand_types[1] & (Direct | Indirect)) == (Direct | Indirect)) + if ((insn->tm->operand_types[1] & (Direct | Indirect)) + == (Direct | Indirect)) { src_op = 1; dest_op = 0; @@ -306,9 +424,7 @@ print_two_operand (info, insn_word, insn) else if (insn->tm->operands == 1) { if (insn->tm->opcode_modifier == StackOp) - { - get_register_operand ((insn_word & 0x001F0000) >> 16, operand[0]); - } + get_register_operand ((insn_word & 0x001F0000) >> 16, operand[0]); } /* Output instruction to stream. */ info->fprintf_func (info->stream, " %s %s%c%s", name, @@ -318,17 +434,17 @@ print_two_operand (info, insn_word, insn) return 1; } -int -print_three_operand (info, insn_word, insn) - disassemble_info *info; - unsigned long insn_word; - struct instruction *insn; +static int +print_three_operand (disassemble_info *info, + unsigned long insn_word, + struct instruction *insn) { - char operand[3][13] = + char operand[3][OPERAND_BUFFER_LEN] = { {0}, {0}, - {0}}; + {0} + }; if (insn->tm == NULL) return 0; @@ -362,24 +478,26 @@ print_three_operand (info, insn_word, insn) return 1; } -int -print_par_insn (info, insn_word, insn) - disassemble_info *info; - unsigned long insn_word; - struct instruction *insn; +static int +print_par_insn (disassemble_info *info, + unsigned long insn_word, + struct instruction *insn) { size_t i, len; char *name1, *name2; - char operand[2][3][13] = + char operand[2][3][OPERAND_BUFFER_LEN] = { { {0}, {0}, - {0}}, + {0} + }, { {0}, {0}, - {0}}}; + {0} + } + }; if (insn->ptm == NULL) return 0; @@ -484,16 +602,16 @@ print_par_insn (info, insn_word, insn) return 1; } -int -print_branch (info, insn_word, insn) - disassemble_info *info; - unsigned long insn_word; - struct instruction *insn; +static int +print_branch (disassemble_info *info, + unsigned long insn_word, + struct instruction *insn) { - char operand[2][13] = + char operand[2][OPERAND_BUFFER_LEN] = { {0}, - {0}}; + {0} + }; unsigned long address; int print_label = 0; @@ -563,153 +681,50 @@ print_branch (info, insn_word, insn) if (address == 0) info->fprintf_func (info->stream, " <%s>", sym->name); else - info->fprintf_func (info->stream, " <%s %c %d>", sym->name, + info->fprintf_func (info->stream, " <%s %c %lu>", sym->name, ((short) address < 0) ? '-' : '+', - abs (address)); + address); } return 1; } int -get_indirect_operand (fragment, size, buffer) - unsigned short fragment; - int size; - char *buffer; +print_insn_tic30 (bfd_vma pc, disassemble_info *info) { - unsigned char mod; - unsigned arnum; - unsigned char disp; + unsigned long insn_word; + struct instruction insn = { 0, NULL, NULL }; + bfd_vma bufaddr = pc - info->buffer_vma; - if (buffer == NULL) - return 0; - /* Determine which bits identify the sections of the indirect - operand based on the size in bytes. */ - switch (size) + /* Obtain the current instruction word from the buffer. */ + insn_word = (((unsigned) *(info->buffer + bufaddr) << 24) + | (*(info->buffer + bufaddr + 1) << 16) + | (*(info->buffer + bufaddr + 2) << 8) + | *(info->buffer + bufaddr + 3)); + _pc = pc / 4; + /* Get the instruction refered to by the current instruction word + and print it out based on its type. */ + if (!get_tic30_instruction (insn_word, &insn)) + return -1; + switch (GET_TYPE (insn_word)) { - case 1: - mod = (fragment & 0x00F8) >> 3; - arnum = (fragment & 0x0007); - disp = 0; + case TWO_OPERAND_1: + case TWO_OPERAND_2: + if (!print_two_operand (info, insn_word, &insn)) + return -1; break; - case 2: - mod = (fragment & 0xF800) >> 11; - arnum = (fragment & 0x0700) >> 8; - disp = (fragment & 0x00FF); + case THREE_OPERAND: + if (!print_three_operand (info, insn_word, &insn)) + return -1; + break; + case PAR_STORE: + case MUL_ADDS: + if (!print_par_insn (info, insn_word, &insn)) + return -1; + break; + case BRANCHES: + if (!print_branch (info, insn_word, &insn)) + return -1; break; - default: - return 0; - } - { - const ind_addr_type *current_ind = tic30_indaddr_tab; - for (; current_ind < tic30_indaddrtab_end; current_ind++) - { - if (current_ind->modfield == mod) - { - if (current_ind->displacement == IMPLIED_DISP && size == 2) - { - continue; - } - else - { - size_t i, len; - int bufcnt; - - len = strlen (current_ind->syntax); - for (i = 0, bufcnt = 0; i < len; i++, bufcnt++) - { - buffer[bufcnt] = current_ind->syntax[i]; - if (buffer[bufcnt - 1] == 'a' && buffer[bufcnt] == 'r') - buffer[++bufcnt] = arnum + '0'; - if (buffer[bufcnt] == '(' - && current_ind->displacement == DISP_REQUIRED) - { - sprintf (&buffer[bufcnt + 1], "%u", disp); - bufcnt += strlen (&buffer[bufcnt + 1]); - } - } - buffer[bufcnt + 1] = '\0'; - break; - } - } - } - } - return 1; -} - -int -get_register_operand (fragment, buffer) - unsigned char fragment; - char *buffer; -{ - const reg *current_reg = tic30_regtab; - - if (buffer == NULL) - return 0; - for (; current_reg < tic30_regtab_end; current_reg++) - { - if ((fragment & 0x1F) == current_reg->opcode) - { - strcpy (buffer, current_reg->name); - return 1; - } - } - return 0; -} - -int -cnvt_tmsfloat_ieee (tmsfloat, size, ieeefloat) - unsigned long tmsfloat; - int size; - float *ieeefloat; -{ - unsigned long exp, sign, mant; - union { - unsigned long l; - float f; - } val; - - if (size == 2) - { - if ((tmsfloat & 0x0000F000) == 0x00008000) - tmsfloat = 0x80000000; - else - { - tmsfloat <<= 16; - tmsfloat = (long) tmsfloat >> 4; - } - } - exp = tmsfloat & 0xFF000000; - if (exp == 0x80000000) - { - *ieeefloat = 0.0; - return 1; - } - exp += 0x7F000000; - sign = (tmsfloat & 0x00800000) << 8; - mant = tmsfloat & 0x007FFFFF; - if (exp == 0xFF000000) - { - if (mant == 0) - *ieeefloat = ERANGE; - if (sign == 0) - *ieeefloat = 1.0 / 0.0; - else - *ieeefloat = -1.0 / 0.0; - return 1; - } - exp >>= 1; - if (sign) - { - mant = (~mant) & 0x007FFFFF; - mant += 1; - exp += mant & 0x00800000; - exp &= 0x7F800000; - mant &= 0x007FFFFF; } - if (tmsfloat == 0x80000000) - sign = mant = exp = 0; - tmsfloat = sign | exp | mant; - val.l = tmsfloat; - *ieeefloat = val.f; - return 1; + return 4; }