--- gcc/config/h8300/h8300.c.orig 2008-03-06 14:59:50.000000000 +0530 +++ gcc/config/h8300/h8300.c 2008-03-06 15:02:17.000000000 +0530 @@ -1422,12 +1422,19 @@ print_operand (FILE *file, rtx x, int co goto def; break; case 'V': - bitint = exact_log2 (INTVAL (x) & 0xff); + if ((exact_log2 ((bitint >> 8) & 0xff)) == -1) + bitint = exact_log2 (bitint & 0xff); + else + bitint = exact_log2 ((bitint >> 8) & 0xff); gcc_assert (bitint >= 0); fprintf (file, "#%d", bitint); break; case 'W': - bitint = exact_log2 ((~INTVAL (x)) & 0xff); + bitint = ((~INTVAL (x)) & 0xffff); + if ((exact_log2 ((bitint >> 8) & 0xff)) == -1) + bitint = exact_log2 (bitint & 0xff); + else + bitint = exact_log2 ((bitint >> 8) & 0xff); gcc_assert (bitint >= 0); fprintf (file, "#%d", bitint); break; @@ -3120,17 +3127,45 @@ output_logical_op (enum machine_mode mod /* The name of an insn. */ const char *opname; char insn_buf[100]; - + int true_for_bit_opcode = 0; + switch (code) { case AND: - opname = "and"; + if ((TARGET_H8300H || TARGET_H8300S) + && (mode == HImode) + && (GET_CODE (operands[2]) == CONST_INT) + && (exact_log2 ((~intval) & 0xffff) != -1)) + { + true_for_bit_opcode = 1; + opname = "bclr"; + } + else + opname = "and"; break; case IOR: - opname = "or"; + if ((TARGET_H8300H || TARGET_H8300S) + && (mode == HImode) + && (GET_CODE (operands[2]) == CONST_INT) + && (exact_log2 (intval & 0xffff) != -1)) + { + true_for_bit_opcode = 2; + opname = "bset"; + } + else + opname = "or"; break; case XOR: - opname = "xor"; + if ((TARGET_H8300H || TARGET_H8300S) + && (mode == HImode) + && (GET_CODE (operands[2]) == CONST_INT) + && (exact_log2 (intval & 0xffff) != -1)) + { + true_for_bit_opcode = 3; + opname = "bnot"; + } + else + opname = "xor"; break; default: gcc_unreachable (); @@ -3152,14 +3187,42 @@ output_logical_op (enum machine_mode mod /* Take care of the lower byte. */ if (b0 != 0) { - sprintf (insn_buf, "%s\t%%s2,%%s0", opname); + switch(true_for_bit_opcode) + { + case 0: + sprintf (insn_buf, "%s\t%%s2,%%s0", opname); + break; + case 1: + sprintf (insn_buf, "%s\t%%W2,%%s0", opname); + break; + case 2: + sprintf (insn_buf, "%s\t%%V2,%%s0", opname); + break; + case 3: + sprintf (insn_buf, "%s\t%%V2,%%s0", opname); + break; + } output_asm_insn (insn_buf, operands); } /* Take care of the upper byte. */ if (b1 != 0) { - sprintf (insn_buf, "%s\t%%t2,%%t0", opname); - output_asm_insn (insn_buf, operands); + switch(true_for_bit_opcode) + { + case 0: + sprintf (insn_buf, "%s\t%%t2,%%t0", opname); + break; + case 1: + sprintf (insn_buf, "%s\t%%W2,%%t0", opname); + break; + case 2: + sprintf (insn_buf, "%s\t%%V2,%%t0", opname); + break; + case 3: + sprintf (insn_buf, "%s\t%%V2,%%t0", opname); + break; + } + output_asm_insn (insn_buf, operands); } } break; @@ -3300,7 +3363,8 @@ compute_logical_op_length (enum machine_ int upper_half_easy_p = 0; /* Insn length. */ unsigned int length = 0; - + int true_for_bit_opcode = 0; + switch (mode) { case HImode: @@ -3314,13 +3378,33 @@ compute_logical_op_length (enum machine_ } else { - /* Take care of the lower byte. */ + if ((TARGET_H8300H || TARGET_H8300S) + && ((((GET_CODE (operands[3]) == XOR) || (GET_CODE (operands[3]) == IOR)) + && (GET_CODE (operands[2]) == CONST_INT) + && (exact_log2 (INTVAL (operands[2]) & 0xffff) != -1)) + || (GET_CODE (operands[3]) == AND + && (GET_CODE (operands[2]) == CONST_INT) + && (exact_log2 ((~INTVAL (operands[2])) & 0xffff) != -1)))) + { + true_for_bit_opcode = 1; + } + /* Take care of the lower byte. */ if (b0 != 0) - length += 2; - + { + if (true_for_bit_opcode) + length += 1; + else + length += 2; + } + /* Take care of the upper byte. */ if (b1 != 0) - length += 2; + { + if (true_for_bit_opcode) + length += 1; + else + length += 2; + } } break; case SImode: --- gcc/testsuite/gcc.target/h8300/bnot_bset_bclr.c 1970-01-01 05:30:00.000000000 +0530 +++ gcc/testsuite/gcc.target/h8300/bnot_bset_bclr.c 2008-03-06 17:18:44.000000000 +0530 @@ -0,0 +1,25 @@ +/* Testcase to check generation of the 3 specific bit manipulation instructions, + "BNOT #imm3,Rn", "BSET #imm,Rn", "BCLR #imm,Rn" */ + +/* { dg-do compile {target h8300*-*-*}} */ +/* { dg-options "" } */ +/* { dg-skip-if "" { "h8300*-*-*" } "*" "-mh -ms -ms2600 -msx" } */ +/* { dg-final { scan-assembler "bnot"} } */ +/* { dg-final { scan-assembler "bset"} } */ +/* { dg-final { scan-assembler "bclr"} } */ + +int main() +{ + int x = 1024 + 512 + 128 + 64; + + x ^= 1024; /* BNOT instead of XOR should be generated */ + x ^= 64; /* BNOT instead of XOR should be generated */ + + x |= 1024; /* BSET instead of OR should be generated */ + x |= 64; /* BSET instead of OR should be generated */ + + x &= 0xfdff; /* BCLR instead of AND should be generated */ + x &= 0xffbf; /* BCLR instead of AND should be generated */ + + return (0); +}