mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-22 11:00:01 +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>
|
Thu Dec 11 17:46:50 1997 Richard Henderson <rth@cygnus.com>
|
||||||
|
|
||||||
* config/tc-m68k.c (m68k_ip): Don't overwrite opcode table data.
|
* config/tc-m68k.c (m68k_ip): Don't overwrite opcode table data.
|
||||||
|
@ -51,8 +51,10 @@
|
|||||||
|
|
||||||
/* The following bitmasks control CPU extensions (ARM7 onwards): */
|
/* The following bitmasks control CPU extensions (ARM7 onwards): */
|
||||||
#define ARM_LONGMUL 0x00000010 /* allow long multiplies */
|
#define ARM_LONGMUL 0x00000010 /* allow long multiplies */
|
||||||
#define ARM_ARCH4 0x00000020
|
#define ARM_HALFWORD 0x00000020 /* allow half word loads */
|
||||||
#define ARM_THUMB ARM_ARCH4
|
#define ARM_THUMB 0x00000040 /* allow BX instruction */
|
||||||
|
|
||||||
|
#define ARM_ARCHv4 (ARM_7 | ARM_LONGMUL | ARM_HALFWORD)
|
||||||
|
|
||||||
/* Some useful combinations: */
|
/* Some useful combinations: */
|
||||||
#define ARM_ANY 0x00ffffff
|
#define ARM_ANY 0x00ffffff
|
||||||
@ -73,7 +75,7 @@
|
|||||||
|
|
||||||
#ifndef CPU_DEFAULT
|
#ifndef CPU_DEFAULT
|
||||||
#if defined __thumb__
|
#if defined __thumb__
|
||||||
#define CPU_DEFAULT (ARM_7 | ARM_THUMB)
|
#define CPU_DEFAULT (ARM_ARCHv4 | ARM_THUMB)
|
||||||
#else
|
#else
|
||||||
#define CPU_DEFAULT ARM_ALL
|
#define CPU_DEFAULT ARM_ALL
|
||||||
#endif
|
#endif
|
||||||
@ -88,6 +90,9 @@ static unsigned long cpu_variant = CPU_DEFAULT | FPU_DEFAULT;
|
|||||||
#ifdef OBJ_COFF
|
#ifdef OBJ_COFF
|
||||||
/* Flags stored in private area of BFD COFF structure */
|
/* Flags stored in private area of BFD COFF structure */
|
||||||
static boolean uses_apcs_26 = false;
|
static boolean uses_apcs_26 = false;
|
||||||
|
static boolean support_interwork = false;
|
||||||
|
static boolean uses_apcs_float = false;
|
||||||
|
static boolean pic_code = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* This array holds the chars that always start a comment. If the
|
/* 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,
|
static void symbol_locate PARAMS ((symbolS *, CONST char *, segT,
|
||||||
valueT, fragS *));
|
valueT, fragS *));
|
||||||
static int add_to_lit_pool PARAMS ((void));
|
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 int validate_offset_imm PARAMS ((int, int));
|
||||||
static void opcode_select PARAMS ((int));
|
static void opcode_select PARAMS ((int));
|
||||||
static void end_of_line PARAMS ((char *));
|
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_arm PARAMS ((int));
|
||||||
static void s_thumb PARAMS ((int));
|
static void s_thumb PARAMS ((int));
|
||||||
static void s_code 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 **));
|
static int my_get_expression PARAMS ((expressionS *, char **));
|
||||||
|
|
||||||
@ -867,6 +874,8 @@ CONST pseudo_typeS md_pseudo_table[] =
|
|||||||
{"arm", s_arm, 0},
|
{"arm", s_arm, 0},
|
||||||
{"thumb", s_thumb, 0},
|
{"thumb", s_thumb, 0},
|
||||||
{"code", s_code, 0},
|
{"code", s_code, 0},
|
||||||
|
{"force_thumb", s_force_thumb, 0},
|
||||||
|
{"thumb_func", s_thumb_func, 0},
|
||||||
{"even", s_even, 0},
|
{"even", s_even, 0},
|
||||||
{"ltorg", s_ltorg, 0},
|
{"ltorg", s_ltorg, 0},
|
||||||
{"pool", s_ltorg, 0},
|
{"pool", s_ltorg, 0},
|
||||||
@ -888,6 +897,7 @@ CONST pseudo_typeS md_pseudo_table[] =
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
symbolS * last_label_seen;
|
symbolS * last_label_seen;
|
||||||
|
static int label_is_thumb_function_name = false;
|
||||||
|
|
||||||
/* Literal stuff */
|
/* Literal stuff */
|
||||||
|
|
||||||
@ -928,7 +938,7 @@ add_to_lit_pool ()
|
|||||||
{
|
{
|
||||||
if (next_literal_pool_place > MAX_LITERAL_POOL_SIZE)
|
if (next_literal_pool_place > MAX_LITERAL_POOL_SIZE)
|
||||||
{
|
{
|
||||||
inst.error = "Literal Pool Overflow\n";
|
inst.error = "Literal Pool Overflow";
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1016,34 +1026,20 @@ symbol_make_empty ()
|
|||||||
return symbolP;
|
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 unsigned int
|
||||||
|
|
||||||
static int
|
|
||||||
validate_immediate (val)
|
validate_immediate (val)
|
||||||
int val;
|
unsigned int val;
|
||||||
{
|
{
|
||||||
unsigned int a = (unsigned int) val;
|
unsigned int a;
|
||||||
int i;
|
unsigned int i;
|
||||||
|
|
||||||
/* Do the easy (and most common ones) quickly */
|
#define rotate_left(v, n) (v << n | v >> (32 - n))
|
||||||
for (i = 0; i <= 24; i += 2)
|
|
||||||
{
|
|
||||||
if ((a & (0xff << i)) == a)
|
|
||||||
return (int) (((32 - i) & 0x1e) << 7) | ((a >> i) & 0xff);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now do the harder ones */
|
for (i = 0; i < 32; i += 2)
|
||||||
for (; i < 32; i += 2)
|
if ((a = rotate_left (val, i)) <= 0xff)
|
||||||
{
|
return a | (i << 7); /* 12-bit pack: [shift-cnt,const] */
|
||||||
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;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1117,6 +1113,9 @@ s_ltorg (internal)
|
|||||||
(valueT) frag_now_fix (), frag_now);
|
(valueT) frag_now_fix (), frag_now);
|
||||||
symbol_table_insert (current_poolP);
|
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)
|
while (lit_count < next_literal_pool_place)
|
||||||
/* First output the expression in the instruction to the pool */
|
/* First output the expression in the instruction to the pool */
|
||||||
emit_expr (&(literals[lit_count++].exp), 4); /* .word */
|
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);
|
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
|
static void
|
||||||
opcode_select (width)
|
opcode_select (width)
|
||||||
int width;
|
int width;
|
||||||
@ -1702,7 +1733,7 @@ do_msr (str, flags)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int value = validate_immediate (inst.reloc.exp.X_add_number);
|
unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
|
||||||
if (value == FAIL)
|
if (value == FAIL)
|
||||||
{
|
{
|
||||||
inst.error = "Invalid constant";
|
inst.error = "Invalid constant";
|
||||||
@ -2579,10 +2610,10 @@ do_ldst (str, flags)
|
|||||||
{
|
{
|
||||||
/* This is actually a load/store of a halfword, or a
|
/* This is actually a load/store of a halfword, or a
|
||||||
signed-extension load */
|
signed-extension load */
|
||||||
if ((cpu_variant & ARM_ARCH4) == 0)
|
if ((cpu_variant & ARM_HALFWORD) == 0)
|
||||||
{
|
{
|
||||||
inst.error
|
inst.error
|
||||||
= "Processor does not support halfwords or signed bytes\n";
|
= "Processor does not support halfwords or signed bytes";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2730,7 +2761,7 @@ do_ldst (str, flags)
|
|||||||
if (add_to_lit_pool () == FAIL)
|
if (add_to_lit_pool () == FAIL)
|
||||||
{
|
{
|
||||||
if (!inst.error)
|
if (!inst.error)
|
||||||
inst.error = "literal pool insertion failed\n";
|
inst.error = "literal pool insertion failed";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3998,8 +4029,8 @@ thumb_mov_compare (str, move)
|
|||||||
if (Rs < 8 && Rd < 8)
|
if (Rs < 8 && Rd < 8)
|
||||||
{
|
{
|
||||||
if (move == THUMB_MOVE)
|
if (move == THUMB_MOVE)
|
||||||
/* A move of two lowregs is, by convention, encoded as
|
/* A move of two lowregs is encoded as ADD Rd, Rs, #0
|
||||||
ADD Rd, Rs, #0 */
|
since a MOV instruction produces unpredictable results */
|
||||||
inst.instruction = T_OPCODE_ADD_I3;
|
inst.instruction = T_OPCODE_ADD_I3;
|
||||||
else
|
else
|
||||||
inst.instruction = T_OPCODE_CMP_LR;
|
inst.instruction = T_OPCODE_CMP_LR;
|
||||||
@ -4106,8 +4137,48 @@ thumb_load_store (str, load_store, size)
|
|||||||
}
|
}
|
||||||
else if (*str == '=')
|
else if (*str == '=')
|
||||||
{
|
{
|
||||||
/* TODO: We should allow the "ldr Rd,=expr" pseudo op in thumb mode */
|
/* Parse an "ldr Rd, =expr" instruction; this is another pseudo op */
|
||||||
abort ();
|
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
|
else
|
||||||
{
|
{
|
||||||
@ -4566,7 +4637,7 @@ do_t_adr (str)
|
|||||||
while (*str == ' ')
|
while (*str == ' ')
|
||||||
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
|
|| skip_past_comma (&str) == FAIL
|
||||||
|| my_get_expression (&inst.reloc.exp, &str))
|
|| my_get_expression (&inst.reloc.exp, &str))
|
||||||
{
|
{
|
||||||
@ -4662,8 +4733,17 @@ md_begin ()
|
|||||||
set_constant_flonums ();
|
set_constant_flonums ();
|
||||||
|
|
||||||
#ifdef OBJ_COFF
|
#ifdef OBJ_COFF
|
||||||
|
{
|
||||||
|
unsigned int flags = 0;
|
||||||
|
|
||||||
/* Set the flags in the private structure */
|
/* Set the flags in the private structure */
|
||||||
bfd_set_private_flags (stdoutput, uses_apcs_26 ? F_APCS26 : 0);
|
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
|
#endif
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -4695,7 +4775,7 @@ md_begin ()
|
|||||||
{
|
{
|
||||||
if (cpu_variant & ARM_THUMB)
|
if (cpu_variant & ARM_THUMB)
|
||||||
mach = bfd_mach_arm_4T;
|
mach = bfd_mach_arm_4T;
|
||||||
else if (cpu_variant & ARM_ARCH4)
|
else if ((cpu_variant & ARM_ARCHv4) == ARM_ARCHv4)
|
||||||
mach = bfd_mach_arm_4;
|
mach = bfd_mach_arm_4;
|
||||||
else if (cpu_variant & ARM_LONGMUL)
|
else if (cpu_variant & ARM_LONGMUL)
|
||||||
mach = bfd_mach_arm_3M;
|
mach = bfd_mach_arm_3M;
|
||||||
@ -4846,6 +4926,14 @@ md_pcrel_from (fixP)
|
|||||||
&& fixP->fx_subsy == NULL)
|
&& fixP->fx_subsy == NULL)
|
||||||
return 0; /* HACK */
|
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;
|
return fixP->fx_where + fixP->fx_frag->fr_address;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4969,8 +5057,13 @@ md_apply_fix3 (fixP, val, seg)
|
|||||||
{
|
{
|
||||||
if (S_IS_DEFINED (fixP->fx_addsy)
|
if (S_IS_DEFINED (fixP->fx_addsy)
|
||||||
&& S_GET_SEGMENT (fixP->fx_addsy) != seg)
|
&& S_GET_SEGMENT (fixP->fx_addsy) != seg)
|
||||||
|
{
|
||||||
|
if (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH)
|
||||||
|
value = 0;
|
||||||
|
else
|
||||||
value += md_pcrel_from (fixP);
|
value += md_pcrel_from (fixP);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fixP->fx_addnumber = value; /* Remember value for emit_reloc */
|
fixP->fx_addnumber = value; /* Remember value for emit_reloc */
|
||||||
|
|
||||||
@ -5244,7 +5337,9 @@ md_apply_fix3 (fixP, val, seg)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
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);
|
md_number_to_chars (buf, newval, THUMB_SIZE);
|
||||||
break;
|
break;
|
||||||
@ -5404,60 +5499,40 @@ tc_gen_reloc (section, fixp)
|
|||||||
"Literal referenced across section boundry (Implicit dump?)");
|
"Literal referenced across section boundry (Implicit dump?)");
|
||||||
return NULL;
|
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:
|
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);
|
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;
|
return reloc;
|
||||||
}
|
}
|
||||||
@ -5503,7 +5578,7 @@ output_inst (str)
|
|||||||
|
|
||||||
if (inst.error)
|
if (inst.error)
|
||||||
{
|
{
|
||||||
as_bad ("%s -- statement `%s'\n", inst.error, str);
|
as_bad (inst.error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5723,8 +5798,7 @@ md_assemble (str)
|
|||||||
if (*q && !strncmp (q, ".req ", 4))
|
if (*q && !strncmp (q, ".req ", 4))
|
||||||
{
|
{
|
||||||
int reg;
|
int reg;
|
||||||
if ((reg = arm_reg_parse (&str)) == FAIL)
|
char * copy_of_str = str;
|
||||||
{
|
|
||||||
char * r;
|
char * r;
|
||||||
|
|
||||||
q += 4;
|
q += 4;
|
||||||
@ -5743,20 +5817,37 @@ md_assemble (str)
|
|||||||
*r = '\0';
|
*r = '\0';
|
||||||
regnum = arm_reg_parse (& q);
|
regnum = arm_reg_parse (& q);
|
||||||
*r = d;
|
*r = d;
|
||||||
|
|
||||||
|
reg = arm_reg_parse (& str);
|
||||||
|
|
||||||
|
if (reg == FAIL)
|
||||||
|
{
|
||||||
if (regnum != FAIL)
|
if (regnum != FAIL)
|
||||||
{
|
{
|
||||||
insert_reg_alias (str, regnum);
|
insert_reg_alias (str, regnum);
|
||||||
*p = c;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
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
|
||||||
|
as_warn ("ignoring incomplete .req pseuso op");
|
||||||
|
|
||||||
*p = c;
|
*p = c;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
*p = c;
|
*p = c;
|
||||||
as_bad ("bad instruction `%s'", start);
|
as_bad ("bad instruction `%s'", start);
|
||||||
@ -5783,6 +5874,9 @@ md_assemble (str)
|
|||||||
* ARM Procedure Calling Standard:
|
* ARM Procedure Calling Standard:
|
||||||
* -mapcs-32 32 bit APCS
|
* -mapcs-32 32 bit APCS
|
||||||
* -mapcs-26 26 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:";
|
CONST char *md_shortopts = "m:";
|
||||||
@ -5843,6 +5937,13 @@ md_parse_option (c, arg)
|
|||||||
cpu_variant = (cpu_variant & ~FPU_ALL) | FPU_NONE;
|
cpu_variant = (cpu_variant & ~FPU_ALL) | FPU_NONE;
|
||||||
thumb_mode = 1;
|
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
|
else
|
||||||
goto bad;
|
goto bad;
|
||||||
break;
|
break;
|
||||||
@ -5854,16 +5955,60 @@ md_parse_option (c, arg)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#ifdef OBJ_COFF
|
#ifdef OBJ_COFF
|
||||||
if (! strcmp (str, "apcs-32"))
|
if (! strncmp (str, "apcs-", 5))
|
||||||
|
{
|
||||||
|
/* 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;
|
uses_apcs_26 = false;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else if (! strcmp (str, "apcs-26"))
|
else if (! strcmp (str, "26"))
|
||||||
{
|
{
|
||||||
uses_apcs_26 = true;
|
uses_apcs_26 = true;
|
||||||
return 1;
|
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
|
#endif
|
||||||
/* Strip off optional "arm" */
|
/* Strip off optional "arm" */
|
||||||
if (! strncmp (str, "arm", 3))
|
if (! strncmp (str, "arm", 3))
|
||||||
@ -5894,6 +6039,20 @@ md_parse_option (c, arg)
|
|||||||
goto bad;
|
goto bad;
|
||||||
break;
|
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':
|
case '6':
|
||||||
if (! strcmp (str, "6"))
|
if (! strcmp (str, "6"))
|
||||||
cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_6;
|
cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_6;
|
||||||
@ -5909,17 +6068,23 @@ md_parse_option (c, arg)
|
|||||||
switch (* str)
|
switch (* str)
|
||||||
{
|
{
|
||||||
case 't':
|
case 't':
|
||||||
cpu_variant |= ARM_THUMB;
|
cpu_variant |= (ARM_THUMB | ARM_ARCHv4);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'm':
|
case 'm':
|
||||||
cpu_variant |= ARM_LONGMUL;
|
cpu_variant |= ARM_LONGMUL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'f': /* fe => fp enabled cpu. */
|
||||||
|
if (str[1] == 'e')
|
||||||
|
++ str;
|
||||||
|
else
|
||||||
|
goto bad;
|
||||||
|
|
||||||
|
case 'c': /* Unknown */
|
||||||
case 'd': /* debug */
|
case 'd': /* debug */
|
||||||
case 'i': /* embedded ice */
|
case 'i': /* embedded ice */
|
||||||
/* Included for completeness in ARM processor
|
/* Included for completeness in ARM processor naming. */
|
||||||
naming. */
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -5953,7 +6118,7 @@ md_parse_option (c, arg)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '4':
|
case '4':
|
||||||
cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_7;
|
cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_ARCHv4;
|
||||||
|
|
||||||
switch (*++str)
|
switch (*++str)
|
||||||
{
|
{
|
||||||
@ -5989,9 +6154,10 @@ md_show_usage (fp)
|
|||||||
FILE *fp;
|
FILE *fp;
|
||||||
{
|
{
|
||||||
fprintf (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\
|
-m[arm]v[2|2a|3|3m|4|4t] select architecture variant\n\
|
||||||
-mthumb\t\t\tonly allow Thumb instructions\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\
|
-mall\t\t\tallow any instruction\n\
|
||||||
-mfpa10, -mfpa11\tselect floating point architecture\n\
|
-mfpa10, -mfpa11\tselect floating point architecture\n\
|
||||||
-mfpe-old\t\tdon't allow floating-point multiple instructions\n\
|
-mfpe-old\t\tdon't allow floating-point multiple instructions\n\
|
||||||
@ -5999,6 +6165,10 @@ md_show_usage (fp)
|
|||||||
#ifdef OBJ_COFF
|
#ifdef OBJ_COFF
|
||||||
fprintf (fp,
|
fprintf (fp,
|
||||||
"-mapcs-32, -mapcs-26\tspecify which ARM Procedure Calling Standard is in use\n");
|
"-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
|
#endif
|
||||||
#ifdef ARM_BI_ENDIAN
|
#ifdef ARM_BI_ENDIAN
|
||||||
fprintf (fp,
|
fprintf (fp,
|
||||||
@ -6074,7 +6244,20 @@ arm_frob_label (sym)
|
|||||||
symbolS *sym;
|
symbolS *sym;
|
||||||
{
|
{
|
||||||
last_label_seen = 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
|
/* 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))
|
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:
|
case C_EXT:
|
||||||
S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
|
S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
|
||||||
@ -6105,6 +6299,11 @@ arm_adjust_symtab ()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ARM_IS_INTERWORK (sym))
|
||||||
|
{
|
||||||
|
coffsymbol(sym->bsym)->native->u.syment.n_flags = 0xFF;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user