;; ----------------------------------------------------------------- ;; BIT FIELDS ;; ----------------------------------------------------------------- ;; The H8/300 has given 1/8th of its opcode space to bitfield ;; instructions so let's use them as well as we can. ;; You'll never believe all these patterns perform one basic action -- ;; load a bit from the source, optionally invert the bit, then store it ;; in the destination (which is known to be zero). ;; ;; Combine obviously need some work to better identify this situation and ;; canonicalize the form better. ;; ;; Inverted loads with a 16bit destination. ;; (define_insn "" [(set (match_operand:HI 0 "register_operand" "=&r") (zero_extract:HI (xor:HI (match_operand:HI 1 "register_operand" "r") (match_operand:HI 3 "const_int_operand" "n")) (const_int 1) (match_operand:HI 2 "const_int_operand" "n")))] "(TARGET_H8300SX) && (1 << INTVAL (operands[2])) == INTVAL (operands[3])" "sub.w %0,%0\;bild %Z2,%Y1\;bst #0,%X0" [(set_attr "length" "8")]) ;; ;; Normal loads with a 32bit destination. ;; (define_insn "*extzv_1_r_h8300hs" [(set (match_operand:SI 0 "register_operand" "=r,r") (zero_extract:SI (match_operand:SI 1 "register_operand" "?0,r") (const_int 1) (match_operand 2 "const_int_operand" "n,n")))] "INTVAL (operands[2]) < 16" { return output_simode_bld (0, operands); } [(set_attr "cc" "set_znv,set_znv") (set_attr "length" "8,6")]) ;; ;; Inverted loads with a 32bit destination. ;; (define_insn "*extzv_1_r_inv_h8300hs" [(set (match_operand:SI 0 "register_operand" "=r,r") (zero_extract:SI (xor:SI (match_operand:SI 1 "register_operand" "?0,r") (match_operand 3 "const_int_operand" "n,n")) (const_int 1) (match_operand 2 "const_int_operand" "n,n")))] "INTVAL (operands[2]) < 16 && (1 << INTVAL (operands[2])) == INTVAL (operands[3])" { return output_simode_bld (1, operands); } [(set_attr "cc" "set_znv,set_znv") (set_attr "length" "8,6")]) (define_expand "insv" [(set (zero_extract:HI (match_operand:HI 0 "general_operand" "") (match_operand:HI 1 "general_operand" "") (match_operand:HI 2 "general_operand" "")) (match_operand:HI 3 "general_operand" ""))] "TARGET_H8300SX" { if (GET_CODE (operands[1]) == CONST_INT && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[1]) <= 8 && INTVAL (operands[2]) >= 0 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 8 && memory_operand (operands[0], GET_MODE (operands[0]))) { /* If the source operand is zero, it's better to use AND rather than BFST. Likewise OR if the operand is all ones. */ if (GET_CODE (operands[3]) == CONST_INT) { HOST_WIDE_INT mask = (1 << INTVAL (operands[1])) - 1; if ((INTVAL (operands[3]) & mask) == 0) FAIL; if ((INTVAL (operands[3]) & mask) == mask) FAIL; } if (! bit_memory_operand (operands[0], GET_MODE (operands[0]))) { if (!can_create_pseudo_p ()) FAIL; operands[0] = replace_equiv_address (operands[0], force_reg (Pmode, XEXP (operands[0], 0))); } operands[3] = gen_lowpart (QImode, operands[3]); if (! operands[3]) FAIL; if (! register_operand (operands[3], QImode)) { if (!can_create_pseudo_p ()) FAIL; operands[3] = force_reg (QImode, operands[3]); } emit_insn (gen_bfst (adjust_address (operands[0], QImode, 0), operands[3], operands[1], operands[2])); DONE; } FAIL; }) (define_insn "" [(set (zero_extract:HI (match_operand:HI 0 "register_operand" "+r") (const_int 1) (match_operand:HI 1 "immediate_operand" "n")) (match_operand:HI 2 "register_operand" "r"))] "" "bld #0,%R2\;bst %Z1,%Y0 ; i1" [(set_attr "length" "4")]) (define_expand "extzv" [(set (match_operand:HI 0 "register_operand" "") (zero_extract:HI (match_operand:HI 1 "bit_operand" "") (match_operand:HI 2 "general_operand" "") (match_operand:HI 3 "general_operand" "")))] "TARGET_H8300SX" { if (GET_CODE (operands[2]) == CONST_INT && GET_CODE (operands[3]) == CONST_INT && INTVAL (operands[2]) <= 8 && INTVAL (operands[3]) >= 0 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 8 && memory_operand (operands[1], QImode)) { rtx temp; /* Optimize the case where we're extracting into a paradoxical subreg. It's only necessary to extend to the inner reg. */ if (GET_CODE (operands[0]) == SUBREG && subreg_lowpart_p (operands[0]) && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (operands[0]))) < GET_MODE_SIZE (GET_MODE (operands[0]))) && (GET_MODE_CLASS (GET_MODE (SUBREG_REG (operands[0]))) == MODE_INT)) operands[0] = SUBREG_REG (operands[0]); if (!can_create_pseudo_p ()) temp = gen_lowpart (QImode, operands[0]); else temp = gen_reg_rtx (QImode); if (! temp) FAIL; if (! bit_memory_operand (operands[1], QImode)) { if (!can_create_pseudo_p ()) FAIL; operands[1] = replace_equiv_address (operands[1], force_reg (Pmode, XEXP (operands[1], 0))); } emit_insn (gen_bfld (temp, operands[1], operands[2], operands[3])); convert_move (operands[0], temp, 1); DONE; } FAIL; }) ;; BAND, BOR, and BXOR patterns (define_insn "" [(set (match_operand:HI 0 "bit_operand" "=Ur") (match_operator:HI 4 "bit_operator" [(zero_extract:HI (match_operand:HI 1 "register_operand" "r") (const_int 1) (match_operand:HI 2 "immediate_operand" "n")) (match_operand:HI 3 "bit_operand" "0")]))] "" "bld %Z2,%Y1\;b%c4 #0,%R0\;bst #0,%R0; bl1" [(set_attr "length" "6")]) (define_insn "" [(set (match_operand:HI 0 "bit_operand" "=Ur") (match_operator:HI 5 "bit_operator" [(zero_extract:HI (match_operand:HI 1 "register_operand" "r") (const_int 1) (match_operand:HI 2 "immediate_operand" "n")) (zero_extract:HI (match_operand:HI 3 "register_operand" "r") (const_int 1) (match_operand:HI 4 "immediate_operand" "n"))]))] "" "bld %Z2,%Y1\;b%c5 %Z4,%Y3\;bst #0,%R0; bl3" [(set_attr "length" "6")]) (define_insn "bfld" [(set (match_operand:QI 0 "register_operand" "=r") (zero_extract:QI (match_operand:QI 1 "bit_memory_operand" "WU") (match_operand:QI 2 "immediate_operand" "n") (match_operand:QI 3 "immediate_operand" "n")))] "TARGET_H8300SX && INTVAL (operands[2]) + INTVAL (operands[3]) <= 8" { operands[2] = GEN_INT ((1 << (INTVAL (operands[2]) + INTVAL (operands[3]))) - (1 << INTVAL (operands[3]))); return "bfld %2,%1,%R0"; } [(set_attr "cc" "none_0hit") (set_attr "length_table" "bitfield")]) (define_insn "bfst" [(set (zero_extract:QI (match_operand:QI 0 "bit_memory_operand" "+WU") (match_operand:QI 2 "immediate_operand" "n") (match_operand:QI 3 "immediate_operand" "n")) (match_operand:QI 1 "register_operand" "r"))] "TARGET_H8300SX && INTVAL (operands[2]) + INTVAL (operands[3]) <= 8" { operands[2] = GEN_INT ((1 << (INTVAL (operands[2]) + INTVAL (operands[3]))) - (1 << INTVAL (operands[3]))); return "bfst %R1,%2,%0"; } [(set_attr "cc" "none_0hit") (set_attr "length_table" "bitfield")]) (define_expand "cstoreqi4" [(use (match_operator 1 "eqne_operator" [(match_operand:QI 2 "h8300_dst_operand" "") (match_operand:QI 3 "h8300_src_operand" "")])) (clobber (match_operand:HI 0 "register_operand"))] "TARGET_H8300SX" { h8300_expand_store (operands); DONE; }) (define_expand "cstorehi4" [(use (match_operator 1 "eqne_operator" [(match_operand:HI 2 "h8300_dst_operand" "") (match_operand:HI 3 "h8300_src_operand" "")])) (clobber (match_operand:HI 0 "register_operand"))] "TARGET_H8300SX" { h8300_expand_store (operands); DONE; }) (define_expand "cstoresi4" [(use (match_operator 1 "eqne_operator" [(match_operand:SI 2 "h8300_dst_operand" "") (match_operand:SI 3 "h8300_src_operand" "")])) (clobber (match_operand:HI 0 "register_operand"))] "TARGET_H8300SX" { h8300_expand_store (operands); DONE; }) (define_insn "*bstzhireg" [(set (match_operand:HI 0 "register_operand" "=r") (match_operator:HI 1 "eqne_operator" [(cc0) (const_int 0)]))] "TARGET_H8300SX" "mulu.w #0,%T0\;b%k1 .Lh8BR%=\;inc.w #1,%T0\\n.Lh8BR%=:" [(set_attr "cc" "clobber")]) (define_insn_and_split "*cmpstz" [(set (zero_extract:QI (match_operand:QI 0 "bit_memory_operand" "+WU,WU") (const_int 1) (match_operand:QI 1 "immediate_operand" "n,n")) (match_operator:QI 2 "eqne_operator" [(match_operand 3 "h8300_dst_operand" "r,rQ") (match_operand 4 "h8300_src_operand" "I,rQi")]))] "TARGET_H8300SX && (GET_MODE (operands[3]) == GET_MODE (operands[4]) || GET_CODE (operands[4]) == CONST_INT) && GET_MODE_CLASS (GET_MODE (operands[3])) == MODE_INT && GET_MODE_SIZE (GET_MODE (operands[3])) <= 4" "#" "reload_completed" [(set (cc0) (match_dup 5)) (set (zero_extract:QI (match_dup 0) (const_int 1) (match_dup 1)) (match_op_dup:QI 2 [(cc0) (const_int 0)]))] { operands[5] = gen_rtx_COMPARE (VOIDmode, operands[3], operands[4]); } [(set_attr "cc" "set_znv,compare")]) (define_insn "*bstz" [(set (zero_extract:QI (match_operand:QI 0 "bit_memory_operand" "+WU") (const_int 1) (match_operand:QI 1 "immediate_operand" "n")) (eq:QI (cc0) (const_int 0)))] "TARGET_H8300SX && reload_completed" "bstz %1,%0" [(set_attr "cc" "none_0hit") (set_attr "length_table" "unary")]) (define_insn "*bistz" [(set (zero_extract:QI (match_operand:QI 0 "bit_memory_operand" "+WU") (const_int 1) (match_operand:QI 1 "immediate_operand" "n")) (ne:QI (cc0) (const_int 0)))] "TARGET_H8300SX && reload_completed" "bistz %1,%0" [(set_attr "cc" "none_0hit") (set_attr "length_table" "unary")]) (define_insn_and_split "*cmpcondbset" [(set (match_operand:QI 0 "nonimmediate_operand" "=WU,WU") (if_then_else:QI (match_operator 1 "eqne_operator" [(match_operand 2 "h8300_dst_operand" "r,rQ") (match_operand 3 "h8300_src_operand" "I,rQi")]) (ior:QI (match_operand:QI 4 "bit_memory_operand" "0,0") (match_operand:QI 5 "single_one_operand" "n,n")) (match_dup 4)))] "TARGET_H8300SX" "#" "reload_completed" [(set (cc0) (match_dup 6)) (set (match_dup 0) (if_then_else:QI (match_op_dup 1 [(cc0) (const_int 0)]) (ior:QI (match_dup 4) (match_dup 5)) (match_dup 4)))] { operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]); } [(set_attr "cc" "set_znv,compare")]) (define_insn "*condbset" [(set (match_operand:QI 0 "bit_memory_operand" "=WU") (if_then_else:QI (match_operator:QI 2 "eqne_operator" [(cc0) (const_int 0)]) (ior:QI (match_operand:QI 3 "bit_memory_operand" "0") (match_operand:QI 1 "single_one_operand" "n")) (match_dup 3)))] "TARGET_H8300SX && reload_completed" "bset/%j2\t%V1,%0" [(set_attr "cc" "none_0hit") (set_attr "length_table" "logicb")]) (define_insn_and_split "*cmpcondbclr" [(set (match_operand:QI 0 "nonimmediate_operand" "=WU,WU") (if_then_else:QI (match_operator 1 "eqne_operator" [(match_operand 2 "h8300_dst_operand" "r,rQ") (match_operand 3 "h8300_src_operand" "I,rQi")]) (and:QI (match_operand:QI 4 "bit_memory_operand" "0,0") (match_operand:QI 5 "single_zero_operand" "n,n")) (match_dup 4)))] "TARGET_H8300SX" "#" "reload_completed" [(set (cc0) (match_dup 6)) (set (match_dup 0) (if_then_else:QI (match_op_dup 1 [(cc0) (const_int 0)]) (and:QI (match_dup 4) (match_dup 5)) (match_dup 4)))] { operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]); } [(set_attr "cc" "set_znv,compare")]) (define_insn "*condbclr" [(set (match_operand:QI 0 "bit_memory_operand" "=WU") (if_then_else:QI (match_operator:QI 2 "eqne_operator" [(cc0) (const_int 0)]) (and:QI (match_operand:QI 3 "bit_memory_operand" "0") (match_operand:QI 1 "single_zero_operand" "n")) (match_dup 3)))] "TARGET_H8300SX && reload_completed" "bclr/%j2\t%W1,%0" [(set_attr "cc" "none_0hit") (set_attr "length_table" "logicb")]) (define_insn_and_split "*cmpcondbsetreg" [(set (match_operand:QI 0 "nonimmediate_operand" "=WU,WU") (if_then_else:QI (match_operator 1 "eqne_operator" [(match_operand 2 "h8300_dst_operand" "r,rQ") (match_operand 3 "h8300_src_operand" "I,rQi")]) (ior:QI (match_operand:QI 4 "bit_memory_operand" "0,0") (ashift:QI (const_int 1) (match_operand:QI 5 "register_operand" "r,r"))) (match_dup 4)))] "TARGET_H8300SX" "#" "reload_completed" [(set (cc0) (match_dup 6)) (set (match_dup 0) (if_then_else:QI (match_op_dup 1 [(cc0) (const_int 0)]) (ior:QI (match_dup 4) (ashift:QI (const_int 1) (match_operand:QI 5 "register_operand" "r,r"))) (match_dup 4)))] { operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]); } [(set_attr "cc" "set_znv,compare")]) (define_insn "*condbsetreg" [(set (match_operand:QI 0 "bit_memory_operand" "=WU") (if_then_else:QI (match_operator:QI 2 "eqne_operator" [(cc0) (const_int 0)]) (ior:QI (match_operand:QI 3 "bit_memory_operand" "0") (ashift:QI (const_int 1) (match_operand:QI 1 "register_operand" "r"))) (match_dup 3)))] "TARGET_H8300SX && reload_completed" "bset/%j2\t%R1,%0" [(set_attr "cc" "none_0hit") (set_attr "length_table" "logicb")]) (define_insn_and_split "*cmpcondbclrreg" [(set (match_operand:QI 0 "nonimmediate_operand" "=WU,WU") (if_then_else:QI (match_operator 1 "eqne_operator" [(match_operand 2 "h8300_dst_operand" "r,rQ") (match_operand 3 "h8300_src_operand" "I,rQi")]) (and:QI (match_operand:QI 4 "bit_memory_operand" "0,0") (ashift:QI (const_int 1) (match_operand:QI 5 "register_operand" "r,r"))) (match_dup 4)))] "TARGET_H8300SX" "#" "reload_completed" [(set (cc0) (match_dup 6)) (set (match_dup 0) (if_then_else:QI (match_op_dup 1 [(cc0) (const_int 0)]) (and:QI (match_dup 4) (ashift:QI (const_int 1) (match_operand:QI 5 "register_operand" "r,r"))) (match_dup 4)))] { operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]); } [(set_attr "cc" "set_znv,compare")]) (define_insn "*condbclrreg" [(set (match_operand:QI 0 "bit_memory_operand" "=WU") (if_then_else:QI (match_operator:QI 2 "eqne_operator" [(cc0) (const_int 0)]) (and:QI (match_operand:QI 3 "bit_memory_operand" "0") (ashift:QI (const_int 1) (match_operand:QI 1 "register_operand" "r"))) (match_dup 3)))] "TARGET_H8300SX && reload_completed" "bclr/%j2\t%R1,%0" [(set_attr "cc" "none_0hit") (set_attr "length_table" "logicb")])