Commit 590e2636 by Max Filippov Committed by Max Filippov

Implement call0 ABI for xtensa

call0 is an ABI that doesn't use register windows.

2015-03-03  Max Filippov  <jcmvbkbc@gmail.com>

gcc/
	* config/xtensa/constraints.md ("a" constraint): Include stack
	pointer in case of call0 ABI.
	("q" constraint): Make empty in case of call0 ABI.
	("D" constraint): Include stack pointer in case of call0 ABI.
	* config/xtensa/xtensa-protos.h (xtensa_set_return_address,
	xtensa_expand_epilogue, xtensa_regno_to_class): Add new function
	prototypes.
	* config/xtensa/xtensa.c (xtensa_callee_save_size): New
	variable.
	(xtensa_regno_to_class): Make it a local variable in the
	function xtensa_regno_to_class.
	(xtensa_function_epilogue, TARGET_ASM_FUNCTION_EPILOGUE): Remove
	macro, function prototype and implementation.
	(reg_nonleaf_alloc_order): Make it a local variable in the
	function order_regs_for_local_alloc.
	(xtensa_conditional_register_usage): New function.
	(TARGET_CONDITIONAL_REGISTER_USAGE): Define macro.
	(xtensa_valid_move): Allow direct moves to stack pointer
	register in call0 ABI.
	(xtensa_setup_frame_addresses): Only spill register windows in
	windowed ABI.
	(xtensa_emit_call): Emit call(x)8 or call(x)0 in windowed and
	call0 ABI respectively.
	(xtensa_function_arg_1): Only mark a7 register for copying in
	windowed ABI.
	(xtensa_call_save_reg): New function.
	(compute_frame_size): Add space for callee saved register
	storage to the frame size in call0 ABI.
	(xtensa_expand_prologue): Generate code to set up stack frame
	and save callee-saved registers in call0 ABI.
	(xtensa_expand_epilogue): New function.
	(xtensa_set_return_address): New function.
	(xtensa_return_addr): Calculate return address in call0 ABI.
	(xtensa_builtin_saveregs): Only mark a7 register for copying and
	emit copying code in windowed ABI.
	(order_regs_for_local_alloc): Add preferred register allocation
	order for non-leaf function in call0 ABI.
	(xtensa_static_chain): Add atatic chain passing for call0 ABI.
	(xtensa_asm_trampoline_template): Add trampoline generation for
	call0 ABI.
	(xtensa_trampoline_init): Add trampoline initialization for
	call0 ABI.
	(xtensa_conditional_register_usage, xtensa_regno_to_class): New
	functions.
	* config/xtensa/xtensa.h (TARGET_WINDOWED_ABI): New macro.
	(TARGET_CPU_CPP_BUILTINS): Add built-in define for call0 ABI.
	(CALL_USED_REGISTERS): Modify to encode both windowed and call0
	ABI call-used registers.
	(HARD_FRAME_POINTER_REGNUM): Add frame pointer for call0 ABI.
	(INCOMING_REGNO, OUTGOING_REGNO): Use argument unchanged in
	call0 ABI.
	(REG_CLASS_CONTENTS): Include all registers into the preferred
	reload registers set, adjust the set in the
	xtensa_conditional_register_usage.
	(xtensa_regno_to_class): Drop variable declaration.
	(REGNO_REG_CLASS): Redefine to use xtensa_regno_to_class
	function.
	(WINDOW_SIZE): Define as 8 or 0 for windowed and call0 ABI
	respectively.
	(FUNCTION_PROFILER): Add _mcount call for call0 ABI.
	(TRAMPOLINE_SIZE): Define trampoline size for call0 ABI.
	(RETURN_ADDR_IN_PREVIOUS_FRAME): Define to 0 in call0 ABI.
	(ASM_OUTPUT_POOL_PROLOGUE): Always generate literal pool
	location in call0 ABI.
	(EH_RETURN_STACKADJ_RTX): New definition, use a10 for passing
	stack adjustment size when handling exception.
	(CRT_CALL_STATIC_FUNCTION): Add definition for call0 ABI.
	* config/xtensa/xtensa.md (A9_REG, UNSPECV_BLOCKAGE): New
	definitions.
	("return" pattern): Generate ret.n/ret in call0 ABI.
	("epilogue" pattern): Expand epilogue.
	("nonlocal_goto" pattern): Use default in call0 ABI.
	("eh_return" pattern): Move implementation to eh_set_a0_windowed,
	emit eh_set_a0_* depending on ABI.
	("eh_set_a0_windowed" pattern): Former eh_return pattern.
	("eh_set_a0_call0", "blockage"): New patterns.

libgcc/
	* config/xtensa/lib2funcs.S (__xtensa_libgcc_window_spill,
	__xtensa_nonlocal_goto): Don't compile for call0 ABI.
	(__xtensa_sync_caches): Only use entry and retw in windowed ABI,
	use ret in call0 ABI.
	* config/xtensa/t-windowed: New file.
	* libgcc/config/xtensa/t-xtensa (LIB2ADDEH): Move to t-windowed.
	* libgcc/configure: Regenerated.
	* libgcc/configure.ac: Check if xtensa target is configured for
	windowed ABI and thus needs to use custom unwind code.

From-SVN: r221158
parent d76b082e
2015-03-03 Max Filippov <jcmvbkbc@gmail.com>
Implement call0 ABI for xtensa
* config/xtensa/constraints.md ("a" constraint): Include stack
pointer in case of call0 ABI.
("q" constraint): Make empty in case of call0 ABI.
("D" constraint): Include stack pointer in case of call0 ABI.
* config/xtensa/xtensa-protos.h (xtensa_set_return_address,
xtensa_expand_epilogue, xtensa_regno_to_class): Add new function
prototypes.
* config/xtensa/xtensa.c (xtensa_callee_save_size): New
variable.
(xtensa_regno_to_class): Make it a local variable in the
function xtensa_regno_to_class.
(xtensa_function_epilogue, TARGET_ASM_FUNCTION_EPILOGUE): Remove
macro, function prototype and implementation.
(reg_nonleaf_alloc_order): Make it a local variable in the
function order_regs_for_local_alloc.
(xtensa_conditional_register_usage): New function.
(TARGET_CONDITIONAL_REGISTER_USAGE): Define macro.
(xtensa_valid_move): Allow direct moves to stack pointer
register in call0 ABI.
(xtensa_setup_frame_addresses): Only spill register windows in
windowed ABI.
(xtensa_emit_call): Emit call(x)8 or call(x)0 in windowed and
call0 ABI respectively.
(xtensa_function_arg_1): Only mark a7 register for copying in
windowed ABI.
(xtensa_call_save_reg): New function.
(compute_frame_size): Add space for callee saved register
storage to the frame size in call0 ABI.
(xtensa_expand_prologue): Generate code to set up stack frame
and save callee-saved registers in call0 ABI.
(xtensa_expand_epilogue): New function.
(xtensa_set_return_address): New function.
(xtensa_return_addr): Calculate return address in call0 ABI.
(xtensa_builtin_saveregs): Only mark a7 register for copying and
emit copying code in windowed ABI.
(order_regs_for_local_alloc): Add preferred register allocation
order for non-leaf function in call0 ABI.
(xtensa_static_chain): Add atatic chain passing for call0 ABI.
(xtensa_asm_trampoline_template): Add trampoline generation for
call0 ABI.
(xtensa_trampoline_init): Add trampoline initialization for
call0 ABI.
(xtensa_conditional_register_usage, xtensa_regno_to_class): New
functions.
* config/xtensa/xtensa.h (TARGET_WINDOWED_ABI): New macro.
(TARGET_CPU_CPP_BUILTINS): Add built-in define for call0 ABI.
(CALL_USED_REGISTERS): Modify to encode both windowed and call0
ABI call-used registers.
(HARD_FRAME_POINTER_REGNUM): Add frame pointer for call0 ABI.
(INCOMING_REGNO, OUTGOING_REGNO): Use argument unchanged in
call0 ABI.
(REG_CLASS_CONTENTS): Include all registers into the preferred
reload registers set, adjust the set in the
xtensa_conditional_register_usage.
(xtensa_regno_to_class): Drop variable declaration.
(REGNO_REG_CLASS): Redefine to use xtensa_regno_to_class
function.
(WINDOW_SIZE): Define as 8 or 0 for windowed and call0 ABI
respectively.
(FUNCTION_PROFILER): Add _mcount call for call0 ABI.
(TRAMPOLINE_SIZE): Define trampoline size for call0 ABI.
(RETURN_ADDR_IN_PREVIOUS_FRAME): Define to 0 in call0 ABI.
(ASM_OUTPUT_POOL_PROLOGUE): Always generate literal pool
location in call0 ABI.
(EH_RETURN_STACKADJ_RTX): New definition, use a10 for passing
stack adjustment size when handling exception.
(CRT_CALL_STATIC_FUNCTION): Add definition for call0 ABI.
* config/xtensa/xtensa.md (A9_REG, UNSPECV_BLOCKAGE): New
definitions.
("return" pattern): Generate ret.n/ret in call0 ABI.
("epilogue" pattern): Expand epilogue.
("nonlocal_goto" pattern): Use default in call0 ABI.
("eh_return" pattern): Move implementation to eh_set_a0_windowed,
emit eh_set_a0_* depending on ABI.
("eh_set_a0_windowed" pattern): Former eh_return pattern.
("eh_set_a0_call0", "blockage"): New patterns.
2015-03-03 Martin Liska <mliska@suse.cz> 2015-03-03 Martin Liska <mliska@suse.cz>
PR ipa/65287 PR ipa/65287
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
;; Register constraints. ;; Register constraints.
(define_register_constraint "a" "GR_REGS" (define_register_constraint "a" "TARGET_WINDOWED_ABI ? GR_REGS : AR_REGS"
"General-purpose AR registers @code{a0}-@code{a15}, "General-purpose AR registers @code{a0}-@code{a15},
except @code{a1} (@code{sp}).") except @code{a1} (@code{sp}).")
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
"Floating-point registers @code{f0}-@code{f15}; only available if the "Floating-point registers @code{f0}-@code{f15}; only available if the
Xtensa Floating-Pointer Coprocessor is configured.") Xtensa Floating-Pointer Coprocessor is configured.")
(define_register_constraint "q" "SP_REG" (define_register_constraint "q" "TARGET_WINDOWED_ABI ? SP_REG : NO_REGS"
"@internal "@internal
The stack pointer (register @code{a1}).") The stack pointer (register @code{a1}).")
...@@ -53,7 +53,7 @@ ...@@ -53,7 +53,7 @@
General-purpose AR registers, but only if the Xtensa 16-Bit Integer General-purpose AR registers, but only if the Xtensa 16-Bit Integer
Multiply Option is configured.") Multiply Option is configured.")
(define_register_constraint "D" "TARGET_DENSITY ? GR_REGS: NO_REGS" (define_register_constraint "D" "TARGET_DENSITY ? (TARGET_WINDOWED_ABI ? GR_REGS : AR_REGS) : NO_REGS"
"@internal "@internal
General-purpose AR registers, but only if the Xtensa Code Density General-purpose AR registers, but only if the Xtensa Code Density
Option is configured.") Option is configured.")
......
...@@ -61,6 +61,7 @@ extern void init_cumulative_args (CUMULATIVE_ARGS *, int); ...@@ -61,6 +61,7 @@ extern void init_cumulative_args (CUMULATIVE_ARGS *, int);
extern void print_operand (FILE *, rtx, int); extern void print_operand (FILE *, rtx, int);
extern void print_operand_address (FILE *, rtx); extern void print_operand_address (FILE *, rtx);
extern void xtensa_output_literal (FILE *, rtx, machine_mode, int); extern void xtensa_output_literal (FILE *, rtx, machine_mode, int);
extern void xtensa_set_return_address (rtx, rtx);
extern rtx xtensa_return_addr (int, rtx); extern rtx xtensa_return_addr (int, rtx);
#endif /* RTX_CODE */ #endif /* RTX_CODE */
...@@ -68,6 +69,8 @@ extern void xtensa_setup_frame_addresses (void); ...@@ -68,6 +69,8 @@ extern void xtensa_setup_frame_addresses (void);
extern int xtensa_dbx_register_number (int); extern int xtensa_dbx_register_number (int);
extern long compute_frame_size (int); extern long compute_frame_size (int);
extern void xtensa_expand_prologue (void); extern void xtensa_expand_prologue (void);
extern void xtensa_expand_epilogue (void);
extern void order_regs_for_local_alloc (void); extern void order_regs_for_local_alloc (void);
extern enum reg_class xtensa_regno_to_class (int regno);
#endif /* !__XTENSA_PROTOS_H__ */ #endif /* !__XTENSA_PROTOS_H__ */
...@@ -66,6 +66,7 @@ extern unsigned xtensa_current_frame_size; ...@@ -66,6 +66,7 @@ extern unsigned xtensa_current_frame_size;
#define TARGET_ABSOLUTE_LITERALS XSHAL_USE_ABSOLUTE_LITERALS #define TARGET_ABSOLUTE_LITERALS XSHAL_USE_ABSOLUTE_LITERALS
#define TARGET_THREADPTR XCHAL_HAVE_THREADPTR #define TARGET_THREADPTR XCHAL_HAVE_THREADPTR
#define TARGET_LOOPS XCHAL_HAVE_LOOPS #define TARGET_LOOPS XCHAL_HAVE_LOOPS
#define TARGET_WINDOWED_ABI (XSHAL_ABI == XTHAL_ABI_WINDOWED)
#define TARGET_DEFAULT \ #define TARGET_DEFAULT \
((XCHAL_HAVE_L32R ? 0 : MASK_CONST16) | \ ((XCHAL_HAVE_L32R ? 0 : MASK_CONST16) | \
...@@ -83,7 +84,8 @@ extern unsigned xtensa_current_frame_size; ...@@ -83,7 +84,8 @@ extern unsigned xtensa_current_frame_size;
builtin_assert ("machine=xtensa"); \ builtin_assert ("machine=xtensa"); \
builtin_define ("__xtensa__"); \ builtin_define ("__xtensa__"); \
builtin_define ("__XTENSA__"); \ builtin_define ("__XTENSA__"); \
builtin_define ("__XTENSA_WINDOWED_ABI__"); \ builtin_define (TARGET_WINDOWED_ABI ? \
"__XTENSA_WINDOWED_ABI__" : "__XTENSA_CALL0_ABI__");\
builtin_define (TARGET_BIG_ENDIAN ? "__XTENSA_EB__" : "__XTENSA_EL__"); \ builtin_define (TARGET_BIG_ENDIAN ? "__XTENSA_EB__" : "__XTENSA_EL__"); \
if (!TARGET_HARD_FLOAT) \ if (!TARGET_HARD_FLOAT) \
builtin_define ("__XTENSA_SOFT_FLOAT__"); \ builtin_define ("__XTENSA_SOFT_FLOAT__"); \
...@@ -238,10 +240,18 @@ extern unsigned xtensa_current_frame_size; ...@@ -238,10 +240,18 @@ extern unsigned xtensa_current_frame_size;
registers that can be used without being saved. registers that can be used without being saved.
The latter must include the registers where values are returned The latter must include the registers where values are returned
and the register where structure-value addresses are passed. and the register where structure-value addresses are passed.
Aside from that, you can include as many other registers as you like. */ Aside from that, you can include as many other registers as you like.
The value encoding is the following:
1: register is used by all ABIs;
bit 1 is set: register is used by windowed ABI;
bit 2 is set: register is used by call0 ABI.
Proper values are computed in TARGET_CONDITIONAL_REGISTER_USAGE. */
#define CALL_USED_REGISTERS \ #define CALL_USED_REGISTERS \
{ \ { \
1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, \ 1, 1, 4, 4, 4, 4, 4, 4, 1, 1, 1, 1, 2, 2, 2, 2, \
1, 1, 1, \ 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, \ 1, \
...@@ -341,7 +351,8 @@ extern char xtensa_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER]; ...@@ -341,7 +351,8 @@ extern char xtensa_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER];
#define STACK_POINTER_REGNUM (GP_REG_FIRST + 1) #define STACK_POINTER_REGNUM (GP_REG_FIRST + 1)
/* Base register for access to local variables of the function. */ /* Base register for access to local variables of the function. */
#define HARD_FRAME_POINTER_REGNUM (GP_REG_FIRST + 7) #define HARD_FRAME_POINTER_REGNUM (GP_REG_FIRST + \
(TARGET_WINDOWED_ABI ? 7 : 15))
/* The register number of the frame pointer register, which is used to /* The register number of the frame pointer register, which is used to
access automatic variables in the stack frame. For Xtensa, this access automatic variables in the stack frame. For Xtensa, this
...@@ -366,14 +377,16 @@ extern char xtensa_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER]; ...@@ -366,14 +377,16 @@ extern char xtensa_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER];
we use a fixed window size of 8. */ we use a fixed window size of 8. */
#define INCOMING_REGNO(OUT) \ #define INCOMING_REGNO(OUT) \
((GP_REG_P (OUT) && \ (TARGET_WINDOWED_ABI ? \
((unsigned) ((OUT) - GP_REG_FIRST) >= WINDOW_SIZE)) ? \ ((GP_REG_P (OUT) && \
(OUT) - WINDOW_SIZE : (OUT)) ((unsigned) ((OUT) - GP_REG_FIRST) >= WINDOW_SIZE)) ? \
(OUT) - WINDOW_SIZE : (OUT)) : (OUT))
#define OUTGOING_REGNO(IN) \ #define OUTGOING_REGNO(IN) \
((GP_REG_P (IN) && \ (TARGET_WINDOWED_ABI ? \
((unsigned) ((IN) - GP_REG_FIRST) < WINDOW_SIZE)) ? \ ((GP_REG_P (IN) && \
(IN) + WINDOW_SIZE : (IN)) ((unsigned) ((IN) - GP_REG_FIRST) < WINDOW_SIZE)) ? \
(IN) + WINDOW_SIZE : (IN)) : (IN))
/* Define the classes of registers for register constraints in the /* Define the classes of registers for register constraints in the
...@@ -422,7 +435,7 @@ enum reg_class ...@@ -422,7 +435,7 @@ enum reg_class
{ 0xfff80000, 0x00000007 }, /* floating-point registers */ \ { 0xfff80000, 0x00000007 }, /* floating-point registers */ \
{ 0x00000000, 0x00000008 }, /* MAC16 accumulator */ \ { 0x00000000, 0x00000008 }, /* MAC16 accumulator */ \
{ 0x00000002, 0x00000000 }, /* stack pointer register */ \ { 0x00000002, 0x00000000 }, /* stack pointer register */ \
{ 0x0000ff7d, 0x00000000 }, /* preferred reload registers */ \ { 0x0000fffd, 0x00000000 }, /* preferred reload registers */ \
{ 0x0000fffd, 0x00000000 }, /* general-purpose registers */ \ { 0x0000fffd, 0x00000000 }, /* general-purpose registers */ \
{ 0x0003ffff, 0x00000000 }, /* integer registers */ \ { 0x0003ffff, 0x00000000 }, /* integer registers */ \
{ 0xffffffff, 0x0000000f } /* all registers */ \ { 0xffffffff, 0x0000000f } /* all registers */ \
...@@ -432,9 +445,7 @@ enum reg_class ...@@ -432,9 +445,7 @@ enum reg_class
register REGNO. In general there is more that one such class; register REGNO. In general there is more that one such class;
choose a class which is "minimal", meaning that no smaller class choose a class which is "minimal", meaning that no smaller class
also contains the register. */ also contains the register. */
extern const enum reg_class xtensa_regno_to_class[FIRST_PSEUDO_REGISTER]; #define REGNO_REG_CLASS(REGNO) xtensa_regno_to_class (REGNO)
#define REGNO_REG_CLASS(REGNO) xtensa_regno_to_class[ (REGNO) ]
/* Use the Xtensa AR register file for base registers. /* Use the Xtensa AR register file for base registers.
No index registers. */ No index registers. */
...@@ -497,7 +508,7 @@ extern const enum reg_class xtensa_regno_to_class[FIRST_PSEUDO_REGISTER]; ...@@ -497,7 +508,7 @@ extern const enum reg_class xtensa_regno_to_class[FIRST_PSEUDO_REGISTER];
#define STACK_BOUNDARY 128 #define STACK_BOUNDARY 128
/* Use a fixed register window size of 8. */ /* Use a fixed register window size of 8. */
#define WINDOW_SIZE 8 #define WINDOW_SIZE (TARGET_WINDOWED_ABI ? 8 : 0)
/* Symbolic macros for the registers used to return integer, floating /* Symbolic macros for the registers used to return integer, floating
point, and values of coprocessor and user-defined modes. */ point, and values of coprocessor and user-defined modes. */
...@@ -561,11 +572,11 @@ typedef struct xtensa_args ...@@ -561,11 +572,11 @@ typedef struct xtensa_args
fprintf (FILE, "\t%s\ta10, a0\n", TARGET_DENSITY ? "mov.n" : "mov"); \ fprintf (FILE, "\t%s\ta10, a0\n", TARGET_DENSITY ? "mov.n" : "mov"); \
if (flag_pic) \ if (flag_pic) \
{ \ { \
fprintf (FILE, "\tmovi\ta8, _mcount@PLT\n"); \ fprintf (FILE, "\tmovi\ta%d, _mcount@PLT\n", WINDOW_SIZE); \
fprintf (FILE, "\tcallx8\ta8\n"); \ fprintf (FILE, "\tcallx%d\ta%d\n", WINDOW_SIZE, WINDOW_SIZE); \
} \ } \
else \ else \
fprintf (FILE, "\tcall8\t_mcount\n"); \ fprintf (FILE, "\tcall%d\t_mcount\n", WINDOW_SIZE); \
} while (0) } while (0)
/* Stack pointer value doesn't matter at exit. */ /* Stack pointer value doesn't matter at exit. */
...@@ -573,7 +584,11 @@ typedef struct xtensa_args ...@@ -573,7 +584,11 @@ typedef struct xtensa_args
/* Size in bytes of the trampoline, as an integer. Make sure this is /* Size in bytes of the trampoline, as an integer. Make sure this is
a multiple of TRAMPOLINE_ALIGNMENT to avoid -Wpadded warnings. */ a multiple of TRAMPOLINE_ALIGNMENT to avoid -Wpadded warnings. */
#define TRAMPOLINE_SIZE (TARGET_CONST16 || TARGET_ABSOLUTE_LITERALS ? 60 : 52) #define TRAMPOLINE_SIZE (TARGET_WINDOWED_ABI ? \
(TARGET_CONST16 || TARGET_ABSOLUTE_LITERALS ? \
60 : 52) : \
(TARGET_CONST16 || TARGET_ABSOLUTE_LITERALS ? \
32 : 24))
/* Alignment required for trampolines, in bits. */ /* Alignment required for trampolines, in bits. */
#define TRAMPOLINE_ALIGNMENT 32 #define TRAMPOLINE_ALIGNMENT 32
...@@ -615,7 +630,7 @@ typedef struct xtensa_args ...@@ -615,7 +630,7 @@ typedef struct xtensa_args
/* Define this if the return address of a particular stack frame is /* Define this if the return address of a particular stack frame is
accessed from the frame pointer of the previous stack frame. */ accessed from the frame pointer of the previous stack frame. */
#define RETURN_ADDR_IN_PREVIOUS_FRAME 1 #define RETURN_ADDR_IN_PREVIOUS_FRAME TARGET_WINDOWED_ABI
/* A C expression whose value is RTL representing the value of the /* A C expression whose value is RTL representing the value of the
return address for the frame COUNT steps up from the current return address for the frame COUNT steps up from the current
...@@ -770,7 +785,7 @@ typedef struct xtensa_args ...@@ -770,7 +785,7 @@ typedef struct xtensa_args
/* Define output to appear before the constant pool. */ /* Define output to appear before the constant pool. */
#define ASM_OUTPUT_POOL_PROLOGUE(FILE, FUNNAME, FUNDECL, SIZE) \ #define ASM_OUTPUT_POOL_PROLOGUE(FILE, FUNNAME, FUNDECL, SIZE) \
do { \ do { \
if ((SIZE) > 0) \ if ((SIZE) > 0 || !TARGET_WINDOWED_ABI) \
{ \ { \
resolve_unique_section ((FUNDECL), 0, flag_function_sections); \ resolve_unique_section ((FUNDECL), 0, flag_function_sections); \
switch_to_section (function_section (FUNDECL)); \ switch_to_section (function_section (FUNDECL)); \
...@@ -805,6 +820,8 @@ typedef struct xtensa_args ...@@ -805,6 +820,8 @@ typedef struct xtensa_args
| DW_EH_PE_pcrel | DW_EH_PE_sdata4) \ | DW_EH_PE_pcrel | DW_EH_PE_sdata4) \
: DW_EH_PE_absptr) : DW_EH_PE_absptr)
#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, GP_REG_FIRST + 10)
/* Emit a PC-relative relocation. */ /* Emit a PC-relative relocation. */
#define ASM_OUTPUT_DWARF_PCREL(FILE, SIZE, LABEL) \ #define ASM_OUTPUT_DWARF_PCREL(FILE, SIZE, LABEL) \
do { \ do { \
...@@ -818,8 +835,16 @@ typedef struct xtensa_args ...@@ -818,8 +835,16 @@ typedef struct xtensa_args
a MOVI and let the assembler relax it -- for the .init and .fini a MOVI and let the assembler relax it -- for the .init and .fini
sections, the assembler knows to put the literal in the right sections, the assembler knows to put the literal in the right
place. */ place. */
#if defined(__XTENSA_WINDOWED_ABI__)
#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \ #define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \
asm (SECTION_OP "\n\ asm (SECTION_OP "\n\
movi\ta8, " USER_LABEL_PREFIX #FUNC "\n\ movi\ta8, " USER_LABEL_PREFIX #FUNC "\n\
callx8\ta8\n" \ callx8\ta8\n" \
TEXT_SECTION_ASM_OP); TEXT_SECTION_ASM_OP);
#elif defined(__XTENSA_CALL0_ABI__)
#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \
asm (SECTION_OP "\n\
movi\ta0, " USER_LABEL_PREFIX #FUNC "\n\
callx0\ta0\n" \
TEXT_SECTION_ASM_OP);
#endif
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
(A1_REG 1) (A1_REG 1)
(A7_REG 7) (A7_REG 7)
(A8_REG 8) (A8_REG 8)
(A9_REG 9)
(UNSPEC_NOP 2) (UNSPEC_NOP 2)
(UNSPEC_PLT 3) (UNSPEC_PLT 3)
...@@ -44,6 +45,7 @@ ...@@ -44,6 +45,7 @@
(UNSPECV_S32C1I 5) (UNSPECV_S32C1I 5)
(UNSPECV_EH_RETURN 6) (UNSPECV_EH_RETURN 6)
(UNSPECV_SET_TP 7) (UNSPECV_SET_TP 7)
(UNSPECV_BLOCKAGE 8)
]) ])
;; This code iterator allows signed and unsigned widening multiplications ;; This code iterator allows signed and unsigned widening multiplications
...@@ -1658,9 +1660,11 @@ ...@@ -1658,9 +1660,11 @@
(define_insn "return" (define_insn "return"
[(return) [(return)
(use (reg:SI A0_REG))] (use (reg:SI A0_REG))]
"reload_completed" "(TARGET_WINDOWED_ABI || !xtensa_current_frame_size) && reload_completed"
{ {
return (TARGET_DENSITY ? "retw.n" : "retw"); return TARGET_WINDOWED_ABI ?
(TARGET_DENSITY ? "retw.n" : "retw") :
(TARGET_DENSITY ? "ret.n" : "ret");
} }
[(set_attr "type" "jump") [(set_attr "type" "jump")
(set_attr "mode" "none") (set_attr "mode" "none")
...@@ -1681,7 +1685,7 @@ ...@@ -1681,7 +1685,7 @@
[(return)] [(return)]
"" ""
{ {
emit_jump_insn (gen_return ()); xtensa_expand_epilogue ();
DONE; DONE;
}) })
...@@ -1700,7 +1704,7 @@ ...@@ -1700,7 +1704,7 @@
(match_operand:SI 1 "general_operand" "") (match_operand:SI 1 "general_operand" "")
(match_operand:SI 2 "general_operand" "") (match_operand:SI 2 "general_operand" "")
(match_operand:SI 3 "" "")] (match_operand:SI 3 "" "")]
"" "TARGET_WINDOWED_ABI"
{ {
xtensa_expand_nonlocal_goto (operands); xtensa_expand_nonlocal_goto (operands);
DONE; DONE;
...@@ -1713,7 +1717,18 @@ ...@@ -1713,7 +1717,18 @@
;; already been applied to the handler, but the generic version doesn't ;; already been applied to the handler, but the generic version doesn't
;; allow us to frob it quite enough, so we just frob here. ;; allow us to frob it quite enough, so we just frob here.
(define_insn_and_split "eh_return" (define_expand "eh_return"
[(use (match_operand 0 "general_operand"))]
""
{
if (TARGET_WINDOWED_ABI)
emit_insn (gen_eh_set_a0_windowed (operands[0]));
else
emit_insn (gen_eh_set_a0_call0 (operands[0]));
DONE;
})
(define_insn_and_split "eh_set_a0_windowed"
[(set (reg:SI A0_REG) [(set (reg:SI A0_REG)
(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] (unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")]
UNSPECV_EH_RETURN)) UNSPECV_EH_RETURN))
...@@ -1726,6 +1741,29 @@ ...@@ -1726,6 +1741,29 @@
(set (reg:SI A0_REG) (rotatert:SI (match_dup 1) (const_int 2)))] (set (reg:SI A0_REG) (rotatert:SI (match_dup 1) (const_int 2)))]
"") "")
(define_insn_and_split "eh_set_a0_call0"
[(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
UNSPECV_EH_RETURN)
(clobber (match_scratch:SI 1 "=r"))]
""
"#"
"reload_completed"
[(const_int 0)]
{
xtensa_set_return_address (operands[0], operands[1]);
DONE;
})
;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
;; all of memory. This blocks insns from being moved across this point.
(define_insn "blockage"
[(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
""
""
[(set_attr "length" "0")
(set_attr "type" "nop")])
;; Setting up a frame pointer is tricky for Xtensa because GCC doesn't ;; Setting up a frame pointer is tricky for Xtensa because GCC doesn't
;; know if a frame pointer is required until the reload pass, and ;; know if a frame pointer is required until the reload pass, and
;; because there may be an incoming argument value in the hard frame ;; because there may be an incoming argument value in the hard frame
......
2015-03-03 Max Filippov <jcmvbkbc@gmail.com>
Implement call0 ABI for xtensa
* config/xtensa/lib2funcs.S (__xtensa_libgcc_window_spill,
__xtensa_nonlocal_goto): Don't compile for call0 ABI.
(__xtensa_sync_caches): Only use entry and retw in windowed ABI,
use ret in call0 ABI.
* config/xtensa/t-windowed: New file.
* libgcc/config/xtensa/t-xtensa (LIB2ADDEH): Move to t-windowed.
* libgcc/configure: Regenerated.
* libgcc/configure.ac: Check if xtensa target is configured for
windowed ABI and thus needs to use custom unwind code.
2015-02-12 Jonathan Wakely <jwakely@redhat.com> 2015-02-12 Jonathan Wakely <jwakely@redhat.com>
PR libgcc/64885 PR libgcc/64885
......
...@@ -29,6 +29,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see ...@@ -29,6 +29,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
current register window. This is used to set up the stack so that current register window. This is used to set up the stack so that
arbitrary frames can be accessed. */ arbitrary frames can be accessed. */
#if XCHAL_HAVE_WINDOWED && !__XTENSA_CALL0_ABI__
.align 4 .align 4
.global __xtensa_libgcc_window_spill .global __xtensa_libgcc_window_spill
.type __xtensa_libgcc_window_spill,@function .type __xtensa_libgcc_window_spill,@function
...@@ -38,6 +39,7 @@ __xtensa_libgcc_window_spill: ...@@ -38,6 +39,7 @@ __xtensa_libgcc_window_spill:
syscall syscall
retw retw
.size __xtensa_libgcc_window_spill, .-__xtensa_libgcc_window_spill .size __xtensa_libgcc_window_spill, .-__xtensa_libgcc_window_spill
#endif
/* __xtensa_nonlocal_goto: This code does all the hard work of a /* __xtensa_nonlocal_goto: This code does all the hard work of a
...@@ -51,6 +53,7 @@ __xtensa_libgcc_window_spill: ...@@ -51,6 +53,7 @@ __xtensa_libgcc_window_spill:
This function never returns to its caller but instead goes directly This function never returns to its caller but instead goes directly
to the address of the specified goto handler. */ to the address of the specified goto handler. */
#if XCHAL_HAVE_WINDOWED && !__XTENSA_CALL0_ABI__
.align 4 .align 4
.global __xtensa_nonlocal_goto .global __xtensa_nonlocal_goto
.type __xtensa_nonlocal_goto,@function .type __xtensa_nonlocal_goto,@function
...@@ -128,6 +131,7 @@ __xtensa_nonlocal_goto: ...@@ -128,6 +131,7 @@ __xtensa_nonlocal_goto:
retw retw
.size __xtensa_nonlocal_goto, .-__xtensa_nonlocal_goto .size __xtensa_nonlocal_goto, .-__xtensa_nonlocal_goto
#endif
/* __xtensa_sync_caches: This function is called after writing a trampoline /* __xtensa_sync_caches: This function is called after writing a trampoline
...@@ -154,7 +158,9 @@ __xtensa_nonlocal_goto: ...@@ -154,7 +158,9 @@ __xtensa_nonlocal_goto:
.global __xtensa_sync_caches .global __xtensa_sync_caches
.type __xtensa_sync_caches,@function .type __xtensa_sync_caches,@function
__xtensa_sync_caches: __xtensa_sync_caches:
#if XCHAL_HAVE_WINDOWED && !__XTENSA_CALL0_ABI__
entry sp, 32 entry sp, 32
#endif
#if XCHAL_DCACHE_SIZE > 0 #if XCHAL_DCACHE_SIZE > 0
/* Flush the trampoline from the data cache. */ /* Flush the trampoline from the data cache. */
extui a4, a2, 0, XCHAL_DCACHE_LINEWIDTH extui a4, a2, 0, XCHAL_DCACHE_LINEWIDTH
...@@ -182,5 +188,9 @@ __xtensa_sync_caches: ...@@ -182,5 +188,9 @@ __xtensa_sync_caches:
bnez a4, .Licache_loop bnez a4, .Licache_loop
#endif #endif
isync isync
#if XCHAL_HAVE_WINDOWED && !__XTENSA_CALL0_ABI__
retw retw
#else
ret
#endif
.size __xtensa_sync_caches, .-__xtensa_sync_caches .size __xtensa_sync_caches, .-__xtensa_sync_caches
...@@ -52,6 +52,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see ...@@ -52,6 +52,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define ENTRY_BYTE 0x36 #define ENTRY_BYTE 0x36
#endif #endif
#ifdef __XTENSA_WINDOWED_ABI__
#define MD_FALLBACK_FRAME_STATE_FOR xtensa_fallback_frame_state #define MD_FALLBACK_FRAME_STATE_FOR xtensa_fallback_frame_state
static _Unwind_Reason_Code static _Unwind_Reason_Code
...@@ -94,4 +95,6 @@ xtensa_fallback_frame_state (struct _Unwind_Context *context, ...@@ -94,4 +95,6 @@ xtensa_fallback_frame_state (struct _Unwind_Context *context,
return _URC_NO_REASON; return _URC_NO_REASON;
} }
#endif /* __XTENSA_WINDOWED_ABI__ */
#endif /* ifdef inhibit_libc */ #endif /* ifdef inhibit_libc */
LIB2ADDEH = $(srcdir)/config/xtensa/unwind-dw2-xtensa.c \
$(srcdir)/unwind-dw2-fde.c $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c
...@@ -11,6 +11,3 @@ LIB1ASMFUNCS = _mulsi3 _divsi3 _modsi3 _udivsi3 _umodsi3 \ ...@@ -11,6 +11,3 @@ LIB1ASMFUNCS = _mulsi3 _divsi3 _modsi3 _udivsi3 _umodsi3 \
_truncdfsf2 _extendsfdf2 _truncdfsf2 _extendsfdf2
LIB2ADD = $(srcdir)/config/xtensa/lib2funcs.S LIB2ADD = $(srcdir)/config/xtensa/lib2funcs.S
LIB2ADDEH = $(srcdir)/config/xtensa/unwind-dw2-xtensa.c \
$(srcdir)/unwind-dw2-fde.c $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c
...@@ -4810,6 +4810,27 @@ EOF ...@@ -4810,6 +4810,27 @@ EOF
;; ;;
esac esac
# Check if xtensa target is configured for windowed ABI and thus needs to use
# custom unwind code.
# This is after config.host so we can augment tmake_file.
case ${host} in
xtensa*-*)
cat > conftest.c <<EOF
#ifdef __XTENSA_CALL0_ABI__
#error
#endif
EOF
if { ac_try='${CC-cc} -E -o conftest.i conftest.c 1>&5'
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
(eval $ac_try) 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; }; then
tmake_file="${tmake_file} xtensa/t-windowed"
fi
;;
esac
# Check for visibility support. This is after config.host so that # Check for visibility support. This is after config.host so that
# we can check for asm_hidden_op. # we can check for asm_hidden_op.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __attribute__((visibility(\"hidden\")))" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __attribute__((visibility(\"hidden\")))" >&5
......
...@@ -436,6 +436,22 @@ EOF ...@@ -436,6 +436,22 @@ EOF
;; ;;
esac esac
# Check if xtensa target is configured for windowed ABI and thus needs to use
# custom unwind code.
# This is after config.host so we can augment tmake_file.
case ${host} in
xtensa*-*)
cat > conftest.c <<EOF
#ifdef __XTENSA_CALL0_ABI__
#error
#endif
EOF
if AC_TRY_COMMAND(${CC-cc} -E -o conftest.i conftest.c 1>&AS_MESSAGE_LOG_FD); then
tmake_file="${tmake_file} xtensa/t-windowed"
fi
;;
esac
# Check for visibility support. This is after config.host so that # Check for visibility support. This is after config.host so that
# we can check for asm_hidden_op. # we can check for asm_hidden_op.
AC_CACHE_CHECK([for __attribute__((visibility("hidden")))], AC_CACHE_CHECK([for __attribute__((visibility("hidden")))],
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment