1 /* Disassemble V850 instructions. 2 Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2005, 2007, 2010, 3 2012 Free Software Foundation, Inc. 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 program; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 20 MA 02110-1301, USA. */ 21 22 23 #include "sysdep.h" 24 #include <stdio.h> 25 #include "opcode/v850.h" 26 #include "dis-asm.h" 27 #include "opintl.h" 28 29 static const char *const v850_reg_names[] = 30 { 31 "r0", "r1", "r2", "sp", "gp", "r5", "r6", "r7", 32 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", 33 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", 34 "r24", "r25", "r26", "r27", "r28", "r29", "ep", "lp" 35 }; 36 37 static const char *const v850_sreg_names[] = 38 { 39 "eipc/vip/mpm", "eipsw/mpc", "fepc/tid", "fepsw/ppa", "ecr/vmecr", "psw/vmtid", 40 "sr6/fpsr/vmadr/dcc", "sr7/fpepc/dc0", 41 "sr8/fpst/vpecr/dcv1", "sr9/fpcc/vptid", "sr10/fpcfg/vpadr/spal", "sr11/spau", 42 "sr12/vdecr/ipa0l", "eiic/vdtid/ipa0u", "feic/ipa1l", "dbic/ipa1u", 43 "ctpc/ipa2l", "ctpsw/ipa2u", "dbpc/ipa3l", "dbpsw/ipa3u", "ctbp/dpa0l", 44 "dir/dpa0u", "bpc/dpa0u", "asid/dpa1l", 45 "bpav/dpa1u", "bpam/dpa2l", "bpdv/dpa2u", "bpdm/dpa3l", "eiwr/dpa3u", 46 "fewr", "dbwr", "bsel" 47 }; 48 49 static const char *const v850_cc_names[] = 50 { 51 "v", "c/l", "z", "nh", "s/n", "t", "lt", "le", 52 "nv", "nc/nl", "nz", "h", "ns/p", "sa", "ge", "gt" 53 }; 54 55 static const char *const v850_float_cc_names[] = 56 { 57 "f/t", "un/or", "eq/neq", "ueq/ogl", "olt/uge", "ult/oge", "ole/ugt", "ule/ogt", 58 "sf/st", "ngle/gle", "seq/sne", "ngl/gl", "lt/nlt", "nge/ge", "le/nle", "ngt/gt" 59 }; 60 61 62 static void 63 print_value (int flags, bfd_vma memaddr, struct disassemble_info *info, long value) 64 { 65 if (flags & V850_PCREL) 66 { 67 bfd_vma addr = value + memaddr; 68 info->print_address_func (addr, info); 69 } 70 else if (flags & V850_OPERAND_DISP) 71 { 72 if (flags & V850_OPERAND_SIGNED) 73 { 74 info->fprintf_func (info->stream, "%ld", value); 75 } 76 else 77 { 78 info->fprintf_func (info->stream, "%lu", value); 79 } 80 } 81 else if (flags & V850E_IMMEDIATE32) 82 { 83 info->fprintf_func (info->stream, "0x%lx", value); 84 } 85 else 86 { 87 if (flags & V850_OPERAND_SIGNED) 88 { 89 info->fprintf_func (info->stream, "%ld", value); 90 } 91 else 92 { 93 info->fprintf_func (info->stream, "%lu", value); 94 } 95 } 96 } 97 98 static long 99 get_operand_value (const struct v850_operand *operand, 100 unsigned long insn, 101 int bytes_read, 102 bfd_vma memaddr, 103 struct disassemble_info * info, 104 bfd_boolean noerror, 105 int *invalid) 106 { 107 long value; 108 bfd_byte buffer[4]; 109 110 if ((operand->flags & V850E_IMMEDIATE16) 111 || (operand->flags & V850E_IMMEDIATE16HI)) 112 { 113 int status = info->read_memory_func (memaddr + bytes_read, buffer, 2, info); 114 115 if (status == 0) 116 { 117 value = bfd_getl16 (buffer); 118 119 if (operand->flags & V850E_IMMEDIATE16HI) 120 value <<= 16; 121 122 return value; 123 } 124 125 if (!noerror) 126 info->memory_error_func (status, memaddr + bytes_read, info); 127 128 return 0; 129 } 130 131 if (operand->flags & V850E_IMMEDIATE23) 132 { 133 int status = info->read_memory_func (memaddr + 2, buffer, 4, info); 134 135 if (status == 0) 136 { 137 value = bfd_getl32 (buffer); 138 139 value = (operand->extract) (value, invalid); 140 141 return value; 142 } 143 144 if (!noerror) 145 info->memory_error_func (status, memaddr + bytes_read, info); 146 147 return 0; 148 } 149 150 if (operand->flags & V850E_IMMEDIATE32) 151 { 152 int status = info->read_memory_func (memaddr + bytes_read, buffer, 4, info); 153 154 if (status == 0) 155 { 156 bytes_read += 4; 157 value = bfd_getl32 (buffer); 158 159 return value; 160 } 161 162 if (!noerror) 163 info->memory_error_func (status, memaddr + bytes_read, info); 164 165 return 0; 166 } 167 168 if (operand->extract) 169 value = (operand->extract) (insn, invalid); 170 else 171 { 172 if (operand->bits == -1) 173 value = (insn & operand->shift); 174 else 175 value = (insn >> operand->shift) & ((1 << operand->bits) - 1); 176 177 if (operand->flags & V850_OPERAND_SIGNED) 178 value = ((long)(value << (sizeof (long)*8 - operand->bits)) 179 >> (sizeof (long)*8 - operand->bits)); 180 } 181 182 return value; 183 } 184 185 186 static int 187 disassemble (bfd_vma memaddr, struct disassemble_info *info, int bytes_read, unsigned long insn) 188 { 189 struct v850_opcode *op = (struct v850_opcode *)v850_opcodes; 190 const struct v850_operand *operand; 191 int match = 0; 192 int target_processor; 193 194 switch (info->mach) 195 { 196 case 0: 197 default: 198 target_processor = PROCESSOR_V850; 199 break; 200 201 case bfd_mach_v850e: 202 target_processor = PROCESSOR_V850E; 203 break; 204 205 case bfd_mach_v850e1: 206 target_processor = PROCESSOR_V850E; 207 break; 208 209 case bfd_mach_v850e2: 210 target_processor = PROCESSOR_V850E2; 211 break; 212 213 case bfd_mach_v850e2v3: 214 target_processor = PROCESSOR_V850E2V3; 215 break; 216 } 217 218 /* If this is a two byte insn, then mask off the high bits. */ 219 if (bytes_read == 2) 220 insn &= 0xffff; 221 222 /* Find the opcode. */ 223 while (op->name) 224 { 225 if ((op->mask & insn) == op->opcode 226 && (op->processors & target_processor) 227 && !(op->processors & PROCESSOR_OPTION_ALIAS)) 228 { 229 /* Code check start. */ 230 const unsigned char *opindex_ptr; 231 unsigned int opnum; 232 unsigned int memop; 233 234 for (opindex_ptr = op->operands, opnum = 1; 235 *opindex_ptr != 0; 236 opindex_ptr++, opnum++) 237 { 238 int invalid = 0; 239 long value; 240 241 operand = &v850_operands[*opindex_ptr]; 242 243 value = get_operand_value (operand, insn, bytes_read, memaddr, info, 1, &invalid); 244 245 if (invalid) 246 goto next_opcode; 247 248 if ((operand->flags & V850_NOT_R0) && value == 0 && (op->memop) <=2) 249 goto next_opcode; 250 251 if ((operand->flags & V850_NOT_SA) && value == 0xd) 252 goto next_opcode; 253 254 if ((operand->flags & V850_NOT_IMM0) && value == 0) 255 goto next_opcode; 256 } 257 258 /* Code check end. */ 259 260 match = 1; 261 (*info->fprintf_func) (info->stream, "%s\t", op->name); 262 #if 0 263 fprintf (stderr, "match: insn: %lx, mask: %lx, opcode: %lx, name: %s\n", 264 insn, op->mask, op->opcode, op->name ); 265 #endif 266 267 memop = op->memop; 268 /* Now print the operands. 269 270 MEMOP is the operand number at which a memory 271 address specification starts, or zero if this 272 instruction has no memory addresses. 273 274 A memory address is always two arguments. 275 276 This information allows us to determine when to 277 insert commas into the output stream as well as 278 when to insert disp[reg] expressions onto the 279 output stream. */ 280 281 for (opindex_ptr = op->operands, opnum = 1; 282 *opindex_ptr != 0; 283 opindex_ptr++, opnum++) 284 { 285 bfd_boolean square = FALSE; 286 long value; 287 int flag; 288 char *prefix; 289 290 operand = &v850_operands[*opindex_ptr]; 291 292 value = get_operand_value (operand, insn, bytes_read, memaddr, info, 0, 0); 293 294 /* The first operand is always output without any 295 special handling. 296 297 For the following arguments: 298 299 If memop && opnum == memop + 1, then we need '[' since 300 we're about to output the register used in a memory 301 reference. 302 303 If memop && opnum == memop + 2, then we need ']' since 304 we just finished the register in a memory reference. We 305 also need a ',' before this operand. 306 307 Else we just need a comma. 308 309 We may need to output a trailing ']' if the last operand 310 in an instruction is the register for a memory address. 311 312 The exception (and there's always an exception) is the 313 "jmp" insn which needs square brackets around it's only 314 register argument. */ 315 prefix = ""; 316 if (operand->flags & V850_OPERAND_BANG) 317 { 318 prefix = "!"; 319 } 320 else if (operand->flags & V850_OPERAND_PERCENT) 321 { 322 prefix = "%"; 323 } 324 325 if (opnum == 1 && opnum == memop) 326 { 327 info->fprintf_func (info->stream, "%s[", prefix); 328 square = TRUE; 329 } 330 else if (opnum > 1 331 && (v850_operands[*(opindex_ptr - 1)].flags & V850_OPERAND_DISP) != 0 332 && opnum == memop) 333 { 334 info->fprintf_func (info->stream, "%s[", prefix); 335 square = TRUE; 336 } 337 else if (opnum > 1) 338 info->fprintf_func (info->stream, ", %s", prefix); 339 340 /* Extract the flags, ignoring ones which do not effect disassembly output. */ 341 flag = operand->flags & (V850_OPERAND_REG 342 | V850_REG_EVEN 343 | V850_OPERAND_EP 344 | V850_OPERAND_SRG 345 | V850E_OPERAND_REG_LIST 346 | V850_OPERAND_CC 347 | V850_OPERAND_FLOAT_CC); 348 349 switch (flag) 350 { 351 case V850_OPERAND_REG: info->fprintf_func (info->stream, "%s", v850_reg_names[value]); break; 352 case (V850_OPERAND_REG|V850_REG_EVEN): info->fprintf_func (info->stream, "%s", v850_reg_names[value*2]); break; 353 case V850_OPERAND_EP: info->fprintf_func (info->stream, "ep"); break; 354 case V850_OPERAND_SRG: info->fprintf_func (info->stream, "%s", v850_sreg_names[value]); break; 355 356 case V850E_OPERAND_REG_LIST: 357 { 358 static int list12_regs[32] = { 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 359 0, 0, 0, 0, 0, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 }; 360 int *regs; 361 int i; 362 unsigned long int mask = 0; 363 int pc = 0; 364 365 366 switch (operand->shift) 367 { 368 case 0xffe00001: regs = list12_regs; break; 369 default: 370 /* xgettext:c-format */ 371 fprintf (stderr, _("unknown operand shift: %x\n"), operand->shift ); 372 abort (); 373 } 374 375 for (i = 0; i < 32; i++) 376 { 377 if (value & (1 << i)) 378 { 379 switch (regs[ i ]) 380 { 381 default: mask |= (1 << regs[ i ]); break; 382 /* xgettext:c-format */ 383 case 0: fprintf (stderr, _("unknown reg: %d\n"), i ); abort (); 384 case -1: pc = 1; break; 385 } 386 } 387 } 388 389 info->fprintf_func (info->stream, "{"); 390 391 if (mask || pc) 392 { 393 if (mask) 394 { 395 unsigned int bit; 396 int shown_one = 0; 397 398 for (bit = 0; bit < 32; bit++) 399 if (mask & (1 << bit)) 400 { 401 unsigned long int first = bit; 402 unsigned long int last; 403 404 if (shown_one) 405 info->fprintf_func (info->stream, ", "); 406 else 407 shown_one = 1; 408 409 info->fprintf_func (info->stream, "%s", v850_reg_names[first]); 410 411 for (bit++; bit < 32; bit++) 412 if ((mask & (1 << bit)) == 0) 413 break; 414 415 last = bit; 416 417 if (last > first + 1) 418 { 419 info->fprintf_func (info->stream, " - %s", v850_reg_names[ last - 1 ]); 420 } 421 } 422 } 423 424 if (pc) 425 info->fprintf_func (info->stream, "%sPC", mask ? ", " : ""); 426 } 427 428 info->fprintf_func (info->stream, "}"); 429 } 430 break; 431 432 case V850_OPERAND_CC: info->fprintf_func (info->stream, "%s", v850_cc_names[value]); break; 433 case V850_OPERAND_FLOAT_CC: info->fprintf_func (info->stream, "%s", v850_float_cc_names[value]); break; 434 435 default: 436 print_value (operand->flags, memaddr, info, value); 437 break; 438 } 439 440 if (square) 441 (*info->fprintf_func) (info->stream, "]"); 442 } 443 444 /* All done. */ 445 break; 446 } 447 next_opcode: 448 op++; 449 } 450 451 return match; 452 } 453 454 int 455 print_insn_v850 (bfd_vma memaddr, struct disassemble_info * info) 456 { 457 int status, status2, match; 458 bfd_byte buffer[8]; 459 int length = 0, code_length = 0; 460 unsigned long insn = 0, insn2 = 0; 461 int target_processor; 462 463 switch (info->mach) 464 { 465 case 0: 466 default: 467 target_processor = PROCESSOR_V850; 468 break; 469 470 case bfd_mach_v850e: 471 target_processor = PROCESSOR_V850E; 472 break; 473 474 case bfd_mach_v850e1: 475 target_processor = PROCESSOR_V850E; 476 break; 477 478 case bfd_mach_v850e2: 479 target_processor = PROCESSOR_V850E2; 480 break; 481 482 case bfd_mach_v850e2v3: 483 target_processor = PROCESSOR_V850E2V3; 484 break; 485 } 486 487 status = info->read_memory_func (memaddr, buffer, 2, info); 488 489 if (status) 490 { 491 info->memory_error_func (status, memaddr, info); 492 return -1; 493 } 494 495 insn = bfd_getl16 (buffer); 496 497 status2 = info->read_memory_func (memaddr+2, buffer, 2 , info); 498 499 if (!status2) 500 { 501 insn2 = bfd_getl16 (buffer); 502 /* fprintf (stderr, "insn2 0x%08lx\n", insn2); */ 503 } 504 505 /* Special case. */ 506 if (length == 0 507 && (target_processor == PROCESSOR_V850E2 508 || target_processor == PROCESSOR_V850E2V3)) 509 { 510 if ((insn & 0xffff) == 0x02e0 /* jr 32bit */ 511 && !status2 && (insn2 & 0x1) == 0) 512 { 513 length = 2; 514 code_length = 6; 515 } 516 else if ((insn & 0xffe0) == 0x02e0 /* jarl 32bit */ 517 && !status2 && (insn2 & 0x1) == 0) 518 { 519 length = 2; 520 code_length = 6; 521 } 522 else if ((insn & 0xffe0) == 0x06e0 /* jmp 32bit */ 523 && !status2 && (insn2 & 0x1) == 0) 524 { 525 length = 2; 526 code_length = 6; 527 } 528 } 529 530 if (length == 0 531 && target_processor == PROCESSOR_V850E2V3) 532 { 533 if (((insn & 0xffe0) == 0x0780 /* ld.b 23bit */ 534 && !status2 && (insn2 & 0x000f) == 0x0005) 535 || ((insn & 0xffe0) == 0x07a0 /* ld.bu 23bit */ 536 && !status2 && (insn2 & 0x000f) == 0x0005) 537 || ((insn & 0xffe0) == 0x0780 /* ld.h 23bit */ 538 && !status2 && (insn2 & 0x000f) == 0x0007) 539 || ((insn & 0xffe0) == 0x07a0 /* ld.hu 23bit */ 540 && !status2 && (insn2 & 0x000f) == 0x0007) 541 || ((insn & 0xffe0) == 0x0780 /* ld.w 23bit */ 542 && !status2 && (insn2 & 0x000f) == 0x0009)) 543 { 544 length = 4; 545 code_length = 6; 546 } 547 else if (((insn & 0xffe0) == 0x0780 /* st.b 23bit */ 548 && !status2 && (insn2 & 0x000f) == 0x000d) 549 || ((insn & 0xffe0) == 0x07a0 /* st.h 23bit */ 550 && !status2 && (insn2 & 0x000f) == 0x000d) 551 || ((insn & 0xffe0) == 0x0780 /* st.w 23bit */ 552 && !status2 && (insn2 & 0x000f) == 0x000f)) 553 { 554 length = 4; 555 code_length = 6; 556 } 557 } 558 559 if (length == 0 560 && target_processor != PROCESSOR_V850) 561 { 562 if ((insn & 0xffe0) == 0x0620) /* 32 bit MOV */ 563 { 564 length = 2; 565 code_length = 6; 566 } 567 else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm16<<16 */ 568 && !status2 && (insn2 & 0x001f) == 0x0013) 569 { 570 length = 4; 571 code_length = 6; 572 } 573 else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm16 */ 574 && !status2 && (insn2 & 0x001f) == 0x000b) 575 { 576 length = 4; 577 code_length = 6; 578 } 579 else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm32 */ 580 && !status2 && (insn2 & 0x001f) == 0x001b) 581 { 582 length = 4; 583 code_length = 8; 584 } 585 } 586 587 if (length == 4 588 || (length == 0 589 && (insn & 0x0600) == 0x0600)) 590 { 591 /* This is a 4 byte insn. */ 592 status = info->read_memory_func (memaddr, buffer, 4, info); 593 if (!status) 594 { 595 insn = bfd_getl32 (buffer); 596 597 if (!length) 598 length = code_length = 4; 599 } 600 } 601 602 if (code_length > length) 603 { 604 status = info->read_memory_func (memaddr + length, buffer, code_length - length, info); 605 if (status) 606 length = 0; 607 } 608 609 if (length == 0 && !status) 610 length = code_length = 2; 611 612 if (length == 2) 613 insn &= 0xffff; 614 615 match = disassemble (memaddr, info, length, insn); 616 617 if (!match) 618 { 619 int l = 0; 620 621 status = info->read_memory_func (memaddr, buffer, code_length, info); 622 623 while (l < code_length) 624 { 625 if (code_length - l == 2) 626 { 627 insn = bfd_getl16 (buffer + l) & 0xffff; 628 info->fprintf_func (info->stream, ".short\t0x%04lx", insn); 629 l += 2; 630 } 631 else 632 { 633 insn = bfd_getl32 (buffer + l); 634 info->fprintf_func (info->stream, ".long\t0x%08lx", insn); 635 l += 4; 636 } 637 } 638 } 639 640 return code_length; 641 } 642