1211501Sanchie/* Disassemble V850 instructions. 2211501Sanchie Copyright (C) 1996-2022 Free Software Foundation, Inc. 3211501Sanchie 4211501Sanchie This file is part of the GNU opcodes library. 5211501Sanchie 6211501Sanchie This library is free software; you can redistribute it and/or modify 7211501Sanchie it under the terms of the GNU General Public License as published by 8211501Sanchie the Free Software Foundation; either version 3, or (at your option) 9211501Sanchie any later version. 10211501Sanchie 11211501Sanchie It is distributed in the hope that it will be useful, but WITHOUT 12211501Sanchie ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13211501Sanchie or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 14211501Sanchie License for more details. 15211501Sanchie 16211501Sanchie You should have received a copy of the GNU General Public License 17211501Sanchie along with this program; if not, write to the Free Software 18211501Sanchie Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 19211501Sanchie MA 02110-1301, USA. */ 20211501Sanchie 21211501Sanchie 22211501Sanchie#include "sysdep.h" 23211501Sanchie#include <stdio.h> 24211501Sanchie#include <string.h> 25211501Sanchie#include "opcode/v850.h" 26211501Sanchie#include "disassemble.h" 27211501Sanchie#include "opintl.h" 28211501Sanchie#include "libiberty.h" 29211501Sanchie 30254889Smarkjstatic const int v850_cacheop_codes[] = 31254889Smarkj{ 32211501Sanchie 0x00, 0x20, 0x40, 0x60, 0x61, 0x04, 0x06, 33211501Sanchie 0x07, 0x24, 0x26, 0x27, 0x44, 0x64, 0x65, -1 34211501Sanchie}; 35211501Sanchie 36211501Sanchiestatic const int v850_prefop_codes[] = 37211501Sanchie{ 0x00, 0x04, -1}; 38254889Smarkj 39211501Sanchiestatic void 40211501Sanchieprint_value (int flags, 41211501Sanchie bfd_vma memaddr, 42211501Sanchie struct disassemble_info *info, 43211501Sanchie long value) 44211501Sanchie{ 45211501Sanchie if (flags & V850_PCREL) 46211501Sanchie { 47211501Sanchie bfd_vma addr = value + memaddr; 48211501Sanchie 49211501Sanchie if (flags & V850_INVERSE_PCREL) 50211501Sanchie addr = memaddr - value; 51211501Sanchie info->print_address_func (addr, info); 52254889Smarkj } 53211501Sanchie else if (flags & V850_OPERAND_DISP) 54211501Sanchie { 55211501Sanchie if (flags & V850_OPERAND_SIGNED) 56211501Sanchie { 57211501Sanchie info->fprintf_func (info->stream, "%ld", value); 58211501Sanchie } 59211501Sanchie else 60211501Sanchie { 61211501Sanchie info->fprintf_func (info->stream, "%lu", value); 62227293Sed } 63211501Sanchie } 64211501Sanchie else if ((flags & V850E_IMMEDIATE32) 65211501Sanchie || (flags & V850E_IMMEDIATE16HI)) 66211501Sanchie { 67215701Sdim info->fprintf_func (info->stream, "0x%lx", value); 68211501Sanchie } 69211501Sanchie else 70211501Sanchie { 71211501Sanchie if (flags & V850_OPERAND_SIGNED) 72211501Sanchie { 73211501Sanchie info->fprintf_func (info->stream, "%ld", value); 74211501Sanchie } 75211501Sanchie else 76211501Sanchie { 77211501Sanchie info->fprintf_func (info->stream, "%lu", value); 78211501Sanchie } 79211501Sanchie } 80211501Sanchie} 81211501Sanchie 82211501Sanchiestatic long 83211501Sanchieget_operand_value (const struct v850_operand *operand, 84211501Sanchie unsigned long insn, 85211501Sanchie int bytes_read, 86211501Sanchie bfd_vma memaddr, 87211501Sanchie struct disassemble_info * info, 88211501Sanchie bool noerror, 89211501Sanchie int *invalid) 90211501Sanchie{ 91211501Sanchie unsigned long value; 92211501Sanchie bfd_byte buffer[4]; 93211501Sanchie 94211501Sanchie if ((operand->flags & V850E_IMMEDIATE16) 95211501Sanchie || (operand->flags & V850E_IMMEDIATE16HI)) 96211501Sanchie { 97211501Sanchie int status = info->read_memory_func (memaddr + bytes_read, buffer, 2, info); 98211501Sanchie 99211501Sanchie if (status == 0) 100211501Sanchie { 101211501Sanchie value = bfd_getl16 (buffer); 102211501Sanchie 103211501Sanchie if (operand->flags & V850E_IMMEDIATE16HI) 104211501Sanchie value <<= 16; 105211501Sanchie else if (value & 0x8000) 106211501Sanchie value |= (-1UL << 16); 107211501Sanchie 108211501Sanchie return value; 109211501Sanchie } 110211501Sanchie 111211501Sanchie if (!noerror) 112211501Sanchie info->memory_error_func (status, memaddr + bytes_read, info); 113211501Sanchie 114211501Sanchie return 0; 115211501Sanchie } 116211501Sanchie 117211501Sanchie if (operand->flags & V850E_IMMEDIATE23) 118211501Sanchie { 119211501Sanchie int status = info->read_memory_func (memaddr + 2, buffer, 4, info); 120211501Sanchie 121211501Sanchie if (status == 0) 122211501Sanchie { 123211501Sanchie value = bfd_getl32 (buffer); 124211501Sanchie 125211501Sanchie value = (operand->extract) (value, invalid); 126211501Sanchie 127211501Sanchie return value; 128211501Sanchie } 129211501Sanchie 130211501Sanchie if (!noerror) 131211501Sanchie info->memory_error_func (status, memaddr + bytes_read, info); 132211501Sanchie 133211501Sanchie return 0; 134211501Sanchie } 135211501Sanchie 136211501Sanchie if (operand->flags & V850E_IMMEDIATE32) 137211501Sanchie { 138211501Sanchie int status = info->read_memory_func (memaddr + bytes_read, buffer, 4, info); 139211501Sanchie 140211501Sanchie if (status == 0) 141211501Sanchie { 142211501Sanchie bytes_read += 4; 143211501Sanchie value = bfd_getl32 (buffer); 144211501Sanchie 145211501Sanchie return value; 146211501Sanchie } 147211501Sanchie 148211501Sanchie if (!noerror) 149211501Sanchie info->memory_error_func (status, memaddr + bytes_read, info); 150211501Sanchie 151211501Sanchie return 0; 152211501Sanchie } 153211501Sanchie 154211501Sanchie if (operand->extract) 155211501Sanchie value = (operand->extract) (insn, invalid); 156211501Sanchie else 157211501Sanchie { 158211501Sanchie if (operand->bits == -1) 159211501Sanchie value = (insn & operand->shift); 160211501Sanchie else 161211501Sanchie value = (insn >> operand->shift) & ((1ul << operand->bits) - 1); 162211501Sanchie 163211501Sanchie if (operand->flags & V850_OPERAND_SIGNED) 164211501Sanchie { 165211501Sanchie unsigned long sign = 1ul << (operand->bits - 1); 166211501Sanchie value = (value ^ sign) - sign; 167211501Sanchie } 168211501Sanchie } 169211501Sanchie 170211501Sanchie return value; 171211501Sanchie} 172211501Sanchie 173211501Sanchiestatic const char * 174211501Sanchieget_v850_sreg_name (unsigned int reg) 175211501Sanchie{ 176211501Sanchie static const char *const v850_sreg_names[] = 177211501Sanchie { 178211501Sanchie "eipc/vip/mpm", "eipsw/mpc", "fepc/tid", "fepsw/ppa", "ecr/vmecr", "psw/vmtid", 179211501Sanchie "sr6/fpsr/vmadr/dcc", "sr7/fpepc/dc0", 180211501Sanchie "sr8/fpst/vpecr/dcv1", "sr9/fpcc/vptid", "sr10/fpcfg/vpadr/spal", "sr11/spau", 181211501Sanchie "sr12/vdecr/ipa0l", "eiic/vdtid/ipa0u", "feic/ipa1l", "dbic/ipa1u", 182211501Sanchie "ctpc/ipa2l", "ctpsw/ipa2u", "dbpc/ipa3l", "dbpsw/ipa3u", "ctbp/dpa0l", 183211501Sanchie "dir/dpa0u", "bpc/dpa0u", "asid/dpa1l", 184211501Sanchie "bpav/dpa1u", "bpam/dpa2l", "bpdv/dpa2u", "bpdm/dpa3l", "eiwr/dpa3u", 185211501Sanchie "fewr", "dbwr", "bsel" 186211501Sanchie }; 187254523Sandre 188254523Sandre if (reg < ARRAY_SIZE (v850_sreg_names)) 189254889Smarkj return v850_sreg_names[reg]; 190254889Smarkj return _("<invalid s-reg number>"); 191211501Sanchie} 192211501Sanchie 193211501Sanchiestatic const char * 194211501Sanchieget_v850_reg_name (unsigned int reg) 195211501Sanchie{ 196211501Sanchie static const char *const v850_reg_names[] = 197211501Sanchie { 198211501Sanchie "r0", "r1", "r2", "sp", "gp", "r5", "r6", "r7", 199211501Sanchie "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", 200211501Sanchie "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", 201211501Sanchie "r24", "r25", "r26", "r27", "r28", "r29", "ep", "lp" 202211501Sanchie }; 203211501Sanchie 204211501Sanchie if (reg < ARRAY_SIZE (v850_reg_names)) 205211501Sanchie return v850_reg_names[reg]; 206211501Sanchie return _("<invalid reg number>"); 207211501Sanchie} 208211501Sanchie 209211501Sanchiestatic const char * 210211501Sanchieget_v850_vreg_name (unsigned int reg) 211211501Sanchie{ 212211501Sanchie static const char *const v850_vreg_names[] = 213211501Sanchie { 214211501Sanchie "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7", "vr8", "vr9", 215211501Sanchie "vr10", "vr11", "vr12", "vr13", "vr14", "vr15", "vr16", "vr17", "vr18", 216211501Sanchie "vr19", "vr20", "vr21", "vr22", "vr23", "vr24", "vr25", "vr26", "vr27", 217211501Sanchie "vr28", "vr29", "vr30", "vr31" 218211501Sanchie }; 219211501Sanchie 220211501Sanchie if (reg < ARRAY_SIZE (v850_vreg_names)) 221211501Sanchie return v850_vreg_names[reg]; 222211501Sanchie return _("<invalid v-reg number>"); 223211501Sanchie} 224211501Sanchie 225211501Sanchiestatic const char * 226211501Sanchieget_v850_cc_name (unsigned int reg) 227211501Sanchie{ 228211501Sanchie static const char *const v850_cc_names[] = 229211501Sanchie { 230211501Sanchie "v", "c/l", "z", "nh", "s/n", "t", "lt", "le", 231211501Sanchie "nv", "nc/nl", "nz", "h", "ns/p", "sa", "ge", "gt" 232211501Sanchie }; 233211501Sanchie 234211501Sanchie if (reg < ARRAY_SIZE (v850_cc_names)) 235211501Sanchie return v850_cc_names[reg]; 236211501Sanchie return _("<invalid CC-reg number>"); 237211501Sanchie} 238211501Sanchie 239211501Sanchiestatic const char * 240211501Sanchieget_v850_float_cc_name (unsigned int reg) 241211501Sanchie{ 242211501Sanchie static const char *const v850_float_cc_names[] = 243211501Sanchie { 244211501Sanchie "f/t", "un/or", "eq/neq", "ueq/ogl", "olt/uge", "ult/oge", "ole/ugt", "ule/ogt", 245211501Sanchie "sf/st", "ngle/gle", "seq/sne", "ngl/gl", "lt/nlt", "nge/ge", "le/nle", "ngt/gt" 246211501Sanchie }; 247211501Sanchie 248211501Sanchie if (reg < ARRAY_SIZE (v850_float_cc_names)) 249211501Sanchie return v850_float_cc_names[reg]; 250211501Sanchie return _("<invalid float-CC-reg number>"); 251211501Sanchie} 252211501Sanchie 253211501Sanchiestatic const char * 254211501Sanchieget_v850_cacheop_name (unsigned int reg) 255211501Sanchie{ 256211501Sanchie static const char *const v850_cacheop_names[] = 257211501Sanchie { 258211501Sanchie "chbii", "cibii", "cfali", "cisti", "cildi", "chbid", "chbiwbd", 259211501Sanchie "chbwbd", "cibid", "cibiwbd", "cibwbd", "cfald", "cistd", "cildd" 260211501Sanchie }; 261211501Sanchie 262211501Sanchie if (reg < ARRAY_SIZE (v850_cacheop_names)) 263211501Sanchie return v850_cacheop_names[reg]; 264211501Sanchie return _("<invalid cacheop number>"); 265211501Sanchie} 266211501Sanchie 267211501Sanchiestatic const char * 268211501Sanchieget_v850_prefop_name (unsigned int reg) 269211501Sanchie{ 270211501Sanchie static const char *const v850_prefop_names[] = 271211501Sanchie { "prefi", "prefd" }; 272211501Sanchie 273211501Sanchie if (reg < ARRAY_SIZE (v850_prefop_names)) 274211501Sanchie return v850_prefop_names[reg]; 275211501Sanchie return _("<invalid prefop number>"); 276211501Sanchie} 277211501Sanchie 278211501Sanchiestatic int 279211501Sanchiedisassemble (bfd_vma memaddr, 280211501Sanchie struct disassemble_info *info, 281211501Sanchie int bytes_read, 282211501Sanchie unsigned long insn) 283211501Sanchie{ 284211501Sanchie struct v850_opcode *op = (struct v850_opcode *) v850_opcodes; 285211501Sanchie const struct v850_operand *operand; 286211501Sanchie int match = 0; 287211501Sanchie int target_processor; 288211501Sanchie 289211501Sanchie switch (info->mach) 290211501Sanchie { 291211501Sanchie case 0: 292211501Sanchie default: 293211501Sanchie target_processor = PROCESSOR_V850; 294211501Sanchie break; 295211501Sanchie 296211501Sanchie case bfd_mach_v850e: 297211501Sanchie target_processor = PROCESSOR_V850E; 298211501Sanchie break; 299211501Sanchie 300211501Sanchie case bfd_mach_v850e1: 301211501Sanchie target_processor = PROCESSOR_V850E; 302211501Sanchie break; 303211501Sanchie 304211501Sanchie case bfd_mach_v850e2: 305211501Sanchie target_processor = PROCESSOR_V850E2; 306211501Sanchie break; 307211501Sanchie 308211501Sanchie case bfd_mach_v850e2v3: 309211501Sanchie target_processor = PROCESSOR_V850E2V3; 310211501Sanchie break; 311211501Sanchie 312211501Sanchie case bfd_mach_v850e3v5: 313211501Sanchie target_processor = PROCESSOR_V850E3V5; 314211501Sanchie break; 315211501Sanchie } 316211501Sanchie 317211501Sanchie /* If this is a two byte insn, then mask off the high bits. */ 318211501Sanchie if (bytes_read == 2) 319211501Sanchie insn &= 0xffff; 320211501Sanchie 321211501Sanchie /* Find the opcode. */ 322211501Sanchie while (op->name) 323211501Sanchie { 324211501Sanchie if ((op->mask & insn) == op->opcode 325211501Sanchie && (op->processors & target_processor) 326211501Sanchie && !(op->processors & PROCESSOR_OPTION_ALIAS)) 327211501Sanchie { 328211501Sanchie /* Code check start. */ 329211501Sanchie const unsigned char *opindex_ptr; 330211501Sanchie unsigned int opnum; 331211501Sanchie unsigned int memop; 332211501Sanchie 333211501Sanchie for (opindex_ptr = op->operands, opnum = 1; 334211501Sanchie *opindex_ptr != 0; 335211501Sanchie opindex_ptr++, opnum++) 336211501Sanchie { 337211501Sanchie int invalid = 0; 338211501Sanchie long value; 339211501Sanchie 340211501Sanchie operand = &v850_operands[*opindex_ptr]; 341211501Sanchie 342211501Sanchie value = get_operand_value (operand, insn, bytes_read, memaddr, 343211501Sanchie info, 1, &invalid); 344211501Sanchie 345211501Sanchie if (invalid) 346211501Sanchie goto next_opcode; 347211501Sanchie 348211501Sanchie if ((operand->flags & V850_NOT_R0) && value == 0 && (op->memop) <=2) 349211501Sanchie goto next_opcode; 350211501Sanchie 351211501Sanchie if ((operand->flags & V850_NOT_SA) && value == 0xd) 352211501Sanchie goto next_opcode; 353211501Sanchie 354211501Sanchie if ((operand->flags & V850_NOT_IMM0) && value == 0) 355211501Sanchie goto next_opcode; 356211501Sanchie } 357211501Sanchie 358211501Sanchie /* Code check end. */ 359211501Sanchie 360211501Sanchie match = 1; 361211501Sanchie (*info->fprintf_func) (info->stream, "%s\t", op->name); 362211501Sanchie#if 0 363211501Sanchie fprintf (stderr, "match: insn: %lx, mask: %lx, opcode: %lx, name: %s\n", 364211501Sanchie insn, op->mask, op->opcode, op->name ); 365211501Sanchie#endif 366211501Sanchie 367211501Sanchie memop = op->memop; 368211501Sanchie /* Now print the operands. 369211501Sanchie 370211501Sanchie MEMOP is the operand number at which a memory 371211501Sanchie address specification starts, or zero if this 372241394Skevlo instruction has no memory addresses. 373211501Sanchie 374211501Sanchie A memory address is always two arguments. 375211501Sanchie 376 This information allows us to determine when to 377 insert commas into the output stream as well as 378 when to insert disp[reg] expressions onto the 379 output stream. */ 380 381 for (opindex_ptr = op->operands, opnum = 1; 382 *opindex_ptr != 0; 383 opindex_ptr++, opnum++) 384 { 385 bool square = false; 386 long value; 387 int flag; 388 char *prefix; 389 390 operand = &v850_operands[*opindex_ptr]; 391 392 value = get_operand_value (operand, insn, bytes_read, memaddr, 393 info, 0, 0); 394 395 /* The first operand is always output without any 396 special handling. 397 398 For the following arguments: 399 400 If memop && opnum == memop + 1, then we need '[' since 401 we're about to output the register used in a memory 402 reference. 403 404 If memop && opnum == memop + 2, then we need ']' since 405 we just finished the register in a memory reference. We 406 also need a ',' before this operand. 407 408 Else we just need a comma. 409 410 We may need to output a trailing ']' if the last operand 411 in an instruction is the register for a memory address. 412 413 The exception (and there's always an exception) are the 414 "jmp" insn which needs square brackets around it's only 415 register argument, and the clr1/not1/set1/tst1 insns 416 which [...] around their second register argument. */ 417 418 prefix = ""; 419 if (operand->flags & V850_OPERAND_BANG) 420 { 421 prefix = "!"; 422 } 423 else if (operand->flags & V850_OPERAND_PERCENT) 424 { 425 prefix = "%"; 426 } 427 428 if (opnum == 1 && opnum == memop) 429 { 430 info->fprintf_func (info->stream, "%s[", prefix); 431 square = true; 432 } 433 else if ( (strcmp ("stc.w", op->name) == 0 434 || strcmp ("cache", op->name) == 0 435 || strcmp ("pref", op->name) == 0) 436 && opnum == 2 && opnum == memop) 437 { 438 info->fprintf_func (info->stream, ", ["); 439 square = true; 440 } 441 else if ( (strcmp (op->name, "pushsp") == 0 442 || strcmp (op->name, "popsp") == 0 443 || strcmp (op->name, "dbpush" ) == 0) 444 && opnum == 2) 445 { 446 info->fprintf_func (info->stream, "-"); 447 } 448 else if (opnum > 1 449 && (v850_operands[*(opindex_ptr - 1)].flags 450 & V850_OPERAND_DISP) != 0 451 && opnum == memop) 452 { 453 info->fprintf_func (info->stream, "%s[", prefix); 454 square = true; 455 } 456 else if (opnum == 2 457 && ( op->opcode == 0x00e407e0 /* clr1 */ 458 || op->opcode == 0x00e207e0 /* not1 */ 459 || op->opcode == 0x00e007e0 /* set1 */ 460 || op->opcode == 0x00e607e0 /* tst1 */ 461 )) 462 { 463 info->fprintf_func (info->stream, ", %s[", prefix); 464 square = true; 465 } 466 else if (opnum > 1) 467 info->fprintf_func (info->stream, ", %s", prefix); 468 469 /* Extract the flags, ignoring ones which do not 470 effect disassembly output. */ 471 flag = operand->flags & (V850_OPERAND_REG 472 | V850_REG_EVEN 473 | V850_OPERAND_EP 474 | V850_OPERAND_SRG 475 | V850E_OPERAND_REG_LIST 476 | V850_OPERAND_CC 477 | V850_OPERAND_VREG 478 | V850_OPERAND_CACHEOP 479 | V850_OPERAND_PREFOP 480 | V850_OPERAND_FLOAT_CC); 481 482 switch (flag) 483 { 484 case V850_OPERAND_REG: 485 info->fprintf_func (info->stream, "%s", get_v850_reg_name (value)); 486 break; 487 case (V850_OPERAND_REG|V850_REG_EVEN): 488 info->fprintf_func (info->stream, "%s", get_v850_reg_name (value * 2)); 489 break; 490 case V850_OPERAND_EP: 491 info->fprintf_func (info->stream, "ep"); 492 break; 493 case V850_OPERAND_SRG: 494 info->fprintf_func (info->stream, "%s", get_v850_sreg_name (value)); 495 break; 496 case V850E_OPERAND_REG_LIST: 497 { 498 static int list12_regs[32] = { 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 499 0, 0, 0, 0, 0, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 }; 500 int *regs; 501 int i; 502 unsigned int mask = 0; 503 int pc = 0; 504 505 switch (operand->shift) 506 { 507 case 0xffe00001: regs = list12_regs; break; 508 default: 509 /* xgettext:c-format */ 510 opcodes_error_handler (_("unknown operand shift: %x"), 511 operand->shift); 512 abort (); 513 } 514 515 for (i = 0; i < 32; i++) 516 { 517 if (value & (1u << i)) 518 { 519 switch (regs[ i ]) 520 { 521 default: 522 mask |= (1u << regs[ i ]); 523 break; 524 case 0: 525 /* xgettext:c-format */ 526 opcodes_error_handler (_("unknown reg: %d"), i); 527 abort (); 528 break; 529 case -1: 530 pc = 1; 531 break; 532 } 533 } 534 } 535 536 info->fprintf_func (info->stream, "{"); 537 538 if (mask || pc) 539 { 540 if (mask) 541 { 542 unsigned int bit; 543 int shown_one = 0; 544 545 for (bit = 0; bit < 32; bit++) 546 if (mask & (1u << bit)) 547 { 548 unsigned int first = bit; 549 unsigned int last; 550 551 if (shown_one) 552 info->fprintf_func (info->stream, ", "); 553 else 554 shown_one = 1; 555 556 info->fprintf_func (info->stream, "%s", get_v850_reg_name (first)); 557 558 for (bit++; bit < 32; bit++) 559 if ((mask & (1u << bit)) == 0) 560 break; 561 562 last = bit; 563 564 if (last > first + 1) 565 { 566 info->fprintf_func (info->stream, " - %s", get_v850_reg_name (last - 1)); 567 } 568 } 569 } 570 571 if (pc) 572 info->fprintf_func (info->stream, "%sPC", mask ? ", " : ""); 573 } 574 575 info->fprintf_func (info->stream, "}"); 576 } 577 break; 578 579 case V850_OPERAND_CC: 580 info->fprintf_func (info->stream, "%s", get_v850_cc_name (value)); 581 break; 582 583 case V850_OPERAND_FLOAT_CC: 584 info->fprintf_func (info->stream, "%s", get_v850_float_cc_name (value)); 585 break; 586 587 case V850_OPERAND_CACHEOP: 588 { 589 int idx; 590 591 for (idx = 0; v850_cacheop_codes[idx] != -1; idx++) 592 { 593 if (value == v850_cacheop_codes[idx]) 594 { 595 info->fprintf_func (info->stream, "%s", 596 get_v850_cacheop_name (idx)); 597 goto MATCH_CACHEOP_CODE; 598 } 599 } 600 info->fprintf_func (info->stream, "%d", (int) value); 601 } 602 MATCH_CACHEOP_CODE: 603 break; 604 605 case V850_OPERAND_PREFOP: 606 { 607 int idx; 608 609 for (idx = 0; v850_prefop_codes[idx] != -1; idx++) 610 { 611 if (value == v850_prefop_codes[idx]) 612 { 613 info->fprintf_func (info->stream, "%s", 614 get_v850_prefop_name (idx)); 615 goto MATCH_PREFOP_CODE; 616 } 617 } 618 info->fprintf_func (info->stream, "%d", (int) value); 619 } 620 MATCH_PREFOP_CODE: 621 break; 622 623 case V850_OPERAND_VREG: 624 info->fprintf_func (info->stream, "%s", get_v850_vreg_name (value)); 625 break; 626 627 default: 628 print_value (operand->flags, memaddr, info, value); 629 break; 630 } 631 632 if (square) 633 (*info->fprintf_func) (info->stream, "]"); 634 } 635 636 /* All done. */ 637 break; 638 } 639 next_opcode: 640 op++; 641 } 642 643 return match; 644} 645 646int 647print_insn_v850 (bfd_vma memaddr, struct disassemble_info * info) 648{ 649 int status, status2, match; 650 bfd_byte buffer[8]; 651 int length = 0, code_length = 0; 652 unsigned long insn = 0, insn2 = 0; 653 int target_processor; 654 655 switch (info->mach) 656 { 657 case 0: 658 default: 659 target_processor = PROCESSOR_V850; 660 break; 661 662 case bfd_mach_v850e: 663 target_processor = PROCESSOR_V850E; 664 break; 665 666 case bfd_mach_v850e1: 667 target_processor = PROCESSOR_V850E; 668 break; 669 670 case bfd_mach_v850e2: 671 target_processor = PROCESSOR_V850E2; 672 break; 673 674 case bfd_mach_v850e2v3: 675 target_processor = PROCESSOR_V850E2V3; 676 break; 677 678 case bfd_mach_v850e3v5: 679 target_processor = PROCESSOR_V850E3V5; 680 break; 681 } 682 683 status = info->read_memory_func (memaddr, buffer, 2, info); 684 685 if (status) 686 { 687 info->memory_error_func (status, memaddr, info); 688 return -1; 689 } 690 691 insn = bfd_getl16 (buffer); 692 693 status2 = info->read_memory_func (memaddr+2, buffer, 2 , info); 694 695 if (!status2) 696 { 697 insn2 = bfd_getl16 (buffer); 698 /* fprintf (stderr, "insn2 0x%08lx\n", insn2); */ 699 } 700 701 /* Special case. */ 702 if (length == 0 703 && ((target_processor & PROCESSOR_V850E2_UP) != 0)) 704 { 705 if ((insn & 0xffff) == 0x02e0 /* jr 32bit */ 706 && !status2 && (insn2 & 0x1) == 0) 707 { 708 length = 2; 709 code_length = 6; 710 } 711 else if ((insn & 0xffe0) == 0x02e0 /* jarl 32bit */ 712 && !status2 && (insn2 & 0x1) == 0) 713 { 714 length = 2; 715 code_length = 6; 716 } 717 else if ((insn & 0xffe0) == 0x06e0 /* jmp 32bit */ 718 && !status2 && (insn2 & 0x1) == 0) 719 { 720 length = 2; 721 code_length = 6; 722 } 723 } 724 725 if (length == 0 726 && ((target_processor & PROCESSOR_V850E3V5_UP) != 0)) 727 { 728 if ( ((insn & 0xffe0) == 0x07a0 /* ld.dw 23bit (v850e3v5) */ 729 && !status2 && (insn2 & 0x000f) == 0x0009) 730 || ((insn & 0xffe0) == 0x07a0 /* st.dw 23bit (v850e3v5) */ 731 && !status2 && (insn2 & 0x000f) == 0x000f)) 732 { 733 length = 4; 734 code_length = 6; 735 } 736 } 737 738 if (length == 0 739 && ((target_processor & PROCESSOR_V850E2V3_UP) != 0)) 740 { 741 if (((insn & 0xffe0) == 0x0780 /* ld.b 23bit */ 742 && !status2 && (insn2 & 0x000f) == 0x0005) 743 || ((insn & 0xffe0) == 0x07a0 /* ld.bu 23bit */ 744 && !status2 && (insn2 & 0x000f) == 0x0005) 745 || ((insn & 0xffe0) == 0x0780 /* ld.h 23bit */ 746 && !status2 && (insn2 & 0x000f) == 0x0007) 747 || ((insn & 0xffe0) == 0x07a0 /* ld.hu 23bit */ 748 && !status2 && (insn2 & 0x000f) == 0x0007) 749 || ((insn & 0xffe0) == 0x0780 /* ld.w 23bit */ 750 && !status2 && (insn2 & 0x000f) == 0x0009)) 751 { 752 length = 4; 753 code_length = 6; 754 } 755 else if (((insn & 0xffe0) == 0x0780 /* st.b 23bit */ 756 && !status2 && (insn2 & 0x000f) == 0x000d) 757 || ((insn & 0xffe0) == 0x07a0 /* st.h 23bit */ 758 && !status2 && (insn2 & 0x000f) == 0x000d) 759 || ((insn & 0xffe0) == 0x0780 /* st.w 23bit */ 760 && !status2 && (insn2 & 0x000f) == 0x000f)) 761 { 762 length = 4; 763 code_length = 6; 764 } 765 } 766 767 if (length == 0 768 && target_processor != PROCESSOR_V850) 769 { 770 if ((insn & 0xffe0) == 0x0620) /* 32 bit MOV */ 771 { 772 length = 2; 773 code_length = 6; 774 } 775 else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm16<<16 */ 776 && !status2 && (insn2 & 0x001f) == 0x0013) 777 { 778 length = 4; 779 code_length = 6; 780 } 781 else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm16 */ 782 && !status2 && (insn2 & 0x001f) == 0x000b) 783 { 784 length = 4; 785 code_length = 6; 786 } 787 else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm32 */ 788 && !status2 && (insn2 & 0x001f) == 0x001b) 789 { 790 length = 4; 791 code_length = 8; 792 } 793 } 794 795 if (length == 4 796 || (length == 0 797 && (insn & 0x0600) == 0x0600)) 798 { 799 /* This is a 4 byte insn. */ 800 status = info->read_memory_func (memaddr, buffer, 4, info); 801 if (!status) 802 { 803 insn = bfd_getl32 (buffer); 804 805 if (!length) 806 length = code_length = 4; 807 } 808 } 809 810 if (code_length > length) 811 { 812 status = info->read_memory_func (memaddr + length, buffer, code_length - length, info); 813 if (status) 814 length = 0; 815 } 816 817 if (length == 0 && !status) 818 length = code_length = 2; 819 820 if (length == 2) 821 insn &= 0xffff; 822 823 /* when the last 2 bytes of section is 0xffff, length will be 0 and cause infinitive loop */ 824 if (length == 0) 825 return -1; 826 827 match = disassemble (memaddr, info, length, insn); 828 829 if (!match) 830 { 831 int l = 0; 832 833 status = info->read_memory_func (memaddr, buffer, code_length, info); 834 835 while (l < code_length) 836 { 837 if (code_length - l == 2) 838 { 839 insn = bfd_getl16 (buffer + l) & 0xffff; 840 info->fprintf_func (info->stream, ".short\t0x%04lx", insn); 841 l += 2; 842 } 843 else 844 { 845 insn = bfd_getl32 (buffer + l); 846 info->fprintf_func (info->stream, ".long\t0x%08lx", insn); 847 l += 4; 848 } 849 } 850 } 851 852 return code_length; 853} 854