This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [AVR][Resend] Save RAMPZ register in interrupt handler routines
- From: "Anatoly Sokolov" <aesok at post dot ru>
- To: gcc-patches at gcc dot gnu dot org
- Cc: eweddington at cso dot atmel dot com
- Date: Tue, 12 Feb 2008 01:42:18 +0300
- Subject: Re: [AVR][Resend] Save RAMPZ register in interrupt handler routines
Hello.
For FLASH memory access for 128KB avr-libc have
pgm_read_*_far macros.
These macros modify RAMPZ register and is non-reenterable.
Using these
macros in main loop/interrupts code can cause collisions
of access to FLASH
memory.
For solving of this problem need save RAMPZ register in
interrupt
handler routines for 128KB devices ('avr31' and 'avr51'
architectures).
2008-02-11 Anatoly Sokolov <aesok@post.ru>
* config/avr/avr.h (AVR_HAVE_RAMPZ): Define.
* config/avr/avr.c (expand_prologue): Save RAMPZ
register.
(expand_epilogue): Restore RAMPZ register.
* config/avr/avr.md (RAMPZ_ADDR): New constant.
Index: gcc/config/avr/avr.md
===================================================================
--- gcc/config/avr/avr.md (revision 132243)
+++ gcc/config/avr/avr.md (working copy)
@@ -47,6 +47,7 @@
(ZERO_REGNO 1) ; zero register r1
(SREG_ADDR 0x5F)
+ (RAMPZ_ADDR 0x5B)
(UNSPEC_STRLEN 0)
(UNSPEC_INDEX_JMP 1)
Index: gcc/config/avr/avr.c
===================================================================
--- gcc/config/avr/avr.c (revision 132243)
+++ gcc/config/avr/avr.c (working copy)
@@ -586,6 +586,7 @@
expand_prologue (void)
{
int live_seq;
+ HARD_REG_SET set;
int minimize;
HOST_WIDE_INT size = get_frame_size();
/* Define templates for push instructions. */
@@ -609,6 +610,7 @@
return;
}
+ avr_regs_to_save (&set);
live_seq = sequent_regs_live ();
minimize = (TARGET_CALL_PROLOGUES
&& !cfun->machine->is_interrupt
@@ -639,7 +641,18 @@
RTX_FRAME_RELATED_P (insn) = 1;
insn = emit_move_insn (pushbyte, tmp_reg_rtx);
RTX_FRAME_RELATED_P (insn) = 1;
-
+
+ /* Push RAMPZ. */
+ if(AVR_HAVE_RAMPZ
+ && (TEST_HARD_REG_BIT (set, REG_Z) &&
TEST_HARD_REG_BIT (set, REG_Z + 1)))
+ {
+ insn = emit_move_insn (tmp_reg_rtx,
+ gen_rtx_MEM (QImode,
GEN_INT (RAMPZ_ADDR)));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ insn = emit_move_insn (pushbyte, tmp_reg_rtx);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+
/* Clear zero reg. */
insn = emit_move_insn (zero_reg_rtx, const0_rtx);
RTX_FRAME_RELATED_P (insn) = 1;
@@ -660,8 +673,6 @@
}
else
{
- HARD_REG_SET set;
- avr_regs_to_save (&set);
int reg;
for (reg = 0; reg < 32; ++reg)
{
@@ -811,6 +822,7 @@
{
int reg;
int live_seq;
+ HARD_REG_SET set;
int minimize;
HOST_WIDE_INT size = get_frame_size();
@@ -821,6 +833,7 @@
return;
}
+ avr_regs_to_save (&set);
live_seq = sequent_regs_live ();
minimize = (TARGET_CALL_PROLOGUES
&& !cfun->machine->is_interrupt
@@ -895,8 +908,6 @@
}
}
/* Restore used registers. */
- HARD_REG_SET set;
- avr_regs_to_save (&set);
for (reg = 31; reg >= 0; --reg)
{
if (TEST_HARD_REG_BIT (set, reg))
@@ -904,6 +915,14 @@
}
if (cfun->machine->is_interrupt ||
cfun->machine->is_signal)
{
+ /* Restore RAMPZ using tmp reg as scratch. */
+ if(AVR_HAVE_RAMPZ
+ && (TEST_HARD_REG_BIT (set, REG_Z) &&
TEST_HARD_REG_BIT (set, REG_Z + 1)))
+ {
+ emit_insn (gen_popqi (tmp_reg_rtx));
+ emit_move_insn (gen_rtx_MEM(QImode,
GEN_INT(RAMPZ_ADDR)),
+ tmp_reg_rtx);
+ }
/* Restore SREG using tmp reg as scratch. */
emit_insn (gen_popqi (tmp_reg_rtx));
Index: gcc/config/avr/avr.h
===================================================================
--- gcc/config/avr/avr.h (revision 132243)
+++ gcc/config/avr/avr.h (working copy)
@@ -99,6 +99,7 @@
#define AVR_HAVE_MUL (avr_have_mul_p)
#define AVR_HAVE_MOVW (avr_have_movw_lpmx_p)
#define AVR_HAVE_LPMX (avr_have_movw_lpmx_p)
+#define AVR_HAVE_RAMPZ (avr_current_arch->have_elpm)
#define AVR_2_BYTE_PC 1
#define AVR_3_BYTE_PC 0
Anatoly.