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