diff options
Diffstat (limited to 'gcc/config/i386/i386.md')
-rw-r--r-- | gcc/config/i386/i386.md | 63 |
1 files changed, 61 insertions, 2 deletions
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index de669ba865e..2fbf654a208 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -146,6 +146,7 @@ (UNSPEC_FPREM1_U 91) (UNSPEC_C2_FLAG 95) + (UNSPEC_FXAM_MEM 96) ; SSP patterns (UNSPEC_SP_SET 100) @@ -18811,9 +18812,56 @@ (set_attr "unit" "i387") (set_attr "mode" "<MODE>")]) +(define_insn_and_split "fxam<mode>2_i387_with_temp" + [(set (match_operand:HI 0 "register_operand" "") + (unspec:HI + [(match_operand:MODEF 1 "memory_operand" "")] + UNSPEC_FXAM_MEM))] + "TARGET_USE_FANCY_MATH_387 + && !(reload_completed || reload_in_progress)" + "#" + "&& 1" + [(set (match_dup 2)(match_dup 1)) + (set (match_dup 0) + (unspec:HI [(match_dup 2)] UNSPEC_FXAM))] +{ + operands[2] = gen_reg_rtx (<MODE>mode); + + MEM_VOLATILE_P (operands[1]) = 1; +} + [(set_attr "type" "multi") + (set_attr "unit" "i387") + (set_attr "mode" "<MODE>")]) + +(define_expand "isinfxf2" + [(use (match_operand:SI 0 "register_operand" "")) + (use (match_operand:XF 1 "register_operand" ""))] + "TARGET_USE_FANCY_MATH_387 + && TARGET_C99_FUNCTIONS" +{ + rtx mask = GEN_INT (0x45); + rtx val = GEN_INT (0x05); + + rtx cond; + + rtx scratch = gen_reg_rtx (HImode); + rtx res = gen_reg_rtx (QImode); + + emit_insn (gen_fxamxf2_i387 (scratch, operands[1])); + + emit_insn (gen_andqi_ext_0 (scratch, scratch, mask)); + emit_insn (gen_cmpqi_ext_3 (scratch, val)); + cond = gen_rtx_fmt_ee (EQ, QImode, + gen_rtx_REG (CCmode, FLAGS_REG), + const0_rtx); + emit_insn (gen_rtx_SET (VOIDmode, res, cond)); + emit_insn (gen_zero_extendqisi2 (operands[0], res)); + DONE; +}) + (define_expand "isinf<mode>2" [(use (match_operand:SI 0 "register_operand" "")) - (use (match_operand:X87MODEF 1 "register_operand" ""))] + (use (match_operand:MODEF 1 "nonimmediate_operand" ""))] "TARGET_USE_FANCY_MATH_387 && TARGET_C99_FUNCTIONS && !(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)" @@ -18826,7 +18874,18 @@ rtx scratch = gen_reg_rtx (HImode); rtx res = gen_reg_rtx (QImode); - emit_insn (gen_fxam<mode>2_i387 (scratch, operands[1])); + /* Remove excess precision by forcing value through memory. */ + if (memory_operand (operands[1], VOIDmode)) + emit_insn (gen_fxam<mode>2_i387_with_temp (scratch, operands[1])); + else + { + int slot = virtuals_instantiated ? SLOT_TEMP : SLOT_VIRTUAL; + rtx temp = assign_386_stack_local (<MODE>mode, slot); + + emit_move_insn (temp, operands[1]); + emit_insn (gen_fxam<mode>2_i387_with_temp (scratch, temp)); + } + emit_insn (gen_andqi_ext_0 (scratch, scratch, mask)); emit_insn (gen_cmpqi_ext_3 (scratch, val)); cond = gen_rtx_fmt_ee (EQ, QImode, |