This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
issues trying to add ColdFire v4e FPU support to gcc-20020107
- From: Peter Barada <pbarada at mail dot wm dot sps dot mot dot com>
- To: gcc at gcc dot gnu dot org
- Date: Wed, 16 Jan 2002 16:08:19 -0500
- Subject: issues trying to add ColdFire v4e FPU support to gcc-20020107
I'm in the midst of adding FPU support to gcc-20020107 by lifting my
code form gcc-2.95.3, and I've runin to a problem...
Given the following code:
typedef double ftype;
ftype x(ftype *p, int y)
{
return p[y];
}
The following code is generated by gcc-20020107 for -O -m68881:
x:
link.w %a6,#0
move.l 12(%a6),%d0
lsl.l #3,%d0
move.l 8(%a6),%a0
fmove.d (%a0,%d0.l),%fp0
unlk %a6
rts
The .c.00.rtl dump for the insn 'fmove.d (%a0,%d0.l),%fp0' looks like:
(insn 18 16 20 (set (reg:DF 35)
(mem:DF (plus:SI (reg:SI 33)
(reg:SI 34)) [0 S8 A16])) -1 (nil)
(nil))
My problem is that the ColdFire FPU doesn't support the 'address
register indirect with index' addressing mode. I've mofidifued the
movdf pattern to look like:
(define_expand "movdf"
[(set (match_operand:DF 0 "nonimmediate_operand" "")
(match_operand:DF 1 "general_operand" ""))]
""
"
{
if (TARGET_CFV4E) {
/* 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));
}
if (symbolic_operand(operands[0], SImode))
operands[0] = force_reg(SImode, XEXP (operands[0], 0));
if (symbolic_operand(operands[1], SImode))
operands[1] = force_reg(SImode, XEXP (operands[1], 0));
}
}")
and added the pattern:
(define_insn "movdf_v4e"
[(set (match_operand:DF 0 "general_operand" "=f,<Q>U,r,f")
(match_operand:DF 1 "general_operand" "f<Q>U,f,f,r"))]
"TARGET_CFV4E"
"*
{
if (which_alternative == 2)
return \"subq%.l %#8,%%sp\;fmove%.d %1,%@\;move%.l %+,%0\;move%.l %+,%R0\";
if (which_alternative == 3)
return \"move%.l %R1,%-\;move%.l %1,%-\;f%&move%.d %@,%0\;addq%.l #8,%%sp\";
return \"fmove%.d %1,%0\";
}")
Where the constaint 'Q' is register indirect, and 'U' is register
indirect with offset, so I'd expect RTL that doesn't use (REG+REG).
But the dump with -mcfv4e turned on(and I've checked that TARGET_CFV4E
is true) *still* generats .c.00.rtl that has REG+REG addressing mode.
I then modified GO_IF_LEGITIMATE_ADDRESS to be:
/* If Coldfire and float, only accept addressing modes 2-5 */
#define GO_IF_CFV4E_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
{ if (LEGITIMATE_BASE_REG_P(X) \
|| ((GET_CODE (X) == PRE_DEC || GET_CODE (X) == POST_INC) \
&& LEGITIMATE_BASE_REG_P (XEXP (X, 0))) \
|| ((GET_CODE (X) == PLUS) && LEGITIMATE_BASE_REG_P (XEXP (X, 0)) \
&& (GET_CODE (XEXP (X, 1)) == CONST_INT) \
&& ((((unsigned) INTVAL (XEXP (X, 1)) + 0x8000) < 0x100000)))) \
goto ADDR;}
/* If pic, we accept INDEX+LABEL, which is what do_tablejump makes. */
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
{ if (TARGET_CFV4E && (GET_MODE_CLASS (MODE) == MODE_FLOAT)) \
{ GO_IF_CFV4E_LEGITIMATE_ADDRESS(MODE, X, ADDR); \
} else { \
GO_IF_NONINDEXED_ADDRESS (X, ADDR); \
GO_IF_INDEXED_ADDRESS (X, ADDR); \
if (flag_pic && MODE == CASE_VECTOR_MODE && GET_CODE (X) == PLUS \
&& LEGITIMATE_INDEX_P (XEXP (X, 0)) \
&& GET_CODE (XEXP (X, 1)) == LABEL_REF) \
goto ADDR; } }
Which should reject any address for class FLOAT that isn't address
modes 2-5 (register indirect, predecrement, postincrement, register
indirect with offset).
I've also modified LEGITIMIZE_ADDRESS to be:
#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \
{ register int ch = (X) != (OLDX); \
if (GET_CODE (X) == PLUS) \
{ int copied = 0; \
if (GET_CODE (XEXP (X, 0)) == MULT) \
{ COPY_ONCE (X); XEXP (X, 0) = force_operand (XEXP (X, 0), 0);} \
if (GET_CODE (XEXP (X, 1)) == MULT) \
{ COPY_ONCE (X); XEXP (X, 1) = force_operand (XEXP (X, 1), 0);} \
if (ch && GET_CODE (XEXP (X, 1)) == REG \
&& GET_CODE (XEXP (X, 0)) == REG) \
{ if (TARGET_CFV4E && GET_MODE_CLASS (MODE) == MODE_FLOAT) \
{ COPY_ONCE (X); X = force_operand(X, 0); goto WIN;} \
if (ch) goto WIN; } \
if (ch) { GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN); } \
if (GET_CODE (XEXP (X, 0)) == REG \
|| (GET_CODE (XEXP (X, 0)) == SIGN_EXTEND \
&& GET_CODE (XEXP (XEXP (X, 0), 0)) == REG \
&& GET_MODE (XEXP (XEXP (X, 0), 0)) == HImode)) \
{ register rtx temp = gen_reg_rtx (Pmode); \
register rtx val = force_operand (XEXP (X, 1), 0); \
emit_move_insn (temp, val); \
COPY_ONCE (X); \
XEXP (X, 1) = temp; \
goto WIN; } \
else if (GET_CODE (XEXP (X, 1)) == REG \
|| (GET_CODE (XEXP (X, 1)) == SIGN_EXTEND \
&& GET_CODE (XEXP (XEXP (X, 1), 0)) == REG \
&& GET_MODE (XEXP (XEXP (X, 1), 0)) == HImode)) \
{ register rtx temp = gen_reg_rtx (Pmode); \
register rtx val = force_operand (XEXP (X, 0), 0); \
emit_move_insn (temp, val); \
COPY_ONCE (X); \
XEXP (X, 0) = temp; \
goto WIN; }}}
Note the check for TARGET_CFV4E and MODE_CLASS of FLOAT which forces
REG+REG into a register and uses indirect.
And *still* it generates:
(insn 18 16 20 (set (reg:DF 35)
(mem:DF (plus:SI (reg:SI 33)
(reg:SI 34)) [0 S8 A16])) -1 (nil)
(nil))
Which causes the compilation to fail with:
/tmp/t.c:7: unrecognizable insn:
(insn 20 18 22 (set (reg:DF 35)
(mem:DF (plus:SI (reg:SI 33)
(reg:SI 36)) [0 S8 A16])) -1 (nil)
(expr_list:REG_DEAD (reg:SI 33)
(expr_list:REG_DEAD (reg:SI 36)
(nil))))
/tmp/t.c:7: Internal compiler error in extract_insn, at recog.c:2129
In gcc-2.95.3, the rtl dump for this was the two instructions:
(insn 14 13 16 (set (reg:SI 34)
(plus:SI (reg:SI 33)
(reg/v:SI 29))) -1 (nil)
(nil))
(insn 16 14 18 (set (reg:DF 35)
(mem:DF (reg:SI 34) 0)) -1 (nil)
(nil))
So my question is:
1) How does gcc decide that (REG+REG) is valid for the movdf instuction?
2) Is it considered valid for the compiler to generate RTL that the
patterns constraints reject in the rtl generation pass and hope
that GO_IF_LEGITIMATE_ADDRESS and LEGITIMIZE_ADDRESS will fix?
2) If the answer to 2 is true, should I split the instruction up
in the expand of movdf if operand1 is of that addressing mode, or
should I add a 'valid_fpu_src_operand' predicate in the movdf_v4e
insn pattern to reject (REG+REG) addressing modes?
Thanks for any suggestions,
--
Peter Barada Peter.Barada@motorola.com
Wizard 781-852-2768 (direct)
WaveMark Solutions(wholly owned by Motorola) 781-270-0193 (fax)