Index: gcc/configure.ac =================================================================== --- gcc/configure.ac (revision 143289) +++ gcc/configure.ac (working copy) @@ -2975,6 +2975,12 @@ [AC_DEFINE(HAVE_AS_IX86_SAHF, 1, [Define if your assembler supports the sahf mnemonic.])]) + gcc_GAS_CHECK_FEATURE([swap suffix], + gcc_cv_as_ix86_swap,,, + [movl.s %esp, %ebp],, + [AC_DEFINE(HAVE_AS_IX86_SWAP, 1, + [Define if your assembler supports the swap suffix.])]) + gcc_GAS_CHECK_FEATURE([different section symbol subtraction], gcc_cv_as_ix86_diff_sect_delta,,, [.section .rodata Index: gcc/config/i386/i386.h =================================================================== --- gcc/config/i386/i386.h (revision 143289) +++ gcc/config/i386/i386.h (working copy) @@ -2426,6 +2426,9 @@ /* This value is used for amd64 targets and specifies the current abi to be used. MS_ABI means ms abi. Otherwise SYSV_ABI means sysv abi. */ int call_abi; + /* This value is used for i386 targets and specifies if the function + * should start with the hooking-friendly Win32 function prologue */ + int msvc_prologue; }; #define ix86_stack_locals (cfun->machine->stack_locals) Index: gcc/config/i386/i386.md =================================================================== --- gcc/config/i386/i386.md (revision 143289) +++ gcc/config/i386/i386.md (working copy) @@ -226,6 +226,7 @@ (UNSPECV_CLD 15) (UNSPECV_VZEROALL 16) (UNSPECV_VZEROUPPER 17) + (UNSPECV_VSWAPMOV 18) ]) ;; Constants to represent pcomtrue/pcomfalse variants @@ -15245,6 +15246,16 @@ (set_attr "length_immediate" "0") (set_attr "modrm" "0")]) +(define_insn "vswapmov" +[(unspec_volatile [(match_operand 0 "register_operand" "0") + (match_operand 1 "register_operand" "1")] + UNSPECV_VSWAPMOV )] + "" + "movl.s\t%1,%0" + [(set_attr "length" "2") + (set_attr "length_immediate" "0") + (set_attr "modrm" "0")]) + ;; Align to 16-byte boundary, max skip in op0. Used to avoid ;; branch prediction penalty for the third jump in a 16-byte ;; block on K8. Index: gcc/config/i386/i386-protos.h =================================================================== --- gcc/config/i386/i386-protos.h (revision 143289) +++ gcc/config/i386/i386-protos.h (working copy) @@ -142,6 +142,7 @@ extern int ix86_cfun_abi (void); extern int ix86_function_abi (const_tree); extern int ix86_function_type_abi (const_tree); +extern int ix86_function_msvc_prologue (const_tree fntype); extern void ix86_call_abi_override (const_tree); extern tree ix86_fn_abi_va_list (tree); extern tree ix86_canonical_va_list_type (tree); Index: gcc/config/i386/i386.c =================================================================== --- gcc/config/i386/i386.c (revision 143289) +++ gcc/config/i386/i386.c (working copy) @@ -4584,6 +4584,19 @@ } int +ix86_function_msvc_prologue (const_tree fntype) +{ + if (!TARGET_64BIT && fntype != NULL) + { + if(lookup_attribute ("msvc_prologue", TYPE_ATTRIBUTES (fntype))) + { + return 1; + } + } + return 0; +} + +int ix86_function_abi (const_tree fndecl) { if (! fndecl) @@ -4614,6 +4627,11 @@ cfun->machine->call_abi = DEFAULT_ABI; else cfun->machine->call_abi = ix86_function_type_abi (TREE_TYPE (fndecl)); + + if (fndecl == NULL_TREE) + cfun->machine->msvc_prologue = 0; + else + cfun->machine->msvc_prologue = ix86_function_msvc_prologue (TREE_TYPE (fndecl)); } /* MS and SYSV ABI have different set of call used registers. Avoid expensive @@ -7959,6 +7977,7 @@ bool pic_reg_used; struct ix86_frame frame; HOST_WIDE_INT allocate; + int gen_frame_pointer = frame_pointer_needed; ix86_finalize_stack_realign_flags (); @@ -7967,6 +7986,28 @@ ix86_compute_frame_layout (&frame); + if(cfun->machine->msvc_prologue) + { + insn = emit_insn(gen_vswapmov(gen_rtx_REG (Pmode, DI_REG), gen_rtx_REG (Pmode, DI_REG))); + RTX_FRAME_RELATED_P (insn) = 1; + insn = emit_insn (gen_push (hard_frame_pointer_rtx)); + RTX_FRAME_RELATED_P (insn) = 1; + insn = emit_insn(gen_vswapmov(hard_frame_pointer_rtx, stack_pointer_rtx)); + RTX_FRAME_RELATED_P (insn) = 1; + + if(frame_pointer_needed && !(crtl->drap_reg && crtl->stack_realign_needed)) + { + gen_frame_pointer = 0; + } + else + { + /* Undo what we've just done */ + insn = emit_insn ((*ix86_gen_pop1) (hard_frame_pointer_rtx)); + RTX_FRAME_RELATED_P (insn) = 1; + } + } + + /* Emit prologue code to adjust stack alignment and setup DRAP, in case of DRAP is needed and stack realignment is really needed after reload */ if (crtl->drap_reg && crtl->stack_realign_needed) @@ -8015,11 +8056,10 @@ /* Note: AT&T enter does NOT have reversed args. Enter is probably slower on all targets. Also sdb doesn't like it. */ - if (frame_pointer_needed) + if (gen_frame_pointer) { insn = emit_insn (gen_push (hard_frame_pointer_rtx)); RTX_FRAME_RELATED_P (insn) = 1; - insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx); RTX_FRAME_RELATED_P (insn) = 1; } @@ -26197,11 +26237,24 @@ } if (!TARGET_64BIT) { - warning (OPT_Wattributes, "%qs attribute only available for 64-bit", - IDENTIFIER_POINTER (name)); - *no_add_attrs = true; - return NULL_TREE; + if(!is_attribute_p ("msvc_prologue", name)) + { + warning (OPT_Wattributes, "%qs attribute only available for 64-bit", + IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + return NULL_TREE; + } } + else + { + if(is_attribute_p ("msvc_prologue", name)) + { + warning (OPT_Wattributes, "%qs attribute only available for 32-bit", + IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + return NULL_TREE; + } + } /* Can combine regparm with all attributes but fastcall. */ if (is_attribute_p ("ms_abi", name)) @@ -29241,6 +29294,9 @@ /* ms_abi and sysv_abi calling convention function attributes. */ { "ms_abi", 0, 0, false, true, true, ix86_handle_abi_attribute }, { "sysv_abi", 0, 0, false, true, true, ix86_handle_abi_attribute }, +#ifdef HAVE_AS_IX86_SWAP + { "msvc_prologue", 0, 0, false, true, true, ix86_handle_abi_attribute }, +#endif /* End element. */ { NULL, 0, 0, false, false, false, NULL } };