1/* Instruction printing code for the ARM 2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 3 Free Software Foundation, Inc. 4 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org) 5 Modification by James G. Smith (jsmith@cygnus.co.uk) 6 7This file is part of libopcodes. 8 9This program is free software; you can redistribute it and/or modify it under 10the terms of the GNU General Public License as published by the Free 11Software Foundation; either version 2 of the License, or (at your option) 12any later version. 13 14This program is distributed in the hope that it will be useful, but WITHOUT 15ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 16FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 17more details. 18 19You should have received a copy of the GNU General Public License 20along with this program; if not, write to the Free Software 21Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 22 23#include "sysdep.h" 24#include "dis-asm.h" 25#define DEFINE_TABLE 26#include "arm-opc.h" 27#include "coff/internal.h" 28#include "libcoff.h" 29#include "opintl.h" 30 31/* FIXME: This shouldn't be done here */ 32#include "elf-bfd.h" 33#include "elf/internal.h" 34#include "elf/arm.h" 35 36#ifndef streq 37#define streq(a,b) (strcmp ((a), (b)) == 0) 38#endif 39 40#ifndef strneq 41#define strneq(a,b,n) (strncmp ((a), (b), (n)) == 0) 42#endif 43 44#ifndef NUM_ELEM 45#define NUM_ELEM(a) (sizeof (a) / sizeof (a)[0]) 46#endif 47 48static char * arm_conditional[] = 49{"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc", 50 "hi", "ls", "ge", "lt", "gt", "le", "", "nv"}; 51 52typedef struct 53{ 54 const char * name; 55 const char * description; 56 const char * reg_names[16]; 57} 58arm_regname; 59 60static arm_regname regnames[] = 61{ 62 { "raw" , "Select raw register names", 63 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"}}, 64 { "gcc", "Select register names used by GCC", 65 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc" }}, 66 { "std", "Select register names used in ARM's ISA documentation", 67 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc" }}, 68 { "apcs", "Select register names used in the APCS", 69 { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "sl", "fp", "ip", "sp", "lr", "pc" }}, 70 { "atpcs", "Select register names used in the ATPCS", 71 { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "IP", "SP", "LR", "PC" }}, 72 { "special-atpcs", "Select special register names used in the ATPCS", 73 { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "WR", "v5", "SB", "SL", "FP", "IP", "SP", "LR", "PC" }} 74}; 75 76/* Default to GCC register name set. */ 77static unsigned int regname_selected = 1; 78 79#define NUM_ARM_REGNAMES NUM_ELEM (regnames) 80#define arm_regnames regnames[regname_selected].reg_names 81 82static boolean force_thumb = false; 83 84static char * arm_fp_const[] = 85{"0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0"}; 86 87static char * arm_shift[] = 88{"lsl", "lsr", "asr", "ror"}; 89 90/* Forward declarations. */ 91static void arm_decode_shift PARAMS ((long, fprintf_ftype, void *)); 92static int print_insn_arm PARAMS ((bfd_vma, struct disassemble_info *, long)); 93static int print_insn_thumb PARAMS ((bfd_vma, struct disassemble_info *, long)); 94static void parse_disassembler_options PARAMS ((char *)); 95static int print_insn PARAMS ((bfd_vma, struct disassemble_info *, boolean)); 96int get_arm_regname_num_options (void); 97int set_arm_regname_option (int option); 98int get_arm_regnames (int option, const char **setname, 99 const char **setdescription, 100 const char ***register_names); 101 102/* Functions. */ 103int 104get_arm_regname_num_options (void) 105{ 106 return NUM_ARM_REGNAMES; 107} 108 109int 110set_arm_regname_option (int option) 111{ 112 int old = regname_selected; 113 regname_selected = option; 114 return old; 115} 116 117int 118get_arm_regnames (int option, const char **setname, 119 const char **setdescription, 120 const char ***register_names) 121{ 122 *setname = regnames[option].name; 123 *setdescription = regnames[option].description; 124 *register_names = regnames[option].reg_names; 125 return 16; 126} 127 128static void 129arm_decode_shift (given, func, stream) 130 long given; 131 fprintf_ftype func; 132 void * stream; 133{ 134 func (stream, "%s", arm_regnames[given & 0xf]); 135 136 if ((given & 0xff0) != 0) 137 { 138 if ((given & 0x10) == 0) 139 { 140 int amount = (given & 0xf80) >> 7; 141 int shift = (given & 0x60) >> 5; 142 143 if (amount == 0) 144 { 145 if (shift == 3) 146 { 147 func (stream, ", rrx"); 148 return; 149 } 150 151 amount = 32; 152 } 153 154 func (stream, ", %s #%d", arm_shift[shift], amount); 155 } 156 else 157 func (stream, ", %s %s", arm_shift[(given & 0x60) >> 5], 158 arm_regnames[(given & 0xf00) >> 8]); 159 } 160} 161 162/* Print one instruction from PC on INFO->STREAM. 163 Return the size of the instruction (always 4 on ARM). */ 164static int 165print_insn_arm (pc, info, given) 166 bfd_vma pc; 167 struct disassemble_info * info; 168 long given; 169{ 170 struct arm_opcode * insn; 171 void * stream = info->stream; 172 fprintf_ftype func = info->fprintf_func; 173 174 for (insn = arm_opcodes; insn->assembler; insn++) 175 { 176 if ((given & insn->mask) == insn->value) 177 { 178 char * c; 179 180 for (c = insn->assembler; *c; c++) 181 { 182 if (*c == '%') 183 { 184 switch (*++c) 185 { 186 case '%': 187 func (stream, "%%"); 188 break; 189 190 case 'a': 191 if (((given & 0x000f0000) == 0x000f0000) 192 && ((given & 0x02000000) == 0)) 193 { 194 int offset = given & 0xfff; 195 196 func (stream, "[pc"); 197 198 if (given & 0x01000000) 199 { 200 if ((given & 0x00800000) == 0) 201 offset = - offset; 202 203 /* pre-indexed */
| 1/* Instruction printing code for the ARM 2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 3 Free Software Foundation, Inc. 4 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org) 5 Modification by James G. Smith (jsmith@cygnus.co.uk) 6 7This file is part of libopcodes. 8 9This program is free software; you can redistribute it and/or modify it under 10the terms of the GNU General Public License as published by the Free 11Software Foundation; either version 2 of the License, or (at your option) 12any later version. 13 14This program is distributed in the hope that it will be useful, but WITHOUT 15ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 16FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 17more details. 18 19You should have received a copy of the GNU General Public License 20along with this program; if not, write to the Free Software 21Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 22 23#include "sysdep.h" 24#include "dis-asm.h" 25#define DEFINE_TABLE 26#include "arm-opc.h" 27#include "coff/internal.h" 28#include "libcoff.h" 29#include "opintl.h" 30 31/* FIXME: This shouldn't be done here */ 32#include "elf-bfd.h" 33#include "elf/internal.h" 34#include "elf/arm.h" 35 36#ifndef streq 37#define streq(a,b) (strcmp ((a), (b)) == 0) 38#endif 39 40#ifndef strneq 41#define strneq(a,b,n) (strncmp ((a), (b), (n)) == 0) 42#endif 43 44#ifndef NUM_ELEM 45#define NUM_ELEM(a) (sizeof (a) / sizeof (a)[0]) 46#endif 47 48static char * arm_conditional[] = 49{"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc", 50 "hi", "ls", "ge", "lt", "gt", "le", "", "nv"}; 51 52typedef struct 53{ 54 const char * name; 55 const char * description; 56 const char * reg_names[16]; 57} 58arm_regname; 59 60static arm_regname regnames[] = 61{ 62 { "raw" , "Select raw register names", 63 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"}}, 64 { "gcc", "Select register names used by GCC", 65 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc" }}, 66 { "std", "Select register names used in ARM's ISA documentation", 67 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc" }}, 68 { "apcs", "Select register names used in the APCS", 69 { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "sl", "fp", "ip", "sp", "lr", "pc" }}, 70 { "atpcs", "Select register names used in the ATPCS", 71 { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "IP", "SP", "LR", "PC" }}, 72 { "special-atpcs", "Select special register names used in the ATPCS", 73 { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "WR", "v5", "SB", "SL", "FP", "IP", "SP", "LR", "PC" }} 74}; 75 76/* Default to GCC register name set. */ 77static unsigned int regname_selected = 1; 78 79#define NUM_ARM_REGNAMES NUM_ELEM (regnames) 80#define arm_regnames regnames[regname_selected].reg_names 81 82static boolean force_thumb = false; 83 84static char * arm_fp_const[] = 85{"0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0"}; 86 87static char * arm_shift[] = 88{"lsl", "lsr", "asr", "ror"}; 89 90/* Forward declarations. */ 91static void arm_decode_shift PARAMS ((long, fprintf_ftype, void *)); 92static int print_insn_arm PARAMS ((bfd_vma, struct disassemble_info *, long)); 93static int print_insn_thumb PARAMS ((bfd_vma, struct disassemble_info *, long)); 94static void parse_disassembler_options PARAMS ((char *)); 95static int print_insn PARAMS ((bfd_vma, struct disassemble_info *, boolean)); 96int get_arm_regname_num_options (void); 97int set_arm_regname_option (int option); 98int get_arm_regnames (int option, const char **setname, 99 const char **setdescription, 100 const char ***register_names); 101 102/* Functions. */ 103int 104get_arm_regname_num_options (void) 105{ 106 return NUM_ARM_REGNAMES; 107} 108 109int 110set_arm_regname_option (int option) 111{ 112 int old = regname_selected; 113 regname_selected = option; 114 return old; 115} 116 117int 118get_arm_regnames (int option, const char **setname, 119 const char **setdescription, 120 const char ***register_names) 121{ 122 *setname = regnames[option].name; 123 *setdescription = regnames[option].description; 124 *register_names = regnames[option].reg_names; 125 return 16; 126} 127 128static void 129arm_decode_shift (given, func, stream) 130 long given; 131 fprintf_ftype func; 132 void * stream; 133{ 134 func (stream, "%s", arm_regnames[given & 0xf]); 135 136 if ((given & 0xff0) != 0) 137 { 138 if ((given & 0x10) == 0) 139 { 140 int amount = (given & 0xf80) >> 7; 141 int shift = (given & 0x60) >> 5; 142 143 if (amount == 0) 144 { 145 if (shift == 3) 146 { 147 func (stream, ", rrx"); 148 return; 149 } 150 151 amount = 32; 152 } 153 154 func (stream, ", %s #%d", arm_shift[shift], amount); 155 } 156 else 157 func (stream, ", %s %s", arm_shift[(given & 0x60) >> 5], 158 arm_regnames[(given & 0xf00) >> 8]); 159 } 160} 161 162/* Print one instruction from PC on INFO->STREAM. 163 Return the size of the instruction (always 4 on ARM). */ 164static int 165print_insn_arm (pc, info, given) 166 bfd_vma pc; 167 struct disassemble_info * info; 168 long given; 169{ 170 struct arm_opcode * insn; 171 void * stream = info->stream; 172 fprintf_ftype func = info->fprintf_func; 173 174 for (insn = arm_opcodes; insn->assembler; insn++) 175 { 176 if ((given & insn->mask) == insn->value) 177 { 178 char * c; 179 180 for (c = insn->assembler; *c; c++) 181 { 182 if (*c == '%') 183 { 184 switch (*++c) 185 { 186 case '%': 187 func (stream, "%%"); 188 break; 189 190 case 'a': 191 if (((given & 0x000f0000) == 0x000f0000) 192 && ((given & 0x02000000) == 0)) 193 { 194 int offset = given & 0xfff; 195 196 func (stream, "[pc"); 197 198 if (given & 0x01000000) 199 { 200 if ((given & 0x00800000) == 0) 201 offset = - offset; 202 203 /* pre-indexed */
|
204 func (stream, ", #%x]", offset);
| 204 func (stream, ", #%d]", offset);
|
205 206 offset += pc + 8; 207 208 /* Cope with the possibility of write-back 209 being used. Probably a very dangerous thing 210 for the programmer to do, but who are we to 211 argue ? */ 212 if (given & 0x00200000) 213 func (stream, "!"); 214 } 215 else 216 { 217 /* Post indexed. */
| 205 206 offset += pc + 8; 207 208 /* Cope with the possibility of write-back 209 being used. Probably a very dangerous thing 210 for the programmer to do, but who are we to 211 argue ? */ 212 if (given & 0x00200000) 213 func (stream, "!"); 214 } 215 else 216 { 217 /* Post indexed. */
|
218 func (stream, "], #%x", offset);
| 218 func (stream, "], #%d", offset);
|
219 220 offset = pc + 8; /* ie ignore the offset. */ 221 } 222 223 func (stream, "\t; "); 224 info->print_address_func (offset, info); 225 } 226 else 227 { 228 func (stream, "[%s", 229 arm_regnames[(given >> 16) & 0xf]); 230 if ((given & 0x01000000) != 0) 231 { 232 if ((given & 0x02000000) == 0) 233 { 234 int offset = given & 0xfff; 235 if (offset) 236 func (stream, ", %s#%d", 237 (((given & 0x00800000) == 0) 238 ? "-" : ""), offset); 239 } 240 else 241 { 242 func (stream, ", %s", 243 (((given & 0x00800000) == 0) 244 ? "-" : "")); 245 arm_decode_shift (given, func, stream); 246 } 247 248 func (stream, "]%s", 249 ((given & 0x00200000) != 0) ? "!" : ""); 250 } 251 else 252 { 253 if ((given & 0x02000000) == 0) 254 { 255 int offset = given & 0xfff; 256 if (offset) 257 func (stream, "], %s#%d", 258 (((given & 0x00800000) == 0) 259 ? "-" : ""), offset); 260 else 261 func (stream, "]"); 262 } 263 else 264 { 265 func (stream, "], %s", 266 (((given & 0x00800000) == 0) 267 ? "-" : "")); 268 arm_decode_shift (given, func, stream); 269 } 270 } 271 } 272 break; 273 274 case 's': 275 if ((given & 0x004f0000) == 0x004f0000) 276 { 277 /* PC relative with immediate offset. */ 278 int offset = ((given & 0xf00) >> 4) | (given & 0xf); 279 280 if ((given & 0x00800000) == 0) 281 offset = -offset; 282
| 219 220 offset = pc + 8; /* ie ignore the offset. */ 221 } 222 223 func (stream, "\t; "); 224 info->print_address_func (offset, info); 225 } 226 else 227 { 228 func (stream, "[%s", 229 arm_regnames[(given >> 16) & 0xf]); 230 if ((given & 0x01000000) != 0) 231 { 232 if ((given & 0x02000000) == 0) 233 { 234 int offset = given & 0xfff; 235 if (offset) 236 func (stream, ", %s#%d", 237 (((given & 0x00800000) == 0) 238 ? "-" : ""), offset); 239 } 240 else 241 { 242 func (stream, ", %s", 243 (((given & 0x00800000) == 0) 244 ? "-" : "")); 245 arm_decode_shift (given, func, stream); 246 } 247 248 func (stream, "]%s", 249 ((given & 0x00200000) != 0) ? "!" : ""); 250 } 251 else 252 { 253 if ((given & 0x02000000) == 0) 254 { 255 int offset = given & 0xfff; 256 if (offset) 257 func (stream, "], %s#%d", 258 (((given & 0x00800000) == 0) 259 ? "-" : ""), offset); 260 else 261 func (stream, "]"); 262 } 263 else 264 { 265 func (stream, "], %s", 266 (((given & 0x00800000) == 0) 267 ? "-" : "")); 268 arm_decode_shift (given, func, stream); 269 } 270 } 271 } 272 break; 273 274 case 's': 275 if ((given & 0x004f0000) == 0x004f0000) 276 { 277 /* PC relative with immediate offset. */ 278 int offset = ((given & 0xf00) >> 4) | (given & 0xf); 279 280 if ((given & 0x00800000) == 0) 281 offset = -offset; 282
|
283 func (stream, "[pc, #%x]\t; ", offset);
| 283 func (stream, "[pc, #%d]\t; ", offset);
|
284 285 (*info->print_address_func) 286 (offset + pc + 8, info); 287 } 288 else 289 { 290 func (stream, "[%s", 291 arm_regnames[(given >> 16) & 0xf]); 292 if ((given & 0x01000000) != 0) 293 { 294 /* Pre-indexed. */ 295 if ((given & 0x00400000) == 0x00400000) 296 { 297 /* Immediate. */ 298 int offset = ((given & 0xf00) >> 4) | (given & 0xf); 299 if (offset) 300 func (stream, ", %s#%d", 301 (((given & 0x00800000) == 0) 302 ? "-" : ""), offset); 303 } 304 else 305 { 306 /* Register. */ 307 func (stream, ", %s%s", 308 (((given & 0x00800000) == 0) 309 ? "-" : ""), 310 arm_regnames[given & 0xf]); 311 } 312 313 func (stream, "]%s", 314 ((given & 0x00200000) != 0) ? "!" : ""); 315 } 316 else 317 { 318 /* Post-indexed. */ 319 if ((given & 0x00400000) == 0x00400000) 320 { 321 /* Immediate. */ 322 int offset = ((given & 0xf00) >> 4) | (given & 0xf); 323 if (offset) 324 func (stream, "], %s#%d", 325 (((given & 0x00800000) == 0) 326 ? "-" : ""), offset); 327 else 328 func (stream, "]"); 329 } 330 else 331 { 332 /* Register. */ 333 func (stream, "], %s%s", 334 (((given & 0x00800000) == 0) 335 ? "-" : ""), 336 arm_regnames[given & 0xf]); 337 } 338 } 339 } 340 break; 341 342 case 'b': 343 (*info->print_address_func) 344 (BDISP (given) * 4 + pc + 8, info); 345 break; 346 347 case 'c': 348 func (stream, "%s", 349 arm_conditional [(given >> 28) & 0xf]); 350 break; 351 352 case 'm': 353 { 354 int started = 0; 355 int reg; 356 357 func (stream, "{"); 358 for (reg = 0; reg < 16; reg++) 359 if ((given & (1 << reg)) != 0) 360 { 361 if (started) 362 func (stream, ", "); 363 started = 1; 364 func (stream, "%s", arm_regnames[reg]); 365 } 366 func (stream, "}"); 367 } 368 break; 369 370 case 'o': 371 if ((given & 0x02000000) != 0) 372 { 373 int rotate = (given & 0xf00) >> 7; 374 int immed = (given & 0xff); 375 immed = (((immed << (32 - rotate)) 376 | (immed >> rotate)) & 0xffffffff); 377 func (stream, "#%d\t; 0x%x", immed, immed); 378 } 379 else 380 arm_decode_shift (given, func, stream); 381 break; 382 383 case 'p': 384 if ((given & 0x0000f000) == 0x0000f000) 385 func (stream, "p"); 386 break; 387 388 case 't': 389 if ((given & 0x01200000) == 0x00200000) 390 func (stream, "t"); 391 break; 392 393 case 'h': 394 if ((given & 0x00000020) == 0x00000020) 395 func (stream, "h"); 396 else 397 func (stream, "b"); 398 break; 399 400 case 'A': 401 func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]); 402 if ((given & 0x01000000) != 0) 403 { 404 int offset = given & 0xff; 405 if (offset) 406 func (stream, ", %s#%d]%s", 407 ((given & 0x00800000) == 0 ? "-" : ""), 408 offset * 4, 409 ((given & 0x00200000) != 0 ? "!" : "")); 410 else 411 func (stream, "]"); 412 } 413 else 414 { 415 int offset = given & 0xff; 416 if (offset) 417 func (stream, "], %s#%d", 418 ((given & 0x00800000) == 0 ? "-" : ""), 419 offset * 4); 420 else 421 func (stream, "]"); 422 } 423 break; 424 425 case 'B': 426 /* Print ARM V5 BLX(1) address: pc+25 bits. */ 427 { 428 bfd_vma address; 429 bfd_vma offset = 0; 430 431 if (given & 0x00800000) 432 /* Is signed, hi bits should be ones. */ 433 offset = (-1) ^ 0x00ffffff; 434 435 /* Offset is (SignExtend(offset field)<<2). */ 436 offset += given & 0x00ffffff; 437 offset <<= 2; 438 address = offset + pc + 8; 439 440 if (given & 0x01000000) 441 /* H bit allows addressing to 2-byte boundaries. */ 442 address += 2; 443 444 info->print_address_func (address, info); 445 } 446 break; 447 448 case 'C': 449 func (stream, "_"); 450 if (given & 0x80000) 451 func (stream, "f"); 452 if (given & 0x40000) 453 func (stream, "s"); 454 if (given & 0x20000) 455 func (stream, "x"); 456 if (given & 0x10000) 457 func (stream, "c"); 458 break; 459 460 case 'F': 461 switch (given & 0x00408000) 462 { 463 case 0: 464 func (stream, "4"); 465 break; 466 case 0x8000: 467 func (stream, "1"); 468 break; 469 case 0x00400000: 470 func (stream, "2"); 471 break; 472 default: 473 func (stream, "3"); 474 } 475 break; 476 477 case 'P': 478 switch (given & 0x00080080) 479 { 480 case 0: 481 func (stream, "s"); 482 break; 483 case 0x80: 484 func (stream, "d"); 485 break; 486 case 0x00080000: 487 func (stream, "e"); 488 break; 489 default: 490 func (stream, _("<illegal precision>")); 491 break; 492 } 493 break; 494 case 'Q': 495 switch (given & 0x00408000) 496 { 497 case 0: 498 func (stream, "s"); 499 break; 500 case 0x8000: 501 func (stream, "d"); 502 break; 503 case 0x00400000: 504 func (stream, "e"); 505 break; 506 default: 507 func (stream, "p"); 508 break; 509 } 510 break; 511 case 'R': 512 switch (given & 0x60) 513 { 514 case 0: 515 break; 516 case 0x20: 517 func (stream, "p"); 518 break; 519 case 0x40: 520 func (stream, "m"); 521 break; 522 default: 523 func (stream, "z"); 524 break; 525 } 526 break; 527 528 case '0': case '1': case '2': case '3': case '4': 529 case '5': case '6': case '7': case '8': case '9': 530 { 531 int bitstart = *c++ - '0'; 532 int bitend = 0; 533 while (*c >= '0' && *c <= '9') 534 bitstart = (bitstart * 10) + *c++ - '0'; 535 536 switch (*c) 537 { 538 case '-': 539 c++; 540 541 while (*c >= '0' && *c <= '9') 542 bitend = (bitend * 10) + *c++ - '0'; 543 544 if (!bitend) 545 abort (); 546 547 switch (*c) 548 { 549 case 'r': 550 { 551 long reg; 552 553 reg = given >> bitstart; 554 reg &= (2 << (bitend - bitstart)) - 1; 555 556 func (stream, "%s", arm_regnames[reg]); 557 } 558 break; 559 case 'd': 560 { 561 long reg; 562 563 reg = given >> bitstart; 564 reg &= (2 << (bitend - bitstart)) - 1; 565 566 func (stream, "%d", reg); 567 } 568 break; 569 case 'x': 570 { 571 long reg; 572 573 reg = given >> bitstart; 574 reg &= (2 << (bitend - bitstart)) - 1; 575 576 func (stream, "0x%08x", reg); 577 578 /* Some SWI instructions have special 579 meanings. */ 580 if ((given & 0x0fffffff) == 0x0FF00000) 581 func (stream, "\t; IMB"); 582 else if ((given & 0x0fffffff) == 0x0FF00001) 583 func (stream, "\t; IMBRange"); 584 } 585 break; 586 case 'X': 587 { 588 long reg; 589 590 reg = given >> bitstart; 591 reg &= (2 << (bitend - bitstart)) - 1; 592 593 func (stream, "%01x", reg & 0xf); 594 } 595 break; 596 case 'f': 597 { 598 long reg; 599 600 reg = given >> bitstart; 601 reg &= (2 << (bitend - bitstart)) - 1; 602 603 if (reg > 7) 604 func (stream, "#%s", 605 arm_fp_const[reg & 7]); 606 else 607 func (stream, "f%d", reg); 608 } 609 break; 610 default: 611 abort (); 612 } 613 break; 614 615 case '`': 616 c++; 617 if ((given & (1 << bitstart)) == 0) 618 func (stream, "%c", *c); 619 break; 620 case '\'': 621 c++; 622 if ((given & (1 << bitstart)) != 0) 623 func (stream, "%c", *c); 624 break; 625 case '?': 626 ++c; 627 if ((given & (1 << bitstart)) != 0) 628 func (stream, "%c", *c++); 629 else 630 func (stream, "%c", *++c); 631 break; 632 default: 633 abort (); 634 } 635 break; 636 637 default: 638 abort (); 639 } 640 } 641 } 642 else 643 func (stream, "%c", *c); 644 } 645 return 4; 646 } 647 } 648 abort (); 649} 650 651/* Print one instruction from PC on INFO->STREAM. 652 Return the size of the instruction. */ 653static int 654print_insn_thumb (pc, info, given) 655 bfd_vma pc; 656 struct disassemble_info * info; 657 long given; 658{ 659 struct thumb_opcode * insn; 660 void * stream = info->stream; 661 fprintf_ftype func = info->fprintf_func; 662 663 for (insn = thumb_opcodes; insn->assembler; insn++) 664 { 665 if ((given & insn->mask) == insn->value) 666 { 667 char * c = insn->assembler; 668 669 /* Special processing for Thumb 2 instruction BL sequence: */ 670 if (!*c) /* Check for empty (not NULL) assembler string. */ 671 { 672 info->bytes_per_chunk = 4; 673 info->bytes_per_line = 4; 674 675 if ((given & 0x10000000) == 0) 676 func (stream, "blx\t"); 677 else 678 func (stream, "bl\t"); 679 680 info->print_address_func (BDISP23 (given) * 2 + pc + 4, info); 681 return 4; 682 } 683 else 684 { 685 info->bytes_per_chunk = 2; 686 info->bytes_per_line = 4; 687 688 given &= 0xffff; 689 690 for (; *c; c++) 691 { 692 if (*c == '%') 693 { 694 int domaskpc = 0; 695 int domasklr = 0; 696 697 switch (*++c) 698 { 699 case '%': 700 func (stream, "%%"); 701 break; 702 703 case 'S': 704 { 705 long reg; 706 707 reg = (given >> 3) & 0x7; 708 if (given & (1 << 6)) 709 reg += 8; 710 711 func (stream, "%s", arm_regnames[reg]); 712 } 713 break; 714 715 case 'D': 716 { 717 long reg; 718 719 reg = given & 0x7; 720 if (given & (1 << 7)) 721 reg += 8; 722 723 func (stream, "%s", arm_regnames[reg]); 724 } 725 break; 726 727 case 'T': 728 func (stream, "%s", 729 arm_conditional [(given >> 8) & 0xf]); 730 break; 731 732 case 'N': 733 if (given & (1 << 8)) 734 domasklr = 1; 735 /* Fall through. */ 736 case 'O': 737 if (*c == 'O' && (given & (1 << 8))) 738 domaskpc = 1; 739 /* Fall through. */ 740 case 'M': 741 { 742 int started = 0; 743 int reg; 744 745 func (stream, "{"); 746 747 /* It would be nice if we could spot 748 ranges, and generate the rS-rE format: */ 749 for (reg = 0; (reg < 8); reg++) 750 if ((given & (1 << reg)) != 0) 751 { 752 if (started) 753 func (stream, ", "); 754 started = 1; 755 func (stream, "%s", arm_regnames[reg]); 756 } 757 758 if (domasklr) 759 { 760 if (started) 761 func (stream, ", "); 762 started = 1; 763 func (stream, arm_regnames[14] /* "lr" */); 764 } 765 766 if (domaskpc) 767 { 768 if (started) 769 func (stream, ", "); 770 func (stream, arm_regnames[15] /* "pc" */); 771 } 772 773 func (stream, "}"); 774 } 775 break; 776 777 778 case '0': case '1': case '2': case '3': case '4': 779 case '5': case '6': case '7': case '8': case '9': 780 { 781 int bitstart = *c++ - '0'; 782 int bitend = 0; 783 784 while (*c >= '0' && *c <= '9') 785 bitstart = (bitstart * 10) + *c++ - '0'; 786 787 switch (*c) 788 { 789 case '-': 790 { 791 long reg; 792 793 c++; 794 while (*c >= '0' && *c <= '9') 795 bitend = (bitend * 10) + *c++ - '0'; 796 if (!bitend) 797 abort (); 798 reg = given >> bitstart; 799 reg &= (2 << (bitend - bitstart)) - 1; 800 switch (*c) 801 { 802 case 'r': 803 func (stream, "%s", arm_regnames[reg]); 804 break; 805 806 case 'd': 807 func (stream, "%d", reg); 808 break; 809 810 case 'H': 811 func (stream, "%d", reg << 1); 812 break; 813 814 case 'W': 815 func (stream, "%d", reg << 2); 816 break; 817 818 case 'a': 819 /* PC-relative address -- the bottom two 820 bits of the address are dropped 821 before the calculation. */ 822 info->print_address_func 823 (((pc + 4) & ~3) + (reg << 2), info); 824 break; 825 826 case 'x': 827 func (stream, "0x%04x", reg); 828 break; 829 830 case 'I': 831 reg = ((reg ^ (1 << bitend)) - (1 << bitend)); 832 func (stream, "%d", reg); 833 break; 834 835 case 'B': 836 reg = ((reg ^ (1 << bitend)) - (1 << bitend)); 837 (*info->print_address_func) 838 (reg * 2 + pc + 4, info); 839 break; 840 841 default: 842 abort (); 843 } 844 } 845 break; 846 847 case '\'': 848 c++; 849 if ((given & (1 << bitstart)) != 0) 850 func (stream, "%c", *c); 851 break; 852 853 case '?': 854 ++c; 855 if ((given & (1 << bitstart)) != 0) 856 func (stream, "%c", *c++); 857 else 858 func (stream, "%c", *++c); 859 break; 860 861 default: 862 abort (); 863 } 864 } 865 break; 866 867 default: 868 abort (); 869 } 870 } 871 else 872 func (stream, "%c", *c); 873 } 874 } 875 return 2; 876 } 877 } 878 879 /* No match. */ 880 abort (); 881} 882 883/* Parse an individual disassembler option. */ 884void 885parse_arm_disassembler_option (option) 886 char * option; 887{ 888 if (option == NULL) 889 return; 890 891 if (strneq (option, "reg-names-", 10)) 892 { 893 int i; 894 895 option += 10; 896 897 for (i = NUM_ARM_REGNAMES; i--;) 898 if (streq (option, regnames[i].name)) 899 { 900 regname_selected = i; 901 break; 902 } 903 904 if (i < 0) 905 fprintf (stderr, _("Unrecognised register name set: %s\n"), option); 906 } 907 else if (streq (option, "force-thumb")) 908 force_thumb = 1; 909 else if (streq (option, "no-force-thumb")) 910 force_thumb = 0; 911 else 912 fprintf (stderr, _("Unrecognised disassembler option: %s\n"), option); 913 914 return; 915} 916 917/* Parse the string of disassembler options, spliting it at whitespaces. */ 918static void 919parse_disassembler_options (options) 920 char * options; 921{ 922 char * space; 923 924 if (options == NULL) 925 return; 926 927 do 928 { 929 space = strchr (options, ' '); 930 931 if (space) 932 { 933 * space = '\0'; 934 parse_arm_disassembler_option (options); 935 * space = ' '; 936 options = space + 1; 937 } 938 else 939 parse_arm_disassembler_option (options); 940 } 941 while (space); 942} 943 944/* NOTE: There are no checks in these routines that 945 the relevant number of data bytes exist. */ 946static int 947print_insn (pc, info, little) 948 bfd_vma pc; 949 struct disassemble_info * info; 950 boolean little; 951{ 952 unsigned char b[4]; 953 long given; 954 int status; 955 int is_thumb; 956 957 if (info->disassembler_options) 958 { 959 parse_disassembler_options (info->disassembler_options); 960 961 /* To avoid repeated parsing of these options, we remove them here. */ 962 info->disassembler_options = NULL; 963 } 964 965 is_thumb = force_thumb; 966 967 if (!is_thumb && info->symbols != NULL) 968 { 969 if (bfd_asymbol_flavour (*info->symbols) == bfd_target_coff_flavour) 970 { 971 coff_symbol_type * cs; 972 973 cs = coffsymbol (*info->symbols); 974 is_thumb = ( cs->native->u.syment.n_sclass == C_THUMBEXT 975 || cs->native->u.syment.n_sclass == C_THUMBSTAT 976 || cs->native->u.syment.n_sclass == C_THUMBLABEL 977 || cs->native->u.syment.n_sclass == C_THUMBEXTFUNC 978 || cs->native->u.syment.n_sclass == C_THUMBSTATFUNC); 979 } 980 else if (bfd_asymbol_flavour (*info->symbols) == bfd_target_elf_flavour) 981 { 982 elf_symbol_type * es; 983 unsigned int type; 984 985 es = *(elf_symbol_type **)(info->symbols); 986 type = ELF_ST_TYPE (es->internal_elf_sym.st_info); 987 988 is_thumb = (type == STT_ARM_TFUNC) || (type == STT_ARM_16BIT); 989 } 990 } 991 992 info->bytes_per_chunk = 4; 993 info->display_endian = little ? BFD_ENDIAN_LITTLE : BFD_ENDIAN_BIG; 994 995 if (little) 996 { 997 status = info->read_memory_func (pc, (bfd_byte *) &b[0], 4, info); 998 if (status != 0 && is_thumb) 999 { 1000 info->bytes_per_chunk = 2; 1001 1002 status = info->read_memory_func (pc, (bfd_byte *) b, 2, info); 1003 b[3] = b[2] = 0; 1004 } 1005 1006 if (status != 0) 1007 { 1008 info->memory_error_func (status, pc, info); 1009 return -1; 1010 } 1011 1012 given = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24); 1013 } 1014 else 1015 { 1016 status = info->read_memory_func 1017 (pc & ~ 0x3, (bfd_byte *) &b[0], 4, info); 1018 if (status != 0) 1019 { 1020 info->memory_error_func (status, pc, info); 1021 return -1; 1022 } 1023 1024 if (is_thumb) 1025 { 1026 if (pc & 0x2) 1027 { 1028 given = (b[2] << 8) | b[3]; 1029 1030 status = info->read_memory_func 1031 ((pc + 4) & ~ 0x3, (bfd_byte *) b, 4, info); 1032 if (status != 0) 1033 { 1034 info->memory_error_func (status, pc + 4, info); 1035 return -1; 1036 } 1037 1038 given |= (b[0] << 24) | (b[1] << 16); 1039 } 1040 else 1041 given = (b[0] << 8) | b[1] | (b[2] << 24) | (b[3] << 16); 1042 } 1043 else 1044 given = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3]); 1045 } 1046 1047 if (info->flags & INSN_HAS_RELOC) 1048 /* If the instruction has a reloc associated with it, then 1049 the offset field in the instruction will actually be the 1050 addend for the reloc. (We are using REL type relocs). 1051 In such cases, we can ignore the pc when computing 1052 addresses, since the addend is not currently pc-relative. */ 1053 pc = 0; 1054 1055 if (is_thumb) 1056 status = print_insn_thumb (pc, info, given); 1057 else 1058 status = print_insn_arm (pc, info, given); 1059 1060 return status; 1061} 1062 1063int 1064print_insn_big_arm (pc, info) 1065 bfd_vma pc; 1066 struct disassemble_info * info; 1067{ 1068 return print_insn (pc, info, false); 1069} 1070 1071int 1072print_insn_little_arm (pc, info) 1073 bfd_vma pc; 1074 struct disassemble_info * info; 1075{ 1076 return print_insn (pc, info, true); 1077} 1078 1079void 1080print_arm_disassembler_options (FILE * stream) 1081{ 1082 int i; 1083 1084 fprintf (stream, _("\n\ 1085The following ARM specific disassembler options are supported for use with\n\ 1086the -M switch:\n")); 1087 1088 for (i = NUM_ARM_REGNAMES; i--;) 1089 fprintf (stream, " reg-names-%s %*c%s\n", 1090 regnames[i].name, 1091 14 - strlen (regnames[i].name), ' ', 1092 regnames[i].description); 1093 1094 fprintf (stream, " force-thumb Assume all insns are Thumb insns\n"); 1095 fprintf (stream, " no-force-thumb Examine preceeding label to determine an insn's type\n\n"); 1096}
| 284 285 (*info->print_address_func) 286 (offset + pc + 8, info); 287 } 288 else 289 { 290 func (stream, "[%s", 291 arm_regnames[(given >> 16) & 0xf]); 292 if ((given & 0x01000000) != 0) 293 { 294 /* Pre-indexed. */ 295 if ((given & 0x00400000) == 0x00400000) 296 { 297 /* Immediate. */ 298 int offset = ((given & 0xf00) >> 4) | (given & 0xf); 299 if (offset) 300 func (stream, ", %s#%d", 301 (((given & 0x00800000) == 0) 302 ? "-" : ""), offset); 303 } 304 else 305 { 306 /* Register. */ 307 func (stream, ", %s%s", 308 (((given & 0x00800000) == 0) 309 ? "-" : ""), 310 arm_regnames[given & 0xf]); 311 } 312 313 func (stream, "]%s", 314 ((given & 0x00200000) != 0) ? "!" : ""); 315 } 316 else 317 { 318 /* Post-indexed. */ 319 if ((given & 0x00400000) == 0x00400000) 320 { 321 /* Immediate. */ 322 int offset = ((given & 0xf00) >> 4) | (given & 0xf); 323 if (offset) 324 func (stream, "], %s#%d", 325 (((given & 0x00800000) == 0) 326 ? "-" : ""), offset); 327 else 328 func (stream, "]"); 329 } 330 else 331 { 332 /* Register. */ 333 func (stream, "], %s%s", 334 (((given & 0x00800000) == 0) 335 ? "-" : ""), 336 arm_regnames[given & 0xf]); 337 } 338 } 339 } 340 break; 341 342 case 'b': 343 (*info->print_address_func) 344 (BDISP (given) * 4 + pc + 8, info); 345 break; 346 347 case 'c': 348 func (stream, "%s", 349 arm_conditional [(given >> 28) & 0xf]); 350 break; 351 352 case 'm': 353 { 354 int started = 0; 355 int reg; 356 357 func (stream, "{"); 358 for (reg = 0; reg < 16; reg++) 359 if ((given & (1 << reg)) != 0) 360 { 361 if (started) 362 func (stream, ", "); 363 started = 1; 364 func (stream, "%s", arm_regnames[reg]); 365 } 366 func (stream, "}"); 367 } 368 break; 369 370 case 'o': 371 if ((given & 0x02000000) != 0) 372 { 373 int rotate = (given & 0xf00) >> 7; 374 int immed = (given & 0xff); 375 immed = (((immed << (32 - rotate)) 376 | (immed >> rotate)) & 0xffffffff); 377 func (stream, "#%d\t; 0x%x", immed, immed); 378 } 379 else 380 arm_decode_shift (given, func, stream); 381 break; 382 383 case 'p': 384 if ((given & 0x0000f000) == 0x0000f000) 385 func (stream, "p"); 386 break; 387 388 case 't': 389 if ((given & 0x01200000) == 0x00200000) 390 func (stream, "t"); 391 break; 392 393 case 'h': 394 if ((given & 0x00000020) == 0x00000020) 395 func (stream, "h"); 396 else 397 func (stream, "b"); 398 break; 399 400 case 'A': 401 func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]); 402 if ((given & 0x01000000) != 0) 403 { 404 int offset = given & 0xff; 405 if (offset) 406 func (stream, ", %s#%d]%s", 407 ((given & 0x00800000) == 0 ? "-" : ""), 408 offset * 4, 409 ((given & 0x00200000) != 0 ? "!" : "")); 410 else 411 func (stream, "]"); 412 } 413 else 414 { 415 int offset = given & 0xff; 416 if (offset) 417 func (stream, "], %s#%d", 418 ((given & 0x00800000) == 0 ? "-" : ""), 419 offset * 4); 420 else 421 func (stream, "]"); 422 } 423 break; 424 425 case 'B': 426 /* Print ARM V5 BLX(1) address: pc+25 bits. */ 427 { 428 bfd_vma address; 429 bfd_vma offset = 0; 430 431 if (given & 0x00800000) 432 /* Is signed, hi bits should be ones. */ 433 offset = (-1) ^ 0x00ffffff; 434 435 /* Offset is (SignExtend(offset field)<<2). */ 436 offset += given & 0x00ffffff; 437 offset <<= 2; 438 address = offset + pc + 8; 439 440 if (given & 0x01000000) 441 /* H bit allows addressing to 2-byte boundaries. */ 442 address += 2; 443 444 info->print_address_func (address, info); 445 } 446 break; 447 448 case 'C': 449 func (stream, "_"); 450 if (given & 0x80000) 451 func (stream, "f"); 452 if (given & 0x40000) 453 func (stream, "s"); 454 if (given & 0x20000) 455 func (stream, "x"); 456 if (given & 0x10000) 457 func (stream, "c"); 458 break; 459 460 case 'F': 461 switch (given & 0x00408000) 462 { 463 case 0: 464 func (stream, "4"); 465 break; 466 case 0x8000: 467 func (stream, "1"); 468 break; 469 case 0x00400000: 470 func (stream, "2"); 471 break; 472 default: 473 func (stream, "3"); 474 } 475 break; 476 477 case 'P': 478 switch (given & 0x00080080) 479 { 480 case 0: 481 func (stream, "s"); 482 break; 483 case 0x80: 484 func (stream, "d"); 485 break; 486 case 0x00080000: 487 func (stream, "e"); 488 break; 489 default: 490 func (stream, _("<illegal precision>")); 491 break; 492 } 493 break; 494 case 'Q': 495 switch (given & 0x00408000) 496 { 497 case 0: 498 func (stream, "s"); 499 break; 500 case 0x8000: 501 func (stream, "d"); 502 break; 503 case 0x00400000: 504 func (stream, "e"); 505 break; 506 default: 507 func (stream, "p"); 508 break; 509 } 510 break; 511 case 'R': 512 switch (given & 0x60) 513 { 514 case 0: 515 break; 516 case 0x20: 517 func (stream, "p"); 518 break; 519 case 0x40: 520 func (stream, "m"); 521 break; 522 default: 523 func (stream, "z"); 524 break; 525 } 526 break; 527 528 case '0': case '1': case '2': case '3': case '4': 529 case '5': case '6': case '7': case '8': case '9': 530 { 531 int bitstart = *c++ - '0'; 532 int bitend = 0; 533 while (*c >= '0' && *c <= '9') 534 bitstart = (bitstart * 10) + *c++ - '0'; 535 536 switch (*c) 537 { 538 case '-': 539 c++; 540 541 while (*c >= '0' && *c <= '9') 542 bitend = (bitend * 10) + *c++ - '0'; 543 544 if (!bitend) 545 abort (); 546 547 switch (*c) 548 { 549 case 'r': 550 { 551 long reg; 552 553 reg = given >> bitstart; 554 reg &= (2 << (bitend - bitstart)) - 1; 555 556 func (stream, "%s", arm_regnames[reg]); 557 } 558 break; 559 case 'd': 560 { 561 long reg; 562 563 reg = given >> bitstart; 564 reg &= (2 << (bitend - bitstart)) - 1; 565 566 func (stream, "%d", reg); 567 } 568 break; 569 case 'x': 570 { 571 long reg; 572 573 reg = given >> bitstart; 574 reg &= (2 << (bitend - bitstart)) - 1; 575 576 func (stream, "0x%08x", reg); 577 578 /* Some SWI instructions have special 579 meanings. */ 580 if ((given & 0x0fffffff) == 0x0FF00000) 581 func (stream, "\t; IMB"); 582 else if ((given & 0x0fffffff) == 0x0FF00001) 583 func (stream, "\t; IMBRange"); 584 } 585 break; 586 case 'X': 587 { 588 long reg; 589 590 reg = given >> bitstart; 591 reg &= (2 << (bitend - bitstart)) - 1; 592 593 func (stream, "%01x", reg & 0xf); 594 } 595 break; 596 case 'f': 597 { 598 long reg; 599 600 reg = given >> bitstart; 601 reg &= (2 << (bitend - bitstart)) - 1; 602 603 if (reg > 7) 604 func (stream, "#%s", 605 arm_fp_const[reg & 7]); 606 else 607 func (stream, "f%d", reg); 608 } 609 break; 610 default: 611 abort (); 612 } 613 break; 614 615 case '`': 616 c++; 617 if ((given & (1 << bitstart)) == 0) 618 func (stream, "%c", *c); 619 break; 620 case '\'': 621 c++; 622 if ((given & (1 << bitstart)) != 0) 623 func (stream, "%c", *c); 624 break; 625 case '?': 626 ++c; 627 if ((given & (1 << bitstart)) != 0) 628 func (stream, "%c", *c++); 629 else 630 func (stream, "%c", *++c); 631 break; 632 default: 633 abort (); 634 } 635 break; 636 637 default: 638 abort (); 639 } 640 } 641 } 642 else 643 func (stream, "%c", *c); 644 } 645 return 4; 646 } 647 } 648 abort (); 649} 650 651/* Print one instruction from PC on INFO->STREAM. 652 Return the size of the instruction. */ 653static int 654print_insn_thumb (pc, info, given) 655 bfd_vma pc; 656 struct disassemble_info * info; 657 long given; 658{ 659 struct thumb_opcode * insn; 660 void * stream = info->stream; 661 fprintf_ftype func = info->fprintf_func; 662 663 for (insn = thumb_opcodes; insn->assembler; insn++) 664 { 665 if ((given & insn->mask) == insn->value) 666 { 667 char * c = insn->assembler; 668 669 /* Special processing for Thumb 2 instruction BL sequence: */ 670 if (!*c) /* Check for empty (not NULL) assembler string. */ 671 { 672 info->bytes_per_chunk = 4; 673 info->bytes_per_line = 4; 674 675 if ((given & 0x10000000) == 0) 676 func (stream, "blx\t"); 677 else 678 func (stream, "bl\t"); 679 680 info->print_address_func (BDISP23 (given) * 2 + pc + 4, info); 681 return 4; 682 } 683 else 684 { 685 info->bytes_per_chunk = 2; 686 info->bytes_per_line = 4; 687 688 given &= 0xffff; 689 690 for (; *c; c++) 691 { 692 if (*c == '%') 693 { 694 int domaskpc = 0; 695 int domasklr = 0; 696 697 switch (*++c) 698 { 699 case '%': 700 func (stream, "%%"); 701 break; 702 703 case 'S': 704 { 705 long reg; 706 707 reg = (given >> 3) & 0x7; 708 if (given & (1 << 6)) 709 reg += 8; 710 711 func (stream, "%s", arm_regnames[reg]); 712 } 713 break; 714 715 case 'D': 716 { 717 long reg; 718 719 reg = given & 0x7; 720 if (given & (1 << 7)) 721 reg += 8; 722 723 func (stream, "%s", arm_regnames[reg]); 724 } 725 break; 726 727 case 'T': 728 func (stream, "%s", 729 arm_conditional [(given >> 8) & 0xf]); 730 break; 731 732 case 'N': 733 if (given & (1 << 8)) 734 domasklr = 1; 735 /* Fall through. */ 736 case 'O': 737 if (*c == 'O' && (given & (1 << 8))) 738 domaskpc = 1; 739 /* Fall through. */ 740 case 'M': 741 { 742 int started = 0; 743 int reg; 744 745 func (stream, "{"); 746 747 /* It would be nice if we could spot 748 ranges, and generate the rS-rE format: */ 749 for (reg = 0; (reg < 8); reg++) 750 if ((given & (1 << reg)) != 0) 751 { 752 if (started) 753 func (stream, ", "); 754 started = 1; 755 func (stream, "%s", arm_regnames[reg]); 756 } 757 758 if (domasklr) 759 { 760 if (started) 761 func (stream, ", "); 762 started = 1; 763 func (stream, arm_regnames[14] /* "lr" */); 764 } 765 766 if (domaskpc) 767 { 768 if (started) 769 func (stream, ", "); 770 func (stream, arm_regnames[15] /* "pc" */); 771 } 772 773 func (stream, "}"); 774 } 775 break; 776 777 778 case '0': case '1': case '2': case '3': case '4': 779 case '5': case '6': case '7': case '8': case '9': 780 { 781 int bitstart = *c++ - '0'; 782 int bitend = 0; 783 784 while (*c >= '0' && *c <= '9') 785 bitstart = (bitstart * 10) + *c++ - '0'; 786 787 switch (*c) 788 { 789 case '-': 790 { 791 long reg; 792 793 c++; 794 while (*c >= '0' && *c <= '9') 795 bitend = (bitend * 10) + *c++ - '0'; 796 if (!bitend) 797 abort (); 798 reg = given >> bitstart; 799 reg &= (2 << (bitend - bitstart)) - 1; 800 switch (*c) 801 { 802 case 'r': 803 func (stream, "%s", arm_regnames[reg]); 804 break; 805 806 case 'd': 807 func (stream, "%d", reg); 808 break; 809 810 case 'H': 811 func (stream, "%d", reg << 1); 812 break; 813 814 case 'W': 815 func (stream, "%d", reg << 2); 816 break; 817 818 case 'a': 819 /* PC-relative address -- the bottom two 820 bits of the address are dropped 821 before the calculation. */ 822 info->print_address_func 823 (((pc + 4) & ~3) + (reg << 2), info); 824 break; 825 826 case 'x': 827 func (stream, "0x%04x", reg); 828 break; 829 830 case 'I': 831 reg = ((reg ^ (1 << bitend)) - (1 << bitend)); 832 func (stream, "%d", reg); 833 break; 834 835 case 'B': 836 reg = ((reg ^ (1 << bitend)) - (1 << bitend)); 837 (*info->print_address_func) 838 (reg * 2 + pc + 4, info); 839 break; 840 841 default: 842 abort (); 843 } 844 } 845 break; 846 847 case '\'': 848 c++; 849 if ((given & (1 << bitstart)) != 0) 850 func (stream, "%c", *c); 851 break; 852 853 case '?': 854 ++c; 855 if ((given & (1 << bitstart)) != 0) 856 func (stream, "%c", *c++); 857 else 858 func (stream, "%c", *++c); 859 break; 860 861 default: 862 abort (); 863 } 864 } 865 break; 866 867 default: 868 abort (); 869 } 870 } 871 else 872 func (stream, "%c", *c); 873 } 874 } 875 return 2; 876 } 877 } 878 879 /* No match. */ 880 abort (); 881} 882 883/* Parse an individual disassembler option. */ 884void 885parse_arm_disassembler_option (option) 886 char * option; 887{ 888 if (option == NULL) 889 return; 890 891 if (strneq (option, "reg-names-", 10)) 892 { 893 int i; 894 895 option += 10; 896 897 for (i = NUM_ARM_REGNAMES; i--;) 898 if (streq (option, regnames[i].name)) 899 { 900 regname_selected = i; 901 break; 902 } 903 904 if (i < 0) 905 fprintf (stderr, _("Unrecognised register name set: %s\n"), option); 906 } 907 else if (streq (option, "force-thumb")) 908 force_thumb = 1; 909 else if (streq (option, "no-force-thumb")) 910 force_thumb = 0; 911 else 912 fprintf (stderr, _("Unrecognised disassembler option: %s\n"), option); 913 914 return; 915} 916 917/* Parse the string of disassembler options, spliting it at whitespaces. */ 918static void 919parse_disassembler_options (options) 920 char * options; 921{ 922 char * space; 923 924 if (options == NULL) 925 return; 926 927 do 928 { 929 space = strchr (options, ' '); 930 931 if (space) 932 { 933 * space = '\0'; 934 parse_arm_disassembler_option (options); 935 * space = ' '; 936 options = space + 1; 937 } 938 else 939 parse_arm_disassembler_option (options); 940 } 941 while (space); 942} 943 944/* NOTE: There are no checks in these routines that 945 the relevant number of data bytes exist. */ 946static int 947print_insn (pc, info, little) 948 bfd_vma pc; 949 struct disassemble_info * info; 950 boolean little; 951{ 952 unsigned char b[4]; 953 long given; 954 int status; 955 int is_thumb; 956 957 if (info->disassembler_options) 958 { 959 parse_disassembler_options (info->disassembler_options); 960 961 /* To avoid repeated parsing of these options, we remove them here. */ 962 info->disassembler_options = NULL; 963 } 964 965 is_thumb = force_thumb; 966 967 if (!is_thumb && info->symbols != NULL) 968 { 969 if (bfd_asymbol_flavour (*info->symbols) == bfd_target_coff_flavour) 970 { 971 coff_symbol_type * cs; 972 973 cs = coffsymbol (*info->symbols); 974 is_thumb = ( cs->native->u.syment.n_sclass == C_THUMBEXT 975 || cs->native->u.syment.n_sclass == C_THUMBSTAT 976 || cs->native->u.syment.n_sclass == C_THUMBLABEL 977 || cs->native->u.syment.n_sclass == C_THUMBEXTFUNC 978 || cs->native->u.syment.n_sclass == C_THUMBSTATFUNC); 979 } 980 else if (bfd_asymbol_flavour (*info->symbols) == bfd_target_elf_flavour) 981 { 982 elf_symbol_type * es; 983 unsigned int type; 984 985 es = *(elf_symbol_type **)(info->symbols); 986 type = ELF_ST_TYPE (es->internal_elf_sym.st_info); 987 988 is_thumb = (type == STT_ARM_TFUNC) || (type == STT_ARM_16BIT); 989 } 990 } 991 992 info->bytes_per_chunk = 4; 993 info->display_endian = little ? BFD_ENDIAN_LITTLE : BFD_ENDIAN_BIG; 994 995 if (little) 996 { 997 status = info->read_memory_func (pc, (bfd_byte *) &b[0], 4, info); 998 if (status != 0 && is_thumb) 999 { 1000 info->bytes_per_chunk = 2; 1001 1002 status = info->read_memory_func (pc, (bfd_byte *) b, 2, info); 1003 b[3] = b[2] = 0; 1004 } 1005 1006 if (status != 0) 1007 { 1008 info->memory_error_func (status, pc, info); 1009 return -1; 1010 } 1011 1012 given = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24); 1013 } 1014 else 1015 { 1016 status = info->read_memory_func 1017 (pc & ~ 0x3, (bfd_byte *) &b[0], 4, info); 1018 if (status != 0) 1019 { 1020 info->memory_error_func (status, pc, info); 1021 return -1; 1022 } 1023 1024 if (is_thumb) 1025 { 1026 if (pc & 0x2) 1027 { 1028 given = (b[2] << 8) | b[3]; 1029 1030 status = info->read_memory_func 1031 ((pc + 4) & ~ 0x3, (bfd_byte *) b, 4, info); 1032 if (status != 0) 1033 { 1034 info->memory_error_func (status, pc + 4, info); 1035 return -1; 1036 } 1037 1038 given |= (b[0] << 24) | (b[1] << 16); 1039 } 1040 else 1041 given = (b[0] << 8) | b[1] | (b[2] << 24) | (b[3] << 16); 1042 } 1043 else 1044 given = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3]); 1045 } 1046 1047 if (info->flags & INSN_HAS_RELOC) 1048 /* If the instruction has a reloc associated with it, then 1049 the offset field in the instruction will actually be the 1050 addend for the reloc. (We are using REL type relocs). 1051 In such cases, we can ignore the pc when computing 1052 addresses, since the addend is not currently pc-relative. */ 1053 pc = 0; 1054 1055 if (is_thumb) 1056 status = print_insn_thumb (pc, info, given); 1057 else 1058 status = print_insn_arm (pc, info, given); 1059 1060 return status; 1061} 1062 1063int 1064print_insn_big_arm (pc, info) 1065 bfd_vma pc; 1066 struct disassemble_info * info; 1067{ 1068 return print_insn (pc, info, false); 1069} 1070 1071int 1072print_insn_little_arm (pc, info) 1073 bfd_vma pc; 1074 struct disassemble_info * info; 1075{ 1076 return print_insn (pc, info, true); 1077} 1078 1079void 1080print_arm_disassembler_options (FILE * stream) 1081{ 1082 int i; 1083 1084 fprintf (stream, _("\n\ 1085The following ARM specific disassembler options are supported for use with\n\ 1086the -M switch:\n")); 1087 1088 for (i = NUM_ARM_REGNAMES; i--;) 1089 fprintf (stream, " reg-names-%s %*c%s\n", 1090 regnames[i].name, 1091 14 - strlen (regnames[i].name), ' ', 1092 regnames[i].description); 1093 1094 fprintf (stream, " force-thumb Assume all insns are Thumb insns\n"); 1095 fprintf (stream, " no-force-thumb Examine preceeding label to determine an insn's type\n\n"); 1096}
|