--- gcc/config/sparc/sparc.md 2018/04/24 18:10:25 1.1 +++ gcc/config/sparc/sparc.md 2018/04/24 18:15:14 1.1.1.2 @@ -1,5 +1,5 @@ ;;- Machine description for SPARC chip for GNU C compiler -;; Copyright (C) 1987, 1988, 1989, 1992 Free Software Foundation, Inc. +;; Copyright (C) 1987, 1988, 1989, 1992, 1993 Free Software Foundation, Inc. ;; Contributed by Michael Tiemann (tiemann@cygnus.com) ;; This file is part of GNU CC. @@ -772,29 +772,96 @@ ;; Move instructions -(define_expand "movsi" - [(set (match_operand:SI 0 "general_operand" "") - (match_operand:SI 1 "general_operand" ""))] +(define_expand "movqi" + [(set (match_operand:QI 0 "general_operand" "") + (match_operand:QI 1 "general_operand" ""))] "" " { - if (emit_move_sequence (operands, SImode, NULL_RTX)) + if (emit_move_sequence (operands, QImode)) DONE; }") -(define_expand "reload_insi" - [(set (match_operand:SI 0 "register_operand" "=r") - (match_operand:SI 1 "general_operand" "")) - (clobber (match_operand:SI 2 "register_operand" "=&r"))] +(define_insn "" + [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q") + (match_operand:QI 1 "move_operand" "rI,K,Q,rJ"))] + "register_operand (operands[0], QImode) + || register_operand (operands[1], QImode) + || operands[1] == const0_rtx" + "@ + mov %1,%0 + sethi %%hi(%a1),%0 + ldub %1,%0 + stb %r1,%0" + [(set_attr "type" "move,move,load,store") + (set_attr "length" "*,1,*,1")]) + +(define_insn "" + [(set (match_operand:QI 0 "register_operand" "=r") + (subreg:QI (lo_sum:SI (match_operand:QI 1 "register_operand" "r") + (match_operand 2 "immediate_operand" "in")) 0))] + "" + "or %1,%%lo(%a2),%0" + [(set_attr "length" "1")]) + +(define_insn "" + [(set (mem:QI (match_operand:SI 0 "symbolic_operand" "")) + (match_operand:QI 1 "reg_or_0_operand" "rJ")) + (clobber (match_scratch:SI 2 "=&r"))] + "" + "sethi %%hi(%a0),%2\;stb %r1,[%2+%%lo(%a0)]" + [(set_attr "type" "store") + (set_attr "length" "2")]) + +(define_expand "movhi" + [(set (match_operand:HI 0 "general_operand" "") + (match_operand:HI 1 "general_operand" ""))] "" " { - if (emit_move_sequence (operands, SImode, operands[2])) + if (emit_move_sequence (operands, HImode)) DONE; +}") - /* We don't want the clobber emitted, so handle this ourselves. */ - emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1])); - DONE; +(define_insn "" + [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q") + (match_operand:HI 1 "move_operand" "rI,K,Q,rJ"))] + "register_operand (operands[0], HImode) + || register_operand (operands[1], HImode) + || operands[1] == const0_rtx" + "@ + mov %1,%0 + sethi %%hi(%a1),%0 + lduh %1,%0 + sth %r1,%0" + [(set_attr "type" "move,move,load,store") + (set_attr "length" "*,1,*,1")]) + +(define_insn "" + [(set (match_operand:HI 0 "register_operand" "=r") + (lo_sum:HI (match_operand:HI 1 "register_operand" "r") + (match_operand 2 "immediate_operand" "in")))] + "" + "or %1,%%lo(%a2),%0" + [(set_attr "length" "1")]) + +(define_insn "" + [(set (mem:HI (match_operand:SI 0 "symbolic_operand" "")) + (match_operand:HI 1 "reg_or_0_operand" "rJ")) + (clobber (match_scratch:SI 2 "=&r"))] + "" + "sethi %%hi(%a0),%2\;sth %r1,[%2+%%lo(%a0)]" + [(set_attr "type" "store") + (set_attr "length" "2")]) + +(define_expand "movsi" + [(set (match_operand:SI 0 "general_operand" "") + (match_operand:SI 1 "general_operand" ""))] + "" + " +{ + if (emit_move_sequence (operands, SImode)) + DONE; }") ;; We must support both 'r' and 'f' registers here, because combine may @@ -898,23 +965,6 @@ [(set_attr "type" "move") (set_attr "length" "1")]) -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (lo_sum:DI (match_operand:DI 1 "register_operand" "0") - (match_operand:DI 2 "immediate_operand" "in")))] - "" - "* -{ - /* Don't output a 64 bit constant, since we can't trust the assembler to - handle it correctly. */ - if (GET_CODE (operands[2]) == CONST_DOUBLE) - operands[2] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (operands[2])); - return \"or %R1,%%lo(%a2),%R0\"; -}" - ;; Need to set length for this arith insn because operand2 - ;; is not an "arith_operand". - [(set_attr "length" "1")]) - ;; For PIC, symbol_refs are put inside unspec so that the optimizer won't ;; confuse them with real addresses. (define_insn "" @@ -927,6 +977,8 @@ ;; is not an "arith_operand". [(set_attr "length" "1")]) +;; ??? Can the next two be moved above the PIC stuff? + (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (lo_sum:SI (match_operand:SI 1 "register_operand" "r") @@ -946,87 +998,51 @@ [(set_attr "type" "store") (set_attr "length" "2")]) -(define_expand "movhi" - [(set (match_operand:HI 0 "general_operand" "") - (match_operand:HI 1 "general_operand" ""))] +(define_expand "movdi" + [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "") + (match_operand:DI 1 "general_operand" ""))] "" " { - if (emit_move_sequence (operands, HImode, NULL_RTX)) + if (emit_move_sequence (operands, DImode)) DONE; }") (define_insn "" - [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q") - (match_operand:HI 1 "move_operand" "rI,K,Q,rJ"))] - "register_operand (operands[0], HImode) - || register_operand (operands[1], HImode) + [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "=r,Q,r,r,?f,?f,?Q") + (match_operand:DI 1 "general_operand" "r,r,Q,i,f,Q,f"))] + "register_operand (operands[0], DImode) + || register_operand (operands[1], DImode) || operands[1] == const0_rtx" - "@ - mov %1,%0 - sethi %%hi(%a1),%0 - lduh %1,%0 - sth %r1,%0" - [(set_attr "type" "move,move,load,store") - (set_attr "length" "*,1,*,1")]) - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r") - (lo_sum:HI (match_operand:HI 1 "register_operand" "r") - (match_operand 2 "immediate_operand" "in")))] - "" - "or %1,%%lo(%a2),%0" - [(set_attr "length" "1")]) - -(define_insn "" - [(set (mem:HI (match_operand:SI 0 "symbolic_operand" "")) - (match_operand:HI 1 "reg_or_0_operand" "rJ")) - (clobber (match_scratch:SI 2 "=&r"))] - "" - "sethi %%hi(%a0),%2\;sth %r1,[%2+%%lo(%a0)]" - [(set_attr "type" "store") - (set_attr "length" "2")]) - -(define_expand "movqi" - [(set (match_operand:QI 0 "general_operand" "") - (match_operand:QI 1 "general_operand" ""))] - "" - " + "* { - if (emit_move_sequence (operands, QImode, NULL_RTX)) - DONE; -}") - -(define_insn "" - [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q") - (match_operand:QI 1 "move_operand" "rI,K,Q,rJ"))] - "register_operand (operands[0], QImode) - || register_operand (operands[1], QImode) - || operands[1] == const0_rtx" - "@ - mov %1,%0 - sethi %%hi(%a1),%0 - ldub %1,%0 - stb %r1,%0" - [(set_attr "type" "move,move,load,store") - (set_attr "length" "*,1,*,1")]) + if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) + return output_fp_move_double (operands); + return output_move_double (operands); +}" + [(set_attr "type" "move,store,load,multi,fp,fpload,fpstore") + (set_attr "length" "2,3,3,3,2,3,3")]) (define_insn "" - [(set (match_operand:QI 0 "register_operand" "=r") - (subreg:QI (lo_sum:SI (match_operand:QI 1 "register_operand" "r") - (match_operand 2 "immediate_operand" "in")) 0))] + [(set (match_operand:DI 0 "register_operand" "=r") + (lo_sum:DI (match_operand:DI 1 "register_operand" "0") + (match_operand:DI 2 "immediate_operand" "in")))] "" - "or %1,%%lo(%a2),%0" + "* +{ + /* Don't output a 64 bit constant, since we can't trust the assembler to + handle it correctly. */ + if (GET_CODE (operands[2]) == CONST_DOUBLE) + operands[2] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (operands[2])); + return \"or %R1,%%lo(%a2),%R0\"; +}" + ;; Need to set length for this arith insn because operand2 + ;; is not an "arith_operand". [(set_attr "length" "1")]) -(define_insn "" - [(set (mem:QI (match_operand:SI 0 "symbolic_operand" "")) - (match_operand:QI 1 "reg_or_0_operand" "rJ")) - (clobber (match_scratch:SI 2 "=&r"))] - "" - "sethi %%hi(%a0),%2\;stb %r1,[%2+%%lo(%a0)]" - [(set_attr "type" "store") - (set_attr "length" "2")]) +;; ??? There's no symbolic (set (mem:DI ...) ...). + +;; Block move insns. ;; ??? We get better code without it. See output_block_move in sparc.c. @@ -1077,91 +1093,78 @@ ;; Floating point move insns -;; This pattern forces (set (reg:TF ...) (const_double ...)) +;; This pattern forces (set (reg:SF ...) (const_double ...)) ;; to be reloaded by putting the constant into memory. -;; It must come before the more general movtf pattern. +;; It must come before the more general movsf pattern. (define_insn "" - [(set (match_operand:TF 0 "general_operand" "=?r,f,o") - (match_operand:TF 1 "" "?E,m,G"))] + [(set (match_operand:SF 0 "general_operand" "=?r,f,m") + (match_operand:SF 1 "" "?E,m,G"))] "TARGET_FPU && GET_CODE (operands[1]) == CONST_DOUBLE" "* { switch (which_alternative) { case 0: - return output_move_quad (operands); + return singlemove_string (operands); case 1: - return output_fp_move_quad (operands); + return \"ld %1,%0\"; case 2: - operands[1] = adj_offsettable_operand (operands[0], 4); - operands[2] = adj_offsettable_operand (operands[0], 8); - operands[3] = adj_offsettable_operand (operands[0], 12); - return \"st %%g0,%0\;st %%g0,%1\;st %%g0,%2\;st %%g0,%3\"; + return \"st %%g0,%0\"; } }" [(set_attr "type" "load,fpload,store") - (set_attr "length" "5,5,5")]) + (set_attr "length" "2,1,1")]) -(define_expand "movtf" - [(set (match_operand:TF 0 "general_operand" "") - (match_operand:TF 1 "general_operand" ""))] +(define_expand "movsf" + [(set (match_operand:SF 0 "general_operand" "") + (match_operand:SF 1 "general_operand" ""))] "" " { - if (emit_move_sequence (operands, TFmode, NULL_RTX)) + if (emit_move_sequence (operands, SFmode)) DONE; }") (define_insn "" - [(set (match_operand:TF 0 "reg_or_nonsymb_mem_operand" "=f,r,Q,Q,f,&r") - (match_operand:TF 1 "reg_or_nonsymb_mem_operand" "f,r,f,r,Q,Q"))] + [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" "=f,r,f,r,Q,Q") + (match_operand:SF 1 "reg_or_nonsymb_mem_operand" "f,r,Q,Q,f,r"))] "TARGET_FPU - && (register_operand (operands[0], TFmode) - || register_operand (operands[1], TFmode))" - "* -{ - if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) - return output_fp_move_quad (operands); - return output_move_quad (operands); -}" - [(set_attr "type" "fp,move,fpstore,store,fpload,load") - (set_attr "length" "4,4,5,5,5,5")]) + && (register_operand (operands[0], SFmode) + || register_operand (operands[1], SFmode))" + "@ + fmovs %1,%0 + mov %1,%0 + ld %1,%0 + ld %1,%0 + st %r1,%0 + st %r1,%0" + [(set_attr "type" "fp,move,fpload,load,fpstore,store")]) ;; Exactly the same as above, except that all `f' cases are deleted. ;; This is necessary to prevent reload from ever trying to use a `f' reg ;; when -mno-fpu. (define_insn "" - [(set (match_operand:TF 0 "reg_or_nonsymb_mem_operand" "=r,Q,&r") - (match_operand:TF 1 "reg_or_nonsymb_mem_operand" "r,r,Q"))] + [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" "=r,r,Q") + (match_operand:SF 1 "reg_or_nonsymb_mem_operand" "r,Q,r"))] "! TARGET_FPU - && (register_operand (operands[0], TFmode) - || register_operand (operands[1], TFmode))" - "* -{ - if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) - return output_fp_move_quad (operands); - return output_move_quad (operands); -}" - [(set_attr "type" "move,store,load") - (set_attr "length" "4,5,5")]) + && (register_operand (operands[0], SFmode) + || register_operand (operands[1], SFmode))" + "@ + mov %1,%0 + ld %1,%0 + st %r1,%0" + [(set_attr "type" "move,load,store")]) (define_insn "" - [(set (mem:TF (match_operand:SI 0 "symbolic_operand" "i,i")) - (match_operand:TF 1 "reg_or_0_operand" "rf,G")) - (clobber (match_scratch:SI 2 "=&r,&r"))] + [(set (mem:SF (match_operand:SI 0 "symbolic_operand" "i")) + (match_operand:SF 1 "reg_or_0_operand" "rfG")) + (clobber (match_scratch:SI 2 "=&r"))] "" - "* -{ - output_asm_insn (\"sethi %%hi(%a0),%2\", operands); - if (which_alternative == 0) - return \"std %1,[%2+%%lo(%a0)]\;std %S1,[%2+%%lo(%a0+8)]\"; - else - return \"st %%g0,[%2+%%lo(%a0)]\;st %%g0,[%2+%%lo(%a0+4)]\; st %%g0,[%2+%%lo(%a0+8)]\;st %%g0,[%2+%%lo(%a0+12)]\"; -}" + "sethi %%hi(%a0),%2\;st %r1,[%2+%%lo(%a0)]" [(set_attr "type" "store") - (set_attr "length" "5")]) - + (set_attr "length" "2")]) + ;; This pattern forces (set (reg:DF ...) (const_double ...)) ;; to be reloaded by putting the constant into memory. ;; It must come before the more general movdf pattern. @@ -1192,12 +1195,12 @@ "" " { - if (emit_move_sequence (operands, DFmode, NULL_RTX)) + if (emit_move_sequence (operands, DFmode)) DONE; }") (define_insn "" - [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" "=T,U,f,r,Q,Q,f,&r") + [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" "=T,U,f,r,Q,Q,f,r") (match_operand:DF 1 "reg_or_nonsymb_mem_operand" "U,T,f,r,f,r,Q,Q"))] "TARGET_FPU && (register_operand (operands[0], DFmode) @@ -1252,107 +1255,91 @@ }" [(set_attr "type" "store") (set_attr "length" "3")]) - -;; Double-word move insns. - -(define_expand "movdi" - [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "") - (match_operand:DI 1 "general_operand" ""))] - "" - " -{ - if (emit_move_sequence (operands, DImode, NULL_RTX)) - DONE; -}") -(define_insn "" - [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "=r,Q,&r,&r,?f,?f,?Q") - (match_operand:DI 1 "general_operand" "r,r,Q,i,f,Q,f"))] - "register_operand (operands[0], DImode) - || register_operand (operands[1], DImode) - || operands[1] == const0_rtx" - "* -{ - if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) - return output_fp_move_double (operands); - return output_move_double (operands); -}" - [(set_attr "type" "move,store,load,multi,fp,fpload,fpstore") - (set_attr "length" "2,3,3,3,2,3,3")]) - -;; Floating-point move insns. - -;; This pattern forces (set (reg:SF ...) (const_double ...)) +;; This pattern forces (set (reg:TF ...) (const_double ...)) ;; to be reloaded by putting the constant into memory. -;; It must come before the more general movsf pattern. +;; It must come before the more general movtf pattern. (define_insn "" - [(set (match_operand:SF 0 "general_operand" "=?r,f,m") - (match_operand:SF 1 "" "?E,m,G"))] + [(set (match_operand:TF 0 "general_operand" "=?r,f,o") + (match_operand:TF 1 "" "?E,m,G"))] "TARGET_FPU && GET_CODE (operands[1]) == CONST_DOUBLE" "* { switch (which_alternative) { case 0: - return singlemove_string (operands); + return output_move_quad (operands); case 1: - return \"ld %1,%0\"; + return output_fp_move_quad (operands); case 2: - return \"st %%g0,%0\"; + operands[1] = adj_offsettable_operand (operands[0], 4); + operands[2] = adj_offsettable_operand (operands[0], 8); + operands[3] = adj_offsettable_operand (operands[0], 12); + return \"st %%g0,%0\;st %%g0,%1\;st %%g0,%2\;st %%g0,%3\"; } }" [(set_attr "type" "load,fpload,store") - (set_attr "length" "2,1,1")]) + (set_attr "length" "5,5,5")]) -(define_expand "movsf" - [(set (match_operand:SF 0 "general_operand" "") - (match_operand:SF 1 "general_operand" ""))] +(define_expand "movtf" + [(set (match_operand:TF 0 "general_operand" "") + (match_operand:TF 1 "general_operand" ""))] "" " { - if (emit_move_sequence (operands, SFmode, NULL_RTX)) + if (emit_move_sequence (operands, TFmode)) DONE; }") (define_insn "" - [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" "=f,r,f,r,Q,Q") - (match_operand:SF 1 "reg_or_nonsymb_mem_operand" "f,r,Q,Q,f,r"))] + [(set (match_operand:TF 0 "reg_or_nonsymb_mem_operand" "=f,r,Q,Q,f,&r") + (match_operand:TF 1 "reg_or_nonsymb_mem_operand" "f,r,f,r,Q,Q"))] "TARGET_FPU - && (register_operand (operands[0], SFmode) - || register_operand (operands[1], SFmode))" - "@ - fmovs %1,%0 - mov %1,%0 - ld %1,%0 - ld %1,%0 - st %r1,%0 - st %r1,%0" - [(set_attr "type" "fp,move,fpload,load,fpstore,store")]) + && (register_operand (operands[0], TFmode) + || register_operand (operands[1], TFmode))" + "* +{ + if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) + return output_fp_move_quad (operands); + return output_move_quad (operands); +}" + [(set_attr "type" "fp,move,fpstore,store,fpload,load") + (set_attr "length" "4,4,5,5,5,5")]) ;; Exactly the same as above, except that all `f' cases are deleted. ;; This is necessary to prevent reload from ever trying to use a `f' reg ;; when -mno-fpu. (define_insn "" - [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" "=r,r,Q") - (match_operand:SF 1 "reg_or_nonsymb_mem_operand" "r,Q,r"))] + [(set (match_operand:TF 0 "reg_or_nonsymb_mem_operand" "=r,Q,&r") + (match_operand:TF 1 "reg_or_nonsymb_mem_operand" "r,r,Q"))] "! TARGET_FPU - && (register_operand (operands[0], SFmode) - || register_operand (operands[1], SFmode))" - "@ - mov %1,%0 - ld %1,%0 - st %r1,%0" - [(set_attr "type" "move,load,store")]) + && (register_operand (operands[0], TFmode) + || register_operand (operands[1], TFmode))" + "* +{ + if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) + return output_fp_move_quad (operands); + return output_move_quad (operands); +}" + [(set_attr "type" "move,store,load") + (set_attr "length" "4,5,5")]) (define_insn "" - [(set (mem:SF (match_operand:SI 0 "symbolic_operand" "i")) - (match_operand:SF 1 "reg_or_0_operand" "rfG")) - (clobber (match_scratch:SI 2 "=&r"))] + [(set (mem:TF (match_operand:SI 0 "symbolic_operand" "i,i")) + (match_operand:TF 1 "reg_or_0_operand" "rf,G")) + (clobber (match_scratch:SI 2 "=&r,&r"))] "" - "sethi %%hi(%a0),%2\;st %r1,[%2+%%lo(%a0)]" + "* +{ + output_asm_insn (\"sethi %%hi(%a0),%2\", operands); + if (which_alternative == 0) + return \"std %1,[%2+%%lo(%a0)]\;std %S1,[%2+%%lo(%a0+8)]\"; + else + return \"st %%g0,[%2+%%lo(%a0)]\;st %%g0,[%2+%%lo(%a0+4)]\; st %%g0,[%2+%%lo(%a0+8)]\;st %%g0,[%2+%%lo(%a0+12)]\"; +}" [(set_attr "type" "store") - (set_attr "length" "2")]) + (set_attr "length" "5")]) ;;- zero extension instructions @@ -1368,11 +1355,16 @@ { rtx temp = gen_reg_rtx (SImode); rtx shift_16 = gen_rtx (CONST_INT, VOIDmode, 16); + int op1_subword = 0; if (GET_CODE (operand1) == SUBREG) - operand1 = XEXP (operand1, 0); + { + op1_subword = SUBREG_WORD (operand1); + operand1 = XEXP (operand1, 0); + } - emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, 0), + emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, + op1_subword), shift_16)); emit_insn (gen_lshrsi3 (operand0, temp, shift_16)); DONE; @@ -1469,11 +1461,16 @@ { rtx temp = gen_reg_rtx (SImode); rtx shift_16 = gen_rtx (CONST_INT, VOIDmode, 16); + int op1_subword = 0; if (GET_CODE (operand1) == SUBREG) - operand1 = XEXP (operand1, 0); + { + op1_subword = SUBREG_WORD (operand1); + operand1 = XEXP (operand1, 0); + } - emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, 0), + emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, + op1_subword), shift_16)); emit_insn (gen_ashrsi3 (operand0, temp, shift_16)); DONE; @@ -1494,15 +1491,24 @@ { rtx temp = gen_reg_rtx (SImode); rtx shift_24 = gen_rtx (CONST_INT, VOIDmode, 24); + int op1_subword = 0; + int op0_subword = 0; if (GET_CODE (operand1) == SUBREG) - operand1 = XEXP (operand1, 0); + { + op1_subword = SUBREG_WORD (operand1); + operand1 = XEXP (operand1, 0); + } if (GET_CODE (operand0) == SUBREG) - operand0 = XEXP (operand0, 0); - emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, 0), + { + op0_subword = SUBREG_WORD (operand0); + operand0 = XEXP (operand0, 0); + } + emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, + op1_subword), shift_24)); if (GET_MODE (operand0) != SImode) - operand0 = gen_rtx (SUBREG, SImode, operand0, 0); + operand0 = gen_rtx (SUBREG, SImode, operand0, op0_subword); emit_insn (gen_ashrsi3 (operand0, temp, shift_24)); DONE; }") @@ -1522,10 +1528,16 @@ { rtx temp = gen_reg_rtx (SImode); rtx shift_24 = gen_rtx (CONST_INT, VOIDmode, 24); + int op1_subword = 0; if (GET_CODE (operand1) == SUBREG) - operand1 = XEXP (operand1, 0); - emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, 0), + { + op1_subword = SUBREG_WORD (operand1); + operand1 = XEXP (operand1, 0); + } + + emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, + op1_subword), shift_24)); emit_insn (gen_ashrsi3 (operand0, temp, shift_24)); DONE; @@ -1828,7 +1840,7 @@ (define_expand "umulsidi3" [(set (match_operand:DI 0 "register_operand" "") (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "")) - (zero_extend:DI (match_operand:SI 2 "arith_operand" ""))))] + (zero_extend:DI (match_operand:SI 2 "uns_arith_operand" ""))))] "TARGET_V8 || TARGET_SPARCLITE" " { @@ -1852,7 +1864,7 @@ (define_insn "const_umulsidi3" [(set (match_operand:DI 0 "register_operand" "=r") (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) - (match_operand:SI 2 "small_int" "I")))] + (match_operand:SI 2 "uns_small_int" "")))] "TARGET_V8 || TARGET_SPARCLITE" "umul %1,%2,%R0\;rd %%y,%0" [(set_attr "length" "2")]) @@ -1903,8 +1915,8 @@ "TARGET_V8" "wr %%g0,%%g0,%%y\;nop\;nop\;nop\;udivcc %1,%2,%0" [(set_attr "length" "5")]) - -;;- and instructions + +;;- Boolean instructions ;; We define DImode `and` so with DImode `not` we can get ;; DImode `andn`. Other combinations are possible. @@ -2510,136 +2522,66 @@ ;;- arithmetic shift instructions -;; We can trivially handle shifting the constant 1 by 64 bits. -;; For other shifts we use the library routine. -;; ??? Questionable, we can do better than this can't we? -(define_expand "ashldi3" - [(parallel [(set (match_operand:DI 0 "register_operand" "") - (ashift:DI (match_operand:DI 1 "const_double_operand" "") - (match_operand:SI 2 "register_operand" ""))) - (clobber (reg:SI 0))])] - "" - " -{ - if (GET_CODE (operands[1]) == CONST_DOUBLE - && CONST_DOUBLE_HIGH (operands[1]) == 0 - && CONST_DOUBLE_LOW (operands[1]) == 1) - operands[1] = const1_rtx; - else if (operands[1] != const1_rtx) - FAIL; -}") - -;; ??? Questionable, we can do better than this can't we? -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=&r") - (ashift:DI (const_int 1) - (match_operand:SI 1 "register_operand" "r"))) - (clobber (reg:SI 0))] - "" - "subcc %1,32,%%g0\;addx %%g0,0,%R0\;xor %R0,1,%0\;sll %R0,%1,%R0\;sll %0,%1,%0" - [(set_attr "type" "multi") - (set_attr "length" "5")]) - (define_insn "ashlsi3" [(set (match_operand:SI 0 "register_operand" "=r") (ashift:SI (match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "arith_operand" "rI")))] "" - "sll %1,%2,%0") - -(define_expand "lshldi3" - [(parallel [(set (match_operand:DI 0 "register_operand" "") - (lshift:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "const_int_operand" ""))) - (clobber (match_scratch:SI 3 ""))])] - "" - " + "* { - if (GET_CODE (operands[2]) != CONST_INT) - FAIL; + if (GET_CODE (operands[2]) == CONST_INT + && (unsigned) INTVAL (operands[2]) > 31) + operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); + + return \"sll %1,%2,%0\"; }") (define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (lshift:DI (match_operand:DI 1 "register_operand" "r") - (match_operand:DI 2 "const_int_operand" "I"))) - (clobber (match_scratch:SI 3 "=r"))] - "INTVAL (operands[2]) < 32" - "* -{ - operands[4] = GEN_INT (32 - INTVAL (operands[2])); - return \"srl %R1,%4,%3\;sll %R1,%2,%R0\;sll %1,%2,%0\;or %3,%0,%0\"; -}" - [(set_attr "type" "multi") - (set_attr "length" "4")]) + [(set (reg:CC_NOOV 0) + (compare:CC_NOOV (ashift:SI (match_operand:SI 0 "register_operand" "r") + (const_int 1)) + (const_int 0)))] + "" + "addcc %0,%0,%%g0" + [(set_attr "type" "compare")]) (define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (lshift:DI (match_operand:DI 1 "register_operand" "r") - (match_operand:DI 2 "const_int_operand" "I"))) - (clobber (match_scratch:SI 3 "=X"))] - "INTVAL (operands[2]) >= 32" - "* -{ - operands[4] = GEN_INT (INTVAL (operands[2]) - 32); - return \"sll %R1,%4,%0\;mov %%g0,%R0\"; -}" - [(set_attr "type" "multi") - (set_attr "length" "2")]) + [(set (reg:CC_NOOV 0) + (compare:CC_NOOV (ashift:SI (match_operand:SI 1 "register_operand" "r") + (const_int 1)) + (const_int 0))) + (set (match_operand:SI 0 "register_operand" "=r") + (ashift:SI (match_dup 1) (const_int 1)))] + "" + "addcc %1,%1,%0") (define_insn "ashrsi3" [(set (match_operand:SI 0 "register_operand" "=r") (ashiftrt:SI (match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "arith_operand" "rI")))] "" - "sra %1,%2,%0") + "* +{ + if (GET_CODE (operands[2]) == CONST_INT + && (unsigned) INTVAL (operands[2]) > 31) + operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); + + return \"sra %1,%2,%0\"; +}") (define_insn "lshrsi3" [(set (match_operand:SI 0 "register_operand" "=r") (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "arith_operand" "rI")))] "" - "srl %1,%2,%0") - -(define_expand "lshrdi3" - [(parallel [(set (match_operand:DI 0 "register_operand" "") - (lshiftrt:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "const_int_operand" ""))) - (clobber (match_scratch:SI 3 ""))])] - "" - " -{ - if (GET_CODE (operands[2]) != CONST_INT) - FAIL; -}") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (lshiftrt:DI (match_operand:DI 1 "register_operand" "r") - (match_operand:DI 2 "const_int_operand" "I"))) - (clobber (match_scratch:SI 3 "=r"))] - "INTVAL (operands[2]) < 32" "* { - operands[4] = GEN_INT (32 - INTVAL (operands[2])); - return \"sll %1,%4,%3\;srl %1,%2,%0\;srl %R1,%2,%R0\;or %3,%R0,%R0\"; -}" - [(set_attr "type" "multi") - (set_attr "length" "4")]) + if (GET_CODE (operands[2]) == CONST_INT + && (unsigned) INTVAL (operands[2]) > 31) + operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (lshiftrt:DI (match_operand:DI 1 "register_operand" "r") - (match_operand:DI 2 "const_int_operand" "I"))) - (clobber (match_scratch:SI 3 "=X"))] - "INTVAL (operands[2]) >= 32" - "* -{ - operands[4] = GEN_INT (INTVAL (operands[2]) - 32); - return \"srl %1,%4,%R0\;mov %%g0,%0\"; -}" - [(set_attr "type" "multi") - (set_attr "length" "2")]) + return \"srl %1,%2,%0\"; +}") ;; Unconditional and other jump instructions ;; On the Sparc, by setting the annul bit on an unconditional branch, the @@ -2775,8 +2717,23 @@ DONE; }") +;; We can't use the same pattern for these two insns, because then registers +;; in the address may not be properly reloaded. + +(define_insn "" + [(call (mem:SI (match_operand:SI 0 "address_operand" "p")) + (match_operand 1 "" "")) + (clobber (reg:SI 15))] + ;;- Do not use operand 1 for most machines. + "" + "* +{ + return \"call %a0,%1%#\"; +}" + [(set_attr "type" "call")]) + (define_insn "" - [(call (mem:SI (match_operand:SI 0 "call_operand_address" "S,r")) + [(call (mem:SI (match_operand:SI 0 "immediate_operand" "i")) (match_operand 1 "" "")) (clobber (reg:SI 15))] ;;- Do not use operand 1 for most machines. @@ -2789,7 +2746,21 @@ ;; This is a call that wants a structure value. (define_insn "" - [(call (mem:SI (match_operand:SI 0 "call_operand_address" "S,r")) + [(call (mem:SI (match_operand:SI 0 "address_operand" "p")) + (match_operand 1 "" "")) + (match_operand 2 "immediate_operand" "") + (clobber (reg:SI 15))] + ;;- Do not use operand 1 for most machines. + "GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) > 0" + "* +{ + return \"call %a0,%1\;nop\;unimp %2\"; +}" + [(set_attr "type" "call_no_delay_slot")]) + +;; This is a call that wants a structure value. +(define_insn "" + [(call (mem:SI (match_operand:SI 0 "immediate_operand" "i")) (match_operand 1 "" "")) (match_operand 2 "immediate_operand" "") (clobber (reg:SI 15))] @@ -2835,7 +2806,20 @@ (define_insn "" [(set (match_operand 0 "" "=rf") - (call (mem:SI (match_operand:SI 1 "call_operand_address" "rS")) + (call (mem:SI (match_operand:SI 1 "address_operand" "p")) + (match_operand 2 "" ""))) + (clobber (reg:SI 15))] + ;;- Do not use operand 2 for most machines. + "" + "* +{ + return \"call %a1,%2%#\"; +}" + [(set_attr "type" "call")]) + +(define_insn "" + [(set (match_operand 0 "" "=rf") + (call (mem:SI (match_operand:SI 1 "immediate_operand" "i")) (match_operand 2 "" ""))) (clobber (reg:SI 15))] ;;- Do not use operand 2 for most machines. @@ -2862,7 +2846,24 @@ ;; returns a structure value and expects to skip an unimp instruction. (define_insn "" - [(call (mem:SI (match_operand:SI 0 "call_operand_address" "rS")) + [(call (mem:SI (match_operand:SI 0 "address_operand" "p")) + (const_int 0)) + (match_operand:DI 1 "memory_operand" "o") + (match_operand 2 "" "") + (clobber (reg:SI 15))] + "" + "* +{ + operands[2] = adj_offsettable_operand (operands[1], 8); + return \"call %a0,0\;nop\;nop\;std %%o0,%1\;std %%f0,%2\"; +}" + [(set_attr "type" "multi")]) + +;; Make a call followed by two nops in case the function being called +;; returns a structure value and expects to skip an unimp instruction. + +(define_insn "" + [(call (mem:SI (match_operand:SI 0 "immediate_operand" "i")) (const_int 0)) (match_operand:DI 1 "memory_operand" "o") (match_operand 2 "" "") @@ -2871,7 +2872,7 @@ "* { operands[2] = adj_offsettable_operand (operands[1], 8); - return \"call %a0,0\;nop\;nop\;std %%o0,%1\;st %%f0,%2\"; + return \"call %a0,0\;nop\;nop\;std %%o0,%1\;std %%f0,%2\"; }" [(set_attr "type" "multi")]) @@ -2991,6 +2992,14 @@ "jmp %%o0+0\;restore" [(set_attr "type" "misc") (set_attr "length" "2")]) + +;; Special pattern for the FLUSH instruction. + +(define_insn "flush" + [(unspec_volatile [(match_operand 0 "" "")] 2)] + "" + "iflush %a0" + [(set_attr "type" "misc")]) ;; find first set. @@ -3034,7 +3043,7 @@ " { operands[1] = legitimize_pic_address (operands[1], GET_MODE (operands[0]), - operands[3], 0); + operands[3]); }") (define_split @@ -3047,7 +3056,7 @@ " { operands[2] = legitimize_pic_address (operands[2], GET_MODE (operands[1]), - operands[0], 0); + operands[0]); }") ;; Sign- and Zero-extend operations can have symbolic memory operands. @@ -3063,7 +3072,7 @@ " { operands[3] = legitimize_pic_address (operands[3], GET_MODE (operands[2]), - operands[0], 0); + operands[0]); }") (define_split @@ -3087,7 +3096,7 @@ [(set (match_dup 0) (match_dup 1))] " { - operands[1] = legitimize_pic_address (operands[1], Pmode, operands[0], 0); + operands[1] = legitimize_pic_address (operands[1], Pmode, operands[0]); }") ;; These split sne/seq insns. The forms of the resulting insns are @@ -3476,7 +3485,7 @@ (define_peephole [(parallel [(set (match_operand 0 "" "") - (call (mem:SI (match_operand:SI 1 "call_operand_address" "S,r")) + (call (mem:SI (match_operand:SI 1 "call_operand_address" "pi")) (match_operand 2 "" ""))) (clobber (reg:SI 15))]) (set (pc) (label_ref (match_operand 3 "" "")))] @@ -3487,7 +3496,7 @@ }") (define_peephole - [(parallel [(call (mem:SI (match_operand:SI 0 "call_operand_address" "S,r")) + [(parallel [(call (mem:SI (match_operand:SI 0 "call_operand_address" "pi")) (match_operand 1 "" "")) (clobber (reg:SI 15))]) (set (pc) (label_ref (match_operand 2 "" "")))]