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
This commit is contained in:
Marek Michalkiewicz 2000-06-24 20:01:26 +02:00 committed by Denis Chertykov
parent f9f27ee563
commit 78cf8279ac
6 changed files with 201 additions and 96 deletions

View File

@ -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.

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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")])
;;============================================================================

View File

@ -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