This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

SH @(expr,pc) fix-ups broken


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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]