diff options
-rw-r--r-- | gcc/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/config/h8300/h8300-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/h8300/h8300.c | 144 | ||||
-rw-r--r-- | gcc/config/h8300/h8300.md | 270 |
4 files changed, 268 insertions, 159 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2d5043f2..ffc4ad5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2001-08-29 Kazu Hirata <kazu@hxi.com> + + * config/h8300/h8300-protos.h: Add a prototype for + emit_logical_op. + * config/h8300/h8300.c (emit_logical_op): New. + * config/h8300/h8300.md (andhi3): Use emit_logical_op. + (andsi3): Likewise. + (iorhi3): Likewise. + (iorsi3): Likewise. + (xorhi3): Likewise. + (xorsi3): Likewise. + 2001-08-29 John David Anglin <dave@hiauly1.hia.nrc.ca> * pa.c (move_operand): Cast GET_MODE_SIZE results to HOST_WIDE_INT for diff --git a/gcc/config/h8300/h8300-protos.h b/gcc/config/h8300/h8300-protos.h index 4841d07..36997e1 100644 --- a/gcc/config/h8300/h8300-protos.h +++ b/gcc/config/h8300/h8300-protos.h @@ -37,6 +37,7 @@ extern void print_operand PARAMS ((FILE *, rtx, int)); extern void final_prescan_insn PARAMS ((rtx, rtx *, int)); extern int do_movsi PARAMS ((rtx[])); extern void notice_update_cc PARAMS ((rtx, rtx)); +extern const char *output_logical_op PARAMS ((enum machine_mode, int, rtx *)); extern int expand_a_shift PARAMS ((enum machine_mode, int, rtx[])); extern int expand_a_rotate PARAMS ((int, rtx[])); extern int fix_bit_operand PARAMS ((rtx *, int, enum rtx_code)); diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c index 61c255f..3c95e57 100644 --- a/gcc/config/h8300/h8300.c +++ b/gcc/config/h8300/h8300.c @@ -1601,6 +1601,150 @@ bit_operator (x, mode) || code == IOR); } +const char * +output_logical_op (mode, code, operands) + enum machine_mode mode; + int code; + rtx *operands; +{ + /* Pretend that every byte is affected if both operands are registers. */ + unsigned HOST_WIDE_INT intval = + (unsigned HOST_WIDE_INT) ((GET_CODE (operands[2]) == CONST_INT) + ? INTVAL (operands[2]) : 0x55555555); + /* The determinant of the algorithm. If we perform an AND, 0 + affects a bit. Otherwise, 1 affects a bit. */ + unsigned HOST_WIDE_INT det = (code != AND) ? intval : ~intval; + /* The name of an insn. */ + const char *opname; + char insn_buf[100]; + + switch (code) + { + case AND: + opname = "and"; + break; + case IOR: + opname = "or"; + break; + case XOR: + opname = "xor"; + break; + default: + abort (); + } + + switch (mode) + { + case HImode: + /* First, see if we can finish with one insn. */ + if ((TARGET_H8300H || TARGET_H8300S) + && ((det & 0x00ff) != 0) + && ((det & 0xff00) != 0)) + { + sprintf (insn_buf, "%s.w\t%%T2,%%T0", opname); + output_asm_insn (insn_buf, operands); + } + else + { + /* Take care of the lower byte. */ + if ((det & 0x00ff) != 0) + { + sprintf (insn_buf, "%s\t%%s2,%%s0", opname); + output_asm_insn (insn_buf, operands); + } + /* Take care of the upper byte. */ + if ((det & 0xff00) != 0) + { + sprintf (insn_buf, "%s\t%%t2,%%t0", opname); + output_asm_insn (insn_buf, operands); + } + } + break; + case SImode: + /* First, see if we can finish with one insn. + + If code is either AND or XOR, we exclude two special cases, + 0xffffff00 and 0xffff00ff, because insns like sub.w or neg.w + can do a better job. */ + if ((TARGET_H8300H || TARGET_H8300S) + && ((det & 0x0000ffff) != 0) + && ((det & 0xffff0000) != 0) + && (code == IOR || det != 0xffffff00) + && (code == IOR || det != 0xffff00ff)) + { + sprintf (insn_buf, "%s.l\t%%S2,%%S0", opname); + output_asm_insn (insn_buf, operands); + } + else + { + /* Take care of the lower and upper words individually. For + each word, we try different methods in the order of + + 1) the special insn (in case of AND or XOR), + 2) the word-wise insn, and + 3) The byte-wise insn. */ + if ((TARGET_H8300H || TARGET_H8300S) + && ((det & 0x0000ffff) == 0x0000ffff) + && code != IOR) + output_asm_insn ((code == AND) + ? "sub.w\t%f0,%f0" : "neg.w\t%f0", + operands); + else if ((TARGET_H8300H || TARGET_H8300S) + && ((det & 0x000000ff) != 0) + && ((det & 0x0000ff00) != 0)) + { + sprintf (insn_buf, "%s.w\t%%f2,%%f0", opname); + output_asm_insn (insn_buf, operands); + } + else + { + if ((det & 0x000000ff) != 0) + { + sprintf (insn_buf, "%s\t%%w2,%%w0", opname); + output_asm_insn (insn_buf, operands); + } + if ((det & 0x0000ff00) != 0) + { + sprintf (insn_buf, "%s\t%%x2,%%x0", opname); + output_asm_insn (insn_buf, operands); + } + } + + if ((TARGET_H8300H || TARGET_H8300S) + && ((det & 0xffff0000) == 0xffff0000) + && code != IOR) + output_asm_insn ((code == AND) + ? "sub.w\t%e0,%e0" : "neg.w\t%e0", + operands); + else if (TARGET_H8300H || TARGET_H8300S) + { + if ((det & 0xffff0000) != 0) + { + sprintf (insn_buf, "%s.w\t%%e2,%%e0", opname); + output_asm_insn (insn_buf, operands); + } + } + else + { + if ((det & 0x00ff0000) != 0) + { + sprintf (insn_buf, "%s\t%%y2,%%y0", opname); + output_asm_insn (insn_buf, operands); + } + if ((det & 0xff000000) != 0) + { + sprintf (insn_buf, "%s\t%%z2,%%z0", opname); + output_asm_insn (insn_buf, operands); + } + } + } + break; + default: + abort (); + } + return ""; +} + /* Shifts. We devote a fair bit of code to getting efficient shifts since we can only diff --git a/gcc/config/h8300/h8300.md b/gcc/config/h8300/h8300.md index b8a9b5e..d9d5496 100644 --- a/gcc/config/h8300/h8300.md +++ b/gcc/config/h8300/h8300.md @@ -988,83 +988,55 @@ DONE; }") -(define_insn "andhi3" +(define_expand "andhi3" + [(set (match_operand:HI 0 "register_operand" "") + (and:HI (match_operand:HI 1 "register_operand" "") + (match_operand:HI 2 "nonmemory_operand" "")))] + "" + "") + +(define_insn "" [(set (match_operand:HI 0 "register_operand" "=r") (and:HI (match_operand:HI 1 "register_operand" "%0") (match_operand:HI 2 "nonmemory_operand" "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 || TARGET_H8300S) - return \"and.w %T2,%T0\"; - return \"and %s2,%s0\;and %t2,%t0;\"; -}" + "TARGET_H8300" + "* return output_logical_op (HImode, AND, operands);" [(set_attr "length" "4") (set_attr "cc" "clobber")]) -(define_insn "andsi3" +(define_insn "" + [(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" "r,n")))] + "TARGET_H8300H || TARGET_H8300S" + "* return output_logical_op (HImode, AND, operands);" + [(set_attr "length" "2,4") + (set_attr "cc" "set_znv,clobber")]) + +(define_expand "andsi3" + [(set (match_operand:SI 0 "register_operand" "") + (and:SI (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "nonmemory_operand" "")))] + "" + "") + +(define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (and:SI (match_operand:SI 1 "register_operand" "%0") (match_operand:SI 2 "nonmemory_operand" "rn")))] - "" - "* -{ - if (GET_CODE (operands[2]) == CONST_INT) - { - int i = INTVAL (operands[2]); - int upper_cleared, lower_cleared; - - /* The h8300h can't do byte-wise operations on the - upper 16bits of 32bit registers. However, if - those bits aren't going to change, or they're - going to be zero'd out, then we can work on the - low-order bits. */ - if ((TARGET_H8300H || TARGET_H8300S) - && ((i & 0xffff0000) != 0xffff0000 - || (i & 0xffff0000) == 0x00000000)) - return \"and.l %S2,%S0\"; - - lower_cleared = 0; - if ((i & 0x0000ffff) == 0x00000000) - { - output_asm_insn (\"sub.w %f0,%f0\", operands); - lower_cleared = 1; - } - - upper_cleared = 0; - if ((i & 0xffff0000) == 0x00000000) - { - output_asm_insn (\"sub.w %e0,%e0\", operands); - upper_cleared = 1; - } - - if ((i & 0x000000ff) != 0x000000ff && !lower_cleared) - output_asm_insn (\"and %w2,%w0\", operands); - if ((i & 0x0000ff00) != 0x0000ff00 && !lower_cleared) - output_asm_insn (\"and %x2,%x0\", operands); - if ((i & 0x00ff0000) != 0x00ff0000 && !upper_cleared) - output_asm_insn (\"and %y2,%y0\", operands); - if ((i & 0xff000000) != 0xff000000 && !upper_cleared) - output_asm_insn (\"and %z2,%z0\", operands); - return \"\"; - } - if (TARGET_H8300H || TARGET_H8300S) - return \"and.l %S2,%S0\"; - return \"and %w2,%w0\;and %x2,%x0\;and %y2,%y0\;and %z2,%z0\"; -}" + "TARGET_H8300" + "* return output_logical_op (SImode, AND, operands);" [(set_attr "length" "8") (set_attr "cc" "clobber")]) +(define_insn "" + [(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,n")))] + "TARGET_H8300H || TARGET_H8300S" + "* return output_logical_op (SImode, AND, operands);" + [(set_attr "length" "4,6") + (set_attr "cc" "set_znv,clobber")]) ;; ---------------------------------------------------------------------- ;; OR INSTRUCTIONS @@ -1093,66 +1065,56 @@ DONE; }") -(define_insn "iorhi3" +(define_expand "iorhi3" [(set (match_operand:HI 0 "general_operand" "=r,r") (ior:HI (match_operand:HI 1 "general_operand" "%0,0") (match_operand:HI 2 "general_operand" "J,rn")))] "" - "* -{ - 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 \"\"; - } - if (TARGET_H8300H || TARGET_H8300S) - return \"or.w %T2,%T0\"; - return \"or %s2,%s0\;or %t2,%t0; %2 or2\"; -}" +(define_insn "" + [(set (match_operand:HI 0 "general_operand" "=r,r") + (ior:HI (match_operand:HI 1 "general_operand" "%0,0") + (match_operand:HI 2 "general_operand" "J,rn")))] + "TARGET_H8300" + "* return output_logical_op (HImode, IOR, operands);" [(set_attr "length" "2,4") (set_attr "cc" "clobber,clobber")]) -(define_insn "iorsi3" +(define_insn "" + [(set (match_operand:HI 0 "general_operand" "=r,r,r") + (ior:HI (match_operand:HI 1 "general_operand" "%0,0,0") + (match_operand:HI 2 "general_operand" "J,r,n")))] + "TARGET_H8300H || TARGET_H8300S" + "* return output_logical_op (HImode, IOR, operands);" + [(set_attr "length" "2,2,4") + (set_attr "cc" "clobber,set_znv,clobber")]) + +(define_expand "iorsi3" + [(set (match_operand:SI 0 "register_operand" "") + (ior:SI (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "nonmemory_operand" "")))] + "" + "") + +(define_insn "" [(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 (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 || TARGET_H8300S) - && (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 || TARGET_H8300S) - return \"or.l %S2,%S0\"; - return \"or %w2,%w0\;or %x2,%x0\;or %y2,%y0\;or %z2,%z0\"; -}" + "TARGET_H8300" + "* return output_logical_op (SImode, IOR, operands);" [(set_attr "length" "2,8") (set_attr "cc" "clobber,clobber")]) +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r,r,r") + (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0") + (match_operand:SI 2 "nonmemory_operand" "J,r,n")))] + "TARGET_H8300H || TARGET_H8300S" + "* return output_logical_op (SImode, IOR, operands);" + [(set_attr "length" "2,4,6") + (set_attr "cc" "clobber,set_znv,clobber")]) + ;; ---------------------------------------------------------------------- ;; XOR INSTRUCTIONS ;; ---------------------------------------------------------------------- @@ -1180,65 +1142,55 @@ DONE; }") -(define_insn "xorhi3" +(define_expand "xorhi3" + [(set (match_operand:HI 0 "register_operand" "") + (xor:HI (match_operand:HI 1 "general_operand" "") + (match_operand:HI 2 "nonmemory_operand" "")))] + "" + "") + +(define_insn "" [(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 (GET_CODE (operands[2]) == CONST_INT) - { - int i = INTVAL (operands[2]); - - 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 || TARGET_H8300S) - return \"xor.w %T2,%T0\"; - return \"xor %s2,%s0\;xor %t2,%t0\"; -}" + "TARGET_H8300" + "* return output_logical_op (HImode, XOR, operands);" [(set_attr "length" "2,4") (set_attr "cc" "clobber,clobber")]) -(define_insn "xorsi3" +(define_insn "" + [(set (match_operand:HI 0 "register_operand" "=r,r,r") + (xor:HI (match_operand:HI 1 "general_operand" "%0,0,0") + (match_operand:HI 2 "nonmemory_operand" "J,r,n")))] + "TARGET_H8300H || TARGET_H8300S" + "* return output_logical_op (HImode, XOR, operands);" + [(set_attr "length" "2,2,4") + (set_attr "cc" "clobber,set_znv,clobber")]) + +(define_expand "xorsi3" + [(set (match_operand:SI 0 "register_operand" "") + (xor:SI (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "nonmemory_operand" "")))] + "" + "") + +(define_insn "" [(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" "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 || TARGET_H8300S) - && (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 || TARGET_H8300S) - return \"xor.l %S2,%S0\"; - return \"xor %w2,%w0\;xor %x2,%x0\;xor %y2,%y0\;xor %z2,%z0\"; -}" + "TARGET_H8300" + "* return output_logical_op (SImode, XOR, operands);" [(set_attr "length" "2,8") (set_attr "cc" "clobber,clobber")]) + +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r,r,r") + (xor:SI (match_operand:SI 1 "register_operand" "%0,0,0") + (match_operand:SI 2 "nonmemory_operand" "J,r,n")))] + "TARGET_H8300H || TARGET_H8300S" + "* return output_logical_op (SImode, XOR, operands);" + [(set_attr "length" "2,4,6") + (set_attr "cc" "clobber,set_znv,clobber")]) ;; ---------------------------------------------------------------------- ;; NEGATION INSTRUCTIONS |