diff options
Diffstat (limited to 'gcc/config/mn10300/mn10300.md')
-rw-r--r-- | gcc/config/mn10300/mn10300.md | 129 |
1 files changed, 125 insertions, 4 deletions
diff --git a/gcc/config/mn10300/mn10300.md b/gcc/config/mn10300/mn10300.md index d3061ad54b8..8e090a3395d 100644 --- a/gcc/config/mn10300/mn10300.md +++ b/gcc/config/mn10300/mn10300.md @@ -155,7 +155,6 @@ { if (XEXP (operands[1], 0) == stack_pointer_rtx) { - emit_move_insn (operands[0], XEXP (operands[1], 0)); if (GET_CODE (XEXP (operands[1], 1)) == SUBREG && (GET_MODE_SIZE (GET_MODE (XEXP (operands[1], 1))) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (XEXP (operands[1], 1)))))) @@ -164,10 +163,10 @@ SUBREG_REG (XEXP (operands[1], 1)))); else emit_move_insn (operands[2], XEXP (operands[1], 1)); + emit_move_insn (operands[0], XEXP (operands[1], 0)); } else { - emit_move_insn (operands[0], XEXP (operands[1], 1)); if (GET_CODE (XEXP (operands[1], 0)) == SUBREG && (GET_MODE_SIZE (GET_MODE (XEXP (operands[1], 0))) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (XEXP (operands[1], 0)))))) @@ -176,6 +175,7 @@ SUBREG_REG (XEXP (operands[1], 0)))); else emit_move_insn (operands[2], XEXP (operands[1], 0)); + emit_move_insn (operands[0], XEXP (operands[1], 1)); } emit_insn (gen_addsi3 (operands[0], operands[0], operands[2])); DONE; @@ -849,7 +849,7 @@ [(set_attr "cc" "clobber,none_0hit")]) (define_insn "" - [(set (match_operand:QI 0 "general_operand" "=R,d") + [(set (match_operand:QI 0 "general_operand" "+R,d") (subreg:QI (and:SI (subreg:SI (match_dup 0) 0) (match_operand:SI 1 "const_int_operand" "i,i")) 0))] @@ -860,7 +860,7 @@ [(set_attr "cc" "clobber,set_znv")]) (define_insn "" - [(set (match_operand:QI 0 "general_operand" "=R,d") + [(set (match_operand:QI 0 "general_operand" "+R,d") (subreg:QI (ior:SI (subreg:SI (match_dup 0) 0) (match_operand:SI 1 "const_int_operand" "i,i")) 0))] @@ -1339,6 +1339,127 @@ [(set_attr "cc" "set_zn")]) ;; ---------------------------------------------------------------------- +;; FP INSTRUCTIONS +;; ---------------------------------------------------------------------- +;; +;; The mn103 series does not have floating point instructions, but since +;; FP values are held in integer regs, we can clear the high bit easily +;; which gives us an efficient inline floating point absolute value. +;; +;; Similarly for negation of a FP value. +;; + +(define_expand "absdf2" + [(set (match_operand:DF 0 "register_operand" "") + (abs:DF (match_operand:DF 1 "register_operand" "")))] + "" + " +{ + rtx target, result, insns; + + start_sequence (); + target = operand_subword (operands[0], 1, 1, DFmode); + result = expand_binop (SImode, and_optab, + operand_subword_force (operands[1], 1, DFmode), + GEN_INT(0x7fffffff), target, 0, OPTAB_WIDEN); + + if (result == 0) + abort (); + + if (result != target) + emit_move_insn (result, target); + + emit_move_insn (operand_subword (operands[0], 0, 1, DFmode), + operand_subword_force (operands[1], 0, DFmode)); + + insns = get_insns (); + end_sequence (); + + emit_no_conflict_block (insns, operands[0], operands[1], 0, 0); + DONE; +}") + +(define_expand "abssf2" + [(set (match_operand:SF 0 "register_operand" "") + (abs:SF (match_operand:SF 1 "register_operand" "")))] + "" + " +{ + rtx result; + rtx target; + + target = operand_subword_force (operands[0], 0, SFmode); + result = expand_binop (SImode, and_optab, + operand_subword_force (operands[1], 0, SFmode), + GEN_INT(0x7fffffff), target, 0, OPTAB_WIDEN); + if (result == 0) + abort (); + + if (result != target) + emit_move_insn (result, target); + + /* Make a place for REG_EQUAL. */ + emit_move_insn (operands[0], operands[0]); + DONE; +}") + + +(define_expand "negdf2" + [(set (match_operand:DF 0 "register_operand" "") + (neg:DF (match_operand:DF 1 "register_operand" "")))] + "" + " +{ + rtx target, result, insns; + + start_sequence (); + target = operand_subword (operands[0], 1, 1, DFmode); + result = expand_binop (SImode, xor_optab, + operand_subword_force (operands[1], 1, DFmode), + GEN_INT(0x80000000), target, 0, OPTAB_WIDEN); + + if (result == 0) + abort (); + + if (result != target) + emit_move_insn (result, target); + + emit_move_insn (operand_subword (operands[0], 0, 1, DFmode), + operand_subword_force (operands[1], 0, DFmode)); + + insns = get_insns (); + end_sequence (); + + emit_no_conflict_block (insns, operands[0], operands[1], 0, 0); + DONE; +}") + +(define_expand "negsf2" + [(set (match_operand:SF 0 "register_operand" "") + (neg:SF (match_operand:SF 1 "register_operand" "")))] + "" + " +{ + rtx result; + rtx target; + + target = operand_subword_force (operands[0], 0, SFmode); + result = expand_binop (SImode, xor_optab, + operand_subword_force (operands[1], 0, SFmode), + GEN_INT(0x80000000), target, 0, OPTAB_WIDEN); + if (result == 0) + abort (); + + if (result != target) + emit_move_insn (result, target); + + /* Make a place for REG_EQUAL. */ + emit_move_insn (operands[0], operands[0]); + DONE; +}") + + +;; ---------------------------------------------------------------------- ;; PROLOGUE/EPILOGUE ;; ---------------------------------------------------------------------- (define_expand "prologue" |