This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Restricted addressing modes in ColdFire FPU for DFmode
>>I'm working on adding the V4E ColdFire FPU instructions to gcc-2.95.3,
>>and I've been having a very hard time convincing gcc to deal with the
>>restricted addressing modes that the ColdFire FPU supports.
>>
>>.....
>>(define_insn "movdf_v4e"
>> [(set (match_operand:DF 0 "general_operand" "=f,<Q>S")
>> (match_operand:DF 1 "general_operand" "f<Q>S,f"))]
>> "TARGET_FPU_V4E"
>> "*
>>{
>> return \"fmove%.d %1,%0\";
>>}")
>>
>
> What happens if you change the predicate in the define_insn to
>
> "nonimmedate_operand"
>
> for BOTH operands[0] and operands[1]?
If I use the following RTL:
(define_expand "movdf"
[(set (match_operand:DF 0 "nonimmediate_operand" "")
(match_operand:DF 1 "nonimmediate_operand" ""))]
""
"")
(define_insn "movdf_v4e"
[(set (match_operand:DF 0 "nonimmediate_operand" "=f,<Q>S")
(match_operand:DF 1 "nonimmediate_operand" "f<Q>S,f"))]
"TARGET_FPU_V4E"
"*
{
return \"fmove%.d %1,%0\";
}")
I get:
/tmp/z.c: In function `x':
/tmp/z.c:4: internal error--unrecognizable insn:
(insn 8 16 9 (set (reg/i:DF 16 %fp0)
(const_double:DF (const_int 0 [0x0]) 0 [0x0] 0 [0x0] 1073643520 [0x3ffe8000])) -1 (nil)
(expr_list:REG_EQUAL (const_double:DF (const_int 0 [0x0]) 0 [0x0] 0 [0x0] 1073643520 [0x3ffe8000])
(nil)))
So I have to push the constant to memory. If I use the rtl:
(define_expand "movdf"
[(set (match_operand:DF 0 "nonimmediate_operand" "")
(match_operand:DF 1 "nonimmediate_operand" ""))]
""
"
{
rtx insn;
if (TARGET_FPU_V4E) {
/* The ColdFire FPU can't deal with absolute addresses or double
* constants, so push it to memory */
if (CONSTANT_P (operands[1])) {
operands[1] = force_const_mem(DFmode, operands[1]);
if (! memory_address_p (DFmode, XEXP (operands[1], 0))
&& ! reload_in_progress)
operands[1] = change_address (operands[1], DFmode,
XEXP (operands[1], 0));
}
/* Since the Coldfire can't deal with absolute addresses, force
* the address of the reference into a register and do it indirect */
if (!reload_in_progress && GET_CODE (operands[1]) == MEM
&& GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF) {
operands[1] = gen_rtx (MEM, DFmode,
force_reg (Pmode, XEXP (operands[1], 0)));
#if 0
/* Set RTX_CANNOT_COMBINE to prevent the combiner from putting
this back together, but only on the insn, not the operand! */
insn = emit_insn(gen_rtx_SET(VOIDmode, operands[0], operands[1]));
RTX_CANNOT_COMBINE_P(insn) = 1;
DONE;
#endif
}
}
}")
(define_insn "movdf_v4e"
[(set (match_operand:DF 0 "nonimmediate_operand" "=f,<Q>S")
(match_operand:DF 1 "nonimmediate_operand" "f<Q>S,f"))]
"TARGET_FPU_V4E"
"*
{
return \"fmove%.d %1,%0\";
}")
I get:
/tmp/z.c: In function `x':
/tmp/z.c:4: internal error--insn does not satisfy its constraints:
(insn 21 8 9 (set (reg:DF 17 %fp1)
(mem:DF (symbol_ref/u:SI ("*.LC0")) 0)) 67 {movdf_v4e} (nil)
(nil))
If I turn the '#if 0' to '#if 1' then it works(as long as all the
other code to support RTX_CANNOT_COMBINE_P is there as well)...
--
Peter Barada Peter.Barada@motorola.com
Wizard 781-852-2768 (direct)
WaveMark Solutions(wholly owned by Motorola) 781-270-0193 (fax)