1 1.1 christos /* Print Motorola 68k instructions. 2 1.11 christos Copyright (C) 1986-2024 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 #include "sysdep.h" 22 1.8 christos #include "disassemble.h" 23 1.1 christos #include "floatformat.h" 24 1.1 christos #include "libiberty.h" 25 1.1 christos #include "opintl.h" 26 1.9 christos #include "cpu-m68k.h" 27 1.1 christos #include "opcode/m68k.h" 28 1.1 christos 29 1.1 christos /* Local function prototypes. */ 30 1.1 christos 31 1.1 christos const char * const fpcr_names[] = 32 1.1 christos { 33 1.1 christos "", "%fpiar", "%fpsr", "%fpiar/%fpsr", "%fpcr", 34 1.1 christos "%fpiar/%fpcr", "%fpsr/%fpcr", "%fpiar/%fpsr/%fpcr" 35 1.1 christos }; 36 1.1 christos 37 1.1 christos static char *const reg_names[] = 38 1.1 christos { 39 1.1 christos "%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", 40 1.1 christos "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%fp", "%sp", 41 1.1 christos "%ps", "%pc" 42 1.1 christos }; 43 1.1 christos 44 1.1 christos /* Name of register halves for MAC/EMAC. 45 1.1 christos Seperate from reg_names since 'spu', 'fpl' look weird. */ 46 1.1 christos static char *const reg_half_names[] = 47 1.1 christos { 48 1.1 christos "%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", 49 1.1 christos "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%a6", "%a7", 50 1.1 christos "%ps", "%pc" 51 1.1 christos }; 52 1.1 christos 53 1.1 christos /* Sign-extend an (unsigned char). */ 54 1.1 christos #if __STDC__ == 1 55 1.1 christos #define COERCE_SIGNED_CHAR(ch) ((signed char) (ch)) 56 1.1 christos #else 57 1.1 christos #define COERCE_SIGNED_CHAR(ch) ((int) (((ch) ^ 0x80) & 0xFF) - 128) 58 1.1 christos #endif 59 1.1 christos 60 1.7 christos /* Error code of print_insn_arg's return value. */ 61 1.7 christos 62 1.7 christos enum print_insn_arg_error 63 1.7 christos { 64 1.7 christos /* An invalid operand is found. */ 65 1.7 christos PRINT_INSN_ARG_INVALID_OPERAND = -1, 66 1.7 christos 67 1.7 christos /* An opcode table error. */ 68 1.7 christos PRINT_INSN_ARG_INVALID_OP_TABLE = -2, 69 1.7 christos 70 1.7 christos /* A memory error. */ 71 1.7 christos PRINT_INSN_ARG_MEMORY_ERROR = -3, 72 1.7 christos }; 73 1.7 christos 74 1.1 christos /* Get a 1 byte signed integer. */ 75 1.1 christos #define NEXTBYTE(p, val) \ 76 1.1 christos do \ 77 1.1 christos { \ 78 1.1 christos p += 2; \ 79 1.1 christos if (!FETCH_DATA (info, p)) \ 80 1.7 christos return PRINT_INSN_ARG_MEMORY_ERROR; \ 81 1.1 christos val = COERCE_SIGNED_CHAR (p[-1]); \ 82 1.1 christos } \ 83 1.1 christos while (0) 84 1.1 christos 85 1.1 christos /* Get a 2 byte signed integer. */ 86 1.1 christos #define COERCE16(x) ((int) (((x) ^ 0x8000) - 0x8000)) 87 1.1 christos 88 1.1 christos #define NEXTWORD(p, val, ret_val) \ 89 1.1 christos do \ 90 1.1 christos { \ 91 1.1 christos p += 2; \ 92 1.1 christos if (!FETCH_DATA (info, p)) \ 93 1.1 christos return ret_val; \ 94 1.1 christos val = COERCE16 ((p[-2] << 8) + p[-1]); \ 95 1.1 christos } \ 96 1.6 christos while (0) 97 1.1 christos 98 1.1 christos /* Get a 4 byte signed integer. */ 99 1.9 christos #define COERCE32(x) (((bfd_vma) (x) ^ 0x80000000) - 0x80000000) 100 1.1 christos 101 1.1 christos #define NEXTLONG(p, val, ret_val) \ 102 1.1 christos do \ 103 1.1 christos { \ 104 1.1 christos p += 4; \ 105 1.1 christos if (!FETCH_DATA (info, p)) \ 106 1.1 christos return ret_val; \ 107 1.9 christos val = COERCE32 (((((((unsigned) p[-4] << 8) + p[-3]) << 8) \ 108 1.9 christos + p[-2]) << 8) + p[-1]); \ 109 1.1 christos } \ 110 1.1 christos while (0) 111 1.1 christos 112 1.1 christos /* Get a 4 byte unsigned integer. */ 113 1.1 christos #define NEXTULONG(p, val) \ 114 1.1 christos do \ 115 1.1 christos { \ 116 1.1 christos p += 4; \ 117 1.1 christos if (!FETCH_DATA (info, p)) \ 118 1.7 christos return PRINT_INSN_ARG_MEMORY_ERROR; \ 119 1.9 christos val = (((((((unsigned) p[-4] << 8) + p[-3]) << 8) \ 120 1.9 christos + p[-2]) << 8) + p[-1]); \ 121 1.1 christos } \ 122 1.1 christos while (0) 123 1.1 christos 124 1.1 christos /* Get a single precision float. */ 125 1.1 christos #define NEXTSINGLE(val, p) \ 126 1.1 christos do \ 127 1.1 christos { \ 128 1.1 christos p += 4; \ 129 1.1 christos if (!FETCH_DATA (info, p)) \ 130 1.7 christos return PRINT_INSN_ARG_MEMORY_ERROR; \ 131 1.1 christos floatformat_to_double (& floatformat_ieee_single_big, \ 132 1.1 christos (char *) p - 4, & val); \ 133 1.1 christos } \ 134 1.1 christos while (0) 135 1.1 christos 136 1.1 christos /* Get a double precision float. */ 137 1.1 christos #define NEXTDOUBLE(val, p) \ 138 1.1 christos do \ 139 1.1 christos { \ 140 1.1 christos p += 8; \ 141 1.1 christos if (!FETCH_DATA (info, p)) \ 142 1.7 christos return PRINT_INSN_ARG_MEMORY_ERROR; \ 143 1.1 christos floatformat_to_double (& floatformat_ieee_double_big, \ 144 1.1 christos (char *) p - 8, & val); \ 145 1.1 christos } \ 146 1.1 christos while (0) 147 1.1 christos 148 1.1 christos /* Get an extended precision float. */ 149 1.1 christos #define NEXTEXTEND(val, p) \ 150 1.1 christos do \ 151 1.1 christos { \ 152 1.1 christos p += 12; \ 153 1.1 christos if (!FETCH_DATA (info, p)) \ 154 1.7 christos return PRINT_INSN_ARG_MEMORY_ERROR; \ 155 1.1 christos floatformat_to_double (& floatformat_m68881_ext, \ 156 1.1 christos (char *) p - 12, & val); \ 157 1.1 christos } \ 158 1.1 christos while (0) 159 1.1 christos 160 1.1 christos /* Need a function to convert from packed to double 161 1.1 christos precision. Actually, it's easier to print a 162 1.1 christos packed number than a double anyway, so maybe 163 1.1 christos there should be a special case to handle this... */ 164 1.1 christos #define NEXTPACKED(p, val) \ 165 1.1 christos do \ 166 1.1 christos { \ 167 1.1 christos p += 12; \ 168 1.1 christos if (!FETCH_DATA (info, p)) \ 169 1.7 christos return PRINT_INSN_ARG_MEMORY_ERROR; \ 170 1.1 christos val = 0.0; \ 171 1.1 christos } \ 172 1.1 christos while (0) 173 1.1 christos 174 1.1 christos 175 1.1 christos /* Maximum length of an instruction. */ 177 1.1 christos #define MAXLEN 22 178 1.1 christos 179 1.1 christos struct private 180 1.1 christos { 181 1.1 christos /* Points to first byte not fetched. */ 182 1.1 christos bfd_byte *max_fetched; 183 1.1 christos bfd_byte the_buffer[MAXLEN]; 184 1.1 christos bfd_vma insn_start; 185 1.1 christos }; 186 1.1 christos 187 1.7 christos /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive) 188 1.7 christos to ADDR (exclusive) are valid. Returns 1 for success, 0 on memory 189 1.1 christos error. */ 190 1.1 christos #define FETCH_DATA(info, addr) \ 191 1.1 christos ((addr) <= ((struct private *) (info->private_data))->max_fetched \ 192 1.1 christos ? 1 : fetch_data ((info), (addr))) 193 1.1 christos 194 1.1 christos static int 195 1.1 christos fetch_data (struct disassemble_info *info, bfd_byte *addr) 196 1.1 christos { 197 1.1 christos int status; 198 1.1 christos struct private *priv = (struct private *)info->private_data; 199 1.1 christos bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer); 200 1.1 christos 201 1.1 christos status = (*info->read_memory_func) (start, 202 1.1 christos priv->max_fetched, 203 1.1 christos addr - priv->max_fetched, 204 1.1 christos info); 205 1.1 christos if (status != 0) 206 1.1 christos { 207 1.1 christos (*info->memory_error_func) (status, start, info); 208 1.1 christos return 0; 209 1.1 christos } 210 1.1 christos else 211 1.1 christos priv->max_fetched = addr; 212 1.1 christos return 1; 213 1.1 christos } 214 1.1 christos 215 1.1 christos /* This function is used to print to the bit-bucket. */ 217 1.11 christos static int 218 1.1 christos dummy_printer (void *file ATTRIBUTE_UNUSED, 219 1.1 christos enum disassembler_style style ATTRIBUTE_UNUSED, 220 1.1 christos const char *format ATTRIBUTE_UNUSED, 221 1.1 christos ...) 222 1.1 christos { 223 1.1 christos return 0; 224 1.1 christos } 225 1.1 christos 226 1.1 christos static void 227 1.1 christos dummy_print_address (bfd_vma vma ATTRIBUTE_UNUSED, 228 1.1 christos struct disassemble_info *info ATTRIBUTE_UNUSED) 229 1.1 christos { 230 1.1 christos } 231 1.1 christos 232 1.1 christos /* Fetch BITS bits from a position in the instruction specified by CODE. 233 1.1 christos CODE is a "place to put an argument", or 'x' for a destination 234 1.1 christos that is a general address (mode and register). 235 1.1 christos BUFFER contains the instruction. 236 1.1 christos Returns -1 on failure. */ 237 1.1 christos 238 1.1 christos static int 239 1.1 christos fetch_arg (unsigned char *buffer, 240 1.1 christos int code, 241 1.1 christos int bits, 242 1.1 christos disassemble_info *info) 243 1.1 christos { 244 1.1 christos int val = 0; 245 1.1 christos 246 1.1 christos switch (code) 247 1.1 christos { 248 1.1 christos case '/': /* MAC/EMAC mask bit. */ 249 1.1 christos val = buffer[3] >> 5; 250 1.1 christos break; 251 1.1 christos 252 1.1 christos case 'G': /* EMAC ACC load. */ 253 1.1 christos val = ((buffer[3] >> 3) & 0x2) | ((~buffer[1] >> 7) & 0x1); 254 1.1 christos break; 255 1.1 christos 256 1.1 christos case 'H': /* EMAC ACC !load. */ 257 1.1 christos val = ((buffer[3] >> 3) & 0x2) | ((buffer[1] >> 7) & 0x1); 258 1.1 christos break; 259 1.1 christos 260 1.1 christos case ']': /* EMAC ACCEXT bit. */ 261 1.1 christos val = buffer[0] >> 2; 262 1.1 christos break; 263 1.1 christos 264 1.1 christos case 'I': /* MAC/EMAC scale factor. */ 265 1.1 christos val = buffer[2] >> 1; 266 1.1 christos break; 267 1.1 christos 268 1.1 christos case 'F': /* EMAC ACCx. */ 269 1.1 christos val = buffer[0] >> 1; 270 1.1 christos break; 271 1.1 christos 272 1.1 christos case 'f': 273 1.1 christos val = buffer[1]; 274 1.1 christos break; 275 1.1 christos 276 1.1 christos case 's': 277 1.1 christos val = buffer[1]; 278 1.1 christos break; 279 1.1 christos 280 1.1 christos case 'd': /* Destination, for register or quick. */ 281 1.1 christos val = (buffer[0] << 8) + buffer[1]; 282 1.1 christos val >>= 9; 283 1.1 christos break; 284 1.1 christos 285 1.1 christos case 'x': /* Destination, for general arg. */ 286 1.1 christos val = (buffer[0] << 8) + buffer[1]; 287 1.1 christos val >>= 6; 288 1.1 christos break; 289 1.1 christos 290 1.1 christos case 'k': 291 1.1 christos if (! FETCH_DATA (info, buffer + 3)) 292 1.1 christos return -1; 293 1.1 christos val = (buffer[3] >> 4); 294 1.1 christos break; 295 1.1 christos 296 1.1 christos case 'C': 297 1.1 christos if (! FETCH_DATA (info, buffer + 3)) 298 1.1 christos return -1; 299 1.1 christos val = buffer[3]; 300 1.1 christos break; 301 1.1 christos 302 1.1 christos case '1': 303 1.1 christos if (! FETCH_DATA (info, buffer + 3)) 304 1.1 christos return -1; 305 1.1 christos val = (buffer[2] << 8) + buffer[3]; 306 1.1 christos val >>= 12; 307 1.1 christos break; 308 1.1 christos 309 1.1 christos case '2': 310 1.1 christos if (! FETCH_DATA (info, buffer + 3)) 311 1.1 christos return -1; 312 1.1 christos val = (buffer[2] << 8) + buffer[3]; 313 1.1 christos val >>= 6; 314 1.1 christos break; 315 1.1 christos 316 1.1 christos case '3': 317 1.1 christos case 'j': 318 1.1 christos if (! FETCH_DATA (info, buffer + 3)) 319 1.1 christos return -1; 320 1.1 christos val = (buffer[2] << 8) + buffer[3]; 321 1.1 christos break; 322 1.1 christos 323 1.1 christos case '4': 324 1.1 christos if (! FETCH_DATA (info, buffer + 5)) 325 1.1 christos return -1; 326 1.1 christos val = (buffer[4] << 8) + buffer[5]; 327 1.1 christos val >>= 12; 328 1.1 christos break; 329 1.1 christos 330 1.1 christos case '5': 331 1.1 christos if (! FETCH_DATA (info, buffer + 5)) 332 1.1 christos return -1; 333 1.1 christos val = (buffer[4] << 8) + buffer[5]; 334 1.1 christos val >>= 6; 335 1.1 christos break; 336 1.1 christos 337 1.1 christos case '6': 338 1.1 christos if (! FETCH_DATA (info, buffer + 5)) 339 1.1 christos return -1; 340 1.1 christos val = (buffer[4] << 8) + buffer[5]; 341 1.1 christos break; 342 1.1 christos 343 1.1 christos case '7': 344 1.1 christos if (! FETCH_DATA (info, buffer + 3)) 345 1.1 christos return -1; 346 1.1 christos val = (buffer[2] << 8) + buffer[3]; 347 1.1 christos val >>= 7; 348 1.1 christos break; 349 1.1 christos 350 1.1 christos case '8': 351 1.1 christos if (! FETCH_DATA (info, buffer + 3)) 352 1.1 christos return -1; 353 1.1 christos val = (buffer[2] << 8) + buffer[3]; 354 1.1 christos val >>= 10; 355 1.1 christos break; 356 1.1 christos 357 1.1 christos case '9': 358 1.1 christos if (! FETCH_DATA (info, buffer + 3)) 359 1.1 christos return -1; 360 1.1 christos val = (buffer[2] << 8) + buffer[3]; 361 1.1 christos val >>= 5; 362 1.1 christos break; 363 1.1 christos 364 1.1 christos case 'e': 365 1.1 christos val = (buffer[1] >> 6); 366 1.1 christos break; 367 1.1 christos 368 1.1 christos case 'E': 369 1.1 christos if (! FETCH_DATA (info, buffer + 3)) 370 1.1 christos return -1; 371 1.1 christos val = (buffer[2] >> 1); 372 1.1 christos break; 373 1.1 christos 374 1.1 christos case 'm': 375 1.1 christos val = (buffer[1] & 0x40 ? 0x8 : 0) 376 1.1 christos | ((buffer[0] >> 1) & 0x7) 377 1.1 christos | (buffer[3] & 0x80 ? 0x10 : 0); 378 1.1 christos break; 379 1.1 christos 380 1.1 christos case 'n': 381 1.1 christos val = (buffer[1] & 0x40 ? 0x8 : 0) | ((buffer[0] >> 1) & 0x7); 382 1.1 christos break; 383 1.1 christos 384 1.1 christos case 'o': 385 1.1 christos val = (buffer[2] >> 4) | (buffer[3] & 0x80 ? 0x10 : 0); 386 1.1 christos break; 387 1.1 christos 388 1.1 christos case 'M': 389 1.1 christos val = (buffer[1] & 0xf) | (buffer[3] & 0x40 ? 0x10 : 0); 390 1.1 christos break; 391 1.1 christos 392 1.1 christos case 'N': 393 1.1 christos val = (buffer[3] & 0xf) | (buffer[3] & 0x40 ? 0x10 : 0); 394 1.1 christos break; 395 1.1 christos 396 1.1 christos case 'h': 397 1.1 christos val = buffer[2] >> 2; 398 1.1 christos break; 399 1.1 christos 400 1.1 christos default: 401 1.1 christos abort (); 402 1.1 christos } 403 1.1 christos 404 1.1 christos /* bits is never too big. */ 405 1.1 christos return val & ((1 << bits) - 1); 406 1.1 christos } 407 1.1 christos 408 1.1 christos /* Check if an EA is valid for a particular code. This is required 409 1.1 christos for the EMAC instructions since the type of source address determines 410 1.1 christos if it is a EMAC-load instruciton if the EA is mode 2-5, otherwise it 411 1.1 christos is a non-load EMAC instruction and the bits mean register Ry. 412 1.1 christos A similar case exists for the movem instructions where the register 413 1.10 christos mask is interpreted differently for different EAs. */ 414 1.1 christos 415 1.1 christos static bool 416 1.1 christos m68k_valid_ea (char code, int val) 417 1.1 christos { 418 1.1 christos int mode, mask; 419 1.1 christos #define M(n0,n1,n2,n3,n4,n5,n6,n70,n71,n72,n73,n74) \ 420 1.1 christos (n0 | n1 << 1 | n2 << 2 | n3 << 3 | n4 << 4 | n5 << 5 | n6 << 6 \ 421 1.1 christos | n70 << 7 | n71 << 8 | n72 << 9 | n73 << 10 | n74 << 11) 422 1.1 christos 423 1.1 christos switch (code) 424 1.1 christos { 425 1.1 christos case '*': 426 1.1 christos mask = M (1,1,1,1,1,1,1,1,1,1,1,1); 427 1.1 christos break; 428 1.1 christos case '~': 429 1.1 christos mask = M (0,0,1,1,1,1,1,1,1,0,0,0); 430 1.1 christos break; 431 1.1 christos case '%': 432 1.1 christos mask = M (1,1,1,1,1,1,1,1,1,0,0,0); 433 1.1 christos break; 434 1.1 christos case ';': 435 1.1 christos mask = M (1,0,1,1,1,1,1,1,1,1,1,1); 436 1.1 christos break; 437 1.1 christos case '@': 438 1.1 christos mask = M (1,0,1,1,1,1,1,1,1,1,1,0); 439 1.1 christos break; 440 1.1 christos case '!': 441 1.1 christos mask = M (0,0,1,0,0,1,1,1,1,1,1,0); 442 1.1 christos break; 443 1.1 christos case '&': 444 1.1 christos mask = M (0,0,1,0,0,1,1,1,1,0,0,0); 445 1.1 christos break; 446 1.1 christos case '$': 447 1.1 christos mask = M (1,0,1,1,1,1,1,1,1,0,0,0); 448 1.1 christos break; 449 1.1 christos case '?': 450 1.1 christos mask = M (1,0,1,0,0,1,1,1,1,0,0,0); 451 1.1 christos break; 452 1.1 christos case '/': 453 1.1 christos mask = M (1,0,1,0,0,1,1,1,1,1,1,0); 454 1.1 christos break; 455 1.1 christos case '|': 456 1.1 christos mask = M (0,0,1,0,0,1,1,1,1,1,1,0); 457 1.1 christos break; 458 1.1 christos case '>': 459 1.1 christos mask = M (0,0,1,0,1,1,1,1,1,0,0,0); 460 1.1 christos break; 461 1.1 christos case '<': 462 1.1 christos mask = M (0,0,1,1,0,1,1,1,1,1,1,0); 463 1.1 christos break; 464 1.1 christos case 'm': 465 1.1 christos mask = M (1,1,1,1,1,0,0,0,0,0,0,0); 466 1.1 christos break; 467 1.1 christos case 'n': 468 1.1 christos mask = M (0,0,0,0,0,1,0,0,0,1,0,0); 469 1.1 christos break; 470 1.1 christos case 'o': 471 1.1 christos mask = M (0,0,0,0,0,0,1,1,1,0,1,1); 472 1.1 christos break; 473 1.1 christos case 'p': 474 1.1 christos mask = M (1,1,1,1,1,1,0,0,0,0,0,0); 475 1.1 christos break; 476 1.1 christos case 'q': 477 1.1 christos mask = M (1,0,1,1,1,1,0,0,0,0,0,0); 478 1.1 christos break; 479 1.1 christos case 'v': 480 1.1 christos mask = M (1,0,1,1,1,1,0,1,1,0,0,0); 481 1.1 christos break; 482 1.1 christos case 'b': 483 1.1 christos mask = M (1,0,1,1,1,1,0,0,0,1,0,0); 484 1.1 christos break; 485 1.1 christos case 'w': 486 1.1 christos mask = M (0,0,1,1,1,1,0,0,0,1,0,0); 487 1.1 christos break; 488 1.1 christos case 'y': 489 1.1 christos mask = M (0,0,1,0,0,1,0,0,0,0,0,0); 490 1.1 christos break; 491 1.1 christos case 'z': 492 1.1 christos mask = M (0,0,1,0,0,1,0,0,0,1,0,0); 493 1.1 christos break; 494 1.1 christos case '4': 495 1.1 christos mask = M (0,0,1,1,1,1,0,0,0,0,0,0); 496 1.1 christos break; 497 1.1 christos default: 498 1.1 christos abort (); 499 1.1 christos } 500 1.1 christos #undef M 501 1.1 christos 502 1.1 christos mode = (val >> 3) & 7; 503 1.1 christos if (mode == 7) 504 1.1 christos mode += val & 7; 505 1.1 christos return (mask & (1 << mode)) != 0; 506 1.1 christos } 507 1.1 christos 508 1.1 christos /* Print a base register REGNO and displacement DISP, on INFO->STREAM. 509 1.1 christos REGNO = -1 for pc, -2 for none (suppressed). */ 510 1.1 christos 511 1.1 christos static void 512 1.1 christos print_base (int regno, bfd_vma disp, disassemble_info *info) 513 1.1 christos { 514 1.11 christos if (regno == -1) 515 1.11 christos { 516 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, "%%pc"); 517 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "@("); 518 1.1 christos (*info->print_address_func) (disp, info); 519 1.1 christos } 520 1.11 christos else 521 1.11 christos { 522 1.11 christos if (regno == -3) 523 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, 524 1.11 christos "%%zpc"); 525 1.11 christos else if (regno != -2) 526 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, 527 1.11 christos "%s", reg_names[regno]); 528 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "@("); 529 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate, 530 1.11 christos "%" PRIx64, (uint64_t) disp); 531 1.11 christos } 532 1.11 christos } 533 1.11 christos 534 1.11 christos /* Print the index register of an indexed argument, as encoded in the 535 1.11 christos extension word. */ 536 1.11 christos 537 1.11 christos static void 538 1.11 christos print_index_register (int ext, disassemble_info *info) 539 1.11 christos { 540 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, 541 1.11 christos "%s", reg_names[(ext >> 12) & 0xf]); 542 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, 543 1.11 christos ":%c", ext & 0x800 ? 'l' : 'w'); 544 1.11 christos if ((ext >> 9) & 3) 545 1.11 christos { 546 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, ":"); 547 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate, 548 1.1 christos "%d", 1 << ((ext >> 9) & 3)); 549 1.1 christos } 550 1.1 christos } 551 1.1 christos 552 1.1 christos /* Print an indexed argument. The base register is BASEREG (-1 for pc). 553 1.1 christos P points to extension word, in buffer. 554 1.1 christos ADDR is the nominal core address of that extension word. 555 1.1 christos Returns NULL upon error. */ 556 1.1 christos 557 1.1 christos static unsigned char * 558 1.1 christos print_indexed (int basereg, 559 1.1 christos unsigned char *p, 560 1.1 christos bfd_vma addr, 561 1.1 christos disassemble_info *info) 562 1.1 christos { 563 1.1 christos int word; 564 1.11 christos bfd_vma base_disp; 565 1.1 christos bfd_vma outer_disp; 566 1.1 christos bool print_index = true; 567 1.1 christos 568 1.1 christos NEXTWORD (p, word, NULL); 569 1.1 christos 570 1.1 christos /* Handle the 68000 style of indexing. */ 571 1.1 christos 572 1.1 christos if ((word & 0x100) == 0) 573 1.1 christos { 574 1.1 christos base_disp = word & 0xff; 575 1.1 christos if ((base_disp & 0x80) != 0) 576 1.1 christos base_disp -= 0x100; 577 1.1 christos if (basereg == -1) 578 1.11 christos base_disp += addr; 579 1.11 christos print_base (basereg, base_disp, info); 580 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, ","); 581 1.1 christos print_index_register (word, info); 582 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, ")"); 583 1.1 christos return p; 584 1.1 christos } 585 1.1 christos 586 1.1 christos /* Handle the generalized kind. */ 587 1.1 christos /* First, compute the displacement to add to the base register. */ 588 1.1 christos if (word & 0200) 589 1.1 christos { 590 1.1 christos if (basereg == -1) 591 1.1 christos basereg = -3; 592 1.1 christos else 593 1.1 christos basereg = -2; 594 1.11 christos } 595 1.1 christos if (word & 0100) 596 1.1 christos print_index = false; 597 1.1 christos base_disp = 0; 598 1.1 christos switch ((word >> 4) & 3) 599 1.1 christos { 600 1.1 christos case 2: 601 1.1 christos NEXTWORD (p, base_disp, NULL); 602 1.1 christos break; 603 1.1 christos case 3: 604 1.1 christos NEXTLONG (p, base_disp, NULL); 605 1.1 christos } 606 1.1 christos if (basereg == -1) 607 1.1 christos base_disp += addr; 608 1.1 christos 609 1.1 christos /* Handle single-level case (not indirect). */ 610 1.1 christos if ((word & 7) == 0) 611 1.11 christos { 612 1.11 christos print_base (basereg, base_disp, info); 613 1.11 christos if (print_index) 614 1.11 christos { 615 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, ","); 616 1.11 christos print_index_register (word, info); 617 1.1 christos } 618 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, ")"); 619 1.1 christos return p; 620 1.1 christos } 621 1.1 christos 622 1.1 christos /* Two level. Compute displacement to add after indirection. */ 623 1.1 christos outer_disp = 0; 624 1.1 christos switch (word & 3) 625 1.1 christos { 626 1.1 christos case 2: 627 1.1 christos NEXTWORD (p, outer_disp, NULL); 628 1.1 christos break; 629 1.1 christos case 3: 630 1.1 christos NEXTLONG (p, outer_disp, NULL); 631 1.1 christos } 632 1.11 christos 633 1.1 christos print_base (basereg, base_disp, info); 634 1.11 christos if ((word & 4) == 0 && print_index) 635 1.11 christos { 636 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, ","); 637 1.1 christos print_index_register (word, info); 638 1.11 christos print_index = false; 639 1.11 christos } 640 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, 641 1.11 christos ")@("); 642 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_address_offset, 643 1.11 christos "%" PRIx64, (uint64_t) outer_disp); 644 1.11 christos if (print_index) 645 1.11 christos { 646 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, ","); 647 1.11 christos print_index_register (word, info); 648 1.1 christos } 649 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, ")"); 650 1.1 christos 651 1.1 christos return p; 652 1.1 christos } 653 1.1 christos 654 1.1 christos #define FETCH_ARG(size, val) \ 655 1.1 christos do \ 656 1.1 christos { \ 657 1.7 christos val = fetch_arg (buffer, place, size, info); \ 658 1.1 christos if (val < 0) \ 659 1.1 christos return PRINT_INSN_ARG_MEMORY_ERROR; \ 660 1.1 christos } \ 661 1.1 christos while (0) 662 1.7 christos 663 1.7 christos /* Returns number of bytes "eaten" by the operand, or 664 1.1 christos return enum print_insn_arg_error. ADDR is the pc for this arg to be 665 1.1 christos relative to. */ 666 1.1 christos 667 1.1 christos static int 668 1.1 christos print_insn_arg (const char *d, 669 1.1 christos unsigned char *buffer, 670 1.1 christos unsigned char *p0, 671 1.1 christos bfd_vma addr, 672 1.1 christos disassemble_info *info) 673 1.1 christos { 674 1.1 christos int val = 0; 675 1.1 christos int place = d[1]; 676 1.1 christos unsigned char *p = p0; 677 1.1 christos int regno; 678 1.1 christos const char *regname; 679 1.1 christos unsigned char *p1; 680 1.1 christos double flval; 681 1.1 christos int flt_p; 682 1.1 christos bfd_signed_vma disp; 683 1.1 christos unsigned int uval; 684 1.1 christos 685 1.1 christos switch (*d) 686 1.1 christos { 687 1.1 christos case 'c': /* Cache identifier. */ 688 1.1 christos { 689 1.11 christos static char *const cacheFieldName[] = { "nc", "dc", "ic", "bc" }; 690 1.11 christos FETCH_ARG (2, val); 691 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_sub_mnemonic, 692 1.1 christos "%s", cacheFieldName[val]); 693 1.1 christos break; 694 1.1 christos } 695 1.1 christos 696 1.1 christos case 'a': /* Address register indirect only. Cf. case '+'. */ 697 1.11 christos { 698 1.11 christos FETCH_ARG (3, val); 699 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, "%s", 700 1.1 christos reg_names[val + 8]); 701 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "@"); 702 1.1 christos break; 703 1.1 christos } 704 1.1 christos 705 1.1 christos case '_': /* 32-bit absolute address for move16. */ 706 1.1 christos { 707 1.1 christos NEXTULONG (p, uval); 708 1.1 christos (*info->print_address_func) (uval, info); 709 1.1 christos break; 710 1.1 christos } 711 1.11 christos 712 1.1 christos case 'C': 713 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, "%%ccr"); 714 1.1 christos break; 715 1.11 christos 716 1.1 christos case 'S': 717 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, "%%sr"); 718 1.1 christos break; 719 1.11 christos 720 1.1 christos case 'U': 721 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, "%%usp"); 722 1.1 christos break; 723 1.11 christos 724 1.1 christos case 'E': 725 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, "%%acc"); 726 1.1 christos break; 727 1.11 christos 728 1.1 christos case 'G': 729 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, "%%macsr"); 730 1.1 christos break; 731 1.11 christos 732 1.1 christos case 'H': 733 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, "%%mask"); 734 1.1 christos break; 735 1.1 christos 736 1.1 christos case 'J': 737 1.1 christos { 738 1.1 christos /* FIXME: There's a problem here, different m68k processors call the 739 1.1 christos same address different names. The tables below try to get it right 740 1.1 christos using info->mach, but only for v4e. */ 741 1.1 christos struct regname { char * name; int value; }; 742 1.1 christos static const struct regname names[] = 743 1.1 christos { 744 1.1 christos {"%sfc", 0x000}, {"%dfc", 0x001}, {"%cacr", 0x002}, 745 1.1 christos {"%tc", 0x003}, {"%itt0",0x004}, {"%itt1", 0x005}, 746 1.1 christos {"%dtt0",0x006}, {"%dtt1",0x007}, {"%buscr",0x008}, 747 1.1 christos {"%rgpiobar", 0x009}, {"%acr4",0x00c}, 748 1.1 christos {"%acr5",0x00d}, {"%acr6",0x00e}, {"%acr7", 0x00f}, 749 1.1 christos {"%usp", 0x800}, {"%vbr", 0x801}, {"%caar", 0x802}, 750 1.1 christos {"%msp", 0x803}, {"%isp", 0x804}, 751 1.1 christos {"%pc", 0x80f}, 752 1.1 christos /* Reg c04 is sometimes called flashbar or rambar. 753 1.1 christos Reg c05 is also sometimes called rambar. */ 754 1.1 christos {"%rambar0", 0xc04}, {"%rambar1", 0xc05}, 755 1.1 christos 756 1.1 christos /* reg c0e is sometimes called mbar2 or secmbar. 757 1.1 christos reg c0f is sometimes called mbar. */ 758 1.1 christos {"%mbar0", 0xc0e}, {"%mbar1", 0xc0f}, 759 1.1 christos 760 1.1 christos /* Should we be calling this psr like we do in case 'Y'? */ 761 1.1 christos {"%mmusr",0x805}, 762 1.1 christos 763 1.1 christos {"%urp", 0x806}, {"%srp", 0x807}, {"%pcr", 0x808}, 764 1.1 christos 765 1.1 christos /* Fido added these. */ 766 1.1 christos {"%cac", 0xffe}, {"%mbo", 0xfff} 767 1.1 christos }; 768 1.1 christos /* Alternate names for v4e (MCF5407/5445x/MCF547x/MCF548x), at least. */ 769 1.1 christos static const struct regname names_v4e[] = 770 1.1 christos { 771 1.1 christos {"%asid",0x003}, {"%acr0",0x004}, {"%acr1",0x005}, 772 1.1 christos {"%acr2",0x006}, {"%acr3",0x007}, {"%mmubar",0x008}, 773 1.1 christos }; 774 1.1 christos unsigned int arch_mask; 775 1.1 christos 776 1.1 christos arch_mask = bfd_m68k_mach_to_features (info->mach); 777 1.1 christos FETCH_ARG (12, val); 778 1.1 christos if (arch_mask & (mcfisa_b | mcfisa_c)) 779 1.1 christos { 780 1.1 christos for (regno = ARRAY_SIZE (names_v4e); --regno >= 0;) 781 1.11 christos if (names_v4e[regno].value == val) 782 1.11 christos { 783 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, 784 1.1 christos "%s", names_v4e[regno].name); 785 1.1 christos break; 786 1.1 christos } 787 1.1 christos if (regno >= 0) 788 1.1 christos break; 789 1.1 christos } 790 1.1 christos for (regno = ARRAY_SIZE (names) - 1; regno >= 0; regno--) 791 1.11 christos if (names[regno].value == val) 792 1.11 christos { 793 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, 794 1.1 christos "%s", names[regno].name); 795 1.1 christos break; 796 1.11 christos } 797 1.1 christos if (regno < 0) 798 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "0x%x", val); 799 1.1 christos } 800 1.1 christos break; 801 1.1 christos 802 1.1 christos case 'Q': 803 1.1 christos FETCH_ARG (3, val); 804 1.1 christos /* 0 means 8, except for the bkpt instruction... */ 805 1.11 christos if (val == 0 && d[1] != 's') 806 1.11 christos val = 8; 807 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate, 808 1.1 christos "#%d", val); 809 1.1 christos break; 810 1.1 christos 811 1.1 christos case 'x': 812 1.1 christos FETCH_ARG (3, val); 813 1.1 christos /* 0 means -1. */ 814 1.11 christos if (val == 0) 815 1.11 christos val = -1; 816 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate, 817 1.1 christos "#%d", val); 818 1.1 christos break; 819 1.1 christos 820 1.11 christos case 'j': 821 1.11 christos FETCH_ARG (3, val); 822 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate, 823 1.1 christos "#%d", val+1); 824 1.1 christos break; 825 1.1 christos 826 1.11 christos case 'K': 827 1.11 christos FETCH_ARG (9, val); 828 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate, 829 1.1 christos "#%d", val); 830 1.1 christos break; 831 1.1 christos 832 1.1 christos case 'M': 833 1.1 christos if (place == 'h') 834 1.1 christos { 835 1.1 christos static char *const scalefactor_name[] = { "<<", ">>" }; 836 1.11 christos 837 1.11 christos FETCH_ARG (1, val); 838 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_sub_mnemonic, 839 1.1 christos "%s", scalefactor_name[val]); 840 1.1 christos } 841 1.1 christos else 842 1.1 christos { 843 1.1 christos FETCH_ARG (8, val); 844 1.11 christos if (val & 0x80) 845 1.11 christos val = val - 0x100; 846 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate, 847 1.1 christos "#%d", val); 848 1.1 christos } 849 1.1 christos break; 850 1.1 christos 851 1.11 christos case 'T': 852 1.11 christos FETCH_ARG (4, val); 853 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate, 854 1.1 christos "#%d", val); 855 1.1 christos break; 856 1.1 christos 857 1.11 christos case 'D': 858 1.11 christos FETCH_ARG (3, val); 859 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, 860 1.1 christos "%s", reg_names[val]); 861 1.1 christos break; 862 1.1 christos 863 1.11 christos case 'A': 864 1.11 christos FETCH_ARG (3, val); 865 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, 866 1.1 christos "%s", reg_names[val + 010]); 867 1.1 christos break; 868 1.1 christos 869 1.11 christos case 'R': 870 1.11 christos FETCH_ARG (4, val); 871 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, 872 1.1 christos "%s", reg_names[val]); 873 1.1 christos break; 874 1.1 christos 875 1.1 christos case 'r': 876 1.11 christos FETCH_ARG (4, regno); 877 1.11 christos if (regno > 7) 878 1.11 christos { 879 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, 880 1.11 christos "%s", reg_names[regno]); 881 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "@"); 882 1.11 christos } 883 1.11 christos else 884 1.11 christos { 885 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "@("); 886 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, 887 1.11 christos "%s", reg_names[regno]); 888 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, ")"); 889 1.1 christos } 890 1.1 christos break; 891 1.1 christos 892 1.11 christos case 'F': 893 1.11 christos FETCH_ARG (3, val); 894 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, 895 1.1 christos "%%fp%d", val); 896 1.1 christos break; 897 1.1 christos 898 1.1 christos case 'O': 899 1.11 christos FETCH_ARG (6, val); 900 1.11 christos if (val & 0x20) 901 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, 902 1.11 christos "%s", reg_names[val & 7]); 903 1.11 christos else 904 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate, 905 1.1 christos "%d", val); 906 1.1 christos break; 907 1.1 christos 908 1.11 christos case '+': 909 1.11 christos FETCH_ARG (3, val); 910 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, 911 1.1 christos "%s", reg_names[val + 8]); 912 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "@+"); 913 1.1 christos break; 914 1.1 christos 915 1.11 christos case '-': 916 1.11 christos FETCH_ARG (3, val); 917 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, 918 1.1 christos "%s", reg_names[val + 8]); 919 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "@-"); 920 1.1 christos break; 921 1.1 christos 922 1.1 christos case 'k': 923 1.1 christos if (place == 'k') 924 1.11 christos { 925 1.11 christos FETCH_ARG (3, val); 926 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "{"); 927 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, 928 1.1 christos "%s", reg_names[val]); 929 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "}"); 930 1.1 christos } 931 1.1 christos else if (place == 'C') 932 1.1 christos { 933 1.1 christos FETCH_ARG (7, val); 934 1.11 christos if (val > 63) /* This is a signed constant. */ 935 1.11 christos val -= 128; 936 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "{"); 937 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate, 938 1.1 christos "#%d", val); 939 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "}"); 940 1.7 christos } 941 1.1 christos else 942 1.1 christos return PRINT_INSN_ARG_INVALID_OPERAND; 943 1.1 christos break; 944 1.1 christos 945 1.1 christos case '#': 946 1.1 christos case '^': 947 1.1 christos p1 = buffer + (*d == '#' ? 2 : 4); 948 1.1 christos if (place == 's') 949 1.1 christos FETCH_ARG (4, val); 950 1.1 christos else if (place == 'C') 951 1.1 christos FETCH_ARG (7, val); 952 1.1 christos else if (place == '8') 953 1.1 christos FETCH_ARG (3, val); 954 1.1 christos else if (place == '3') 955 1.1 christos FETCH_ARG (8, val); 956 1.1 christos else if (place == 'b') 957 1.7 christos NEXTBYTE (p1, val); 958 1.1 christos else if (place == 'w' || place == 'W') 959 1.7 christos NEXTWORD (p1, val, PRINT_INSN_ARG_MEMORY_ERROR); 960 1.1 christos else if (place == 'l') 961 1.7 christos NEXTLONG (p1, val, PRINT_INSN_ARG_MEMORY_ERROR); 962 1.1 christos else 963 1.11 christos return PRINT_INSN_ARG_INVALID_OP_TABLE; 964 1.11 christos 965 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate, 966 1.1 christos "#%d", val); 967 1.1 christos break; 968 1.1 christos 969 1.1 christos case 'B': 970 1.1 christos if (place == 'b') 971 1.1 christos NEXTBYTE (p, disp); 972 1.1 christos else if (place == 'B') 973 1.7 christos disp = COERCE_SIGNED_CHAR (buffer[1]); 974 1.1 christos else if (place == 'w' || place == 'W') 975 1.7 christos NEXTWORD (p, disp, PRINT_INSN_ARG_MEMORY_ERROR); 976 1.1 christos else if (place == 'l' || place == 'L' || place == 'C') 977 1.1 christos NEXTLONG (p, disp, PRINT_INSN_ARG_MEMORY_ERROR); 978 1.1 christos else if (place == 'g') 979 1.1 christos { 980 1.7 christos NEXTBYTE (buffer, disp); 981 1.1 christos if (disp == 0) 982 1.7 christos NEXTWORD (p, disp, PRINT_INSN_ARG_MEMORY_ERROR); 983 1.1 christos else if (disp == -1) 984 1.1 christos NEXTLONG (p, disp, PRINT_INSN_ARG_MEMORY_ERROR); 985 1.1 christos } 986 1.1 christos else if (place == 'c') 987 1.7 christos { 988 1.1 christos if (buffer[1] & 0x40) /* If bit six is one, long offset. */ 989 1.7 christos NEXTLONG (p, disp, PRINT_INSN_ARG_MEMORY_ERROR); 990 1.1 christos else 991 1.1 christos NEXTWORD (p, disp, PRINT_INSN_ARG_MEMORY_ERROR); 992 1.7 christos } 993 1.1 christos else 994 1.1 christos return PRINT_INSN_ARG_INVALID_OP_TABLE; 995 1.1 christos 996 1.1 christos (*info->print_address_func) (addr + disp, info); 997 1.1 christos break; 998 1.1 christos 999 1.1 christos case 'd': 1000 1.1 christos { 1001 1.7 christos int val1; 1002 1.1 christos 1003 1.11 christos NEXTWORD (p, val, PRINT_INSN_ARG_MEMORY_ERROR); 1004 1.11 christos FETCH_ARG (3, val1); 1005 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, 1006 1.11 christos "%s", reg_names[val1 + 8]); 1007 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "@("); 1008 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_address_offset, 1009 1.1 christos "%d", val); 1010 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, ")"); 1011 1.1 christos break; 1012 1.1 christos } 1013 1.1 christos 1014 1.11 christos case 's': 1015 1.11 christos FETCH_ARG (3, val); 1016 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, 1017 1.1 christos "%s", fpcr_names[val]); 1018 1.1 christos break; 1019 1.1 christos 1020 1.11 christos case 'e': 1021 1.11 christos FETCH_ARG (2, val); 1022 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, 1023 1.1 christos "%%acc%d", val); 1024 1.1 christos break; 1025 1.1 christos 1026 1.11 christos case 'g': 1027 1.11 christos FETCH_ARG (1, val); 1028 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, 1029 1.1 christos "%%accext%s", val == 0 ? "01" : "23"); 1030 1.1 christos break; 1031 1.1 christos 1032 1.1 christos case 'i': 1033 1.11 christos FETCH_ARG (2, val); 1034 1.11 christos if (val == 1) 1035 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_sub_mnemonic, 1036 1.11 christos "<<"); 1037 1.11 christos else if (val == 3) 1038 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_sub_mnemonic, 1039 1.7 christos ">>"); 1040 1.1 christos else 1041 1.1 christos return PRINT_INSN_ARG_INVALID_OPERAND; 1042 1.1 christos break; 1043 1.1 christos 1044 1.1 christos case 'I': 1045 1.1 christos /* Get coprocessor ID... */ 1046 1.7 christos val = fetch_arg (buffer, 'd', 3, info); 1047 1.1 christos if (val < 0) 1048 1.11 christos return PRINT_INSN_ARG_MEMORY_ERROR; 1049 1.11 christos if (val != 1) /* Unusual coprocessor ID? */ 1050 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, 1051 1.1 christos "(cpid=%d) ", val); 1052 1.1 christos break; 1053 1.1 christos 1054 1.1 christos case '4': 1055 1.1 christos case '*': 1056 1.1 christos case '~': 1057 1.1 christos case '%': 1058 1.1 christos case ';': 1059 1.1 christos case '@': 1060 1.1 christos case '!': 1061 1.1 christos case '$': 1062 1.1 christos case '?': 1063 1.1 christos case '/': 1064 1.1 christos case '&': 1065 1.1 christos case '|': 1066 1.1 christos case '<': 1067 1.1 christos case '>': 1068 1.1 christos case 'm': 1069 1.1 christos case 'n': 1070 1.1 christos case 'o': 1071 1.1 christos case 'p': 1072 1.1 christos case 'q': 1073 1.1 christos case 'v': 1074 1.1 christos case 'b': 1075 1.1 christos case 'w': 1076 1.1 christos case 'y': 1077 1.1 christos case 'z': 1078 1.1 christos if (place == 'd') 1079 1.1 christos { 1080 1.7 christos val = fetch_arg (buffer, 'x', 6, info); 1081 1.1 christos if (val < 0) 1082 1.1 christos return PRINT_INSN_ARG_MEMORY_ERROR; 1083 1.1 christos val = ((val & 7) << 3) + ((val >> 3) & 7); 1084 1.1 christos } 1085 1.1 christos else 1086 1.1 christos { 1087 1.7 christos val = fetch_arg (buffer, 's', 6, info); 1088 1.1 christos if (val < 0) 1089 1.1 christos return PRINT_INSN_ARG_MEMORY_ERROR; 1090 1.1 christos } 1091 1.1 christos 1092 1.7 christos /* If the <ea> is invalid for *d, then reject this match. */ 1093 1.1 christos if (!m68k_valid_ea (*d, val)) 1094 1.1 christos return PRINT_INSN_ARG_INVALID_OPERAND; 1095 1.1 christos 1096 1.1 christos /* Get register number assuming address register. */ 1097 1.1 christos regno = (val & 7) + 8; 1098 1.1 christos regname = reg_names[regno]; 1099 1.1 christos switch (val >> 3) 1100 1.11 christos { 1101 1.11 christos case 0: 1102 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, 1103 1.1 christos "%s", reg_names[val]); 1104 1.1 christos break; 1105 1.11 christos 1106 1.11 christos case 1: 1107 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, 1108 1.1 christos "%s", regname); 1109 1.1 christos break; 1110 1.11 christos 1111 1.11 christos case 2: 1112 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, 1113 1.1 christos "%s", regname); 1114 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "@"); 1115 1.1 christos break; 1116 1.11 christos 1117 1.11 christos case 3: 1118 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, 1119 1.1 christos "%s", regname); 1120 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "@+"); 1121 1.1 christos break; 1122 1.11 christos 1123 1.11 christos case 4: 1124 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, 1125 1.1 christos "%s", regname); 1126 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "@-"); 1127 1.1 christos break; 1128 1.7 christos 1129 1.11 christos case 5: 1130 1.11 christos NEXTWORD (p, val, PRINT_INSN_ARG_MEMORY_ERROR); 1131 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, 1132 1.11 christos "%s", regname); 1133 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "@("); 1134 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_address_offset, 1135 1.1 christos "%d", val); 1136 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, ")"); 1137 1.1 christos break; 1138 1.1 christos 1139 1.1 christos case 6: 1140 1.7 christos p = print_indexed (regno, p, addr, info); 1141 1.1 christos if (p == NULL) 1142 1.1 christos return PRINT_INSN_ARG_MEMORY_ERROR; 1143 1.1 christos break; 1144 1.1 christos 1145 1.1 christos case 7: 1146 1.1 christos switch (val & 7) 1147 1.7 christos { 1148 1.1 christos case 0: 1149 1.1 christos NEXTWORD (p, val, PRINT_INSN_ARG_MEMORY_ERROR); 1150 1.1 christos (*info->print_address_func) (val, info); 1151 1.1 christos break; 1152 1.1 christos 1153 1.1 christos case 1: 1154 1.1 christos NEXTULONG (p, uval); 1155 1.1 christos (*info->print_address_func) (uval, info); 1156 1.1 christos break; 1157 1.7 christos 1158 1.11 christos case 2: 1159 1.11 christos NEXTWORD (p, val, PRINT_INSN_ARG_MEMORY_ERROR); 1160 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, 1161 1.1 christos "%%pc"); 1162 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "@("); 1163 1.1 christos (*info->print_address_func) (addr + val, info); 1164 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, ")"); 1165 1.1 christos break; 1166 1.1 christos 1167 1.1 christos case 3: 1168 1.7 christos p = print_indexed (-1, p, addr, info); 1169 1.1 christos if (p == NULL) 1170 1.1 christos return PRINT_INSN_ARG_MEMORY_ERROR; 1171 1.1 christos break; 1172 1.1 christos 1173 1.1 christos case 4: 1174 1.1 christos flt_p = 1; /* Assume it's a float... */ 1175 1.1 christos switch (place) 1176 1.1 christos { 1177 1.1 christos case 'b': 1178 1.1 christos NEXTBYTE (p, val); 1179 1.1 christos flt_p = 0; 1180 1.1 christos break; 1181 1.7 christos 1182 1.1 christos case 'w': 1183 1.1 christos NEXTWORD (p, val, PRINT_INSN_ARG_MEMORY_ERROR); 1184 1.1 christos flt_p = 0; 1185 1.1 christos break; 1186 1.7 christos 1187 1.1 christos case 'l': 1188 1.1 christos NEXTLONG (p, val, PRINT_INSN_ARG_MEMORY_ERROR); 1189 1.1 christos flt_p = 0; 1190 1.1 christos break; 1191 1.1 christos 1192 1.1 christos case 'f': 1193 1.1 christos NEXTSINGLE (flval, p); 1194 1.1 christos break; 1195 1.1 christos 1196 1.1 christos case 'F': 1197 1.1 christos NEXTDOUBLE (flval, p); 1198 1.1 christos break; 1199 1.1 christos 1200 1.1 christos case 'x': 1201 1.1 christos NEXTEXTEND (flval, p); 1202 1.1 christos break; 1203 1.1 christos 1204 1.1 christos case 'p': 1205 1.1 christos NEXTPACKED (p, flval); 1206 1.1 christos break; 1207 1.7 christos 1208 1.1 christos default: 1209 1.1 christos return PRINT_INSN_ARG_INVALID_OPERAND; 1210 1.11 christos } 1211 1.11 christos if (flt_p) /* Print a float? */ 1212 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate, 1213 1.11 christos "#0e%g", flval); 1214 1.11 christos else 1215 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate, 1216 1.1 christos "#%d", val); 1217 1.1 christos break; 1218 1.7 christos 1219 1.1 christos default: 1220 1.1 christos return PRINT_INSN_ARG_INVALID_OPERAND; 1221 1.1 christos } 1222 1.1 christos } 1223 1.1 christos 1224 1.1 christos /* If place is '/', then this is the case of the mask bit for 1225 1.1 christos mac/emac loads. Now that the arg has been printed, grab the 1226 1.1 christos mask bit and if set, add a '&' to the arg. */ 1227 1.1 christos if (place == '/') 1228 1.1 christos { 1229 1.11 christos FETCH_ARG (1, val); 1230 1.1 christos if (val) 1231 1.1 christos info->fprintf_styled_func (info->stream, dis_style_text, "&"); 1232 1.1 christos } 1233 1.1 christos break; 1234 1.1 christos 1235 1.1 christos case 'L': 1236 1.1 christos case 'l': 1237 1.1 christos if (place == 'w') 1238 1.1 christos { 1239 1.7 christos char doneany; 1240 1.1 christos p1 = buffer + 2; 1241 1.1 christos NEXTWORD (p1, val, PRINT_INSN_ARG_MEMORY_ERROR); 1242 1.1 christos /* Move the pointer ahead if this point is farther ahead 1243 1.1 christos than the last. */ 1244 1.1 christos p = p1 > p ? p1 : p; 1245 1.11 christos if (val == 0) 1246 1.11 christos { 1247 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate, 1248 1.1 christos "#0"); 1249 1.1 christos break; 1250 1.1 christos } 1251 1.1 christos if (*d == 'l') 1252 1.1 christos { 1253 1.1 christos int newval = 0; 1254 1.1 christos 1255 1.1 christos for (regno = 0; regno < 16; ++regno) 1256 1.1 christos if (val & (0x8000 >> regno)) 1257 1.1 christos newval |= 1 << regno; 1258 1.1 christos val = newval; 1259 1.1 christos } 1260 1.1 christos val &= 0xffff; 1261 1.1 christos doneany = 0; 1262 1.1 christos for (regno = 0; regno < 16; ++regno) 1263 1.1 christos if (val & (1 << regno)) 1264 1.1 christos { 1265 1.1 christos int first_regno; 1266 1.11 christos 1267 1.11 christos if (doneany) 1268 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, 1269 1.11 christos "/"); 1270 1.11 christos doneany = 1; 1271 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, 1272 1.1 christos "%s", reg_names[regno]); 1273 1.1 christos first_regno = regno; 1274 1.1 christos while (val & (1 << (regno + 1))) 1275 1.11 christos ++regno; 1276 1.11 christos if (regno > first_regno) 1277 1.11 christos { 1278 1.11 christos (*info->fprintf_styled_func) (info->stream, 1279 1.11 christos dis_style_text, "-"); 1280 1.11 christos (*info->fprintf_styled_func) (info->stream, 1281 1.11 christos dis_style_register, "%s", 1282 1.1 christos reg_names[regno]); 1283 1.1 christos } 1284 1.1 christos } 1285 1.1 christos } 1286 1.1 christos else if (place == '3') 1287 1.1 christos { 1288 1.1 christos /* `fmovem' insn. */ 1289 1.1 christos char doneany; 1290 1.1 christos 1291 1.1 christos FETCH_ARG (8, val); 1292 1.11 christos if (val == 0) 1293 1.11 christos { 1294 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate, 1295 1.1 christos "#0"); 1296 1.1 christos break; 1297 1.1 christos } 1298 1.1 christos if (*d == 'l') 1299 1.1 christos { 1300 1.1 christos int newval = 0; 1301 1.1 christos 1302 1.1 christos for (regno = 0; regno < 8; ++regno) 1303 1.1 christos if (val & (0x80 >> regno)) 1304 1.1 christos newval |= 1 << regno; 1305 1.1 christos val = newval; 1306 1.1 christos } 1307 1.1 christos val &= 0xff; 1308 1.1 christos doneany = 0; 1309 1.1 christos for (regno = 0; regno < 8; ++regno) 1310 1.1 christos if (val & (1 << regno)) 1311 1.1 christos { 1312 1.11 christos int first_regno; 1313 1.11 christos if (doneany) 1314 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, 1315 1.11 christos "/"); 1316 1.11 christos doneany = 1; 1317 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, 1318 1.1 christos "%%fp%d", regno); 1319 1.1 christos first_regno = regno; 1320 1.1 christos while (val & (1 << (regno + 1))) 1321 1.11 christos ++regno; 1322 1.11 christos if (regno > first_regno) 1323 1.11 christos { 1324 1.11 christos (*info->fprintf_styled_func) (info->stream, 1325 1.11 christos dis_style_text, "-"); 1326 1.11 christos (*info->fprintf_styled_func) (info->stream, 1327 1.11 christos dis_style_register, 1328 1.1 christos "%%fp%d", regno); 1329 1.1 christos } 1330 1.1 christos } 1331 1.1 christos } 1332 1.1 christos else if (place == '8') 1333 1.1 christos { 1334 1.11 christos FETCH_ARG (3, val); 1335 1.11 christos /* fmoveml for FP status registers. */ 1336 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, 1337 1.1 christos "%s", fpcr_names[val]); 1338 1.7 christos } 1339 1.1 christos else 1340 1.1 christos return PRINT_INSN_ARG_INVALID_OP_TABLE; 1341 1.1 christos break; 1342 1.1 christos 1343 1.7 christos case 'X': 1344 1.1 christos place = '8'; 1345 1.1 christos /* Fall through. */ 1346 1.1 christos case 'Y': 1347 1.1 christos case 'Z': 1348 1.1 christos case 'W': 1349 1.1 christos case '0': 1350 1.1 christos case '1': 1351 1.1 christos case '2': 1352 1.1 christos case '3': 1353 1.1 christos { 1354 1.1 christos char *name = 0; 1355 1.1 christos 1356 1.1 christos FETCH_ARG (5, val); 1357 1.1 christos switch (val) 1358 1.1 christos { 1359 1.1 christos case 2: name = "%tt0"; break; 1360 1.1 christos case 3: name = "%tt1"; break; 1361 1.1 christos case 0x10: name = "%tc"; break; 1362 1.1 christos case 0x11: name = "%drp"; break; 1363 1.1 christos case 0x12: name = "%srp"; break; 1364 1.1 christos case 0x13: name = "%crp"; break; 1365 1.1 christos case 0x14: name = "%cal"; break; 1366 1.1 christos case 0x15: name = "%val"; break; 1367 1.1 christos case 0x16: name = "%scc"; break; 1368 1.1 christos case 0x17: name = "%ac"; break; 1369 1.1 christos case 0x18: name = "%psr"; break; 1370 1.1 christos case 0x19: name = "%pcsr"; break; 1371 1.1 christos case 0x1c: 1372 1.1 christos case 0x1d: 1373 1.1 christos { 1374 1.11 christos int break_reg = ((buffer[3] >> 2) & 7); 1375 1.11 christos 1376 1.11 christos (*info->fprintf_styled_func) 1377 1.1 christos (info->stream, dis_style_register, 1378 1.1 christos val == 0x1c ? "%%bad%d" : "%%bac%d", break_reg); 1379 1.1 christos } 1380 1.11 christos break; 1381 1.11 christos default: 1382 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, 1383 1.1 christos "<mmu register %d>", val); 1384 1.11 christos } 1385 1.11 christos if (name) 1386 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, 1387 1.1 christos "%s", name); 1388 1.1 christos } 1389 1.1 christos break; 1390 1.1 christos 1391 1.1 christos case 'f': 1392 1.1 christos { 1393 1.1 christos int fc; 1394 1.1 christos 1395 1.11 christos FETCH_ARG (5, fc); 1396 1.11 christos if (fc == 1) 1397 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, 1398 1.11 christos "%%dfc"); 1399 1.11 christos else if (fc == 0) 1400 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, 1401 1.1 christos "%%sfc"); 1402 1.11 christos else 1403 1.11 christos /* xgettext:c-format */ 1404 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, 1405 1.1 christos _("<function code %d>"), fc); 1406 1.1 christos } 1407 1.1 christos break; 1408 1.11 christos 1409 1.1 christos case 'V': 1410 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, "%%val"); 1411 1.1 christos break; 1412 1.1 christos 1413 1.1 christos case 't': 1414 1.1 christos { 1415 1.1 christos int level; 1416 1.11 christos 1417 1.11 christos FETCH_ARG (3, level); 1418 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate, 1419 1.1 christos "%d", level); 1420 1.1 christos } 1421 1.1 christos break; 1422 1.1 christos 1423 1.1 christos case 'u': 1424 1.1 christos { 1425 1.1 christos short is_upper = 0; 1426 1.1 christos int reg; 1427 1.1 christos 1428 1.1 christos FETCH_ARG (5, reg); 1429 1.1 christos if (reg & 0x10) 1430 1.1 christos { 1431 1.1 christos is_upper = 1; 1432 1.11 christos reg &= 0xf; 1433 1.11 christos } 1434 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, "%s%s", 1435 1.1 christos reg_half_names[reg], 1436 1.1 christos is_upper ? "u" : "l"); 1437 1.1 christos } 1438 1.1 christos break; 1439 1.7 christos 1440 1.1 christos default: 1441 1.1 christos return PRINT_INSN_ARG_INVALID_OP_TABLE; 1442 1.1 christos } 1443 1.1 christos 1444 1.1 christos return p - p0; 1445 1.1 christos } 1446 1.7 christos 1447 1.7 christos /* Try to match the current instruction to best and if so, return the 1448 1.1 christos number of bytes consumed from the instruction stream, else zero. 1449 1.1 christos Return -1 on memory error. */ 1450 1.1 christos 1451 1.1 christos static int 1452 1.1 christos match_insn_m68k (bfd_vma memaddr, 1453 1.1 christos disassemble_info * info, 1454 1.1 christos const struct m68k_opcode * best) 1455 1.1 christos { 1456 1.1 christos unsigned char *save_p; 1457 1.1 christos unsigned char *p; 1458 1.1 christos const char *d; 1459 1.1 christos const char *args = best->args; 1460 1.1 christos 1461 1.11 christos struct private *priv = (struct private *) info->private_data; 1462 1.1 christos bfd_byte *buffer = priv->the_buffer; 1463 1.1 christos fprintf_styled_ftype save_printer = info->fprintf_styled_func; 1464 1.1 christos void (* save_print_address) (bfd_vma, struct disassemble_info *) 1465 1.1 christos = info->print_address_func; 1466 1.1 christos 1467 1.6 christos if (*args == '.') 1468 1.1 christos args++; 1469 1.1 christos 1470 1.1 christos /* Point at first word of argument data, 1471 1.1 christos and at descriptor for first argument. */ 1472 1.1 christos p = buffer + 2; 1473 1.1 christos 1474 1.1 christos /* Figure out how long the fixed-size portion of the instruction is. 1475 1.1 christos The only place this is stored in the opcode table is 1476 1.1 christos in the arguments--look for arguments which specify fields in the 2nd 1477 1.1 christos or 3rd words of the instruction. */ 1478 1.1 christos for (d = args; *d; d += 2) 1479 1.1 christos { 1480 1.1 christos /* I don't think it is necessary to be checking d[0] here; 1481 1.1 christos I suspect all this could be moved to the case statement below. */ 1482 1.1 christos if (d[0] == '#') 1483 1.1 christos { 1484 1.1 christos if (d[1] == 'l' && p - buffer < 6) 1485 1.1 christos p = buffer + 6; 1486 1.1 christos else if (p - buffer < 4 && d[1] != 'C' && d[1] != '8') 1487 1.1 christos p = buffer + 4; 1488 1.1 christos } 1489 1.1 christos 1490 1.1 christos if ((d[0] == 'L' || d[0] == 'l') && d[1] == 'w' && p - buffer < 4) 1491 1.1 christos p = buffer + 4; 1492 1.1 christos 1493 1.1 christos switch (d[1]) 1494 1.1 christos { 1495 1.1 christos case '1': 1496 1.1 christos case '2': 1497 1.1 christos case '3': 1498 1.1 christos case '7': 1499 1.1 christos case '8': 1500 1.1 christos case '9': 1501 1.1 christos case 'i': 1502 1.1 christos if (p - buffer < 4) 1503 1.1 christos p = buffer + 4; 1504 1.1 christos break; 1505 1.1 christos case '4': 1506 1.1 christos case '5': 1507 1.1 christos case '6': 1508 1.1 christos if (p - buffer < 6) 1509 1.1 christos p = buffer + 6; 1510 1.1 christos break; 1511 1.1 christos default: 1512 1.1 christos break; 1513 1.1 christos } 1514 1.1 christos } 1515 1.1 christos 1516 1.1 christos /* pflusha is an exceptions. It takes no arguments but is two words 1517 1.1 christos long. Recognize it by looking at the lower 16 bits of the mask. */ 1518 1.1 christos if (p - buffer < 4 && (best->match & 0xFFFF) != 0) 1519 1.1 christos p = buffer + 4; 1520 1.1 christos 1521 1.1 christos /* lpstop is another exception. It takes a one word argument but is 1522 1.1 christos three words long. */ 1523 1.1 christos if (p - buffer < 6 1524 1.1 christos && (best->match & 0xffff) == 0xffff 1525 1.1 christos && args[0] == '#' 1526 1.1 christos && args[1] == 'w') 1527 1.1 christos { 1528 1.1 christos /* Copy the one word argument into the usual location for a one 1529 1.1 christos word argument, to simplify printing it. We can get away with 1530 1.1 christos this because we know exactly what the second word is, and we 1531 1.7 christos aren't going to print anything based on it. */ 1532 1.7 christos p = buffer + 6; 1533 1.1 christos if (!FETCH_DATA (info, p)) 1534 1.1 christos return -1; 1535 1.1 christos buffer[2] = buffer[4]; 1536 1.1 christos buffer[3] = buffer[5]; 1537 1.7 christos } 1538 1.7 christos 1539 1.1 christos if (!FETCH_DATA (info, p)) 1540 1.1 christos return -1; 1541 1.1 christos 1542 1.11 christos save_p = p; 1543 1.1 christos info->print_address_func = dummy_print_address; 1544 1.1 christos info->fprintf_styled_func = dummy_printer; 1545 1.1 christos 1546 1.1 christos /* We scan the operands twice. The first time we don't print anything, 1547 1.1 christos but look for errors. */ 1548 1.1 christos for (d = args; *d; d += 2) 1549 1.1 christos { 1550 1.1 christos int eaten = print_insn_arg (d, buffer, p, memaddr + (p - buffer), info); 1551 1.1 christos 1552 1.7 christos if (eaten >= 0) 1553 1.7 christos p += eaten; 1554 1.1 christos else if (eaten == PRINT_INSN_ARG_INVALID_OPERAND 1555 1.11 christos || eaten == PRINT_INSN_ARG_MEMORY_ERROR) 1556 1.1 christos { 1557 1.7 christos info->fprintf_styled_func = save_printer; 1558 1.1 christos info->print_address_func = save_print_address; 1559 1.1 christos return eaten == PRINT_INSN_ARG_MEMORY_ERROR ? -1 : 0; 1560 1.1 christos } 1561 1.1 christos else 1562 1.1 christos { 1563 1.11 christos /* We must restore the print functions before trying to print the 1564 1.1 christos error message. */ 1565 1.11 christos info->fprintf_styled_func = save_printer; 1566 1.11 christos info->print_address_func = save_print_address; 1567 1.11 christos info->fprintf_styled_func (info->stream, dis_style_text, 1568 1.11 christos /* xgettext:c-format */ 1569 1.1 christos _("<internal error in opcode table: %s %s>\n"), 1570 1.1 christos best->name, best->args); 1571 1.1 christos return 2; 1572 1.1 christos } 1573 1.1 christos } 1574 1.11 christos 1575 1.1 christos p = save_p; 1576 1.1 christos info->fprintf_styled_func = save_printer; 1577 1.1 christos info->print_address_func = save_print_address; 1578 1.1 christos 1579 1.11 christos d = args; 1580 1.1 christos 1581 1.1 christos info->fprintf_styled_func (info->stream, dis_style_mnemonic, "%s", best->name); 1582 1.11 christos 1583 1.1 christos if (*d) 1584 1.1 christos info->fprintf_styled_func (info->stream, dis_style_text, " "); 1585 1.1 christos 1586 1.1 christos while (*d) 1587 1.1 christos { 1588 1.1 christos p += print_insn_arg (d, buffer, p, memaddr + (p - buffer), info); 1589 1.1 christos d += 2; 1590 1.11 christos 1591 1.1 christos if (*d && *(d - 2) != 'I' && *d != 'k') 1592 1.1 christos info->fprintf_styled_func (info->stream, dis_style_text, ","); 1593 1.1 christos } 1594 1.1 christos 1595 1.1 christos return p - buffer; 1596 1.1 christos } 1597 1.1 christos 1598 1.1 christos /* Try to interpret the instruction at address MEMADDR as one that 1599 1.7 christos can execute on a processor with the features given by ARCH_MASK. 1600 1.7 christos If successful, print the instruction to INFO->STREAM and return 1601 1.1 christos its length in bytes. Return 0 otherwise. Return -1 on memory 1602 1.1 christos error. */ 1603 1.1 christos 1604 1.1 christos static int 1605 1.1 christos m68k_scan_mask (bfd_vma memaddr, disassemble_info *info, 1606 1.1 christos unsigned int arch_mask) 1607 1.1 christos { 1608 1.1 christos int i; 1609 1.1 christos const char *d; 1610 1.1 christos static const struct m68k_opcode **opcodes[16]; 1611 1.1 christos static int numopcodes[16]; 1612 1.1 christos int val; 1613 1.1 christos int major_opcode; 1614 1.1 christos 1615 1.1 christos struct private *priv = (struct private *) info->private_data; 1616 1.1 christos bfd_byte *buffer = priv->the_buffer; 1617 1.1 christos 1618 1.1 christos if (!opcodes[0]) 1619 1.1 christos { 1620 1.1 christos /* Speed up the matching by sorting the opcode 1621 1.1 christos table on the upper four bits of the opcode. */ 1622 1.1 christos const struct m68k_opcode **opc_pointer[16]; 1623 1.1 christos 1624 1.1 christos /* First count how many opcodes are in each of the sixteen buckets. */ 1625 1.1 christos for (i = 0; i < m68k_numopcodes; i++) 1626 1.1 christos numopcodes[(m68k_opcodes[i].opcode >> 28) & 15]++; 1627 1.1 christos 1628 1.1 christos /* Then create a sorted table of pointers 1629 1.1 christos that point into the unsorted table. */ 1630 1.1 christos opc_pointer[0] = xmalloc (sizeof (struct m68k_opcode *) 1631 1.1 christos * m68k_numopcodes); 1632 1.1 christos opcodes[0] = opc_pointer[0]; 1633 1.1 christos 1634 1.1 christos for (i = 1; i < 16; i++) 1635 1.1 christos { 1636 1.1 christos opc_pointer[i] = opc_pointer[i - 1] + numopcodes[i - 1]; 1637 1.1 christos opcodes[i] = opc_pointer[i]; 1638 1.1 christos } 1639 1.1 christos 1640 1.1 christos for (i = 0; i < m68k_numopcodes; i++) 1641 1.1 christos *opc_pointer[(m68k_opcodes[i].opcode >> 28) & 15]++ = &m68k_opcodes[i]; 1642 1.7 christos } 1643 1.7 christos 1644 1.1 christos if (!FETCH_DATA (info, buffer + 2)) 1645 1.1 christos return -1; 1646 1.1 christos major_opcode = (buffer[0] >> 4) & 15; 1647 1.1 christos 1648 1.1 christos for (i = 0; i < numopcodes[major_opcode]; i++) 1649 1.1 christos { 1650 1.1 christos const struct m68k_opcode *opc = opcodes[major_opcode][i]; 1651 1.1 christos unsigned long opcode = opc->opcode; 1652 1.1 christos unsigned long match = opc->match; 1653 1.1 christos const char *args = opc->args; 1654 1.1 christos 1655 1.1 christos if (*args == '.') 1656 1.1 christos args++; 1657 1.1 christos 1658 1.1 christos if (((0xff & buffer[0] & (match >> 24)) == (0xff & (opcode >> 24))) 1659 1.1 christos && ((0xff & buffer[1] & (match >> 16)) == (0xff & (opcode >> 16))) 1660 1.1 christos /* Only fetch the next two bytes if we need to. */ 1661 1.1 christos && (((0xffff & match) == 0) 1662 1.1 christos || 1663 1.1 christos (FETCH_DATA (info, buffer + 4) 1664 1.1 christos && ((0xff & buffer[2] & (match >> 8)) == (0xff & (opcode >> 8))) 1665 1.1 christos && ((0xff & buffer[3] & match) == (0xff & opcode))) 1666 1.1 christos ) 1667 1.1 christos && (opc->arch & arch_mask) != 0) 1668 1.1 christos { 1669 1.1 christos /* Don't use for printout the variants of divul and divsl 1670 1.1 christos that have the same register number in two places. 1671 1.1 christos The more general variants will match instead. */ 1672 1.1 christos for (d = args; *d; d += 2) 1673 1.1 christos if (d[1] == 'D') 1674 1.1 christos break; 1675 1.1 christos 1676 1.1 christos /* Don't use for printout the variants of most floating 1677 1.1 christos point coprocessor instructions which use the same 1678 1.1 christos register number in two places, as above. */ 1679 1.1 christos if (*d == '\0') 1680 1.1 christos for (d = args; *d; d += 2) 1681 1.1 christos if (d[1] == 't') 1682 1.1 christos break; 1683 1.1 christos 1684 1.1 christos /* Don't match fmovel with more than one register; 1685 1.1 christos wait for fmoveml. */ 1686 1.1 christos if (*d == '\0') 1687 1.1 christos { 1688 1.1 christos for (d = args; *d; d += 2) 1689 1.1 christos { 1690 1.1 christos if (d[0] == 's' && d[1] == '8') 1691 1.1 christos { 1692 1.1 christos val = fetch_arg (buffer, d[1], 3, info); 1693 1.1 christos if (val < 0) 1694 1.1 christos return 0; 1695 1.1 christos if ((val & (val - 1)) != 0) 1696 1.1 christos break; 1697 1.1 christos } 1698 1.1 christos } 1699 1.1 christos } 1700 1.1 christos 1701 1.1 christos /* Don't match FPU insns with non-default coprocessor ID. */ 1702 1.1 christos if (*d == '\0') 1703 1.1 christos { 1704 1.1 christos for (d = args; *d; d += 2) 1705 1.1 christos { 1706 1.1 christos if (d[0] == 'I') 1707 1.1 christos { 1708 1.1 christos val = fetch_arg (buffer, 'd', 3, info); 1709 1.1 christos if (val != 1) 1710 1.1 christos break; 1711 1.1 christos } 1712 1.1 christos } 1713 1.1 christos } 1714 1.1 christos 1715 1.1 christos if (*d == '\0') 1716 1.1 christos if ((val = match_insn_m68k (memaddr, info, opc))) 1717 1.1 christos return val; 1718 1.1 christos } 1719 1.6 christos } 1720 1.1 christos return 0; 1721 1.1 christos } 1722 1.1 christos 1723 1.1 christos /* Print the m68k instruction at address MEMADDR in debugged memory, 1724 1.1 christos on INFO->STREAM. Returns length of the instruction, in bytes. */ 1725 1.1 christos 1726 1.1 christos int 1727 1.1 christos print_insn_m68k (bfd_vma memaddr, disassemble_info *info) 1728 1.1 christos { 1729 1.1 christos unsigned int arch_mask; 1730 1.1 christos struct private priv; 1731 1.1 christos int val; 1732 1.1 christos 1733 1.1 christos bfd_byte *buffer = priv.the_buffer; 1734 1.1 christos 1735 1.1 christos info->private_data = & priv; 1736 1.1 christos /* Tell objdump to use two bytes per chunk 1737 1.1 christos and six bytes per line for displaying raw data. */ 1738 1.1 christos info->bytes_per_chunk = 2; 1739 1.1 christos info->bytes_per_line = 6; 1740 1.1 christos info->display_endian = BFD_ENDIAN_BIG; 1741 1.1 christos priv.max_fetched = priv.the_buffer; 1742 1.1 christos priv.insn_start = memaddr; 1743 1.1 christos 1744 1.1 christos arch_mask = bfd_m68k_mach_to_features (info->mach); 1745 1.1 christos if (!arch_mask) 1746 1.1 christos { 1747 1.1 christos /* First try printing an m680x0 instruction. Try printing a Coldfire 1748 1.7 christos one if that fails. */ 1749 1.1 christos val = m68k_scan_mask (memaddr, info, m68k_mask); 1750 1.1 christos if (val <= 0) 1751 1.1 christos val = m68k_scan_mask (memaddr, info, mcf_mask); 1752 1.1 christos } 1753 1.1 christos else 1754 1.1 christos { 1755 1.1 christos val = m68k_scan_mask (memaddr, info, arch_mask); 1756 1.1 christos } 1757 1.11 christos 1758 1.11 christos if (val == 0) 1759 1.11 christos { 1760 1.11 christos /* Handle undefined instructions. */ 1761 1.11 christos info->fprintf_styled_func (info->stream, dis_style_assembler_directive, 1762 1.11 christos ".short"); 1763 1.11 christos info->fprintf_styled_func (info->stream, dis_style_text, " "); 1764 1.11 christos info->fprintf_styled_func (info->stream, dis_style_immediate, 1765 1.1 christos "0x%04x", (buffer[0] << 8) + buffer[1]); 1766 1.1 christos } 1767 1.1 christos 1768 return val ? val : 2; 1769 } 1770