From 431291ca9f9415e852e2af5ee425bcb7f576ebaa Mon Sep 17 00:00:00 2001 From: =?utf8?q?Christian=20W=C3=BCrdig?= Date: Wed, 2 Aug 2006 20:15:09 +0000 Subject: [PATCH] in case of SSE: copy xmm0 to FPU TOS --- ir/be/ia32/ia32_transform.c | 49 +++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/ir/be/ia32/ia32_transform.c b/ir/be/ia32/ia32_transform.c index bb8c5ce0d..83ae6d8f1 100644 --- a/ir/be/ia32/ia32_transform.c +++ b/ir/be/ia32/ia32_transform.c @@ -2322,6 +2322,54 @@ static ir_node *gen_be_Call(ia32_transform_env_t *env) { return NULL; } +/** + * In case SSE is used we need to copy the result from XMM0 to FPU TOS before return. + */ +static ir_node *gen_be_Return(ia32_transform_env_t *env) { + ir_node *ret_val = get_irn_n(env->irn, be_pos_Return_val); + ir_node *ret_mem = get_irn_n(env->irn, be_pos_Return_mem); + ir_mode *mode; + + if (! ret_val || ! USE_SSE2(env->cg)) + return NULL; + + mode = get_irn_mode(ret_val); + + if (mode_is_float(mode)) { + ir_node *frame = get_irg_frame(env->irg); + entity *ent = frame_alloc_area(get_irg_frame_type(env->irg), get_mode_size_bytes(mode), 16, 0); + ir_node *sse_store, *fld, *mproj; + + /* store xmm0 onto stack */ + sse_store = new_rd_ia32_xStoreSimple(env->dbg, env->irg, env->block, frame, ret_val, ret_mem); + set_ia32_ls_mode(sse_store, mode); + set_ia32_op_type(sse_store, ia32_AddrModeD); + set_ia32_use_frame(sse_store); + set_ia32_frame_ent(sse_store, ent); + set_ia32_am_flavour(sse_store, ia32_B); + set_ia32_am_support(sse_store, ia32_am_Dest); + sse_store = new_r_Proj(env->irg, env->block, sse_store, mode_M, pn_ia32_xStore_M); + + /* load into st0 */ + fld = new_rd_ia32_SetST0(env->dbg, env->irg, env->block, frame, sse_store); + set_ia32_ls_mode(fld, mode); + set_ia32_op_type(fld, ia32_AddrModeS); + set_ia32_use_frame(fld); + set_ia32_frame_ent(fld, ent); + set_ia32_am_flavour(fld, ia32_B); + set_ia32_am_support(fld, ia32_am_Source); + mproj = new_r_Proj(env->irg, env->block, fld, mode_M, pn_ia32_SetST0_M); + fld = new_r_Proj(env->irg, env->block, fld, mode, pn_ia32_SetST0_res); + + /* set new return value */ + set_irn_n(env->irn, be_pos_Return_val, fld); + set_irn_n(env->irn, be_pos_Return_mem, mproj); + } + + return NULL; +} + + /** * This function just sets the register for the Unknown node * as this is not done during register allocation because Unknown @@ -2817,6 +2865,7 @@ void ia32_register_transformers(void) { /* handle generic backend nodes */ GEN(be_FrameAddr); GEN(be_Call); + GEN(be_Return); GEN(be_FrameLoad); GEN(be_FrameStore); GEN(be_StackParam); -- 2.20.1