aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Michalkiewicz <marekm@linux.org.pl>2000-06-24 20:01:26 +0200
committerDenis Chertykov <denisc@gcc.gnu.org>2000-06-24 22:01:26 +0400
commit78cf8279acfb5c38229579af7d72ce3b9bfc511c (patch)
tree5ac9b8f3997175b76bbf24be11bb1c4e821c878a
parentf9f27ee563eb3741820d0fa91196900dd5621108 (diff)
downloadgcc-78cf8279acfb5c38229579af7d72ce3b9bfc511c.zip
gcc-78cf8279acfb5c38229579af7d72ce3b9bfc511c.tar.gz
gcc-78cf8279acfb5c38229579af7d72ce3b9bfc511c.tar.bz2
avr-protos.h (avr_hard_regno_mode_ok): New prototype.
* config/avr/avr-protos.h (avr_hard_regno_mode_ok): New prototype. * config/avr/avr.c (out_adj_frame_ptr, out_set_stack_ptr): New functions, common code moved from function_{prologue,epilogue} and extended to support the -mtiny-stack option. (function_prologue, function_epilogue): Use them. Use lo8/hi8 consistently for asm output readability. (avr_hard_regno_mode_ok): New function. * config/avr/avr.h (TARGET_SWITCHES): Fix typo. Add -mtiny-stack. (UNITS_PER_WORD): Define as 4 (not 1) when compiling libgcc2.c. (HARD_REGNO_MODE_OK): Call the avr_hard_regno_mode_ok function. * config/avr/avr.md (*mov_sp_r): Add support for -mtiny-stack. Write SPH before SPL. (*movqi): No need to disable interrupts for just one "out" in alternative 5. Change length attribute from 4 to 1. * config/avr/libgcc.S (__prologue_saves__, __epilogue_restores__): Write SPH before SPL. From-SVN: r34678
-rw-r--r--gcc/ChangeLog19
-rw-r--r--gcc/config/avr/avr-protos.h2
-rw-r--r--gcc/config/avr/avr.c229
-rw-r--r--gcc/config/avr/avr.h13
-rw-r--r--gcc/config/avr/avr.md26
-rw-r--r--gcc/config/avr/libgcc.S8
6 files changed, 201 insertions, 96 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4d78128..7e39f84 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,22 @@
+2000-06-24 Marek Michalkiewicz <marekm@linux.org.pl>
+
+ * config/avr/avr-protos.h (avr_hard_regno_mode_ok): New prototype.
+ * config/avr/avr.c (out_adj_frame_ptr, out_set_stack_ptr):
+ New functions, common code moved from function_{prologue,epilogue}
+ and extended to support the -mtiny-stack option.
+ (function_prologue, function_epilogue): Use them.
+ Use lo8/hi8 consistently for asm output readability.
+ (avr_hard_regno_mode_ok): New function.
+ * config/avr/avr.h (TARGET_SWITCHES): Fix typo. Add -mtiny-stack.
+ (UNITS_PER_WORD): Define as 4 (not 1) when compiling libgcc2.c.
+ (HARD_REGNO_MODE_OK): Call the avr_hard_regno_mode_ok function.
+ * config/avr/avr.md (*mov_sp_r): Add support for -mtiny-stack.
+ Write SPH before SPL.
+ (*movqi): No need to disable interrupts for just one "out"
+ in alternative 5. Change length attribute from 4 to 1.
+ * config/avr/libgcc.S (__prologue_saves__, __epilogue_restores__):
+ Write SPH before SPL.
+
2000-06-24 Bernd Schmidt <bernds@cygnus.co.uk>
* rtl.texi (Vector Operations): New node.
diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h
index 7532754..4399dba 100644
--- a/gcc/config/avr/avr-protos.h
+++ b/gcc/config/avr/avr-protos.h
@@ -138,6 +138,8 @@ extern int byte_immediate_operand PARAMS ((register rtx op,
extern int test_hard_reg_class PARAMS ((enum reg_class class, rtx x));
extern int jump_over_one_insn_p PARAMS ((rtx insn, rtx dest));
+extern int avr_hard_regno_mode_ok PARAMS ((int regno,
+ enum machine_mode mode));
#endif /* RTX_CODE */
#ifdef HAVE_MACHINE_MODES
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index 5ac63f19..4e58c72 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -49,6 +49,8 @@ static int signal_function_p PARAMS ((tree));
static int sequent_regs_live PARAMS ((void));
static char * ptrreg_to_str PARAMS ((int));
static char * cond_string PARAMS ((enum rtx_code));
+static int out_adj_frame_ptr PARAMS ((FILE *, int));
+static int out_set_stack_ptr PARAMS ((FILE *, int, int));
/* Allocate registers from r25 to r8 for parameters for function calls */
@@ -332,6 +334,124 @@ sequent_regs_live ()
}
+/* Output to FILE the asm instructions to adjust the frame pointer by
+ ADJ (r29:r28 -= ADJ;) which can be positive (prologue) or negative
+ (epilogue). Returns the number of instructions generated. */
+
+static int
+out_adj_frame_ptr (file, adj)
+ FILE *file;
+ int adj;
+{
+ int size = 0;
+
+ if (adj)
+ {
+ /* For -mtiny-stack, the high byte (r29) does not change -
+ prefer "subi" (1 cycle) over "sbiw" (2 cycles). */
+
+ if (adj < -63 || adj > 63 || TARGET_TINY_STACK)
+ {
+ fprintf (file, (AS2 (subi, r28, lo8(%d)) CR_TAB), adj);
+ size++;
+
+ if (TARGET_TINY_STACK)
+ {
+ /* In addition to any local data, each level of function calls
+ needs at least 4 more bytes of stack space for the saved
+ frame pointer and return address. So, (255 - 16) leaves
+ room for 4 levels of function calls. */
+
+ if (adj < -(255 - 16) || adj > (255 - 16))
+ fatal ("Frame pointer change (%d) too big for -mtiny-stack",
+ adj);
+ }
+ else
+ {
+ fprintf (file, (AS2 (sbci, r29, hi8(%d)) CR_TAB), adj);
+ size++;
+ }
+ }
+ else if (adj < 0)
+ {
+ fprintf (file, (AS2 (adiw, r28, %d) CR_TAB), -adj);
+ size++;
+ }
+ else
+ {
+ fprintf (file, (AS2 (sbiw, r28, %d) CR_TAB), adj);
+ size++;
+ }
+ }
+ return size;
+}
+
+
+/* Output to FILE the asm instructions to copy r29:r28 to SPH:SPL,
+ handling various cases of interrupt enable flag state BEFORE and AFTER
+ (0=disabled, 1=enabled, -1=unknown/unchanged) and target_flags.
+ Returns the number of instructions generated. */
+
+static int
+out_set_stack_ptr (file, before, after)
+ FILE *file;
+ int before;
+ int after;
+{
+ int do_sph, do_cli, do_save, size;
+
+ if (TARGET_NO_INTERRUPTS)
+ {
+ before = 0;
+ after = 0;
+ }
+
+ do_sph = !TARGET_TINY_STACK;
+ do_cli = (before != 0 && (after == 0 || do_sph));
+ do_save = (before == -1 && after == -1 && do_cli);
+ size = 1;
+
+ if (do_save)
+ {
+ fprintf (file, AS2 (in, __tmp_reg__, __SREG__) CR_TAB);
+ size++;
+ }
+
+ if (do_cli)
+ {
+ fprintf (file, "cli" CR_TAB);
+ size++;
+ }
+
+ /* Do SPH first - maybe this will disable interrupts for one instruction
+ someday, much like x86 does when changing SS (a suggestion has been
+ sent to avr@atmel.com for consideration in future devices). */
+ if (do_sph)
+ {
+ fprintf (file, AS2 (out, __SP_H__, r29) CR_TAB);
+ size++;
+ }
+
+ /* Set/restore the I flag now - interrupts will be really enabled only
+ after the next instruction starts. This was not clearly documented.
+ XXX - verify this on the new devices with enhanced AVR core. */
+ if (do_save)
+ {
+ fprintf (file, AS2 (out, __SREG__, __tmp_reg__) CR_TAB);
+ size++;
+ }
+ else if (after == 1 && (before != 1 || do_cli))
+ {
+ fprintf (file, "sei" CR_TAB);
+ size++;
+ }
+
+ fprintf (file, AS2 (out, __SP_L__, r28) "\n");
+
+ return size;
+}
+
+
/* Output function prologue */
void
@@ -392,8 +512,8 @@ function_prologue (FILE *file, int size)
else if (minimize && (frame_pointer_needed || live_seq > 6))
{
fprintf (file, ("\t"
- AS2 (ldi, r26, %d) CR_TAB
- AS2 (ldi, r27, %d) CR_TAB), size & 0xff, size / 0x100);
+ AS2 (ldi, r26, lo8(%d)) CR_TAB
+ AS2 (ldi, r27, hi8(%d)) CR_TAB), size, size);
fprintf (file, (AS2 (ldi, r30, pm_lo8(.L_%s_body)) CR_TAB
AS2 (ldi, r31, pm_hi8(.L_%s_body)) CR_TAB)
@@ -444,44 +564,20 @@ function_prologue (FILE *file, int size)
prologue_size += 4;
if (size)
{
- if (size > 63)
- {
- fprintf (file, ("\t"
- AS2 (subi,r28,%d) CR_TAB
- AS2 (sbci,r29,%d) CR_TAB)
- , size & 0xff, size / 0x100);
- prologue_size += 2;
- }
- else
- {
- fprintf (file, "\t" AS2 (sbiw,r28,%d) CR_TAB, size);
- ++prologue_size;
- }
+ fputs ("\t", file);
+ prologue_size += out_adj_frame_ptr (file, size);
+
if (interrupt_func_p)
{
- fprintf (file,
- "cli" CR_TAB
- AS2 (out,__SP_L__,r28) CR_TAB
- "sei" CR_TAB
- AS2 (out,__SP_H__,r29) "\n");
- prologue_size += 4;
+ prologue_size += out_set_stack_ptr (file, -1, 1);
}
- else if (signal_func_p || TARGET_NO_INTERRUPTS)
+ else if (signal_func_p)
{
- fprintf (file,
- AS2 (out,__SP_L__,r28) CR_TAB
- AS2 (out,__SP_H__,r29) "\n");
- prologue_size += 2;
+ prologue_size += out_set_stack_ptr (file, 0, 0);
}
else
{
- fprintf (file,
- AS2 (in,__tmp_reg__,__SREG__) CR_TAB
- "cli" CR_TAB
- AS2 (out,__SP_L__,r28) CR_TAB
- AS2 (out,__SREG__,__tmp_reg__) CR_TAB
- AS2 (out,__SP_H__,r29) "\n");
- prologue_size += 5;
+ prologue_size += out_set_stack_ptr (file, -1, -1);
}
}
}
@@ -533,20 +629,7 @@ function_epilogue (FILE *file, int size)
++epilogue_size;
if (frame_pointer_needed)
{
- if (size)
- {
- if (size > 63)
- {
- fprintf (file, AS2 (subi,r28,lo8(-%d)) CR_TAB, size);
- fprintf (file, AS2 (sbci,r29,hi8(-%d)) CR_TAB, size);
- epilogue_size += 2;
- }
- else
- {
- fprintf (file, AS2 (adiw,r28,%d) CR_TAB, size);
- ++epilogue_size;
- }
- }
+ epilogue_size += out_adj_frame_ptr (file, -size);
}
else
{
@@ -574,41 +657,16 @@ function_epilogue (FILE *file, int size)
{
if (size)
{
- if (size > 63)
- {
- fprintf (file, "\t" AS2 (subi,r28,lo8(-%d)) CR_TAB, size);
- fprintf (file, AS2 (sbci,r29,hi8(-%d)) CR_TAB, size);
- epilogue_size += 2;
- }
- else
- {
- fprintf (file, "\t" AS2 (adiw,r28,%d) CR_TAB, size);
- ++epilogue_size;
- }
+ fputs ("\t", file);
+ epilogue_size += out_adj_frame_ptr (file, -size);
+
if (interrupt_func_p | signal_func_p)
{
- fprintf (file,
- "cli" CR_TAB
- AS2 (out,__SP_L__,r28) CR_TAB
- AS2 (out,__SP_H__,r29) "\n");
- epilogue_size += 3;
- }
- else if (TARGET_NO_INTERRUPTS)
- {
- fprintf (file,
- AS2 (out,__SP_L__,r28) CR_TAB
- AS2 (out,__SP_H__,r29) "\n");
- epilogue_size += 2;
+ epilogue_size += out_set_stack_ptr (file, -1, 0);
}
else
{
- fprintf (file,
- AS2 (in,__tmp_reg__,__SREG__) CR_TAB
- "cli" CR_TAB
- AS2 (out,__SP_L__,r28) CR_TAB
- AS2 (out,__SREG__,__tmp_reg__) CR_TAB
- AS2 (out,__SP_H__,r29) "\n");
- epilogue_size += 5;
+ epilogue_size += out_set_stack_ptr (file, -1, -1);
}
}
fprintf (file, "\t"
@@ -3886,3 +3944,20 @@ jump_over_one_insn_p (insn, dest)
int dest_addr = insn_addresses[uid];
return dest_addr - jump_addr == 2;
}
+
+/* Returns 1 if a value of mode MODE can be stored starting with hard
+ register number REGNO. On the enhanced core, it should be a win to
+ align modes larger than QI on even register numbers (even if < 24).
+ so that the "movw" instruction can be used on them. */
+
+int
+avr_hard_regno_mode_ok (regno, mode)
+ int regno;
+ enum machine_mode mode;
+{
+ if (mode == QImode)
+ return 1;
+ if (regno < 24 /* && !TARGET_ENHANCED */ )
+ return 1;
+ return !(regno & 1);
+}
diff --git a/gcc/config/avr/avr.h b/gcc/config/avr/avr.h
index b357af5..0096629 100644
--- a/gcc/config/avr/avr.h
+++ b/gcc/config/avr/avr.h
@@ -52,6 +52,7 @@ extern int target_flags;
#define TARGET_NO_INTERRUPTS (target_flags & 0x20000)
#define TARGET_INSN_SIZE_DUMP (target_flags & 0x2000)
#define TARGET_CALL_PROLOGUES (target_flags & 0x40000)
+#define TARGET_TINY_STACK (target_flags & 0x80000)
/* Dump each assembler insn's rtl into the output file.
This is for debugging the compiler itself. */
@@ -87,7 +88,8 @@ extern int target_flags;
{"int8",0x10000,"Assume int to be 8 bit integer"}, \
{"no-interrupts",0x20000,"Don't output interrupt compatible code"}, \
{"call-prologues",0x40000, \
- "Use subroutines for functions prologeu/epilogue"}, \
+ "Use subroutines for functions prologue/epilogue"}, \
+ {"tiny-stack", 0x80000, "Change only low 8 bits of stack pointer"}, \
{"rtl",0x10, NULL}, \
{"size",0x2000,"Output instruction size's to the asm file"}, \
{"deb",0xfe0, NULL}, \
@@ -194,8 +196,13 @@ extern struct mcu_type_s *avr_mcu_type;
Note that this is not necessarily the width of data type `int'; */
#define BITS_PER_WORD 8
+#ifdef IN_LIBGCC2
+/* This is to get correct SI and DI modes in libgcc2.c (32 and 64 bits). */
+#define UNITS_PER_WORD 4
+#else
/* Width of a word, in units (bytes). */
#define UNITS_PER_WORD 1
+#endif
/* Width in bits of a pointer.
See also the macro `Pmode' defined below. */
@@ -452,9 +459,7 @@ extern struct mcu_type_s *avr_mcu_type;
((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) \
/ UNITS_PER_WORD)) */
-#define HARD_REGNO_MODE_OK(REGNO, MODE) (((REGNO) >= 24 && (MODE) != QImode) \
- ? ! ((REGNO) & 1) \
- : 1)
+#define HARD_REGNO_MODE_OK(REGNO, MODE) avr_hard_regno_mode_ok(REGNO, MODE)
/* A C expression that is nonzero if it is permissible to store a
value of mode MODE in hard register number REGNO (or in several
registers starting with that one). For a machine where all
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index f3ac93b..4d2451e 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -147,22 +147,29 @@
(define_insn "*mov_sp_r"
[(set (reg:HI 32)
(match_operand:HI 0 "register_operand" "r"))]
- "!TARGET_NO_INTERRUPTS"
+ "(!TARGET_TINY_STACK && !TARGET_NO_INTERRUPTS)"
"in __tmp_reg__,__SREG__
cli
- out __SP_L__,%A0
+ out __SP_H__,%B0
out __SREG__,__tmp_reg__
- out __SP_H__,%B0"
+ out __SP_L__,%A0"
[(set_attr "length" "5")])
(define_insn "*mov_sp_r_no_interrupts"
[(set (reg:HI 32)
(match_operand:HI 0 "register_operand" "r"))]
- "TARGET_NO_INTERRUPTS"
- "out __SP_L__,%A0
- out __SP_H__,%B0"
+ "(!TARGET_TINY_STACK && TARGET_NO_INTERRUPTS)"
+ "out __SP_H__,%B0
+ out __SP_L__,%A0"
[(set_attr "length" "2")])
+(define_insn "*mov_sp_r_tiny"
+ [(set (reg:HI 32)
+ (match_operand:HI 0 "register_operand" "r"))]
+ "TARGET_TINY_STACK"
+ "out __SP_L__,%A0"
+ [(set_attr "length" "1")])
+
;;========================================================================
;; move byte
(define_expand "movqi"
@@ -209,13 +216,10 @@
case 4:
return out_movqi_r_mr (insn,operands,NULL);
case 5:
- return (AS2 (in,__tmp_reg__,__SREG__) CR_TAB
- \"cli\" CR_TAB
- AS2 (out,__SREG__,__tmp_reg__)CR_TAB
- AS2 (out,%0,%1));
+ return (AS2 (out,%0,%1));
}
}"
- [(set_attr "length" "1,1,1,5,5,4")
+ [(set_attr "length" "1,1,1,5,5,1")
(set_attr "cc" "none,clobber,none,clobber,clobber,none")])
;;============================================================================
diff --git a/gcc/config/avr/libgcc.S b/gcc/config/avr/libgcc.S
index 10fa12e..00aa50b 100644
--- a/gcc/config/avr/libgcc.S
+++ b/gcc/config/avr/libgcc.S
@@ -583,9 +583,9 @@ __prologue_saves__:
sbc r29,r27
in __tmp_reg__,__SREG__
cli
- out __SP_L__,r28
- out __SREG__,__tmp_reg__
out __SP_H__,r29
+ out __SREG__,__tmp_reg__
+ out __SP_L__,r28
_prologue_end:
ijmp
.endfunc
@@ -621,9 +621,9 @@ __epilogue_restores__:
adc r29,__zero_reg__
in __tmp_reg__,__SREG__
cli
- out __SP_L__,r28
- out __SREG__,__tmp_reg__
out __SP_H__,r29
+ out __SREG__,__tmp_reg__
+ out __SP_L__,r28
mov r28,r26
mov r29,r27
ret