00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <stdio.h>
00019 #include "sysdep.h"
00020 #include "opcode/d30v.h"
00021 #include "dis-asm.h"
00022 #include "opintl.h"
00023
00024 #define PC_MASK 0xFFFFFFFF
00025
00026 static int lookup_opcode PARAMS ((struct d30v_insn *insn, long num, int is_long));
00027 static void print_insn PARAMS ((struct disassemble_info *info, bfd_vma memaddr, long long num,
00028 struct d30v_insn *insn, int is_long, int show_ext));
00029 static int extract_value PARAMS ((long long num, struct d30v_operand *oper, int is_long));
00030
00031 int
00032 print_insn_d30v (memaddr, info)
00033 bfd_vma memaddr;
00034 struct disassemble_info *info;
00035 {
00036 int status, result;
00037 bfd_byte buffer[12];
00038 unsigned long in1, in2;
00039 struct d30v_insn insn;
00040 long long num;
00041
00042 insn.form = (struct d30v_format *) NULL;
00043
00044 info->bytes_per_line = 8;
00045 info->bytes_per_chunk = 4;
00046 info->display_endian = BFD_ENDIAN_BIG;
00047
00048 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
00049 if (status != 0)
00050 {
00051 (*info->memory_error_func) (status, memaddr, info);
00052 return -1;
00053 }
00054 in1 = bfd_getb32 (buffer);
00055
00056 status = (*info->read_memory_func) (memaddr + 4, buffer, 4, info);
00057 if (status != 0)
00058 {
00059 info->bytes_per_line = 8;
00060 if (!(result = lookup_opcode (&insn, in1, 0)))
00061 (*info->fprintf_func) (info->stream, ".long\t0x%x", in1);
00062 else
00063 print_insn (info, memaddr, (long long) in1, &insn, 0, result);
00064 return 4;
00065 }
00066 in2 = bfd_getb32 (buffer);
00067
00068 if (in1 & in2 & FM01)
00069 {
00070
00071 if (!(result = lookup_opcode (&insn, in1, 1)))
00072 {
00073 (*info->fprintf_func) (info->stream, ".long\t0x%x,0x%x", in1, in2);
00074 return 8;
00075 }
00076 num = (long long) in1 << 32 | in2;
00077 print_insn (info, memaddr, num, &insn, 1, result);
00078 }
00079 else
00080 {
00081 num = in1;
00082 if (!(result = lookup_opcode (&insn, in1, 0)))
00083 (*info->fprintf_func) (info->stream, ".long\t0x%x", in1);
00084 else
00085 print_insn (info, memaddr, num, &insn, 0, result);
00086
00087 switch (((in1 >> 31) << 1) | (in2 >> 31))
00088 {
00089 case 0:
00090 (*info->fprintf_func) (info->stream, "\t||\t");
00091 break;
00092 case 1:
00093 (*info->fprintf_func) (info->stream, "\t->\t");
00094 break;
00095 case 2:
00096 (*info->fprintf_func) (info->stream, "\t<-\t");
00097 default:
00098 break;
00099 }
00100
00101 insn.form = (struct d30v_format *) NULL;
00102 num = in2;
00103 if (!(result = lookup_opcode (&insn, in2, 0)))
00104 (*info->fprintf_func) (info->stream, ".long\t0x%x", in2);
00105 else
00106 print_insn (info, memaddr, num, &insn, 0, result);
00107 }
00108 return 8;
00109 }
00110
00111
00112
00113
00114
00115 static int
00116 lookup_opcode (insn, num, is_long)
00117 struct d30v_insn *insn;
00118 long num;
00119 int is_long;
00120 {
00121 int i = 0, index;
00122 struct d30v_format *f;
00123 struct d30v_opcode *op = (struct d30v_opcode *) d30v_opcode_table;
00124 int op1 = (num >> 25) & 0x7;
00125 int op2 = (num >> 20) & 0x1f;
00126 int mod = (num >> 18) & 0x3;
00127
00128
00129 do
00130 {
00131 if ((op->op1 == op1) && (op->op2 == op2))
00132 break;
00133 op++;
00134 }
00135 while (op->name);
00136
00137 if (!op || !op->name)
00138 return 0;
00139
00140 while (op->op1 == op1 && op->op2 == op2)
00141 {
00142
00143 index = op->format[i++];
00144 do
00145 {
00146 f = (struct d30v_format *) &d30v_format_table[index];
00147 while (f->form == index)
00148 {
00149 if ((!is_long || f->form >= LONG) && (f->modifier == mod))
00150 {
00151 insn->form = f;
00152 break;
00153 }
00154 f++;
00155 }
00156 if (insn->form)
00157 break;
00158 }
00159 while ((index = op->format[i++]) != 0);
00160 if (insn->form)
00161 break;
00162 op++;
00163 i = 0;
00164 }
00165 if (insn->form == NULL)
00166 return 0;
00167
00168 insn->op = op;
00169 insn->ecc = (num >> 28) & 0x7;
00170 if (op->format[1])
00171 return 2;
00172 else
00173 return 1;
00174 }
00175
00176 static void
00177 print_insn (info, memaddr, num, insn, is_long, show_ext)
00178 struct disassemble_info *info;
00179 bfd_vma memaddr;
00180 long long num;
00181 struct d30v_insn *insn;
00182 int is_long;
00183 int show_ext;
00184 {
00185 int val, opnum, need_comma = 0;
00186 struct d30v_operand *oper;
00187 int i, match, opind = 0, need_paren = 0, found_control = 0;
00188
00189 (*info->fprintf_func) (info->stream, "%s", insn->op->name);
00190
00191
00192 if (d30v_operand_table[insn->form->operands[0]].flags & OPERAND_NAME)
00193 {
00194 opind++;
00195 val =
00196 extract_value (num,
00197 (struct d30v_operand *) &d30v_operand_table[insn->form->operands[0]],
00198 is_long);
00199 (*info->fprintf_func) (info->stream, "%s", d30v_cc_names[val]);
00200 }
00201
00202
00203 if (show_ext == 2)
00204 {
00205 if (is_long)
00206 (*info->fprintf_func) (info->stream, ".l");
00207 else
00208 (*info->fprintf_func) (info->stream, ".s");
00209 }
00210
00211 if (insn->ecc)
00212 (*info->fprintf_func) (info->stream, "/%s", d30v_ecc_names[insn->ecc]);
00213
00214 (*info->fprintf_func) (info->stream, "\t");
00215
00216 while ((opnum = insn->form->operands[opind++]) != 0)
00217 {
00218 int bits;
00219 oper = (struct d30v_operand *) &d30v_operand_table[opnum];
00220 bits = oper->bits;
00221 if (oper->flags & OPERAND_SHIFT)
00222 bits += 3;
00223
00224 if (need_comma
00225 && oper->flags != OPERAND_PLUS
00226 && oper->flags != OPERAND_MINUS)
00227 {
00228 need_comma = 0;
00229 (*info->fprintf_func) (info->stream, ", ");
00230 }
00231
00232 if (oper->flags == OPERAND_ATMINUS)
00233 {
00234 (*info->fprintf_func) (info->stream, "@-");
00235 continue;
00236 }
00237 if (oper->flags == OPERAND_MINUS)
00238 {
00239 (*info->fprintf_func) (info->stream, "-");
00240 continue;
00241 }
00242 if (oper->flags == OPERAND_PLUS)
00243 {
00244 (*info->fprintf_func) (info->stream, "+");
00245 continue;
00246 }
00247 if (oper->flags == OPERAND_ATSIGN)
00248 {
00249 (*info->fprintf_func) (info->stream, "@");
00250 continue;
00251 }
00252 if (oper->flags == OPERAND_ATPAR)
00253 {
00254 (*info->fprintf_func) (info->stream, "@(");
00255 need_paren = 1;
00256 continue;
00257 }
00258
00259 if (oper->flags == OPERAND_SPECIAL)
00260 continue;
00261
00262 val = extract_value (num, oper, is_long);
00263
00264 if (oper->flags & OPERAND_REG)
00265 {
00266 match = 0;
00267 if (oper->flags & OPERAND_CONTROL)
00268 {
00269 struct d30v_operand *oper3 =
00270 (struct d30v_operand *) &d30v_operand_table[insn->form->operands[2]];
00271 int id = extract_value (num, oper3, is_long);
00272 found_control = 1;
00273 switch (id)
00274 {
00275 case 0:
00276 val |= OPERAND_CONTROL;
00277 break;
00278 case 1:
00279 case 2:
00280 val = OPERAND_CONTROL + MAX_CONTROL_REG + id;
00281 break;
00282 case 3:
00283 val |= OPERAND_FLAG;
00284 break;
00285 default:
00286 fprintf (stderr, "illegal id (%d)\n", id);
00287 }
00288 }
00289 else if (oper->flags & OPERAND_ACC)
00290 val |= OPERAND_ACC;
00291 else if (oper->flags & OPERAND_FLAG)
00292 val |= OPERAND_FLAG;
00293 for (i = 0; i < reg_name_cnt (); i++)
00294 {
00295 if (val == pre_defined_registers[i].value)
00296 {
00297 if (pre_defined_registers[i].pname)
00298 (*info->fprintf_func)
00299 (info->stream, "%s", pre_defined_registers[i].pname);
00300 else
00301 (*info->fprintf_func)
00302 (info->stream, "%s", pre_defined_registers[i].name);
00303 match = 1;
00304 break;
00305 }
00306 }
00307 if (match == 0)
00308 {
00309
00310
00311 (*info->fprintf_func)
00312 (info->stream, _("<unknown register %d>"), val & 0x3F);
00313 }
00314 }
00315
00316
00317
00318
00319
00320 else if (oper->flags & OPERAND_PCREL)
00321 {
00322 int neg = 0;
00323
00324
00325 if (oper->flags & OPERAND_SIGNED || bits == 32)
00326 {
00327 long max;
00328 max = (1 << (bits - 1));
00329 if (val & max)
00330 {
00331 if (bits == 32)
00332 val = -val;
00333 else
00334 val = -val & ((1 << bits) - 1);
00335 neg = 1;
00336 }
00337 }
00338 if (neg)
00339 {
00340 (*info->fprintf_func) (info->stream, "-%x\t(", val);
00341 (*info->print_address_func) ((memaddr - val) & PC_MASK, info);
00342 (*info->fprintf_func) (info->stream, ")");
00343 }
00344 else
00345 {
00346 (*info->fprintf_func) (info->stream, "%x\t(", val);
00347 (*info->print_address_func) ((memaddr + val) & PC_MASK, info);
00348 (*info->fprintf_func) (info->stream, ")");
00349 }
00350 }
00351 else if (insn->op->reloc_flag == RELOC_ABS)
00352 {
00353 (*info->print_address_func) (val, info);
00354 }
00355 else
00356 {
00357 if (oper->flags & OPERAND_SIGNED)
00358 {
00359 int max = (1 << (bits - 1));
00360 if (val & max)
00361 {
00362 val = -val;
00363 if (bits < 32)
00364 val &= ((1 << bits) - 1);
00365 (*info->fprintf_func) (info->stream, "-");
00366 }
00367 }
00368 (*info->fprintf_func) (info->stream, "0x%x", val);
00369 }
00370
00371 if (insn->form->operands[opind] && !(found_control && opind == 2))
00372 need_comma = 1;
00373 }
00374 if (need_paren)
00375 (*info->fprintf_func) (info->stream, ")");
00376 }
00377
00378 static int
00379 extract_value (num, oper, is_long)
00380 long long num;
00381 struct d30v_operand *oper;
00382 int is_long;
00383 {
00384 int val;
00385 int shift = 12 - oper->position;
00386 int mask = (0xFFFFFFFF >> (32 - oper->bits));
00387
00388 if (is_long)
00389 {
00390 if (oper->bits == 32)
00391 {
00392
00393 val = ((num & 0x3FFFF)
00394 | ((num & 0xFF00000) >> 2)
00395 | ((num & 0x3F00000000LL) >> 6));
00396 }
00397 else
00398 val = (num >> (32 + shift)) & mask;
00399 }
00400 else
00401 val = (num >> shift) & mask;
00402
00403 if (oper->flags & OPERAND_SHIFT)
00404 val <<= 3;
00405
00406 return val;
00407 }