/* tc-arm.c -- Assemble 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)
Modified by David Taylor (dtaylor@armltd.co.uk)
static int target_oabi = 0;
/* Flags stored in private area of BFD structure. */
-static int uses_apcs_26 = false;
-static int atpcs = false;
-static int support_interwork = false;
-static int uses_apcs_float = false;
-static int pic_code = false;
+static int uses_apcs_26 = FALSE;
+static int atpcs = FALSE;
+static int support_interwork = FALSE;
+static int uses_apcs_float = FALSE;
+static int pic_code = FALSE;
/* Variables that we set while parsing command-line options. Once all
options have been read we re-process these values to set the real
struct asm_psr
{
- const char * template;
- boolean cpsr;
+ const char *template;
+ bfd_boolean cpsr;
unsigned long field;
};
static const struct asm_psr psrs[] =
{
- {"CPSR", true, PSR_c | PSR_f},
- {"CPSR_all", true, PSR_c | PSR_f},
- {"SPSR", false, PSR_c | PSR_f},
- {"SPSR_all", false, PSR_c | PSR_f},
- {"CPSR_flg", true, PSR_f},
- {"CPSR_f", true, PSR_f},
- {"SPSR_flg", false, PSR_f},
- {"SPSR_f", false, PSR_f},
- {"CPSR_c", true, PSR_c},
- {"CPSR_ctl", true, PSR_c},
- {"SPSR_c", false, PSR_c},
- {"SPSR_ctl", false, PSR_c},
- {"CPSR_x", true, PSR_x},
- {"CPSR_s", true, PSR_s},
- {"SPSR_x", false, PSR_x},
- {"SPSR_s", false, PSR_s},
+ {"CPSR", TRUE, PSR_c | PSR_f},
+ {"CPSR_all", TRUE, PSR_c | PSR_f},
+ {"SPSR", FALSE, PSR_c | PSR_f},
+ {"SPSR_all", FALSE, PSR_c | PSR_f},
+ {"CPSR_flg", TRUE, PSR_f},
+ {"CPSR_f", TRUE, PSR_f},
+ {"SPSR_flg", FALSE, PSR_f},
+ {"SPSR_f", FALSE, PSR_f},
+ {"CPSR_c", TRUE, PSR_c},
+ {"CPSR_ctl", TRUE, PSR_c},
+ {"SPSR_c", FALSE, PSR_c},
+ {"SPSR_ctl", FALSE, PSR_c},
+ {"CPSR_x", TRUE, PSR_x},
+ {"CPSR_s", TRUE, PSR_s},
+ {"SPSR_x", FALSE, PSR_x},
+ {"SPSR_s", FALSE, PSR_s},
/* Combinations of flags. */
- {"CPSR_fs", true, PSR_f | PSR_s},
- {"CPSR_fx", true, PSR_f | PSR_x},
- {"CPSR_fc", true, PSR_f | PSR_c},
- {"CPSR_sf", true, PSR_s | PSR_f},
- {"CPSR_sx", true, PSR_s | PSR_x},
- {"CPSR_sc", true, PSR_s | PSR_c},
- {"CPSR_xf", true, PSR_x | PSR_f},
- {"CPSR_xs", true, PSR_x | PSR_s},
- {"CPSR_xc", true, PSR_x | PSR_c},
- {"CPSR_cf", true, PSR_c | PSR_f},
- {"CPSR_cs", true, PSR_c | PSR_s},
- {"CPSR_cx", true, PSR_c | PSR_x},
- {"CPSR_fsx", true, PSR_f | PSR_s | PSR_x},
- {"CPSR_fsc", true, PSR_f | PSR_s | PSR_c},
- {"CPSR_fxs", true, PSR_f | PSR_x | PSR_s},
- {"CPSR_fxc", true, PSR_f | PSR_x | PSR_c},
- {"CPSR_fcs", true, PSR_f | PSR_c | PSR_s},
- {"CPSR_fcx", true, PSR_f | PSR_c | PSR_x},
- {"CPSR_sfx", true, PSR_s | PSR_f | PSR_x},
- {"CPSR_sfc", true, PSR_s | PSR_f | PSR_c},
- {"CPSR_sxf", true, PSR_s | PSR_x | PSR_f},
- {"CPSR_sxc", true, PSR_s | PSR_x | PSR_c},
- {"CPSR_scf", true, PSR_s | PSR_c | PSR_f},
- {"CPSR_scx", true, PSR_s | PSR_c | PSR_x},
- {"CPSR_xfs", true, PSR_x | PSR_f | PSR_s},
- {"CPSR_xfc", true, PSR_x | PSR_f | PSR_c},
- {"CPSR_xsf", true, PSR_x | PSR_s | PSR_f},
- {"CPSR_xsc", true, PSR_x | PSR_s | PSR_c},
- {"CPSR_xcf", true, PSR_x | PSR_c | PSR_f},
- {"CPSR_xcs", true, PSR_x | PSR_c | PSR_s},
- {"CPSR_cfs", true, PSR_c | PSR_f | PSR_s},
- {"CPSR_cfx", true, PSR_c | PSR_f | PSR_x},
- {"CPSR_csf", true, PSR_c | PSR_s | PSR_f},
- {"CPSR_csx", true, PSR_c | PSR_s | PSR_x},
- {"CPSR_cxf", true, PSR_c | PSR_x | PSR_f},
- {"CPSR_cxs", true, PSR_c | PSR_x | PSR_s},
- {"CPSR_fsxc", true, PSR_f | PSR_s | PSR_x | PSR_c},
- {"CPSR_fscx", true, PSR_f | PSR_s | PSR_c | PSR_x},
- {"CPSR_fxsc", true, PSR_f | PSR_x | PSR_s | PSR_c},
- {"CPSR_fxcs", true, PSR_f | PSR_x | PSR_c | PSR_s},
- {"CPSR_fcsx", true, PSR_f | PSR_c | PSR_s | PSR_x},
- {"CPSR_fcxs", true, PSR_f | PSR_c | PSR_x | PSR_s},
- {"CPSR_sfxc", true, PSR_s | PSR_f | PSR_x | PSR_c},
- {"CPSR_sfcx", true, PSR_s | PSR_f | PSR_c | PSR_x},
- {"CPSR_sxfc", true, PSR_s | PSR_x | PSR_f | PSR_c},
- {"CPSR_sxcf", true, PSR_s | PSR_x | PSR_c | PSR_f},
- {"CPSR_scfx", true, PSR_s | PSR_c | PSR_f | PSR_x},
- {"CPSR_scxf", true, PSR_s | PSR_c | PSR_x | PSR_f},
- {"CPSR_xfsc", true, PSR_x | PSR_f | PSR_s | PSR_c},
- {"CPSR_xfcs", true, PSR_x | PSR_f | PSR_c | PSR_s},
- {"CPSR_xsfc", true, PSR_x | PSR_s | PSR_f | PSR_c},
- {"CPSR_xscf", true, PSR_x | PSR_s | PSR_c | PSR_f},
- {"CPSR_xcfs", true, PSR_x | PSR_c | PSR_f | PSR_s},
- {"CPSR_xcsf", true, PSR_x | PSR_c | PSR_s | PSR_f},
- {"CPSR_cfsx", true, PSR_c | PSR_f | PSR_s | PSR_x},
- {"CPSR_cfxs", true, PSR_c | PSR_f | PSR_x | PSR_s},
- {"CPSR_csfx", true, PSR_c | PSR_s | PSR_f | PSR_x},
- {"CPSR_csxf", true, PSR_c | PSR_s | PSR_x | PSR_f},
- {"CPSR_cxfs", true, PSR_c | PSR_x | PSR_f | PSR_s},
- {"CPSR_cxsf", true, PSR_c | PSR_x | PSR_s | PSR_f},
- {"SPSR_fs", false, PSR_f | PSR_s},
- {"SPSR_fx", false, PSR_f | PSR_x},
- {"SPSR_fc", false, PSR_f | PSR_c},
- {"SPSR_sf", false, PSR_s | PSR_f},
- {"SPSR_sx", false, PSR_s | PSR_x},
- {"SPSR_sc", false, PSR_s | PSR_c},
- {"SPSR_xf", false, PSR_x | PSR_f},
- {"SPSR_xs", false, PSR_x | PSR_s},
- {"SPSR_xc", false, PSR_x | PSR_c},
- {"SPSR_cf", false, PSR_c | PSR_f},
- {"SPSR_cs", false, PSR_c | PSR_s},
- {"SPSR_cx", false, PSR_c | PSR_x},
- {"SPSR_fsx", false, PSR_f | PSR_s | PSR_x},
- {"SPSR_fsc", false, PSR_f | PSR_s | PSR_c},
- {"SPSR_fxs", false, PSR_f | PSR_x | PSR_s},
- {"SPSR_fxc", false, PSR_f | PSR_x | PSR_c},
- {"SPSR_fcs", false, PSR_f | PSR_c | PSR_s},
- {"SPSR_fcx", false, PSR_f | PSR_c | PSR_x},
- {"SPSR_sfx", false, PSR_s | PSR_f | PSR_x},
- {"SPSR_sfc", false, PSR_s | PSR_f | PSR_c},
- {"SPSR_sxf", false, PSR_s | PSR_x | PSR_f},
- {"SPSR_sxc", false, PSR_s | PSR_x | PSR_c},
- {"SPSR_scf", false, PSR_s | PSR_c | PSR_f},
- {"SPSR_scx", false, PSR_s | PSR_c | PSR_x},
- {"SPSR_xfs", false, PSR_x | PSR_f | PSR_s},
- {"SPSR_xfc", false, PSR_x | PSR_f | PSR_c},
- {"SPSR_xsf", false, PSR_x | PSR_s | PSR_f},
- {"SPSR_xsc", false, PSR_x | PSR_s | PSR_c},
- {"SPSR_xcf", false, PSR_x | PSR_c | PSR_f},
- {"SPSR_xcs", false, PSR_x | PSR_c | PSR_s},
- {"SPSR_cfs", false, PSR_c | PSR_f | PSR_s},
- {"SPSR_cfx", false, PSR_c | PSR_f | PSR_x},
- {"SPSR_csf", false, PSR_c | PSR_s | PSR_f},
- {"SPSR_csx", false, PSR_c | PSR_s | PSR_x},
- {"SPSR_cxf", false, PSR_c | PSR_x | PSR_f},
- {"SPSR_cxs", false, PSR_c | PSR_x | PSR_s},
- {"SPSR_fsxc", false, PSR_f | PSR_s | PSR_x | PSR_c},
- {"SPSR_fscx", false, PSR_f | PSR_s | PSR_c | PSR_x},
- {"SPSR_fxsc", false, PSR_f | PSR_x | PSR_s | PSR_c},
- {"SPSR_fxcs", false, PSR_f | PSR_x | PSR_c | PSR_s},
- {"SPSR_fcsx", false, PSR_f | PSR_c | PSR_s | PSR_x},
- {"SPSR_fcxs", false, PSR_f | PSR_c | PSR_x | PSR_s},
- {"SPSR_sfxc", false, PSR_s | PSR_f | PSR_x | PSR_c},
- {"SPSR_sfcx", false, PSR_s | PSR_f | PSR_c | PSR_x},
- {"SPSR_sxfc", false, PSR_s | PSR_x | PSR_f | PSR_c},
- {"SPSR_sxcf", false, PSR_s | PSR_x | PSR_c | PSR_f},
- {"SPSR_scfx", false, PSR_s | PSR_c | PSR_f | PSR_x},
- {"SPSR_scxf", false, PSR_s | PSR_c | PSR_x | PSR_f},
- {"SPSR_xfsc", false, PSR_x | PSR_f | PSR_s | PSR_c},
- {"SPSR_xfcs", false, PSR_x | PSR_f | PSR_c | PSR_s},
- {"SPSR_xsfc", false, PSR_x | PSR_s | PSR_f | PSR_c},
- {"SPSR_xscf", false, PSR_x | PSR_s | PSR_c | PSR_f},
- {"SPSR_xcfs", false, PSR_x | PSR_c | PSR_f | PSR_s},
- {"SPSR_xcsf", false, PSR_x | PSR_c | PSR_s | PSR_f},
- {"SPSR_cfsx", false, PSR_c | PSR_f | PSR_s | PSR_x},
- {"SPSR_cfxs", false, PSR_c | PSR_f | PSR_x | PSR_s},
- {"SPSR_csfx", false, PSR_c | PSR_s | PSR_f | PSR_x},
- {"SPSR_csxf", false, PSR_c | PSR_s | PSR_x | PSR_f},
- {"SPSR_cxfs", false, PSR_c | PSR_x | PSR_f | PSR_s},
- {"SPSR_cxsf", false, PSR_c | PSR_x | PSR_s | PSR_f},
+ {"CPSR_fs", TRUE, PSR_f | PSR_s},
+ {"CPSR_fx", TRUE, PSR_f | PSR_x},
+ {"CPSR_fc", TRUE, PSR_f | PSR_c},
+ {"CPSR_sf", TRUE, PSR_s | PSR_f},
+ {"CPSR_sx", TRUE, PSR_s | PSR_x},
+ {"CPSR_sc", TRUE, PSR_s | PSR_c},
+ {"CPSR_xf", TRUE, PSR_x | PSR_f},
+ {"CPSR_xs", TRUE, PSR_x | PSR_s},
+ {"CPSR_xc", TRUE, PSR_x | PSR_c},
+ {"CPSR_cf", TRUE, PSR_c | PSR_f},
+ {"CPSR_cs", TRUE, PSR_c | PSR_s},
+ {"CPSR_cx", TRUE, PSR_c | PSR_x},
+ {"CPSR_fsx", TRUE, PSR_f | PSR_s | PSR_x},
+ {"CPSR_fsc", TRUE, PSR_f | PSR_s | PSR_c},
+ {"CPSR_fxs", TRUE, PSR_f | PSR_x | PSR_s},
+ {"CPSR_fxc", TRUE, PSR_f | PSR_x | PSR_c},
+ {"CPSR_fcs", TRUE, PSR_f | PSR_c | PSR_s},
+ {"CPSR_fcx", TRUE, PSR_f | PSR_c | PSR_x},
+ {"CPSR_sfx", TRUE, PSR_s | PSR_f | PSR_x},
+ {"CPSR_sfc", TRUE, PSR_s | PSR_f | PSR_c},
+ {"CPSR_sxf", TRUE, PSR_s | PSR_x | PSR_f},
+ {"CPSR_sxc", TRUE, PSR_s | PSR_x | PSR_c},
+ {"CPSR_scf", TRUE, PSR_s | PSR_c | PSR_f},
+ {"CPSR_scx", TRUE, PSR_s | PSR_c | PSR_x},
+ {"CPSR_xfs", TRUE, PSR_x | PSR_f | PSR_s},
+ {"CPSR_xfc", TRUE, PSR_x | PSR_f | PSR_c},
+ {"CPSR_xsf", TRUE, PSR_x | PSR_s | PSR_f},
+ {"CPSR_xsc", TRUE, PSR_x | PSR_s | PSR_c},
+ {"CPSR_xcf", TRUE, PSR_x | PSR_c | PSR_f},
+ {"CPSR_xcs", TRUE, PSR_x | PSR_c | PSR_s},
+ {"CPSR_cfs", TRUE, PSR_c | PSR_f | PSR_s},
+ {"CPSR_cfx", TRUE, PSR_c | PSR_f | PSR_x},
+ {"CPSR_csf", TRUE, PSR_c | PSR_s | PSR_f},
+ {"CPSR_csx", TRUE, PSR_c | PSR_s | PSR_x},
+ {"CPSR_cxf", TRUE, PSR_c | PSR_x | PSR_f},
+ {"CPSR_cxs", TRUE, PSR_c | PSR_x | PSR_s},
+ {"CPSR_fsxc", TRUE, PSR_f | PSR_s | PSR_x | PSR_c},
+ {"CPSR_fscx", TRUE, PSR_f | PSR_s | PSR_c | PSR_x},
+ {"CPSR_fxsc", TRUE, PSR_f | PSR_x | PSR_s | PSR_c},
+ {"CPSR_fxcs", TRUE, PSR_f | PSR_x | PSR_c | PSR_s},
+ {"CPSR_fcsx", TRUE, PSR_f | PSR_c | PSR_s | PSR_x},
+ {"CPSR_fcxs", TRUE, PSR_f | PSR_c | PSR_x | PSR_s},
+ {"CPSR_sfxc", TRUE, PSR_s | PSR_f | PSR_x | PSR_c},
+ {"CPSR_sfcx", TRUE, PSR_s | PSR_f | PSR_c | PSR_x},
+ {"CPSR_sxfc", TRUE, PSR_s | PSR_x | PSR_f | PSR_c},
+ {"CPSR_sxcf", TRUE, PSR_s | PSR_x | PSR_c | PSR_f},
+ {"CPSR_scfx", TRUE, PSR_s | PSR_c | PSR_f | PSR_x},
+ {"CPSR_scxf", TRUE, PSR_s | PSR_c | PSR_x | PSR_f},
+ {"CPSR_xfsc", TRUE, PSR_x | PSR_f | PSR_s | PSR_c},
+ {"CPSR_xfcs", TRUE, PSR_x | PSR_f | PSR_c | PSR_s},
+ {"CPSR_xsfc", TRUE, PSR_x | PSR_s | PSR_f | PSR_c},
+ {"CPSR_xscf", TRUE, PSR_x | PSR_s | PSR_c | PSR_f},
+ {"CPSR_xcfs", TRUE, PSR_x | PSR_c | PSR_f | PSR_s},
+ {"CPSR_xcsf", TRUE, PSR_x | PSR_c | PSR_s | PSR_f},
+ {"CPSR_cfsx", TRUE, PSR_c | PSR_f | PSR_s | PSR_x},
+ {"CPSR_cfxs", TRUE, PSR_c | PSR_f | PSR_x | PSR_s},
+ {"CPSR_csfx", TRUE, PSR_c | PSR_s | PSR_f | PSR_x},
+ {"CPSR_csxf", TRUE, PSR_c | PSR_s | PSR_x | PSR_f},
+ {"CPSR_cxfs", TRUE, PSR_c | PSR_x | PSR_f | PSR_s},
+ {"CPSR_cxsf", TRUE, PSR_c | PSR_x | PSR_s | PSR_f},
+ {"SPSR_fs", FALSE, PSR_f | PSR_s},
+ {"SPSR_fx", FALSE, PSR_f | PSR_x},
+ {"SPSR_fc", FALSE, PSR_f | PSR_c},
+ {"SPSR_sf", FALSE, PSR_s | PSR_f},
+ {"SPSR_sx", FALSE, PSR_s | PSR_x},
+ {"SPSR_sc", FALSE, PSR_s | PSR_c},
+ {"SPSR_xf", FALSE, PSR_x | PSR_f},
+ {"SPSR_xs", FALSE, PSR_x | PSR_s},
+ {"SPSR_xc", FALSE, PSR_x | PSR_c},
+ {"SPSR_cf", FALSE, PSR_c | PSR_f},
+ {"SPSR_cs", FALSE, PSR_c | PSR_s},
+ {"SPSR_cx", FALSE, PSR_c | PSR_x},
+ {"SPSR_fsx", FALSE, PSR_f | PSR_s | PSR_x},
+ {"SPSR_fsc", FALSE, PSR_f | PSR_s | PSR_c},
+ {"SPSR_fxs", FALSE, PSR_f | PSR_x | PSR_s},
+ {"SPSR_fxc", FALSE, PSR_f | PSR_x | PSR_c},
+ {"SPSR_fcs", FALSE, PSR_f | PSR_c | PSR_s},
+ {"SPSR_fcx", FALSE, PSR_f | PSR_c | PSR_x},
+ {"SPSR_sfx", FALSE, PSR_s | PSR_f | PSR_x},
+ {"SPSR_sfc", FALSE, PSR_s | PSR_f | PSR_c},
+ {"SPSR_sxf", FALSE, PSR_s | PSR_x | PSR_f},
+ {"SPSR_sxc", FALSE, PSR_s | PSR_x | PSR_c},
+ {"SPSR_scf", FALSE, PSR_s | PSR_c | PSR_f},
+ {"SPSR_scx", FALSE, PSR_s | PSR_c | PSR_x},
+ {"SPSR_xfs", FALSE, PSR_x | PSR_f | PSR_s},
+ {"SPSR_xfc", FALSE, PSR_x | PSR_f | PSR_c},
+ {"SPSR_xsf", FALSE, PSR_x | PSR_s | PSR_f},
+ {"SPSR_xsc", FALSE, PSR_x | PSR_s | PSR_c},
+ {"SPSR_xcf", FALSE, PSR_x | PSR_c | PSR_f},
+ {"SPSR_xcs", FALSE, PSR_x | PSR_c | PSR_s},
+ {"SPSR_cfs", FALSE, PSR_c | PSR_f | PSR_s},
+ {"SPSR_cfx", FALSE, PSR_c | PSR_f | PSR_x},
+ {"SPSR_csf", FALSE, PSR_c | PSR_s | PSR_f},
+ {"SPSR_csx", FALSE, PSR_c | PSR_s | PSR_x},
+ {"SPSR_cxf", FALSE, PSR_c | PSR_x | PSR_f},
+ {"SPSR_cxs", FALSE, PSR_c | PSR_x | PSR_s},
+ {"SPSR_fsxc", FALSE, PSR_f | PSR_s | PSR_x | PSR_c},
+ {"SPSR_fscx", FALSE, PSR_f | PSR_s | PSR_c | PSR_x},
+ {"SPSR_fxsc", FALSE, PSR_f | PSR_x | PSR_s | PSR_c},
+ {"SPSR_fxcs", FALSE, PSR_f | PSR_x | PSR_c | PSR_s},
+ {"SPSR_fcsx", FALSE, PSR_f | PSR_c | PSR_s | PSR_x},
+ {"SPSR_fcxs", FALSE, PSR_f | PSR_c | PSR_x | PSR_s},
+ {"SPSR_sfxc", FALSE, PSR_s | PSR_f | PSR_x | PSR_c},
+ {"SPSR_sfcx", FALSE, PSR_s | PSR_f | PSR_c | PSR_x},
+ {"SPSR_sxfc", FALSE, PSR_s | PSR_x | PSR_f | PSR_c},
+ {"SPSR_sxcf", FALSE, PSR_s | PSR_x | PSR_c | PSR_f},
+ {"SPSR_scfx", FALSE, PSR_s | PSR_c | PSR_f | PSR_x},
+ {"SPSR_scxf", FALSE, PSR_s | PSR_c | PSR_x | PSR_f},
+ {"SPSR_xfsc", FALSE, PSR_x | PSR_f | PSR_s | PSR_c},
+ {"SPSR_xfcs", FALSE, PSR_x | PSR_f | PSR_c | PSR_s},
+ {"SPSR_xsfc", FALSE, PSR_x | PSR_s | PSR_f | PSR_c},
+ {"SPSR_xscf", FALSE, PSR_x | PSR_s | PSR_c | PSR_f},
+ {"SPSR_xcfs", FALSE, PSR_x | PSR_c | PSR_f | PSR_s},
+ {"SPSR_xcsf", FALSE, PSR_x | PSR_c | PSR_s | PSR_f},
+ {"SPSR_cfsx", FALSE, PSR_c | PSR_f | PSR_s | PSR_x},
+ {"SPSR_cfxs", FALSE, PSR_c | PSR_f | PSR_x | PSR_s},
+ {"SPSR_csfx", FALSE, PSR_c | PSR_s | PSR_f | PSR_x},
+ {"SPSR_csxf", FALSE, PSR_c | PSR_s | PSR_x | PSR_f},
+ {"SPSR_cxfs", FALSE, PSR_c | PSR_x | PSR_f | PSR_s},
+ {"SPSR_cxsf", FALSE, PSR_c | PSR_x | PSR_s | PSR_f},
};
enum vfp_dp_reg_pos
static void s_force_thumb PARAMS ((int));
static void s_thumb_func PARAMS ((int));
static void s_thumb_set PARAMS ((int));
-static void arm_s_text PARAMS ((int));
-static void arm_s_data PARAMS ((int));
#ifdef OBJ_ELF
-static void arm_s_section PARAMS ((int));
static void s_arm_elf_cons PARAMS ((int));
#endif
{ "even", s_even, 0 },
{ "ltorg", s_ltorg, 0 },
{ "pool", s_ltorg, 0 },
- /* Allow for the effect of section changes. */
- { "text", arm_s_text, 0 },
- { "data", arm_s_data, 0 },
#ifdef OBJ_ELF
- { "section", arm_s_section, 0 },
- { "section.s", arm_s_section, 0 },
- { "sect", arm_s_section, 0 },
- { "sect.s", arm_s_section, 0 },
{ "word", s_arm_elf_cons, 4 },
{ "long", s_arm_elf_cons, 4 },
- { "file", dwarf2_directive_file, 0 },
+ { "file", (void (*) PARAMS ((int))) dwarf2_directive_file, 0 },
{ "loc", dwarf2_directive_loc, 0 },
#else
{ "word", cons, 4},
*/
symbolS * last_label_seen;
-static int label_is_thumb_function_name = false;
+static int label_is_thumb_function_name = FALSE;
-/* Literal stuff. */
+/* Literal Pool stuff. */
#define MAX_LITERAL_POOL_SIZE 1024
-typedef struct literalS
+/* Literal pool structure. Held on a per-section
+ and per-sub-section basis. */
+typedef struct literal_pool
{
- struct expressionS exp;
- struct arm_it * inst;
-} literalT;
+ expressionS literals [MAX_LITERAL_POOL_SIZE];
+ unsigned int next_free_entry;
+ unsigned int id;
+ symbolS * symbol;
+ segT section;
+ subsegT sub_section;
+ struct literal_pool * next;
+} literal_pool;
+
+/* Pointer to a linked list of literal pools. */
+literal_pool * list_of_pools = NULL;
-literalT literals[MAX_LITERAL_POOL_SIZE];
+static literal_pool * find_literal_pool PARAMS ((void));
+static literal_pool * find_or_make_literal_pool PARAMS ((void));
-/* Next free entry in the pool. */
-int next_literal_pool_place = 0;
+static literal_pool *
+find_literal_pool ()
+{
+ literal_pool * pool;
-/* Next literal pool number. */
-int lit_pool_num = 1;
+ for (pool = list_of_pools; pool != NULL; pool = pool->next)
+ {
+ if (pool->section == now_seg
+ && pool->sub_section == now_subseg)
+ break;
+ }
-symbolS * current_poolP = NULL;
+ return pool;
+}
+static literal_pool *
+find_or_make_literal_pool ()
+{
+ /* Next literal pool ID number. */
+ static unsigned int latest_pool_num = 1;
+ literal_pool * pool;
+
+ pool = find_literal_pool ();
+
+ if (pool == NULL)
+ {
+ /* Create a new pool. */
+ pool = (literal_pool *) xmalloc (sizeof (* pool));
+ if (! pool)
+ return NULL;
+
+ pool->next_free_entry = 0;
+ pool->section = now_seg;
+ pool->sub_section = now_subseg;
+ pool->next = list_of_pools;
+ pool->symbol = NULL;
+
+ /* Add it to the list. */
+ list_of_pools = pool;
+ }
+
+ /* New pools, and emptied pools, will have a NULL symbol. */
+ if (pool->symbol == NULL)
+ {
+ pool->symbol = symbol_create (FAKE_LABEL_NAME, undefined_section,
+ (valueT) 0, &zero_address_frag);
+ pool->id = latest_pool_num ++;
+ }
+
+ /* Done. */
+ return pool;
+}
+
+/* Add the literal in the global 'inst'
+ structure to the relevent literal pool. */
static int
add_to_lit_pool ()
{
- int lit_count = 0;
+ literal_pool * pool;
+ unsigned int entry;
- if (current_poolP == NULL)
- current_poolP = symbol_create (FAKE_LABEL_NAME, undefined_section,
- (valueT) 0, &zero_address_frag);
+ pool = find_or_make_literal_pool ();
- /* Check if this literal value is already in the pool: */
- while (lit_count < next_literal_pool_place)
+ /* Check if this literal value is already in the pool. */
+ for (entry = 0; entry < pool->next_free_entry; entry ++)
{
- if (literals[lit_count].exp.X_op == inst.reloc.exp.X_op
- && inst.reloc.exp.X_op == O_constant
- && (literals[lit_count].exp.X_add_number
+ if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
+ && (inst.reloc.exp.X_op == O_constant)
+ && (pool->literals[entry].X_add_number
== inst.reloc.exp.X_add_number)
- && literals[lit_count].exp.X_unsigned == inst.reloc.exp.X_unsigned)
+ && (pool->literals[entry].X_unsigned
+ == inst.reloc.exp.X_unsigned))
break;
- if (literals[lit_count].exp.X_op == inst.reloc.exp.X_op
- && inst.reloc.exp.X_op == O_symbol
- && (literals[lit_count].exp.X_add_number
+ if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
+ && (inst.reloc.exp.X_op == O_symbol)
+ && (pool->literals[entry].X_add_number
== inst.reloc.exp.X_add_number)
- && (literals[lit_count].exp.X_add_symbol
+ && (pool->literals[entry].X_add_symbol
== inst.reloc.exp.X_add_symbol)
- && (literals[lit_count].exp.X_op_symbol
+ && (pool->literals[entry].X_op_symbol
== inst.reloc.exp.X_op_symbol))
- break;
-
- lit_count++;
+ break;
}
- if (lit_count == next_literal_pool_place) /* New entry. */
+ /* Do we need to create a new entry? */
+ if (entry == pool->next_free_entry)
{
- if (next_literal_pool_place >= MAX_LITERAL_POOL_SIZE)
+ if (entry >= MAX_LITERAL_POOL_SIZE)
{
inst.error = _("literal pool overflow");
return FAIL;
}
- literals[next_literal_pool_place].exp = inst.reloc.exp;
- lit_count = next_literal_pool_place++;
+ pool->literals[entry] = inst.reloc.exp;
+ pool->next_free_entry += 1;
}
- inst.reloc.exp.X_op = O_symbol;
- inst.reloc.exp.X_add_number = (lit_count) * 4 - 8;
- inst.reloc.exp.X_add_symbol = current_poolP;
+ inst.reloc.exp.X_op = O_symbol;
+ inst.reloc.exp.X_add_number = ((int) entry) * 4 - 8;
+ inst.reloc.exp.X_add_symbol = pool->symbol;
return SUCCESS;
}
S_SET_SEGMENT (symbolP, segment);
S_SET_VALUE (symbolP, valu);
- symbol_clear_list_pointers(symbolP);
+ symbol_clear_list_pointers (symbolP);
symbol_set_frag (symbolP, frag);
s_ltorg (ignored)
int ignored ATTRIBUTE_UNUSED;
{
- int lit_count = 0;
+ unsigned int entry;
+ literal_pool * pool;
char sym_name[20];
- if (current_poolP == NULL)
+ pool = find_literal_pool ();
+ if (pool == NULL
+ || pool->symbol == NULL
+ || pool->next_free_entry == 0)
return;
/* Align pool as you have word accesses.
record_alignment (now_seg, 2);
- sprintf (sym_name, "$$lit_\002%x", lit_pool_num++);
+ sprintf (sym_name, "$$lit_\002%x", pool->id);
- symbol_locate (current_poolP, sym_name, now_seg,
+ symbol_locate (pool->symbol, sym_name, now_seg,
(valueT) frag_now_fix (), frag_now);
- symbol_table_insert (current_poolP);
+ symbol_table_insert (pool->symbol);
- ARM_SET_THUMB (current_poolP, thumb_mode);
+ ARM_SET_THUMB (pool->symbol, thumb_mode);
#if defined OBJ_COFF || defined OBJ_ELF
- ARM_SET_INTERWORK (current_poolP, support_interwork);
+ ARM_SET_INTERWORK (pool->symbol, support_interwork);
#endif
- while (lit_count < next_literal_pool_place)
+ for (entry = 0; entry < pool->next_free_entry; entry ++)
/* First output the expression in the instruction to the pool. */
- emit_expr (&(literals[lit_count++].exp), 4); /* .word */
+ emit_expr (&(pool->literals[entry]), 4); /* .word */
- next_literal_pool_place = 0;
- current_poolP = NULL;
+ /* Mark the pool as empty. */
+ pool->next_free_entry = 0;
+ pool->symbol = NULL;
}
/* Same as s_align_ptwo but align 0 => align 2. */
/* The following label is the name/address of the start of a Thumb function.
We need to know this for the interworking support. */
- label_is_thumb_function_name = true;
+ label_is_thumb_function_name = TRUE;
demand_empty_rest_of_line ();
}
#endif
}
-/* If we change section we must dump the literal pool first. */
-
-static void
-arm_s_text (ignore)
- int ignore;
-{
- if (now_seg != text_section)
- s_ltorg (0);
-
-#ifdef OBJ_ELF
- obj_elf_text (ignore);
-#else
- s_text (ignore);
-#endif
-}
-
-static void
-arm_s_data (ignore)
- int ignore;
-{
- if (flag_readonly_data_in_text)
- {
- if (now_seg != text_section)
- s_ltorg (0);
- }
- else if (now_seg != data_section)
- s_ltorg (0);
-
-#ifdef OBJ_ELF
- obj_elf_data (ignore);
-#else
- s_data (ignore);
-#endif
-}
-
-#ifdef OBJ_ELF
-static void
-arm_s_section (ignore)
- int ignore;
-{
- s_ltorg (0);
-
- obj_elf_section (ignore);
-}
-#endif
-
static void
opcode_select (width)
int width;
str ++;
memset (& expr, '\0', sizeof (expr));
- if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
+ if (my_get_expression (& expr, & str)
+ || (expr.X_op != O_constant
+ /* As a convenience we allow 'bkpt' without an operand. */
+ && expr.X_op != O_absent))
{
- inst.error = _("bad or missing expression");
+ inst.error = _("bad expression");
return;
}
memset (& expr, '\0', sizeof (expr));
- if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
+ if (my_get_expression (& expr, & str)
+ || (expr.X_op != O_constant
+ /* As a convenience we allow 'bkpt' without an operand. */
+ && expr.X_op != O_absent))
{
- inst.error = _("bad or missing expression");
+ inst.error = _("bad expression");
return;
}
return -1;
}
-/* Return true if anything in the expression is a bignum. */
+/* Return TRUE if anything in the expression is a bignum. */
static int
walk_no_bignums (sp)
inst.instruction |= LDM_TYPE_2_OR_3;
}
+ if (inst.instruction & WRITE_BACK)
+ {
+ /* Check for unpredictable uses of writeback. */
+ if (inst.instruction & LOAD_BIT)
+ {
+ /* Not allowed in LDM type 2. */
+ if ((inst.instruction & LDM_TYPE_2_OR_3)
+ && ((range & (1 << REG_PC)) == 0))
+ as_warn (_("writeback of base register is UNPREDICTABLE"));
+ /* Only allowed if base reg not in list for other types. */
+ else if (range & (1 << base_reg))
+ as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
+ }
+ else /* STM. */
+ {
+ /* Not allowed for type 2. */
+ if (inst.instruction & LDM_TYPE_2_OR_3)
+ as_warn (_("writeback of base register is UNPREDICTABLE"));
+ /* Only allowed if base reg not in list, or first in list. */
+ else if ((range & (1 << base_reg))
+ && (range & ((1 << base_reg) - 1)))
+ as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
+ }
+ }
+
inst.instruction |= range;
end_of_line (str);
return;
/* Sanity check -- should have raised a parse error above. */
if (count == 0 || count > 32)
- abort();
+ abort ();
/* Final test -- the registers must be consecutive. */
while (count--)
/* Sanity check -- should have raised a parse error above. */
if (count == 0 || count > 16)
- abort();
+ abort ();
/* Final test -- the registers must be consecutive. */
while (count--)
}
static void
-vfp_sp_ldstm(str, ldstm_type)
+vfp_sp_ldstm (str, ldstm_type)
char *str;
enum vfp_ldstm_type ldstm_type;
{
}
static void
-vfp_dp_ldstm(str, ldstm_type)
+vfp_dp_ldstm (str, ldstm_type)
char *str;
enum vfp_ldstm_type ldstm_type;
{
/* Using VFP conventions (even if soft-float). */
if (cpu_variant & FPU_VFP_EXT_NONE) flags |= F_VFP_FLOAT;
+#if defined OBJ_ELF
+ if (cpu_variant & ARM_CEXT_MAVERICK)
+ {
+ flags ^= F_SOFT_FLOAT;
+ flags |= EF_ARM_MAVERICK_FLOAT;
+ }
+#endif
bfd_set_private_flags (stdoutput, flags);
/* Catch special cases. */
if (cpu_variant & ARM_CEXT_XSCALE)
mach = bfd_mach_arm_XScale;
+ else if (cpu_variant & ARM_CEXT_MAVERICK)
+ mach = bfd_mach_arm_ep9312;
else if (cpu_variant & ARM_EXT_V5E)
mach = bfd_mach_arm_5TE;
else if (cpu_variant & ARM_EXT_V5)
newimm |= (temp & 0xfffff000);
md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
+ fixP->fx_done = 1;
break;
case BFD_RELOC_ARM_ADRL_IMMEDIATE:
{
unsigned int highpart = 0;
unsigned int newinsn = 0xe1a00000; /* nop. */
+
newimm = validate_immediate (value);
temp = md_chars_to_number (buf, INSN_SIZE);
{
as_bad_where (fixP->fx_file, fixP->fx_line,
_("unable to compute ADRL instructions for PC offset of 0x%lx"),
- value);
+ (long) value);
break;
}
value = fixP->fx_offset;
#endif
value += diff;
+
if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
as_bad_where (fixP->fx_file, fixP->fx_line,
_("branch with link out of range"));
newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
- /* Remove bit zero of the adjusted offset. Bit zero can only be
- set if the upper insn is at a half-word boundary, since the
- destination address, an ARM instruction, must always be on a
- word boundary. The semantics of the BLX (1) instruction, however,
- are that bit zero in the offset must always be zero, and the
- corresponding bit one in the target address will be set from bit
- one of the source address. */
- newval2 &= ~1;
+ /* For a BLX instruction, make sure that the relocation is rounded up
+ to a word boundary. This follows the semantics of the instruction
+ which specifies that bit 1 of the target address will come from bit
+ 1 of the base address. */
+ newval2 = (newval2 + 1) & ~ 1;
md_number_to_chars (buf, newval, THUMB_SIZE);
md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
}
break;
#endif
- case BFD_RELOC_ARM_GOTPC:
- md_number_to_chars (buf, value, 4);
- break;
-
case BFD_RELOC_ARM_CP_OFF_IMM:
sign = value >= 0;
if (value < -1023 || value > 1023 || (value & 3))
if ((value + 2) & ~0x3fe)
as_bad_where (fixP->fx_file, fixP->fx_line,
- _("invalid offset, value too big (0x%08lX)"), value);
+ _("invalid offset, value too big (0x%08lX)"),
+ (long) value);
/* Round up, since pc will be rounded down. */
newval |= (value + 2) >> 2;
case 9: /* SP load/store. */
if (value & ~0x3fc)
as_bad_where (fixP->fx_file, fixP->fx_line,
- _("invalid offset, value too big (0x%08lX)"), value);
+ _("invalid offset, value too big (0x%08lX)"),
+ (long) value);
newval |= value >> 2;
break;
case 6: /* Word load/store. */
if (value & ~0x7c)
as_bad_where (fixP->fx_file, fixP->fx_line,
- _("invalid offset, value too big (0x%08lX)"), value);
+ _("invalid offset, value too big (0x%08lX)"),
+ (long) value);
newval |= value << 4; /* 6 - 2. */
break;
case 7: /* Byte load/store. */
if (value & ~0x1f)
as_bad_where (fixP->fx_file, fixP->fx_line,
- _("invalid offset, value too big (0x%08lX)"), value);
+ _("invalid offset, value too big (0x%08lX)"),
+ (long) value);
newval |= value << 6;
break;
case 8: /* Halfword load/store. */
if (value & ~0x3e)
as_bad_where (fixP->fx_file, fixP->fx_line,
- _("invalid offset, value too big (0x%08lX)"), value);
+ _("invalid offset, value too big (0x%08lX)"),
+ (long) value);
newval |= value << 5; /* 6 - 1. */
break;
case BFD_RELOC_ARM_LITERAL:
case BFD_RELOC_ARM_HWLITERAL:
- /* If this is called then the a literal has been referenced across
- a section boundary - possibly due to an implicit dump. */
+ /* If this is called then the a literal has
+ been referenced across a section boundary. */
as_bad_where (fixp->fx_file, fixp->fx_line,
- _("literal referenced across section boundary (Implicit dump?)"));
+ _("literal referenced across section boundary"));
return NULL;
#ifdef OBJ_ELF
case BFD_RELOC_ARM_IMMEDIATE:
as_bad_where (fixp->fx_file, fixp->fx_line,
- _("internal relocation (type %d) not fixed up (IMMEDIATE)"),
- fixp->fx_r_type);
+ _("internal relocation (type: IMMEDIATE) not fixed up"));
return NULL;
case BFD_RELOC_ARM_ADRL_IMMEDIATE:
case BFD_RELOC_ARM_OFFSET_IMM:
as_bad_where (fixp->fx_file, fixp->fx_line,
- _("internal_relocation (type %d) not fixed up (OFFSET_IMM)"),
- fixp->fx_r_type);
+ _("internal_relocation (type: OFFSET_IMM) not fixed up"));
return NULL;
default:
switch (fixp->fx_r_type)
{
- case BFD_RELOC_ARM_IMMEDIATE: type = "IMMEDIATE"; break;
- case BFD_RELOC_ARM_OFFSET_IMM: type = "OFFSET_IMM"; break;
case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
case BFD_RELOC_ARM_SWI: type = "SWI"; break;
}
#ifdef OBJ_ELF
- if (code == BFD_RELOC_32_PCREL
+ if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
&& GOT_symbol
&& fixp->fx_addsy == GOT_symbol)
{
-mthumb Start in Thumb mode
-mthumb-interwork Code supports ARM/Thumb interworking
- For now we will also provide support for
+ For now we will also provide support for:
-mapcs-32 32-bit Program counter
-mapcs-26 26-bit Program counter
*/
-CONST char * md_shortopts = "m:k";
+const char * md_shortopts = "m:k";
#ifdef ARM_BI_ENDIAN
#define OPTION_EB (OPTION_MD_BASE + 0)
void
arm_cleanup ()
{
- if (current_poolP == NULL)
- return;
+ literal_pool * pool;
- /* Put it at the end of text section. */
- subseg_set (text_section, 0);
- s_ltorg (0);
+ for (pool = list_of_pools; pool; pool = pool->next)
+ {
+ /* Put it at the end of the relevent section. */
+ subseg_set (pool->section, pool->sub_section);
+ s_ltorg (0);
+ }
}
void
THUMB_SET_FUNC (sym, 1);
- label_is_thumb_function_name = false;
+ label_is_thumb_function_name = FALSE;
}
}
return name;
}
-boolean
+#if defined OBJ_COFF || defined OBJ_ELF
+void
arm_validate_fix (fixP)
fixS * fixP;
{
&& ! THUMB_IS_FUNC (fixP->fx_addsy))
{
fixP->fx_addsy = find_real_start (fixP->fx_addsy);
- return true;
}
+}
+#endif
+
+int
+arm_force_relocation (fixp)
+ struct fix * fixp;
+{
+#if defined (OBJ_COFF) && defined (TE_PE)
+ if (fixp->fx_r_type == BFD_RELOC_RVA)
+ return 1;
+#endif
+#ifdef OBJ_ELF
+ if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
+ || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
+ || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
+ || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
+ return 1;
+#endif
- return false;
+ /* Resolve these relocations even if the symbol is extern or weak. */
+ if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
+ || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
+ return 0;
+
+ return generic_force_reloc (fixp);
}
#ifdef OBJ_COFF
be resolved before the binbary is emitted, so it is safe to say that
it is adjustable. */
-boolean
+bfd_boolean
arm_fix_adjustable (fixP)
fixS * fixP;
{
return 0;
}
#endif
+
#ifdef OBJ_ELF
/* Relocations against Thumb function names must be left unadjusted,
so that the linker can use this information to correctly set the
addresses also ought to have their bottom bit set (assuming that
they reside in Thumb code), but at the moment they will not. */
-boolean
+bfd_boolean
arm_fix_adjustable (fixP)
fixS * fixP;
{
if (fixP->fx_addsy == NULL)
return 1;
- /* Prevent all adjustments to global symbols. */
- if (S_IS_EXTERN (fixP->fx_addsy))
- return 0;
-
- if (S_IS_WEAK (fixP->fx_addsy))
- return 0;
-
if (THUMB_IS_FUNC (fixP->fx_addsy)
&& fixP->fx_subsy == NULL)
return 0;
|| fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
return 0;
+ /* Don't allow symbols to be discarded on GOT related relocs. */
+ if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
+ || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
+ || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF)
+ return 0;
+
return 1;
}
elf_frob_symbol (symp, puntp);
}
-int
-arm_force_relocation (fixp)
- struct fix * fixp;
-{
- if ( fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
- || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
- || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
- || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
- || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
- || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
- return 1;
-
- return 0;
-}
-
static bfd_reloc_code_real_type
arm_parse_reloc ()
{