diff --git a/gcc/config/h8300/h8300.md b/gcc/config/h8300/h8300.md index 282710efedc..4c8f512d2d9 100644 --- a/gcc/config/h8300/h8300.md +++ b/gcc/config/h8300/h8300.md @@ -48,6 +48,11 @@ ;; would be more efficient time and space-wise. Similar sequences ;; can be found using bit-set insns dec, etc +;; Many logical operations should have "bit" variants if only one +;; bit is going to be operated on. + +;; Should be HI & SImode tstXX insns which test one bit using btst. + (define_attr "type" "branch,bcs,return,call,arith,move,float,multi" (const_string "arith")) @@ -943,60 +948,86 @@ DONE; }") -;; ??? Should have a bclr case here also. -;; ??? This should be symmetric with iorhi3. - (define_insn "andhi3" - [(set (match_operand:HI 0 "register_operand" "=r") - (and:HI (match_operand:HI 1 "register_operand" "%0") - (match_operand:HI 2 "nonmemory_operand" "rn")))] + [(set (match_operand:HI 0 "register_operand" "=r,r") + (and:HI (match_operand:HI 1 "register_operand" "%0,0") + (match_operand:HI 2 "nonmemory_operand" "J,rn")))] "" "* { if (GET_CODE (operands[2]) == CONST_INT) { int i = INTVAL (operands[2]); + if ((i & 0x00ff) != 0x00ff) output_asm_insn (\"and %s2,%s0\", operands); if ((i & 0xff00) != 0xff00) output_asm_insn (\"and %t2,%t0\", operands); return \"\"; } + if (TARGET_H8300H) + return \"and.w %T2,%T0\"; return \"and %s2,%s0\;and %t2,%t0;\"; }" - [(set_attr "type" "multi") - (set_attr "length" "4") - (set_attr "cc" "clobber")]) - -;; ??? There is an iorsi3 for TARGET_H8300. Should we have andsi3? + [(set_attr "type" "arith,multi") + (set_attr "length" "2,4") + (set_attr "cc" "clobber,clobber")]) (define_insn "andsi3" [(set (match_operand:SI 0 "register_operand" "=r,r") (and:SI (match_operand:SI 1 "register_operand" "%0,0") - (match_operand:SI 2 "nonmemory_operand" "r,i")))] - "TARGET_H8300H" - "@ - and %S2,%S0 - and %S2,%S0" - [(set_attr "type" "arith") - (set_attr "length" "4,6") - (set_attr "cc" "set")]) + (match_operand:SI 2 "nonmemory_operand" "J,rn")))] + "" + "* +{ + if (GET_CODE (operands[2]) == CONST_INT) + { + int i = INTVAL (operands[2]); + + /* ??? If we used e0..e7, then we could sub.w eX,eX to + clear the high word if (i & 0xffff0000) == 0. */ + + /* The h8300h can't do byte-wise operations on the + upper 16bits of 32bit registers. However, if + those bits aren't going to change, then we can + work on the low-order bits. */ + if (TARGET_H8300H + && (i & 0xffff0000) != 0xffff0000) + return \"and.l %S2,%S0\"; + + if ((i & 0x000000ff) != 0x000000ff) + output_asm_insn (\"and %w2,%w0\", operands); + if ((i & 0x0000ff00) != 0x0000ff00) + output_asm_insn (\"and %x2,%x0\", operands); + if ((i & 0x00ff0000) != 0x00ff0000) + output_asm_insn (\"and %y2,%y0\", operands); + if ((i & 0xff000000) != 0xff000000) + output_asm_insn (\"and %z2,%z0\", operands); + return \"\"; + } + if (TARGET_H8300H) + return \"and.l %S2,%S0\"; + return \"and %w2,%w0\;and %x2,%x0\;and %y2,%y0\;and %z2,%z0\;\"; +}" + [(set_attr "type" "arith,multi") + (set_attr "length" "2,8") + (set_attr "cc" "clobber,clobber")]) ;; ---------------------------------------------------------------------- ;; OR INSTRUCTIONS ;; ---------------------------------------------------------------------- (define_insn "iorqi3_internal" - [(set (match_operand:QI 0 "bit_operand" "=U,r") + [(set (match_operand:QI 0 "bit_operand" "=r,U") (ior:QI (match_operand:QI 1 "bit_operand" "%0,0") - (match_operand:QI 2 "nonmemory_operand" "P,rn")))] + (match_operand:QI 2 "nonmemory_operand" "rn,P")))] "register_operand (operands[0], QImode) || p_operand (operands[2], QImode)" "@ - bset %V2,%R0 - or %X2,%X0" + or %X2,%X0 + bset %V2,%R0" [(set_attr "type" "arith") - (set_attr "length" "4,2") - (set_attr "cc" "none_0hit,set")]) + (set_attr "length" "2,4") + (set_attr "cc" "set,none_0hit")]) (define_expand "iorqi3" [(set (match_operand:QI 0 "bit_operand" "=r,U") @@ -1009,9 +1040,6 @@ DONE; }") -;; ??? Should have a bset case here also. -;; ??? This should be symmetric with andhi3. - (define_insn "iorhi3" [(set (match_operand:HI 0 "general_operand" "=r,r") (ior:HI (match_operand:HI 1 "general_operand" "%0,0") @@ -1019,60 +1047,60 @@ "" "* { - if (TARGET_H8300) + if (GET_CODE (operands[2]) == CONST_INT) { - if (GET_CODE (operands[2]) == CONST_INT) - { - int i = INTVAL (operands[2]); - if ((i & 0x00ff) != 0) - output_asm_insn (\"or %s2,%s0\", operands); - if ((i & 0xff00) != 0) - output_asm_insn (\"or %t2,%t0\", operands); - return \"\"; - } - return \"or %s2,%s0\;or %t2,%t0; %2 or2\"; - } - else - { - return \"or %S2,%S0\"; + int i = INTVAL (operands[2]); + + if ((i & 0x00ff) != 0) + output_asm_insn (\"or %s2,%s0\", operands); + if ((i & 0xff00) != 0) + output_asm_insn (\"or %t2,%t0\", operands); + return \"\"; } + if (TARGET_H8300H) + return \"or.w %T2,%T0\"; + return \"or %s2,%s0\;or %t2,%t0; %2 or2\"; }" - [(set_attr "type" "multi") + [(set_attr "type" "arith,multi") (set_attr "length" "2,4") (set_attr "cc" "clobber,clobber")]) (define_insn "iorsi3" - [(set (match_operand:SI 0 "register_operand" "=r") - (ior:SI (match_operand:SI 1 "register_operand" "%0") - (match_operand:SI 2 "nonmemory_operand" "ri")))] + [(set (match_operand:SI 0 "register_operand" "=r,r") + (ior:SI (match_operand:SI 1 "register_operand" "%0,0") + (match_operand:SI 2 "nonmemory_operand" "J,rn")))] "" "* { - if (TARGET_H8300) + if (GET_CODE (operands[2]) == CONST_INT) { - if (GET_CODE (operands[2]) == CONST_INT) - { - int i = INTVAL (operands[2]); - if ((i & 0x000000ff) != 0) - output_asm_insn (\"or %w2,%w0\", operands); - if ((i & 0x0000ff00) != 0) - output_asm_insn (\"or %x2,%x0\", operands); - if ((i & 0x00ff0000) != 0) - output_asm_insn (\"or %y2,%y0\", operands); - if ((i & 0xff000000) != 0) - output_asm_insn (\"or %z2,%z0\", operands); - return \"\"; - } - return \"or %w2,%w0\;or %x2,%x0\;or %y2,%y0\;or %z2,%z0\;\"; - } - else - { - return \"or %S2,%S0\"; + int i = INTVAL (operands[2]); + + /* The h8300h can't do byte-wise operations on the + upper 16bits of 32bit registers. However, if + those bits aren't going to change, then we can + work on the low-order bits. */ + if (TARGET_H8300H + && (i & 0xffff0000) != 0x00000000) + return \"or.l %S2,%S0\"; + + if ((i & 0x000000ff) != 0) + output_asm_insn (\"or %w2,%w0\", operands); + if ((i & 0x0000ff00) != 0) + output_asm_insn (\"or %x2,%x0\", operands); + if ((i & 0x00ff0000) != 0) + output_asm_insn (\"or %y2,%y0\", operands); + if ((i & 0xff000000) != 0) + output_asm_insn (\"or %z2,%z0\", operands); + return \"\"; } + if (TARGET_H8300H) + return \"or.l %S2,%S0\"; + return \"or %w2,%w0\;or %x2,%x0\;or %y2,%y0\;or %z2,%z0\;\"; }" - [(set_attr "type" "multi") - (set_attr "length" "8") - (set_attr "cc" "clobber")]) + [(set_attr "type" "arith,multi") + (set_attr "length" "2,8") + (set_attr "cc" "clobber,clobber")]) ;; ---------------------------------------------------------------------- ;; XOR INSTRUCTIONS @@ -1101,37 +1129,67 @@ DONE; }") -;; ??? This should be symmetric with andhi3. - (define_insn "xorhi3" - [(set (match_operand:HI 0 "register_operand" "=r") - (xor:HI (match_operand:HI 1 "general_operand" "%0") - (match_operand:HI 2 "nonmemory_operand" "rn")))] + [(set (match_operand:HI 0 "register_operand" "=r,r") + (xor:HI (match_operand:HI 1 "general_operand" "%0,0") + (match_operand:HI 2 "nonmemory_operand" "J,rn")))] "" "* { - if (TARGET_H8300) - return \"xor %s2,%s0\;xor %t2,%t0\"; - else - return \"xor %S2,%S0\"; -}" - [(set_attr "type" "multi") - (set_attr "length" "4") - (set_attr "cc" "clobber")]) + if (GET_CODE (operands[2]) == CONST_INT) + { + int i = INTVAL (operands[2]); -;; ??? There is an iorsi3 for TARGET_H8300. Should we have xorsi3? + if ((i & 0x00ff) != 0) + output_asm_insn (\"xor %s2,%s0\", operands); + if ((i & 0xff00) != 0) + output_asm_insn (\"xor %t2,%t0\", operands); + return \"\"; + } + if (TARGET_H8300H) + return \"xor.w %T2,%T0\"; + return \"xor %s2,%s0\;xor %t2,%t0\"; +}" + [(set_attr "type" "arith,multi") + (set_attr "length" "2,4") + (set_attr "cc" "clobber,clobber")]) (define_insn "xorsi3" [(set (match_operand:SI 0 "register_operand" "=r,r") (xor:SI (match_operand:SI 1 "register_operand" "%0,0") - (match_operand:SI 2 "nonmemory_operand" "r,i")))] - "TARGET_H8300H" - "@ - xor %S2,%S0 - xor %S2,%S0" - [(set_attr "type" "arith") - (set_attr "length" "4,6") - (set_attr "cc" "set")]) + (match_operand:SI 2 "nonmemory_operand" "J,rn")))] + "" + "* +{ + if (GET_CODE (operands[2]) == CONST_INT) + { + int i = INTVAL (operands[2]); + + /* The h8300h can't do byte-wise operations on the + upper 16bits of 32bit registers. However, if + those bits aren't going to change, then we can + work on the low-order bits. */ + if (TARGET_H8300H + && (i & 0xffff0000) != 0x00000000) + return \"xor.l %S2,%S0\"; + + if ((i & 0x000000ff) != 0) + output_asm_insn (\"xor %w2,%w0\", operands); + if ((i & 0x0000ff00) != 0) + output_asm_insn (\"xor %x2,%x0\", operands); + if ((i & 0x00ff0000) != 0) + output_asm_insn (\"xor %y2,%y0\", operands); + if ((i & 0xff000000) != 0) + output_asm_insn (\"xor %z2,%z0\", operands); + return \"\"; + } + if (TARGET_H8300H) + return \"xor.l %S2,%S0\"; + return \"xor %w2,%w0\;xor %x2,%x0\;xor %y2,%y0\;xor %z2,%z0\;\"; +}" + [(set_attr "type" "arith,multi") + (set_attr "length" "2,8") + (set_attr "cc" "clobber,clobber")]) ;; ---------------------------------------------------------------------- ;; NEGATION INSTRUCTIONS @@ -1233,8 +1291,11 @@ return \"not %T0\"; }" [(set_attr "type" "arith") - (set_attr "length" "4") - (set_attr "cc" "clobber")]) + (set_attr "cc" "clobber") + (set (attr "length") + (if_then_else (eq (symbol_ref "TARGET_H8300H") (const_int 0)) + (const_int 8) + (const_int 2)))]) (define_insn "one_cmplsi2" [(set (match_operand:SI 0 "register_operand" "=r") @@ -1252,7 +1313,7 @@ (set (attr "length") (if_then_else (eq (symbol_ref "TARGET_H8300H") (const_int 0)) (const_int 8) - (const_int 4)))]) + (const_int 2)))]) ;; ----------------------------------------------------------------------