diff --git a/gcc/config/moxie/moxie-protos.h b/gcc/config/moxie/moxie-protos.h index 8a7880464db50..ab4e360736137 100644 --- a/gcc/config/moxie/moxie-protos.h +++ b/gcc/config/moxie/moxie-protos.h @@ -18,6 +18,6 @@ along with GCC; see the file COPYING3. If not see . */ extern void moxie_expand_prologue (void); -extern void moxie_expand_epilogue (void); +extern void moxie_expand_epilogue (int); extern int moxie_initial_elimination_offset (int, int); extern bool moxie_offset_address_p (rtx); diff --git a/gcc/config/moxie/moxie.cc b/gcc/config/moxie/moxie.cc index 209d03077ea38..47090cffd173a 100644 --- a/gcc/config/moxie/moxie.cc +++ b/gcc/config/moxie/moxie.cc @@ -328,7 +328,7 @@ moxie_expand_prologue (void) } void -moxie_expand_epilogue (void) +moxie_expand_epilogue (int style) { int regno; rtx reg; @@ -336,6 +336,7 @@ moxie_expand_epilogue (void) if (cfun->machine->callee_saved_reg_size != 0) { reg = gen_rtx_REG (Pmode, MOXIE_R12); + if (style) emit_insn (gen_movsi_push(reg)); if (cfun->machine->callee_saved_reg_size <= 255) { emit_move_insn (reg, hard_frame_pointer_rtx); @@ -356,9 +357,11 @@ moxie_expand_epilogue (void) rtx preg = gen_rtx_REG (Pmode, regno); emit_insn (gen_movsi_pop (reg, preg)); } + if (style) emit_insn (gen_movsi_pop(gen_rtx_REG(Pmode, MOXIE_SP), reg)); } - emit_jump_insn (gen_returner ()); + if (style) emit_jump_insn (gen_eh_returner()); + else emit_jump_insn (gen_returner ()); } /* Implements the macro INITIAL_ELIMINATION_OFFSET, return the OFFSET. */ diff --git a/gcc/config/moxie/moxie.h b/gcc/config/moxie/moxie.h index f94a3a72d0f2d..5a06878b65639 100644 --- a/gcc/config/moxie/moxie.h +++ b/gcc/config/moxie/moxie.h @@ -256,13 +256,21 @@ enum reg_class gen_frame_mem (Pmode, \ plus_constant (Pmode, stack_pointer_rtx, UNITS_PER_WORD)) +#define RETURN_ADDR_RTX(C,FA) C!=0?NULL_RTX: \ + gen_frame_mem (Pmode, \ + plus_constant (Pmode, hard_frame_pointer_rtx, UNITS_PER_WORD)) + /* Describe how we implement __builtin_eh_return. */ -#define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (N+2) : INVALID_REGNUM) +#define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (N+8) : INVALID_REGNUM) /* Store the return handler into the call frame. */ -#define EH_RETURN_HANDLER_RTX \ +/*#define EH_RETURN_HANDLER_RTX \ gen_frame_mem (Pmode, \ - plus_constant (Pmode, frame_pointer_rtx, UNITS_PER_WORD)) + plus_constant (Pmode, frame_pointer_rtx, UNITS_PER_WORD))*/ +#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, MOXIE_R12) +#define INCOMING_FRAME_SP_OFFSET 12 +#define ARG_POINTER_CFA_OFFSET(FUNDECL) 12 +#define DYNAMIC_CHAIN_ADDRESS(FRAMEADDR) plus_constant(Pmode, FRAMEADDR, -12) /* Storage Layout */ @@ -424,5 +432,6 @@ enum reg_class } #define HAS_LONG_UNCOND_BRANCH true +#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) DW_EH_PE_sdata4 #endif /* GCC_MOXIE_H */ diff --git a/gcc/config/moxie/moxie.md b/gcc/config/moxie/moxie.md index 18316628c235d..b130a99489870 100644 --- a/gcc/config/moxie/moxie.md +++ b/gcc/config/moxie/moxie.md @@ -506,7 +506,7 @@ "" " { - moxie_expand_epilogue (); + moxie_expand_epilogue (0); DONE; } ") @@ -515,3 +515,36 @@ [(return)] "reload_completed" "ret") + +(define_expand "eh_return" + [(use (match_operand 0 "register_operand"))] + "" +{ + rtx tmp, sa = EH_RETURN_STACKADJ_RTX, ra = operands[0]; + + /* Tricky bit: we write the address of the handler to which we will + be returning into someone else's stack frame, one word below the + stack address we wish to restore. */ + tmp = gen_rtx_PLUS (Pmode, arg_pointer_rtx, sa); + tmp = plus_constant (Pmode, tmp, 2*UNITS_PER_WORD); + tmp = gen_rtx_MEM (Pmode, tmp); + emit_move_insn (tmp, ra); + + emit_jump_insn (gen_eh_return_internal ()); + emit_barrier (); + DONE; +}) + +(define_insn_and_split "eh_return_internal" + [(eh_return)] + "" + "#" + "epilogue_completed" + [(const_int 0)] + "moxie_expand_epilogue (1); DONE;") + +(define_insn "eh_returner" + [(simple_return)] + "" + "add\\t$r12, $fp\\n\\tinc\\t$r12, 12\\n\\tmov\\t$sp, $r12\\n\\tld.l\\t$fp, ($fp)\\n\\tcmp\\t$fp, $r12\\n\\tbltu\\t.-6\\n\\tldo.l\\t$r12, -4($r12)\\n\\tjmp\\t$r12" + [(set_attr "length" "18")])