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
This commit is contained in:
parent
7d7f30cfa0
commit
0c96007e77
|
@ -1,3 +1,33 @@
|
||||||
|
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>
|
2000-04-25 Bruce Korb <bkorb@gnu.org>
|
||||||
|
|
||||||
* fixinc/Makefile.in: make the removal of old programs more
|
* fixinc/Makefile.in: make the removal of old programs more
|
||||||
|
|
|
@ -26,12 +26,17 @@ __CTOR_LIST__:
|
||||||
__DTOR_LIST__:
|
__DTOR_LIST__:
|
||||||
data8 -1
|
data8 -1
|
||||||
|
|
||||||
|
.section .IA_64.unwind
|
||||||
|
__EH_FRAME_BEGIN__:
|
||||||
|
|
||||||
.section .sdata
|
.section .sdata
|
||||||
|
5: data8 @segrel(6f)
|
||||||
.type dtor_ptr#,@object
|
.type dtor_ptr#,@object
|
||||||
.size dtor_ptr#,8
|
.size dtor_ptr#,8
|
||||||
dtor_ptr:
|
dtor_ptr:
|
||||||
data8 __DTOR_LIST__# + 8
|
data8 __DTOR_LIST__# + 8
|
||||||
|
|
||||||
|
/* A handle for __cxa_finalize to manage c++ local destructors. */
|
||||||
.global __dso_handle#
|
.global __dso_handle#
|
||||||
.type __dso_handle#,@object
|
.type __dso_handle#,@object
|
||||||
.size __dso_handle#,8
|
.size __dso_handle#,8
|
||||||
|
@ -45,6 +50,16 @@ __dso_handle:
|
||||||
data8 0
|
data8 0
|
||||||
#endif
|
#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.
|
* 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
|
.align 16
|
||||||
.proc __do_global_dtors_aux#
|
.proc __do_global_dtors_aux#
|
||||||
|
|
||||||
__do_global_dtors_aux:
|
__do_global_dtors_aux:
|
||||||
#ifndef SHARED
|
#ifndef SHARED
|
||||||
{ .mii
|
{ .mii
|
||||||
alloc loc2 = ar.pfs, 0, 3, 0, 0
|
alloc loc3 = ar.pfs, 0, 4, 1, 0
|
||||||
addl loc0 = @gprel(dtor_ptr#), gp
|
addl loc0 = @gprel(dtor_ptr#), gp
|
||||||
mov loc1 = b0
|
mov loc1 = b0
|
||||||
}
|
}
|
||||||
|
mov loc2 = gp
|
||||||
#else
|
#else
|
||||||
/*
|
/*
|
||||||
if (__cxa_finalize)
|
if (__cxa_finalize)
|
||||||
__cxa_finalize(__dso_handle)
|
__cxa_finalize(__dso_handle)
|
||||||
*/
|
*/
|
||||||
{ .mii
|
{ .mii
|
||||||
alloc loc2 = ar.pfs, 1, 3, 0, 0
|
alloc loc3 = ar.pfs, 0, 4, 1, 0
|
||||||
addl loc0 = @gprel(dtor_ptr#), gp
|
addl loc0 = @gprel(dtor_ptr#), gp
|
||||||
addl r16 = @ltoff(@fptr(__cxa_finalize#)), gp
|
addl r16 = @ltoff(@fptr(__cxa_finalize#)), gp
|
||||||
;;
|
;;
|
||||||
}
|
}
|
||||||
|
mov loc2 = gp
|
||||||
{ .mmi
|
{ .mmi
|
||||||
ld8 r16 = [r16]
|
ld8 r16 = [r16]
|
||||||
;;
|
;;
|
||||||
addl r32 = @ltoff(__dso_handle#), gp
|
addl out0 = @ltoff(__dso_handle#), gp
|
||||||
cmp.ne p7, p0 = r0, r16
|
cmp.ne p7, p0 = r0, r16
|
||||||
;;
|
;;
|
||||||
}
|
}
|
||||||
{ .mmi
|
{ .mmi
|
||||||
ld8 r32 = [r32]
|
ld8 out0 = [out0]
|
||||||
(p7) ld8 r18 = [r16], 8
|
(p7) ld8 r18 = [r16], 8
|
||||||
mov loc1 = b0
|
mov loc1 = b0
|
||||||
;;
|
;;
|
||||||
|
@ -138,10 +170,37 @@ __do_global_dtors_aux:
|
||||||
{ .mfb
|
{ .mfb
|
||||||
cmp.ne p6, p0 = r0, r16
|
cmp.ne p6, p0 = r0, r16
|
||||||
(p6) br.cond.sptk.few 0b
|
(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
|
{ .mii
|
||||||
mov b0 = loc1
|
mov b0 = loc1
|
||||||
mov ar.pfs = loc2
|
mov ar.pfs = loc3
|
||||||
}
|
}
|
||||||
{ .bbb
|
{ .bbb
|
||||||
br.ret.sptk.many b0
|
br.ret.sptk.many b0
|
||||||
|
@ -149,6 +208,61 @@ __do_global_dtors_aux:
|
||||||
}
|
}
|
||||||
.endp __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
|
#ifdef SHARED
|
||||||
.weak __cxa_finalize#
|
.weak __cxa_finalize#
|
||||||
#endif
|
#endif
|
||||||
|
.weak __deregister_frame_info#
|
||||||
|
.weak __register_frame_info#
|
||||||
|
|
|
@ -26,6 +26,10 @@ __CTOR_END__:
|
||||||
__DTOR_END__:
|
__DTOR_END__:
|
||||||
data8 0
|
data8 0
|
||||||
|
|
||||||
|
.section .IA_64.unwind
|
||||||
|
__EH_FRAME_END__:
|
||||||
|
data8 -1
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fragment of the ELF _init routine that invokes our dtor cleanup.
|
* Fragment of the ELF _init routine that invokes our dtor cleanup.
|
||||||
*
|
*
|
||||||
|
|
|
@ -567,7 +567,7 @@ ia64_compute_frame_size (size)
|
||||||
/* The FR save area needs to be 16-byte aligned. */
|
/* The FR save area needs to be 16-byte aligned. */
|
||||||
if (fr_size)
|
if (fr_size)
|
||||||
{
|
{
|
||||||
tmp = (size + fr_size + pr_size + br_size);
|
tmp = (size + fr_size + br_size);
|
||||||
fr_pad_size = IA64_STACK_ALIGN (tmp) - tmp;
|
fr_pad_size = IA64_STACK_ALIGN (tmp) - tmp;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -653,14 +653,36 @@ save_restore_insns (save_p)
|
||||||
{
|
{
|
||||||
offset_rtx = tmp_reg;
|
offset_rtx = tmp_reg;
|
||||||
insn = emit_insn (gen_movdi (tmp_reg, GEN_INT (offset)));
|
insn = emit_insn (gen_movdi (tmp_reg, GEN_INT (offset)));
|
||||||
|
if (save_p)
|
||||||
RTX_FRAME_RELATED_P (insn) = 1;
|
RTX_FRAME_RELATED_P (insn) = 1;
|
||||||
}
|
}
|
||||||
insn = emit_insn (gen_adddi3 (tmp_reg,
|
insn = emit_insn (gen_adddi3 (tmp_reg,
|
||||||
(frame_pointer_needed ? frame_pointer_rtx
|
(frame_pointer_needed ? frame_pointer_rtx
|
||||||
: stack_pointer_rtx),
|
: stack_pointer_rtx),
|
||||||
offset_rtx));
|
offset_rtx));
|
||||||
|
if (save_p)
|
||||||
RTX_FRAME_RELATED_P (insn) = 1;
|
RTX_FRAME_RELATED_P (insn) = 1;
|
||||||
|
|
||||||
|
/* If one is used, we save/restore all of them. */
|
||||||
|
for (regno = PR_REG (0); regno <= PR_REG (63); regno++)
|
||||||
|
if (TEST_HARD_REG_BIT (current_frame_info.mask, regno))
|
||||||
|
{
|
||||||
|
rtx mem = gen_rtx_MEM (DImode, tmp_post_inc);
|
||||||
|
if (save_p)
|
||||||
|
{
|
||||||
|
insn = emit_insn (gen_pr_spill (tmp2_reg));
|
||||||
|
RTX_FRAME_RELATED_P (insn) = 1;
|
||||||
|
insn = emit_insn (gen_movdi (mem, tmp2_reg));
|
||||||
|
RTX_FRAME_RELATED_P (insn) = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
insn = emit_insn (gen_movdi (tmp2_reg, mem));
|
||||||
|
insn = emit_insn (gen_pr_restore (tmp2_reg));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Must save/restore ar.unat if any GR is spilled/restored. */
|
/* Must save/restore ar.unat if any GR is spilled/restored. */
|
||||||
if (current_frame_info.gr_size != 0
|
if (current_frame_info.gr_size != 0
|
||||||
|| current_function_varargs || current_function_stdarg)
|
|| current_function_varargs || current_function_stdarg)
|
||||||
|
@ -669,13 +691,16 @@ save_restore_insns (save_p)
|
||||||
if (save_p)
|
if (save_p)
|
||||||
{
|
{
|
||||||
insn = emit_insn (gen_unat_spill (tmp2_reg));
|
insn = emit_insn (gen_unat_spill (tmp2_reg));
|
||||||
|
if (save_p)
|
||||||
RTX_FRAME_RELATED_P (insn) = 1;
|
RTX_FRAME_RELATED_P (insn) = 1;
|
||||||
insn = emit_insn (gen_movdi (mem, tmp2_reg));
|
insn = emit_insn (gen_movdi (mem, tmp2_reg));
|
||||||
|
if (save_p)
|
||||||
RTX_FRAME_RELATED_P (insn) = 1;
|
RTX_FRAME_RELATED_P (insn) = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
insn = emit_insn (gen_movdi (tmp2_reg, mem));
|
insn = emit_insn (gen_movdi (tmp2_reg, mem));
|
||||||
|
if (save_p)
|
||||||
RTX_FRAME_RELATED_P (insn) = 1;
|
RTX_FRAME_RELATED_P (insn) = 1;
|
||||||
/* The restore happens after the last ld8.fill instruction. */
|
/* The restore happens after the last ld8.fill instruction. */
|
||||||
}
|
}
|
||||||
|
@ -691,6 +716,7 @@ save_restore_insns (save_p)
|
||||||
else
|
else
|
||||||
insn = emit_insn (gen_gr_restore (gen_rtx_REG (DImode, regno),
|
insn = emit_insn (gen_gr_restore (gen_rtx_REG (DImode, regno),
|
||||||
mem));
|
mem));
|
||||||
|
if (save_p)
|
||||||
RTX_FRAME_RELATED_P (insn) = 1;
|
RTX_FRAME_RELATED_P (insn) = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -710,29 +736,8 @@ save_restore_insns (save_p)
|
||||||
else
|
else
|
||||||
insn = emit_insn (gen_fr_restore (gen_rtx_REG (XFmode, regno),
|
insn = emit_insn (gen_fr_restore (gen_rtx_REG (XFmode, regno),
|
||||||
mem));
|
mem));
|
||||||
RTX_FRAME_RELATED_P (insn) = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If one is used, we save/restore all of them. */
|
|
||||||
for (regno = PR_REG (0); regno <= PR_REG (63); regno++)
|
|
||||||
if (TEST_HARD_REG_BIT (current_frame_info.mask, regno))
|
|
||||||
{
|
|
||||||
rtx mem = gen_rtx_MEM (DImode, tmp_post_inc);
|
|
||||||
if (save_p)
|
if (save_p)
|
||||||
{
|
|
||||||
insn = emit_insn (gen_pr_spill (tmp2_reg));
|
|
||||||
RTX_FRAME_RELATED_P (insn) = 1;
|
RTX_FRAME_RELATED_P (insn) = 1;
|
||||||
insn = emit_insn (gen_movdi (mem, tmp2_reg));
|
|
||||||
RTX_FRAME_RELATED_P (insn) = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
insn = emit_insn (gen_movdi (tmp2_reg, mem));
|
|
||||||
RTX_FRAME_RELATED_P (insn) = 1;
|
|
||||||
insn = emit_insn (gen_pr_restore (tmp2_reg));
|
|
||||||
RTX_FRAME_RELATED_P (insn) = 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (regno = BR_REG (0); regno <= BR_REG (7); regno++)
|
for (regno = BR_REG (0); regno <= BR_REG (7); regno++)
|
||||||
|
@ -752,8 +757,10 @@ save_restore_insns (save_p)
|
||||||
}
|
}
|
||||||
|
|
||||||
insn = emit_insn (gen_movdi (tmp2_reg, src));
|
insn = emit_insn (gen_movdi (tmp2_reg, src));
|
||||||
|
if (save_p)
|
||||||
RTX_FRAME_RELATED_P (insn) = 1;
|
RTX_FRAME_RELATED_P (insn) = 1;
|
||||||
insn = emit_insn (gen_movdi (dest, tmp2_reg));
|
insn = emit_insn (gen_movdi (dest, tmp2_reg));
|
||||||
|
if (save_p)
|
||||||
RTX_FRAME_RELATED_P (insn) = 1;
|
RTX_FRAME_RELATED_P (insn) = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -933,9 +940,10 @@ ia64_expand_prologue ()
|
||||||
ia64_need_regstk = 0;
|
ia64_need_regstk = 0;
|
||||||
ia64_arpfs_regno = LOC_REG (locals - 1);
|
ia64_arpfs_regno = LOC_REG (locals - 1);
|
||||||
|
|
||||||
emit_insn (gen_alloc (gen_rtx_REG (DImode, ia64_arpfs_regno),
|
insn = emit_insn (gen_alloc (gen_rtx_REG (DImode, ia64_arpfs_regno),
|
||||||
GEN_INT (inputs), GEN_INT (locals),
|
GEN_INT (inputs), GEN_INT (locals),
|
||||||
GEN_INT (outputs), GEN_INT (rotates)));
|
GEN_INT (outputs), GEN_INT (rotates)));
|
||||||
|
RTX_FRAME_RELATED_P (insn) = 1;
|
||||||
|
|
||||||
/* Emit a save of BR_REG (0) if we call other functions.
|
/* Emit a save of BR_REG (0) if we call other functions.
|
||||||
Do this even if this function doesn't return, as EH
|
Do this even if this function doesn't return, as EH
|
||||||
|
@ -1020,6 +1028,8 @@ ia64_expand_epilogue ()
|
||||||
pointer updates anti-dependent on them. */
|
pointer updates anti-dependent on them. */
|
||||||
emit_insn (gen_blockage ());
|
emit_insn (gen_blockage ());
|
||||||
|
|
||||||
|
if (cfun->machine->ia64_eh_epilogue_sp == NULL_RTX)
|
||||||
|
{
|
||||||
if (frame_pointer_needed)
|
if (frame_pointer_needed)
|
||||||
{
|
{
|
||||||
/* If there is a frame pointer, then we need to make the stack pointer
|
/* If there is a frame pointer, then we need to make the stack pointer
|
||||||
|
@ -1046,6 +1056,10 @@ ia64_expand_epilogue ()
|
||||||
offset));
|
offset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
/* Return via eh_epilogue, so we already have our new stack pointer. */
|
||||||
|
else
|
||||||
|
emit_insn (gen_movdi (stack_pointer_rtx, cfun->machine->ia64_eh_epilogue_sp));
|
||||||
|
|
||||||
if (ia64_arpfs_regno)
|
if (ia64_arpfs_regno)
|
||||||
emit_insn (gen_pfs_restore (gen_rtx_REG (DImode, ia64_arpfs_regno)));
|
emit_insn (gen_pfs_restore (gen_rtx_REG (DImode, ia64_arpfs_regno)));
|
||||||
|
@ -1054,6 +1068,11 @@ ia64_expand_epilogue ()
|
||||||
emit_move_insn (gen_rtx_REG (DImode, BR_REG (0)),
|
emit_move_insn (gen_rtx_REG (DImode, BR_REG (0)),
|
||||||
gen_rtx_REG (DImode, ia64_rp_regno));
|
gen_rtx_REG (DImode, ia64_rp_regno));
|
||||||
|
|
||||||
|
if (cfun->machine->ia64_eh_epilogue_bsp != NULL_RTX)
|
||||||
|
{
|
||||||
|
/* We have to restore the bsp. */
|
||||||
|
emit_insn (gen_set_bsp (cfun->machine->ia64_eh_epilogue_bsp));
|
||||||
|
}
|
||||||
emit_jump_insn (gen_return_internal (gen_rtx_REG (DImode, BR_REG (0))));
|
emit_jump_insn (gen_return_internal (gen_rtx_REG (DImode, BR_REG (0))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1064,10 +1083,39 @@ ia64_function_prologue (file, size)
|
||||||
FILE *file;
|
FILE *file;
|
||||||
int size;
|
int size;
|
||||||
{
|
{
|
||||||
|
rtx insn;
|
||||||
if (ia64_need_regstk)
|
if (ia64_need_regstk)
|
||||||
fprintf (file, "\t.regstk %d, 0, 0, 0\n", ia64_input_regs);
|
fprintf (file, "\t.regstk %d, 0, 0, 0\n", ia64_input_regs);
|
||||||
|
|
||||||
/* ??? Emit .body directive. GNU as ignores .body currently. */
|
if (!flag_unwind_tables && (!flag_exceptions || exceptions_via_longjmp))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Emit the .prologue directive. in order to do this, we need to find
|
||||||
|
where the stack pointer is moved toa GR, if it is, and mark it. */
|
||||||
|
|
||||||
|
for (insn = get_insns (); insn != NULL_RTX; insn = NEXT_INSN (insn))
|
||||||
|
{
|
||||||
|
if (RTX_FRAME_RELATED_P (insn) && GET_CODE (insn) == INSN)
|
||||||
|
{
|
||||||
|
rtx pat = PATTERN (insn);
|
||||||
|
if (GET_CODE (pat) == SET)
|
||||||
|
{
|
||||||
|
rtx dest = SET_DEST (pat);
|
||||||
|
rtx src = SET_SRC (pat);
|
||||||
|
if (GET_CODE (src) == REG && REGNO (src) == STACK_POINTER_REGNUM
|
||||||
|
&& GET_CODE (dest) == REG)
|
||||||
|
{
|
||||||
|
int reg = REGNO (dest);
|
||||||
|
if (REGNO (dest) == FRAME_POINTER_REGNUM)
|
||||||
|
reg = ia64_fp_regno;
|
||||||
|
fprintf (file, "\t.prologue 0x2, %d\n", reg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (insn == NULL_RTX)
|
||||||
|
fprintf (file, "\t.prologue\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Emit the function epilogue. */
|
/* Emit the function epilogue. */
|
||||||
|
@ -1987,6 +2035,23 @@ ia64_add_gc_roots ()
|
||||||
ggc_add_rtx_root (&ia64_compare_op1, 1);
|
ggc_add_rtx_root (&ia64_compare_op1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ia64_init_machine_status (p)
|
||||||
|
struct function *p;
|
||||||
|
{
|
||||||
|
p->machine =
|
||||||
|
(struct machine_function *) xcalloc (1, sizeof (struct machine_function));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ia64_mark_machine_status (p)
|
||||||
|
struct function *p;
|
||||||
|
{
|
||||||
|
ggc_mark_rtx (p->machine->ia64_eh_epilogue_sp);
|
||||||
|
ggc_mark_rtx (p->machine->ia64_eh_epilogue_bsp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Handle TARGET_OPTIONS switches. */
|
/* Handle TARGET_OPTIONS switches. */
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1997,6 +2062,9 @@ ia64_override_options ()
|
||||||
|
|
||||||
ia64_section_threshold = g_switch_set ? g_switch_value : IA64_DEFAULT_GVALUE;
|
ia64_section_threshold = g_switch_set ? g_switch_value : IA64_DEFAULT_GVALUE;
|
||||||
|
|
||||||
|
init_machine_status = ia64_init_machine_status;
|
||||||
|
mark_machine_status = ia64_mark_machine_status;
|
||||||
|
|
||||||
ia64_add_gc_roots ();
|
ia64_add_gc_roots ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2445,6 +2513,9 @@ rtx_needs_barrier (x, flags, pred)
|
||||||
break;
|
break;
|
||||||
case 19: /* fetchadd_acq */
|
case 19: /* fetchadd_acq */
|
||||||
break;
|
break;
|
||||||
|
case 20: /* mov = ar.bsp */
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
abort ();
|
abort ();
|
||||||
}
|
}
|
||||||
|
@ -2485,6 +2556,10 @@ rtx_needs_barrier (x, flags, pred)
|
||||||
need_barrier |= rws_access_reg (i, new_flags, pred);
|
need_barrier |= rws_access_reg (i, new_flags, pred);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 5: /* set_bsp */
|
||||||
|
need_barrier = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
abort ();
|
abort ();
|
||||||
}
|
}
|
||||||
|
@ -2749,6 +2824,232 @@ ia64_encode_section_info (decl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Output assmebly directives for prologue regions. */
|
||||||
|
|
||||||
|
static int spill_offset;
|
||||||
|
static int sp_offset;
|
||||||
|
static int spill_offset_emitted = 1;
|
||||||
|
static rtx tmp_reg = NULL_RTX;
|
||||||
|
static int tmp_saved = -1;
|
||||||
|
|
||||||
|
|
||||||
|
/* This function processes a SET pattern looking for specific patterns
|
||||||
|
which result in emitting an assembly directive required for unwinding. */
|
||||||
|
static int
|
||||||
|
process_set (asm_out_file, pat)
|
||||||
|
FILE *asm_out_file;
|
||||||
|
rtx pat;
|
||||||
|
{
|
||||||
|
rtx src = SET_SRC (pat);
|
||||||
|
rtx dest = SET_DEST (pat);
|
||||||
|
static rtx frame_reg = NULL_RTX;
|
||||||
|
static int frame_size = 0;
|
||||||
|
|
||||||
|
/* Look for the ALLOC insn. reg = alloc .... */
|
||||||
|
if (GET_CODE (src) == UNSPEC_VOLATILE && XINT (src, 1) == 0
|
||||||
|
&& GET_CODE (dest) == REG && GR_REGNO_P (REGNO (dest)))
|
||||||
|
{
|
||||||
|
/* Assume this is a stack allocate insn. */
|
||||||
|
fprintf (asm_out_file, "\t.save ar.pfs, r%d\n",
|
||||||
|
REGNO (dest) + ia64_input_regs);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* look for SP = .... */
|
||||||
|
if (GET_CODE (dest) == REG && REGNO (dest) == STACK_POINTER_REGNUM)
|
||||||
|
{
|
||||||
|
if (GET_CODE (src) == PLUS)
|
||||||
|
{
|
||||||
|
rtx op0 = XEXP (src, 0);
|
||||||
|
rtx op1 = XEXP (src, 1);
|
||||||
|
if (op0 == dest && GET_CODE (op1) == CONST_INT)
|
||||||
|
{
|
||||||
|
fprintf (asm_out_file, "\t.fframe %d\n", -INTVAL (op1));
|
||||||
|
frame_size = INTVAL (op1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (op0 == dest && GET_CODE (op1) == REG)
|
||||||
|
{
|
||||||
|
fprintf (asm_out_file, "\t.vframe r%d\n", REGNO (op1));
|
||||||
|
frame_size = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Look for a frame offset. */
|
||||||
|
if (GET_CODE (dest) == REG)
|
||||||
|
{
|
||||||
|
if (GET_CODE (src) == PLUS)
|
||||||
|
{
|
||||||
|
rtx op0 = XEXP (src, 0);
|
||||||
|
rtx op1 = XEXP (src, 1);
|
||||||
|
if (GET_CODE (op0) == REG && REGNO (op0) == FRAME_POINTER_REGNUM
|
||||||
|
&& GET_CODE (op1) == CONST_INT)
|
||||||
|
{
|
||||||
|
sp_offset = -frame_size + INTVAL (op1);
|
||||||
|
spill_offset = INTVAL (op1);
|
||||||
|
spill_offset_emitted = 0;
|
||||||
|
frame_reg = dest;
|
||||||
|
/* We delay issuing the spill offset since we might
|
||||||
|
be saving non-spill things off this register,
|
||||||
|
thus adjusting its offset before a spill is seen. */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Register move we need to look at. */
|
||||||
|
if (GET_CODE (dest) == REG && GET_CODE (src) == REG)
|
||||||
|
{
|
||||||
|
int regno = REGNO (src);
|
||||||
|
if (BR_REGNO_P (regno))
|
||||||
|
{
|
||||||
|
/* Saving return address pointer. */
|
||||||
|
if (regno == BR_REG (0))
|
||||||
|
{
|
||||||
|
fprintf (asm_out_file, "\t.save rp, r%d\n",
|
||||||
|
REGNO (dest) + ia64_input_regs);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/* If its br1 to br5, we copy them to temp regs, then save the
|
||||||
|
temp reg to memory next. */
|
||||||
|
if (regno >= BR_REG (1) && regno <= BR_REG (5))
|
||||||
|
{
|
||||||
|
tmp_reg = dest;
|
||||||
|
tmp_saved = regno;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Search for special reg moves. */
|
||||||
|
if (GET_CODE (dest) == REG && GET_CODE (src) == UNSPEC)
|
||||||
|
{
|
||||||
|
int unspec_code = XINT (src, 1);
|
||||||
|
/* Copied to a temp register, save it until we see the temp
|
||||||
|
register stored. */
|
||||||
|
if (unspec_code == 5 || unspec_code == 9)
|
||||||
|
{
|
||||||
|
tmp_reg = dest;
|
||||||
|
tmp_saved = unspec_code;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (GET_CODE (dest) == MEM && GET_CODE (XEXP (dest, 0)) == POST_INC
|
||||||
|
&& GET_CODE (XEXP (XEXP (dest, 0), 0)) == REG)
|
||||||
|
{
|
||||||
|
int spill_unspec = 0;
|
||||||
|
/* We adjust the spill_offset early, so we dont miss it later. */
|
||||||
|
spill_offset += 8;
|
||||||
|
sp_offset += 8;
|
||||||
|
if (GET_CODE (src) == UNSPEC)
|
||||||
|
{
|
||||||
|
spill_unspec = XINT (src, 1);
|
||||||
|
/* 1 and 3 are unspecs for the GR and FR spills. */
|
||||||
|
if (spill_unspec != 1 && spill_unspec != 3)
|
||||||
|
spill_unspec = 0;
|
||||||
|
}
|
||||||
|
/* ST8 or st8.spill insn. */
|
||||||
|
if ((GET_CODE (src) == REG) || spill_unspec != 0)
|
||||||
|
{
|
||||||
|
int regno;
|
||||||
|
if (spill_unspec != 0)
|
||||||
|
{
|
||||||
|
regno = REGNO (XVECEXP (src, 0, 0));
|
||||||
|
if (!spill_offset_emitted)
|
||||||
|
{
|
||||||
|
fprintf (asm_out_file, "\t.spill %d\n",
|
||||||
|
/* (frame_size + 16 - spill_offset ) / 4); */
|
||||||
|
(-(spill_offset - 8) + 16) / 4);
|
||||||
|
spill_offset_emitted = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
regno = REGNO (src);
|
||||||
|
|
||||||
|
if (GR_REGNO_P (regno))
|
||||||
|
{
|
||||||
|
if (regno >= GR_REG (4) && regno <= GR_REG (7))
|
||||||
|
fprintf (asm_out_file, "\t.save.g 0x%x\n",
|
||||||
|
1 << (regno - GR_REG (4)));
|
||||||
|
else if (tmp_reg != NULL_RTX && regno == REGNO (tmp_reg))
|
||||||
|
{
|
||||||
|
/* We saved a special reg to a temp reg, and now we're
|
||||||
|
dumping it to memory. */
|
||||||
|
tmp_reg = NULL_RTX;
|
||||||
|
/* register 9 is ar.unat. */
|
||||||
|
if (tmp_saved == 9)
|
||||||
|
fprintf (asm_out_file, "\t.savesp ar.unat, %d\n",
|
||||||
|
(sp_offset - 8) / 4);
|
||||||
|
else if (tmp_saved == 5)
|
||||||
|
fprintf (asm_out_file, "\t.savesp pr, %d\n",
|
||||||
|
(sp_offset - 8) / 4);
|
||||||
|
else if (tmp_saved >= BR_REG (1) && tmp_saved <= BR_REG (5))
|
||||||
|
{
|
||||||
|
/* BR regs are saved this way too. */
|
||||||
|
fprintf (asm_out_file, "\t.save.b 0x%x\n",
|
||||||
|
1 << (tmp_saved - BR_REG (1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (FR_REGNO_P (regno))
|
||||||
|
{
|
||||||
|
if (regno >= FR_REG (2) && regno <= FR_REG (5))
|
||||||
|
fprintf (asm_out_file, "\t.save.f 0x%x\n",
|
||||||
|
1 << (regno - FR_REG (2)));
|
||||||
|
else
|
||||||
|
if (regno >= FR_REG (16) && regno <= FR_REG (31))
|
||||||
|
fprintf (asm_out_file, "\t.save.gf 0x0, 0x%x\n",
|
||||||
|
1 << (regno - FR_REG (12)));
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* This function looks at a single insn and emits any directives
|
||||||
|
required to unwind this insn. */
|
||||||
|
void
|
||||||
|
process_for_unwind_directive (asm_out_file, insn)
|
||||||
|
FILE *asm_out_file;
|
||||||
|
rtx insn;
|
||||||
|
{
|
||||||
|
if ((flag_unwind_tables
|
||||||
|
|| (flag_exceptions && !exceptions_via_longjmp))
|
||||||
|
&& RTX_FRAME_RELATED_P (insn))
|
||||||
|
{
|
||||||
|
rtx code, pat;
|
||||||
|
pat = PATTERN (insn);
|
||||||
|
|
||||||
|
switch (GET_CODE (pat))
|
||||||
|
{
|
||||||
|
case SET:
|
||||||
|
{
|
||||||
|
process_set (asm_out_file, pat);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PARALLEL:
|
||||||
|
{
|
||||||
|
int par_index;
|
||||||
|
int limit = XVECLEN (pat, 0);
|
||||||
|
for (par_index = 0; par_index < limit; par_index++)
|
||||||
|
{
|
||||||
|
rtx x = XVECEXP (pat, 0, par_index);
|
||||||
|
if (GET_CODE (x) == SET)
|
||||||
|
process_set (asm_out_file, x);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#define def_builtin(name, type, code) \
|
#define def_builtin(name, type, code) \
|
||||||
builtin_function ((name), (type), (code), BUILT_IN_MD, NULL_PTR)
|
builtin_function ((name), (type), (code), BUILT_IN_MD, NULL_PTR)
|
||||||
|
|
|
@ -2115,6 +2115,71 @@ do { \
|
||||||
fprintf (FILE, "\n"); \
|
fprintf (FILE, "\n"); \
|
||||||
} while (0)
|
} 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
|
/* A C statement to output to the stdio stream STREAM an assembler instruction
|
||||||
to assemble a single byte containing the number VALUE. */
|
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
|
You should define this symbol if your target supports DWARF 2 frame unwind
|
||||||
information and the default definition does not work. */
|
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
|
/* A C expression that is nonzero if the normal exception table output should
|
||||||
be omitted.
|
be omitted.
|
||||||
|
@ -2739,6 +2804,21 @@ do { \
|
||||||
|
|
||||||
#define ISSUE_RATE 3
|
#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
|
enum ia64_builtins
|
||||||
{
|
{
|
||||||
IA64_BUILTIN_SYNCHRONIZE,
|
IA64_BUILTIN_SYNCHRONIZE,
|
||||||
|
|
|
@ -3083,6 +3083,33 @@
|
||||||
"mov ar.unat = %0"
|
"mov ar.unat = %0"
|
||||||
[(set_attr "type" "M")])
|
[(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;
|
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
|
;; This flushes at least 64 bytes starting from the address pointed
|
||||||
;; to by operand[0].
|
;; to by operand[0].
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue