[BACK]Return to spu-dis.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / external / gpl3 / binutils.old / dist / opcodes

Annotation of src/external/gpl3/binutils.old/dist/opcodes/spu-dis.c, Revision 1.1.1.5

1.1       christos    1: /* Disassemble SPU instructions
                      2:
1.1.1.5 ! christos    3:    Copyright (C) 2006-2020 Free Software Foundation, Inc.
1.1       christos    4:
                      5:    This file is part of the GNU opcodes library.
                      6:
                      7:    This library is free software; you can redistribute it and/or modify
                      8:    it under the terms of the GNU General Public License as published by
                      9:    the Free Software Foundation; either version 3, or (at your option)
                     10:    any later version.
                     11:
                     12:    It is distributed in the hope that it will be useful, but WITHOUT
                     13:    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     14:    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
                     15:    License for more details.
                     16:
                     17:    You should have received a copy of the GNU General Public License
                     18:    along with this file; see the file COPYING.  If not, write to the
                     19:    Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
                     20:    MA 02110-1301, USA.  */
                     21:
                     22: #include "sysdep.h"
                     23: #include <stdio.h>
1.1.1.4   christos   24: #include "disassemble.h"
1.1       christos   25: #include "opcode/spu.h"
                     26:
                     27: /* This file provides a disassembler function which uses
                     28:    the disassembler interface defined in dis-asm.h.   */
                     29:
                     30: extern const struct spu_opcode spu_opcodes[];
                     31: extern const int spu_num_opcodes;
                     32:
                     33: static const struct spu_opcode *spu_disassemble_table[(1<<11)];
                     34:
                     35: static void
                     36: init_spu_disassemble (void)
                     37: {
                     38:   int i;
                     39:
                     40:   /* If two instructions have the same opcode then we prefer the first
                     41:    * one.  In most cases it is just an alternate mnemonic. */
                     42:   for (i = 0; i < spu_num_opcodes; i++)
                     43:     {
                     44:       int o = spu_opcodes[i].opcode;
                     45:       if (o >= (1 << 11))
                     46:        abort ();
                     47:       if (spu_disassemble_table[o] == 0)
                     48:        spu_disassemble_table[o] = &spu_opcodes[i];
                     49:     }
                     50: }
                     51:
                     52: /* Determine the instruction from the 10 least significant bits. */
                     53: static const struct spu_opcode *
                     54: get_index_for_opcode (unsigned int insn)
                     55: {
                     56:   const struct spu_opcode *op_index;
                     57:   unsigned int opcode = insn >> (32-11);
                     58:
                     59:   /* Init the table.  This assumes that element 0/opcode 0 (currently
                     60:    * NOP) is always used */
                     61:   if (spu_disassemble_table[0] == 0)
                     62:     init_spu_disassemble ();
                     63:
                     64:   if ((op_index = spu_disassemble_table[opcode & 0x780]) != 0
                     65:       && op_index->insn_type == RRR)
                     66:     return op_index;
                     67:
                     68:   if ((op_index = spu_disassemble_table[opcode & 0x7f0]) != 0
                     69:       && (op_index->insn_type == RI18 || op_index->insn_type == LBT))
                     70:     return op_index;
                     71:
                     72:   if ((op_index = spu_disassemble_table[opcode & 0x7f8]) != 0
                     73:       && op_index->insn_type == RI10)
                     74:     return op_index;
                     75:
                     76:   if ((op_index = spu_disassemble_table[opcode & 0x7fc]) != 0
                     77:       && (op_index->insn_type == RI16))
                     78:     return op_index;
                     79:
                     80:   if ((op_index = spu_disassemble_table[opcode & 0x7fe]) != 0
                     81:       && (op_index->insn_type == RI8))
                     82:     return op_index;
                     83:
                     84:   if ((op_index = spu_disassemble_table[opcode & 0x7ff]) != 0)
                     85:     return op_index;
                     86:
                     87:   return 0;
                     88: }
                     89:
                     90: /* Print a Spu instruction.  */
                     91:
                     92: int
                     93: print_insn_spu (bfd_vma memaddr, struct disassemble_info *info)
                     94: {
                     95:   bfd_byte buffer[4];
                     96:   int value;
                     97:   int hex_value;
                     98:   int status;
                     99:   unsigned int insn;
                    100:   const struct spu_opcode *op_index;
                    101:   enum spu_insns tag;
                    102:
                    103:   status = (*info->read_memory_func) (memaddr, buffer, 4, info);
                    104:   if (status != 0)
                    105:     {
                    106:       (*info->memory_error_func) (status, memaddr, info);
                    107:       return -1;
                    108:     }
                    109:
                    110:   insn = bfd_getb32 (buffer);
                    111:
                    112:   op_index = get_index_for_opcode (insn);
                    113:
                    114:   if (op_index == 0)
                    115:     {
                    116:       (*info->fprintf_func) (info->stream, ".long 0x%x", insn);
                    117:     }
                    118:   else
                    119:     {
                    120:       int i;
                    121:       int paren = 0;
                    122:       tag = (enum spu_insns)(op_index - spu_opcodes);
                    123:       (*info->fprintf_func) (info->stream, "%s", op_index->mnemonic);
                    124:       if (tag == M_BI || tag == M_BISL || tag == M_IRET || tag == M_BISLED
                    125:          || tag == M_BIHNZ || tag == M_BIHZ || tag == M_BINZ || tag == M_BIZ
                    126:           || tag == M_SYNC || tag == M_HBR)
                    127:        {
                    128:          int fb = (insn >> (32-18)) & 0x7f;
                    129:          if (fb & 0x40)
                    130:            (*info->fprintf_func) (info->stream, tag == M_SYNC ? "c" : "p");
                    131:          if (fb & 0x20)
                    132:            (*info->fprintf_func) (info->stream, "d");
                    133:          if (fb & 0x10)
                    134:            (*info->fprintf_func) (info->stream, "e");
                    135:        }
                    136:       if (op_index->arg[0] != 0)
                    137:        (*info->fprintf_func) (info->stream, "\t");
                    138:       hex_value = 0;
                    139:       for (i = 1;  i <= op_index->arg[0]; i++)
                    140:        {
                    141:          int arg = op_index->arg[i];
                    142:          if (arg != A_P && !paren && i > 1)
                    143:            (*info->fprintf_func) (info->stream, ",");
                    144:
                    145:          switch (arg)
                    146:            {
                    147:            case A_T:
                    148:              (*info->fprintf_func) (info->stream, "$%d",
                    149:                                     DECODE_INSN_RT (insn));
                    150:              break;
                    151:            case A_A:
                    152:              (*info->fprintf_func) (info->stream, "$%d",
                    153:                                     DECODE_INSN_RA (insn));
                    154:              break;
                    155:            case A_B:
                    156:              (*info->fprintf_func) (info->stream, "$%d",
                    157:                                     DECODE_INSN_RB (insn));
                    158:              break;
                    159:            case A_C:
                    160:              (*info->fprintf_func) (info->stream, "$%d",
                    161:                                     DECODE_INSN_RC (insn));
                    162:              break;
                    163:            case A_S:
                    164:              (*info->fprintf_func) (info->stream, "$sp%d",
                    165:                                     DECODE_INSN_RA (insn));
                    166:              break;
                    167:            case A_H:
                    168:              (*info->fprintf_func) (info->stream, "$ch%d",
                    169:                                     DECODE_INSN_RA (insn));
                    170:              break;
                    171:            case A_P:
                    172:              paren++;
                    173:              (*info->fprintf_func) (info->stream, "(");
                    174:              break;
                    175:            case A_U7A:
                    176:              (*info->fprintf_func) (info->stream, "%d",
                    177:                                     173 - DECODE_INSN_U8 (insn));
                    178:              break;
                    179:            case A_U7B:
                    180:              (*info->fprintf_func) (info->stream, "%d",
                    181:                                     155 - DECODE_INSN_U8 (insn));
                    182:              break;
                    183:            case A_S3:
                    184:            case A_S6:
                    185:            case A_S7:
                    186:            case A_S7N:
                    187:            case A_U3:
                    188:            case A_U5:
                    189:            case A_U6:
                    190:            case A_U7:
                    191:              hex_value = DECODE_INSN_I7 (insn);
                    192:              (*info->fprintf_func) (info->stream, "%d", hex_value);
                    193:              break;
                    194:            case A_S11:
                    195:              (*info->print_address_func) (memaddr + DECODE_INSN_I9a (insn) * 4,
                    196:                                           info);
                    197:              break;
                    198:            case A_S11I:
                    199:              (*info->print_address_func) (memaddr + DECODE_INSN_I9b (insn) * 4,
                    200:                                           info);
                    201:              break;
                    202:            case A_S10:
                    203:            case A_S10B:
                    204:              hex_value = DECODE_INSN_I10 (insn);
                    205:              (*info->fprintf_func) (info->stream, "%d", hex_value);
                    206:              break;
                    207:            case A_S14:
                    208:              hex_value = DECODE_INSN_I10 (insn) * 16;
                    209:              (*info->fprintf_func) (info->stream, "%d", hex_value);
                    210:              break;
                    211:            case A_S16:
                    212:              hex_value = DECODE_INSN_I16 (insn);
                    213:              (*info->fprintf_func) (info->stream, "%d", hex_value);
                    214:              break;
                    215:            case A_X16:
                    216:              hex_value = DECODE_INSN_U16 (insn);
                    217:              (*info->fprintf_func) (info->stream, "%u", hex_value);
                    218:              break;
                    219:            case A_R18:
                    220:              value = DECODE_INSN_I16 (insn) * 4;
                    221:              if (value == 0)
                    222:                (*info->fprintf_func) (info->stream, "%d", value);
                    223:              else
                    224:                {
                    225:                  hex_value = memaddr + value;
                    226:                  (*info->print_address_func) (hex_value & 0x3ffff, info);
                    227:                }
                    228:              break;
                    229:            case A_S18:
                    230:              value = DECODE_INSN_U16 (insn) * 4;
                    231:              if (value == 0)
                    232:                (*info->fprintf_func) (info->stream, "%d", value);
                    233:              else
                    234:                (*info->print_address_func) (value, info);
                    235:              break;
                    236:            case A_U18:
                    237:              value = DECODE_INSN_U18 (insn);
                    238:              if (value == 0 || !(*info->symbol_at_address_func)(0, info))
                    239:                {
                    240:                  hex_value = value;
                    241:                  (*info->fprintf_func) (info->stream, "%u", value);
                    242:                }
                    243:              else
                    244:                (*info->print_address_func) (value, info);
                    245:              break;
                    246:            case A_U14:
                    247:              hex_value = DECODE_INSN_U14 (insn);
                    248:              (*info->fprintf_func) (info->stream, "%u", hex_value);
                    249:              break;
                    250:            }
                    251:          if (arg != A_P && paren)
                    252:            {
                    253:              (*info->fprintf_func) (info->stream, ")");
                    254:              paren--;
                    255:            }
                    256:        }
                    257:       if (hex_value > 16)
                    258:        (*info->fprintf_func) (info->stream, "\t# %x", hex_value);
                    259:     }
                    260:   return 4;
                    261: }

CVSweb <webmaster@jp.NetBSD.org>