static rtx legitimize_dllimport_symbol (rtx, bool);
static rtx legitimize_pe_coff_extern_decl (rtx, bool);
static void ix86_print_operand_address_as (FILE *, rtx, addr_space_t, bool);
-static void ix86_emit_restore_reg_using_pop (rtx);
+static void ix86_emit_restore_reg_using_pop (rtx, bool = false);
#ifndef CHECK_STACK_LIMIT
/* Generate an "push" pattern for input ARG. */
rtx
-gen_push (rtx arg)
+gen_push (rtx arg, bool ppx_p)
{
struct machine_function *m = cfun->machine;
if (REG_P (arg) && GET_MODE (arg) != word_mode)
arg = gen_rtx_REG (word_mode, REGNO (arg));
- return gen_rtx_SET (gen_rtx_MEM (word_mode,
- gen_rtx_PRE_DEC (Pmode,
- stack_pointer_rtx)),
- arg);
+ rtx stack = gen_rtx_MEM (word_mode,
+ gen_rtx_PRE_DEC (Pmode,
+ stack_pointer_rtx));
+ return ppx_p ? gen_pushp_di (stack, arg) : gen_rtx_SET (stack, arg);
}
rtx
/* Generate an "pop" pattern for input ARG. */
rtx
-gen_pop (rtx arg)
+gen_pop (rtx arg, bool ppx_p)
{
if (REG_P (arg) && GET_MODE (arg) != word_mode)
arg = gen_rtx_REG (word_mode, REGNO (arg));
- return gen_rtx_SET (arg,
- gen_rtx_MEM (word_mode,
- gen_rtx_POST_INC (Pmode,
- stack_pointer_rtx)));
+ rtx stack = gen_rtx_MEM (word_mode,
+ gen_rtx_POST_INC (Pmode,
+ stack_pointer_rtx));
+
+ return ppx_p ? gen_popp_di (arg, stack) : gen_rtx_SET (arg, stack);
}
rtx
/* Generate a "push2" pattern for input ARG. */
rtx
-gen_push2 (rtx mem, rtx reg1, rtx reg2)
+gen_push2 (rtx mem, rtx reg1, rtx reg2, bool ppx_p = false)
{
struct machine_function *m = cfun->machine;
const int offset = UNITS_PER_WORD * 2;
if (REG_P (reg2) && GET_MODE (reg2) != word_mode)
reg2 = gen_rtx_REG (word_mode, REGNO (reg2));
- return gen_push2_di (mem, reg1, reg2);
+ return ppx_p ? gen_push2p_di (mem, reg1, reg2):
+ gen_push2_di (mem, reg1, reg2);
}
/* Return >= 0 if there is an unused call-clobbered register available
for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
if (GENERAL_REGNO_P (regno) && ix86_save_reg (regno, true, true))
{
- insn = emit_insn (gen_push (gen_rtx_REG (word_mode, regno)));
+ insn = emit_insn (gen_push (gen_rtx_REG (word_mode, regno),
+ TARGET_APX_PPX));
RTX_FRAME_RELATED_P (insn) = 1;
}
}
gen_rtx_REG (word_mode,
regno_list[0]),
gen_rtx_REG (word_mode,
- regno_list[1])));
+ regno_list[1]),
+ TARGET_APX_PPX));
RTX_FRAME_RELATED_P (insn) = 1;
rtx dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (3));
}
else
{
- insn = emit_insn (gen_push (gen_rtx_REG (word_mode, regno)));
+ insn = emit_insn (gen_push (gen_rtx_REG (word_mode, regno),
+ TARGET_APX_PPX));
RTX_FRAME_RELATED_P (insn) = 1;
aligned = true;
}
if (loaded_regnum == 1)
{
insn = emit_insn (gen_push (gen_rtx_REG (word_mode,
- regno_list[0])));
+ regno_list[0]),
+ TARGET_APX_PPX));
RTX_FRAME_RELATED_P (insn) = 1;
}
}
emit_insn (gen_prologue_use (stack_pointer_rtx));
}
-/* Emit code to restore REG using a POP insn. */
+/* Emit code to restore REG using a POP or POPP insn. */
static void
-ix86_emit_restore_reg_using_pop (rtx reg)
+ix86_emit_restore_reg_using_pop (rtx reg, bool ppx_p)
{
struct machine_function *m = cfun->machine;
- rtx_insn *insn = emit_insn (gen_pop (reg));
+ rtx_insn *insn = emit_insn (gen_pop (reg, ppx_p));
ix86_add_cfa_restore_note (insn, reg, m->fs.sp_offset);
m->fs.sp_offset -= UNITS_PER_WORD;
/* Emit code to restore REG using a POP2 insn. */
static void
-ix86_emit_restore_reg_using_pop2 (rtx reg1, rtx reg2)
+ix86_emit_restore_reg_using_pop2 (rtx reg1, rtx reg2, bool ppx_p = false)
{
struct machine_function *m = cfun->machine;
const int offset = UNITS_PER_WORD * 2;
+ rtx_insn *insn;
rtx mem = gen_rtx_MEM (TImode, gen_rtx_POST_INC (Pmode,
stack_pointer_rtx));
- rtx_insn *insn = emit_insn (gen_pop2_di (reg1, mem, reg2));
+
+ if (ppx_p)
+ insn = emit_insn (gen_pop2p_di (reg1, mem, reg2));
+ else
+ insn = emit_insn (gen_pop2_di (reg1, mem, reg2));
RTX_FRAME_RELATED_P (insn) = 1;
/* Emit code to restore saved registers using POP insns. */
static void
-ix86_emit_restore_regs_using_pop (void)
+ix86_emit_restore_regs_using_pop (bool ppx_p)
{
unsigned int regno;
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
if (GENERAL_REGNO_P (regno) && ix86_save_reg (regno, false, true))
- ix86_emit_restore_reg_using_pop (gen_rtx_REG (word_mode, regno));
+ ix86_emit_restore_reg_using_pop (gen_rtx_REG (word_mode, regno), ppx_p);
}
/* Emit code to restore saved registers using POP2 insns. */
ix86_emit_restore_reg_using_pop2 (gen_rtx_REG (word_mode,
regno_list[0]),
gen_rtx_REG (word_mode,
- regno_list[1]));
+ regno_list[1]),
+ TARGET_APX_PPX);
loaded_regnum = 0;
regno_list[0] = regno_list[1] = -1;
}
}
else
{
- ix86_emit_restore_reg_using_pop (gen_rtx_REG (word_mode, regno));
+ ix86_emit_restore_reg_using_pop (gen_rtx_REG (word_mode, regno),
+ TARGET_APX_PPX);
aligned = true;
}
}
if (loaded_regnum == 1)
- ix86_emit_restore_reg_using_pop (gen_rtx_REG (word_mode, regno_list[0]));
+ ix86_emit_restore_reg_using_pop (gen_rtx_REG (word_mode, regno_list[0]),
+ TARGET_APX_PPX);
}
/* Emit code and notes for the LEAVE instruction. If insn is non-null,
if (TARGET_APX_PUSH2POP2 && m->func_type == TYPE_NORMAL)
ix86_emit_restore_regs_using_pop2 ();
else
- ix86_emit_restore_regs_using_pop ();
+ ix86_emit_restore_regs_using_pop (TARGET_APX_PPX);
}
/* If we used a stack pointer and haven't already got rid of it,
;; For insn_callee_abi:
UNSPEC_CALLEE_ABI
- ;; For PUSH2/POP2 support
+ ;; For APX PUSH2/POP2 support
UNSPEC_APXPUSH2
UNSPEC_APXPOP2_LOW
UNSPEC_APXPOP2_HIGH
+
+ ;; For APX PPX support
+ UNSPEC_APX_PPX
])
(define_c_enum "unspecv" [
[(set_attr "mode" "TI")
(set_attr "prefix" "evex")])
+(define_insn "pushp_di"
+ [(set (match_operand:DI 0 "push_operand" "=<")
+ (match_operand:DI 1 "register_operand" "r"))
+ (unspec:DI [(const_int 0)] UNSPEC_APX_PPX)]
+ "TARGET_64BIT"
+ "pushp\t%1"
+ [(set_attr "mode" "DI")])
+
+(define_insn "popp_di"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (match_operand:DI 1 "pop_operand" ">"))
+ (unspec:DI [(const_int 0)] UNSPEC_APX_PPX)]
+ "TARGET_APX_PPX"
+ "popp\t%0"
+ [(set_attr "mode" "DI")])
+
+(define_insn "push2p_di"
+ [(set (match_operand:TI 0 "push_operand" "=<")
+ (unspec:TI [(match_operand:DI 1 "register_operand" "r")
+ (match_operand:DI 2 "register_operand" "r")]
+ UNSPEC_APXPUSH2))
+ (unspec:DI [(const_int 0)] UNSPEC_APX_PPX)]
+ "TARGET_APX_PUSH2POP2 && TARGET_APX_PPX"
+ "push2p\t%1, %2"
+ [(set_attr "mode" "TI")
+ (set_attr "type" "multi")
+ (set_attr "prefix" "evex")])
+
+(define_insn "pop2p_di"
+ [(parallel [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(match_operand:TI 1 "pop_operand" ">")]
+ UNSPEC_APXPOP2_LOW))
+ (set (match_operand:DI 2 "register_operand" "=r")
+ (unspec:DI [(const_int 0)] UNSPEC_APXPOP2_HIGH))
+ (unspec:DI [(const_int 0)] UNSPEC_APX_PPX)])]
+ "TARGET_APX_PUSH2POP2 && TARGET_APX_PPX"
+ "pop2p\t%0, %2"
+ [(set_attr "mode" "TI")
+ (set_attr "prefix" "evex")])
+
(define_insn "*pushsf_rex64"
[(set (match_operand:SF 0 "push_operand" "=X,X,X")
(match_operand:SF 1 "nonmemory_no_elim_operand" "f,rF,v"))]