ColdFire v4e FPU addressing problems

Peter Barada pbarada@mail.wm.sps.mot.com
Fri Jan 18 09:26:00 GMT 2002


I'm slogging along adding in FPU support for ColdFire's FPU, and I've
run into a problem that I'm not sure of how to fix.

The V4E FPU can not load values using an absolute address, so i
modified movdf to push contants into memory, and force symbol
addresses into registers:

(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));
  }
}")

(define_insn "movdf_v4e"
  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,<Q>U,r,f")
	(match_operand:DF 1 "valid_fpu_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\";
}")

Note the 'valid_fpu_operand' predicate which I had to invent to
reject constants since the gcse pass tried to propagate them.
The constraint of '<Q>U' alloew predecrement, register indirect,
postincrement, an register indirect with offset.  Note that 'm' and
'o' are rejected as constraints since the FPU can't deal with (R+R)
addressing either.

The current problem is that in global_alloc(), the reload pass is trying
to reload FPU constants, and at line 7518 of gcc/reload1.c, the following
code executes:

  /* If IN is a simple operand, use gen_move_insn.  */
  else if (GET_RTX_CLASS (GET_CODE (in)) == 'o' || GET_CODE (in) == SUBREG)
    emit_insn (gen_move_insn (out, in));

(gdb) call debug_rtx(out)

(reg:DF 17 %fp1)
(gdb) call debug_rtx(in)

(const_double:DF 0 [0x0] 0 [0x0] 1073643520 [0x3ffe8000])
(gdb) down
#1  0x081033ff in emit_insn (pattern=0x401abfb0)
    at /home/pbarada/work/cvs-wavemark/cross-linux-tools/gcc-3/gcc/emit-rtl.c:3934
(gdb) call debug_rtx(pattern)

(set (reg:DF 17 %fp1)
    (mem/u/f:DF (symbol_ref/u:SI ("*.LC1")) [6 S8 A32]))
(gdb) 


Since the FPU can't deal with absolute addresses, this fails with:

/tmp/boldfill.c:44: unrecognizable insn:
(insn 246 101 103 (set (reg:DF 17 %fp1)
        (mem/u/f:DF (symbol_ref/u:SI ("*.LC1")) [6 S8 A32])) -1 (nil)
    (nil))
/tmp/boldfill.c:44: Internal compiler error in extract_insn, at recog.c:2129


Does anyone have any ideas how I can convince reload that if it wants
to reload the FPU constant that it has to use an address register to
hold its address and load it indirectly...

Thanks for any advice,

-- 
Peter Barada                                   Peter.Barada@motorola.com
Wizard                                         781-852-2768 (direct)
WaveMark Solutions(wholly owned by Motorola)   781-270-0193 (fax)



More information about the Gcc mailing list