On Thu, 28 Jun 2007 14:55:17 +0200, "Rask Ingemann Lambertsen" <[EMAIL PROTECTED]> 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" <[EMAIL PROTECTED]> 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?