public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
From: Peter Barada <pbarada@mail.wm.sps.mot.com>
To: gcc@gcc.gnu.org
Cc: Peter.Barada@motorola.com
Subject: Re: Restricted addressing modes in ColdFire FPU for DFmode
Date: Fri, 07 Dec 2001 10:13:00 -0000	[thread overview]
Message-ID: <200112071802.fB7I2cd25266@hyper.wm.sps.mot.com> (raw)


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.

The fmove.d instruction supports only the following addressing modes:
predecrement, postincement, indirect, inderect with offset, and
pc-relative with offset(for loads).  Note that neither register direct
nor absolute addressing is supported.  I created to following RTL for
movdf:

(define_expand "movdf"
  [(set (match_operand:DF 0 "nonimmediate_operand" "")
	(match_operand:DF 1 "general_operand" ""))]
  ""
  "
{
  if (TARGET_FPU_V4E) {
    /* The ColdFire FPU can't deal with absolute addresses or double
     * constants, so push the constant 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)));
  }
}")

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


And that split up symbolic addressing quite well(as well as handled constants):

(insn 8 6 9 (set (reg:SI 30)
        (symbol_ref/u:SI ("*.LC0"))) -1 (nil)
    (expr_list:REG_EQUAL (symbol_ref/u:SI ("*.LC0"))
        (nil)))

(insn 9 8 10 (set (reg/i:DF 16 %fp0)
        (mem:DF (reg:SI 30) 0)) -1 (nil)
    (nil))

but the combiner converted that back into:

(insn 9 8 10 (set (reg/i:DF 16 %fp0)
        (mem:DF (symbol_ref/u:SI ("*.LC0")) 0)) 67 {movdf_v4e} (nil)
    (expr_list:REG_EQUAL (const_double:DF (mem/u:DF (symbol_ref/u:SI ("*.LC0")) 0) 0 [0x0] 0 [0x0] 1073643520 [0x3ffe8000])
        (nil)))

Which died with:

/tmp/z.c: In function `x':
/tmp/z.c:5: 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))



I looked over combine.c, and I didn't see anyway that a target can
prevent combination from happening.  So in desperation I decided to
add a flag to the rtx struct:

  /* 1 in an INSN or a SET if this rtx can *not* be combined with
     either RTX next to it.  Its necessary to limit the combiner from
     creating RTX that the machine description worked very hard to
     keep seperate */
  unsigned cannot_combine : 1;


And its access macro:

#define RTX_CANNOT_COMBINE_P(RTX) ((RTX)->cannot_combine)


As well as modify the initializer of global_rtl to add the extra zero...
And then added the following statment to cant_combine_insn_p():

  /* For particular chips with restrictive addressing modes, the
     machine description may split up accesses and then mark the
     instruction.  As an example the ColdFire FPU can't deal with
     absolute addressing, but the ColdFire integer unit can, so the
     m68k.md forces the symbol_ref into a register and uses indirect
     addressing, and marks the instruction as one that can't be
     combined. */
  if (RTX_CANNOT_COMBINE_P (insn))
    return 1;


As well as changed the movdf pattern to:

(define_expand "movdf"
  [(set (match_operand:DF 0 "nonimmediate_operand" "")
	(match_operand:DF 1 "general_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)));
      /* Create the instruciton and set RTX_CANNOT_COMBINE_P to
         prevent the combiner from putting this back together.
      insn = emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
      RTX_CANNOT_COMBINE_P (insn) = 1;
      DONE;
    }
  }
}")


Now the following code:

double x(void)
{
  return 0.5;
}

Compiles into:

	.file	"z.c"
gcc2_compiled.:
.section	.rodata
	.align 	2
.LC0:
	.double 0r5.00000000000000000000e-1
.text
.globl x
	.type	 x,@function
x:
	link.w %a6,#0
	lea .LC0,%a0
	fmove.d (%a0),%fp0
	unlk %a6
	rts

Which looks correct.


My question to you all is whether or not this is a viable approach.
Does anyone have a suggestion for how better to solve this problem?

Thanks in advance for your guidance,

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

             reply	other threads:[~2001-12-07 18:06 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2001-12-07 10:13 Peter Barada [this message]
2001-12-07 11:27 ` Alan Lehotsky
2001-12-07 13:01   ` Peter Barada
2001-12-07 17:35 Re^2: " Peter Barada
2001-12-08 22:46 ` Richard Henderson
2001-12-10  8:15   ` Peter Barada
2001-12-10 13:11     ` Richard Henderson
2001-12-10 13:59       ` Peter Barada
2001-12-10 15:06         ` Peter Barada

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200112071802.fB7I2cd25266@hyper.wm.sps.mot.com \
    --to=pbarada@mail.wm.sps.mot.com \
    --cc=Peter.Barada@motorola.com \
    --cc=gcc@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).