diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5eb9fc2f937..03b0d83ac7b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2003-01-07 Kazu Hirata + + * config/h8300/h8300.c (output_logical_op): Simplify and + optimize the handling of SImode. + * config/h8300/h8300.c (compute_logical_op_length): Update + accordingly. + * config/h8300/h8300.c (compute_logical_op_cc): Likewise. + 2003-01-07 Richard Sandiford * config/mips/mips.c (mips_va_arg): In the EABI code, apply the diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c index 3f2a358a35b..d7e521900bb 100644 --- a/gcc/config/h8300/h8300.c +++ b/gcc/config/h8300/h8300.c @@ -2061,6 +2061,13 @@ output_logical_op (mode, operands) /* The determinant of the algorithm. If we perform an AND, 0 affects a bit. Otherwise, 1 affects a bit. */ const unsigned HOST_WIDE_INT det = (code != AND) ? intval : ~intval; + /* Break up DET into pieces. */ + const unsigned HOST_WIDE_INT b0 = (det >> 0) & 0xff; + const unsigned HOST_WIDE_INT b1 = (det >> 8) & 0xff; + const unsigned HOST_WIDE_INT w0 = (det >> 0) & 0xffff; + const unsigned HOST_WIDE_INT w1 = (det >> 16) & 0xffff; + int lower_half_easy_p = 0; + int upper_half_easy_p = 0; /* The name of an insn. */ const char *opname; char insn_buf[100]; @@ -2108,20 +2115,25 @@ output_logical_op (mode, operands) } break; case SImode: - /* First, see if we can finish with one insn. + if (TARGET_H8300H || TARGET_H8300S) + { + /* Determine if the lower half can be taken care of in no more + than two bytes. */ + lower_half_easy_p = (b0 == 0 + || b1 == 0 + || (code != IOR && w0 == 0xffff)); - If code is either AND or XOR, we exclude two special cases, - 0xffffff00 and 0xffff00ff, because insns like sub.w or not.w - can do a better job. */ + /* Determine if the upper half can be taken care of in no more + than two bytes. */ + upper_half_easy_p = ((code != IOR && w1 == 0xffff) + || (code == AND && w1 == 0xff00)); + } + + /* Check if doing everything with one insn is no worse than + using multiple insns. */ if ((TARGET_H8300H || TARGET_H8300S) - && ((det & 0x0000ffff) != 0) - && ((det & 0xffff0000) != 0) - && (code == IOR || det != 0xffffff00) - && (code == IOR || det != 0xffff00ff) - && !(code == AND - && (det == 0xff00ffff - || (det & 0xffff00ff) == 0xff000000 - || (det & 0xffffff00) == 0xff000000))) + && w0 != 0 && w1 != 0 + && !(lower_half_easy_p && upper_half_easy_p)) { sprintf (insn_buf, "%s.l\t%%S2,%%S0", opname); output_asm_insn (insn_buf, operands); @@ -2214,6 +2226,13 @@ compute_logical_op_length (mode, operands) /* The determinant of the algorithm. If we perform an AND, 0 affects a bit. Otherwise, 1 affects a bit. */ const unsigned HOST_WIDE_INT det = (code != AND) ? intval : ~intval; + /* Break up DET into pieces. */ + const unsigned HOST_WIDE_INT b0 = (det >> 0) & 0xff; + const unsigned HOST_WIDE_INT b1 = (det >> 8) & 0xff; + const unsigned HOST_WIDE_INT w0 = (det >> 0) & 0xffff; + const unsigned HOST_WIDE_INT w1 = (det >> 16) & 0xffff; + int lower_half_easy_p = 0; + int upper_half_easy_p = 0; /* Insn length. */ unsigned int length = 0; @@ -2242,20 +2261,25 @@ compute_logical_op_length (mode, operands) } break; case SImode: - /* First, see if we can finish with one insn. + if (TARGET_H8300H || TARGET_H8300S) + { + /* Determine if the lower half can be taken care of in no more + than two bytes. */ + lower_half_easy_p = (b0 == 0 + || b1 == 0 + || (code != IOR && w0 == 0xffff)); - If code is either AND or XOR, we exclude two special cases, - 0xffffff00 and 0xffff00ff, because insns like sub.w or not.w - can do a better job. */ + /* Determine if the upper half can be taken care of in no more + than two bytes. */ + upper_half_easy_p = ((code != IOR && w1 == 0xffff) + || (code == AND && w1 == 0xff00)); + } + + /* Check if doing everything with one insn is no worse than + using multiple insns. */ if ((TARGET_H8300H || TARGET_H8300S) - && ((det & 0x0000ffff) != 0) - && ((det & 0xffff0000) != 0) - && (code == IOR || det != 0xffffff00) - && (code == IOR || det != 0xffff00ff) - && !(code == AND - && (det == 0xff00ffff - || (det & 0xffff00ff) == 0xff000000 - || (det & 0xffffff00) == 0xff000000))) + && w0 != 0 && w1 != 0 + && !(lower_half_easy_p && upper_half_easy_p)) { if (REG_P (operands[2])) length += 4; @@ -2336,6 +2360,13 @@ compute_logical_op_cc (mode, operands) /* The determinant of the algorithm. If we perform an AND, 0 affects a bit. Otherwise, 1 affects a bit. */ const unsigned HOST_WIDE_INT det = (code != AND) ? intval : ~intval; + /* Break up DET into pieces. */ + const unsigned HOST_WIDE_INT b0 = (det >> 0) & 0xff; + const unsigned HOST_WIDE_INT b1 = (det >> 8) & 0xff; + const unsigned HOST_WIDE_INT w0 = (det >> 0) & 0xffff; + const unsigned HOST_WIDE_INT w1 = (det >> 16) & 0xffff; + int lower_half_easy_p = 0; + int upper_half_easy_p = 0; /* Condition code. */ enum attr_cc cc = CC_CLOBBER; @@ -2351,20 +2382,25 @@ compute_logical_op_cc (mode, operands) } break; case SImode: - /* First, see if we can finish with one insn. + if (TARGET_H8300H || TARGET_H8300S) + { + /* Determine if the lower half can be taken care of in no more + than two bytes. */ + lower_half_easy_p = (b0 == 0 + || b1 == 0 + || (code != IOR && w0 == 0xffff)); - If code is either AND or XOR, we exclude two special cases, - 0xffffff00 and 0xffff00ff, because insns like sub.w or not.w - can do a better job. */ + /* Determine if the upper half can be taken care of in no more + than two bytes. */ + upper_half_easy_p = ((code != IOR && w1 == 0xffff) + || (code == AND && w1 == 0xff00)); + } + + /* Check if doing everything with one insn is no worse than + using multiple insns. */ if ((TARGET_H8300H || TARGET_H8300S) - && ((det & 0x0000ffff) != 0) - && ((det & 0xffff0000) != 0) - && (code == IOR || det != 0xffffff00) - && (code == IOR || det != 0xffff00ff) - && !(code == AND - && (det == 0xff00ffff - || (det & 0xffff00ff) == 0xff000000 - || (det & 0xffffff00) == 0xff000000))) + && w0 != 0 && w1 != 0 + && !(lower_half_easy_p && upper_half_easy_p)) { cc = CC_SET_ZNV; }