#define FPU_ALL 0xff000000 /* Note this is ~ARM_ANY */
#define FPU_MEMMULTI 0x7f000000 /* Not fpu_core */
+
#ifndef CPU_DEFAULT
+#if defined __thumb__
+#define CPU_DEFAULT (ARM_7 | ARM_THUMB)
+#else
#define CPU_DEFAULT ARM_ALL
#endif
+#endif
#ifndef FPU_DEFAULT
#define FPU_DEFAULT FPU_ALL
static unsigned long cpu_variant = CPU_DEFAULT | FPU_DEFAULT;
+#ifdef OBJ_COFF
/* Flags stored in private area of BFD COFF structure */
static boolean uses_apcs_26 = false;
+#endif
/* This array holds the chars that always start a comment. If the
pre-processor is disabled, these aren't very useful */
int pc_rel, int reloc));
static int arm_reg_parse PARAMS ((char **ccp));
static int arm_psr_parse PARAMS ((char **ccp));
+static void symbol_locate PARAMS ((symbolS *, CONST char *, segT,
+ valueT, fragS *));
+static int add_to_lit_pool PARAMS ((void));
+static int validate_immediate PARAMS ((int));
+static int validate_offset_imm PARAMS ((int, int));
+static void opcode_select PARAMS ((int));
+static void end_of_line PARAMS ((char *));
+static int reg_required_here PARAMS ((char **, int));
+static int psr_required_here PARAMS ((char **, int));
+static int psrf_required_here PARAMS ((char **, int));
+static int co_proc_number PARAMS ((char **));
+static int cp_opc_expr PARAMS ((char **, int, int));
+static int cp_reg_required_here PARAMS ((char **, int));
+static int fp_reg_required_here PARAMS ((char **, int));
+static int cp_address_offset PARAMS ((char **));
+static int cp_address_required_here PARAMS ((char **));
+static int my_get_float_expression PARAMS ((char **));
+static int skip_past_comma PARAMS ((char **));
+static int walk_no_bignums PARAMS ((symbolS *));
+static int negate_data_op PARAMS ((unsigned long *,
+ unsigned long));
+static int data_op2 PARAMS ((char **));
+static int fp_op2 PARAMS ((char **));
+static long reg_list PARAMS ((char **));
+static void thumb_load_store PARAMS ((char *, int, int));
+static int decode_shift PARAMS ((char **, int));
+static int ldst_extend PARAMS ((char **, int));
+static void thumb_add_sub PARAMS ((char *, int));
+static void insert_reg PARAMS ((int));
+static void thumb_shift PARAMS ((char *, int));
+static void thumb_mov_compare PARAMS ((char *, int));
+static void set_constant_flonums PARAMS ((void));
+static valueT md_chars_to_number PARAMS ((char *, int));
+static void insert_reg_alias PARAMS ((char *, int));
+static void output_inst PARAMS ((char *));
/* ARM instructions take 4bytes in the object file, Thumb instructions
take 2: */
CONST char *comp_suffix; /* Compulsory suffix that must follow conds */
CONST struct asm_flg *flags; /* Bits to toggle if flag 'n' set */
unsigned long variants; /* Which CPU variants this exists for */
- void (*parms)(); /* Function to call to parse args */
+ /* Function to call to parse args */
+ void (*parms) PARAMS ((char *, unsigned long));
};
static CONST struct asm_opcode insns[] =
#define OPCODE_BIC 14
#define OPCODE_MVN 15
+static void do_t_nop PARAMS ((char *operands));
static void do_t_arit PARAMS ((char *operands));
static void do_t_add PARAMS ((char *operands));
static void do_t_asr PARAMS ((char *operands));
-static void do_t_branch PARAMS ((char *operands));
+static void do_t_branch9 PARAMS ((char *operands));
+static void do_t_branch12 PARAMS ((char *operands));
+static void do_t_branch23 PARAMS ((char *operands));
static void do_t_bx PARAMS ((char *operands));
static void do_t_compare PARAMS ((char *operands));
static void do_t_ldmstm PARAMS ((char *operands));
CONST char *template; /* Basic string to match */
unsigned long value; /* Basic instruction code */
int size;
- void (*parms)(); /* Function to call to parse args */
+ /* Function to call to parse args */
+ void (*parms) PARAMS ((char *));
};
static CONST struct thumb_opcode tinsns[] =
{"add", 0x0000, 2, do_t_add},
{"and", 0x4000, 2, do_t_arit},
{"asr", 0x0000, 2, do_t_asr},
- {"b", T_OPCODE_BRANCH, 2, do_t_branch},
- {"beq", 0xd0fe, 2, do_t_branch},
- {"bne", 0xd1fe, 2, do_t_branch},
- {"bcs", 0xd2fe, 2, do_t_branch},
- {"bhs", 0xd2fe, 2, do_t_branch},
- {"bcc", 0xd3fe, 2, do_t_branch},
- {"bul", 0xd3fe, 2, do_t_branch},
- {"blo", 0xd3fe, 2, do_t_branch},
- {"bmi", 0xd4fe, 2, do_t_branch},
- {"bpl", 0xd5fe, 2, do_t_branch},
- {"bvs", 0xd6fe, 2, do_t_branch},
- {"bvc", 0xd7fe, 2, do_t_branch},
- {"bhi", 0xd8fe, 2, do_t_branch},
- {"bls", 0xd9fe, 2, do_t_branch},
- {"bge", 0xdafe, 2, do_t_branch},
- {"blt", 0xdbfe, 2, do_t_branch},
- {"bgt", 0xdcfe, 2, do_t_branch},
- {"ble", 0xddfe, 2, do_t_branch},
+ {"b", T_OPCODE_BRANCH, 2, do_t_branch12},
+ {"beq", 0xd0fe, 2, do_t_branch9},
+ {"bne", 0xd1fe, 2, do_t_branch9},
+ {"bcs", 0xd2fe, 2, do_t_branch9},
+ {"bhs", 0xd2fe, 2, do_t_branch9},
+ {"bcc", 0xd3fe, 2, do_t_branch9},
+ {"bul", 0xd3fe, 2, do_t_branch9},
+ {"blo", 0xd3fe, 2, do_t_branch9},
+ {"bmi", 0xd4fe, 2, do_t_branch9},
+ {"bpl", 0xd5fe, 2, do_t_branch9},
+ {"bvs", 0xd6fe, 2, do_t_branch9},
+ {"bvc", 0xd7fe, 2, do_t_branch9},
+ {"bhi", 0xd8fe, 2, do_t_branch9},
+ {"bls", 0xd9fe, 2, do_t_branch9},
+ {"bge", 0xdafe, 2, do_t_branch9},
+ {"blt", 0xdbfe, 2, do_t_branch9},
+ {"bgt", 0xdcfe, 2, do_t_branch9},
+ {"ble", 0xddfe, 2, do_t_branch9},
{"bic", 0x4380, 2, do_t_arit},
- {"bl", 0xf7fffffe, 4, do_t_branch},
+ {"bl", 0xf7fffffe, 4, do_t_branch23},
{"bx", 0x4700, 2, do_t_bx},
{"cmn", T_OPCODE_CMN, 2, do_t_arit},
{"cmp", 0x0000, 2, do_t_compare},
{"tst", T_OPCODE_TST, 2, do_t_arit},
/* Pseudo ops: */
{"adr", 0x0000, 2, do_t_adr},
- {"nop", 0x0000, 2, do_nop},
+ {"nop", 0x46C0, 2, do_t_nop}, /* mov r8,r8 */
};
struct reg_entry
int next_literal_pool_place = 0; /* Next free entry in the pool */
int lit_pool_num = 1; /* Next literal pool number */
symbolS *current_poolP = NULL;
-symbolS *symbol_make_empty ();
+symbolS *symbol_make_empty PARAMS ((void));
static int
add_to_lit_pool ()
return SUCCESS;
}
-/* Can't use symbol_new here, so have to create a symbol and them at
+/* Can't use symbol_new here, so have to create a symbol and then at
a later date assign it a value. Thats what these functions do */
static void
symbol_locate (symbolP, name, segment, valu, frag)
return symbolP;
}
-
+
/* Check that an immediate is valid, and if so, convert it to the right format
*/
break;
default:
- as_bad ("invalid operand to .code directive (%d)", temp);
+ as_bad ("invalid operand to .code directive (%d) (expecting 16 or 32)", temp);
}
}
}
static int
-fp_op2 (str, flags)
+fp_op2 (str)
char **str;
- unsigned long flags;
{
while (**str == ' ')
(*str)++;
if (Rn != FAIL)
{
/* All register format. */
- if (Rd > 7 || Rs > 7 || Rd > 7)
+ if (Rd > 7 || Rs > 7 || Rn > 7)
{
if (Rs != Rd)
{
}
else if (*str == '=')
{
+ /* TODO: We should allow the "ldr Rd,=expr" pseudo op in thumb mode */
abort ();
}
else
inst.error = "Invalid offset";
return;
}
- inst.instruction |= offset << 6;
+ inst.instruction |= (offset >> size) << 6;
}
else
inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
end_of_line (str);
}
+static void
+do_t_nop (str)
+ char *str;
+{
+ /* Do nothing */
+ end_of_line (str);
+ return;
+}
+
/* Handle the Format 4 instructions that do not have equivalents in other
formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
BIC and MVN. */
}
static void
-do_t_branch (str)
+do_t_branch9 (str)
char *str;
{
if (my_get_expression (&inst.reloc.exp, &str))
return;
- inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
+ inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
+ inst.reloc.pc_rel = 1;
+ end_of_line (str);
+}
+
+static void
+do_t_branch12 (str)
+ char *str;
+{
+ if (my_get_expression (&inst.reloc.exp, &str))
+ return;
+ inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
+ inst.reloc.pc_rel = 1;
+ end_of_line (str);
+}
+
+static void
+do_t_branch23 (str)
+ char *str;
+{
+ if (my_get_expression (&inst.reloc.exp, &str))
+ return;
+ inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
inst.reloc.pc_rel = 1;
end_of_line (str);
}
char *str;
{
/* This is a pseudo-op of the form "adr rd, label" to be converted
- into a relative address of the form "add rd, pc, #label-.-8" */
+ into a relative address of the form "add rd, pc, #label-.-4" */
while (*str == ' ')
str++;
}
inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
- inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
+ inst.reloc.exp.X_add_number -= 4; /* PC relative adjust */
inst.reloc.pc_rel = 1;
inst.instruction |= REG_PC; /* Rd is already placed into the instruction */
end_of_line (str);
#ifdef OBJ_COFF
/* Set the flags in the private structure */
- coff_arm_bfd_set_private_flags (stdoutput, uses_apcs_26 ? F_APCS26 : 0);
+ bfd_set_private_flags (stdoutput, uses_apcs_26 ? F_APCS26 : 0);
#endif
{
default:
case ARM_6 | ARM_3 | ARM_2: /* Actually no CPU type defined */
+ mach = bfd_mach_arm_4;
+ break;
+
case ARM_7: /* also ARM_6 */
mach = bfd_mach_arm_3;
break;
}
/* Catch special cases */
- if (cpu_variant & ARM_THUMB)
- mach = bfd_mach_arm_4T;
- else if (cpu_variant & ARM_LONGMUL)
- mach = bfd_mach_arm_3M;
- else if (cpu_variant & ARM_ARCH4)
- mach = bfd_mach_arm_4;
+ if (cpu_variant != (FPU_DEFAULT | CPU_DEFAULT))
+ {
+ if (cpu_variant & ARM_THUMB)
+ mach = bfd_mach_arm_4T;
+ else if (cpu_variant & ARM_ARCH4)
+ mach = bfd_mach_arm_4;
+ else if (cpu_variant & ARM_LONGMUL)
+ mach = bfd_mach_arm_3M;
+ }
bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
}
assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
/* Note whether this will delete the relocation. */
+#if 0 /* patch from REarnshaw to JDavis (disabled for the moment, since it doesn't work fully) */
+ if ((fixP->fx_addsy == 0 || fixP->fx_addsy->sy_value.X_op == O_constant)
+ && !fixP->fx_pcrel)
+#else
if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
+#endif
fixP->fx_done = 1;
/* If this symbol is in a different section then we need to leave it for
break;
case BFD_RELOC_ARM_PCREL_BRANCH:
- if (arm_data->thumb_mode)
- {
- unsigned long newval2;
- newval = md_chars_to_number (buf, THUMB_SIZE);
- if (fixP->fx_size == 4)
- {
- unsigned long diff;
-
- newval2 = md_chars_to_number (buf, THUMB_SIZE);
- diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
- if (diff & 0x400000)
- diff |= ~0x3fffff;
- value += diff;
- if ((value & 0x400000) && ((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);
- md_number_to_chars (buf, newval, THUMB_SIZE);
- md_number_to_chars (buf, newval2, THUMB_SIZE);
- }
- else
- {
- if (newval == T_OPCODE_BRANCH)
- {
- unsigned long diff = (newval & 0x7ff) << 1;
- if (diff & 0x800)
- diff |= ~0x7ff;
-
- value += diff;
- if ((value & 0x800) && ((value & ~0x7ff) != ~0x7ff))
- as_bad_where (fixP->fx_file, fixP->fx_line,
- "Branch out of range");
- newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
- }
- else
- {
- unsigned long diff = (newval & 0xff) << 1;
- if (diff & 0x100)
- diff |= ~0xff;
-
- value += diff;
- if ((value & 0x100) && ((value & ~0xff) != ~0xff))
- as_bad_where (fixP->fx_file, fixP->fx_line,
- "Branch out of range");
- newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
- }
- md_number_to_chars (buf, newval, THUMB_SIZE);
- }
- }
- else
- {
- value = (value >> 2) & 0x00ffffff;
- newval = md_chars_to_number (buf, INSN_SIZE);
- value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
- newval = value | (newval & 0xff000000);
- md_number_to_chars (buf, newval, INSN_SIZE);
- }
+ value = (value >> 2) & 0x00ffffff;
+ newval = md_chars_to_number (buf, INSN_SIZE);
+ value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
+ newval = value | (newval & 0xff000000);
+ md_number_to_chars (buf, newval, INSN_SIZE);
+ break;
+
+ case BFD_RELOC_THUMB_PCREL_BRANCH9: /* conditional branch */
+ newval = md_chars_to_number (buf, THUMB_SIZE);
+ {
+ addressT diff = (newval & 0xff) << 1;
+ if (diff & 0x100)
+ diff |= ~0xff;
+
+ value += diff;
+ if ((value & 0x100) && ((value & ~0xff) != ~0xff))
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ "Branch out of range");
+ newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
+ }
+ md_number_to_chars (buf, newval, THUMB_SIZE);
+ break;
+
+ case BFD_RELOC_THUMB_PCREL_BRANCH12: /* unconditional branch */
+ newval = md_chars_to_number (buf, THUMB_SIZE);
+ {
+ addressT diff = (newval & 0x7ff) << 1;
+ if (diff & 0x800)
+ diff |= ~0x7ff;
+
+ value += diff;
+ if ((value & 0x800) && ((value & ~0x7ff) != ~0x7ff))
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ "Branch out of range");
+ newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
+ }
+ md_number_to_chars (buf, newval, THUMB_SIZE);
+ break;
+
+ case BFD_RELOC_THUMB_PCREL_BRANCH23:
+ newval = md_chars_to_number (buf, THUMB_SIZE);
+ {
+ offsetT newval2;
+ addressT diff;
+
+ newval2 = md_chars_to_number (buf + 2, THUMB_SIZE);
+ diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
+ if (diff & 0x400000)
+ diff |= ~0x3fffff;
+ value += diff;
+ if ((value & 0x400000) && ((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);
+ md_number_to_chars (buf, newval, THUMB_SIZE);
+ md_number_to_chars (buf + 2, newval2, THUMB_SIZE);
+ }
break;
case BFD_RELOC_8:
switch (newval >> 12)
{
case 4: /* PC load */
- /* PC loads are somewhat odd, bit 2 of the PC is forced to zero
- for these loads, so we may need to round up the offset if the
- instruction is not word aligned since the final address must
- be. */
+ /* Thumb PC loads are somewhat odd, bit 1 of the PC is
+ forced to zero for these loads, so we will need to round
+ up the offset if the instruction address is not word
+ aligned (since the final address produced must be, and
+ we can only describe word-aligned immediate offsets). */
if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
as_bad_where (fixP->fx_file, fixP->fx_line,
- "Invalid offset, target not word aligned");
+ "Invalid offset, target not word aligned (0x%08X)",
+ (unsigned int)(fixP->fx_frag->fr_address + fixP->fx_where + value));
if ((value + 2) & ~0x3fe)
as_bad_where (fixP->fx_file, fixP->fx_line,
"Invalid offset");
- /* Round up, since pc will be rounded down. */
+
+ /* Round up, since pc will be rounded down. */
newval |= (value + 2) >> 2;
break;
case BFD_RELOC_ARM_PCREL_BRANCH:
case BFD_RELOC_RVA:
+ case BFD_RELOC_THUMB_PCREL_BRANCH9:
+ case BFD_RELOC_THUMB_PCREL_BRANCH12:
+ case BFD_RELOC_THUMB_PCREL_BRANCH23:
code = fixp->fx_r_type;
break;
case BFD_RELOC_ARM_HWLITERAL:
/* If this is called then the a literal has been referenced across
a section boundry - possibly due to an implicit dump */
- as_bad ("Literal referenced across section boundry (Implicit dump?)");
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ "Literal referenced across section boundry (Implicit dump?)");
return NULL;
case BFD_RELOC_ARM_IMMEDIATE:
- as_bad ("Internal_relocation (type %d) not fixed up (IMMEDIATE)"
- , fixp->fx_r_type);
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ "Internal_relocation (type %d) not fixed up (IMMEDIATE)",
+ fixp->fx_r_type);
return NULL;
case BFD_RELOC_ARM_OFFSET_IMM:
- as_bad ("Internal_relocation (type %d) not fixed up (OFFSET_IMM)"
- , fixp->fx_r_type);
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ "Internal_relocation (type %d) not fixed up (OFFSET_IMM)",
+ fixp->fx_r_type);
return NULL;
case BFD_RELOC_ARM_OFFSET_IMM8:
- as_bad ("Internal_relocation (type %d) not fixed up (OFFSET_IMM8)"
- , fixp->fx_r_type);
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ "Internal_relocation (type %d) not fixed up (OFFSET_IMM8)",
+ fixp->fx_r_type);
return NULL;
case BFD_RELOC_ARM_SHIFT_IMM:
- as_bad ("Internal_relocation (type %d) not fixed up (SHIFT_IMM)"
- , fixp->fx_r_type);
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ "Internal_relocation (type %d) not fixed up (SHIFT_IMM)",
+ fixp->fx_r_type);
return NULL;
case BFD_RELOC_ARM_SWI:
- as_bad ("Internal_relocation (type %d) not fixed up (SWI)"
- , fixp->fx_r_type);
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ "Internal_relocation (type %d) not fixed up (SWI)",
+ fixp->fx_r_type);
return NULL;
case BFD_RELOC_ARM_MULTI:
- as_bad ("Internal_relocation (type %d) not fixed up (MULTI)"
- , fixp->fx_r_type);
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ "Internal_relocation (type %d) not fixed up (MULTI)",
+ fixp->fx_r_type);
return NULL;
case BFD_RELOC_ARM_CP_OFF_IMM:
- as_bad ("Internal_relocation (type %d) not fixed up (CP_OFF_IMM)"
- , fixp->fx_r_type);
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ "Internal_relocation (type %d) not fixed up (CP_OFF_IMM)",
+ fixp->fx_r_type);
return NULL;
case BFD_RELOC_ARM_THUMB_OFFSET:
- as_bad ("Internal_relocation (type %d) not fixed up (THUMB_OFFSET)"
- , fixp->fx_r_type);
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ "Internal_relocation (type %d) not fixed up (THUMB_OFFSET)",
+ fixp->fx_r_type);
return NULL;
default:
return (1);
}
-void
+static void
output_inst (str)
char *str;
{
}
to = frag_more (inst.size);
- if (thumb_mode && (inst.size > 2))
+ if (thumb_mode && (inst.size > THUMB_SIZE))
{
- md_number_to_chars (to, inst.instruction >> 16, 2);
- to += 2;
- inst.size = 2;
+ assert (inst.size == (2 * THUMB_SIZE));
+ md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
+ md_number_to_chars (to + 2, inst.instruction, THUMB_SIZE);
}
-
- md_number_to_chars (to, inst.instruction, inst.size);
+ else
+ md_number_to_chars (to, inst.instruction, inst.size);
if (inst.reloc.type != BFD_RELOC_NONE)
fix_new_arm (frag_now, to - frag_now->fr_literal,
cpu_variant = ARM_ALL | FPU_ALL;
return 1;
}
- else if (! strcmp( str, "apcs-32" ))
+#ifdef OBJ_COFF
+ if (! strcmp (str, "apcs-32"))
{
uses_apcs_26 = false;
return 1;
}
- else if (! strcmp( str, "apcs-26" ))
+ else if (! strcmp (str, "apcs-26"))
{
uses_apcs_26 = true;
return 1;
}
-
+#endif
/* Strip off optional "arm" */
if (! strncmp (str, "arm", 3))
str += 3;
{
case 'a': cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_3; break;
case 0: cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_2; break;
- default: as_bad( "Invalid architecture variant -m%s", arg ); break;
+ default: as_bad ("Invalid architecture variant -m%s", arg); break;
}
break;
{
case 'm': cpu_variant |= ARM_LONGMUL; break;
case 0: break;
- default: as_bad( "Invalid architecture variant -m%s", arg ); break;
+ default: as_bad ("Invalid architecture variant -m%s", arg); break;
}
break;
{
case 't': cpu_variant |= ARM_THUMB; break;
case 0: break;
- default: as_bad( "Invalid architecture variant -m%s", arg ); break;
+ default: as_bad ("Invalid architecture variant -m%s", arg); break;
}
break;
default:
- as_bad( "Invalid architecture variant -m%s", arg );
+ as_bad ("Invalid architecture variant -m%s", arg);
break;
}
break;
-mall\t\t\tallow any instruction\n\
-mfpa10, -mfpa11\tselect floating point architecture\n\
-mfpe-old\t\tdon't allow floating-point multiple instructions\n\
--mno-fpu\t\tdon't allow any floating-point instructions.\n\
--mapcs-32, -mapcs-26\tspecify which ARM Procedure Calling Standard is in use\n");
+-mno-fpu\t\tdon't allow any floating-point instructions.\n");
+#ifdef OBJ_COFF
+ fprintf (fp,
+"-mapcs-32, -mapcs-26\tspecify which ARM Procedure Calling Standard is in use\n");
+#endif
#ifdef ARM_BI_ENDIAN
fprintf (fp,
"-EB\t\t\tassemble code for a big endian cpu\n\
* for this kind of use. We need to dump the literal pool before
* references are made to a null symbol pointer. */
void
-arm_after_pass_hook (ignore)
- asection *ignore;
+arm_after_pass_hook ()
{
if (current_poolP != NULL)
{
symbolS *sym;
{
last_label_seen = sym;
+ ARM_SET_TYPE(sym,thumb_mode);
+}
+
+/* Adjust the symbol table. This marks Thumb symbols as distinct from
+ ARM ones. */
+
+void
+arm_adjust_symtab ()
+{
+ symbolS *sym;
+
+ for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
+ {
+ if (ARM_GET_TYPE(sym)) /* Thumb */
+ {
+ switch (S_GET_STORAGE_CLASS (sym))
+ {
+ case C_EXT:
+ S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
+ break;
+ case C_STAT:
+ S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
+ break;
+ case C_LABEL:
+ S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
+ break;
+ default: /* do nothing */
+ break;
+ }
+ }
+ }
+
+ return;
}
int