This patch builds upon the patch in: http://gcc.gnu.org/ml/gcc-patches/2013-01/msg01457.html
It merges the DFmode and DDmode moves into one pattern. In addition, it merges the -mmfpgpr code with the normal floating point moves, using a new conditional constraint (wg) that only returns FLOAT_REGS for the power6x. I have tested this via bootstrap, and there were no regressions. Is patch acceptable to check in when the 4.9 tree opens up? 2013-01-30 Michael Meissner <meiss...@linux.vnet.ibm.com> * config/rs6000/constraints.md (wg constraint): New constraint to return FLOAT_REGS if -mmfpgpr (power6x) was used. * config/rs6000/rs6000.h (enum r6000_reg_class_enum): Add wg constraint. * config/rs6000/rs6000.c (rs6000_debug_reg_global): If -mdebug=reg, print wg, wl, wx, and wz constraints. (rs6000_init_hard_regno_mode_ok): Initialize new constraints. Initialize the reload functions for 64-bit binary/decimal floating point types. (reg_offset_addressing_ok_p): If we are on a power7 or later, use LFIWZX and STFIWX to load/store 32-bit decimal types, and don't create the buffer on the stack to overcome not having a 32-bit load and store. (rs6000_emit_move): Likewise. (rs6000_secondary_memory_needed_rtx): Likewise. (rs6000_alloc_sdmode_stack_slot): Likewise. (rs6000_preferred_reload_class): On VSX, we can create SFmode 0.0f via xxlxor, just like DFmode 0.0. * config/rs6000/dfp.md (movdd): Delete, combine with binary floating point moves in rs6000.md. Combine power6x (mfpgpr) moves with other moves by using conditional constraits (wg). Use LFIWZX and STFIWX for loading SDmode on power7. (movdd splitters): Likewise. (movdd_hardfloat32): Likewise. (movdd_softfloat32): Likewise. (movdd_hardfloat64_mfpgpr): Likewise. (movdd_hardfloat64): Likewise. (movdd_softfloat64): Likewise. * config/rs6000/rs6000.md (FMOVE64): New iterators to combine 64-bit binary and decimal floating point moves. (FMOVE64X): Likewise. (movdf): Combine 64-bit binary and decimal floating point moves. Combine power6x (mfpgpr) moves with other moves by using conditional constraits (wg). (mov<mode> for DFmode/DDmode): Likewise. (DFmode/DDmode splitters): Likewise. (movdf_hardfloat32): Likewise. (mov<mode>_hardfloat32 for DFmode/DDmode): Likewise. (movdf_softfloat32): Likewise. (movdf_hardfloat64_mfpgpr): Likewise. (movdf_hardfloat64): Likewise. (mov<mode>_hardfloat64 for DFmode/DDmode): Likewise. (movdf_softfloat64): Likewise. (mov<mode>_softfloat64 for DFmode/DDmode): Likewise. (reload_<mode>_load): Move to later in the file so they aren't in the middle of the floating point move insns. (reload_<mode>_store): Likewise. * doc/md.texi (PowerPC and IBM RS6000 constraints): Document wg constraint. -- Michael Meissner, IBM 5 Technology Place Drive, M/S 2757, Westford, MA 01886-3141, USA meiss...@linux.vnet.ibm.com fax +1 (978) 399-6899
Index: gcc/config/rs6000/constraints.md =================================================================== --- gcc/config/rs6000/constraints.md (revision 195586) +++ gcc/config/rs6000/constraints.md (working copy) @@ -69,6 +69,9 @@ (define_register_constraint "wa" "rs6000 "@internal") ;; Register constraints to simplify move patterns +(define_register_constraint "wg" "rs6000_constraints[RS6000_CONSTRAINT_wg]" + "Floating point register if -mmfpgpr is used, or NO_REGS.") + (define_register_constraint "wl" "rs6000_constraints[RS6000_CONSTRAINT_wl]" "Floating point register if the LFIWAX instruction is enabled or NO_REGS.") Index: gcc/config/rs6000/rs6000.h =================================================================== --- gcc/config/rs6000/rs6000.h (revision 195586) +++ gcc/config/rs6000/rs6000.h (working copy) @@ -1324,6 +1324,7 @@ enum r6000_reg_class_enum { RS6000_CONSTRAINT_v, /* Altivec registers */ RS6000_CONSTRAINT_wa, /* Any VSX register */ RS6000_CONSTRAINT_wd, /* VSX register for V2DF */ + RS6000_CONSTRAINT_wg, /* FPR register for -mmfpgpr */ RS6000_CONSTRAINT_wf, /* VSX register for V4SF */ RS6000_CONSTRAINT_wl, /* FPR register for LFIWAX */ RS6000_CONSTRAINT_ws, /* VSX register for DF */ Index: gcc/config/rs6000/dfp.md =================================================================== --- gcc/config/rs6000/dfp.md (revision 195586) +++ gcc/config/rs6000/dfp.md (working copy) @@ -111,211 +111,6 @@ (define_insn "*nabsdd2_fpr" "fnabs %0,%1" [(set_attr "type" "fp")]) -(define_expand "movdd" - [(set (match_operand:DD 0 "nonimmediate_operand" "") - (match_operand:DD 1 "any_operand" ""))] - "" - "{ rs6000_emit_move (operands[0], operands[1], DDmode); DONE; }") - -(define_split - [(set (match_operand:DD 0 "gpc_reg_operand" "") - (match_operand:DD 1 "const_int_operand" ""))] - "! TARGET_POWERPC64 && reload_completed - && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31) - || (GET_CODE (operands[0]) == SUBREG - && GET_CODE (SUBREG_REG (operands[0])) == REG - && REGNO (SUBREG_REG (operands[0])) <= 31))" - [(set (match_dup 2) (match_dup 4)) - (set (match_dup 3) (match_dup 1))] - " -{ - int endian = (WORDS_BIG_ENDIAN == 0); - HOST_WIDE_INT value = INTVAL (operands[1]); - - operands[2] = operand_subword (operands[0], endian, 0, DDmode); - operands[3] = operand_subword (operands[0], 1 - endian, 0, DDmode); -#if HOST_BITS_PER_WIDE_INT == 32 - operands[4] = (value & 0x80000000) ? constm1_rtx : const0_rtx; -#else - operands[4] = GEN_INT (value >> 32); - operands[1] = GEN_INT (((value & 0xffffffff) ^ 0x80000000) - 0x80000000); -#endif -}") - -(define_split - [(set (match_operand:DD 0 "gpc_reg_operand" "") - (match_operand:DD 1 "const_double_operand" ""))] - "! TARGET_POWERPC64 && reload_completed - && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31) - || (GET_CODE (operands[0]) == SUBREG - && GET_CODE (SUBREG_REG (operands[0])) == REG - && REGNO (SUBREG_REG (operands[0])) <= 31))" - [(set (match_dup 2) (match_dup 4)) - (set (match_dup 3) (match_dup 5))] - " -{ - int endian = (WORDS_BIG_ENDIAN == 0); - long l[2]; - REAL_VALUE_TYPE rv; - - REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]); - REAL_VALUE_TO_TARGET_DECIMAL64 (rv, l); - - operands[2] = operand_subword (operands[0], endian, 0, DDmode); - operands[3] = operand_subword (operands[0], 1 - endian, 0, DDmode); - operands[4] = gen_int_mode (l[endian], SImode); - operands[5] = gen_int_mode (l[1 - endian], SImode); -}") - -(define_split - [(set (match_operand:DD 0 "gpc_reg_operand" "") - (match_operand:DD 1 "const_double_operand" ""))] - "TARGET_POWERPC64 && reload_completed - && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31) - || (GET_CODE (operands[0]) == SUBREG - && GET_CODE (SUBREG_REG (operands[0])) == REG - && REGNO (SUBREG_REG (operands[0])) <= 31))" - [(set (match_dup 2) (match_dup 3))] - " -{ - int endian = (WORDS_BIG_ENDIAN == 0); - long l[2]; - REAL_VALUE_TYPE rv; -#if HOST_BITS_PER_WIDE_INT >= 64 - HOST_WIDE_INT val; -#endif - - REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]); - REAL_VALUE_TO_TARGET_DECIMAL64 (rv, l); - - operands[2] = gen_lowpart (DImode, operands[0]); - /* HIGHPART is lower memory address when WORDS_BIG_ENDIAN. */ -#if HOST_BITS_PER_WIDE_INT >= 64 - val = ((HOST_WIDE_INT)(unsigned long)l[endian] << 32 - | ((HOST_WIDE_INT)(unsigned long)l[1 - endian])); - - operands[3] = gen_int_mode (val, DImode); -#else - operands[3] = immed_double_const (l[1 - endian], l[endian], DImode); -#endif -}") - -;; Don't have reload use general registers to load a constant. First, -;; it might not work if the output operand is the equivalent of -;; a non-offsettable memref, but also it is less efficient than loading -;; the constant into an FP register, since it will probably be used there. -;; The "??" is a kludge until we can figure out a more reasonable way -;; of handling these non-offsettable values. -(define_insn "*movdd_hardfloat32" - [(set (match_operand:DD 0 "nonimmediate_operand" "=!r,??r,m,d,d,m,!r,!r,!r") - (match_operand:DD 1 "input_operand" "r,m,r,d,m,d,G,H,F"))] - "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS - && (gpc_reg_operand (operands[0], DDmode) - || gpc_reg_operand (operands[1], DDmode))" - "* -{ - switch (which_alternative) - { - default: - gcc_unreachable (); - case 0: - case 1: - case 2: - return \"#\"; - case 3: - return \"fmr %0,%1\"; - case 4: - return \"lfd%U1%X1 %0,%1\"; - case 5: - return \"stfd%U0%X0 %1,%0\"; - case 6: - case 7: - case 8: - return \"#\"; - } -}" - [(set_attr "type" "two,load,store,fp,fpload,fpstore,*,*,*") - (set_attr "length" "8,16,16,4,4,4,8,12,16")]) - -(define_insn "*movdd_softfloat32" - [(set (match_operand:DD 0 "nonimmediate_operand" "=r,r,m,r,r,r") - (match_operand:DD 1 "input_operand" "r,m,r,G,H,F"))] - "! TARGET_POWERPC64 && (TARGET_SOFT_FLOAT || !TARGET_FPRS) - && (gpc_reg_operand (operands[0], DDmode) - || gpc_reg_operand (operands[1], DDmode))" - "#" - [(set_attr "type" "two,load,store,*,*,*") - (set_attr "length" "8,8,8,8,12,16")]) - -; ld/std require word-aligned displacements -> 'Y' constraint. -; List Y->r and r->Y before r->r for reload. -(define_insn "*movdd_hardfloat64_mfpgpr" - [(set (match_operand:DD 0 "nonimmediate_operand" "=Y,r,!r,d,d,m,*c*l,!r,*h,!r,!r,!r,r,d") - (match_operand:DD 1 "input_operand" "r,Y,r,d,m,d,r,h,0,G,H,F,d,r"))] - "TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS - && (gpc_reg_operand (operands[0], DDmode) - || gpc_reg_operand (operands[1], DDmode))" - "@ - std%U0%X0 %1,%0 - ld%U1%X1 %0,%1 - mr %0,%1 - fmr %0,%1 - lfd%U1%X1 %0,%1 - stfd%U0%X0 %1,%0 - mt%0 %1 - mf%1 %0 - nop - # - # - # - mftgpr %0,%1 - mffgpr %0,%1" - [(set_attr "type" "store,load,*,fp,fpload,fpstore,mtjmpr,mfjmpr,*,*,*,*,mftgpr,mffgpr") - (set_attr "length" "4,4,4,4,4,4,4,4,4,8,12,16,4,4")]) - -; ld/std require word-aligned displacements -> 'Y' constraint. -; List Y->r and r->Y before r->r for reload. -(define_insn "*movdd_hardfloat64" - [(set (match_operand:DD 0 "nonimmediate_operand" "=Y,r,!r,d,d,m,*c*l,!r,*h,!r,!r,!r") - (match_operand:DD 1 "input_operand" "r,Y,r,d,m,d,r,h,0,G,H,F"))] - "TARGET_POWERPC64 && !TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS - && (gpc_reg_operand (operands[0], DDmode) - || gpc_reg_operand (operands[1], DDmode))" - "@ - std%U0%X0 %1,%0 - ld%U1%X1 %0,%1 - mr %0,%1 - fmr %0,%1 - lfd%U1%X1 %0,%1 - stfd%U0%X0 %1,%0 - mt%0 %1 - mf%1 %0 - nop - # - # - #" - [(set_attr "type" "store,load,*,fp,fpload,fpstore,mtjmpr,mfjmpr,*,*,*,*") - (set_attr "length" "4,4,4,4,4,4,4,4,4,8,12,16")]) - -(define_insn "*movdd_softfloat64" - [(set (match_operand:DD 0 "nonimmediate_operand" "=r,Y,r,cl,r,r,r,r,*h") - (match_operand:DD 1 "input_operand" "Y,r,r,r,h,G,H,F,0"))] - "TARGET_POWERPC64 && (TARGET_SOFT_FLOAT || !TARGET_FPRS) - && (gpc_reg_operand (operands[0], DDmode) - || gpc_reg_operand (operands[1], DDmode))" - "@ - ld%U1%X1 %0,%1 - std%U0%X0 %1,%0 - mr %0,%1 - mt%0 %1 - mf%1 %0 - # - # - # - nop" - [(set_attr "type" "load,store,*,mtjmpr,mfjmpr,*,*,*,*") - (set_attr "length" "4,4,4,4,4,8,12,16,4")]) - (define_expand "negtd2" [(set (match_operand:TD 0 "gpc_reg_operand" "") (neg:TD (match_operand:TD 1 "gpc_reg_operand" "")))] Index: gcc/config/rs6000/rs6000.md =================================================================== --- gcc/config/rs6000/rs6000.md (revision 195586) +++ gcc/config/rs6000/rs6000.md (working copy) @@ -255,6 +255,8 @@ (define_mode_iterator FMA_F [ ; Floating point move iterators to combine binary and decimal moves (define_mode_iterator FMOVE32 [SF SD]) +(define_mode_iterator FMOVE64 [DF DD]) +(define_mode_iterator FMOVE64X [DI DF DD]) ; Whether a floating point move is ok, don't allow SD without hardware FP (define_mode_attr fmove_ok [(SF "") @@ -7955,15 +7957,16 @@ (define_insn "*mov<mode>_softfloat" (set_attr "length" "4,4,4,4,4,4,4,4,8,4")]) -(define_expand "movdf" - [(set (match_operand:DF 0 "nonimmediate_operand" "") - (match_operand:DF 1 "any_operand" ""))] +;; Move 64-bit binary/decimal floating point +(define_expand "mov<mode>" + [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "") + (match_operand:FMOVE64 1 "any_operand" ""))] "" - "{ rs6000_emit_move (operands[0], operands[1], DFmode); DONE; }") + "{ rs6000_emit_move (operands[0], operands[1], <MODE>mode); DONE; }") (define_split - [(set (match_operand:DF 0 "gpc_reg_operand" "") - (match_operand:DF 1 "const_int_operand" ""))] + [(set (match_operand:FMOVE64 0 "gpc_reg_operand" "") + (match_operand:FMOVE64 1 "const_int_operand" ""))] "! TARGET_POWERPC64 && reload_completed && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31) || (GET_CODE (operands[0]) == SUBREG @@ -7976,8 +7979,8 @@ (define_split int endian = (WORDS_BIG_ENDIAN == 0); HOST_WIDE_INT value = INTVAL (operands[1]); - operands[2] = operand_subword (operands[0], endian, 0, DFmode); - operands[3] = operand_subword (operands[0], 1 - endian, 0, DFmode); + operands[2] = operand_subword (operands[0], endian, 0, <MODE>mode); + operands[3] = operand_subword (operands[0], 1 - endian, 0, <MODE>mode); #if HOST_BITS_PER_WIDE_INT == 32 operands[4] = (value & 0x80000000) ? constm1_rtx : const0_rtx; #else @@ -7987,8 +7990,8 @@ (define_split }") (define_split - [(set (match_operand:DF 0 "gpc_reg_operand" "") - (match_operand:DF 1 "const_double_operand" ""))] + [(set (match_operand:FMOVE64 0 "gpc_reg_operand" "") + (match_operand:FMOVE64 1 "const_double_operand" ""))] "! TARGET_POWERPC64 && reload_completed && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31) || (GET_CODE (operands[0]) == SUBREG @@ -8003,17 +8006,17 @@ (define_split REAL_VALUE_TYPE rv; REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]); - REAL_VALUE_TO_TARGET_DOUBLE (rv, l); + <real_value_to_target> (rv, l); - operands[2] = operand_subword (operands[0], endian, 0, DFmode); - operands[3] = operand_subword (operands[0], 1 - endian, 0, DFmode); + operands[2] = operand_subword (operands[0], endian, 0, <MODE>mode); + operands[3] = operand_subword (operands[0], 1 - endian, 0, <MODE>mode); operands[4] = gen_int_mode (l[endian], SImode); operands[5] = gen_int_mode (l[1 - endian], SImode); }") (define_split - [(set (match_operand:DF 0 "gpc_reg_operand" "") - (match_operand:DF 1 "const_double_operand" ""))] + [(set (match_operand:FMOVE64 0 "gpc_reg_operand" "") + (match_operand:FMOVE64 1 "const_double_operand" ""))] "TARGET_POWERPC64 && reload_completed && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31) || (GET_CODE (operands[0]) == SUBREG @@ -8030,7 +8033,7 @@ (define_split #endif REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]); - REAL_VALUE_TO_TARGET_DOUBLE (rv, l); + <real_value_to_target> (rv, l); operands[2] = gen_lowpart (DImode, operands[0]); /* HIGHPART is lower memory address when WORDS_BIG_ENDIAN. */ @@ -8055,12 +8058,12 @@ (define_split ;; since the D-form version of the memory instructions does not need a GPR for ;; reloading. -(define_insn "*movdf_hardfloat32" - [(set (match_operand:DF 0 "nonimmediate_operand" "=m,d,d,ws,?wa,Z,?Z,ws,?wa,wa,Y,r,!r,!r,!r,!r") - (match_operand:DF 1 "input_operand" "d,m,d,Z,Z,ws,wa,ws,wa,j,r,Y,r,G,H,F"))] +(define_insn "*mov<mode>_hardfloat32" + [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=m,d,d,ws,?wa,Z,?Z,ws,?wa,wa,Y,r,!r,!r,!r,!r") + (match_operand:FMOVE64 1 "input_operand" "d,m,d,Z,Z,ws,wa,ws,wa,j,r,Y,r,G,H,F"))] "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT - && (gpc_reg_operand (operands[0], DFmode) - || gpc_reg_operand (operands[1], DFmode))" + && (gpc_reg_operand (operands[0], <MODE>mode) + || gpc_reg_operand (operands[1], <MODE>mode))" "@ stfd%U0%X0 %1,%0 lfd%U1%X1 %0,%1 @@ -8081,90 +8084,30 @@ (define_insn "*movdf_hardfloat32" [(set_attr "type" "fpstore,fpload,fp,fpload,fpload,fpstore,fpstore,vecsimple,vecsimple,vecsimple,store,load,two,fp,fp,*") (set_attr "length" "4,4,4,4,4,4,4,4,4,4,8,8,8,8,12,16")]) -(define_insn "*movdf_softfloat32" - [(set (match_operand:DF 0 "nonimmediate_operand" "=Y,r,r,r,r,r") - (match_operand:DF 1 "input_operand" "r,Y,r,G,H,F"))] +(define_insn "*mov<mode>_softfloat32" + [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=Y,r,r,r,r,r") + (match_operand:FMOVE64 1 "input_operand" "r,Y,r,G,H,F"))] "! TARGET_POWERPC64 && ((TARGET_FPRS && TARGET_SINGLE_FLOAT) || TARGET_SOFT_FLOAT || TARGET_E500_SINGLE) - && (gpc_reg_operand (operands[0], DFmode) - || gpc_reg_operand (operands[1], DFmode))" + && (gpc_reg_operand (operands[0], <MODE>mode) + || gpc_reg_operand (operands[1], <MODE>mode))" "#" [(set_attr "type" "store,load,two,*,*,*") (set_attr "length" "8,8,8,8,12,16")]) -;; Reload patterns to support gpr load/store with misaligned mem. -;; and multiple gpr load/store at offset >= 0xfffc -(define_expand "reload_<mode>_store" - [(parallel [(match_operand 0 "memory_operand" "=m") - (match_operand 1 "gpc_reg_operand" "r") - (match_operand:GPR 2 "register_operand" "=&b")])] - "" -{ - rs6000_secondary_reload_gpr (operands[1], operands[0], operands[2], true); - DONE; -}) - -(define_expand "reload_<mode>_load" - [(parallel [(match_operand 0 "gpc_reg_operand" "=r") - (match_operand 1 "memory_operand" "m") - (match_operand:GPR 2 "register_operand" "=b")])] - "" -{ - rs6000_secondary_reload_gpr (operands[0], operands[1], operands[2], false); - DONE; -}) - -; ld/std require word-aligned displacements -> 'Y' constraint. -; List Y->r and r->Y before r->r for reload. -(define_insn "*movdf_hardfloat64_mfpgpr" - [(set (match_operand:DF 0 "nonimmediate_operand" "=Y,r,!r,ws,?wa,ws,?wa,Z,?Z,m,d,d,wa,*c*l,!r,*h,!r,!r,!r,r,d") - (match_operand:DF 1 "input_operand" "r,Y,r,ws,?wa,Z,Z,ws,wa,d,m,d,j,r,h,0,G,H,F,d,r"))] - "TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS - && TARGET_DOUBLE_FLOAT - && (gpc_reg_operand (operands[0], DFmode) - || gpc_reg_operand (operands[1], DFmode))" - "@ - std%U0%X0 %1,%0 - ld%U1%X1 %0,%1 - mr %0,%1 - xxlor %x0,%x1,%x1 - xxlor %x0,%x1,%x1 - lxsd%U1x %x0,%y1 - lxsd%U1x %x0,%y1 - stxsd%U0x %x1,%y0 - stxsd%U0x %x1,%y0 - stfd%U0%X0 %1,%0 - lfd%U1%X1 %0,%1 - fmr %0,%1 - xxlxor %x0,%x0,%x0 - mt%0 %1 - mf%1 %0 - nop - # - # - # - mftgpr %0,%1 - mffgpr %0,%1" - [(set_attr "type" "store,load,*,fp,fp,fpload,fpload,fpstore,fpstore,fpstore,fpload,fp,vecsimple,mtjmpr,mfjmpr,*,*,*,*,mftgpr,mffgpr") - (set_attr "length" "4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,8,12,16,4,4")]) - ; ld/std require word-aligned displacements -> 'Y' constraint. ; List Y->r and r->Y before r->r for reload. -(define_insn "*movdf_hardfloat64" - [(set (match_operand:DF 0 "nonimmediate_operand" "=m,d,d,Y,r,!r,ws,?wa,Z,?Z,ws,?wa,wa,*c*l,!r,*h,!r,!r,!r") - (match_operand:DF 1 "input_operand" "d,m,d,r,Y,r,Z,Z,ws,wa,ws,wa,j,r,h,0,G,H,F"))] - "TARGET_POWERPC64 && !TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS - && TARGET_DOUBLE_FLOAT - && (gpc_reg_operand (operands[0], DFmode) - || gpc_reg_operand (operands[1], DFmode))" +(define_insn "*mov<mode>_hardfloat64" + [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=m,d,d,ws,?wa,Z,?Z,ws,?wa,wa,Y,r,!r,*c*l,!r,*h,!r,!r,!r,r,wg") + (match_operand:FMOVE64 1 "input_operand" "d,m,d,Z,Z,ws,wa,ws,wa,j,r,Y,r,r,h,0,G,H,F,wg,r"))] + "TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT + && (gpc_reg_operand (operands[0], <MODE>mode) + || gpc_reg_operand (operands[1], <MODE>mode))" "@ stfd%U0%X0 %1,%0 lfd%U1%X1 %0,%1 fmr %0,%1 - std%U0%X0 %1,%0 - ld%U1%X1 %0,%1 - mr %0,%1 lxsd%U1x %x0,%y1 lxsd%U1x %x0,%y1 stxsd%U0x %x1,%y0 @@ -8172,21 +8115,26 @@ (define_insn "*movdf_hardfloat64" xxlor %x0,%x1,%x1 xxlor %x0,%x1,%x1 xxlxor %x0,%x0,%x0 + std%U0%X0 %1,%0 + ld%U1%X1 %0,%1 + mr %0,%1 mt%0 %1 mf%1 %0 nop # # - #" - [(set_attr "type" "fpstore,fpload,fp,store,load,*,fpload,fpload,fpstore,fpstore,vecsimple,vecsimple,vecsimple,mtjmpr,mfjmpr,*,*,*,*") - (set_attr "length" "4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,8,12,16")]) + # + mftgpr %0,%1 + mffgpr %0,%1" + [(set_attr "type" "fpstore,fpload,fp,fpload,fpload,fpstore,fpstore,vecsimple,vecsimple,vecsimple,store,load,*,mtjmpr,mfjmpr,*,*,*,*,mftgpr,mffgpr") + (set_attr "length" "4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,8,12,16,4,4")]) -(define_insn "*movdf_softfloat64" - [(set (match_operand:DF 0 "nonimmediate_operand" "=Y,r,r,cl,r,r,r,r,*h") - (match_operand:DF 1 "input_operand" "r,Y,r,r,h,G,H,F,0"))] +(define_insn "*mov<mode>_softfloat64" + [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=Y,r,r,cl,r,r,r,r,*h") + (match_operand:FMOVE64 1 "input_operand" "r,Y,r,r,h,G,H,F,0"))] "TARGET_POWERPC64 && (TARGET_SOFT_FLOAT || !TARGET_FPRS) - && (gpc_reg_operand (operands[0], DFmode) - || gpc_reg_operand (operands[1], DFmode))" + && (gpc_reg_operand (operands[0], <MODE>mode) + || gpc_reg_operand (operands[1], <MODE>mode))" "@ std%U0%X0 %1,%0 ld%U1%X1 %0,%1 @@ -8513,6 +8461,33 @@ (define_expand "abstf2_internal" operands[6] = simplify_gen_subreg (DFmode, operands[0], TFmode, lo_word); }") +;; Reload helper functions used by rs6000_secondary_reload. The patterns all +;; must have 3 arguments, and scratch register constraint must be a single +;; constraint. + +;; Reload patterns to support gpr load/store with misaligned mem. +;; and multiple gpr load/store at offset >= 0xfffc +(define_expand "reload_<mode>_store" + [(parallel [(match_operand 0 "memory_operand" "=m") + (match_operand 1 "gpc_reg_operand" "r") + (match_operand:GPR 2 "register_operand" "=&b")])] + "" +{ + rs6000_secondary_reload_gpr (operands[1], operands[0], operands[2], true); + DONE; +}) + +(define_expand "reload_<mode>_load" + [(parallel [(match_operand 0 "gpc_reg_operand" "=r") + (match_operand 1 "memory_operand" "m") + (match_operand:GPR 2 "register_operand" "=b")])] + "" +{ + rs6000_secondary_reload_gpr (operands[0], operands[1], operands[2], false); + DONE; +}) + + ;; Next come the multi-word integer load and store and the load and store ;; multiple insns. Index: gcc/doc/md.texi =================================================================== --- gcc/doc/md.texi (revision 195586) +++ gcc/doc/md.texi (working copy) @@ -2075,6 +2075,9 @@ VSX vector register to hold vector doubl @item wf VSX vector register to hold vector float data +@item wg +If @option{-mmfpgpr} was used, a floating point register + @item wl If the LFIWAX instruction is enabled, a floating point register