This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[ARM] Cirrus EP93xx Maverick Crunch Support - "bge" pattern


G'day all,

As I wrote previously on gcc-patches (
http://gcc.gnu.org/ml/gcc-patches/2007-06/msg00244.html ), I'm working
on code to get the MaverickCrunch Floating-Point Co-processor supported
on ARM.  I mentioned previously that you can't use the same opcodes for
testing GE on the MaverickCrunch, as you use on ARM.  See the below
table for NZCV values from MaverickCrunch.

MaverickCrunch - (cfcmp*):
        N  Z  C  V
A == B  0  1  0  0
A <  B  1  0  0  0
A >  B  1  0  0  1
unord   0  0  0  0

ARM/FPA/VFP - (cmp*):
        N  Z  C  V
A == B  0  1  1  0
A <  B  1  0  0  0
A >  B  0  0  1  0
unord   0  0  1  1

I've added a new "maverick_comparison_operator" similar to
"arm_comparison_operator" to predicates.md, and added the right bits to
arm.md, as shown below:

;; Special predication pattern for Maverick Crunch floating-point

(define_cond_exec
  [(match_operator 0 "maverick_comparison_operator"
    [(match_operand:CCFP 1 "cc_register" "")
     (const_int 0)])]
  "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
  ""
)

All the other predicates are fine, since they are only used in floating
point comparisons.  But "ge" is also used for integer comparisons.  Now,
my problem is with the following code: 

; Special pattern to match GE for MAVERICK.
(define_insn "*arm_bge"
  [(set (pc)
	(if_then_else (ge (match_operand 1 "cc_register" "") (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
  "*
  gcc_assert (!arm_ccfsm_state);
  if (get_attr_cirrus (prev_active_insn(insn)) == CIRRUS_COMPARE)
      return \"beq\\t%l0\;bvs\\t%l0\"; else return \"bge\\t%l0\;nop\";
  "
  [(set_attr "conds" "jump_clob")
   (set_attr "length" "8")]
)

As you can see, I need to replace all bge with a maverick crunch
equivalent.  However, "bge" is still also used with integer comparisons,
e.g:

	double a, b;
	if (a>=b) {

produces:

	cfcmpd	r15, mvd1, mvd0
	beq	.L4
	bvs	.L4
	b	.L2
.L4:

I haven't got a good example for the integer ge, but unsidf makes use of
ge (NB, I disabled MaverickCrunch 64-bit support for clarity, and
bugfixing):

	unsigned int e = 9;
	double e_d = e;

produces:

	mov	r3, #9
	str	r3, [fp, #-32]
	ldr	r0, [fp, #-32]
	bl	__aeabi_i2d
	str	r0, [fp, #-44]
	str	r1, [fp, #-40]
	ldr	r3, [fp, #-32]
	cmp	r3, #0
	bge	.L2
	nop
	mov	r0, r0	@ nop
	mov	r0, r0	@ nop
	cfldrd	mvd0, .L4
	mov	r0, r0	@ nop
	cfldrd	mvd1, [fp, #-44]
	mov	r0, r0	@ nop
	cfaddd	mvd1, mvd1, mvd0
	cfstrd	mvd1, [fp, #-44]
.L2:

This seems to work fine for C code, but when I generate C++ code, I get
errors.  Can anyone suggest a better way of writing the above code?  I'd
rather the jump_clob didn't actually happen unless it was definitely a
cirrus compare, and not an ARM compare, but I can't seem to write the
code correctly.

Also, is "(get_attr_cirrus (prev_active_insn(insn)) == CIRRUS_COMPARE)"
the best way to find out if the last compare instruction was a cirrus
compare, or an ARM compare?  Should I add a new routine to find the last
compare insn, e.g. prev_compare_insn???  I know that a branch doesn't
have to be directly after a comparison.

This and invalid coprocessor offset issue are the only two outstanding
bugs for MaverickCrunch support on the Cirrus EP93xx.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]