1 1.1 christos /* Disassemble V850 instructions. 2 1.10 christos Copyright (C) 1996-2025 Free Software Foundation, Inc. 3 1.1 christos 4 1.1 christos This file is part of the GNU opcodes library. 5 1.1 christos 6 1.1 christos This library is free software; you can redistribute it and/or modify 7 1.1 christos it under the terms of the GNU General Public License as published by 8 1.1 christos the Free Software Foundation; either version 3, or (at your option) 9 1.1 christos any later version. 10 1.1 christos 11 1.1 christos It is distributed in the hope that it will be useful, but WITHOUT 12 1.1 christos ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13 1.1 christos or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 14 1.1 christos License for more details. 15 1.1 christos 16 1.1 christos You should have received a copy of the GNU General Public License 17 1.1 christos along with this program; if not, write to the Free Software 18 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 19 1.1 christos MA 02110-1301, USA. */ 20 1.1 christos 21 1.1 christos 22 1.1 christos #include "sysdep.h" 23 1.1 christos #include <stdio.h> 24 1.3 christos #include <string.h> 25 1.1 christos #include "opcode/v850.h" 26 1.6 christos #include "disassemble.h" 27 1.1 christos #include "opintl.h" 28 1.7 christos #include "libiberty.h" 29 1.3 christos 30 1.3 christos static const int v850_cacheop_codes[] = 31 1.3 christos { 32 1.3 christos 0x00, 0x20, 0x40, 0x60, 0x61, 0x04, 0x06, 33 1.3 christos 0x07, 0x24, 0x26, 0x27, 0x44, 0x64, 0x65, -1 34 1.3 christos }; 35 1.3 christos 36 1.3 christos static const int v850_prefop_codes[] = 37 1.3 christos { 0x00, 0x04, -1}; 38 1.3 christos 39 1.1 christos static void 40 1.3 christos print_value (int flags, 41 1.3 christos bfd_vma memaddr, 42 1.3 christos struct disassemble_info *info, 43 1.3 christos long value) 44 1.1 christos { 45 1.1 christos if (flags & V850_PCREL) 46 1.1 christos { 47 1.1 christos bfd_vma addr = value + memaddr; 48 1.3 christos 49 1.3 christos if (flags & V850_INVERSE_PCREL) 50 1.3 christos addr = memaddr - value; 51 1.1 christos info->print_address_func (addr, info); 52 1.1 christos } 53 1.1 christos else if (flags & V850_OPERAND_DISP) 54 1.1 christos { 55 1.1 christos if (flags & V850_OPERAND_SIGNED) 56 1.1 christos { 57 1.1 christos info->fprintf_func (info->stream, "%ld", value); 58 1.1 christos } 59 1.1 christos else 60 1.1 christos { 61 1.1 christos info->fprintf_func (info->stream, "%lu", value); 62 1.1 christos } 63 1.1 christos } 64 1.3 christos else if ((flags & V850E_IMMEDIATE32) 65 1.3 christos || (flags & V850E_IMMEDIATE16HI)) 66 1.1 christos { 67 1.1 christos info->fprintf_func (info->stream, "0x%lx", value); 68 1.1 christos } 69 1.1 christos else 70 1.1 christos { 71 1.1 christos if (flags & V850_OPERAND_SIGNED) 72 1.1 christos { 73 1.1 christos info->fprintf_func (info->stream, "%ld", value); 74 1.1 christos } 75 1.1 christos else 76 1.1 christos { 77 1.1 christos info->fprintf_func (info->stream, "%lu", value); 78 1.1 christos } 79 1.1 christos } 80 1.1 christos } 81 1.1 christos 82 1.1 christos static long 83 1.1 christos get_operand_value (const struct v850_operand *operand, 84 1.1 christos unsigned long insn, 85 1.1 christos int bytes_read, 86 1.1 christos bfd_vma memaddr, 87 1.1 christos struct disassemble_info * info, 88 1.8 christos bool noerror, 89 1.1 christos int *invalid) 90 1.1 christos { 91 1.7 christos unsigned long value; 92 1.1 christos bfd_byte buffer[4]; 93 1.1 christos 94 1.1 christos if ((operand->flags & V850E_IMMEDIATE16) 95 1.1 christos || (operand->flags & V850E_IMMEDIATE16HI)) 96 1.1 christos { 97 1.1 christos int status = info->read_memory_func (memaddr + bytes_read, buffer, 2, info); 98 1.1 christos 99 1.1 christos if (status == 0) 100 1.1 christos { 101 1.1 christos value = bfd_getl16 (buffer); 102 1.1 christos 103 1.1 christos if (operand->flags & V850E_IMMEDIATE16HI) 104 1.1 christos value <<= 16; 105 1.3 christos else if (value & 0x8000) 106 1.3 christos value |= (-1UL << 16); 107 1.1 christos 108 1.1 christos return value; 109 1.1 christos } 110 1.1 christos 111 1.1 christos if (!noerror) 112 1.1 christos info->memory_error_func (status, memaddr + bytes_read, info); 113 1.1 christos 114 1.1 christos return 0; 115 1.1 christos } 116 1.1 christos 117 1.1 christos if (operand->flags & V850E_IMMEDIATE23) 118 1.1 christos { 119 1.1 christos int status = info->read_memory_func (memaddr + 2, buffer, 4, info); 120 1.1 christos 121 1.1 christos if (status == 0) 122 1.1 christos { 123 1.1 christos value = bfd_getl32 (buffer); 124 1.1 christos 125 1.1 christos value = (operand->extract) (value, invalid); 126 1.1 christos 127 1.1 christos return value; 128 1.1 christos } 129 1.1 christos 130 1.1 christos if (!noerror) 131 1.1 christos info->memory_error_func (status, memaddr + bytes_read, info); 132 1.1 christos 133 1.1 christos return 0; 134 1.1 christos } 135 1.1 christos 136 1.1 christos if (operand->flags & V850E_IMMEDIATE32) 137 1.1 christos { 138 1.1 christos int status = info->read_memory_func (memaddr + bytes_read, buffer, 4, info); 139 1.1 christos 140 1.1 christos if (status == 0) 141 1.1 christos { 142 1.1 christos bytes_read += 4; 143 1.1 christos value = bfd_getl32 (buffer); 144 1.1 christos 145 1.1 christos return value; 146 1.1 christos } 147 1.1 christos 148 1.1 christos if (!noerror) 149 1.1 christos info->memory_error_func (status, memaddr + bytes_read, info); 150 1.1 christos 151 1.1 christos return 0; 152 1.1 christos } 153 1.1 christos 154 1.1 christos if (operand->extract) 155 1.1 christos value = (operand->extract) (insn, invalid); 156 1.1 christos else 157 1.1 christos { 158 1.1 christos if (operand->bits == -1) 159 1.1 christos value = (insn & operand->shift); 160 1.1 christos else 161 1.7 christos value = (insn >> operand->shift) & ((1ul << operand->bits) - 1); 162 1.1 christos 163 1.1 christos if (operand->flags & V850_OPERAND_SIGNED) 164 1.7 christos { 165 1.7 christos unsigned long sign = 1ul << (operand->bits - 1); 166 1.7 christos value = (value ^ sign) - sign; 167 1.7 christos } 168 1.1 christos } 169 1.1 christos 170 1.1 christos return value; 171 1.1 christos } 172 1.1 christos 173 1.7 christos static const char * 174 1.7 christos get_v850_sreg_name (unsigned int reg) 175 1.7 christos { 176 1.7 christos static const char *const v850_sreg_names[] = 177 1.7 christos { 178 1.7 christos "eipc/vip/mpm", "eipsw/mpc", "fepc/tid", "fepsw/ppa", "ecr/vmecr", "psw/vmtid", 179 1.7 christos "sr6/fpsr/vmadr/dcc", "sr7/fpepc/dc0", 180 1.7 christos "sr8/fpst/vpecr/dcv1", "sr9/fpcc/vptid", "sr10/fpcfg/vpadr/spal", "sr11/spau", 181 1.7 christos "sr12/vdecr/ipa0l", "eiic/vdtid/ipa0u", "feic/ipa1l", "dbic/ipa1u", 182 1.7 christos "ctpc/ipa2l", "ctpsw/ipa2u", "dbpc/ipa3l", "dbpsw/ipa3u", "ctbp/dpa0l", 183 1.7 christos "dir/dpa0u", "bpc/dpa0u", "asid/dpa1l", 184 1.7 christos "bpav/dpa1u", "bpam/dpa2l", "bpdv/dpa2u", "bpdm/dpa3l", "eiwr/dpa3u", 185 1.7 christos "fewr", "dbwr", "bsel" 186 1.7 christos }; 187 1.7 christos 188 1.7 christos if (reg < ARRAY_SIZE (v850_sreg_names)) 189 1.7 christos return v850_sreg_names[reg]; 190 1.7 christos return _("<invalid s-reg number>"); 191 1.7 christos } 192 1.7 christos 193 1.7 christos static const char * 194 1.7 christos get_v850_reg_name (unsigned int reg) 195 1.7 christos { 196 1.7 christos static const char *const v850_reg_names[] = 197 1.7 christos { 198 1.7 christos "r0", "r1", "r2", "sp", "gp", "r5", "r6", "r7", 199 1.7 christos "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", 200 1.7 christos "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", 201 1.7 christos "r24", "r25", "r26", "r27", "r28", "r29", "ep", "lp" 202 1.7 christos }; 203 1.7 christos 204 1.7 christos if (reg < ARRAY_SIZE (v850_reg_names)) 205 1.7 christos return v850_reg_names[reg]; 206 1.7 christos return _("<invalid reg number>"); 207 1.7 christos } 208 1.7 christos 209 1.7 christos static const char * 210 1.7 christos get_v850_vreg_name (unsigned int reg) 211 1.7 christos { 212 1.7 christos static const char *const v850_vreg_names[] = 213 1.7 christos { 214 1.7 christos "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7", "vr8", "vr9", 215 1.7 christos "vr10", "vr11", "vr12", "vr13", "vr14", "vr15", "vr16", "vr17", "vr18", 216 1.7 christos "vr19", "vr20", "vr21", "vr22", "vr23", "vr24", "vr25", "vr26", "vr27", 217 1.7 christos "vr28", "vr29", "vr30", "vr31" 218 1.7 christos }; 219 1.7 christos 220 1.7 christos if (reg < ARRAY_SIZE (v850_vreg_names)) 221 1.7 christos return v850_vreg_names[reg]; 222 1.7 christos return _("<invalid v-reg number>"); 223 1.7 christos } 224 1.7 christos 225 1.7 christos static const char * 226 1.7 christos get_v850_cc_name (unsigned int reg) 227 1.7 christos { 228 1.7 christos static const char *const v850_cc_names[] = 229 1.7 christos { 230 1.7 christos "v", "c/l", "z", "nh", "s/n", "t", "lt", "le", 231 1.7 christos "nv", "nc/nl", "nz", "h", "ns/p", "sa", "ge", "gt" 232 1.7 christos }; 233 1.7 christos 234 1.7 christos if (reg < ARRAY_SIZE (v850_cc_names)) 235 1.7 christos return v850_cc_names[reg]; 236 1.7 christos return _("<invalid CC-reg number>"); 237 1.7 christos } 238 1.7 christos 239 1.7 christos static const char * 240 1.7 christos get_v850_float_cc_name (unsigned int reg) 241 1.7 christos { 242 1.7 christos static const char *const v850_float_cc_names[] = 243 1.7 christos { 244 1.7 christos "f/t", "un/or", "eq/neq", "ueq/ogl", "olt/uge", "ult/oge", "ole/ugt", "ule/ogt", 245 1.7 christos "sf/st", "ngle/gle", "seq/sne", "ngl/gl", "lt/nlt", "nge/ge", "le/nle", "ngt/gt" 246 1.7 christos }; 247 1.7 christos 248 1.7 christos if (reg < ARRAY_SIZE (v850_float_cc_names)) 249 1.7 christos return v850_float_cc_names[reg]; 250 1.7 christos return _("<invalid float-CC-reg number>"); 251 1.7 christos } 252 1.7 christos 253 1.7 christos static const char * 254 1.7 christos get_v850_cacheop_name (unsigned int reg) 255 1.7 christos { 256 1.7 christos static const char *const v850_cacheop_names[] = 257 1.7 christos { 258 1.7 christos "chbii", "cibii", "cfali", "cisti", "cildi", "chbid", "chbiwbd", 259 1.7 christos "chbwbd", "cibid", "cibiwbd", "cibwbd", "cfald", "cistd", "cildd" 260 1.7 christos }; 261 1.7 christos 262 1.7 christos if (reg < ARRAY_SIZE (v850_cacheop_names)) 263 1.7 christos return v850_cacheop_names[reg]; 264 1.7 christos return _("<invalid cacheop number>"); 265 1.7 christos } 266 1.7 christos 267 1.7 christos static const char * 268 1.7 christos get_v850_prefop_name (unsigned int reg) 269 1.7 christos { 270 1.7 christos static const char *const v850_prefop_names[] = 271 1.7 christos { "prefi", "prefd" }; 272 1.7 christos 273 1.7 christos if (reg < ARRAY_SIZE (v850_prefop_names)) 274 1.7 christos return v850_prefop_names[reg]; 275 1.7 christos return _("<invalid prefop number>"); 276 1.7 christos } 277 1.1 christos 278 1.1 christos static int 279 1.3 christos disassemble (bfd_vma memaddr, 280 1.3 christos struct disassemble_info *info, 281 1.3 christos int bytes_read, 282 1.3 christos unsigned long insn) 283 1.1 christos { 284 1.3 christos struct v850_opcode *op = (struct v850_opcode *) v850_opcodes; 285 1.1 christos const struct v850_operand *operand; 286 1.1 christos int match = 0; 287 1.1 christos int target_processor; 288 1.1 christos 289 1.1 christos switch (info->mach) 290 1.1 christos { 291 1.1 christos case 0: 292 1.1 christos default: 293 1.1 christos target_processor = PROCESSOR_V850; 294 1.1 christos break; 295 1.1 christos 296 1.1 christos case bfd_mach_v850e: 297 1.1 christos target_processor = PROCESSOR_V850E; 298 1.1 christos break; 299 1.1 christos 300 1.1 christos case bfd_mach_v850e1: 301 1.1 christos target_processor = PROCESSOR_V850E; 302 1.1 christos break; 303 1.1 christos 304 1.1 christos case bfd_mach_v850e2: 305 1.1 christos target_processor = PROCESSOR_V850E2; 306 1.1 christos break; 307 1.1 christos 308 1.1 christos case bfd_mach_v850e2v3: 309 1.1 christos target_processor = PROCESSOR_V850E2V3; 310 1.1 christos break; 311 1.3 christos 312 1.3 christos case bfd_mach_v850e3v5: 313 1.3 christos target_processor = PROCESSOR_V850E3V5; 314 1.3 christos break; 315 1.1 christos } 316 1.1 christos 317 1.1 christos /* If this is a two byte insn, then mask off the high bits. */ 318 1.1 christos if (bytes_read == 2) 319 1.1 christos insn &= 0xffff; 320 1.1 christos 321 1.1 christos /* Find the opcode. */ 322 1.1 christos while (op->name) 323 1.1 christos { 324 1.1 christos if ((op->mask & insn) == op->opcode 325 1.1 christos && (op->processors & target_processor) 326 1.1 christos && !(op->processors & PROCESSOR_OPTION_ALIAS)) 327 1.1 christos { 328 1.1 christos /* Code check start. */ 329 1.1 christos const unsigned char *opindex_ptr; 330 1.1 christos unsigned int opnum; 331 1.1 christos unsigned int memop; 332 1.1 christos 333 1.1 christos for (opindex_ptr = op->operands, opnum = 1; 334 1.1 christos *opindex_ptr != 0; 335 1.1 christos opindex_ptr++, opnum++) 336 1.1 christos { 337 1.1 christos int invalid = 0; 338 1.1 christos long value; 339 1.1 christos 340 1.1 christos operand = &v850_operands[*opindex_ptr]; 341 1.1 christos 342 1.3 christos value = get_operand_value (operand, insn, bytes_read, memaddr, 343 1.3 christos info, 1, &invalid); 344 1.1 christos 345 1.1 christos if (invalid) 346 1.1 christos goto next_opcode; 347 1.1 christos 348 1.1 christos if ((operand->flags & V850_NOT_R0) && value == 0 && (op->memop) <=2) 349 1.1 christos goto next_opcode; 350 1.1 christos 351 1.1 christos if ((operand->flags & V850_NOT_SA) && value == 0xd) 352 1.1 christos goto next_opcode; 353 1.1 christos 354 1.1 christos if ((operand->flags & V850_NOT_IMM0) && value == 0) 355 1.1 christos goto next_opcode; 356 1.1 christos } 357 1.1 christos 358 1.1 christos /* Code check end. */ 359 1.1 christos 360 1.1 christos match = 1; 361 1.1 christos (*info->fprintf_func) (info->stream, "%s\t", op->name); 362 1.1 christos #if 0 363 1.1 christos fprintf (stderr, "match: insn: %lx, mask: %lx, opcode: %lx, name: %s\n", 364 1.1 christos insn, op->mask, op->opcode, op->name ); 365 1.1 christos #endif 366 1.1 christos 367 1.1 christos memop = op->memop; 368 1.1 christos /* Now print the operands. 369 1.1 christos 370 1.1 christos MEMOP is the operand number at which a memory 371 1.1 christos address specification starts, or zero if this 372 1.1 christos instruction has no memory addresses. 373 1.1 christos 374 1.1 christos A memory address is always two arguments. 375 1.1 christos 376 1.1 christos This information allows us to determine when to 377 1.1 christos insert commas into the output stream as well as 378 1.1 christos when to insert disp[reg] expressions onto the 379 1.1 christos output stream. */ 380 1.1 christos 381 1.1 christos for (opindex_ptr = op->operands, opnum = 1; 382 1.1 christos *opindex_ptr != 0; 383 1.1 christos opindex_ptr++, opnum++) 384 1.1 christos { 385 1.8 christos bool square = false; 386 1.1 christos long value; 387 1.1 christos int flag; 388 1.1 christos char *prefix; 389 1.1 christos 390 1.1 christos operand = &v850_operands[*opindex_ptr]; 391 1.1 christos 392 1.3 christos value = get_operand_value (operand, insn, bytes_read, memaddr, 393 1.3 christos info, 0, 0); 394 1.1 christos 395 1.1 christos /* The first operand is always output without any 396 1.1 christos special handling. 397 1.1 christos 398 1.1 christos For the following arguments: 399 1.1 christos 400 1.1 christos If memop && opnum == memop + 1, then we need '[' since 401 1.1 christos we're about to output the register used in a memory 402 1.1 christos reference. 403 1.1 christos 404 1.1 christos If memop && opnum == memop + 2, then we need ']' since 405 1.1 christos we just finished the register in a memory reference. We 406 1.1 christos also need a ',' before this operand. 407 1.1 christos 408 1.1 christos Else we just need a comma. 409 1.1 christos 410 1.1 christos We may need to output a trailing ']' if the last operand 411 1.1 christos in an instruction is the register for a memory address. 412 1.1 christos 413 1.3 christos The exception (and there's always an exception) are the 414 1.1 christos "jmp" insn which needs square brackets around it's only 415 1.3 christos register argument, and the clr1/not1/set1/tst1 insns 416 1.3 christos which [...] around their second register argument. */ 417 1.3 christos 418 1.1 christos prefix = ""; 419 1.1 christos if (operand->flags & V850_OPERAND_BANG) 420 1.1 christos { 421 1.1 christos prefix = "!"; 422 1.1 christos } 423 1.1 christos else if (operand->flags & V850_OPERAND_PERCENT) 424 1.1 christos { 425 1.1 christos prefix = "%"; 426 1.1 christos } 427 1.1 christos 428 1.1 christos if (opnum == 1 && opnum == memop) 429 1.1 christos { 430 1.1 christos info->fprintf_func (info->stream, "%s[", prefix); 431 1.8 christos square = true; 432 1.1 christos } 433 1.3 christos else if ( (strcmp ("stc.w", op->name) == 0 434 1.3 christos || strcmp ("cache", op->name) == 0 435 1.3 christos || strcmp ("pref", op->name) == 0) 436 1.3 christos && opnum == 2 && opnum == memop) 437 1.3 christos { 438 1.3 christos info->fprintf_func (info->stream, ", ["); 439 1.8 christos square = true; 440 1.3 christos } 441 1.3 christos else if ( (strcmp (op->name, "pushsp") == 0 442 1.3 christos || strcmp (op->name, "popsp") == 0 443 1.3 christos || strcmp (op->name, "dbpush" ) == 0) 444 1.3 christos && opnum == 2) 445 1.3 christos { 446 1.3 christos info->fprintf_func (info->stream, "-"); 447 1.3 christos } 448 1.1 christos else if (opnum > 1 449 1.3 christos && (v850_operands[*(opindex_ptr - 1)].flags 450 1.3 christos & V850_OPERAND_DISP) != 0 451 1.1 christos && opnum == memop) 452 1.1 christos { 453 1.1 christos info->fprintf_func (info->stream, "%s[", prefix); 454 1.8 christos square = true; 455 1.1 christos } 456 1.3 christos else if (opnum == 2 457 1.3 christos && ( op->opcode == 0x00e407e0 /* clr1 */ 458 1.3 christos || op->opcode == 0x00e207e0 /* not1 */ 459 1.3 christos || op->opcode == 0x00e007e0 /* set1 */ 460 1.3 christos || op->opcode == 0x00e607e0 /* tst1 */ 461 1.3 christos )) 462 1.3 christos { 463 1.3 christos info->fprintf_func (info->stream, ", %s[", prefix); 464 1.8 christos square = true; 465 1.3 christos } 466 1.1 christos else if (opnum > 1) 467 1.1 christos info->fprintf_func (info->stream, ", %s", prefix); 468 1.1 christos 469 1.3 christos /* Extract the flags, ignoring ones which do not 470 1.3 christos effect disassembly output. */ 471 1.1 christos flag = operand->flags & (V850_OPERAND_REG 472 1.1 christos | V850_REG_EVEN 473 1.1 christos | V850_OPERAND_EP 474 1.1 christos | V850_OPERAND_SRG 475 1.1 christos | V850E_OPERAND_REG_LIST 476 1.1 christos | V850_OPERAND_CC 477 1.3 christos | V850_OPERAND_VREG 478 1.3 christos | V850_OPERAND_CACHEOP 479 1.3 christos | V850_OPERAND_PREFOP 480 1.1 christos | V850_OPERAND_FLOAT_CC); 481 1.1 christos 482 1.1 christos switch (flag) 483 1.1 christos { 484 1.3 christos case V850_OPERAND_REG: 485 1.7 christos info->fprintf_func (info->stream, "%s", get_v850_reg_name (value)); 486 1.3 christos break; 487 1.3 christos case (V850_OPERAND_REG|V850_REG_EVEN): 488 1.7 christos info->fprintf_func (info->stream, "%s", get_v850_reg_name (value * 2)); 489 1.3 christos break; 490 1.3 christos case V850_OPERAND_EP: 491 1.3 christos info->fprintf_func (info->stream, "ep"); 492 1.3 christos break; 493 1.3 christos case V850_OPERAND_SRG: 494 1.7 christos info->fprintf_func (info->stream, "%s", get_v850_sreg_name (value)); 495 1.3 christos break; 496 1.1 christos case V850E_OPERAND_REG_LIST: 497 1.1 christos { 498 1.1 christos static int list12_regs[32] = { 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 499 1.1 christos 0, 0, 0, 0, 0, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 }; 500 1.1 christos int *regs; 501 1.1 christos int i; 502 1.7 christos unsigned int mask = 0; 503 1.1 christos int pc = 0; 504 1.1 christos 505 1.1 christos switch (operand->shift) 506 1.1 christos { 507 1.1 christos case 0xffe00001: regs = list12_regs; break; 508 1.1 christos default: 509 1.1 christos /* xgettext:c-format */ 510 1.6 christos opcodes_error_handler (_("unknown operand shift: %x"), 511 1.6 christos operand->shift); 512 1.1 christos abort (); 513 1.1 christos } 514 1.1 christos 515 1.1 christos for (i = 0; i < 32; i++) 516 1.1 christos { 517 1.7 christos if (value & (1u << i)) 518 1.1 christos { 519 1.1 christos switch (regs[ i ]) 520 1.1 christos { 521 1.6 christos default: 522 1.7 christos mask |= (1u << regs[ i ]); 523 1.6 christos break; 524 1.6 christos case 0: 525 1.1 christos /* xgettext:c-format */ 526 1.6 christos opcodes_error_handler (_("unknown reg: %d"), i); 527 1.6 christos abort (); 528 1.6 christos break; 529 1.6 christos case -1: 530 1.6 christos pc = 1; 531 1.6 christos break; 532 1.1 christos } 533 1.1 christos } 534 1.1 christos } 535 1.1 christos 536 1.1 christos info->fprintf_func (info->stream, "{"); 537 1.1 christos 538 1.1 christos if (mask || pc) 539 1.1 christos { 540 1.1 christos if (mask) 541 1.1 christos { 542 1.1 christos unsigned int bit; 543 1.1 christos int shown_one = 0; 544 1.1 christos 545 1.1 christos for (bit = 0; bit < 32; bit++) 546 1.7 christos if (mask & (1u << bit)) 547 1.1 christos { 548 1.7 christos unsigned int first = bit; 549 1.7 christos unsigned int last; 550 1.1 christos 551 1.1 christos if (shown_one) 552 1.1 christos info->fprintf_func (info->stream, ", "); 553 1.1 christos else 554 1.1 christos shown_one = 1; 555 1.1 christos 556 1.7 christos info->fprintf_func (info->stream, "%s", get_v850_reg_name (first)); 557 1.1 christos 558 1.1 christos for (bit++; bit < 32; bit++) 559 1.7 christos if ((mask & (1u << bit)) == 0) 560 1.1 christos break; 561 1.1 christos 562 1.1 christos last = bit; 563 1.1 christos 564 1.1 christos if (last > first + 1) 565 1.1 christos { 566 1.7 christos info->fprintf_func (info->stream, " - %s", get_v850_reg_name (last - 1)); 567 1.1 christos } 568 1.1 christos } 569 1.1 christos } 570 1.1 christos 571 1.1 christos if (pc) 572 1.1 christos info->fprintf_func (info->stream, "%sPC", mask ? ", " : ""); 573 1.1 christos } 574 1.1 christos 575 1.1 christos info->fprintf_func (info->stream, "}"); 576 1.1 christos } 577 1.1 christos break; 578 1.1 christos 579 1.3 christos case V850_OPERAND_CC: 580 1.7 christos info->fprintf_func (info->stream, "%s", get_v850_cc_name (value)); 581 1.3 christos break; 582 1.3 christos 583 1.3 christos case V850_OPERAND_FLOAT_CC: 584 1.7 christos info->fprintf_func (info->stream, "%s", get_v850_float_cc_name (value)); 585 1.3 christos break; 586 1.3 christos 587 1.3 christos case V850_OPERAND_CACHEOP: 588 1.3 christos { 589 1.3 christos int idx; 590 1.3 christos 591 1.3 christos for (idx = 0; v850_cacheop_codes[idx] != -1; idx++) 592 1.3 christos { 593 1.3 christos if (value == v850_cacheop_codes[idx]) 594 1.3 christos { 595 1.3 christos info->fprintf_func (info->stream, "%s", 596 1.7 christos get_v850_cacheop_name (idx)); 597 1.3 christos goto MATCH_CACHEOP_CODE; 598 1.3 christos } 599 1.3 christos } 600 1.3 christos info->fprintf_func (info->stream, "%d", (int) value); 601 1.3 christos } 602 1.3 christos MATCH_CACHEOP_CODE: 603 1.3 christos break; 604 1.3 christos 605 1.3 christos case V850_OPERAND_PREFOP: 606 1.3 christos { 607 1.3 christos int idx; 608 1.3 christos 609 1.3 christos for (idx = 0; v850_prefop_codes[idx] != -1; idx++) 610 1.3 christos { 611 1.3 christos if (value == v850_prefop_codes[idx]) 612 1.3 christos { 613 1.3 christos info->fprintf_func (info->stream, "%s", 614 1.7 christos get_v850_prefop_name (idx)); 615 1.3 christos goto MATCH_PREFOP_CODE; 616 1.3 christos } 617 1.3 christos } 618 1.3 christos info->fprintf_func (info->stream, "%d", (int) value); 619 1.3 christos } 620 1.3 christos MATCH_PREFOP_CODE: 621 1.3 christos break; 622 1.3 christos 623 1.3 christos case V850_OPERAND_VREG: 624 1.7 christos info->fprintf_func (info->stream, "%s", get_v850_vreg_name (value)); 625 1.3 christos break; 626 1.1 christos 627 1.1 christos default: 628 1.1 christos print_value (operand->flags, memaddr, info, value); 629 1.1 christos break; 630 1.1 christos } 631 1.1 christos 632 1.1 christos if (square) 633 1.1 christos (*info->fprintf_func) (info->stream, "]"); 634 1.1 christos } 635 1.1 christos 636 1.1 christos /* All done. */ 637 1.1 christos break; 638 1.1 christos } 639 1.1 christos next_opcode: 640 1.1 christos op++; 641 1.1 christos } 642 1.1 christos 643 1.1 christos return match; 644 1.1 christos } 645 1.1 christos 646 1.1 christos int 647 1.1 christos print_insn_v850 (bfd_vma memaddr, struct disassemble_info * info) 648 1.1 christos { 649 1.1 christos int status, status2, match; 650 1.1 christos bfd_byte buffer[8]; 651 1.1 christos int length = 0, code_length = 0; 652 1.1 christos unsigned long insn = 0, insn2 = 0; 653 1.1 christos int target_processor; 654 1.1 christos 655 1.1 christos switch (info->mach) 656 1.1 christos { 657 1.1 christos case 0: 658 1.1 christos default: 659 1.1 christos target_processor = PROCESSOR_V850; 660 1.1 christos break; 661 1.1 christos 662 1.1 christos case bfd_mach_v850e: 663 1.1 christos target_processor = PROCESSOR_V850E; 664 1.1 christos break; 665 1.1 christos 666 1.1 christos case bfd_mach_v850e1: 667 1.1 christos target_processor = PROCESSOR_V850E; 668 1.1 christos break; 669 1.1 christos 670 1.1 christos case bfd_mach_v850e2: 671 1.1 christos target_processor = PROCESSOR_V850E2; 672 1.1 christos break; 673 1.1 christos 674 1.1 christos case bfd_mach_v850e2v3: 675 1.1 christos target_processor = PROCESSOR_V850E2V3; 676 1.1 christos break; 677 1.3 christos 678 1.3 christos case bfd_mach_v850e3v5: 679 1.3 christos target_processor = PROCESSOR_V850E3V5; 680 1.3 christos break; 681 1.1 christos } 682 1.1 christos 683 1.1 christos status = info->read_memory_func (memaddr, buffer, 2, info); 684 1.1 christos 685 1.1 christos if (status) 686 1.1 christos { 687 1.1 christos info->memory_error_func (status, memaddr, info); 688 1.1 christos return -1; 689 1.1 christos } 690 1.1 christos 691 1.1 christos insn = bfd_getl16 (buffer); 692 1.1 christos 693 1.1 christos status2 = info->read_memory_func (memaddr+2, buffer, 2 , info); 694 1.1 christos 695 1.1 christos if (!status2) 696 1.1 christos { 697 1.1 christos insn2 = bfd_getl16 (buffer); 698 1.1 christos /* fprintf (stderr, "insn2 0x%08lx\n", insn2); */ 699 1.1 christos } 700 1.1 christos 701 1.1 christos /* Special case. */ 702 1.1 christos if (length == 0 703 1.3 christos && ((target_processor & PROCESSOR_V850E2_UP) != 0)) 704 1.1 christos { 705 1.1 christos if ((insn & 0xffff) == 0x02e0 /* jr 32bit */ 706 1.1 christos && !status2 && (insn2 & 0x1) == 0) 707 1.1 christos { 708 1.1 christos length = 2; 709 1.1 christos code_length = 6; 710 1.1 christos } 711 1.1 christos else if ((insn & 0xffe0) == 0x02e0 /* jarl 32bit */ 712 1.1 christos && !status2 && (insn2 & 0x1) == 0) 713 1.1 christos { 714 1.1 christos length = 2; 715 1.1 christos code_length = 6; 716 1.1 christos } 717 1.1 christos else if ((insn & 0xffe0) == 0x06e0 /* jmp 32bit */ 718 1.1 christos && !status2 && (insn2 & 0x1) == 0) 719 1.1 christos { 720 1.1 christos length = 2; 721 1.1 christos code_length = 6; 722 1.1 christos } 723 1.1 christos } 724 1.1 christos 725 1.1 christos if (length == 0 726 1.3 christos && ((target_processor & PROCESSOR_V850E3V5_UP) != 0)) 727 1.3 christos { 728 1.3 christos if ( ((insn & 0xffe0) == 0x07a0 /* ld.dw 23bit (v850e3v5) */ 729 1.3 christos && !status2 && (insn2 & 0x000f) == 0x0009) 730 1.3 christos || ((insn & 0xffe0) == 0x07a0 /* st.dw 23bit (v850e3v5) */ 731 1.3 christos && !status2 && (insn2 & 0x000f) == 0x000f)) 732 1.3 christos { 733 1.3 christos length = 4; 734 1.3 christos code_length = 6; 735 1.3 christos } 736 1.3 christos } 737 1.3 christos 738 1.3 christos if (length == 0 739 1.3 christos && ((target_processor & PROCESSOR_V850E2V3_UP) != 0)) 740 1.1 christos { 741 1.1 christos if (((insn & 0xffe0) == 0x0780 /* ld.b 23bit */ 742 1.1 christos && !status2 && (insn2 & 0x000f) == 0x0005) 743 1.1 christos || ((insn & 0xffe0) == 0x07a0 /* ld.bu 23bit */ 744 1.1 christos && !status2 && (insn2 & 0x000f) == 0x0005) 745 1.1 christos || ((insn & 0xffe0) == 0x0780 /* ld.h 23bit */ 746 1.1 christos && !status2 && (insn2 & 0x000f) == 0x0007) 747 1.1 christos || ((insn & 0xffe0) == 0x07a0 /* ld.hu 23bit */ 748 1.1 christos && !status2 && (insn2 & 0x000f) == 0x0007) 749 1.1 christos || ((insn & 0xffe0) == 0x0780 /* ld.w 23bit */ 750 1.1 christos && !status2 && (insn2 & 0x000f) == 0x0009)) 751 1.1 christos { 752 1.1 christos length = 4; 753 1.1 christos code_length = 6; 754 1.1 christos } 755 1.1 christos else if (((insn & 0xffe0) == 0x0780 /* st.b 23bit */ 756 1.1 christos && !status2 && (insn2 & 0x000f) == 0x000d) 757 1.1 christos || ((insn & 0xffe0) == 0x07a0 /* st.h 23bit */ 758 1.1 christos && !status2 && (insn2 & 0x000f) == 0x000d) 759 1.1 christos || ((insn & 0xffe0) == 0x0780 /* st.w 23bit */ 760 1.1 christos && !status2 && (insn2 & 0x000f) == 0x000f)) 761 1.1 christos { 762 1.1 christos length = 4; 763 1.1 christos code_length = 6; 764 1.1 christos } 765 1.1 christos } 766 1.1 christos 767 1.1 christos if (length == 0 768 1.1 christos && target_processor != PROCESSOR_V850) 769 1.1 christos { 770 1.1 christos if ((insn & 0xffe0) == 0x0620) /* 32 bit MOV */ 771 1.1 christos { 772 1.1 christos length = 2; 773 1.1 christos code_length = 6; 774 1.1 christos } 775 1.1 christos else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm16<<16 */ 776 1.1 christos && !status2 && (insn2 & 0x001f) == 0x0013) 777 1.1 christos { 778 1.1 christos length = 4; 779 1.1 christos code_length = 6; 780 1.1 christos } 781 1.1 christos else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm16 */ 782 1.1 christos && !status2 && (insn2 & 0x001f) == 0x000b) 783 1.1 christos { 784 1.1 christos length = 4; 785 1.1 christos code_length = 6; 786 1.1 christos } 787 1.1 christos else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm32 */ 788 1.1 christos && !status2 && (insn2 & 0x001f) == 0x001b) 789 1.1 christos { 790 1.1 christos length = 4; 791 1.1 christos code_length = 8; 792 1.1 christos } 793 1.1 christos } 794 1.1 christos 795 1.1 christos if (length == 4 796 1.1 christos || (length == 0 797 1.1 christos && (insn & 0x0600) == 0x0600)) 798 1.1 christos { 799 1.1 christos /* This is a 4 byte insn. */ 800 1.1 christos status = info->read_memory_func (memaddr, buffer, 4, info); 801 1.1 christos if (!status) 802 1.1 christos { 803 1.1 christos insn = bfd_getl32 (buffer); 804 1.1 christos 805 1.1 christos if (!length) 806 1.1 christos length = code_length = 4; 807 1.1 christos } 808 1.1 christos } 809 1.1 christos 810 1.1 christos if (code_length > length) 811 1.1 christos { 812 1.1 christos status = info->read_memory_func (memaddr + length, buffer, code_length - length, info); 813 1.1 christos if (status) 814 1.1 christos length = 0; 815 1.1 christos } 816 1.1 christos 817 1.1 christos if (length == 0 && !status) 818 1.1 christos length = code_length = 2; 819 1.1 christos 820 1.1 christos if (length == 2) 821 1.1 christos insn &= 0xffff; 822 1.1 christos 823 1.3 christos /* when the last 2 bytes of section is 0xffff, length will be 0 and cause infinitive loop */ 824 1.3 christos if (length == 0) 825 1.3 christos return -1; 826 1.3 christos 827 1.1 christos match = disassemble (memaddr, info, length, insn); 828 1.1 christos 829 1.1 christos if (!match) 830 1.1 christos { 831 1.1 christos int l = 0; 832 1.1 christos 833 1.1 christos status = info->read_memory_func (memaddr, buffer, code_length, info); 834 1.1 christos 835 1.1 christos while (l < code_length) 836 1.1 christos { 837 1.1 christos if (code_length - l == 2) 838 1.1 christos { 839 1.1 christos insn = bfd_getl16 (buffer + l) & 0xffff; 840 1.1 christos info->fprintf_func (info->stream, ".short\t0x%04lx", insn); 841 1.1 christos l += 2; 842 1.1 christos } 843 1.1 christos else 844 1.1 christos { 845 1.1 christos insn = bfd_getl32 (buffer + l); 846 1.1 christos info->fprintf_func (info->stream, ".long\t0x%08lx", insn); 847 1.1 christos l += 4; 848 1.1 christos } 849 1.1 christos } 850 1.1 christos } 851 1.1 christos 852 1.1 christos return code_length; 853 1.1 christos } 854