h8300-protos.h: Add a prototype for emit_logical_op.

* 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.

From-SVN: r45272
This commit is contained in:
Kazu Hirata 2001-08-29 18:18:15 +00:00 committed by Kazu Hirata
parent 6e9c53b489
commit 366a7b2715
4 changed files with 268 additions and 159 deletions

View File

@ -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

View File

@ -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));

View File

@ -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

View File

@ -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