mirror of git://gcc.gnu.org/git/gcc.git
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
This commit is contained in:
parent
3aee198212
commit
4b2678f886
|
|
@ -1,3 +1,12 @@
|
|||
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.
|
||||
|
||||
2012-06-18 Ian Bolton <ian.bolton@arm.com>
|
||||
Sameera Deshpande <sameera.deshpande@arm.com>
|
||||
Greta Yorsh <greta.yorsh@arm.com>
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue