summaryrefslogtreecommitdiffstats
path: root/patches/gcc-4.4.3/atmel/0002-Fix-incomplete-check-in-RTL-for-pm-annotation.patch
blob: e8995b6eb8e284d8171699129b10dadb09919290 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
From 78d4497ba8df93b225e3303d96334186fa7945ae Mon Sep 17 00:00:00 2001
From: Stephan Linz <linz@li-pro.net>
Date: Tue, 19 Apr 2011 22:39:33 +0200
Subject: [PATCH 02/10] Fix incomplete check in RTL for pm() annotation

Backend (avr part) creates special "pm()" annotation by looking at
RTL. This is done in avr.c by function avr_assemble_integer(). This
patch allows function address expressions of the form address+k to
be correctly recognized as program memory addresses and thus force
use of pm() assembler syntax.

GCC bug #35013 report:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35013

Original ATMEL patch from:
http://distribute.atmel.no/tools/opensource/avr-gcc/gcc-4.4.3/40-gcc-4.4.3-bug-35013.patch

Signed-off-by: Stephan Linz <linz@li-pro.net>
---
 gcc/config/avr/avr-protos.h |    1 +
 gcc/config/avr/avr.c        |   26 ++++++++++++++++++++++----
 2 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h
index d61ac39..c300c89 100644
--- a/gcc/config/avr/avr-protos.h
+++ b/gcc/config/avr/avr-protos.h
@@ -114,6 +114,7 @@ extern int reg_unused_after (rtx insn, rtx reg);
 extern int _reg_unused_after (rtx insn, rtx reg);
 extern int avr_jump_mode (rtx x, rtx insn);
 extern int byte_immediate_operand (rtx op, enum machine_mode mode);
+extern int text_segment_operand (rtx op, enum machine_mode mode);
 extern int test_hard_reg_class (enum reg_class rclass, rtx x);
 extern int jump_over_one_insn_p (rtx insn, rtx dest);
 
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index 4351e59..4a2588d 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -1276,8 +1276,7 @@ print_operand_address (FILE *file, rtx addr)
 
     default:
       if (CONSTANT_ADDRESS_P (addr)
-	  && ((GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (addr))
-	      || GET_CODE (addr) == LABEL_REF))
+	  && text_segment_operand (addr, VOIDmode))
 	{
 	  fprintf (file, "gs(");
 	  output_addr_const (file,addr);
@@ -1593,6 +1592,26 @@ byte_immediate_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
           && INTVAL (op) <= 0xff && INTVAL (op) >= 0);
 }
 
+/* Return true if OP is a program memory reference.*/
+int
+text_segment_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  switch (GET_CODE (op))
+    {
+    case LABEL_REF :
+      return true;
+    case SYMBOL_REF :
+      return SYMBOL_REF_FUNCTION_P (op);
+    case PLUS :
+      /* Assume canonical format of symbol + constant.
+	 Fall through.  */
+    case CONST :
+      return text_segment_operand (XEXP (op, 0), VOIDmode);
+    default :
+      return false;
+    }
+}
+
 /* Output all insn addresses and their sizes into the assembly language
    output file.  This is helpful for debugging whether the length attributes
    in the md file are correct.
@@ -4808,8 +4827,7 @@ static bool
 avr_assemble_integer (rtx x, unsigned int size, int aligned_p)
 {
   if (size == POINTER_SIZE / BITS_PER_UNIT && aligned_p
-      && ((GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (x))
-	  || GET_CODE (x) == LABEL_REF))
+      && text_segment_operand (x, VOIDmode) )
     {
       fputs ("\t.word\tgs(", asm_out_file);
       output_addr_const (asm_out_file, x);
-- 
1.6.0.4