This is the mail archive of the
newlib@sourceware.org
mailing list for the newlib project.
[Patch, AArch64] Bug fix in pc-relative literal load instruction handling
- From: Yufeng Zhang <Yufeng dot Zhang at arm dot com>
- To: newlib at sourceware dot org
- Cc: Richard Earnshaw <Richard dot Earnshaw at arm dot com>
- Date: Mon, 05 Nov 2012 19:12:34 +0000
- Subject: [Patch, AArch64] Bug fix in pc-relative literal load instruction handling
Hi,
This patch fixes a bug in the AArch64 GAS in handling pc-relative
literal load instructions where 16-byte literal is involved, e.g.
LDR Q0, =0xdeadbeef
The literal pool generator silently rejected the generation of 16-byte
literals, and then the generic part of GAS got confused and issued error
message of "redefined symbol cannot be used on reloc".
Is it OK to commit?
Thanks,
Yufeng
gas/
2012-10-18 Yufeng Zhang <yufeng.zhang@arm.com>
* config/tc-aarch64.c (exp_has_bignum_p): Remove.
(my_get_expression): Not get rid bignums.
(s_ltorg): Increase the range of 'align'.
(programmer_friendly_fixup): Allow bignum expression.
gas/testsuite/
2012-10-18 Yufeng Zhang <yufeng.zhang@arm.com>
* gas/aarch64/illegal.s: Add test for unaccepted LDR literal.
* gas/aarch64/illegal.l: Update.
* gas/aarch64/programmer-friendly.s: Add tests for LDR literal with
the auto-generation of lteral in pool.
* gas/aarch64/programmer-friendly.d: Update.
diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
index e7a2fe0..4cd72c9 100644
--- a/gas/config/tc-aarch64.c
+++ b/gas/config/tc-aarch64.c
@@ -484,25 +484,6 @@ skip_past_char (char **str, char c)
/* Arithmetic expressions (possibly involving symbols). */
-/* Return TRUE if anything in the expression *SP is a bignum. */
-
-static bfd_boolean
-exp_has_bignum_p (symbolS * sp)
-{
- if (symbol_get_value_expression (sp)->X_op == O_big)
- return TRUE;
-
- if (symbol_get_value_expression (sp)->X_add_symbol)
- {
- return (exp_has_bignum_p (symbol_get_value_expression (sp)->X_add_symbol)
- || (symbol_get_value_expression (sp)->X_op_symbol
- && exp_has_bignum_p (symbol_get_value_expression (sp)->
- X_op_symbol)));
- }
-
- return FALSE;
-}
-
static bfd_boolean in_my_get_expression_p = FALSE;
/* Third argument to my_get_expression. */
@@ -571,23 +552,6 @@ my_get_expression (expressionS * ep, char **str, int prefix_mode,
(void) seg;
#endif
- /* Get rid of any bignums now, so that we don't generate an error for which
- we can't establish a line number later on. Big numbers are never valid
- in instructions, which is where this routine is always called. */
- if (ep->X_op == O_big
- || (ep->X_add_symbol
- && (exp_has_bignum_p (ep->X_add_symbol)
- || (ep->X_op_symbol && exp_has_bignum_p (ep->X_op_symbol)))))
- {
- if (prefix_present_p && error_p ())
- set_fatal_syntax_error (_("invalid constant"));
- else
- set_first_syntax_error (_("invalid constant"));
- *str = input_line_pointer;
- input_line_pointer = save_in;
- return FALSE;
- }
-
*str = input_line_pointer;
input_line_pointer = save_in;
return TRUE;
@@ -1730,7 +1694,7 @@ s_ltorg (int ignored ATTRIBUTE_UNUSED)
char sym_name[20];
int align;
- for (align = 2; align < 4; align++)
+ for (align = 2; align <= 4; align++)
{
int size = 1 << align;
@@ -5275,6 +5239,7 @@ programmer_friendly_fixup (aarch64_instruction *instr)
if (op == OP_LDRSW_LIT)
size = 4;
if (instr->reloc.exp.X_op != O_constant
+ && instr->reloc.exp.X_op != O_big
&& instr->reloc.exp.X_op != O_symbol)
{
record_operand_error (opcode, 1,
diff --git a/gas/testsuite/gas/aarch64/illegal.l b/gas/testsuite/gas/aarch64/illegal.l
index 6c741cf..6905866 100644
--- a/gas/testsuite/gas/aarch64/illegal.l
+++ b/gas/testsuite/gas/aarch64/illegal.l
@@ -549,3 +549,4 @@
[^:]*:538: Error: .*`mov x0,##5'
[^:]*:540: Error: .*`msr daifset,x0'
[^:]*:541: Error: .*`msr daifclr,x0'
+[^:]*:546: Error: .*
diff --git a/gas/testsuite/gas/aarch64/illegal.s b/gas/testsuite/gas/aarch64/illegal.s
index 9a12463..c13dec4 100644
--- a/gas/testsuite/gas/aarch64/illegal.s
+++ b/gas/testsuite/gas/aarch64/illegal.s
@@ -539,3 +539,8 @@
msr daifset, x0
msr daifclr, x0
+
+ // No 16-byte relocation
+ ldr q0, =one_label
+
+one_label:
diff --git a/gas/testsuite/gas/aarch64/programmer-friendly.d b/gas/testsuite/gas/aarch64/programmer-friendly.d
index 90cea5e..9e9f2d5 100644
--- a/gas/testsuite/gas/aarch64/programmer-friendly.d
+++ b/gas/testsuite/gas/aarch64/programmer-friendly.d
@@ -6,7 +6,7 @@ Disassembly of section \.text:
0000000000000000 <.*>:
0: 4f03e420 movi v0\.16b, #0x61
- 4: 98000181 ldrsw x1, 34 <\.text\+0x34>
+ 4: 98000241 ldrsw x1, 4c <\.text\+0x4c>
8: 98000007 ldrsw x7, 0 <\.text>
8: R_AARCH64_LD_PREL_LO19 \.data\+0x4
c: fa42a02a ccmp x1, x2, #0xa, ge
@@ -19,4 +19,18 @@ Disassembly of section \.text:
28: ab2083e0 adds x0, sp, w0, sxtb
2c: ab20a7e0 adds x0, sp, w0, sxth #1
30: ab20cbe0 adds x0, sp, w0, sxtw #2
- 34: deadbeef \.word 0xdeadbeef
+ 34: 9c000160 ldr q0, 60 <\.text\+0x60>
+ 38: 5c0000c0 ldr d0, 50 <\.text\+0x50>
+ 3c: 580000a0 ldr x0, 50 <\.text\+0x50>
+ 40: 1c000060 ldr s0, 4c <\.text\+0x4c>
+ 44: 18000040 ldr w0, 4c <\.text\+0x4c>
+ 48: 58000080 ldr x0, 58 <\.text\+0x58>
+ 4c: deadbeef \.word 0xdeadbeef
+ 50: .* \.word 0x.*
+ 54: .* \.word 0x.*
+ ...
+ 58: R_AARCH64_ABS64 \.data
+ 60: .* \.word 0x.*
+ 64: .* \.word 0x.*
+ 68: .* \.word 0x.*
+ 6c: .* \.word 0x.*
diff --git a/gas/testsuite/gas/aarch64/programmer-friendly.s b/gas/testsuite/gas/aarch64/programmer-friendly.s
index f39ca5d..9dd93fe 100644
--- a/gas/testsuite/gas/aarch64/programmer-friendly.s
+++ b/gas/testsuite/gas/aarch64/programmer-friendly.s
@@ -49,6 +49,17 @@ u16_lable:
adds x0, sp, x0, uxtb #4
adds x0, sp, x0, uxth #4
adds x0, sp, x0, uxtw #4
+
adds x0, sp, x0, sxtb #0
adds x0, sp, x0, sxth #1
adds x0, sp, x0, sxtw #2
+
+ // More tests on
+ // LDR Wt, label | =value
+ // Find more comment above.
+ ldr q0, =0xdeadcafebeefbabe0123456789abcedf
+ ldr d0, =0xfebeefbabe012345
+ ldr x0, =0xfebeefbabe012345
+ ldr s0, =0xdeadbeef
+ ldr w0, =0xdeadbeef
+ ldr x0, =u16_lable