aboutsummaryrefslogtreecommitdiff
path: root/gas/config
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2009-04-01 14:02:57 +0000
committerNathan Sidwell <nathan@codesourcery.com>2009-04-01 14:02:57 +0000
commite7495e4595478f4547f3d2b0647514ae4221a692 (patch)
tree2e5cd474f54a25ca20fbbde8a882aa00312c45d2 /gas/config
parent42240548bff3ab683ff48c8eb0de53d1a9068aa4 (diff)
downloadgdb-e7495e4595478f4547f3d2b0647514ae4221a692.zip
gdb-e7495e4595478f4547f3d2b0647514ae4221a692.tar.gz
gdb-e7495e4595478f4547f3d2b0647514ae4221a692.tar.bz2
* config/tc-arm.c (do_nop): Generate v6k nops whenever possible.
(arm_handle_align): Generate v6k ARM, thumb2 wide & narrow nops whenever possible. testsuite/ * gas/arm/align.s, gas/arm/align.d: New. * gas/arm/thumb32.d, gas/arm/arch6zk.d, gas/arm/arch6zk.s, arm/thumb2_relax.d: Adjust for align changes.
Diffstat (limited to 'gas/config')
-rw-r--r--gas/config/tc-arm.c82
1 files changed, 63 insertions, 19 deletions
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index 98d8b7f..78215ab 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -7316,11 +7316,14 @@ do_mull (void)
static void
do_nop (void)
{
- if (inst.operands[0].present)
+ if (inst.operands[0].present
+ || ARM_CPU_HAS_FEATURE (selected_cpu, arm_ext_v6k))
{
/* Architectural NOP hints are CPSR sets with no bits selected. */
inst.instruction &= 0xf0000000;
- inst.instruction |= 0x0320f000 + inst.operands[0].imm;
+ inst.instruction |= 0x0320f000;
+ if (inst.operands[0].present)
+ inst.instruction |= inst.operands[0].imm;
}
}
@@ -17580,14 +17583,38 @@ md_section_align (segT segment ATTRIBUTE_UNUSED,
void
arm_handle_align (fragS * fragP)
{
- static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
- static char const thumb_noop[2] = { 0xc0, 0x46 };
- static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
- static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
-
- int bytes, fix, noop_size;
+ static char const arm_noop[2][2][4] =
+ {
+ { /* ARMv1 */
+ {0x00, 0x00, 0xa0, 0xe1}, /* LE */
+ {0xe1, 0xa0, 0x00, 0x00}, /* BE */
+ },
+ { /* ARMv6k */
+ {0x00, 0xf0, 0x20, 0xe3}, /* LE */
+ {0xe3, 0x20, 0xf0, 0x00}, /* BE */
+ },
+ };
+ static char const thumb_noop[2][2][2] =
+ {
+ { /* Thumb-1 */
+ {0xc0, 0x46}, /* LE */
+ {0x46, 0xc0}, /* BE */
+ },
+ { /* Thumb-2 */
+ {0x00, 0xbf}, /* LE */
+ {0xbf, 0x00} /* BE */
+ }
+ };
+ static char const wide_thumb_noop[2][4] =
+ { /* Wide Thumb-2 */
+ {0xaf, 0xf3, 0x00, 0x80}, /* LE */
+ {0xf3, 0xaf, 0x80, 0x00}, /* BE */
+ };
+
+ unsigned bytes, fix, noop_size;
char * p;
const char * noop;
+ const char *narrow_noop = NULL;
if (fragP->fr_type != rs_align_code)
return;
@@ -17603,21 +17630,24 @@ arm_handle_align (fragS * fragP)
if (fragP->tc_frag_data & (~ MODE_RECORDED))
{
- if (target_big_endian)
- noop = thumb_bigend_noop;
+ if (ARM_CPU_HAS_FEATURE (selected_cpu, arm_ext_v6t2))
+ {
+ narrow_noop = thumb_noop[1][target_big_endian];
+ noop = wide_thumb_noop[target_big_endian];
+ }
else
- noop = thumb_noop;
- noop_size = sizeof (thumb_noop);
+ noop = thumb_noop[0][target_big_endian];
+ noop_size = 2;
}
else
{
- if (target_big_endian)
- noop = arm_bigend_noop;
- else
- noop = arm_noop;
- noop_size = sizeof (arm_noop);
+ noop = arm_noop[ARM_CPU_HAS_FEATURE (selected_cpu, arm_ext_v6k) != 0]
+ [target_big_endian];
+ noop_size = 4;
}
-
+
+ fragP->fr_var = noop_size;
+
if (bytes & (noop_size - 1))
{
fix = bytes & (noop_size - 1);
@@ -17626,6 +17656,21 @@ arm_handle_align (fragS * fragP)
bytes -= fix;
}
+ if (narrow_noop)
+ {
+ if (bytes & noop_size)
+ {
+ /* Insert a narrow noop. */
+ memcpy (p, narrow_noop, noop_size);
+ p += noop_size;
+ bytes -= noop_size;
+ fix += noop_size;
+ }
+
+ /* Use wide noops for the remainder */
+ noop_size = 4;
+ }
+
while (bytes >= noop_size)
{
memcpy (p, noop, noop_size);
@@ -17635,7 +17680,6 @@ arm_handle_align (fragS * fragP)
}
fragP->fr_fix += fix;
- fragP->fr_var = noop_size;
}
/* Called from md_do_align. Used to create an alignment