0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/string.h>
0011 #include "nonstdio.h"
0012 #include "ansidecl.h"
0013 #include "spu.h"
0014 #include "dis-asm.h"
0015
0016
0017
0018
0019 extern const struct spu_opcode spu_opcodes[];
0020 extern const int spu_num_opcodes;
0021
0022 #define SPU_DISASM_TBL_SIZE (1 << 11)
0023 static const struct spu_opcode *spu_disassemble_table[SPU_DISASM_TBL_SIZE];
0024
0025 static void
0026 init_spu_disassemble (void)
0027 {
0028 int i;
0029
0030
0031
0032 for (i = 0; i < spu_num_opcodes; i++)
0033 {
0034 int o = spu_opcodes[i].opcode;
0035 if (o >= SPU_DISASM_TBL_SIZE)
0036 continue;
0037 if (spu_disassemble_table[o] == 0)
0038 spu_disassemble_table[o] = &spu_opcodes[i];
0039 }
0040 }
0041
0042
0043 static const struct spu_opcode *
0044 get_index_for_opcode (unsigned int insn)
0045 {
0046 const struct spu_opcode *index;
0047 unsigned int opcode = insn >> (32-11);
0048
0049
0050
0051 if (spu_disassemble_table[0] == 0)
0052 init_spu_disassemble ();
0053
0054 if ((index = spu_disassemble_table[opcode & 0x780]) != 0
0055 && index->insn_type == RRR)
0056 return index;
0057
0058 if ((index = spu_disassemble_table[opcode & 0x7f0]) != 0
0059 && (index->insn_type == RI18 || index->insn_type == LBT))
0060 return index;
0061
0062 if ((index = spu_disassemble_table[opcode & 0x7f8]) != 0
0063 && index->insn_type == RI10)
0064 return index;
0065
0066 if ((index = spu_disassemble_table[opcode & 0x7fc]) != 0
0067 && (index->insn_type == RI16))
0068 return index;
0069
0070 if ((index = spu_disassemble_table[opcode & 0x7fe]) != 0
0071 && (index->insn_type == RI8))
0072 return index;
0073
0074 if ((index = spu_disassemble_table[opcode & 0x7ff]) != 0)
0075 return index;
0076
0077 return NULL;
0078 }
0079
0080
0081
0082 int
0083 print_insn_spu (unsigned long insn, unsigned long memaddr)
0084 {
0085 int value;
0086 int hex_value;
0087 const struct spu_opcode *index;
0088 enum spu_insns tag;
0089
0090 index = get_index_for_opcode (insn);
0091
0092 if (index == 0)
0093 {
0094 printf(".long 0x%lx", insn);
0095 }
0096 else
0097 {
0098 int i;
0099 int paren = 0;
0100 tag = (enum spu_insns)(index - spu_opcodes);
0101 printf("%s", index->mnemonic);
0102 if (tag == M_BI || tag == M_BISL || tag == M_IRET || tag == M_BISLED
0103 || tag == M_BIHNZ || tag == M_BIHZ || tag == M_BINZ || tag == M_BIZ
0104 || tag == M_SYNC || tag == M_HBR)
0105 {
0106 int fb = (insn >> (32-18)) & 0x7f;
0107 if (fb & 0x40)
0108 printf(tag == M_SYNC ? "c" : "p");
0109 if (fb & 0x20)
0110 printf("d");
0111 if (fb & 0x10)
0112 printf("e");
0113 }
0114 if (index->arg[0] != 0)
0115 printf("\t");
0116 hex_value = 0;
0117 for (i = 1; i <= index->arg[0]; i++)
0118 {
0119 int arg = index->arg[i];
0120 if (arg != A_P && !paren && i > 1)
0121 printf(",");
0122
0123 switch (arg)
0124 {
0125 case A_T:
0126 printf("$%lu",
0127 DECODE_INSN_RT (insn));
0128 break;
0129 case A_A:
0130 printf("$%lu",
0131 DECODE_INSN_RA (insn));
0132 break;
0133 case A_B:
0134 printf("$%lu",
0135 DECODE_INSN_RB (insn));
0136 break;
0137 case A_C:
0138 printf("$%lu",
0139 DECODE_INSN_RC (insn));
0140 break;
0141 case A_S:
0142 printf("$sp%lu",
0143 DECODE_INSN_RA (insn));
0144 break;
0145 case A_H:
0146 printf("$ch%lu",
0147 DECODE_INSN_RA (insn));
0148 break;
0149 case A_P:
0150 paren++;
0151 printf("(");
0152 break;
0153 case A_U7A:
0154 printf("%lu",
0155 173 - DECODE_INSN_U8 (insn));
0156 break;
0157 case A_U7B:
0158 printf("%lu",
0159 155 - DECODE_INSN_U8 (insn));
0160 break;
0161 case A_S3:
0162 case A_S6:
0163 case A_S7:
0164 case A_S7N:
0165 case A_U3:
0166 case A_U5:
0167 case A_U6:
0168 case A_U7:
0169 hex_value = DECODE_INSN_I7 (insn);
0170 printf("%d", hex_value);
0171 break;
0172 case A_S11:
0173 print_address(memaddr + DECODE_INSN_I9a (insn) * 4);
0174 break;
0175 case A_S11I:
0176 print_address(memaddr + DECODE_INSN_I9b (insn) * 4);
0177 break;
0178 case A_S10:
0179 case A_S10B:
0180 hex_value = DECODE_INSN_I10 (insn);
0181 printf("%d", hex_value);
0182 break;
0183 case A_S14:
0184 hex_value = DECODE_INSN_I10 (insn) * 16;
0185 printf("%d", hex_value);
0186 break;
0187 case A_S16:
0188 hex_value = DECODE_INSN_I16 (insn);
0189 printf("%d", hex_value);
0190 break;
0191 case A_X16:
0192 hex_value = DECODE_INSN_U16 (insn);
0193 printf("%u", hex_value);
0194 break;
0195 case A_R18:
0196 value = DECODE_INSN_I16 (insn) * 4;
0197 if (value == 0)
0198 printf("%d", value);
0199 else
0200 {
0201 hex_value = memaddr + value;
0202 print_address(hex_value & 0x3ffff);
0203 }
0204 break;
0205 case A_S18:
0206 value = DECODE_INSN_U16 (insn) * 4;
0207 if (value == 0)
0208 printf("%d", value);
0209 else
0210 print_address(value);
0211 break;
0212 case A_U18:
0213 value = DECODE_INSN_U18 (insn);
0214 if (value == 0 || 1)
0215 {
0216 hex_value = value;
0217 printf("%u", value);
0218 }
0219 else
0220 print_address(value);
0221 break;
0222 case A_U14:
0223 hex_value = DECODE_INSN_U14 (insn);
0224 printf("%u", hex_value);
0225 break;
0226 }
0227 if (arg != A_P && paren)
0228 {
0229 printf(")");
0230 paren--;
0231 }
0232 }
0233 if (hex_value > 16)
0234 printf("\t# %x", hex_value);
0235 }
0236 return 4;
0237 }