aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/avr/avr.c
diff options
context:
space:
mode:
authorAndy Hutchinson <hutchinsonandy@gcc.gnu.org>2009-11-15 04:10:20 +0000
committerAndy Hutchinson <hutchinsonandy@gcc.gnu.org>2009-11-15 04:10:20 +0000
commita212a5d408ce85d717a166103601f596b58da9af (patch)
tree6acbfe49dc093b58ca7e058662c88af688c730d0 /gcc/config/avr/avr.c
parentde8caa8cf818f016d6ce5ad6bfade2c34426d6e6 (diff)
downloadgcc-a212a5d408ce85d717a166103601f596b58da9af.zip
gcc-a212a5d408ce85d717a166103601f596b58da9af.tar.gz
gcc-a212a5d408ce85d717a166103601f596b58da9af.tar.bz2
PR target/21078, 21080
PR target/21078, 21080 * config/avr/avr.c (avr_return_addr_rtx): New function for builtin_return_address. (expand_prologue): Calculate stack usage. (avr_asm_function_end_prologue): Output stack size and offset label. * config/avr/avr.h (RETURN_ADDR_RTX): Replace. (machine_function): Add stack_usage. * config/avr/avr-protos.h (avr_return_addr_rtx): New function. From-SVN: r154188
Diffstat (limited to 'gcc/config/avr/avr.c')
-rw-r--r--gcc/config/avr/avr.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index cb2d709..b1713a8 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -461,6 +461,31 @@ rtx avr_builtin_setjmp_frame_value (void)
gen_int_mode (STARTING_FRAME_OFFSET, Pmode));
}
+/* Return contents of MEM at frame pointer + stack size + 1 (+2 if 3 byte PC).
+ This is return address of function. */
+rtx
+avr_return_addr_rtx (int count, const_rtx tem)
+{
+ rtx r;
+
+ /* Can only return this functions return address. Others not supported. */
+ if (count)
+ return NULL;
+
+ if (AVR_3_BYTE_PC)
+ {
+ r = gen_rtx_SYMBOL_REF (Pmode, ".L__stack_usage+2");
+ warning (0, "'builtin_return_address' contains only 2 bytes of address");
+ }
+ else
+ r = gen_rtx_SYMBOL_REF (Pmode, ".L__stack_usage+1");
+
+ r = gen_rtx_PLUS (Pmode, tem, r);
+ r = gen_frame_mem (Pmode, memory_address (Pmode, r));
+ r = gen_rtx_ROTATE (HImode, r, GEN_INT (8));
+ return r;
+}
+
/* Return 1 if the function epilogue is just a single "ret". */
int
@@ -560,6 +585,7 @@ expand_prologue (void)
cfun->machine->is_signal = signal_function_p (current_function_decl);
cfun->machine->is_OS_task = avr_OS_task_function_p (current_function_decl);
cfun->machine->is_OS_main = avr_OS_main_function_p (current_function_decl);
+ cfun->machine->stack_usage = 0;
/* Prologue: naked. */
if (cfun->machine->is_naked)
@@ -588,10 +614,12 @@ expand_prologue (void)
/* Push zero reg. */
insn = emit_move_insn (pushbyte, zero_reg_rtx);
RTX_FRAME_RELATED_P (insn) = 1;
+ cfun->machine->stack_usage++;
/* Push tmp reg. */
insn = emit_move_insn (pushbyte, tmp_reg_rtx);
RTX_FRAME_RELATED_P (insn) = 1;
+ cfun->machine->stack_usage++;
/* Push SREG. */
insn = emit_move_insn (tmp_reg_rtx,
@@ -599,6 +627,7 @@ expand_prologue (void)
RTX_FRAME_RELATED_P (insn) = 1;
insn = emit_move_insn (pushbyte, tmp_reg_rtx);
RTX_FRAME_RELATED_P (insn) = 1;
+ cfun->machine->stack_usage++;
/* Push RAMPZ. */
if(AVR_HAVE_RAMPZ
@@ -609,6 +638,7 @@ expand_prologue (void)
RTX_FRAME_RELATED_P (insn) = 1;
insn = emit_move_insn (pushbyte, tmp_reg_rtx);
RTX_FRAME_RELATED_P (insn) = 1;
+ cfun->machine->stack_usage++;
}
/* Clear zero reg. */
@@ -630,6 +660,7 @@ expand_prologue (void)
emit_insn (gen_call_prologue_saves (gen_int_mode (live_seq, HImode),
gen_int_mode (size + live_seq, HImode)));
RTX_FRAME_RELATED_P (insn) = 1;
+ cfun->machine->stack_usage += size + live_seq;
}
else
{
@@ -641,6 +672,7 @@ expand_prologue (void)
/* Emit push of register to save. */
insn=emit_move_insn (pushbyte, gen_rtx_REG (QImode, reg));
RTX_FRAME_RELATED_P (insn) = 1;
+ cfun->machine->stack_usage++;
}
}
if (frame_pointer_needed)
@@ -650,6 +682,7 @@ expand_prologue (void)
/* Push frame pointer. */
insn = emit_move_insn (pushword, frame_pointer_rtx);
RTX_FRAME_RELATED_P (insn) = 1;
+ cfun->machine->stack_usage += 2;
}
if (!size)
@@ -756,6 +789,7 @@ expand_prologue (void)
emit_insn (sp_plus_insns);
else
emit_insn (fp_plus_insns);
+ cfun->machine->stack_usage += size;
}
}
}
@@ -785,6 +819,11 @@ avr_asm_function_end_prologue (FILE *file)
}
fprintf (file, "/* frame size = " HOST_WIDE_INT_PRINT_DEC " */\n",
get_frame_size());
+ fprintf (file, "/* stack size = %d */\n",
+ cfun->machine->stack_usage);
+ /* Create symbol stack offset here so all functions have it. Add 1 to stack
+ usage for offset so that SP + .L__stack_offset = return address. */
+ fprintf (file, ".L__stack_usage = %d\n", cfun->machine->stack_usage);
}