aboutsummaryrefslogtreecommitdiff
path: root/opcodes/arm-dis.c
diff options
context:
space:
mode:
authorZack Weinberg <zackw@panix.com>2005-06-07 22:16:52 +0000
committerZack Weinberg <zackw@panix.com>2005-06-07 22:16:52 +0000
commit4a5329c63abbeb362968edcc3cb6df0ca754e1ee (patch)
tree4b74032d5703b392b5f92f1568b473a89659e750 /opcodes/arm-dis.c
parent1ae72221f94f4d5938cf529bb439413ffb6a5ade (diff)
downloadgdb-4a5329c63abbeb362968edcc3cb6df0ca754e1ee.zip
gdb-4a5329c63abbeb362968edcc3cb6df0ca754e1ee.tar.gz
gdb-4a5329c63abbeb362968edcc3cb6df0ca754e1ee.tar.bz2
* arm-dis.c: Split up the comments describing the format codes, so
that the ARM and 16-bit Thumb opcode tables each have comments preceding them that describe all the codes, and only the codes, valid in those tables. (32-bit Thumb table is already like this.) Reorder the lists in all three comments to match the order in which the codes are implemented. Remove all forward declarations of static functions. Convert all function definitions to ISO C format. (print_insn_arm, print_insn_thumb16, print_insn_thumb32): Return nothing. (print_insn_thumb16): Remove unused case 'I'. (print_insn): Update for changed calling convention of subroutines.
Diffstat (limited to 'opcodes/arm-dis.c')
-rw-r--r--opcodes/arm-dis.c242
1 files changed, 103 insertions, 139 deletions
diff --git a/opcodes/arm-dis.c b/opcodes/arm-dis.c
index e623f92..a1540b7 100644
--- a/opcodes/arm-dis.c
+++ b/opcodes/arm-dis.c
@@ -49,66 +49,57 @@
#define WORD_ADDRESS(pc) ((pc) & ~0x3)
-/* Format of the disassembler control string :
-
+/* Opcode tables: ARM, 16-bit Thumb, 32-bit Thumb. All three are partially
+ ordered: they must be searched linearly from the top to obtain a correct
+ match. */
+
+/* print_insn_arm recognizes the following format control codes:
+
%% %
+
+ %a print address for ldr/str instruction
+ %s print address for ldr/str halfword/signextend instruction
+ %b print branch destination
+ %c print condition code (always bits 28-31)
+ %m print register mask for ldm/stm instruction
+ %o print operand2 (immediate or register + shift)
+ %p print 'p' iff bits 12-15 are 15
+ %t print 't' iff bit 21 set and bit 24 clear
+ %A print address for ldc/stc/ldf/stf instruction
+ %B print arm BLX(1) destination
+ %I print cirrus signed shift immediate: bits 0..3|4..6
+ %C print the PSR sub type.
+ %F print the COUNT field of a LFM/SFM instruction.
+ %P print floating point precision in arithmetic insn
+ %Q print floating point precision in ldf/stf insn
+ %R print floating point rounding mode
+
+ %<bitfield>r print as an ARM register
%<bitfield>d print the bitfield in decimal
+ %<bitfield>W print the bitfield plus one in decimal
%<bitfield>x print the bitfield in hex
%<bitfield>X print the bitfield as 1 hex digit without leading "0x"
- %<bitfield>W print the bitfield plus one in decimal
- %<bitfield>r print as an ARM register
%<bitfield>f print a floating point constant if >7 else a
floating point register
+ %<bitfield>w print as an iWMMXt width field - [bhwd]ss/us
+ %<bitfield>g print as an iWMMXt 64-bit register
+ %<bitfield>G print as an iWMMXt general purpose or control register
+
%<code>y print a single precision VFP reg.
Codes: 0=>Sm, 1=>Sd, 2=>Sn, 3=>multi-list, 4=>Sm pair
%<code>z print a double precision VFP reg
Codes: 0=>Dm, 1=>Dd, 2=>Dn, 3=>multi-list
- %c print condition code (always bits 28-31)
- %P print floating point precision in arithmetic insn
- %Q print floating point precision in ldf/stf insn
- %R print floating point rounding mode
%<bitnum>'c print specified char iff bit is one
%<bitnum>`c print specified char iff bit is zero
%<bitnum>?ab print a if bit is one else print b
- %p print 'p' iff bits 12-15 are 15
- %t print 't' iff bit 21 set and bit 24 clear
- %o print operand2 (immediate or register + shift)
- %a print address for ldr/str instruction
- %s print address for ldr/str halfword/signextend instruction
- %b print branch destination
- %B print arm BLX(1) destination
- %A print address for ldc/stc/ldf/stf instruction
- %m print register mask for ldm/stm instruction
- %C print the PSR sub type.
- %F print the COUNT field of a LFM/SFM instruction.
- %E print the LSB and WIDTH fields of a BFI or BFC instruction.
- %V print the 16-bit immediate field of a MOVT or MOVW instruction.
-IWMMXT specific format options:
- %<bitfield>g print as an iWMMXt 64-bit register
- %<bitfield>G print as an iWMMXt general purpose or control register
- %<bitfield>w print as an iWMMXt width field - [bhwd]ss/us
- %Z print the Immediate of a WSHUFH instruction.
+
%L print as an iWMMXt N/M width field.
- %l like 'A' except use byte offsets for 'B' & 'H' versions
-Thumb specific format options:
- %D print Thumb register (bits 0..2 as high number if bit 7 set)
- %S print Thumb register (bits 3..5 as high number if bit 6 set)
- %<bitfield>I print bitfield as a signed decimal
- (top bit of range being the sign bit)
- %M print Thumb register mask
- %N print Thumb register mask (with LR)
- %O print Thumb register mask (with PC)
- %I print cirrus signed shift immediate: bits 0..3|4..6
- %<bitfield>B print Thumb branch destination (signed displacement)
- %<bitfield>W print (bitfield * 4) as a decimal
- %<bitfield>H print (bitfield * 2) as a decimal
- %<bitfield>a print (bitfield * 4) as a pc-rel offset + decoded symbol
- %<bitfield>c print bitfield as a condition code
- %e print arm SMI operand (bits 0..7,8..19).
- %s print Thumb right-shift immediate (6..10; 0 == 32). */
+ %Z print the Immediate of a WSHUFH instruction.
+ %l like 'A' except use byte offsets for 'B' & 'H' versions.
-/* Note: There is a partial ordering in this table - it must be searched from
- the top to obtain a correct match. */
+ %e print arm SMI operand (bits 0..7,8..19).
+ %E print the LSB and WIDTH fields of a BFI or BFC instruction.
+ %V print the 16-bit immediate field of a MOVT or MOVW instruction. */
static const struct arm_opcode arm_opcodes[] =
{
@@ -632,6 +623,27 @@ static const struct arm_opcode arm_opcodes[] =
{0, 0x00000000, 0x00000000, 0}
};
+/* print_insn_thumb16 recognizes the following format control codes:
+
+ %S print Thumb register (bits 3..5 as high number if bit 6 set)
+ %D print Thumb register (bits 0..2 as high number if bit 7 set)
+ %<bitfield>I print bitfield as a signed decimal
+ (top bit of range being the sign bit)
+ %N print Thumb register mask (with LR)
+ %O print Thumb register mask (with PC)
+ %M print Thumb register mask
+ %b print CZB's 6-bit unsigned branch destination
+ %s print Thumb right-shift immediate (6..10; 0 == 32).
+ %<bitfield>r print bitfield as an ARM register
+ %<bitfield>d print bitfield as a decimal
+ %<bitfield>H print (bitfield * 2) as a decimal
+ %<bitfield>W print (bitfield * 4) as a decimal
+ %<bitfield>a print (bitfield * 4) as a pc-rel offset + decoded symbol
+ %<bitfield>B print Thumb branch destination (signed displacement)
+ %<bitfield>c print bitfield as a condition code
+ %<bitnum>'c print specified char iff bit is one
+ %<bitnum>?ab print a if bit is one else print b. */
+
static const struct thumb_opcode thumb_opcodes[] =
{
/* Thumb instructions. */
@@ -761,17 +773,9 @@ static const struct thumb_opcode thumb_opcodes[] =
We adopt the convention that hw1 is the high 16 bits of .value and
.mask, hw2 the low 16 bits.
- %-escapes defined for these instructions:
+ print_insn_thumb32 recognizes the following format control codes:
%% %
- %<bitfield>d print bitfield in decimal
- %<bitfield>W print bitfield*4 in decimal
- %<bitfield>r print bitfield as an ARM register
- %<bitfield>c print bitfield as a condition code
-
- %<bitnum>'c print "c" iff bit is one
- %<bitnum>`c print "c" iff bit is zero
- %<bitnum>?ab print "a" if bit is one, else "b"
%I print a 12-bit immediate from hw1[10],hw2[14:12,7:0]
%M print a modified 12-bit immediate (same location)
@@ -786,11 +790,20 @@ static const struct thumb_opcode thumb_opcodes[] =
%E print the lsb and width fields of a bfc/bfi instruction
%F print the lsb and width fields of a sbfx/ubfx instruction
- %B print an unconditional branch offset
%b print a conditional branch offset
+ %B print an unconditional branch offset
%s print the shift field of an SSAT instruction
%R print the rotation field of an SXT instruction
+ %<bitfield>d print bitfield in decimal
+ %<bitfield>W print bitfield*4 in decimal
+ %<bitfield>r print bitfield as an ARM register
+ %<bitfield>c print bitfield as a condition code
+
+ %<bitnum>'c print "c" iff bit is one
+ %<bitnum>`c print "c" iff bit is zero
+ %<bitnum>?ab print "a" if bit is one, else "b"
+
With one exception at the bottom (done because BL and BLX(1) need
to come dead last), this table was machine-sorted first in
decreasing order of number of bits set in the mask, then in
@@ -1062,39 +1075,15 @@ static char * arm_fp_const[] =
static char * arm_shift[] =
{"lsl", "lsr", "asr", "ror"};
-/* Forward declarations. */
-static void arm_decode_shift
- PARAMS ((long, fprintf_ftype, void *));
-static int print_insn_arm
- PARAMS ((bfd_vma, struct disassemble_info *, long));
-static int print_insn_thumb16
- PARAMS ((bfd_vma, struct disassemble_info *, long));
-static int print_insn_thumb32
- PARAMS ((bfd_vma, struct disassemble_info *, long));
-static void parse_disassembler_options
- PARAMS ((char *));
-static int print_insn
- PARAMS ((bfd_vma, struct disassemble_info *, bfd_boolean));
-static int set_iwmmxt_regnames
- PARAMS ((void));
-
-int get_arm_regname_num_options
- PARAMS ((void));
-int set_arm_regname_option
- PARAMS ((int));
-int get_arm_regnames
- PARAMS ((int, const char **, const char **, const char ***));
-
/* Functions. */
int
-get_arm_regname_num_options ()
+get_arm_regname_num_options (void)
{
return NUM_ARM_REGNAMES;
}
int
-set_arm_regname_option (option)
- int option;
+set_arm_regname_option (int option)
{
int old = regname_selected;
regname_selected = option;
@@ -1102,11 +1091,8 @@ set_arm_regname_option (option)
}
int
-get_arm_regnames (option, setname, setdescription, register_names)
- int option;
- const char **setname;
- const char **setdescription;
- const char ***register_names;
+get_arm_regnames (int option, const char **setname, const char **setdescription,
+ const char ***register_names)
{
*setname = regnames[option].name;
*setdescription = regnames[option].description;
@@ -1115,10 +1101,7 @@ get_arm_regnames (option, setname, setdescription, register_names)
}
static void
-arm_decode_shift (given, func, stream)
- long given;
- fprintf_ftype func;
- void * stream;
+arm_decode_shift (long given, fprintf_ftype func, void *stream)
{
func (stream, "%s", arm_regnames[given & 0xf]);
@@ -1149,7 +1132,7 @@ arm_decode_shift (given, func, stream)
}
static int
-set_iwmmxt_regnames ()
+set_iwmmxt_regnames (void)
{
const char * setname;
const char * setdesc;
@@ -1165,15 +1148,11 @@ set_iwmmxt_regnames ()
return iwmmxt_regnames;
}
-
-/* Print one instruction from PC on INFO->STREAM.
- Return the size of the instruction (always 4 on ARM). */
-static int
-print_insn_arm (pc, info, given)
- bfd_vma pc;
- struct disassemble_info *info;
- long given;
+/* Print one ARM instruction from PC on INFO->STREAM. */
+
+static void
+print_insn_arm (bfd_vma pc, struct disassemble_info *info, long given)
{
const struct arm_opcode *insn;
void *stream = info->stream;
@@ -1911,20 +1890,16 @@ print_insn_arm (pc, info, given)
else
func (stream, "%c", *c);
}
- return 4;
+ return;
}
}
abort ();
}
-/* Print one instruction from PC on INFO->STREAM.
- Return the size of the instruction. */
+/* Print one 16-bit Thumb instruction from PC on INFO->STREAM. */
-static int
-print_insn_thumb16 (pc, info, given)
- bfd_vma pc;
- struct disassemble_info *info;
- long given;
+static void
+print_insn_thumb16 (bfd_vma pc, struct disassemble_info *info, long given)
{
const struct thumb_opcode *insn;
void *stream = info->stream;
@@ -2093,11 +2068,6 @@ print_insn_thumb16 (pc, info, given)
func (stream, "0x%04x", reg);
break;
- case 'I':
- reg = ((reg ^ (1 << bitend)) - (1 << bitend));
- func (stream, "%d", reg);
- break;
-
case 'B':
reg = ((reg ^ (1 << bitend)) - (1 << bitend));
(*info->print_address_func)
@@ -2145,18 +2115,17 @@ print_insn_thumb16 (pc, info, given)
abort ();
}
}
- return 2;
+ return;
}
/* No match. */
abort ();
}
-static int
-print_insn_thumb32 (pc, info, given)
- bfd_vma pc;
- struct disassemble_info *info;
- long given;
+/* Print one 32-bit Thumb instruction from PC on INFO->STREAM. */
+
+static void
+print_insn_thumb32 (bfd_vma pc, struct disassemble_info *info, long given)
{
const struct arm_opcode *insn;
void *stream = info->stream;
@@ -2554,7 +2523,7 @@ print_insn_thumb32 (pc, info, given)
abort ();
}
}
- return 4;
+ return;
}
/* No match. */
@@ -2581,8 +2550,7 @@ arm_symbol_is_valid (asymbol * sym,
/* Parse an individual disassembler option. */
void
-parse_arm_disassembler_option (option)
- char * option;
+parse_arm_disassembler_option (char *option)
{
if (option == NULL)
return;
@@ -2619,8 +2587,7 @@ parse_arm_disassembler_option (option)
or commas. (Whitespace separators supported for backwards compatibility). */
static void
-parse_disassembler_options (options)
- char * options;
+parse_disassembler_options (char *options)
{
if (options == NULL)
return;
@@ -2642,16 +2609,14 @@ parse_disassembler_options (options)
the relevant number of data bytes exist. */
static int
-print_insn (pc, info, little)
- bfd_vma pc;
- struct disassemble_info * info;
- bfd_boolean little;
+print_insn (bfd_vma pc, struct disassemble_info *info, bfd_boolean little)
{
unsigned char b[4];
long given;
int status;
int is_thumb;
- int (*printer) (bfd_vma, struct disassemble_info *, long);
+ int size;
+ void (*printer) (bfd_vma, struct disassemble_info *, long);
if (info->disassembler_options)
{
@@ -2697,6 +2662,7 @@ print_insn (pc, info, little)
is four bytes long and is either ordered 0123 or 3210. */
printer = print_insn_arm;
info->bytes_per_chunk = 4;
+ size = 4;
status = info->read_memory_func (pc, (bfd_byte *)b, 4, info);
if (little)
@@ -2710,8 +2676,10 @@ print_insn (pc, info, little)
instruction lengths. Fortunately, the bits that determine
the length of the current instruction are always to be found
in the first two bytes. */
-
+ printer = print_insn_thumb16;
info->bytes_per_chunk = 2;
+ size = 2;
+
status = info->read_memory_func (pc, (bfd_byte *)b, 2, info);
if (!status)
{
@@ -2733,9 +2701,8 @@ print_insn (pc, info, little)
given = (b[1]) | (b[0] << 8) | (given << 16);
printer = print_insn_thumb32;
+ size = 4;
}
- else
- printer = print_insn_thumb16;
}
}
@@ -2752,27 +2719,24 @@ print_insn (pc, info, little)
addresses, since the addend is not currently pc-relative. */
pc = 0;
- return printer (pc, info, given);
+ printer (pc, info, given);
+ return size;
}
int
-print_insn_big_arm (pc, info)
- bfd_vma pc;
- struct disassemble_info * info;
+print_insn_big_arm (bfd_vma pc, struct disassemble_info *info)
{
return print_insn (pc, info, FALSE);
}
int
-print_insn_little_arm (pc, info)
- bfd_vma pc;
- struct disassemble_info * info;
+print_insn_little_arm (bfd_vma pc, struct disassemble_info *info)
{
return print_insn (pc, info, TRUE);
}
void
-print_arm_disassembler_options (FILE * stream)
+print_arm_disassembler_options (FILE *stream)
{
int i;