Commit 07ea0048 by Ulrich Weigand Committed by Ulrich Weigand

spu.c (TARGET_ASM_OUTPUT_MI_THUNK): Define.

	* config/spu/spu.c (TARGET_ASM_OUTPUT_MI_THUNK): Define.
	(TARGET_ASM_CAN_OUTPUT_MI_THUNK): Likewise.
	(spu_output_mi_thunk): New function.

From-SVN: r173420
parent d634bfa1
2011-05-05 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
* config/spu/spu.c (TARGET_ASM_OUTPUT_MI_THUNK): Define.
(TARGET_ASM_CAN_OUTPUT_MI_THUNK): Likewise.
(spu_output_mi_thunk): New function.
2011-05-05 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* config/sparc/sol2.h (ASM_OUTPUT_CALL): Use
......
......@@ -232,6 +232,8 @@ static rtx spu_expand_load (rtx, rtx, rtx, int);
static void spu_trampoline_init (rtx, tree, rtx);
static void spu_conditional_register_usage (void);
static bool spu_ref_may_alias_errno (ao_ref *);
static void spu_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
HOST_WIDE_INT, tree);
/* Which instruction set architecture to use. */
int spu_arch;
......@@ -502,6 +504,11 @@ static const struct attribute_spec spu_attribute_table[] =
#undef TARGET_REF_MAY_ALIAS_ERRNO
#define TARGET_REF_MAY_ALIAS_ERRNO spu_ref_may_alias_errno
#undef TARGET_ASM_OUTPUT_MI_THUNK
#define TARGET_ASM_OUTPUT_MI_THUNK spu_output_mi_thunk
#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
struct gcc_target targetm = TARGET_INITIALIZER;
static void
......@@ -7192,4 +7199,90 @@ spu_ref_may_alias_errno (ao_ref *ref)
return default_ref_may_alias_errno (ref);
}
/* Output thunk to FILE that implements a C++ virtual function call (with
multiple inheritance) to FUNCTION. The thunk adjusts the this pointer
by DELTA, and unless VCALL_OFFSET is zero, applies an additional adjustment
stored at VCALL_OFFSET in the vtable whose address is located at offset 0
relative to the resulting this pointer. */
static void
spu_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
tree function)
{
rtx op[8];
/* Make sure unwind info is emitted for the thunk if needed. */
final_start_function (emit_barrier (), file, 1);
/* Operand 0 is the target function. */
op[0] = XEXP (DECL_RTL (function), 0);
/* Operand 1 is the 'this' pointer. */
if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
op[1] = gen_rtx_REG (Pmode, FIRST_ARG_REGNUM + 1);
else
op[1] = gen_rtx_REG (Pmode, FIRST_ARG_REGNUM);
/* Operands 2/3 are the low/high halfwords of delta. */
op[2] = GEN_INT (trunc_int_for_mode (delta, HImode));
op[3] = GEN_INT (trunc_int_for_mode (delta >> 16, HImode));
/* Operands 4/5 are the low/high halfwords of vcall_offset. */
op[4] = GEN_INT (trunc_int_for_mode (vcall_offset, HImode));
op[5] = GEN_INT (trunc_int_for_mode (vcall_offset >> 16, HImode));
/* Operands 6/7 are temporary registers. */
op[6] = gen_rtx_REG (Pmode, 79);
op[7] = gen_rtx_REG (Pmode, 78);
/* Add DELTA to this pointer. */
if (delta)
{
if (delta >= -0x200 && delta < 0x200)
output_asm_insn ("ai\t%1,%1,%2", op);
else if (delta >= -0x8000 && delta < 0x8000)
{
output_asm_insn ("il\t%6,%2", op);
output_asm_insn ("a\t%1,%1,%6", op);
}
else
{
output_asm_insn ("ilhu\t%6,%3", op);
output_asm_insn ("iohl\t%6,%2", op);
output_asm_insn ("a\t%1,%1,%6", op);
}
}
/* Perform vcall adjustment. */
if (vcall_offset)
{
output_asm_insn ("lqd\t%7,0(%1)", op);
output_asm_insn ("rotqby\t%7,%7,%1", op);
if (vcall_offset >= -0x200 && vcall_offset < 0x200)
output_asm_insn ("ai\t%7,%7,%4", op);
else if (vcall_offset >= -0x8000 && vcall_offset < 0x8000)
{
output_asm_insn ("il\t%6,%4", op);
output_asm_insn ("a\t%7,%7,%6", op);
}
else
{
output_asm_insn ("ilhu\t%6,%5", op);
output_asm_insn ("iohl\t%6,%4", op);
output_asm_insn ("a\t%7,%7,%6", op);
}
output_asm_insn ("lqd\t%6,0(%7)", op);
output_asm_insn ("rotqby\t%6,%6,%7", op);
output_asm_insn ("a\t%1,%1,%6", op);
}
/* Jump to target. */
output_asm_insn ("br\t%0", op);
final_end_function ();
}
#include "gt-spu.h"
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