@ -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 instruction s:
print_insn_thumb32 recognizes the following format control code s:
% % %
% < 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 ;