aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ld/ChangeLog8
-rw-r--r--ld/NEWS2
-rw-r--r--ld/ld.texinfo5
-rw-r--r--ld/ldexp.c31
-rw-r--r--ld/ldgram.y4
-rw-r--r--ld/ldlex.l1
-rw-r--r--ld/testsuite/ChangeLog6
-rw-r--r--ld/testsuite/ld-scripts/log2.exp34
-rw-r--r--ld/testsuite/ld-scripts/log2.s1
-rw-r--r--ld/testsuite/ld-scripts/log2.t8
10 files changed, 96 insertions, 4 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 4af9fca..eef4ca8 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,11 @@
+2013-08-14 Clemens Lang <clemens.lang@fau.de>
+
+ * ldexp.c: Add LOG2CEIL() builtin function to linker script language
+ * ldgram.y: Likewise
+ * ldlex.l: Likewise
+ * NEWS: Mention the new feature.
+ * ld.texinfo: Document the new feature.
+
2013-07-19 Sebastian Huber <sebastian.huber@embedded-brains.de>
* ldgram.y: Add ALIGN_WITH_INPUT output section attribute.
diff --git a/ld/NEWS b/ld/NEWS
index d79c78f..5120036 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -1,5 +1,7 @@
-*- text -*-
+* Add LOG2CEIL() builtin function to the linker script language
+
* Add support for the Texas Instruments MSP430X processor.
* Add support for Altera Nios II.
diff --git a/ld/ld.texinfo b/ld/ld.texinfo
index 986194b..00a0fa4 100644
--- a/ld/ld.texinfo
+++ b/ld/ld.texinfo
@@ -5947,6 +5947,11 @@ Return the length of the memory region named @var{memory}.
Return the absolute LMA of the named @var{section}. (@pxref{Output
Section LMA}).
+@item LOG2CEIL(@var{exp})
+@kindex LOG2CEIL(@var{exp})
+Return the binary logarithm of @var{exp} rounded towards infinity.
+@code{LOG2CEIL(0)} returns 0.
+
@kindex MAX
@item MAX(@var{exp1}, @var{exp2})
Returns the maximum of @var{exp1} and @var{exp2}.
diff --git a/ld/ldexp.c b/ld/ldexp.c
index ae3919b..49e7c65 100644
--- a/ld/ldexp.c
+++ b/ld/ldexp.c
@@ -1,7 +1,5 @@
/* This module handles expression trees.
- Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
- Free Software Foundation, Inc.
+ Copyright 1991-2013 Free Software Foundation, Inc.
Written by Steve Chamberlain of Cygnus Support <sac@cygnus.com>.
This file is part of the GNU Binutils.
@@ -81,6 +79,7 @@ exp_print_token (token_code_type code, int infix_p)
{ GE, ">=" },
{ LSHIFT, "<<" },
{ RSHIFT, ">>" },
+ { LOG2CEIL, "LOG2CEIL" },
{ ALIGN_K, "ALIGN" },
{ BLOCK, "BLOCK" },
{ QUAD, "QUAD" },
@@ -135,6 +134,28 @@ exp_print_token (token_code_type code, int infix_p)
}
static void
+make_log2ceil (void)
+{
+ bfd_vma value = expld.result.value;
+ bfd_vma result = -1;
+ bfd_boolean round_up = FALSE;
+
+ do
+ {
+ result++;
+ /* If more than one bit is set in the value we will need to round up. */
+ if ((value > 1) && (value & 1))
+ round_up = TRUE;
+ }
+ while (value >>= 1);
+
+ if (round_up)
+ result += 1;
+ expld.result.section = NULL;
+ expld.result.value = result;
+}
+
+static void
make_abs (void)
{
if (expld.result.section != NULL)
@@ -242,6 +263,10 @@ fold_unary (etree_type *tree)
make_abs ();
break;
+ case LOG2CEIL:
+ make_log2ceil ();
+ break;
+
case '~':
expld.result.value = ~expld.result.value;
break;
diff --git a/ld/ldgram.y b/ld/ldgram.y
index 26cb677..1ded4e7 100644
--- a/ld/ldgram.y
+++ b/ld/ldgram.y
@@ -148,7 +148,7 @@ static int error_index;
%type <token> assign_op atype attributes_opt sect_constraint opt_align_with_input
%type <name> filename
%token CHIP LIST SECT ABSOLUTE LOAD NEWLINE ENDWORD ORDER NAMEWORD ASSERT_K
-%token FORMAT PUBLIC DEFSYMEND BASE ALIAS TRUNCATE REL
+%token LOG2CEIL FORMAT PUBLIC DEFSYMEND BASE ALIAS TRUNCATE REL
%token INPUT_SCRIPT INPUT_MRI_SCRIPT INPUT_DEFSYM CASE EXTERN START
%token <name> VERS_TAG VERS_IDENTIFIER
%token GLOBAL LOCAL VERSIONK INPUT_VERSION_SCRIPT
@@ -1010,6 +1010,8 @@ exp :
{ $$ = exp_nameop (ORIGIN, $3); }
| LENGTH '(' NAME ')'
{ $$ = exp_nameop (LENGTH, $3); }
+ | LOG2CEIL '(' exp ')'
+ { $$ = exp_unop (LOG2CEIL, $3); }
;
diff --git a/ld/ldlex.l b/ld/ldlex.l
index 75be86d..1695c27 100644
--- a/ld/ldlex.l
+++ b/ld/ldlex.l
@@ -257,6 +257,7 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)*
<EXPRESSION,BOTH,SCRIPT>"ALIGNOF" { RTOKEN(ALIGNOF); }
<EXPRESSION,BOTH>"MAX" { RTOKEN(MAX_K); }
<EXPRESSION,BOTH>"MIN" { RTOKEN(MIN_K); }
+<EXPRESSION,BOTH>"LOG2CEIL" { RTOKEN(LOG2CEIL); }
<EXPRESSION,BOTH,SCRIPT>"ASSERT" { RTOKEN(ASSERT_K); }
<BOTH,SCRIPT>"ENTRY" { RTOKEN(ENTRY);}
<BOTH,SCRIPT,MRI>"EXTERN" { RTOKEN(EXTERN);}
diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index 9d163ec..ecff1d3 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2013-08-14 Clemens Lang <clemens.lang@fau.de>
+
+ * ld-scripts/log2.exp: New: Run the new log2 test.
+ * ld-scripts/log2.s: Source for the new test.
+ * ld-scripts/log2.t: Linker script for new test.
+
2013-08-14 John Tytgat <john@bass-software.com>
PR ld/15787
diff --git a/ld/testsuite/ld-scripts/log2.exp b/ld/testsuite/ld-scripts/log2.exp
new file mode 100644
index 0000000..43827dc
--- /dev/null
+++ b/ld/testsuite/ld-scripts/log2.exp
@@ -0,0 +1,34 @@
+# Test LOG2() expression in linker script language.
+# By Clemens Lang
+# Copyright 2013
+# Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+set testname "binary logarithm"
+
+if {![ld_assemble $as $srcdir/$subdir/log2.s tmpdir/log2.o]} {
+ unresolved $testname
+ return
+}
+
+if {![ld_simple_link $ld tmpdir/log2 "-T $srcdir/$subdir/log2.t tmpdir/log2.o"]} {
+ fail $testname
+} else {
+ pass $testname
+}
diff --git a/ld/testsuite/ld-scripts/log2.s b/ld/testsuite/ld-scripts/log2.s
new file mode 100644
index 0000000..f3f74ab
--- /dev/null
+++ b/ld/testsuite/ld-scripts/log2.s
@@ -0,0 +1 @@
+ .word 0
diff --git a/ld/testsuite/ld-scripts/log2.t b/ld/testsuite/ld-scripts/log2.t
new file mode 100644
index 0000000..abf73a9
--- /dev/null
+++ b/ld/testsuite/ld-scripts/log2.t
@@ -0,0 +1,8 @@
+ASSERT(LOG2CEIL(0) == 0, "LOG2CEIL(0) == 0");
+ASSERT(LOG2CEIL(1) == 0, "LOG2CEIL(1) == 0");
+ASSERT(LOG2CEIL(2) == 1, "LOG2CEIL(2) == 1");
+ASSERT(LOG2CEIL(3) == 2, "LOG2CEIL(3) == 2");
+ASSERT(LOG2CEIL(4) == 2, "LOG2CEIL(4) == 2");
+ASSERT(LOG2CEIL(0x0ff) == 8, "LOG2CEIL(0x0ff) == 8");
+ASSERT(LOG2CEIL(0x100) == 8, "LOG2CEIL(0x100) == 8");
+ASSERT(LOG2CEIL(0x1ff) == 9, "LOG2CEIL(0x1ff) == 9");