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]

Re: [ARM] Cirrus EP93xx Maverick Crunch Support - CC modes / condexec / CC_REGNUM


On Thu, 28 Jun 2007 14:55:17 +0200, "Rask Ingemann Lambertsen"
<rask@sygehus.dk> said:
> On Wed, Jun 27, 2007 at 11:26:41AM +1000, Hasjim Williams wrote:
> > 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
> 
>    The key to getting this right is to use a special comparison mode for
> MaverickCrunch comparisons. You have to look at arm_gen_compare_reg(),
> which
> calls arm_select_cc_mode() to do all the work. I think there's probably a
> mess in there: CCFPmode is used for some non-MaverickCrunch floating
> point
> compares as well as some MaverickCrunch ones. You'll have to sort that
> out.
> The safe way would be to define a new mode, say CCMAVmode, and use that.

I think a new CCMAV mode is needed, if I reenable the cfcmp64 code,
otherwise, the other CCFP modes aren't used, since an ARM processor can
only have one floating-point co-processor, either FPA, VFP or MAVERICK,
selected by the -mfpu arg.  Current patches replaces the
get_arm_condition_code for CCFPmode, if TARGET_MAVERICK is set. 
Conditional execution is tricky, since you don't check for unordered
when doing a integer comparison, and you might want to check for signed
comparison or unsigned comparison.  I think two CC "maverick-specific"
modes are needed for the comparison stuff if 64-bit comparisons are
enabled, because of this reason.  Probably better to leave 64-bit
comparison disabled I think, and let the soft 64-bit int comparison
handle it, and hence not worry about conditional execution for 64-bit
int at all.

> (define_insn "*cirrus_cmpdi"
>   [(set (reg:CC CC_REGNUM)
>         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
>                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
>   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
>   "cfcmp64%?\\tr15, %V0, %V1"
>   [(set_attr "type"   "mav_farith")
>    (set_attr "cirrus" "compare")]
> )
> 
> Does this insn also set the flags according to the MaverickCrunch NZCV
> table
> above? If so, it needs to use a MaverickCrunch CCmode too, in which case,
> with the CANONICALIZE_COMPARISON macro, you can change

Yes, this instruction compares two 64-bit values in the maverick
coprocessor & stores the result in NZCV flags in PC/R15.  At the moment,
I have disabled 64bit support in my Maverick Crunch patches, simply
because the 64-bit support is signed only, or unsigned only depending on
the value of UI in DSPSC in the Maverick co-processor, and most code
doesn't make use of 64-bit, so the performance hit is minimal.  I think
there are some EABI functions to wrap unsigned 64bit functions to signed
64bit functions, but I haven't really checked this, in detail...
 
>    Once you know that all MaverickCrunch comparisons (and only those)
>    have
> (reg:CCMAV CC_REGNUM) in them, then it is easy to write all the
> corresponding comparison and branch instructions.

Agreed.  I have had the correct conditional executing for a while, and
have run the ieee754 tests with dejagnu and they all passed.  It was
only a couple of days ago, that I realised that I was replacing all bge
instructions.  The other comparisons that can't be implemented (on the
maverick crunch), shouldn't matter since they aren't used in the other
comparison modes.  But just to be safe, I have put the CCFP arg on them,
since this is the only mode that they should be used in.  The other
floating point ARM co-processors make use of a CCFPE mode, but the
MaverickCrunch doesn't need it.

In any case I have a working gcc compiler for the MaverickCrunch, that
lets me compile everything and seems to execute everything correctly
now.  However, I have disabled conditional execution and 64-bit int
mode, for the time being...  I think I will have to add a
maverick_cc_register though, like you suggest if I want to enable
conditional execution, otherwise the cc_register will have maverick and
arm comparisons in there, and they won't combine correctly, etc. 
Incidentally it is mentioned in the arm.c comments that conditional
execution can decrease execution time, and code size by deleting branch
instructions, but only if the `target` is not an unconditional branch.

The other "co-processor offset out of range" seems to be related to the
length attr for "sibcall_epilogue" and "epilogue_insns" since saving
each maverick crunch register to the stack takes two instructions (since
they need to be separated by nops, and if you save them all you will go
beyond the length of "44" currently defined.  I've currently defined
this as "108", which is "44" + "64", an extra 16*4, once for each nop
for each register, but I have a feeling that not all 16 maverick crunch
registers are necessarily saved.  Can someone with more ARM knowledge
than me clear this up?

I don't think the nop bugfixes (that I mentioned in the other e-mail)
actually cause an issue...

On Thu, 28 Jun 2007 15:14:35 +0200, "Rask Ingemann Lambertsen"
<rask@sygehus.dk> said:

> where "maverick_comparison_operator" matches those operators map to a
> predicate, get_arm_condition_code() modified to understand CCMAVmode so
> print_operand() will print the correct mnemonics and a new
> non_maverick_cc_register which doesn't match MaverickCrunch specific
> CCmodes.

Since cc_register is already generically defined for ARM (in
predicates.md):

(define_special_predicate "cc_register"
  (and (match_code "reg")
       (and (match_test "REGNO (op) == CC_REGNUM")
	    (ior (match_test "mode == GET_MODE (op)")
		 (match_test "mode == VOIDmode && GET_MODE_CLASS (GET_MODE (op)) == MODE_CC")))))

I guess I will need to define a new "maverick_cc_register".  My question
is can I reuse the same CC_REGNUM? Or do I also need another new
CC_REGNUM_MAVERICK pseudo register?  In arm.md the registers are defined
as follows:

0-11   Standard ARM core regs
12     Scratch register
13     Stack pointer
14     Return address register
15     Program counter
16-23  FPA coprocessor regs
24     Condition code pseudo register
25     Frame pointer reg
26     Arg pointer Regnum
27-42  MAVERICK coprocessor regs
43-46  IWMMXT GR regs
47-62  IWMMXT regs
63-94  VFP registers
95     ?????
96     FIRST_PSEUDO_REGISTER

How do I get a new reg number allocated, if I need one?  Separating a
crunch compare into a separate cc register would make things slightly
simpler for maverick crunch conditional execution wouldn't it?

If a new CC_REGNUM_MAVERICK is defined, then the SF/DF/64-bit compares
would just need to be modified from:

;; Cirrus SF compare instruction
(define_insn "*cirrus_cmpsf"
  [(set (reg:CCFP CC_REGNUM)
	(compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
		      (match_operand:SF 1 "cirrus_fp_register" "v")))]
  "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
  "cfcmps%?\\tr15, %V0, %V1"
  [(set_attr "type"   "mav_farith")
   (set_attr "cirrus" "compare")]
)

to:

;; Cirrus SF compare instruction
(define_insn "*cirrus_cmpsf"
  [(set (reg:CCFP CC_REGNUM_MAVERICK)
	(compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
		      (match_operand:SF 1 "cirrus_fp_register" "v")))]
  "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
  "cfcmps%?\\tr15, %V0, %V1"
  [(set_attr "type"   "mav_farith")
   (set_attr "cirrus" "compare")]
)

And the other arm_bge routines, etc should be modified to
"cc_register_maverick" .  New insn would then need to be defined for
maverick_cond_branch*, etc, which would just then be the same as
arm_cond_branch with arm_comparison_operator and cc_register replaced
with the maverick versions.

The only problem would be, is that anything that clobbers CC_REGNUM
needs to clobber CC_REGNUM_MAVERICK too (and vice-versa), since even
though they are pseudo-registers, they both are the NZCV flags in
pc/r15.  Any way to quickly do a search/replace in arm.md, etc for this?


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