This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC 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]

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.



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