Commit 4b2678f8 by Ian Bolton Committed by Greta Yorsh

New define insn pattern for epilogue with floating point registers (DFmode) and...

New define insn pattern for epilogue with floating point registers (DFmode)
and a new function that emits RTL for this pattern. This function is a
helper for epilogue extension. It is used by a later patch.

gcc/

2012-06-18  Ian Bolton  <ian.bolton@arm.com>
            Sameera Deshpande  <sameera.deshpande@arm.com>
            Greta Yorsh  <greta.yorsh@arm.com>

        * config/arm/arm.md (vfp_pop_multiple_with_writeback) New
	define_insn.
        * config/arm/predicates.md (pop_multiple_fp) New special predicate.
        * config/arm/arm.c (arm_emit_vfp_multi_reg_pop): New function.


Co-Authored-By: Greta Yorsh <greta.yorsh@arm.com>
Co-Authored-By: Sameera Deshpande <sameera.deshpande@arm.com>

From-SVN: r188740
parent 3aee1982
......@@ -2,6 +2,15 @@
Sameera Deshpande <sameera.deshpande@arm.com>
Greta Yorsh <greta.yorsh@arm.com>
* config/arm/arm.md (vfp_pop_multiple_with_writeback) New
define_insn.
* config/arm/predicates.md (pop_multiple_fp) New special predicate.
* config/arm/arm.c (arm_emit_vfp_multi_reg_pop): New function.
2012-06-18 Ian Bolton <ian.bolton@arm.com>
Sameera Deshpande <sameera.deshpande@arm.com>
Greta Yorsh <greta.yorsh@arm.com>
* config/arm/arm.md (load_multiple_with_writeback) New define_insn.
(load_multiple, pop_multiple_with_writeback_and_return) Likewise.
(pop_multiple_with_return, ldr_with_return) Likewise.
......
......@@ -16544,6 +16544,76 @@ arm_emit_multi_reg_pop (unsigned long saved_regs_mask)
REG_NOTES (par) = dwarf;
}
/* Generate and emit an insn pattern that we will recognize as a pop_multi
of NUM_REGS consecutive VFP regs, starting at FIRST_REG.
Unfortunately, since this insn does not reflect very well the actual
semantics of the operation, we need to annotate the insn for the benefit
of DWARF2 frame unwind information. */
static void
arm_emit_vfp_multi_reg_pop (int first_reg, int num_regs, rtx base_reg)
{
int i, j;
rtx par;
rtx dwarf = NULL_RTX;
rtx tmp, reg;
gcc_assert (num_regs && num_regs <= 32);
/* Workaround ARM10 VFPr1 bug. */
if (num_regs == 2 && !arm_arch6)
{
if (first_reg == 15)
first_reg--;
num_regs++;
}
/* We can emit at most 16 D-registers in a single pop_multi instruction, and
there could be up to 32 D-registers to restore.
If there are more than 16 D-registers, make two recursive calls,
each of which emits one pop_multi instruction. */
if (num_regs > 16)
{
arm_emit_vfp_multi_reg_pop (first_reg, 16, base_reg);
arm_emit_vfp_multi_reg_pop (first_reg + 16, num_regs - 16, base_reg);
return;
}
/* The parallel needs to hold num_regs SETs
and one SET for the stack update. */
par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (num_regs + 1));
/* Increment the stack pointer, based on there being
num_regs 8-byte registers to restore. */
tmp = gen_rtx_SET (VOIDmode,
base_reg,
plus_constant (Pmode, base_reg, 8 * num_regs));
RTX_FRAME_RELATED_P (tmp) = 1;
XVECEXP (par, 0, 0) = tmp;
/* Now show every reg that will be restored, using a SET for each. */
for (j = 0, i=first_reg; j < num_regs; i += 2)
{
reg = gen_rtx_REG (DFmode, i);
tmp = gen_rtx_SET (VOIDmode,
reg,
gen_frame_mem
(DFmode,
plus_constant (Pmode, base_reg, 8 * j)));
RTX_FRAME_RELATED_P (tmp) = 1;
XVECEXP (par, 0, j + 1) = tmp;
dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf);
j++;
}
par = emit_insn (par);
REG_NOTES (par) = dwarf;
}
/* Calculate the size of the return value that is passed in registers. */
static unsigned
arm_size_return_regs (void)
......
......@@ -10946,6 +10946,41 @@
[(set_attr "type" "load1")
(set_attr "predicable" "yes")]
)
;; Pop for floating point registers (as used in epilogue RTL)
(define_insn "*vfp_pop_multiple_with_writeback"
[(match_parallel 0 "pop_multiple_fp"
[(set (match_operand:SI 1 "s_register_operand" "+rk")
(plus:SI (match_dup 1)
(match_operand:SI 2 "const_int_operand" "I")))
(set (match_operand:DF 3 "arm_hard_register_operand" "")
(mem:DF (match_dup 1)))])]
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
"*
{
int num_regs = XVECLEN (operands[0], 0);
char pattern[100];
rtx op_list[2];
strcpy (pattern, \"fldmfdd\\t\");
strcat (pattern, reg_names[REGNO (SET_DEST (XVECEXP (operands[0], 0, 0)))]);
strcat (pattern, \"!, {\");
op_list[0] = XEXP (XVECEXP (operands[0], 0, 1), 0);
strcat (pattern, \"%P0\");
if ((num_regs - 1) > 1)
{
strcat (pattern, \"-%P1\");
op_list [1] = XEXP (XVECEXP (operands[0], 0, num_regs - 1), 0);
}
strcat (pattern, \"}\");
output_asm_insn (pattern, op_list);
return \"\";
}
"
[(set_attr "type" "load4")
(set_attr "conds" "unconditional")
(set_attr "predicable" "no")]
)
;; Special patterns for dealing with the constant pool
(define_insn "align_4"
......
......@@ -376,6 +376,14 @@
/*return_pc=*/true);
})
(define_special_predicate "pop_multiple_fp"
(match_code "parallel")
{
return ldm_stm_operation_p (op, /*load=*/true, DFmode,
/*consecutive=*/true,
/*return_pc=*/false);
})
(define_special_predicate "multi_register_push"
(match_code "parallel")
{
......
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