diff options
author | Nick Clifton <nickc@redhat.com> | 2003-03-25 20:56:01 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2003-03-25 20:56:01 +0000 |
commit | 3c228517adac7fbf03219f067fa0e9380e7c05ce (patch) | |
tree | 3f21827b2ccae80ff766209c94ae290257525201 | |
parent | bfc3a2046eeab959642f75e0a8d2bfade9305a2d (diff) | |
download | gdb-3c228517adac7fbf03219f067fa0e9380e7c05ce.tar.gz |
Add iWMMXt support
-rw-r--r-- | bfd/ChangeLog | 23 | ||||
-rw-r--r-- | bfd/archures.c | 1 | ||||
-rw-r--r-- | bfd/bfd-in2.h | 2 | ||||
-rw-r--r-- | bfd/coff-arm.c | 57 | ||||
-rw-r--r-- | bfd/coffcode.h | 21 | ||||
-rw-r--r-- | bfd/coffgen.c | 3 | ||||
-rw-r--r-- | bfd/cpu-arm.c | 6 | ||||
-rw-r--r-- | bfd/elf32-arm.h | 119 | ||||
-rw-r--r-- | bfd/libbfd.h | 1 | ||||
-rw-r--r-- | bfd/reloc.c | 2 | ||||
-rw-r--r-- | include/coff/ChangeLog | 7 | ||||
-rw-r--r-- | include/coff/arm.h | 2 | ||||
-rw-r--r-- | include/elf/ChangeLog | 9 | ||||
-rw-r--r-- | include/elf/arm.h | 3 | ||||
-rw-r--r-- | opcodes/ChangeLog | 11 | ||||
-rw-r--r-- | opcodes/arm-dis.c | 185 | ||||
-rw-r--r-- | opcodes/arm-opc.h | 62 |
17 files changed, 487 insertions, 27 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index e0f41fda6eb..a29b48ace47 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,26 @@ +2003-03-25 Stan Cox <scox@redhat.com> + Nick Clifton <nickc@redhat.com> + + Contribute support for Intel's iWMMXt chip - an ARM variant: + + * archures.c: Add bfd_mach_arm_iWMMXt. + * reloc.c: Add BFD_RELOC_ARM_CP_OFF_IMM_S2. + * bfd-in2.h: Regenerate. + * libbfd.h: Regenerate. + * coff-arm.c (coff_arm_merge_private_bfd_data): Allow iWMMXt + object files to be linked with XScale ones. + (coff_arm_final_link_postscript): Update note section. + * coffcode.h (coff_set_arch_mach_hook): Handle note section. + * coffgen.c (coff_real_object_p): Call bfd_coff_set_arch_mach_hook + after identifying a coff binary. + * cpu-arm.c (processors): Add iWMMXt. + (arch_inf): Likewise. + * elf32-arm.h (arm_object_p): Handle note section. + (elf32_arm_merge_private_bfd_data): Allow iWMMXt object files to + be linked with XScale ones. + (elf32_arm_section_flags): New function: Set flags on note section. + (elf32_arm_final_write_processing): Handle note section. + 2003-03-21 DJ Delorie <dj@redhat.com> * elf32-xstormy16.c (elf32_xstormy16_relocate_section): Call diff --git a/bfd/archures.c b/bfd/archures.c index 62edda109bb..18ebb835115 100644 --- a/bfd/archures.c +++ b/bfd/archures.c @@ -235,6 +235,7 @@ DESCRIPTION .#define bfd_mach_arm_5TE 9 .#define bfd_mach_arm_XScale 10 .#define bfd_mach_arm_ep9312 11 +.#define bfd_mach_arm_iWMMXt 12 . bfd_arch_ns32k, {* National Semiconductors ns32000 *} . bfd_arch_w65, {* WDC 65816 *} . bfd_arch_tic30, {* Texas Instruments TMS320C30 *} diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 2385c409a5c..8960f66df34 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -1691,6 +1691,7 @@ enum bfd_architecture #define bfd_mach_arm_5TE 9 #define bfd_mach_arm_XScale 10 #define bfd_mach_arm_ep9312 11 +#define bfd_mach_arm_iWMMXt 12 bfd_arch_ns32k, /* National Semiconductors ns32000 */ bfd_arch_w65, /* WDC 65816 */ bfd_arch_tic30, /* Texas Instruments TMS320C30 */ @@ -2563,6 +2564,7 @@ field in the instruction. */ BFD_RELOC_ARM_SWI, BFD_RELOC_ARM_MULTI, BFD_RELOC_ARM_CP_OFF_IMM, + BFD_RELOC_ARM_CP_OFF_IMM_S2, BFD_RELOC_ARM_ADR_IMM, BFD_RELOC_ARM_LDR_IMM, BFD_RELOC_ARM_LITERAL, diff --git a/bfd/coff-arm.c b/bfd/coff-arm.c index 2fadcbef557..24015049826 100644 --- a/bfd/coff-arm.c +++ b/bfd/coff-arm.c @@ -2240,6 +2240,25 @@ coff_arm_merge_private_bfd_data (ibfd, obfd) if (ibfd == obfd) return TRUE; + if (bfd_get_mach (obfd) && bfd_get_mach (obfd) != bfd_get_mach (ibfd)) + { + /* For now, allow an output file type of 'xscale' if the + input file type is 'iWMMXt'. This means that we will + not have to build an entire iWMMXt enabled set of libraries + just to test a iWMMXt enabled binary. Change the output + type to iWMMXt though. Similarly allow 'xscale' binaries + to be linked into a 'iWMMXt' output binary. */ + if ( bfd_get_mach (obfd) == bfd_mach_arm_XScale + && bfd_get_mach (ibfd) == bfd_mach_arm_iWMMXt) + bfd_set_arch_mach (obfd, bfd_get_arch (obfd), bfd_mach_arm_iWMMXt); + else if ( bfd_get_mach (ibfd) != bfd_mach_arm_XScale + || bfd_get_mach (obfd) != bfd_mach_arm_iWMMXt) + { + bfd_set_error (bfd_error_wrong_format); + return FALSE; + } + } + /* If the two formats are different we cannot merge anything. This is not an error, since it is permissable to change the input and output formats. */ @@ -2584,6 +2603,44 @@ coff_arm_final_link_postscript (abfd, pfinfo) globals->bfd_of_glue_owner->output_has_begun = TRUE; } + { + asection * arm_arch_section; + + /* Look for a .note section. If one is present check + the machine number encoded in it, and set it to the current + machine number if it is different. This allows XScale and + iWMMXt binaries to be merged and the resulting output to be set + to iWMMXt, even if the first input file had an XScale .note. */ + + arm_arch_section = bfd_get_section_by_name (abfd, ".note"); + + if (arm_arch_section != NULL) + { + char buffer [4]; + + if (bfd_get_section_contents (abfd, arm_arch_section, buffer, + (file_ptr) 0, sizeof buffer)) + { + unsigned long arm_mach; + + /* We have to extract the value this way to allow for a + host whose endian-ness is different from the target. */ + arm_mach = bfd_get_32 (abfd, buffer); + + if (arm_mach != bfd_get_mach (abfd)) + { + bfd_put_32 (abfd, bfd_get_mach (abfd), buffer); + + if (! bfd_set_section_contents (abfd, arm_arch_section, buffer, + (file_ptr) 0, sizeof buffer)) + (*_bfd_error_handler) + (_("warning: unable to update contents of .note section in %s"), + bfd_get_filename (abfd)); + } + } + } + } + return TRUE; } diff --git a/bfd/coffcode.h b/bfd/coffcode.h index ee50a10993c..da8121fd77f 100644 --- a/bfd/coffcode.h +++ b/bfd/coffcode.h @@ -1899,6 +1899,27 @@ coff_set_arch_mach_hook (abfd, filehdr) currently the XScale. */ case F_ARM_5: machine = bfd_mach_arm_XScale; break; } + + { + asection * arm_arch_section; + + arm_arch_section = bfd_get_section_by_name (abfd, ".note"); + + if (arm_arch_section) + { + bfd_byte buffer [4]; + + if (! bfd_get_section_contents (abfd, arm_arch_section, buffer, + (file_ptr) 0, sizeof buffer)) + (*_bfd_error_handler) + (_("%s: warning: unable to retrieve .note section from %s"), + bfd_get_filename (abfd)); + + /* We have to extract the value this way to allow for a + host whose endian-ness is different from the target. */ + machine = bfd_get_32 (abfd, buffer); + } + } break; #endif #ifdef MC68MAGIC diff --git a/bfd/coffgen.c b/bfd/coffgen.c index c905ab17eec..a3e3eecb413 100644 --- a/bfd/coffgen.c +++ b/bfd/coffgen.c @@ -226,7 +226,7 @@ coff_real_object_p (abfd, nscns, internal_f, internal_a) if (! bfd_coff_set_arch_mach_hook (abfd, (PTR) internal_f)) goto fail; - /* Now copy data as required; construct all asections etc */ + /* Now copy data as required; construct all asections etc. */ if (nscns != 0) { unsigned int i; @@ -241,6 +241,7 @@ coff_real_object_p (abfd, nscns, internal_f, internal_a) } } + bfd_coff_set_arch_mach_hook (abfd, (PTR) internal_f); /* make_abs_section (abfd); */ return abfd->xvec; diff --git a/bfd/cpu-arm.c b/bfd/cpu-arm.c index 923c2500afe..eb3011d7d29 100644 --- a/bfd/cpu-arm.c +++ b/bfd/cpu-arm.c @@ -96,7 +96,8 @@ processors[] = { bfd_mach_arm_4, "strongarm110" }, { bfd_mach_arm_4, "strongarm1100" }, { bfd_mach_arm_XScale, "xscale" }, - { bfd_mach_arm_ep9312, "ep9312" } + { bfd_mach_arm_ep9312, "ep9312" }, + { bfd_mach_arm_iWMMXt, "iwmmxt" } }; static bfd_boolean @@ -142,7 +143,8 @@ static const bfd_arch_info_type arch_info_struct[] = N (bfd_mach_arm_5T, "armv5t", FALSE, & arch_info_struct[8]), N (bfd_mach_arm_5TE, "armv5te", FALSE, & arch_info_struct[9]), N (bfd_mach_arm_XScale, "xscale", FALSE, & arch_info_struct[10]), - N (bfd_mach_arm_ep9312, "ep9312", FALSE, NULL) + N (bfd_mach_arm_ep9312, "ep9312", FALSE, & arch_info_struct[11]), + N (bfd_mach_arm_iWMMXt,"iwmmxt", FALSE, NULL) }; const bfd_arch_info_type bfd_arm_arch = diff --git a/bfd/elf32-arm.h b/bfd/elf32-arm.h index 509b4815574..417284b3169 100644 --- a/bfd/elf32-arm.h +++ b/bfd/elf32-arm.h @@ -2119,10 +2119,43 @@ static bfd_boolean elf32_arm_object_p (abfd) bfd *abfd; { - /* XXX - we ought to examine a .note section here. */ + asection * arm_arch_section; - if (elf_elfheader (abfd)->e_flags & EF_ARM_MAVERICK_FLOAT) - bfd_default_set_arch_mach (abfd, bfd_arch_arm, bfd_mach_arm_ep9312); + arm_arch_section = bfd_get_section_by_name (abfd, ARM_NOTE_SECTION); + + if (arm_arch_section) + { + char buffer [4]; + unsigned long arm_mach; + + if (! bfd_get_section_contents (abfd, arm_arch_section, buffer, + (file_ptr) 0, sizeof buffer)) + (*_bfd_error_handler) + (_("%s: warning: unable to retrieve %s section from %s"), + ARM_NOTE_SECTION, bfd_get_filename (abfd)); + else + { + /* We have to extract the value this way to allow for a + host whose endian-ness is different from the target. */ + arm_mach = bfd_get_32 (abfd, buffer); + bfd_default_set_arch_mach (abfd, bfd_arch_arm, arm_mach); + + if (bfd_get_arch (abfd) == bfd_arch_arm) + return TRUE; + + /* If the set failed for some reason, do not leave the architecture + type as 0 (unknown), but issue a warning message and force it to + be set to bfd_arch_arm. */ + (*_bfd_error_handler) + (_("%s: warning: unrecognized ARM machine number: %x"), + bfd_get_filename (abfd), arm_mach); + } + } + else + { + if (elf_elfheader (abfd)->e_flags & EF_ARM_MAVERICK_FLOAT) + bfd_default_set_arch_mach (abfd, bfd_arch_arm, bfd_mach_arm_ep9312); + } return TRUE; } @@ -2263,6 +2296,25 @@ elf32_arm_merge_private_bfd_data (ibfd, obfd) return TRUE; } + if (bfd_get_mach (obfd) && bfd_get_mach (obfd) != bfd_get_mach (ibfd)) + { + /* For now, allow an output file type of 'xscale' if the + input file type is 'iWMMXt'. This means that we will + not have to build an entire iWMMXt enabled set of libraries + just to test a iWMMXt enabled binary. Change the output + type to iWMMXt though. Similarly allow 'xscale' binaries + to be linked into a 'iWMMXt' output binary. */ + if ( bfd_get_mach (obfd) == bfd_mach_arm_XScale + && bfd_get_mach (ibfd) == bfd_mach_arm_iWMMXt) + bfd_set_arch_mach (obfd, bfd_get_arch (obfd), bfd_mach_arm_iWMMXt); + else if ( bfd_get_mach (ibfd) != bfd_mach_arm_XScale + || bfd_get_mach (obfd) != bfd_mach_arm_iWMMXt) + { + bfd_set_error (bfd_error_wrong_format); + return FALSE; + } + } + /* Identical flags must be compatible. */ if (in_flags == out_flags) return TRUE; @@ -3660,6 +3712,65 @@ elf32_arm_reloc_type_class (rela) } } +static bfd_boolean elf32_arm_section_flags PARAMS ((flagword *, Elf_Internal_Shdr *)); +static void elf32_arm_final_write_processing PARAMS ((bfd *, bfd_boolean)); + +/* Set the right machine number for an Arm ELF file. */ + +static bfd_boolean +elf32_arm_section_flags (flags, hdr) + flagword *flags; + Elf_Internal_Shdr *hdr; +{ + if (hdr->sh_type == SHT_NOTE) + *flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_SAME_CONTENTS; + + return TRUE; +} + +void +elf32_arm_final_write_processing (abfd, linker) + bfd *abfd; + bfd_boolean linker ATTRIBUTE_UNUSED; +{ + asection * arm_arch_section; + char buffer [4]; + unsigned long arm_mach; + + /* Look for a .note.arm.ident section. If one is present check + the machine number encoded in it, and set it to the current + machine number if it is different. This allows XScale and + iWMMXt binaries to be merged and the resulting output to be set + to iWMMXt, even if the first input file had an XScale .note. */ + + arm_arch_section = bfd_get_section_by_name (abfd, ARM_NOTE_SECTION); + + if (arm_arch_section == NULL) + return; + + if (! bfd_get_section_contents (abfd, arm_arch_section, buffer, + (file_ptr) 0, sizeof buffer)) + /* If the ident section does not exist then just skip this check. */ + return; + + /* We have to extract the value this way to allow for a + host whose endian-ness is different from the target. */ + arm_mach = bfd_get_32 (abfd, buffer); + + if (arm_mach == bfd_get_mach (abfd)) + return; + + bfd_put_32 (abfd, bfd_get_mach (abfd), buffer); + + if (! bfd_set_section_contents (abfd, arm_arch_section, buffer, + (file_ptr) 0, sizeof buffer)) + (*_bfd_error_handler) + (_("warning: unable to update contents of %s section in %s"), + ARM_NOTE_SECTION, bfd_get_filename (abfd)); + + return; +} + #define ELF_ARCH bfd_arch_arm #define ELF_MACHINE_CODE EM_ARM #define ELF_MAXPAGESIZE 0x8000 @@ -3685,6 +3796,8 @@ elf32_arm_reloc_type_class (rela) #define elf_backend_post_process_headers elf32_arm_post_process_headers #define elf_backend_reloc_type_class elf32_arm_reloc_type_class #define elf_backend_object_p elf32_arm_object_p +#define elf_backend_section_flags elf32_arm_section_flags +#define elf_backend_final_write_processing elf32_arm_final_write_processing #define elf_backend_can_gc_sections 1 #define elf_backend_plt_readonly 1 diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 222b23dcb5d..df2ba3e3f97 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -1043,6 +1043,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_ARM_SWI", "BFD_RELOC_ARM_MULTI", "BFD_RELOC_ARM_CP_OFF_IMM", + "BFD_RELOC_ARM_CP_OFF_IMM_S2", "BFD_RELOC_ARM_ADR_IMM", "BFD_RELOC_ARM_LDR_IMM", "BFD_RELOC_ARM_LITERAL", diff --git a/bfd/reloc.c b/bfd/reloc.c index 9f8a952c591..f4a33218022 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -2519,6 +2519,8 @@ ENUMX ENUMX BFD_RELOC_ARM_CP_OFF_IMM ENUMX + BFD_RELOC_ARM_CP_OFF_IMM_S2 +ENUMX BFD_RELOC_ARM_ADR_IMM ENUMX BFD_RELOC_ARM_LDR_IMM diff --git a/include/coff/ChangeLog b/include/coff/ChangeLog index b2eec4cbe93..be6154d21c1 100644 --- a/include/coff/ChangeLog +++ b/include/coff/ChangeLog @@ -1,3 +1,10 @@ +2003-03-25 Stan Cox <scox@redhat.com> + Nick Clifton <nickc@redhat.com> + + Contribute support for Intel's iWMMXt chip - an ARM variant: + + * arm.h (ARM_NOTE_SECTION): Define. + 2002-11-30 Alan Modra <amodra@bigpond.net.au> * ecoff.h: Replace boolean with bfd_boolean. diff --git a/include/coff/arm.h b/include/coff/arm.h index bcfdcbe4784..8b90228ca98 100644 --- a/include/coff/arm.h +++ b/include/coff/arm.h @@ -124,3 +124,5 @@ struct external_reloc #define RELOC struct external_reloc #define RELSZ 14 #endif + +#define ARM_NOTE_SECTION ".note" diff --git a/include/elf/ChangeLog b/include/elf/ChangeLog index e87cdd2e045..5411f769169 100644 --- a/include/elf/ChangeLog +++ b/include/elf/ChangeLog @@ -1,4 +1,11 @@ -Mon Mar 3 20:35:58 2003 J"orn Rennecke <joern.rennecke@superh.com> +2003-03-25 Stan Cox <scox@redhat.com> + Nick Clifton <nickc@redhat.com> + + Contribute support for Intel's iWMMXt chip - an ARM variant: + + * arm.h (ARM_NOTE_SECTION): Define. + +2003-03-03 J"orn Rennecke <joern.rennecke@superh.com> * sh.h (EF_SH_MERGE_MACH): Make sure SH2E & SH3/SH3E merge to SH3E, and SH2E & SH4 merge to SH4, not SH2E. diff --git a/include/elf/arm.h b/include/elf/arm.h index 534701753c4..3b3f8d0e235 100644 --- a/include/elf/arm.h +++ b/include/elf/arm.h @@ -140,4 +140,7 @@ START_RELOC_NUMBERS (elf_arm_reloc_type) RELOC_NUMBER (R_ARM_RBASE, 255) END_RELOC_NUMBERS (R_ARM_max) +/* The name of the note section used to identify arm variants. */ +#define ARM_NOTE_SECTION ".note.arm.ident" + #endif /* _ELF_ARM_H */ diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index d3162797302..b1338964e53 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,14 @@ +2003-03-25 Stan Cox <scox@redhat.com> + Nick Clifton <nickc@redhat.com> + + Contribute support for Intel's iWMMXt chip - an ARM variant: + + * arm-dis.c (regnames): Add iWMMXt register names. + (set_iwmmxt_regnames): New function. + (print_insn_arm): Handle iWMMXt formatters. + * arm-opc.h: Document iWMMXt formatters. + (arm_opcod): Add iWMMXt instructions. + 2003-03-22 Doug Evans <dje@sebabeach.org> * i386-dis.c (dis386): Recognize icebp (0xf1). diff --git a/opcodes/arm-dis.c b/opcodes/arm-dis.c index 62a2a39ab62..8fb970245dc 100644 --- a/opcodes/arm-dis.c +++ b/opcodes/arm-dis.c @@ -1,24 +1,24 @@ /* Instruction printing code for the ARM - Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 + Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org) Modification by James G. Smith (jsmith@cygnus.co.uk) -This file is part of libopcodes. + This file is part of libopcodes. -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2 of the License, or (at your option) -any later version. + This program is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) + any later version. -This program is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -more details. + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "sysdep.h" #include "dis-asm.h" @@ -70,7 +70,21 @@ static arm_regname regnames[] = { "atpcs", "Select register names used in the ATPCS", { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "IP", "SP", "LR", "PC" }}, { "special-atpcs", "Select special register names used in the ATPCS", - { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "WR", "v5", "SB", "SL", "FP", "IP", "SP", "LR", "PC" }} + { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "WR", "v5", "SB", "SL", "FP", "IP", "SP", "LR", "PC" }}, + { "iwmmxt_regnames", "Select register names used on the Intel(r) Wireless MMX(tm) technology coprocessor", + { "wr0", "wr1", "wr2", "wr3", "wr4", "wr5", "wr6", "wr7", "wr8", "wr9", "wr10", "wr11", "wr12", "wr13", "wr14", "wr15"}}, + { "iwmmxt_Cregnames", "Select control register names used on the Intel(r) Wireless MMX(tm) technology coprocessor", + {"wcid", "wcon", "wcssf", "wcasf", "reserved", "reserved", "reserved", "reserved", "wcgr0", "wcgr1", "wcgr2", "wcgr3", "reserved", "reserved", "reserved", "reserved"}} +}; + +static char * iwmmxt_wwnames[] = +{"b", "h", "w", "d"}; + +static char * iwmmxt_wwssnames[] = +{"b", "bus", "b", "bss", + "h", "hus", "h", "hss", + "w", "wus", "w", "wss", + "d", "dus", "d", "dss" }; /* Default to GCC register name set. */ @@ -98,11 +112,15 @@ static void parse_disassembler_options PARAMS ((char *)); static int print_insn PARAMS ((bfd_vma, struct disassemble_info *, bfd_boolean)); -int get_arm_regname_num_options (void); -int set_arm_regname_option (int option); -int get_arm_regnames (int option, const char **setname, - const char **setdescription, - const char ***register_names); +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 @@ -167,6 +185,24 @@ arm_decode_shift (given, func, stream) } } +static int +set_iwmmxt_regnames () +{ + const char * setname; + const char * setdesc; + const char ** regnames; + int iwmmxt_regnames = 0; + int num_regnames = get_arm_regname_num_options (); + + get_arm_regnames (iwmmxt_regnames, &setname, + &setdesc, ®names); + while ((strcmp ("iwmmxt_regnames", setname)) + && (iwmmxt_regnames < num_regnames)) + get_arm_regnames (++iwmmxt_regnames, &setname, &setdesc, ®names); + + return iwmmxt_regnames; +} + /* Print one instruction from PC on INFO->STREAM. Return the size of the instruction (always 4 on ARM). */ @@ -179,9 +215,15 @@ print_insn_arm (pc, info, given) const struct arm_opcode *insn; void *stream = info->stream; fprintf_ftype func = info->fprintf_func; + static int iwmmxt_regnames = 0; for (insn = arm_opcodes; insn->assembler; insn++) { + if (insn->value == FIRST_IWMMXT_INSN + && info->mach != bfd_mach_arm_XScale + && info->mach != bfd_mach_arm_iWMMXt) + insn = insn + IWMMXT_INSN_COUNT; + if ((given & insn->mask) == insn->value) { char * c; @@ -629,6 +671,63 @@ print_insn_arm (pc, info, given) func (stream, "f%d", reg); } break; + + case 'w': + { + long reg; + + if (bitstart != bitend) + { + reg = given >> bitstart; + reg &= (2 << (bitend - bitstart)) - 1; + if (bitend - bitstart == 1) + func (stream, "%s", iwmmxt_wwnames[reg]); + else + func (stream, "%s", iwmmxt_wwssnames[reg]); + } + else + { + reg = (((given >> 8) & 0x1) | + ((given >> 22) & 0x1)); + func (stream, "%s", iwmmxt_wwnames[reg]); + } + } + break; + + case 'g': + { + long reg; + int current_regnames; + + if (! iwmmxt_regnames) + iwmmxt_regnames = set_iwmmxt_regnames (); + current_regnames = set_arm_regname_option + (iwmmxt_regnames); + + reg = given >> bitstart; + reg &= (2 << (bitend - bitstart)) - 1; + func (stream, "%s", arm_regnames[reg]); + set_arm_regname_option (current_regnames); + } + break; + + case 'G': + { + long reg; + int current_regnames; + + if (! iwmmxt_regnames) + iwmmxt_regnames = set_iwmmxt_regnames (); + current_regnames = set_arm_regname_option + (iwmmxt_regnames + 1); + + reg = given >> bitstart; + reg &= (2 << (bitend - bitstart)) - 1; + func (stream, "%s", arm_regnames[reg]); + set_arm_regname_option (current_regnames); + } + break; + default: abort (); } @@ -734,6 +833,54 @@ print_insn_arm (pc, info, given) } break; + case 'L': + switch (given & 0x00400100) + { + case 0x00000000: func (stream, "b"); break; + case 0x00400000: func (stream, "h"); break; + case 0x00000100: func (stream, "w"); break; + case 0x00400100: func (stream, "d"); break; + default: + break; + } + break; + + case 'Z': + { + int value; + /* given (20, 23) | given (0, 3) */ + value = ((given >> 16) & 0xf0) | (given & 0xf); + func (stream, "%d", value); + } + break; + + case 'l': + /* This is like the 'A' operator, except that if + the width field "M" is zero, then the offset is + *not* multiplied by four. */ + { + int offset = given & 0xff; + int multiplier = (given & 0x00000100) ? 4 : 1; + + func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]); + + if (offset) + { + if ((given & 0x01000000) != 0) + func (stream, ", %s#%d]%s", + ((given & 0x00800000) == 0 ? "-" : ""), + offset * multiplier, + ((given & 0x00200000) != 0 ? "!" : "")); + else + func (stream, "], %s#%d", + ((given & 0x00800000) == 0 ? "-" : ""), + offset * multiplier); + } + else + func (stream, "]"); + } + break; + default: abort (); } diff --git a/opcodes/arm-opc.h b/opcodes/arm-opc.h index 213d4f034de..233a8303fea 100644 --- a/opcodes/arm-opc.h +++ b/opcodes/arm-opc.h @@ -1,6 +1,6 @@ /* Opcode table for the ARM. - Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000 + Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2003 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify @@ -60,6 +60,13 @@ struct thumb_opcode %m print register mask for ldm/stm instruction %C print the PSR sub type. %F print the COUNT field of a LFM/SFM 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) @@ -101,6 +108,59 @@ static const struct arm_opcode arm_opcodes[] = {0x0c500000, 0x0ff00fff, "mra%c\t%12-15r, %16-19r, acc0"}, {0xf450f000, 0xfc70f000, "pld\t%a"}, + /* Intel(r) Wireless MMX(tm) technology instructions. */ +#define FIRST_IWMMXT_INSN 0x0e130130 +#define IWMMXT_INSN_COUNT 47 + {0x0e130130, 0x0f3f0fff, "tandc%22-23w%c\t%12-15r"}, + {0x0e400010, 0x0ff00f3f, "tbcst%6-7w%c\t%16-19g, %12-15r"}, + {0x0e130170, 0x0f3f0ff8, "textrc%22-23w%c\t%12-15r, #%0-2d"}, + {0x0e100070, 0x0f300ff0, "textrm%3?su%22-23w%c\t%12-15r, %16-19g, #%0-2d"}, + {0x0e600010, 0x0ff00f38, "tinsr%6-7w%c\t%16-19g, %12-15r, #%0-2d"}, + {0x0e000110, 0x0ff00fff, "tmcr%c\t%16-19G, %12-15r"}, + {0x0c400000, 0x0ff00ff0, "tmcrr%c\t%0-3g, %12-15r, %16-19r"}, + {0x0e2c0010, 0x0ffc0e10, "tmia%17?tb%16?tb%c\t%5-8g, %0-3r, %12-15r"}, + {0x0e200010, 0x0fff0e10, "tmia%c\t%5-8g, %0-3r, %12-15r"}, + {0x0e280010, 0x0fff0e10, "tmiaph%c\t%5-8g, %0-3r, %12-15r"}, + {0x0e100030, 0x0f300fff, "tmovmsk%22-23w%c\t%12-15r, %16-19g"}, + {0x0e100110, 0x0ff00ff0, "tmrc%c\t%12-15r, %16-19G"}, + {0x0c500000, 0x0ff00ff0, "tmrrc%c\t%12-15r, %16-19r, %0-3g"}, + {0x0e130150, 0x0f3f0fff, "torc%22-23w%c\t%12-15r"}, + {0x0e0001c0, 0x0f300fff, "wacc%22-23w%c\t%12-15g, %16-19g"}, + {0x0e000180, 0x0f000ff0, "wadd%20-23w%c\t%12-15g, %16-19g, %0-3g"}, + {0x0e000020, 0x0f800ff0, "waligni%c\t%12-15g, %16-19g, %0-3g, #%20-22d"}, + {0x0e800020, 0x0fc00ff0, "walignr%20-21d%c\t%12-15g, %16-19g, %0-3g"}, + {0x0e200000, 0x0fe00ff0, "wand%20'n%c\t%12-15g, %16-19g, %0-3g"}, + {0x0e800000, 0x0fa00ff0, "wavg2%22?hb%20'r%c\t%12-15g, %16-19g, %0-3g"}, + {0x0e000060, 0x0f300ff0, "wcmpeq%22-23w%c\t%12-15g, %16-19g, %0-3g"}, + {0x0e100060, 0x0f100ff0, "wcmpgt%21?su%22-23w%c\t%12-15g, %16-19g, %0-3g"}, + {0xfc100100, 0xfe500f00, "wldrw\t%12-15G, %A"}, + {0x0c100000, 0x0e100e00, "wldr%L%c\t%12-15g, %l"}, + {0x0e400100, 0x0fc00ff0, "wmac%21?su%20'z%c\t%12-15g, %16-19g, %0-3g"}, + {0x0e800100, 0x0fd00ff0, "wmadd%21?su%c\t%12-15g, %16-19g, %0-3g"}, + {0x0e000160, 0x0f100ff0, "wmax%21?su%22-23w%c\t%12-15g, %16-19g, %0-3g"}, + {0x0e100160, 0x0f100ff0, "wmin%21?su%22-23w%c\t%12-15g, %16-19g, %0-3g"}, + {0x0e000100, 0x0fc00ff0, "wmul%21?su%20?ml%c\t%12-15g, %16-19g, %0-3g"}, + {0x0e000000, 0x0ff00ff0, "wor%c\t%12-15g, %16-19g, %0-3g"}, + {0x0e000080, 0x0f000ff0, "wpack%20-23w%c\t%12-15g, %16-19g, %0-3g"}, + {0x0e300040, 0x0f300ff0, "wror%22-23w%8'g%c\t%12-15g, %16-19g, %0-3g"}, + {0x0e300148, 0x0f300ffc, "wror%22-23w%8'g%c\t%12-15g, %16-19g, %0-3G"}, + {0x0e000120, 0x0fa00ff0, "wsad%22?hb%20'z%c\t%12-15g, %16-19g, %0-3g"}, + {0x0e0001e0, 0x0f000ff0, "wshufh%c\t%12-15g, %16-19g, #%Z"}, + {0x0e100040, 0x0f300ff0, "wsll%22-23w%8'g%c\t%12-15g, %16-19g, %0-3g"}, + {0x0e100148, 0x0f300ffc, "wsll%22-23w%8'g%c\t%12-15g, %16-19g, %0-3G"}, + {0x0e000040, 0x0f300ff0, "wsra%22-23w%8'g%c\t%12-15g, %16-19g, %0-3g"}, + {0x0e000148, 0x0f300ffc, "wsra%22-23w%8'g%c\t%12-15g, %16-19g, %0-3G"}, + {0x0e200040, 0x0f300ff0, "wsrl%22-23w%8'g%c\t%12-15g, %16-19g, %0-3g"}, + {0x0e200148, 0x0f300ffc, "wsrl%22-23w%8'g%c\t%12-15g, %16-19g, %0-3G"}, + {0xfc000100, 0xfe500f00, "wstrw\t%12-15G, %A"}, + {0x0c000000, 0x0e100e00, "wstr%L%c\t%12-15g, %l"}, + {0x0e0001a0, 0x0f000ff0, "wsub%20-23w%c\t%12-15g, %16-19g, %0-3g"}, + {0x0e0000c0, 0x0f100fff, "wunpckeh%21?su%22-23w%c\t%12-15g, %16-19g"}, + {0x0e0000e0, 0x0f100fff, "wunpckel%21?su%22-23w%c\t%12-15g, %16-19g"}, + {0x0e1000c0, 0x0f300ff0, "wunpckih%22-23w%c\t%12-15g, %16-19g, %0-3g"}, + {0x0e1000e0, 0x0f300ff0, "wunpckil%22-23w%c\t%12-15g, %16-19g, %0-3g"}, + {0x0e100000, 0x0ff00ff0, "wxor%c\t%12-15g, %16-19g, %0-3g"}, + /* V5 Instructions. */ {0xe1200070, 0xfff000f0, "bkpt\t0x%16-19X%12-15X%8-11X%0-3X"}, {0xfa000000, 0xfe000000, "blx\t%B"}, |