From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 8596 invoked by alias); 9 Aug 2007 15:11:19 -0000 Received: (qmail 8441 invoked by uid 22791); 9 Aug 2007 15:11:16 -0000 X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (65.74.133.4) by sourceware.org (qpsmtpd/0.31) with ESMTP; Thu, 09 Aug 2007 15:11:07 +0000 Received: (qmail 24708 invoked from network); 9 Aug 2007 15:11:05 -0000 Received: from unknown (HELO 85-210-151-93.dsl.pipex.com) (paul@127.0.0.2) by mail.codesourcery.com with ESMTPA; 9 Aug 2007 15:11:05 -0000 From: Paul Brook To: binutils@sourceware.org Subject: Improve Thumb-2 relaxation algorithm. Date: Thu, 09 Aug 2007 15:11:00 -0000 User-Agent: KMail/1.9.7 MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline Message-Id: <200708091611.02015.paul@codesourcery.com> Mailing-List: contact binutils-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: binutils-owner@sourceware.org X-SW-Source: 2007-08/txt/msg00128.txt.bz2 The Thumb-2 assembly relaxation code contains logic to terminate relaxation if it looks like conflicting alignment requirements may cause an infinite loop. However the code to calculate offsets during relaxation does not compensate for alignment directives, which leads to false positives if previous relaxations changes moved the target symbol. The patch below borrows code from the mips assembler to help maintain proper alignment during relaxation. The old behaviour isn't wrong per se, just generated unnecessarily large code. Tested on arm-none-eabi. Applied to cvs head. Paul 2007-08-09 Paul Brook gas/ * config/tc-arm.c (relaxed_symbol_addr): Compensate for alignment. gas/testsuite/ * gas/arm/relax_load_align.d: new test. * gas/arm/relax_load_align.s: new test. Index: gas/testsuite/gas/arm/relax_load_align.d =================================================================== --- gas/testsuite/gas/arm/relax_load_align.d (revision 0) +++ gas/testsuite/gas/arm/relax_load_align.d (revision 0) @@ -0,0 +1,9 @@ +# as: -march=armv6kt2 +# objdump: -dr --prefix-addresses --show-raw-insn + +.*: +file format .*arm.* + +Disassembly of section .text: +0+000 <[^>]+> f510 707a adds.w r0, r0, #1000 ; 0x3e8 +0+004 <[^>]+> 4800 ldr r0, \[pc, #0\] \(0+008 <[^>]+>\) +0+006 <[^>]+> 4800 ldr r0, \[pc, #0\] \(0+008 <[^>]+>\) Index: gas/testsuite/gas/arm/relax_load_align.s =================================================================== --- gas/testsuite/gas/arm/relax_load_align.s (revision 0) +++ gas/testsuite/gas/arm/relax_load_align.s (revision 0) @@ -0,0 +1,12 @@ +@ The relaxation algorithm used to not compensate for alignment statements. +@ The early termination to avoid infinite looping would make the second load +@ a wide instruction. + .text + .thumb + .syntax unified +fn: + adds r0, r0, #1000 + ldr r0, 1f + ldr r0, 1f +.align 2 +1: Index: gas/config/tc-arm.c =================================================================== --- gas/config/tc-arm.c (revision 178502) +++ gas/config/tc-arm.c (working copy) @@ -16771,7 +16771,31 @@ relaxed_symbol_addr(fragS *fragp, long s if (stretch != 0 && sym_frag->relax_marker != fragp->relax_marker) - addr += stretch; + { + fragS *f; + + /* Adjust stretch for any alignment frag. Note that if have + been expanding the earlier code, the symbol may be + defined in what appears to be an earlier frag. FIXME: + This doesn't handle the fr_subtype field, which specifies + a maximum number of bytes to skip when doing an + alignment. */ + for (f = fragp; f != NULL && f != sym_frag; f = f->fr_next) + { + if (f->fr_type == rs_align || f->fr_type == rs_align_code) + { + if (stretch < 0) + stretch = - ((- stretch) + & ~ ((1 << (int) f->fr_offset) - 1)); + else + stretch &= ~ ((1 << (int) f->fr_offset) - 1); + if (stretch == 0) + break; + } + } + if (f != NULL) + addr += stretch; + } return addr; }