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
|