mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-21 02:24:17 +08:00
Add support for more ARM processor names.
This commit is contained in:
@ -1,3 +1,11 @@
|
||||
Fri Dec 12 10:35:01 1997 Nick Clifton <nickc@cygnus.com>
|
||||
|
||||
* doc/c-arm.texi (ARM Options): Document support for new ARM
|
||||
processor names.
|
||||
|
||||
* config/tc-arm.c (md_parse_option): Add support for new ARM
|
||||
processor names.
|
||||
|
||||
Thu Dec 11 17:46:50 1997 Richard Henderson <rth@cygnus.com>
|
||||
|
||||
* config/tc-m68k.c (m68k_ip): Don't overwrite opcode table data.
|
||||
|
@ -51,8 +51,10 @@
|
||||
|
||||
/* The following bitmasks control CPU extensions (ARM7 onwards): */
|
||||
#define ARM_LONGMUL 0x00000010 /* allow long multiplies */
|
||||
#define ARM_ARCH4 0x00000020
|
||||
#define ARM_THUMB ARM_ARCH4
|
||||
#define ARM_HALFWORD 0x00000020 /* allow half word loads */
|
||||
#define ARM_THUMB 0x00000040 /* allow BX instruction */
|
||||
|
||||
#define ARM_ARCHv4 (ARM_7 | ARM_LONGMUL | ARM_HALFWORD)
|
||||
|
||||
/* Some useful combinations: */
|
||||
#define ARM_ANY 0x00ffffff
|
||||
@ -73,7 +75,7 @@
|
||||
|
||||
#ifndef CPU_DEFAULT
|
||||
#if defined __thumb__
|
||||
#define CPU_DEFAULT (ARM_7 | ARM_THUMB)
|
||||
#define CPU_DEFAULT (ARM_ARCHv4 | ARM_THUMB)
|
||||
#else
|
||||
#define CPU_DEFAULT ARM_ALL
|
||||
#endif
|
||||
@ -88,6 +90,9 @@ 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;
|
||||
static boolean support_interwork = false;
|
||||
static boolean uses_apcs_float = false;
|
||||
static boolean pic_code = false;
|
||||
#endif
|
||||
|
||||
/* This array holds the chars that always start a comment. If the
|
||||
@ -419,7 +424,7 @@ 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 unsigned validate_immediate PARAMS ((unsigned));
|
||||
static int validate_offset_imm PARAMS ((int, int));
|
||||
static void opcode_select PARAMS ((int));
|
||||
static void end_of_line PARAMS ((char *));
|
||||
@ -856,6 +861,8 @@ static void s_ltorg PARAMS ((int));
|
||||
static void s_arm PARAMS ((int));
|
||||
static void s_thumb PARAMS ((int));
|
||||
static void s_code PARAMS ((int));
|
||||
static void s_force_thumb PARAMS ((int));
|
||||
static void s_thumb_func PARAMS ((int));
|
||||
|
||||
static int my_get_expression PARAMS ((expressionS *, char **));
|
||||
|
||||
@ -867,6 +874,8 @@ CONST pseudo_typeS md_pseudo_table[] =
|
||||
{"arm", s_arm, 0},
|
||||
{"thumb", s_thumb, 0},
|
||||
{"code", s_code, 0},
|
||||
{"force_thumb", s_force_thumb, 0},
|
||||
{"thumb_func", s_thumb_func, 0},
|
||||
{"even", s_even, 0},
|
||||
{"ltorg", s_ltorg, 0},
|
||||
{"pool", s_ltorg, 0},
|
||||
@ -887,7 +896,8 @@ CONST pseudo_typeS md_pseudo_table[] =
|
||||
<insn>
|
||||
*/
|
||||
|
||||
symbolS *last_label_seen;
|
||||
symbolS * last_label_seen;
|
||||
static int label_is_thumb_function_name = false;
|
||||
|
||||
/* Literal stuff */
|
||||
|
||||
@ -928,7 +938,7 @@ add_to_lit_pool ()
|
||||
{
|
||||
if (next_literal_pool_place > MAX_LITERAL_POOL_SIZE)
|
||||
{
|
||||
inst.error = "Literal Pool Overflow\n";
|
||||
inst.error = "Literal Pool Overflow";
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
@ -1016,35 +1026,21 @@ symbol_make_empty ()
|
||||
return symbolP;
|
||||
}
|
||||
|
||||
/* Check that an immediate is valid, and if so, convert it to the right format
|
||||
*/
|
||||
/* Check that an immediate is valid, and if so, convert it to the right format. */
|
||||
|
||||
/* OH, for a rotate instruction in C! */
|
||||
|
||||
static int
|
||||
static unsigned int
|
||||
validate_immediate (val)
|
||||
int val;
|
||||
unsigned int val;
|
||||
{
|
||||
unsigned int a = (unsigned int) val;
|
||||
int i;
|
||||
|
||||
/* Do the easy (and most common ones) quickly */
|
||||
for (i = 0; i <= 24; i += 2)
|
||||
{
|
||||
if ((a & (0xff << i)) == a)
|
||||
return (int) (((32 - i) & 0x1e) << 7) | ((a >> i) & 0xff);
|
||||
}
|
||||
unsigned int a;
|
||||
unsigned int i;
|
||||
|
||||
/* Now do the harder ones */
|
||||
for (; i < 32; i += 2)
|
||||
{
|
||||
if ((a & ((0xff << i) | (0xff >> (32 - i)))) == a)
|
||||
{
|
||||
a = ((a >> i) & 0xff) | ((a << (32 - i)) & 0xff);
|
||||
return (int) a | (((32 - i) >> 1) << 8);
|
||||
}
|
||||
}
|
||||
return FAIL;
|
||||
#define rotate_left(v, n) (v << n | v >> (32 - n))
|
||||
|
||||
for (i = 0; i < 32; i += 2)
|
||||
if ((a = rotate_left (val, i)) <= 0xff)
|
||||
return a | (i << 7); /* 12-bit pack: [shift-cnt,const] */
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1117,6 +1113,9 @@ s_ltorg (internal)
|
||||
(valueT) frag_now_fix (), frag_now);
|
||||
symbol_table_insert (current_poolP);
|
||||
|
||||
ARM_SET_THUMB (current_poolP, thumb_mode);
|
||||
ARM_SET_INTERWORK (current_poolP, support_interwork);
|
||||
|
||||
while (lit_count < next_literal_pool_place)
|
||||
/* First output the expression in the instruction to the pool */
|
||||
emit_expr (&(literals[lit_count++].exp), 4); /* .word */
|
||||
@ -1175,6 +1174,38 @@ s_align (unused) /* Same as s_align_ptwo but align 0 => align 2 */
|
||||
record_alignment (now_seg, temp);
|
||||
}
|
||||
|
||||
static void
|
||||
s_force_thumb (ignore)
|
||||
int ignore;
|
||||
{
|
||||
/* If we are not already in thumb mode go into it, EVEN if
|
||||
the target processor does not support thumb instructions.
|
||||
This is used by gcc/config/arm/lib1funcs.asm for example
|
||||
to compile interworking support functions even if the
|
||||
target processor should not support interworking. */
|
||||
|
||||
if (! thumb_mode)
|
||||
{
|
||||
thumb_mode = 1;
|
||||
|
||||
record_alignment (now_seg, 1);
|
||||
}
|
||||
|
||||
demand_empty_rest_of_line ();
|
||||
}
|
||||
|
||||
static void
|
||||
s_thumb_func (ignore)
|
||||
int ignore;
|
||||
{
|
||||
/* 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;
|
||||
|
||||
demand_empty_rest_of_line();
|
||||
}
|
||||
|
||||
static void
|
||||
opcode_select (width)
|
||||
int width;
|
||||
@ -1702,7 +1733,7 @@ do_msr (str, flags)
|
||||
}
|
||||
else
|
||||
{
|
||||
int value = validate_immediate (inst.reloc.exp.X_add_number);
|
||||
unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
|
||||
if (value == FAIL)
|
||||
{
|
||||
inst.error = "Invalid constant";
|
||||
@ -2579,10 +2610,10 @@ do_ldst (str, flags)
|
||||
{
|
||||
/* This is actually a load/store of a halfword, or a
|
||||
signed-extension load */
|
||||
if ((cpu_variant & ARM_ARCH4) == 0)
|
||||
if ((cpu_variant & ARM_HALFWORD) == 0)
|
||||
{
|
||||
inst.error
|
||||
= "Processor does not support halfwords or signed bytes\n";
|
||||
= "Processor does not support halfwords or signed bytes";
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2730,7 +2761,7 @@ do_ldst (str, flags)
|
||||
if (add_to_lit_pool () == FAIL)
|
||||
{
|
||||
if (!inst.error)
|
||||
inst.error = "literal pool insertion failed\n";
|
||||
inst.error = "literal pool insertion failed";
|
||||
return;
|
||||
}
|
||||
|
||||
@ -3998,8 +4029,8 @@ thumb_mov_compare (str, move)
|
||||
if (Rs < 8 && Rd < 8)
|
||||
{
|
||||
if (move == THUMB_MOVE)
|
||||
/* A move of two lowregs is, by convention, encoded as
|
||||
ADD Rd, Rs, #0 */
|
||||
/* A move of two lowregs is encoded as ADD Rd, Rs, #0
|
||||
since a MOV instruction produces unpredictable results */
|
||||
inst.instruction = T_OPCODE_ADD_I3;
|
||||
else
|
||||
inst.instruction = T_OPCODE_CMP_LR;
|
||||
@ -4106,8 +4137,48 @@ thumb_load_store (str, load_store, size)
|
||||
}
|
||||
else if (*str == '=')
|
||||
{
|
||||
/* TODO: We should allow the "ldr Rd,=expr" pseudo op in thumb mode */
|
||||
abort ();
|
||||
/* Parse an "ldr Rd, =expr" instruction; this is another pseudo op */
|
||||
str++;
|
||||
|
||||
while (*str == ' ')
|
||||
str++;
|
||||
|
||||
if (my_get_expression (& inst.reloc.exp, & str))
|
||||
return;
|
||||
|
||||
end_of_line (str);
|
||||
|
||||
if ( inst.reloc.exp.X_op != O_constant
|
||||
&& inst.reloc.exp.X_op != O_symbol)
|
||||
{
|
||||
inst.error = "Constant expression expected";
|
||||
return;
|
||||
}
|
||||
|
||||
if (inst.reloc.exp.X_op == O_constant
|
||||
&& ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
|
||||
{
|
||||
/* This can be done with a mov instruction */
|
||||
|
||||
inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
|
||||
inst.instruction |= inst.reloc.exp.X_add_number;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Insert into literal pool */
|
||||
if (add_to_lit_pool () == FAIL)
|
||||
{
|
||||
if (!inst.error)
|
||||
inst.error = "literal pool insertion failed";
|
||||
return;
|
||||
}
|
||||
|
||||
inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
|
||||
inst.reloc.pc_rel = 1;
|
||||
inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
|
||||
inst.reloc.exp.X_add_number += 4; /* Adjust ARM pipeline offset to Thumb */
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -4566,7 +4637,7 @@ do_t_adr (str)
|
||||
while (*str == ' ')
|
||||
str++;
|
||||
|
||||
if (reg_required_here (&str, 4) == FAIL
|
||||
if (reg_required_here (&str, 4) == FAIL /* Store Rd in temporary location inside instruction. */
|
||||
|| skip_past_comma (&str) == FAIL
|
||||
|| my_get_expression (&inst.reloc.exp, &str))
|
||||
{
|
||||
@ -4636,7 +4707,7 @@ void
|
||||
md_begin ()
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
if ((arm_ops_hsh = hash_new ()) == NULL
|
||||
|| (arm_tops_hsh = hash_new ()) == NULL
|
||||
|| (arm_cond_hsh = hash_new ()) == NULL
|
||||
@ -4662,8 +4733,17 @@ md_begin ()
|
||||
set_constant_flonums ();
|
||||
|
||||
#ifdef OBJ_COFF
|
||||
/* Set the flags in the private structure */
|
||||
bfd_set_private_flags (stdoutput, uses_apcs_26 ? F_APCS26 : 0);
|
||||
{
|
||||
unsigned int flags = 0;
|
||||
|
||||
/* Set the flags in the private structure */
|
||||
if (uses_apcs_26) flags |= F_APCS26;
|
||||
if (support_interwork) flags |= F_INTERWORK;
|
||||
if (uses_apcs_float) flags |= F_APCS_FLOAT;
|
||||
if (pic_code) flags |= F_PIC;
|
||||
|
||||
bfd_set_private_flags (stdoutput, flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
@ -4695,7 +4775,7 @@ md_begin ()
|
||||
{
|
||||
if (cpu_variant & ARM_THUMB)
|
||||
mach = bfd_mach_arm_4T;
|
||||
else if (cpu_variant & ARM_ARCH4)
|
||||
else if ((cpu_variant & ARM_ARCHv4) == ARM_ARCHv4)
|
||||
mach = bfd_mach_arm_4;
|
||||
else if (cpu_variant & ARM_LONGMUL)
|
||||
mach = bfd_mach_arm_3M;
|
||||
@ -4846,6 +4926,14 @@ md_pcrel_from (fixP)
|
||||
&& fixP->fx_subsy == NULL)
|
||||
return 0; /* HACK */
|
||||
|
||||
if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
|
||||
{
|
||||
/* PC relative addressing on the Thumb is slightly odd
|
||||
as the bottom two bits of the PC are forced to zero
|
||||
for the calculation */
|
||||
return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
|
||||
}
|
||||
|
||||
return fixP->fx_where + fixP->fx_frag->fr_address;
|
||||
}
|
||||
|
||||
@ -4969,7 +5057,12 @@ md_apply_fix3 (fixP, val, seg)
|
||||
{
|
||||
if (S_IS_DEFINED (fixP->fx_addsy)
|
||||
&& S_GET_SEGMENT (fixP->fx_addsy) != seg)
|
||||
value += md_pcrel_from (fixP);
|
||||
{
|
||||
if (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH)
|
||||
value = 0;
|
||||
else
|
||||
value += md_pcrel_from (fixP);
|
||||
}
|
||||
}
|
||||
|
||||
fixP->fx_addnumber = value; /* Remember value for emit_reloc */
|
||||
@ -5244,7 +5337,9 @@ md_apply_fix3 (fixP, val, seg)
|
||||
break;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
as_bad_where (fixP->fx_file, fixP->fx_line,
|
||||
"Unable to process relocation for thumb opcode: %x", newval);
|
||||
break;
|
||||
}
|
||||
md_number_to_chars (buf, newval, THUMB_SIZE);
|
||||
break;
|
||||
@ -5404,60 +5499,40 @@ tc_gen_reloc (section, fixp)
|
||||
"Literal referenced across section boundry (Implicit dump?)");
|
||||
return NULL;
|
||||
|
||||
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);
|
||||
return NULL;
|
||||
|
||||
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);
|
||||
return NULL;
|
||||
|
||||
case BFD_RELOC_ARM_OFFSET_IMM8:
|
||||
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_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_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_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_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_where (fixp->fx_file, fixp->fx_line,
|
||||
"Internal_relocation (type %d) not fixed up (THUMB_OFFSET)",
|
||||
fixp->fx_r_type);
|
||||
return NULL;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
{
|
||||
char * type;
|
||||
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;
|
||||
case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
|
||||
case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
|
||||
case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
|
||||
case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
|
||||
case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
|
||||
case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
|
||||
default: type = "<unknown>"; break;
|
||||
}
|
||||
as_bad_where (fixp->fx_file, fixp->fx_line,
|
||||
"Can not represent %s relocation in this object file format (%d)",
|
||||
type, fixp->fx_pcrel);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
|
||||
assert (reloc->howto != 0);
|
||||
|
||||
if (reloc->howto == NULL)
|
||||
{
|
||||
as_bad_where (fixp->fx_file, fixp->fx_line,
|
||||
"Can not represent %s relocation in this object file format",
|
||||
bfd_get_reloc_code_name (code));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return reloc;
|
||||
}
|
||||
@ -5503,7 +5578,7 @@ output_inst (str)
|
||||
|
||||
if (inst.error)
|
||||
{
|
||||
as_bad ("%s -- statement `%s'\n", inst.error, str);
|
||||
as_bad (inst.error);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -5722,40 +5797,56 @@ md_assemble (str)
|
||||
|
||||
if (*q && !strncmp (q, ".req ", 4))
|
||||
{
|
||||
int reg;
|
||||
if ((reg = arm_reg_parse (&str)) == FAIL)
|
||||
{
|
||||
char *r;
|
||||
int reg;
|
||||
char * copy_of_str = str;
|
||||
char * r;
|
||||
|
||||
q += 4;
|
||||
while (*q == ' ')
|
||||
q++;
|
||||
q += 4;
|
||||
while (*q == ' ')
|
||||
q++;
|
||||
|
||||
for (r = q; *r != '\0'; r++)
|
||||
if (*r == ' ')
|
||||
break;
|
||||
for (r = q; *r != '\0'; r++)
|
||||
if (*r == ' ')
|
||||
break;
|
||||
|
||||
if (r != q)
|
||||
{
|
||||
int regnum;
|
||||
char d = *r;
|
||||
|
||||
if (r != q)
|
||||
*r = '\0';
|
||||
regnum = arm_reg_parse (& q);
|
||||
*r = d;
|
||||
|
||||
reg = arm_reg_parse (& str);
|
||||
|
||||
if (reg == FAIL)
|
||||
{
|
||||
int regnum;
|
||||
char d = *r;
|
||||
|
||||
*r = '\0';
|
||||
regnum = arm_reg_parse (&q);
|
||||
*r = d;
|
||||
if (regnum != FAIL)
|
||||
{
|
||||
insert_reg_alias (str, regnum);
|
||||
*p = c;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
as_warn ("register '%s' does not exist\n", q);
|
||||
}
|
||||
}
|
||||
else if (regnum != FAIL)
|
||||
{
|
||||
if (reg != regnum)
|
||||
as_warn ("ignoring redefinition of register alias '%s'", copy_of_str );
|
||||
|
||||
/* Do not warn abpout redefinitions to the same alias. */
|
||||
}
|
||||
else
|
||||
as_warn ("ignoring redefinition of register alias '%s' to non-existant register '%s'",
|
||||
copy_of_str, q);
|
||||
}
|
||||
else
|
||||
{
|
||||
*p = c;
|
||||
return;
|
||||
}
|
||||
as_warn ("ignoring incomplete .req pseuso op");
|
||||
|
||||
*p = c;
|
||||
return;
|
||||
}
|
||||
|
||||
*p = c;
|
||||
@ -5783,6 +5874,9 @@ md_assemble (str)
|
||||
* ARM Procedure Calling Standard:
|
||||
* -mapcs-32 32 bit APCS
|
||||
* -mapcs-26 26 bit APCS
|
||||
* -mapcs-float Pass floats in float regs
|
||||
* -mapcs-reentrant Position independent code
|
||||
* -mthumb-interwork Code supports Arm/Thumb interworking
|
||||
*/
|
||||
|
||||
CONST char *md_shortopts = "m:";
|
||||
@ -5843,6 +5937,13 @@ md_parse_option (c, arg)
|
||||
cpu_variant = (cpu_variant & ~FPU_ALL) | FPU_NONE;
|
||||
thumb_mode = 1;
|
||||
}
|
||||
else if (! strcmp (str, "thumb-interwork"))
|
||||
{
|
||||
cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_THUMB | ARM_ARCHv4;
|
||||
#ifdef OBJ_COFF
|
||||
support_interwork = true;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
goto bad;
|
||||
break;
|
||||
@ -5854,16 +5955,60 @@ md_parse_option (c, arg)
|
||||
return 1;
|
||||
}
|
||||
#ifdef OBJ_COFF
|
||||
if (! strcmp (str, "apcs-32"))
|
||||
if (! strncmp (str, "apcs-", 5))
|
||||
{
|
||||
uses_apcs_26 = false;
|
||||
return 1;
|
||||
}
|
||||
else if (! strcmp (str, "apcs-26"))
|
||||
{
|
||||
uses_apcs_26 = true;
|
||||
return 1;
|
||||
}
|
||||
/* GCC passes on all command line options starting "-mapcs-..."
|
||||
to us, so we must parse them here. */
|
||||
|
||||
str += 5;
|
||||
|
||||
if (! strcmp (str, "32"))
|
||||
{
|
||||
uses_apcs_26 = false;
|
||||
return 1;
|
||||
}
|
||||
else if (! strcmp (str, "26"))
|
||||
{
|
||||
uses_apcs_26 = true;
|
||||
return 1;
|
||||
}
|
||||
else if (! strcmp (str, "frame"))
|
||||
{
|
||||
/* Stack frames are being generated - does not affect
|
||||
linkage of code. */
|
||||
return 1;
|
||||
}
|
||||
else if (! strcmp (str, "stack-check"))
|
||||
{
|
||||
/* Stack checking is being performed - does not affect
|
||||
linkage, but does require that the functions
|
||||
__rt_stkovf_split_small and __rt_stkovf_split_big be
|
||||
present in the final link. */
|
||||
|
||||
return 1;
|
||||
}
|
||||
else if (! strcmp (str, "float"))
|
||||
{
|
||||
/* Floating point arguments are being passed in the floating
|
||||
point registers. This does affect linking, since this
|
||||
version of the APCS is incompatible with the version that
|
||||
passes floating points in the integer registers. */
|
||||
|
||||
uses_apcs_float = true;
|
||||
return 1;
|
||||
}
|
||||
else if (! strcmp (str, "reentrant"))
|
||||
{
|
||||
/* Reentrant code has been generated. This does affect
|
||||
linking, since there is no point in linking reentrant/
|
||||
position independent code with absolute position code. */
|
||||
pic_code = true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
as_bad ("Unrecognised APCS switch -m%s", arg);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
/* Strip off optional "arm" */
|
||||
if (! strncmp (str, "arm", 3))
|
||||
@ -5894,6 +6039,20 @@ md_parse_option (c, arg)
|
||||
goto bad;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
if (streq (str, "strongarm") || streq (str, "strongarm110"))
|
||||
cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_7 | ARM_ARCHv4 | ARM_LONGMUL;
|
||||
else
|
||||
goto bad;
|
||||
break;
|
||||
|
||||
case '8':
|
||||
if (streq (str, "8"))
|
||||
cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_7 | ARM_ARCHv4 | ARM_LONGMUL;
|
||||
else
|
||||
goto bad;
|
||||
break;
|
||||
|
||||
case '6':
|
||||
if (! strcmp (str, "6"))
|
||||
cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_6;
|
||||
@ -5906,20 +6065,26 @@ md_parse_option (c, arg)
|
||||
cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_7;
|
||||
for (; *str; str++)
|
||||
{
|
||||
switch (*str)
|
||||
switch (* str)
|
||||
{
|
||||
case 't':
|
||||
cpu_variant |= ARM_THUMB;
|
||||
cpu_variant |= (ARM_THUMB | ARM_ARCHv4);
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
cpu_variant |= ARM_LONGMUL;
|
||||
break;
|
||||
|
||||
case 'f': /* fe => fp enabled cpu. */
|
||||
if (str[1] == 'e')
|
||||
++ str;
|
||||
else
|
||||
goto bad;
|
||||
|
||||
case 'c': /* Unknown */
|
||||
case 'd': /* debug */
|
||||
case 'i': /* embedded ice */
|
||||
/* Included for completeness in ARM processor
|
||||
naming. */
|
||||
/* Included for completeness in ARM processor naming. */
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -5953,7 +6118,7 @@ md_parse_option (c, arg)
|
||||
break;
|
||||
|
||||
case '4':
|
||||
cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_7;
|
||||
cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_ARCHv4;
|
||||
|
||||
switch (*++str)
|
||||
{
|
||||
@ -5989,9 +6154,10 @@ md_show_usage (fp)
|
||||
FILE *fp;
|
||||
{
|
||||
fprintf (fp,
|
||||
"-m[arm][1|2|250|3|6|7[t][d][m][i]] select processor variant\n\
|
||||
"-m[arm][<processor name>] select processor variant\n\
|
||||
-m[arm]v[2|2a|3|3m|4|4t] select architecture variant\n\
|
||||
-mthumb\t\t\tonly allow Thumb instructions\n\
|
||||
-mthumb-interwork\tmark the assembled code as supporting interworking\n\
|
||||
-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\
|
||||
@ -5999,6 +6165,10 @@ md_show_usage (fp)
|
||||
#ifdef OBJ_COFF
|
||||
fprintf (fp,
|
||||
"-mapcs-32, -mapcs-26\tspecify which ARM Procedure Calling Standard is in use\n");
|
||||
fprintf (fp,
|
||||
"-mapcs-float\t\tfloating point args are passed in floating point regs\n");
|
||||
fprintf (fp,
|
||||
"-mapcs-reentrant\tposition independent/reentrant code has been generated\n");
|
||||
#endif
|
||||
#ifdef ARM_BI_ENDIAN
|
||||
fprintf (fp,
|
||||
@ -6074,7 +6244,20 @@ arm_frob_label (sym)
|
||||
symbolS *sym;
|
||||
{
|
||||
last_label_seen = sym;
|
||||
ARM_SET_TYPE(sym,thumb_mode);
|
||||
ARM_SET_THUMB (sym, thumb_mode);
|
||||
ARM_SET_INTERWORK (sym, support_interwork);
|
||||
|
||||
if (label_is_thumb_function_name)
|
||||
{
|
||||
/* When the address of a Thumb function is taken the bottom
|
||||
bit of that address should be set. This will allow
|
||||
interworking between Arm and Thumb functions to work
|
||||
correctly. */
|
||||
|
||||
THUMB_SET_FUNC (sym, 1);
|
||||
|
||||
label_is_thumb_function_name = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Adjust the symbol table. This marks Thumb symbols as distinct from
|
||||
@ -6088,9 +6271,20 @@ arm_adjust_symtab ()
|
||||
|
||||
for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
|
||||
{
|
||||
if (ARM_GET_TYPE(sym)) /* Thumb */
|
||||
if (ARM_IS_THUMB (sym))
|
||||
{
|
||||
switch (S_GET_STORAGE_CLASS (sym))
|
||||
if (THUMB_IS_FUNC (sym))
|
||||
{
|
||||
/* Mark the symbol as a Thumb function. */
|
||||
if ( S_GET_STORAGE_CLASS (sym) == C_STAT
|
||||
|| S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
|
||||
S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
|
||||
else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
|
||||
S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
|
||||
else
|
||||
as_bad ("%s: unexpected function type: %d", S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
|
||||
}
|
||||
else switch (S_GET_STORAGE_CLASS (sym))
|
||||
{
|
||||
case C_EXT:
|
||||
S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
|
||||
@ -6105,6 +6299,11 @@ arm_adjust_symtab ()
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ARM_IS_INTERWORK (sym))
|
||||
{
|
||||
coffsymbol(sym->bsym)->native->u.syment.n_flags = 0xFF;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
Reference in New Issue
Block a user