This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
SH @(expr,pc) fix-ups broken
- From: Alexandre Oliva <aoliva at redhat dot com>
- To: binutils at sources dot redhat dot com, hp at bitrange dot com
- Date: 31 Jan 2002 07:11:53 -0200
- Subject: SH @(expr,pc) fix-ups broken
- Organization: GCC Team, Red Hat
This patch contains part of a test that Hans-Peter Nilsson wrote while
contracting with Red Hat, and a fix for the bug it currently exposes.
I'm not convinced the test is correct, and I couldn't find any
rationale behind the `-4' (perhaps it just worked like that at that
time? :-). H-P?
IMO, the `-4' should be taken out, and the newly-introduced
A_DISP_PC_ABS fix-ups should be emitted with a +4 correction such
that, when we subtract 4 at the time of emitting the opcode or
generating a relocation, we get the correct result. Compare, for
example, the use of an immediate, that gets the exact given value into
the objdump output (even though the immediate operand is that minus
4), with the use of an expression that results a constant, that
ends up encoding the value of the expression in the opcode, such that
it references the wrong word.
Anyway, if H-P's test is justifiably correct, this patch fixes the bug
and introduces a testcase. Otherwise, I'd rather remove the `-4' from
the expressions and adjust parse_at such that it uses A_DISP_PC_ABS
for both literal constants and expressions, and it adds 4 to
X_add_number to compensate for the PC offset.
Comments?
Index: opcodes/ChangeLog
from Alexandre Oliva <aoliva@redhat.com>
* sh-opc.h (sh_arg_type): Added A_DISP_PC_ABS.
Index: gas/ChangeLog
from Alexandre Oliva <aoliva@redhat.com>
* config/tc-sh.c (parse_at): Set arg type of @(expr,pc) to
A_DISP_PC only if it's an integral constant, and to
A_DISP_PC_ABS otherwise.
(get_specific): Accept A_DISP_PC_ABS where A_DISP_PC is
expected.
(build_Mytes): Mark PCRELIMM fix-ups as pc-relative only if
the operand type is not A_DISP_PC_ABS.
Index: gas/testsuite/ChangeLog
from Alexandre Oliva <aoliva@redhat.com>
* gas/testsuite/gas/sh/pcrel.d: New test.
* gas/testsuite/gas/sh/pcrel.s: Sources for new test.
* gas/testsuite/gas/sh/basic.exp: Run it.
Index: opcodes/sh-opc.h
===================================================================
RCS file: /cvs/src/src/opcodes/sh-opc.h,v
retrieving revision 1.12
diff -u -p -r1.12 sh-opc.h
--- opcodes/sh-opc.h 2001/10/09 12:25:22 1.12
+++ opcodes/sh-opc.h 2002/01/31 09:09:53
@@ -76,6 +76,7 @@ typedef enum {
A_DISP_GBR,
A_PC,
A_DISP_PC,
+ A_DISP_PC_ABS,
A_DISP_REG_M,
A_DISP_REG_N,
A_GBR,
Index: gas/config/tc-sh.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-sh.c,v
retrieving revision 1.53
diff -u -p -r1.53 tc-sh.c
--- gas/config/tc-sh.c 2002/01/30 18:25:30 1.53
+++ gas/config/tc-sh.c 2002/01/31 09:09:55
@@ -984,10 +984,12 @@ parse_at (src, op)
/* Turn a plain @(4,pc) into @(.+4,pc). */
if (op->immediate.X_op == O_constant)
{
- op->immediate.X_add_symbol = dot();
+ op->immediate.X_add_symbol = dot ();
op->immediate.X_op = O_symbol;
+ op->type = A_DISP_PC;
}
- op->type = A_DISP_PC;
+ else
+ op->type = A_DISP_PC_ABS;
}
else
{
@@ -1169,11 +1171,14 @@ get_specific (opcode, operands)
switch (arg)
{
+ case A_DISP_PC:
+ if (user->type == A_DISP_PC_ABS)
+ break;
+ /* Fall through. */
case A_IMM:
case A_BDISP12:
case A_BDISP8:
case A_DISP_GBR:
- case A_DISP_PC:
case A_MACH:
case A_PR:
case A_MACL:
@@ -1603,10 +1608,12 @@ build_Mytes (opcode, operand)
insert (output + low_byte, BFD_RELOC_SH_IMM8, 0, operand + 1);
break;
case PCRELIMM_8BY4:
- insert (output, BFD_RELOC_SH_PCRELIMM8BY4, 1, operand);
+ insert (output, BFD_RELOC_SH_PCRELIMM8BY4,
+ operand->type != A_DISP_PC_ABS, operand);
break;
case PCRELIMM_8BY2:
- insert (output, BFD_RELOC_SH_PCRELIMM8BY2, 1, operand);
+ insert (output, BFD_RELOC_SH_PCRELIMM8BY2,
+ operand->type != A_DISP_PC_ABS, operand);
break;
case REPEAT:
output = insert_loop_bounds (output, operand);
Index: gas/testsuite/gas/sh/basic.exp
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/sh/basic.exp,v
retrieving revision 1.3
diff -u -p -r1.3 basic.exp
--- gas/testsuite/gas/sh/basic.exp 2001/11/02 17:07:52 1.3
+++ gas/testsuite/gas/sh/basic.exp 2002/01/31 09:09:56
@@ -1,4 +1,4 @@
-# Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
+# Copyright (C) 1995, 1996, 1997, 2002 Free Software Foundation, Inc.
# 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
@@ -90,4 +90,6 @@ if [istarget sh*-*-*] then {
do_fp
# Test DSP instructions
run_dump_test "dsp"
+
+ run_dump_test "pcrel"
}
Index: gas/testsuite/gas/sh/pcrel.d
===================================================================
RCS file: pcrel.d
diff -N pcrel.d
--- /dev/null Tue May 5 13:32:27 1998
+++ gas/testsuite/gas/sh/pcrel.d Thu Jan 31 01:09:56 2002
@@ -0,0 +1,21 @@
+#as: -big
+#objdump: -d
+#name: PC-relative loads
+
+dump.o: file format elf32-sh
+
+Disassembly of section .text:
+
+00000000 <code>:
+ 0: d1 03 mov\.l 10 <litpool>,r1 ! 0xfffffff0
+ 2: d1 03 mov\.l 10 <litpool>,r1 ! 0xfffffff0
+ 4: c7 02 mova 10 <litpool>,r0
+ 6: 61 02 mov\.l @r0,r1
+ 8: d1 01 mov\.l 10 <litpool>,r1 ! 0xfffffff0
+ a: 01 03 bsrf r1
+ c: 00 09 nop
+ e: 00 09 nop
+
+00000010 <litpool>:
+ 10: ff ff \.word 0xffff
+ 12: ff f0 \.word 0xfff0
Index: gas/testsuite/gas/sh/pcrel.s
===================================================================
RCS file: pcrel.s
diff -N pcrel.s
--- /dev/null Tue May 5 13:32:27 1998
+++ gas/testsuite/gas/sh/pcrel.s Thu Jan 31 01:09:56 2002
@@ -0,0 +1,14 @@
+ .text
+
+ .p2align 2
+code:
+ mov.l litpool, r1
+ mov.l @(14,pc), r1
+ mova @(litpool-.-4,pc), r0
+ mov.l @r0,r1
+ mov.l @(litpool-.-4,pc), r1
+ bsrf r1
+ nop
+ nop
+litpool:
+ .long code - .
--
Alexandre Oliva Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer aoliva@{cygnus.com, redhat.com}
CS PhD student at IC-Unicamp oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist Professional serial bug killer