--- gcc/config/i386/i386.md 2018/04/24 18:17:15 1.1.1.2 +++ gcc/config/i386/i386.md 2018/04/24 18:23:23 1.1.1.3 @@ -1,5 +1,5 @@ -;; GCC machine description for Intel 80386. -;; Copyright (C) 1988 Free Software Foundation, Inc. +;; GCC machine description for Intel X86. +;; Copyright (C) 1988, 1994 Free Software Foundation, Inc. ;; Mostly by William Schelter. ;; This file is part of GNU CC. @@ -157,7 +157,7 @@ if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) output_asm_insn (AS1 (fstp,%y0), operands); - return (char *) output_fp_cc0_set (insn); + return output_fp_cc0_set (insn); }") ;; Don't generate tstsf if generating IEEE code, since the `ftst' opcode @@ -190,7 +190,7 @@ if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) output_asm_insn (AS1 (fstp,%y0), operands); - return (char *) output_fp_cc0_set (insn); + return output_fp_cc0_set (insn); }") ;; Don't generate tstdf if generating IEEE code, since the `ftst' opcode @@ -223,7 +223,7 @@ if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) output_asm_insn (AS1 (fstp,%y0), operands); - return (char *) output_fp_cc0_set (insn); + return output_fp_cc0_set (insn); }") ;; Don't generate tstdf if generating IEEE code, since the `ftst' opcode @@ -349,7 +349,7 @@ (clobber (match_scratch:HI 3 "=a"))] "TARGET_80387 && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" - "* return (char *) output_float_compare (insn, operands);") + "* return output_float_compare (insn, operands);") (define_insn "" [(set (cc0) @@ -359,7 +359,7 @@ (match_operand:SI 1 "nonimmediate_operand" "rm"))])) (clobber (match_scratch:HI 3 "=a"))] "TARGET_80387" - "* return (char *) output_float_compare (insn, operands);") + "* return output_float_compare (insn, operands);") (define_insn "" [(set (cc0) @@ -369,7 +369,7 @@ (match_operand:XF 1 "register_operand" "f")])) (clobber (match_scratch:HI 3 "=a"))] "TARGET_80387" - "* return (char *) output_float_compare (insn, operands);") + "* return output_float_compare (insn, operands);") (define_insn "" [(set (cc0) @@ -379,7 +379,7 @@ (match_operand:DF 1 "nonimmediate_operand" "fm"))])) (clobber (match_scratch:HI 3 "=a"))] "TARGET_80387" - "* return (char *) output_float_compare (insn, operands);") + "* return output_float_compare (insn, operands);") (define_insn "" [(set (cc0) @@ -389,7 +389,7 @@ (match_operand:SF 1 "nonimmediate_operand" "fm"))])) (clobber (match_scratch:HI 3 "=a"))] "TARGET_80387" - "* return (char *) output_float_compare (insn, operands);") + "* return output_float_compare (insn, operands);") (define_insn "" [(set (cc0) @@ -397,7 +397,7 @@ (match_operand:XF 1 "register_operand" "f"))) (clobber (match_scratch:HI 2 "=a"))] "TARGET_80387" - "* return (char *) output_float_compare (insn, operands);") + "* return output_float_compare (insn, operands);") (define_insn "" [(set (cc0) @@ -407,7 +407,7 @@ (clobber (match_scratch:HI 3 "=a,a"))] "TARGET_80387 && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" - "* return (char *) output_float_compare (insn, operands);") + "* return output_float_compare (insn, operands);") (define_insn "" [(set (cc0) @@ -417,7 +417,7 @@ (match_operand:SI 1 "nonimmediate_operand" "rm"))])) (clobber (match_scratch:HI 3 "=a"))] "TARGET_80387" - "* return (char *) output_float_compare (insn, operands);") + "* return output_float_compare (insn, operands);") (define_insn "" [(set (cc0) @@ -427,7 +427,7 @@ (match_operand:DF 1 "register_operand" "f")])) (clobber (match_scratch:HI 3 "=a"))] "TARGET_80387" - "* return (char *) output_float_compare (insn, operands);") + "* return output_float_compare (insn, operands);") (define_insn "" [(set (cc0) @@ -437,7 +437,7 @@ (match_operand:SF 1 "nonimmediate_operand" "fm"))])) (clobber (match_scratch:HI 3 "=a"))] "TARGET_80387" - "* return (char *) output_float_compare (insn, operands);") + "* return output_float_compare (insn, operands);") (define_insn "" [(set (cc0) @@ -447,7 +447,7 @@ (match_operand:DF 1 "register_operand" "f")])) (clobber (match_scratch:HI 3 "=a"))] "TARGET_80387" - "* return (char *) output_float_compare (insn, operands);") + "* return output_float_compare (insn, operands);") (define_insn "" [(set (cc0) @@ -455,7 +455,7 @@ (match_operand:DF 1 "register_operand" "f"))) (clobber (match_scratch:HI 2 "=a"))] "TARGET_80387" - "* return (char *) output_float_compare (insn, operands);") + "* return output_float_compare (insn, operands);") ;; These two insns will never be generated by combine due to the mode of ;; the COMPARE. @@ -466,7 +466,7 @@ ; (match_operand:SF 1 "register_operand" "f")))) ; (clobber (match_scratch:HI 2 "=a"))] ; "TARGET_80387" -; "* return (char *) output_float_compare (insn, operands);") +; "* return output_float_compare (insn, operands);") ; ;(define_insn "" ; [(set (cc0) @@ -475,7 +475,7 @@ ; (match_operand:DF 1 "register_operand" "f"))) ; (clobber (match_scratch:HI 2 "=a"))] ; "TARGET_80387" -; "* return (char *) output_float_compare (insn, operands);") +; "* return output_float_compare (insn, operands);") (define_insn "cmpsf_cc_1" [(set (cc0) @@ -485,7 +485,7 @@ (clobber (match_scratch:HI 3 "=a,a"))] "TARGET_80387 && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" - "* return (char *) output_float_compare (insn, operands);") + "* return output_float_compare (insn, operands);") (define_insn "" [(set (cc0) @@ -495,7 +495,7 @@ (match_operand:SI 1 "nonimmediate_operand" "rm"))])) (clobber (match_scratch:HI 3 "=a"))] "TARGET_80387" - "* return (char *) output_float_compare (insn, operands);") + "* return output_float_compare (insn, operands);") (define_insn "" [(set (cc0) @@ -505,7 +505,7 @@ (match_operand:SF 1 "register_operand" "f")])) (clobber (match_scratch:HI 3 "=a"))] "TARGET_80387" - "* return (char *) output_float_compare (insn, operands);") + "* return output_float_compare (insn, operands);") (define_insn "" [(set (cc0) @@ -513,7 +513,7 @@ (match_operand:SF 1 "register_operand" "f"))) (clobber (match_scratch:HI 2 "=a"))] "TARGET_80387" - "* return (char *) output_float_compare (insn, operands);") + "* return output_float_compare (insn, operands);") (define_expand "cmpxf" [(set (cc0) @@ -740,7 +740,7 @@ (define_insn "" [(set (match_operand:SI 0 "push_operand" "=<") (match_operand:SI 1 "general_operand" "g"))] - "! TARGET_486" + "TARGET_386" "push%L0 %1") ;; On a 486, it is faster to move MEM to a REG and then push, rather than @@ -748,8 +748,14 @@ (define_insn "" [(set (match_operand:SI 0 "push_operand" "=<") + (match_operand:SI 1 "nonmemory_operand" "ri"))] + "!TARGET_386 && TARGET_MOVE" + "push%L0 %1") + +(define_insn "" + [(set (match_operand:SI 0 "push_operand" "=<") (match_operand:SI 1 "general_operand" "ri"))] - "TARGET_486" + "!TARGET_386 && !TARGET_MOVE" "push%L0 %1") ;; General case of fullword move. @@ -767,6 +773,15 @@ if (flag_pic && SYMBOLIC_CONST (operands[1])) emit_pic_move (operands, SImode); + + /* Don't generate memory->memory moves, go through a register */ + else if (TARGET_MOVE + && (reload_in_progress | reload_completed) == 0 + && GET_CODE (operands[0]) == MEM + && GET_CODE (operands[1]) == MEM) + { + operands[1] = force_reg (SImode, operands[1]); + } }") ;; On i486, incl reg is faster than movl $1,reg. @@ -774,7 +789,7 @@ (define_insn "" [(set (match_operand:SI 0 "general_operand" "=g,r") (match_operand:SI 1 "general_operand" "ri,m"))] - "" + "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" "* { rtx link; @@ -793,21 +808,52 @@ /* Fastest way to change a 0 to a 1. */ return AS1 (inc%L0,%0); + if (flag_pic && SYMBOLIC_CONST (operands[1])) + return AS2 (lea%L0,%a1,%0); + return AS2 (mov%L0,%1,%0); }") (define_insn "" [(set (match_operand:HI 0 "push_operand" "=<") (match_operand:HI 1 "general_operand" "g"))] - "" + "TARGET_386" + "push%W0 %1") + +(define_insn "" + [(set (match_operand:HI 0 "push_operand" "=<") + (match_operand:HI 1 "nonmemory_operand" "ri"))] + "!TARGET_386 && TARGET_MOVE" + "push%W0 %1") + +(define_insn "" + [(set (match_operand:HI 0 "push_operand" "=<") + (match_operand:HI 1 "general_operand" "ri"))] + "!TARGET_386 && !TARGET_MOVE" "push%W0 %1") ;; On i486, an incl and movl are both faster than incw and movw. -(define_insn "movhi" +(define_expand "movhi" + [(set (match_operand:HI 0 "general_operand" "") + (match_operand:HI 1 "general_operand" ""))] + "" + " +{ + /* Don't generate memory->memory moves, go through a register */ + if (TARGET_MOVE + && (reload_in_progress | reload_completed) == 0 + && GET_CODE (operands[0]) == MEM + && GET_CODE (operands[1]) == MEM) + { + operands[1] = force_reg (HImode, operands[1]); + } +}") + +(define_insn "" [(set (match_operand:HI 0 "general_operand" "=g,r") (match_operand:HI 1 "general_operand" "ri,m"))] - "" + "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" "* { rtx link; @@ -837,10 +883,26 @@ return AS2 (mov%W0,%1,%0); }") -(define_insn "movstricthi" +(define_expand "movstricthi" + [(set (strict_low_part (match_operand:HI 0 "general_operand" "")) + (match_operand:HI 1 "general_operand" ""))] + "" + " +{ + /* Don't generate memory->memory moves, go through a register */ + if (TARGET_MOVE + && (reload_in_progress | reload_completed) == 0 + && GET_CODE (operands[0]) == MEM + && GET_CODE (operands[1]) == MEM) + { + operands[1] = force_reg (HImode, operands[1]); + } +}") + +(define_insn "" [(set (strict_low_part (match_operand:HI 0 "general_operand" "+g,r")) (match_operand:HI 1 "general_operand" "ri,m"))] - "" + "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" "* { rtx link; @@ -868,8 +930,24 @@ ;; the amount pushed up to a halfword. (define_insn "" [(set (match_operand:QI 0 "push_operand" "=<") - (match_operand:QI 1 "general_operand" "q"))] + (match_operand:QI 1 "immediate_operand" "n"))] "" + "* return AS1 (push%W0,%1);") + +(define_insn "" + [(set (match_operand:QI 0 "push_operand" "=<") + (match_operand:QI 1 "nonimmediate_operand" "q"))] + "!TARGET_MOVE" + "* +{ + operands[1] = gen_rtx (REG, HImode, REGNO (operands[1])); + return AS1 (push%W0,%1); +}") + +(define_insn "" + [(set (match_operand:QI 0 "push_operand" "=<") + (match_operand:QI 1 "register_operand" "q"))] + "TARGET_MOVE" "* { operands[1] = gen_rtx (REG, HImode, REGNO (operands[1])); @@ -881,10 +959,26 @@ ;; ??? Do a recognizer for zero_extract that looks just like this, but reads ;; or writes %ah, %bh, %ch, %dh. -(define_insn "movqi" +(define_expand "movqi" + [(set (match_operand:QI 0 "general_operand" "") + (match_operand:QI 1 "general_operand" ""))] + "" + " +{ + /* Don't generate memory->memory moves, go through a register */ + if (TARGET_MOVE + && (reload_in_progress | reload_completed) == 0 + && GET_CODE (operands[0]) == MEM + && GET_CODE (operands[1]) == MEM) + { + operands[1] = force_reg (QImode, operands[1]); + } +}") + +(define_insn "" [(set (match_operand:QI 0 "general_operand" "=q,*r,qm") (match_operand:QI 1 "general_operand" "*g,q,qn"))] - "" + "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" "* { rtx link; @@ -919,10 +1013,26 @@ ;; If operands[1] is a constant, then an andl/orl sequence would be ;; faster. -(define_insn "movstrictqi" +(define_expand "movstrictqi" + [(set (strict_low_part (match_operand:QI 0 "general_operand" "")) + (match_operand:QI 1 "general_operand" ""))] + "" + " +{ + /* Don't generate memory->memory moves, go through a register */ + if (TARGET_MOVE + && (reload_in_progress | reload_completed) == 0 + && GET_CODE (operands[0]) == MEM + && GET_CODE (operands[1]) == MEM) + { + operands[1] = force_reg (QImode, operands[1]); + } +}") + +(define_insn "" [(set (strict_low_part (match_operand:QI 0 "general_operand" "+qm,q")) (match_operand:QI 1 "general_operand" "*qn,m"))] - "" + "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" "* { rtx link; @@ -951,10 +1061,43 @@ return AS2 (mov%B0,%1,%0); }") -(define_insn "" +(define_expand "movsf" + [(set (match_operand:SF 0 "general_operand" "") + (match_operand:SF 1 "general_operand" ""))] + "" + " +{ + /* Special case memory->memory moves and pushes */ + if (TARGET_MOVE + && (reload_in_progress | reload_completed) == 0 + && GET_CODE (operands[0]) == MEM + && (GET_CODE (operands[1]) == MEM || push_operand (operands[0], SFmode))) + { + rtx (*genfunc) PROTO((rtx, rtx)) = (push_operand (operands[0], SFmode)) + ? gen_movsf_push + : gen_movsf_mem; + + emit_insn ((*genfunc) (operands[0], operands[1])); + DONE; + } + + /* If we are loading a floating point constant that isn't 0 or 1 into a register, + indicate we need the pic register loaded. This could be optimized into stores + of constants if the target eventually moves to memory, but better safe than + sorry. */ + if (flag_pic + && GET_CODE (operands[0]) != MEM + && GET_CODE (operands[1]) == CONST_DOUBLE + && !standard_80387_constant_p (operands[1])) + { + current_function_uses_pic_offset_table = 1; + } +}") + +(define_insn "movsf_push_nomove" [(set (match_operand:SF 0 "push_operand" "=<,<") (match_operand:SF 1 "general_operand" "gF,f"))] - "" + "!TARGET_MOVE" "* { if (STACK_REG_P (operands[1])) @@ -979,14 +1122,61 @@ return AS1 (push%L1,%1); }") -;; Allow MEM-MEM moves before reload. The reload class for such a -;; move will be ALL_REGS. PREFERRED_RELOAD_CLASS will narrow this to -;; GENERAL_REGS. For the purposes of regclass, prefer FLOAT_REGS. +(define_insn "movsf_push" + [(set (match_operand:SF 0 "push_operand" "=<,<,<,<") + (match_operand:SF 1 "general_operand" "rF,f,m,m")) + (clobber (match_scratch:SI 2 "=X,X,r,X"))] + "" + "* +{ + if (STACK_REG_P (operands[1])) + { + rtx xops[3]; + + if (! STACK_TOP_P (operands[1])) + abort (); + + xops[0] = AT_SP (SFmode); + xops[1] = GEN_INT (4); + xops[2] = stack_pointer_rtx; + + output_asm_insn (AS2 (sub%L2,%1,%2), xops); + + if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) + output_asm_insn (AS1 (fstp%S0,%0), xops); + else + output_asm_insn (AS1 (fst%S0,%0), xops); + RET; + } + + else if (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != REG) + return AS1 (push%L1,%1); + + else + { + output_asm_insn (AS2 (mov%L2,%1,%2), operands); + return AS1 (push%L2,%2); + } +}") + +;; Special memory<->memory pattern that combine will recreate from the +;; moves to pseudos. +(define_insn "movsf_mem" + [(set (match_operand:SF 0 "memory_operand" "=m") + (match_operand:SF 1 "memory_operand" "m")) + (clobber (match_scratch:SI 2 "=&r"))] + "" + "* +{ + output_asm_insn (AS2 (mov%L2,%1,%2), operands); + return AS2 (mov%L0,%2,%0); +}") -(define_insn "movsf" +;; For the purposes of regclass, prefer FLOAT_REGS. +(define_insn "movsf_normal" [(set (match_operand:SF 0 "general_operand" "=*rfm,*rf,f,!*rm") (match_operand:SF 1 "general_operand" "*rf,*rfm,fG,fF"))] - "" + "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" "* { int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0; @@ -1028,21 +1218,67 @@ /* Handle other kinds of reads to the 387 */ if (STACK_TOP_P (operands[0]) && GET_CODE (operands[1]) == CONST_DOUBLE) - return (char *) output_move_const_single (operands); + return output_move_const_single (operands); if (STACK_TOP_P (operands[0])) return AS1 (fld%z1,%y1); /* Handle all SFmode moves not involving the 387 */ - return (char *) singlemove_string (operands); + return singlemove_string (operands); }") -;;should change to handle the memory operands[1] without doing df push.. -(define_insn "" +(define_insn "swapsf" + [(set (match_operand:SF 0 "register_operand" "f") + (match_operand:SF 1 "register_operand" "f")) + (set (match_dup 1) + (match_dup 0))] + "" + "* +{ + if (STACK_TOP_P (operands[0])) + return AS1 (fxch,%1); + else + return AS1 (fxch,%0); +}") + +(define_expand "movdf" + [(set (match_operand:DF 0 "general_operand" "") + (match_operand:DF 1 "general_operand" ""))] + "" + " +{ + /* Special case memory->memory moves and pushes */ + if (TARGET_MOVE + && (reload_in_progress | reload_completed) == 0 + && GET_CODE (operands[0]) == MEM + && (GET_CODE (operands[1]) == MEM || push_operand (operands[0], DFmode))) + { + rtx (*genfunc) PROTO((rtx, rtx)) = (push_operand (operands[0], DFmode)) + ? gen_movdf_push + : gen_movdf_mem; + + emit_insn ((*genfunc) (operands[0], operands[1])); + DONE; + } + + /* If we are loading a floating point constant that isn't 0 or 1 into a register, + indicate we need the pic register loaded. This could be optimized into stores + of constants if the target eventually moves to memory, but better safe than + sorry. */ + if (flag_pic + && GET_CODE (operands[0]) != MEM + && GET_CODE (operands[1]) == CONST_DOUBLE + && !standard_80387_constant_p (operands[1])) + { + current_function_uses_pic_offset_table = 1; + } +}") + +(define_insn "movdf_push_nomove" [(set (match_operand:DF 0 "push_operand" "=<,<") (match_operand:DF 1 "general_operand" "gF,f"))] - "" + "!TARGET_MOVE" "* { if (STACK_REG_P (operands[1])) @@ -1063,31 +1299,55 @@ RET; } else - return (char *) output_move_double (operands); + return output_move_double (operands); }") -(define_insn "swapdf" - [(set (match_operand:DF 0 "register_operand" "f") - (match_operand:DF 1 "register_operand" "f")) - (set (match_dup 1) - (match_dup 0))] +(define_insn "movdf_push" + [(set (match_operand:DF 0 "push_operand" "=<,<,<,<,<") + (match_operand:DF 1 "general_operand" "rF,f,o,o,o")) + (clobber (match_scratch:SI 2 "=X,X,&r,&r,X")) + (clobber (match_scratch:SI 3 "=X,X,&r,X,X"))] "" "* { - if (STACK_TOP_P (operands[0])) - return AS1 (fxch,%1); + if (STACK_REG_P (operands[1])) + { + rtx xops[3]; + + xops[0] = AT_SP (SFmode); + xops[1] = GEN_INT (8); + xops[2] = stack_pointer_rtx; + + output_asm_insn (AS2 (sub%L2,%1,%2), xops); + + if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) + output_asm_insn (AS1 (fstp%Q0,%0), xops); + else + output_asm_insn (AS1 (fst%Q0,%0), xops); + + RET; + } + + else if (GET_CODE (operands[1]) != MEM) + return output_move_double (operands); + else - return AS1 (fxch,%0); + return output_move_pushmem (operands, insn, GET_MODE_SIZE (DFmode), 2, 4); }") -;; Allow MEM-MEM moves before reload. The reload class for such a -;; move will be ALL_REGS. PREFERRED_RELOAD_CLASS will narrow this to -;; GENERAL_REGS. For the purposes of regclass, prefer FLOAT_REGS. - -(define_insn "movdf" - [(set (match_operand:DF 0 "general_operand" "=*rfm,*rf,f,!*rm") - (match_operand:DF 1 "general_operand" "*rf,*rfm,fG,fF"))] +(define_insn "movdf_mem" + [(set (match_operand:DF 0 "memory_operand" "=o,o") + (match_operand:DF 1 "memory_operand" "o,o")) + (clobber (match_scratch:SI 2 "=&r,&r")) + (clobber (match_scratch:SI 3 "=&r,X"))] "" + "* return output_move_memory (operands, insn, GET_MODE_SIZE (DFmode), 2, 4);") + +;; For the purposes of regclass, prefer FLOAT_REGS. +(define_insn "movdf_normal" + [(set (match_operand:DF 0 "general_operand" "=f,fm,!*rf,!*rm") + (match_operand:DF 1 "general_operand" "fmG,f,*rfm,*rfF"))] + "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" "* { int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0; @@ -1129,20 +1389,68 @@ /* Handle other kinds of reads to the 387 */ if (STACK_TOP_P (operands[0]) && GET_CODE (operands[1]) == CONST_DOUBLE) - return (char *) output_move_const_single (operands); + return output_move_const_single (operands); if (STACK_TOP_P (operands[0])) return AS1 (fld%z1,%y1); /* Handle all DFmode moves not involving the 387 */ - return (char *) output_move_double (operands); + return output_move_double (operands); }") -(define_insn "" +(define_insn "swapdf" + [(set (match_operand:DF 0 "register_operand" "f") + (match_operand:DF 1 "register_operand" "f")) + (set (match_dup 1) + (match_dup 0))] + "" + "* +{ + if (STACK_TOP_P (operands[0])) + return AS1 (fxch,%1); + else + return AS1 (fxch,%0); +}") + +(define_expand "movxf" + [(set (match_operand:XF 0 "general_operand" "") + (match_operand:XF 1 "general_operand" ""))] + "" + " +{ + /* Special case memory->memory moves and pushes */ + if (TARGET_MOVE + && (reload_in_progress | reload_completed) == 0 + && GET_CODE (operands[0]) == MEM + && (GET_CODE (operands[1]) == MEM || push_operand (operands[0], XFmode))) + { + rtx (*genfunc) PROTO((rtx, rtx)) = (push_operand (operands[0], XFmode)) + ? gen_movxf_push + : gen_movxf_mem; + + emit_insn ((*genfunc) (operands[0], operands[1])); + DONE; + } + + /* If we are loading a floating point constant that isn't 0 or 1 into a register, + indicate we need the pic register loaded. This could be optimized into stores + of constants if the target eventually moves to memory, but better safe than + sorry. */ + if (flag_pic + && GET_CODE (operands[0]) != MEM + && GET_CODE (operands[1]) == CONST_DOUBLE + && !standard_80387_constant_p (operands[1])) + { + current_function_uses_pic_offset_table = 1; + } +}") + + +(define_insn "movxf_push_nomove" [(set (match_operand:XF 0 "push_operand" "=<,<") (match_operand:XF 1 "general_operand" "gF,f"))] - "" + "!TARGET_MOVE" "* { if (STACK_REG_P (operands[1])) @@ -1161,29 +1469,53 @@ RET; } else - return (char *) output_move_double (operands); + return output_move_double (operands); }") -(define_insn "swapxf" - [(set (match_operand:XF 0 "register_operand" "f") - (match_operand:XF 1 "register_operand" "f")) - (set (match_dup 1) - (match_dup 0))] +(define_insn "movxf_push" + [(set (match_operand:XF 0 "push_operand" "=<,<,<,<,<") + (match_operand:XF 1 "general_operand" "rF,f,o,o,o")) + (clobber (match_scratch:SI 2 "=X,X,&r,&r,X")) + (clobber (match_scratch:SI 3 "=X,X,&r,X,X"))] "" "* { - if (STACK_TOP_P (operands[0])) - return AS1 (fxch,%1); + if (STACK_REG_P (operands[1])) + { + rtx xops[3]; + + xops[0] = AT_SP (SFmode); + xops[1] = GEN_INT (12); + xops[2] = stack_pointer_rtx; + + output_asm_insn (AS2 (sub%L2,%1,%2), xops); + output_asm_insn (AS1 (fstp%T0,%0), xops); + if (! find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) + output_asm_insn (AS1 (fld%T0,%0), xops); + + RET; + } + + else if (GET_CODE (operands[1]) != MEM + || GET_CODE (operands[2]) != REG) + return output_move_double (operands); + else - return AS1 (fxch,%0); + return output_move_pushmem (operands, insn, GET_MODE_SIZE (XFmode), 2, 4); }") -(define_insn "movxf" +(define_insn "movxf_mem" + [(set (match_operand:XF 0 "memory_operand" "=o,o") + (match_operand:XF 1 "memory_operand" "o,o")) + (clobber (match_scratch:SI 2 "=&r,&r")) + (clobber (match_scratch:SI 3 "=&r,X"))] + "" + "* return output_move_memory (operands, insn, GET_MODE_SIZE (XFmode), 2, 4);") + +(define_insn "movxf_normal" [(set (match_operand:XF 0 "general_operand" "=f,fm,!*rf,!*rm") (match_operand:XF 1 "general_operand" "fmG,f,*rfm,*rfF"))] -;; [(set (match_operand:XF 0 "general_operand" "=*rf,*rfm,f,!*rm") -;; (match_operand:XF 1 "general_operand" "*rfm,*rf,fG,fF"))] - "" + "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" "* { int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0; @@ -1226,33 +1558,61 @@ /* Handle other kinds of reads to the 387 */ if (STACK_TOP_P (operands[0]) && GET_CODE (operands[1]) == CONST_DOUBLE) - return (char *) output_move_const_single (operands); + return output_move_const_single (operands); if (STACK_TOP_P (operands[0])) return AS1 (fld%z1,%y1); /* Handle all XFmode moves not involving the 387 */ - return (char *) output_move_double (operands); + return output_move_double (operands); +}") + +(define_insn "swapxf" + [(set (match_operand:XF 0 "register_operand" "f") + (match_operand:XF 1 "register_operand" "f")) + (set (match_dup 1) + (match_dup 0))] + "" + "* +{ + if (STACK_TOP_P (operands[0])) + return AS1 (fxch,%1); + else + return AS1 (fxch,%0); }") (define_insn "" - [(set (match_operand:DI 0 "push_operand" "=<") - (match_operand:DI 1 "general_operand" "roiF"))] + [(set (match_operand:DI 0 "push_operand" "=<,<,<,<") + (match_operand:DI 1 "general_operand" "riF,o,o,o")) + (clobber (match_scratch:SI 2 "=X,&r,&r,X")) + (clobber (match_scratch:SI 3 "=X,&r,X,X"))] "" "* { - return (char *) output_move_double (operands); + if (GET_CODE (operands[1]) != MEM) + return output_move_double (operands); + + else + return output_move_pushmem (operands, insn, GET_MODE_SIZE (DImode), 2, 4); }") (define_insn "movdi" - [(set (match_operand:DI 0 "general_operand" "=r,rm") - (match_operand:DI 1 "general_operand" "m,riF"))] + [(set (match_operand:DI 0 "general_operand" "=o,o,r,rm") + (match_operand:DI 1 "general_operand" "o,o,m,riF")) + (clobber (match_scratch:SI 2 "=&r,&r,X,X")) + (clobber (match_scratch:SI 3 "=&r,X,X,X"))] "" "* { - return (char *) output_move_double (operands); + rtx low[2], high[2], xop[6]; + + if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) + return output_move_double (operands); + else + return output_move_memory (operands, insn, GET_MODE_SIZE (DImode), 2, 4); }") + ;;- conversion instructions ;;- NONE @@ -1267,7 +1627,7 @@ "" "* { - if ((TARGET_486 || REGNO (operands[0]) == 0) + if ((!TARGET_386 || REGNO (operands[0]) == 0) && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1])) { rtx xops[2]; @@ -1291,7 +1651,7 @@ "" "* { - if ((TARGET_486 || REGNO (operands[0]) == 0) + if ((!TARGET_386 || REGNO (operands[0]) == 0) && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1])) { rtx xops[2]; @@ -1315,7 +1675,7 @@ "" "* { - if ((TARGET_486 || REGNO (operands[0]) == 0) + if ((!TARGET_386 || REGNO (operands[0]) == 0) && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1])) { rtx xops[2]; @@ -1778,7 +2138,7 @@ (clobber (match_operand:SI 3 "memory_operand" "m")) (clobber (match_scratch:SI 4 "=&q"))] "TARGET_80387" - "* return (char *) output_fix_trunc (insn, operands);") + "* return output_fix_trunc (insn, operands);") (define_insn "" [(set (match_operand:DI 0 "general_operand" "=rm") @@ -1788,7 +2148,7 @@ (clobber (match_operand:SI 3 "memory_operand" "m")) (clobber (match_scratch:SI 4 "=&q"))] "TARGET_80387" - "* return (char *) output_fix_trunc (insn, operands);") + "* return output_fix_trunc (insn, operands);") (define_insn "" [(set (match_operand:DI 0 "general_operand" "=rm") @@ -1798,7 +2158,7 @@ (clobber (match_operand:SI 3 "memory_operand" "m")) (clobber (match_scratch:SI 4 "=&q"))] "TARGET_80387" - "* return (char *) output_fix_trunc (insn, operands);") + "* return output_fix_trunc (insn, operands);") ;; Signed MODE_FLOAT conversion to SImode. @@ -1851,7 +2211,7 @@ (clobber (match_operand:SI 3 "memory_operand" "m")) (clobber (match_scratch:SI 4 "=&q"))] "TARGET_80387" - "* return (char *) output_fix_trunc (insn, operands);") + "* return output_fix_trunc (insn, operands);") (define_insn "" [(set (match_operand:SI 0 "general_operand" "=rm") @@ -1860,7 +2220,7 @@ (clobber (match_operand:SI 3 "memory_operand" "m")) (clobber (match_scratch:SI 4 "=&q"))] "TARGET_80387" - "* return (char *) output_fix_trunc (insn, operands);") + "* return output_fix_trunc (insn, operands);") (define_insn "" [(set (match_operand:SI 0 "general_operand" "=rm") @@ -1869,7 +2229,7 @@ (clobber (match_operand:SI 3 "memory_operand" "m")) (clobber (match_scratch:SI 4 "=&q"))] "TARGET_80387" - "* return (char *) output_fix_trunc (insn, operands);") + "* return output_fix_trunc (insn, operands);") ;; Conversion between fixed point and floating point. ;; The actual pattern that matches these is at the end of this file. @@ -2019,25 +2379,75 @@ ;;- add instructions (define_insn "adddi3" - [(set (match_operand:DI 0 "general_operand" "=&r,ro") - (plus:DI (match_operand:DI 1 "general_operand" "%0,0") - (match_operand:DI 2 "general_operand" "o,riF")))] + [(set (match_operand:DI 0 "general_operand" "=&r,ro,o,&r,ro,o,&r,o,o,o") + (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,o,riF,o,or,riF,riF,o") + (match_operand:DI 2 "general_operand" "o,riF,o,0,0,0,oriF,riF,o,o"))) + (clobber (match_scratch:SI 3 "=X,X,&r,X,X,&r,X,X,&r,&r"))] "" "* { - rtx low[3], high[3]; + rtx low[3], high[3], xops[7], temp; CC_STATUS_INIT; + if (rtx_equal_p (operands[0], operands[2])) + { + temp = operands[1]; + operands[1] = operands[2]; + operands[2] = temp; + } + split_di (operands, 3, low, high); + if (!rtx_equal_p (operands[0], operands[1])) + { + xops[0] = high[0]; + xops[1] = low[0]; + xops[2] = high[1]; + xops[3] = low[1]; - if (GET_CODE (low[2]) != CONST_INT || INTVAL (low[2]) != 0) + if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) + { + output_asm_insn (AS2 (mov%L1,%3,%1), xops); + output_asm_insn (AS2 (mov%L0,%2,%0), xops); + } + else + { + xops[4] = high[2]; + xops[5] = low[2]; + xops[6] = operands[3]; + output_asm_insn (AS2 (mov%L6,%3,%6), xops); + output_asm_insn (AS2 (add%L6,%5,%6), xops); + output_asm_insn (AS2 (mov%L1,%6,%1), xops); + output_asm_insn (AS2 (mov%L6,%2,%6), xops); + output_asm_insn (AS2 (adc%L6,%4,%6), xops); + output_asm_insn (AS2 (mov%L0,%6,%0), xops); + RET; + } + } + + if (GET_CODE (operands[3]) == REG && GET_CODE (operands[2]) != REG) + { + xops[0] = high[0]; + xops[1] = low[0]; + xops[2] = high[2]; + xops[3] = low[2]; + xops[4] = operands[3]; + + output_asm_insn (AS2 (mov%L4,%3,%4), xops); + output_asm_insn (AS2 (add%L1,%4,%1), xops); + output_asm_insn (AS2 (mov%L4,%2,%4), xops); + output_asm_insn (AS2 (adc%L0,%4,%0), xops); + } + + else if (GET_CODE (low[2]) != CONST_INT || INTVAL (low[2]) != 0) { output_asm_insn (AS2 (add%L0,%2,%0), low); output_asm_insn (AS2 (adc%L0,%2,%0), high); } + else output_asm_insn (AS2 (add%L0,%2,%0), high); + RET; }") @@ -2056,23 +2466,20 @@ if (REG_P (operands[2]) && REGNO (operands[0]) == REGNO (operands[2])) return AS2 (add%L0,%1,%0); - if (! TARGET_486 || ! REG_P (operands[2])) - { - CC_STATUS_INIT; + if (operands[2] == stack_pointer_rtx) + { + rtx temp; - if (operands[2] == stack_pointer_rtx) - { - rtx temp; + temp = operands[1]; + operands[1] = operands[2]; + operands[2] = temp; + } - temp = operands[1]; - operands[1] = operands[2]; - operands[2] = temp; - } - if (operands[2] != stack_pointer_rtx) - { - operands[1] = SET_SRC (PATTERN (insn)); - return AS2 (lea%L0,%a1,%0); - } + if (operands[2] != stack_pointer_rtx) + { + CC_STATUS_INIT; + operands[1] = SET_SRC (PATTERN (insn)); + return AS2 (lea%L0,%a1,%0); } output_asm_insn (AS2 (mov%L0,%1,%0), operands); @@ -2103,23 +2510,24 @@ && GET_CODE (operands[2]) == CONST_INT && (INTVAL (operands[2]) & 0xff) == 0) { + int byteval = (INTVAL (operands[2]) >> 8) & 0xff; CC_STATUS_INIT; - operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff); - - if (operands[2] == const1_rtx) + if (byteval == 1) return AS1 (inc%B0,%h0); - - if (operands[2] == constm1_rtx) + else if (byteval == 255) return AS1 (dec%B0,%h0); + operands[2] = GEN_INT (byteval); return AS2 (add%B0,%2,%h0); } if (operands[2] == const1_rtx) return AS1 (inc%W0,%0); - if (operands[2] == constm1_rtx) + if (operands[2] == constm1_rtx + || (GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) == 65535)) return AS1 (dec%W0,%0); return AS2 (add%W0,%2,%0); @@ -2135,7 +2543,9 @@ if (operands[2] == const1_rtx) return AS1 (inc%B0,%0); - if (operands[2] == constm1_rtx) + if (operands[2] == constm1_rtx + || (GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) == 255)) return AS1 (dec%B0,%0); return AS2 (add%B0,%2,%0); @@ -2168,7 +2578,7 @@ ;; addsi3 is faster, so put this after. -(define_insn "" +(define_insn "movsi_lea" [(set (match_operand:SI 0 "register_operand" "=r") (match_operand:QI 1 "address_operand" "p"))] "" @@ -2220,23 +2630,66 @@ ;;- subtract instructions (define_insn "subdi3" - [(set (match_operand:DI 0 "general_operand" "=&r,ro") - (minus:DI (match_operand:DI 1 "general_operand" "0,0") - (match_operand:DI 2 "general_operand" "o,riF")))] + [(set (match_operand:DI 0 "general_operand" "=&r,ro,&r,o,o") + (minus:DI (match_operand:DI 1 "general_operand" "0,0,roiF,riF,o") + (match_operand:DI 2 "general_operand" "o,riF,roiF,riF,o"))) + (clobber (match_scratch:SI 3 "=X,X,X,X,&r"))] "" "* { - rtx low[3], high[3]; + rtx low[3], high[3], xops[7]; CC_STATUS_INIT; split_di (operands, 3, low, high); - if (GET_CODE (low[2]) != CONST_INT || INTVAL (low[2]) != 0) + if (!rtx_equal_p (operands[0], operands[1])) + { + xops[0] = high[0]; + xops[1] = low[0]; + xops[2] = high[1]; + xops[3] = low[1]; + + if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) + { + output_asm_insn (AS2 (mov%L1,%3,%1), xops); + output_asm_insn (AS2 (mov%L0,%2,%0), xops); + } + else + { + xops[4] = high[2]; + xops[5] = low[2]; + xops[6] = operands[3]; + output_asm_insn (AS2 (mov%L6,%3,%6), xops); + output_asm_insn (AS2 (sub%L6,%5,%6), xops); + output_asm_insn (AS2 (mov%L1,%6,%1), xops); + output_asm_insn (AS2 (mov%L6,%2,%6), xops); + output_asm_insn (AS2 (sbb%L6,%4,%6), xops); + output_asm_insn (AS2 (mov%L0,%6,%0), xops); + RET; + } + } + + if (GET_CODE (operands[3]) == REG) + { + xops[0] = high[0]; + xops[1] = low[0]; + xops[2] = high[2]; + xops[3] = low[2]; + xops[4] = operands[3]; + + output_asm_insn (AS2 (mov%L4,%3,%4), xops); + output_asm_insn (AS2 (sub%L1,%4,%1), xops); + output_asm_insn (AS2 (mov%L4,%2,%4), xops); + output_asm_insn (AS2 (sbb%L0,%4,%0), xops); + } + + else if (GET_CODE (low[2]) != CONST_INT || INTVAL (low[2]) != 0) { output_asm_insn (AS2 (sub%L0,%2,%0), low); output_asm_insn (AS2 (sbb%L0,%2,%0), high); } + else output_asm_insn (AS2 (sub%L0,%2,%0), high); @@ -2298,14 +2751,14 @@ (define_insn "" [(set (match_operand:HI 0 "general_operand" "=r") - (mult:SI (match_operand:HI 1 "general_operand" "%0") + (mult:HI (match_operand:HI 1 "general_operand" "%0") (match_operand:HI 2 "general_operand" "r")))] "GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0x80" "* return AS2 (imul%W0,%2,%0);") (define_insn "mulhi3" [(set (match_operand:HI 0 "general_operand" "=r,r") - (mult:SI (match_operand:HI 1 "general_operand" "%0,rm") + (mult:HI (match_operand:HI 1 "general_operand" "%0,rm") (match_operand:HI 2 "general_operand" "g,i")))] "" "* @@ -2340,15 +2793,52 @@ return AS3 (imul%L0,%2,%1,%0); }") -(define_insn "" +(define_insn "umulqihi3" [(set (match_operand:HI 0 "general_operand" "=a") - (mult:SI (zero_extend:HI - (match_operand:QI 1 "nonimmediate_operand" "%0")) - (zero_extend:HI - (match_operand:QI 2 "nonimmediate_operand" "qm"))))] + (mult:HI (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "%0")) + (zero_extend:HI (match_operand:QI 2 "nonimmediate_operand" "qm"))))] "" "mul%B0 %2") +(define_insn "mulqihi3" + [(set (match_operand:HI 0 "general_operand" "=a") + (mult:HI (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "%0")) + (sign_extend:HI (match_operand:QI 2 "nonimmediate_operand" "qm"))))] + "" + "imul%B0 %2") + +(define_insn "umulsidi3" + [(set (match_operand:DI 0 "register_operand" "=A") + (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0")) + (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))))] + "TARGET_WIDE_MULTIPLY" + "mul%L0 %2") + +(define_insn "mulsidi3" + [(set (match_operand:DI 0 "register_operand" "=A") + (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%0")) + (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))))] + "TARGET_WIDE_MULTIPLY" + "imul%L0 %2") + +(define_insn "umulsi3_highpart" + [(set (match_operand:SI 0 "register_operand" "=d") + (truncate:SI (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%a")) + (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))) + (const_int 32)))) + (clobber (match_scratch:SI 3 "=a"))] + "TARGET_WIDE_MULTIPLY" + "mul%L0 %2") + +(define_insn "smulsi3_highpart" + [(set (match_operand:SI 0 "register_operand" "=d") + (truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%a")) + (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))) + (const_int 32)))) + (clobber (match_scratch:SI 3 "=a"))] + "TARGET_WIDE_MULTIPLY" + "imul%L0 %2") + ;; The patterns that match these are at the end of this file. (define_expand "mulxf3" @@ -2511,7 +3001,7 @@ if (INTVAL (operands[2]) == 0xffff && REG_P (operands[0]) && (! REG_P (operands[1]) || REGNO (operands[0]) != 0 || REGNO (operands[1]) != 0) - && (! TARGET_486 || ! rtx_equal_p (operands[0], operands[1]))) + && (TARGET_386 || ! rtx_equal_p (operands[0], operands[1]))) { /* ??? tege: Should forget CC_STATUS only if we clobber a remembered operand. Fix that later. */ @@ -2527,7 +3017,7 @@ && !(REG_P (operands[1]) && NON_QI_REG_P (operands[1])) && (! REG_P (operands[1]) || REGNO (operands[0]) != 0 || REGNO (operands[1]) != 0) - && (! TARGET_486 || ! rtx_equal_p (operands[0], operands[1]))) + && (TARGET_386 || ! rtx_equal_p (operands[0], operands[1]))) { /* ??? tege: Should forget CC_STATUS only if we clobber a remembered operand. Fix that later. */ @@ -2935,78 +3425,90 @@ (define_insn "sqrtsf2" [(set (match_operand:SF 0 "register_operand" "=f") (sqrt:SF (match_operand:SF 1 "general_operand" "0")))] - "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + && (TARGET_IEEE_FP || flag_fast_math) " "fsqrt") (define_insn "sqrtdf2" [(set (match_operand:DF 0 "register_operand" "=f") (sqrt:DF (match_operand:DF 1 "general_operand" "0")))] - "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + && (TARGET_IEEE_FP || flag_fast_math) " "fsqrt") (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") (sqrt:DF (float_extend:DF (match_operand:SF 1 "general_operand" "0"))))] - "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + && (TARGET_IEEE_FP || flag_fast_math) " "fsqrt") (define_insn "sqrtxf2" [(set (match_operand:XF 0 "register_operand" "=f") (sqrt:XF (match_operand:XF 1 "general_operand" "0")))] - "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + && (TARGET_IEEE_FP || flag_fast_math) " "fsqrt") (define_insn "" [(set (match_operand:XF 0 "register_operand" "=f") (sqrt:XF (float_extend:XF (match_operand:DF 1 "general_operand" "0"))))] - "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + && (TARGET_IEEE_FP || flag_fast_math) " "fsqrt") (define_insn "" [(set (match_operand:XF 0 "register_operand" "=f") (sqrt:XF (float_extend:XF (match_operand:SF 1 "general_operand" "0"))))] - "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + && (TARGET_IEEE_FP || flag_fast_math) " "fsqrt") (define_insn "sindf2" [(set (match_operand:DF 0 "register_operand" "=f") (unspec:DF [(match_operand:DF 1 "register_operand" "0")] 1))] - "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + && (TARGET_IEEE_FP || flag_fast_math) " "fsin") (define_insn "sinsf2" [(set (match_operand:SF 0 "register_operand" "=f") (unspec:SF [(match_operand:SF 1 "register_operand" "0")] 1))] - "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + && (TARGET_IEEE_FP || flag_fast_math) " "fsin") (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") (unspec:DF [(float_extend:DF (match_operand:SF 1 "register_operand" "0"))] 1))] - "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + && (TARGET_IEEE_FP || flag_fast_math) " "fsin") (define_insn "cosdf2" [(set (match_operand:DF 0 "register_operand" "=f") (unspec:DF [(match_operand:DF 1 "register_operand" "0")] 2))] - "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + && (TARGET_IEEE_FP || flag_fast_math) " "fcos") (define_insn "cossf2" [(set (match_operand:SF 0 "register_operand" "=f") (unspec:SF [(match_operand:SF 1 "register_operand" "0")] 2))] - "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + && (TARGET_IEEE_FP || flag_fast_math) " "fcos") (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") (unspec:DF [(float_extend:DF (match_operand:SF 1 "register_operand" "0"))] 2))] - "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + && (TARGET_IEEE_FP || flag_fast_math) " "fcos") ;;- one complement instructions @@ -3158,7 +3660,7 @@ { if (REG_P (operands[0]) && REGNO (operands[0]) != REGNO (operands[1])) { - if (TARGET_486 && INTVAL (operands[2]) == 1) + if (!TARGET_386 && INTVAL (operands[2]) == 1) { output_asm_insn (AS2 (mov%L0,%1,%0), operands); return AS2 (add%L0,%1,%0); @@ -3659,7 +4161,7 @@ (const_int 1) (match_operand:SI 2 "general_operand" "r")) (match_operand:SI 3 "const_int_operand" "n"))] - "! TARGET_486 && GET_CODE (operands[2]) != CONST_INT" + "TARGET_386 && GET_CODE (operands[2]) != CONST_INT" "* { CC_STATUS_INIT; @@ -3677,7 +4179,7 @@ (xor:SI (ashift:SI (const_int 1) (match_operand:SI 1 "general_operand" "r")) (match_operand:SI 2 "general_operand" "0")))] - "! TARGET_486 && GET_CODE (operands[1]) != CONST_INT" + "TARGET_386 && GET_CODE (operands[1]) != CONST_INT" "* { CC_STATUS_INIT; @@ -3690,7 +4192,7 @@ (xor:SI (match_operand:SI 1 "general_operand" "0") (ashift:SI (const_int 1) (match_operand:SI 2 "general_operand" "r"))))] - "! TARGET_486 && GET_CODE (operands[2]) != CONST_INT" + "TARGET_386 && GET_CODE (operands[2]) != CONST_INT" "* { CC_STATUS_INIT; @@ -4708,126 +5210,42 @@ "!HALF_PIC_P ()" "call %P1") +;; Call subroutine returning any type. + (define_expand "untyped_call" - [(parallel [(call (match_operand:QI 0 "indirect_operand" "") + [(parallel [(call (match_operand 0 "" "") (const_int 0)) - (match_operand:BLK 1 "memory_operand" "") + (match_operand 1 "" "") (match_operand 2 "" "")])] "" " { - rtx addr; - - if (flag_pic) - current_function_uses_pic_offset_table = 1; - - /* With half-pic, force the address into a register. */ - addr = XEXP (operands[0], 0); - if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr)) - XEXP (operands[0], 0) = force_reg (Pmode, addr); + int i; - operands[1] = change_address (operands[1], DImode, XEXP (operands[1], 0)); - if (! expander_call_insn_operand (operands[1], QImode)) - operands[1] - = change_address (operands[1], VOIDmode, - copy_to_mode_reg (Pmode, XEXP (operands[1], 0))); -}") - -(define_insn "" - [(call (match_operand:QI 0 "call_insn_operand" "m") - (const_int 0)) - (match_operand:DI 1 "memory_operand" "o") - (match_operand 2 "" "")] - "" - "* -{ - rtx addr = operands[1]; + emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx)); - if (GET_CODE (operands[0]) == MEM - && ! CONSTANT_ADDRESS_P (XEXP (operands[0], 0))) + for (i = 0; i < XVECLEN (operands[2], 0); i++) { - operands[0] = XEXP (operands[0], 0); - output_asm_insn (AS1 (call,%*%0), operands); + rtx set = XVECEXP (operands[2], 0, i); + emit_move_insn (SET_DEST (set), SET_SRC (set)); } - else - output_asm_insn (AS1 (call,%P0), operands); - - operands[2] = gen_rtx (REG, SImode, 0); - output_asm_insn (AS2 (mov%L2,%2,%1), operands); - operands[2] = gen_rtx (REG, SImode, 1); - operands[1] = adj_offsettable_operand (addr, 4); - output_asm_insn (AS2 (mov%L2,%2,%1), operands); - - operands[1] = adj_offsettable_operand (addr, 8); - return AS1 (fnsave,%1); -}") - -(define_insn "" - [(call (mem:QI (match_operand:SI 0 "symbolic_operand" "")) - (const_int 0)) - (match_operand:DI 1 "memory_operand" "o") - (match_operand 2 "" "")] - "!HALF_PIC_P ()" - "* -{ - rtx addr = operands[1]; - - output_asm_insn (AS1 (call,%P0), operands); - - operands[2] = gen_rtx (REG, SImode, 0); - output_asm_insn (AS2 (mov%L2,%2,%1), operands); - - operands[2] = gen_rtx (REG, SImode, 1); - operands[1] = adj_offsettable_operand (addr, 4); - output_asm_insn (AS2 (mov%L2,%2,%1), operands); - - operands[1] = adj_offsettable_operand (addr, 8); - return AS1 (fnsave,%1); -}") - -;; We use fnsave and frstor to save and restore the floating point result. -;; These are expensive instructions and require a large space to save the -;; FPU state. An more complicated alternative is to use fnstenv to store -;; the FPU environment and test whether the stack top is valid. Store the -;; result of the test, and if it is valid, pop and save the value. The -;; untyped_return would check the test and optionally push the saved value. - -(define_expand "untyped_return" - [(match_operand:BLK 0 "memory_operand" "") - (match_operand 1 "" "")] - "" - " -{ - rtx valreg1 = gen_rtx (REG, SImode, 0); - rtx valreg2 = gen_rtx (REG, SImode, 1); - rtx result = operands[0]; - - /* Restore the FPU state. */ - emit_insn (gen_update_return (change_address (result, SImode, - plus_constant (XEXP (result, 0), - 8)))); - - /* Reload the function value registers. */ - emit_move_insn (valreg1, change_address (result, SImode, XEXP (result, 0))); - emit_move_insn (valreg2, - change_address (result, SImode, - plus_constant (XEXP (result, 0), 4))); - - /* Put USE insns before the return. */ - emit_insn (gen_rtx (USE, VOIDmode, valreg1)); - emit_insn (gen_rtx (USE, VOIDmode, valreg2)); - - /* Construct the return. */ - expand_null_return (); + /* The optimizer does not know that the call sets the function value + registers we stored in the result block. We avoid problems by + claiming that all hard registers are used and clobbered at this + point. */ + emit_insn (gen_blockage ()); DONE; }") -(define_insn "update_return" - [(unspec:SI [(match_operand:SI 0 "memory_operand" "m")] 0)] +;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and +;; all of memory. This blocks insns from being moved across this point. + +(define_insn "blockage" + [(unspec_volatile [(const_int 0)] 0)] "" - "frstor %0") + "") ;; Insn emitted into the body of a function to return from a function. ;; This is only done if the function's epilogue is known to be simple. @@ -5119,7 +5537,7 @@ [(match_operand:DF 1 "nonimmediate_operand" "0,fm") (match_operand:DF 2 "nonimmediate_operand" "fm,0")]))] "TARGET_80387" - "* return (char *) output_387_binary_op (insn, operands);") + "* return output_387_binary_op (insn, operands);") (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") @@ -5127,7 +5545,7 @@ [(float:DF (match_operand:SI 1 "general_operand" "rm")) (match_operand:DF 2 "general_operand" "0")]))] "TARGET_80387" - "* return (char *) output_387_binary_op (insn, operands);") + "* return output_387_binary_op (insn, operands);") (define_insn "" [(set (match_operand:XF 0 "register_operand" "=f,f") @@ -5135,7 +5553,7 @@ [(match_operand:XF 1 "nonimmediate_operand" "0,f") (match_operand:XF 2 "nonimmediate_operand" "f,0")]))] "TARGET_80387" - "* return (char *) output_387_binary_op (insn, operands);") + "* return output_387_binary_op (insn, operands);") (define_insn "" [(set (match_operand:XF 0 "register_operand" "=f") @@ -5143,7 +5561,7 @@ [(float:XF (match_operand:SI 1 "general_operand" "rm")) (match_operand:XF 2 "general_operand" "0")]))] "TARGET_80387" - "* return (char *) output_387_binary_op (insn, operands);") + "* return output_387_binary_op (insn, operands);") (define_insn "" [(set (match_operand:XF 0 "register_operand" "=f,f") @@ -5151,7 +5569,7 @@ [(float_extend:XF (match_operand:SF 1 "general_operand" "fm,0")) (match_operand:XF 2 "general_operand" "0,f")]))] "TARGET_80387" - "* return (char *) output_387_binary_op (insn, operands);") + "* return output_387_binary_op (insn, operands);") (define_insn "" [(set (match_operand:XF 0 "register_operand" "=f") @@ -5159,7 +5577,7 @@ [(match_operand:XF 1 "general_operand" "0") (float:XF (match_operand:SI 2 "general_operand" "rm"))]))] "TARGET_80387" - "* return (char *) output_387_binary_op (insn, operands);") + "* return output_387_binary_op (insn, operands);") (define_insn "" [(set (match_operand:XF 0 "register_operand" "=f,f") @@ -5168,7 +5586,7 @@ (float_extend:XF (match_operand:SF 2 "general_operand" "fm,0"))]))] "TARGET_80387" - "* return (char *) output_387_binary_op (insn, operands);") + "* return output_387_binary_op (insn, operands);") (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f,f") @@ -5176,7 +5594,7 @@ [(float_extend:DF (match_operand:SF 1 "general_operand" "fm,0")) (match_operand:DF 2 "general_operand" "0,f")]))] "TARGET_80387" - "* return (char *) output_387_binary_op (insn, operands);") + "* return output_387_binary_op (insn, operands);") (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") @@ -5184,7 +5602,7 @@ [(match_operand:DF 1 "general_operand" "0") (float:DF (match_operand:SI 2 "general_operand" "rm"))]))] "TARGET_80387" - "* return (char *) output_387_binary_op (insn, operands);") + "* return output_387_binary_op (insn, operands);") (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f,f") @@ -5193,7 +5611,7 @@ (float_extend:DF (match_operand:SF 2 "general_operand" "fm,0"))]))] "TARGET_80387" - "* return (char *) output_387_binary_op (insn, operands);") + "* return output_387_binary_op (insn, operands);") (define_insn "" [(set (match_operand:SF 0 "register_operand" "=f,f") @@ -5201,7 +5619,7 @@ [(match_operand:SF 1 "nonimmediate_operand" "0,fm") (match_operand:SF 2 "nonimmediate_operand" "fm,0")]))] "TARGET_80387" - "* return (char *) output_387_binary_op (insn, operands);") + "* return output_387_binary_op (insn, operands);") (define_insn "" [(set (match_operand:SF 0 "register_operand" "=f") @@ -5209,7 +5627,7 @@ [(float:SF (match_operand:SI 1 "general_operand" "rm")) (match_operand:SF 2 "general_operand" "0")]))] "TARGET_80387" - "* return (char *) output_387_binary_op (insn, operands);") + "* return output_387_binary_op (insn, operands);") (define_insn "" [(set (match_operand:SF 0 "register_operand" "=f") @@ -5217,7 +5635,7 @@ [(match_operand:SF 1 "general_operand" "0") (float:SF (match_operand:SI 2 "general_operand" "rm"))]))] "TARGET_80387" - "* return (char *) output_387_binary_op (insn, operands);") + "* return output_387_binary_op (insn, operands);") (define_expand "strlensi" [(parallel [(set (match_dup 4)