diff options
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/config/alpha/alpha-protos.h | 2 | ||||
-rw-r--r-- | gcc/config/alpha/alpha.c | 50 | ||||
-rw-r--r-- | gcc/config/alpha/alpha.md | 55 |
4 files changed, 67 insertions, 49 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3e7b3d8..f95b9ba 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2000-11-21 Richard Henderson <rth@redhat.com> + + * config/alpha/alpha.c (alpha_split_tfmode_frobsign): New. + * config/alpha/alpha-protos.h: Declare it. + * config/alpha/alpha.md (abstf_internal): Use it. + (negtf_internal): Likewise. + (andnotdi3): Unstar the name. + (movtf_internal): Add o/G alternative. + 2000-11-21 Zack Weinberg <zack@wolery.stanford.edu> * stringpool.c (stringpool_statistics): Also report number and diff --git a/gcc/config/alpha/alpha-protos.h b/gcc/config/alpha/alpha-protos.h index d70ac7f..c12b92d 100644 --- a/gcc/config/alpha/alpha-protos.h +++ b/gcc/config/alpha/alpha-protos.h @@ -90,6 +90,8 @@ extern int alpha_split_conditional_move PARAMS ((enum rtx_code, rtx, rtx, extern void alpha_emit_xfloating_arith PARAMS ((enum rtx_code, rtx[])); extern void alpha_emit_xfloating_cvt PARAMS ((enum rtx_code, rtx[])); extern void alpha_split_tfmode_pair PARAMS ((rtx[])); +extern void alpha_split_tfmode_frobsign PARAMS ((rtx[], + rtx (*)(rtx, rtx, rtx))); extern void alpha_expand_unaligned_load PARAMS ((rtx, rtx, HOST_WIDE_INT, HOST_WIDE_INT, int)); extern void alpha_expand_unaligned_store PARAMS ((rtx, rtx, HOST_WIDE_INT, diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index b4707f2..d16c58c6 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -2357,6 +2357,10 @@ alpha_emit_xfloating_cvt (code, operands) operands[1])); } +/* Split a TFmode OP[1] into DImode OP[2,3] and likewise for + OP[0] into OP[0,1]. Naturally, output operand ordering is + little-endian. */ + void alpha_split_tfmode_pair (operands) rtx operands[4]; @@ -2391,6 +2395,52 @@ alpha_split_tfmode_pair (operands) else abort (); } + +/* Implement negtf2 or abstf2. Op0 is destination, op1 is source, + op2 is a register containing the sign bit, operation is the + logical operation to be performed. */ + +void +alpha_split_tfmode_frobsign (operands, operation) + rtx operands[3]; + rtx (*operation) PARAMS ((rtx, rtx, rtx)); +{ + rtx high_bit = operands[2]; + rtx scratch; + int move; + + alpha_split_tfmode_pair (operands); + + /* Detect three flavours of operand overlap. */ + move = 1; + if (rtx_equal_p (operands[0], operands[2])) + move = 0; + else if (rtx_equal_p (operands[1], operands[2])) + { + if (rtx_equal_p (operands[0], high_bit)) + move = 2; + else + move = -1; + } + + if (move < 0) + emit_move_insn (operands[0], operands[2]); + + /* ??? If the destination overlaps both source tf and high_bit, then + assume source tf is dead in its entirety and use the other half + for a scratch register. Otherwise "scratch" is just the proper + destination register. */ + scratch = operands[move < 2 ? 1 : 3]; + + emit_insn ((*operation) (scratch, high_bit, operands[3])); + + if (move > 0) + { + emit_move_insn (operands[0], operands[2]); + if (move > 1) + emit_move_insn (operands[1], scratch); + } +} /* Use ext[wlq][lh] as the Architecture Handbook describes for extracting unaligned data: diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md index eb1c2e5..028ce48 100644 --- a/gcc/config/alpha/alpha.md +++ b/gcc/config/alpha/alpha.md @@ -1187,7 +1187,7 @@ "zapnot %1,15,%0" [(set_attr "type" "shift")]) -(define_insn "*andnot" +(define_insn "andnotdi3" [(set (match_operand:DI 0 "register_operand" "=r") (and:DI (not:DI (match_operand:DI 1 "reg_or_8bit_operand" "rI")) (match_operand:DI 2 "reg_or_0_operand" "rJ")))] @@ -1876,35 +1876,12 @@ (define_insn_and_split "*abstf_internal" [(set (match_operand:TF 0 "register_operand" "=r") (abs:TF (match_operand:TF 1 "reg_or_fp0_operand" "rG"))) - (use (match_operand:DI 2 "register_operand" "=r"))] + (use (match_operand:DI 2 "register_operand" "r"))] "TARGET_HAS_XFLOATING_LIBS" "#" "&& reload_completed" [(const_int 0)] - " -{ - int move; - rtx tmp; - - alpha_split_tfmode_pair (operands); - - move = 1; - if (rtx_equal_p (operands[0], operands[2])) - move = 0; - else if (rtx_equal_p (operands[1], operands[2])) - move = -1; - - if (move < 0) - emit_move_insn (operands[0], operands[2]); - - tmp = gen_rtx_NOT (DImode, operands[4]); - tmp = gen_rtx_AND (DImode, tmp, operands[3]); - emit_insn (gen_rtx_SET (VOIDmode, operands[1], tmp)); - - if (move > 0) - emit_move_insn (operands[0], operands[2]); - DONE; -}") + "alpha_split_tfmode_frobsign (operands, gen_andnotdi3); DONE;") (define_insn "negsf2" [(set (match_operand:SF 0 "register_operand" "=f") @@ -1937,32 +1914,12 @@ (define_insn_and_split "*negtf_internal" [(set (match_operand:TF 0 "register_operand" "=r") (neg:TF (match_operand:TF 1 "reg_or_fp0_operand" "rG"))) - (use (match_operand:DI 2 "register_operand" "=r"))] + (use (match_operand:DI 2 "register_operand" "r"))] "TARGET_HAS_XFLOATING_LIBS" "#" "&& reload_completed" [(const_int 0)] - " -{ - int move; - - alpha_split_tfmode_pair (operands); - - move = 1; - if (rtx_equal_p (operands[0], operands[2])) - move = 0; - else if (rtx_equal_p (operands[1], operands[2])) - move = -1; - - if (move < 0) - emit_move_insn (operands[0], operands[2]); - - emit_insn (gen_xordi3 (operands[1], operands[3], operands[4])); - - if (move > 0) - emit_move_insn (operands[0], operands[2]); - DONE; -}") + "alpha_split_tfmode_frobsign (operands, gen_xordi3); DONE;") (define_insn "*addsf_ieee" [(set (match_operand:SF 0 "register_operand" "=&f") @@ -4595,7 +4552,7 @@ (define_insn_and_split "*movtf_internal" [(set (match_operand:TF 0 "nonimmediate_operand" "=r,o") - (match_operand:TF 1 "input_operand" "roG,r"))] + (match_operand:TF 1 "input_operand" "roG,rG"))] "register_operand (operands[0], TFmode) || reg_or_fp0_operand (operands[1], TFmode)" "#" |