Commit 0c96007e by Andrew MacLeod Committed by Jim Wilson

Add partial support for IA-64 unwind sections.

	* config/ia64/crtbegin.asm: Add IA-64 unwind support.  Correct alloc
	and gp save/restore problems.
	* config/ia64/crtend.asm: Add IA-64 unwind support.
	* config/ia64/ia64.c (ia64_compute_frame_size): Don't include pr_size
	in fr_pad_size calculation.
	...

Co-Authored-By: Andrew Haley <aph@cygnus.com>
Co-Authored-By: Jim Wilson <wilson@cygnus.com>

From-SVN: r33424
parent 7d7f30cf
Tue Apr 25 16:16:04 2000 Andrew MacLeod <amacleod@cygnus.com>
Jim Wilson <wilson@cygnus.com>
Andrew Haley <aph@cygnus.com>
* config/ia64/crtbegin.asm: Add IA-64 unwind support. Correct alloc
and gp save/restore problems.
* config/ia64/crtend.asm: Add IA-64 unwind support.
* config/ia64/ia64.c (ia64_compute_frame_size): Don't include pr_size
in fr_pad_size calculation.
(save_restore_insns): Move PR save area. Correct uses of
RTX_FRAME_RELATED_P.
(ia64_expand_prologue): Mark alloc with RTX_FRAME_RELATED_P.
(ia64_expand_epilogue): Add eh_epilogue support.
(ia64_function_prologue): Emit .prologue directive.
(ia64_init_machine_status, ia64_mark_machine_status): New functions.
(ia64_override_options): Set init_machine_status and
mark_machine_status.
(rtx_needs_barrier): Handle bsp reads and writes.
(spill_offset, sp_offset, spill_offset_emitted, tmp_reg, tmp_saved):
New static variables.
(process_set, process_for_unwind_directive): New functions.
* config/ia64/ia64.h (ASM_OUTPUT_XDATA_CHAR, ASM_OUTPUT_XDATA_SHORT,
ASM_OUTPUT_XDATA_INT, ASM_OUTPUT_XDATA_DOUBLE_INT, ASM_OUTPUT_EH_CHAR,
ASM_OUTPUT_EH_SHORT, ASM_OUTPUT_EH_INT, ASM_OUTPUT_EH_DOUBLE_INT): New
macros.
(EH_FRAME_SECTION_ASM_OP): Define to IA_64.unwind section.
(IA64_UNWIND_INFO, HANDLER_SECTION, IA64_UNWIND_EMIT): Define.
(struct machine_function): Define.
* config/ia64/ia64.md (bsp_value, set_bsp, eh_epilogue): New patterns.
2000-04-25 Bruce Korb <bkorb@gnu.org>
* fixinc/Makefile.in: make the removal of old programs more
......
......@@ -26,12 +26,17 @@ __CTOR_LIST__:
__DTOR_LIST__:
data8 -1
.section .IA_64.unwind
__EH_FRAME_BEGIN__:
.section .sdata
5: data8 @segrel(6f)
.type dtor_ptr#,@object
.size dtor_ptr#,8
dtor_ptr:
data8 __DTOR_LIST__# + 8
/* A handle for __cxa_finalize to manage c++ local destructors. */
.global __dso_handle#
.type __dso_handle#,@object
.size __dso_handle#,8
......@@ -45,6 +50,16 @@ __dso_handle:
data8 0
#endif
/* The frame object. */
/* ??? How can we rationally keep this size correct? */
.section .bss
.type frame_object#,@object
.size frame_object#,56
.align 8
frame_object:
.zero 56
/*
* Fragment of the ELF _fini routine that invokes our dtor cleanup.
*
......@@ -65,38 +80,55 @@ __dso_handle:
;;
}
.text
/*
* Fragment of the ELF _init routine that sets up the frame info.
*/
.section .init,"ax","progbits"
{ .mfb
st8 [r12] = gp, -16
br.call.sptk.many b0 = __do_frame_setup#
;;
}
{ .mmi
adds r12 = 16, r12
;;
ld8 gp = [r12]
;;
}
.section .text
.align 16
.proc __do_global_dtors_aux#
__do_global_dtors_aux:
#ifndef SHARED
{ .mii
alloc loc2 = ar.pfs, 0, 3, 0, 0
alloc loc3 = ar.pfs, 0, 4, 1, 0
addl loc0 = @gprel(dtor_ptr#), gp
mov loc1 = b0
}
mov loc2 = gp
#else
/*
if (__cxa_finalize)
__cxa_finalize(__dso_handle)
*/
{ .mii
alloc loc2 = ar.pfs, 1, 3, 0, 0
alloc loc3 = ar.pfs, 0, 4, 1, 0
addl loc0 = @gprel(dtor_ptr#), gp
addl r16 = @ltoff(@fptr(__cxa_finalize#)), gp
;;
}
mov loc2 = gp
{ .mmi
ld8 r16 = [r16]
;;
addl r32 = @ltoff(__dso_handle#), gp
addl out0 = @ltoff(__dso_handle#), gp
cmp.ne p7, p0 = r0, r16
;;
}
{ .mmi
ld8 r32 = [r32]
ld8 out0 = [out0]
(p7) ld8 r18 = [r16], 8
mov loc1 = b0
;;
......@@ -139,9 +171,36 @@ __do_global_dtors_aux:
cmp.ne p6, p0 = r0, r16
(p6) br.cond.sptk.few 0b
}
mov gp = loc2
;;
/*
if (__deregister_frame_info)
__deregister_frame_info(__EH_FRAME_BEGIN__)
*/
{ .mii
addl r16 = @ltoff(@fptr(__deregister_frame_info#)), gp
addl out0 = @ltoff(__EH_FRAME_BEGIN__#), gp
;;
}
{ .mmi
ld8 r16 = [r16]
ld8 out0 = [out0]
;;
}
{ .mmi
cmp.ne p7, p0 = r0, r16
;;
(p7) ld8 r18 = [r16], 8
;;
}
{ .mib
(p7) ld8 gp = [r16]
(p7) mov b6 = r18
(p7) br.call.sptk.many b0 = b6
}
{ .mii
mov b0 = loc1
mov ar.pfs = loc2
mov ar.pfs = loc3
}
{ .bbb
br.ret.sptk.many b0
......@@ -149,6 +208,61 @@ __do_global_dtors_aux:
}
.endp __do_global_dtors_aux#
.proc __do_frame_setup#
__do_frame_setup:
/*
if (__register_frame_info)
__register_frame_info(__EH_FRAME_BEGIN__)
*/
{ .mii
alloc loc3 = ar.pfs, 0, 4, 2, 0
addl r16 = @ltoff(@fptr(__register_frame_info#)), gp
addl out0 = @ltoff(__EH_FRAME_BEGIN__#), gp
;;
}
addl out1 = @ltoff(frame_object#), gp
;;
/* frame_object.pc_base = segment_base_offset;
pc_base is at offset 0 within frame_object. */
6:
mov loc0 = ip
addl loc1 = @gprel(5b), gp
;;
ld8 loc1 = [loc1]
ld8 out1 = [out1]
;;
sub loc2 = loc0, loc1
;;
st8 [out1] = loc2
{ .mmi
ld8 r16 = [r16]
ld8 out0 = [out0]
mov loc0 = b0
;;
}
{ .mmi
cmp.ne p7, p0 = r0, r16
;;
(p7) ld8 r18 = [r16], 8
;;
}
{ .mib
(p7) ld8 gp = [r16]
(p7) mov b6 = r18
(p7) br.call.sptk.many b0 = b6
}
{ .mii
mov b0 = loc0
mov ar.pfs = loc3
}
{ .bbb
br.ret.sptk.many b0
;;
}
.endp __do_frame_setup#
#ifdef SHARED
.weak __cxa_finalize#
#endif
.weak __deregister_frame_info#
.weak __register_frame_info#
......@@ -26,6 +26,10 @@ __CTOR_END__:
__DTOR_END__:
data8 0
.section .IA_64.unwind
__EH_FRAME_END__:
data8 -1
/*
* Fragment of the ELF _init routine that invokes our dtor cleanup.
*
......
......@@ -2115,6 +2115,71 @@ do { \
fprintf (FILE, "\n"); \
} while (0)
/* This is how to output an assembler line defining a `char' constant
to an xdata segment. */
#define ASM_OUTPUT_XDATA_CHAR(FILE, SECTION, VALUE) \
do { \
fprintf (FILE, "\t.xdata1\t\"%s\", ", SECTION); \
output_addr_const (FILE, (VALUE)); \
fprintf (FILE, "\n"); \
} while (0)
/* This is how to output an assembler line defining a `short' constant
to an xdata segment. */
#define ASM_OUTPUT_XDATA_SHORT(FILE, SECTION, VALUE) \
do { \
fprintf (FILE, "\t.xdata2\t\"%s\", ", SECTION); \
output_addr_const (FILE, (VALUE)); \
fprintf (FILE, "\n"); \
} while (0)
/* This is how to output an assembler line defining an `int' constant
to an xdata segment. We also handle symbol output here. */
/* ??? For ILP32, also need to handle function addresses here. */
#define ASM_OUTPUT_XDATA_INT(FILE, SECTION, VALUE) \
do { \
fprintf (FILE, "\t.xdata4\t\"%s\", ", SECTION); \
output_addr_const (FILE, (VALUE)); \
fprintf (FILE, "\n"); \
} while (0)
/* This is how to output an assembler line defining a `long' constant
to an xdata segment. We also handle symbol output here. */
#define ASM_OUTPUT_XDATA_DOUBLE_INT(FILE, SECTION, VALUE) \
do { \
fprintf (FILE, "\t.xdata8\t\"%s\", ", SECTION); \
if (GET_CODE (VALUE) == SYMBOL_REF) \
{ \
if (SYMBOL_REF_FLAG (VALUE)) \
fprintf (FILE, "@fptr("); \
else \
fprintf (FILE, "@segrel("); \
} \
output_addr_const (FILE, (VALUE)); \
if (GET_CODE (VALUE) == SYMBOL_REF) \
fprintf (FILE, ")"); \
fprintf (FILE, "\n"); \
} while (0)
/* Output EH data to the unwind segment. */
#define ASM_OUTPUT_EH_CHAR(FILE, VALUE) \
ASM_OUTPUT_XDATA_CHAR(FILE, ".IA_64.unwind_info", VALUE)
#define ASM_OUTPUT_EH_SHORT(FILE, VALUE) \
ASM_OUTPUT_XDATA_SHORT(FILE, ".IA_64.unwind_info", VALUE)
#define ASM_OUTPUT_EH_INT(FILE, VALUE) \
ASM_OUTPUT_XDATA_INT(FILE, ".IA_64.unwind_info", VALUE)
#define ASM_OUTPUT_EH_DOUBLE_INT(FILE, VALUE) \
ASM_OUTPUT_XDATA_DOUBLE_INT(FILE, ".IA_64.unwind_info", VALUE)
/* A C statement to output to the stdio stream STREAM an assembler instruction
to assemble a single byte containing the number VALUE. */
......@@ -2453,7 +2518,7 @@ do { \
You should define this symbol if your target supports DWARF 2 frame unwind
information and the default definition does not work. */
/* #define EH_FRAME_SECTION_ASM_OP */
#define EH_FRAME_SECTION_ASM_OP ".section\t.IA_64.unwind,\"aw\""
/* A C expression that is nonzero if the normal exception table output should
be omitted.
......@@ -2739,6 +2804,21 @@ do { \
#define ISSUE_RATE 3
#define IA64_UNWIND_INFO 1
#define HANDLER_SECTION fprintf (asm_out_file, "\t.personality\t__ia64_personality_v1\n\t.handlerdata\n");
#define IA64_UNWIND_EMIT(f,i) process_for_unwind_directive (f,i)
/* This function contains machine specific function data. */
struct machine_function
{
/* The new stack pointer when unwinding from EH. */
struct rtx_def* ia64_eh_epilogue_sp;
/* The new bsp value when unwinding from EH. */
struct rtx_def* ia64_eh_epilogue_bsp;
};
enum ia64_builtins
{
IA64_BUILTIN_SYNCHRONIZE,
......
......@@ -3083,6 +3083,33 @@
"mov ar.unat = %0"
[(set_attr "type" "M")])
(define_insn "bsp_value"
[(set (match_operand:DI 0 "register_operand" "=r")
(unspec:DI [(const_int 0)] 20))]
""
"mov %0 = ar.bsp"
[(set_attr "type" "I")])
(define_insn "set_bsp"
[(unspec_volatile [(const_int 0)] 5)
(use (match_operand:DI 0 "register_operand" "r"))]
""
"flushrs\; \
mov r19=ar.rsc\; \
;;\; \
and r19=0x1c,r19\; \
;;\; \
mov ar.rsc=r19\; \
;;\; \
mov ar.bspstore=%0\; \
;;\; \
or r19=0x3,r19\; \
;;\; \
loadrs\; \
invala\; \
;;\; \
mov ar.rsc=r19\;"
[(set_attr "type" "I")])
;; ::::::::::::::::::::
;; ::
......@@ -3166,6 +3193,34 @@
DONE;
}")
(define_expand "eh_epilogue"
[(use (match_operand:DI 0 "register_operand" "r"))
(use (match_operand:DI 1 "register_operand" "r"))
(use (match_operand:DI 2 "register_operand" "r"))]
""
"
{
rtx bsp = gen_rtx_REG (Pmode, 10);
rtx sp = gen_rtx_REG (Pmode, 9);
if (GET_CODE (operands[0]) != REG || REGNO (operands[0]) != 10)
{
emit_move_insn (bsp, operands[0]);
operands[0] = bsp;
}
if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 9)
{
emit_move_insn (sp, operands[2]);
operands[2] = sp;
}
emit_insn (gen_rtx_USE (VOIDmode, sp));
emit_insn (gen_rtx_USE (VOIDmode, bsp));
cfun->machine->ia64_eh_epilogue_sp = sp;
cfun->machine->ia64_eh_epilogue_bsp = bsp;
}")
;; This flushes at least 64 bytes starting from the address pointed
;; to by operand[0].
......
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