;; 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.
+;; (and (logical op) (const_int X))
+;; If const_int only specifies a few bits (like a single byte in a 4 byte
+;; operation, then it's more efficient to only apply the and and logical_op
+;; to the bits we care about.
+
+;; Some of the extend instructions accept a general_operand_src, which
+;; allows all the normal memory addressing modes. The length computations
+;; don't take this into account. The lengths in the MD file should be
+;; "worst case" and then be adjusted to their correct values by
+;; h8300_adjust_insn_length.
;; On the h8300h, adds/subs operate on the 32bit "er" registers. Right
;; now GCC doesn't expose the "e" half to the compiler, so using add/subs
;; There's currently no way to have a insv/extzv expander for the h8/300h
;; because word_mode is different for the h8/300 and h8/300h.
+;; Shifts/rotates by small constants should be handled by special
+;; patterns so we get the length and cc status correct.
+
+;; Bitfield operations no longer accept memory operands. We need
+;; to add variants which operate on memory back to the MD.
+
;; ??? Implement remaining bit ops available on the h8300
(define_attr "type" "branch,arith"
[(set (attr "length") (if_then_else (eq_attr "cpu" "h8300") (const_int 2) (const_int 4)))
(set_attr "cc" "set")])
-(define_insn "movqi_internal"
+(define_insn ""
[(set (match_operand:QI 0 "general_operand_dst" "=r,r,<,r,o")
(match_operand:QI 1 "general_operand_src" "I,r>,r,io,r"))]
"register_operand (operands[0],QImode)
[(set (attr "length") (if_then_else (eq_attr "cpu" "h8300") (const_int 2) (const_int 4)))
(set_attr "cc" "set")])
-(define_insn "movhi_internal"
+(define_insn ""
[(set (match_operand:HI 0 "general_operand_dst" "=r,r,<,r,o")
(match_operand:HI 1 "general_operand_src" "I,r>,r,io,r"))]
"register_operand (operands[0],HImode)
[(set (cc0)
(compare:HI (match_operand:HI 0 "register_operand" "r")
(match_operand:HI 1 "register_operand" "r")))]
- "!TARGET_H8300H"
+ "TARGET_H8300"
"cmp.w %T1,%T0"
[(set_attr "length" "2")
(set_attr "cc" "compare")])
(define_insn ""
[(set (cc0)
- (compare:HI (match_operand:HI 0 "register_operand" "r")
- (match_operand:HI 1 "nonmemory_operand" "ri")))]
+ (compare:HI (match_operand:HI 0 "register_operand" "r,r")
+ (match_operand:HI 1 "nonmemory_operand" "r,i")))]
"TARGET_H8300H"
"cmp.w %T1,%T0"
- [(set_attr "length" "2")
- (set_attr "cc" "compare")])
+ [(set_attr "length" "2,4")
+ (set_attr "cc" "compare,compare")])
(define_insn "cmpsi"
[(set (cc0)
- (compare:SI (match_operand:SI 0 "register_operand" "r")
- (match_operand:SI 1 "nonmemory_operand" "ri")))]
+ (compare:SI (match_operand:SI 0 "register_operand" "r,r")
+ (match_operand:SI 1 "nonmemory_operand" "r,i")))]
"TARGET_H8300H"
"cmp.l %S1,%S0"
- [(set_attr "length" "2")
- (set_attr "cc" "compare")])
+ [(set_attr "length" "2,6")
+ (set_attr "cc" "compare,compare")])
\f
;; ----------------------------------------------------------------------
;; ADD INSTRUCTIONS
"@
add %w2,%w0\;addx %x2,%x0\;addx %y2,%y0\;addx %z2,%z0
add.w %f2,%f0\;addx %y2,%y0\;addx %z2,%z0
- mov %f1,%f0\;mov %e1,%e0\;add.w %f2,%f0\;addx %y2,%y0\;addx %z2,%z0"
- [(set_attr "length" "8,6,20")
+ mov.w %f1,%f0\;mov.w %e1,%e0\;add.w %f2,%f0\;addx %y2,%y0\;addx %z2,%z0"
+ [(set_attr "length" "8,6,10")
(set_attr "cc" "clobber")])
(define_insn "addsi_h8300h"
"TARGET_H8300"
"@
sub.w %T2,%T0
- add.b %E2,%s0\;addx %F2,%t0 ; -%0"
+ add.b %E2,%s0\;addx %F2,%t0"
[(set_attr "length" "2,4")
(set_attr "cc" "set_zn_c0,clobber")])
;; AND INSTRUCTIONS
;; ----------------------------------------------------------------------
-(define_insn "andqi3_internal"
+(define_insn ""
[(set (match_operand:QI 0 "bit_operand" "=r,U")
(and:QI (match_operand:QI 1 "bit_operand" "%0,0")
(match_operand:QI 2 "nonmemory_operand" "rn,O")))]
(set_attr "cc" "set,none_0hit")])
(define_expand "andqi3"
- [(set (match_operand:QI 0 "bit_operand" "=r,U")
- (and:QI (match_operand:QI 1 "bit_operand" "%0,0")
- (match_operand:QI 2 "nonmemory_operand" "rn,O")))]
+ [(set (match_operand:QI 0 "bit_operand" "")
+ (and:QI (match_operand:QI 1 "bit_operand" "")
+ (match_operand:QI 2 "nonmemory_operand" "")))]
""
"
{
}")
(define_insn "andhi3"
- [(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")))]
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (and:HI (match_operand:HI 1 "register_operand" "%0")
+ (match_operand:HI 2 "nonmemory_operand" "rn")))]
""
"*
{
return \"and.w %T2,%T0\";
return \"and %s2,%s0\;and %t2,%t0;\";
}"
- [(set_attr "length" "2,4")
- (set_attr "cc" "clobber,clobber")])
+ [(set_attr "length" "4")
+ (set_attr "cc" "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" "J,rn")))]
+ [(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]);
-
- /* ??? If we used e0..e7, then we could sub.w eX,eX to
- clear the high word if (i & 0xffff0000) == 0. */
+ 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, then we can
- work on the low-order bits. */
+ 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
- && (i & 0xffff0000) != 0xffff0000)
+ && ((i & 0xffff0000) != 0xffff0000
+ || (i & 0xffff0000) == 0x00000000))
return \"and.l %S2,%S0\";
- if ((i & 0x000000ff) != 0x000000ff)
+ 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)
+ if ((i & 0x0000ff00) != 0x0000ff00 && !lower_cleared)
output_asm_insn (\"and %x2,%x0\", operands);
- if ((i & 0x00ff0000) != 0x00ff0000)
+ if ((i & 0x00ff0000) != 0x00ff0000 && !upper_cleared)
output_asm_insn (\"and %y2,%y0\", operands);
- if ((i & 0xff000000) != 0xff000000)
+ if ((i & 0xff000000) != 0xff000000 && !upper_cleared)
output_asm_insn (\"and %z2,%z0\", operands);
return \"\";
}
return \"and.l %S2,%S0\";
return \"and %w2,%w0\;and %x2,%x0\;and %y2,%y0\;and %z2,%z0\;\";
}"
- [(set_attr "length" "2,8")
- (set_attr "cc" "clobber,clobber")])
+ [(set_attr "length" "8")
+ (set_attr "cc" "clobber")])
+
;; ----------------------------------------------------------------------
;; OR INSTRUCTIONS
;; ----------------------------------------------------------------------
-(define_insn "iorqi3_internal"
+(define_insn ""
[(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" "rn,P")))]
;; XOR INSTRUCTIONS
;; ----------------------------------------------------------------------
-(define_insn "xorqi3_internal"
+(define_insn ""
[(set (match_operand:QI 0 "bit_operand" "=r,U")
(xor:QI (match_operand:QI 1 "bit_operand" "%0,0")
(match_operand:QI 2 "nonmemory_operand" "rn,P")))]
[(set_attr "cc" "clobber")
(set (attr "length")
(if_then_else (eq (symbol_ref "TARGET_H8300H") (const_int 0))
- (const_int 8)
+ (const_int 4)
(const_int 2)))])
(define_insn "one_cmplsi2"
;; This is a define expand, because pointers may be either 16 or 32 bits.
(define_expand "indirect_jump"
- [(set (pc) (match_operand 0 "jump_address_operand" "Vr"))]
+ [(set (pc) (match_operand 0 "jump_address_operand" ""))]
""
"")
(define_insn "indirect_jump_h8300"
- [(set (pc) (match_operand:HI 0 "jump_address_operand" "V,r"))]
+ [(set (pc) (match_operand:HI 0 "jump_address_operand" "Vr"))]
"TARGET_H8300"
- "@
- jmp @%0
- jmp @%0"
+ "jmp @%0"
[(set_attr "cc" "none")
(set_attr "length" "2")])
(define_insn "indirect_jump_h8300h"
- [(set (pc) (match_operand:SI 0 "jump_address_operand" "V,r"))]
+ [(set (pc) (match_operand:SI 0 "jump_address_operand" "Vr"))]
"TARGET_H8300H"
- "@
- jmp @%0
- jmp @%0"
+ "jmp @%0"
[(set_attr "cc" "none")
(set_attr "length" "2")])
}
}")
-
-;; I don't know why, but if I try to simplify extendhisi2 in the
-;; natural way, I get about a 2X code bloat on the h8300 without
-;; optimization, and a small bloat with optimization. Weird.
+;; This is used when not optimizing. It avoids severe code explosion
+;; due to poor register allocation.
(define_expand "zero_extendhisi2_h8300"
[(set (reg:HI 1) (match_operand:HI 1 "general_operand" ""))
(set (reg:SI 0) (zero_extend:SI (reg:HI 1)))
}
}")
-;; I don't know why, but if I try to simplify extendhisi2 in the
-;; natural way, I get about a 2X code bloat on the h8300 without
-;; optimization, and a small bloat with optimization. Weird.
+;; This is used when not optimizing. It avoids severe code explosion
+;; due to poor register allocation.
(define_expand "extendhisi2_h8300"
[(set (reg:HI 1) (match_operand:HI 1 "general_operand" ""))
(set (reg:SI 0) (sign_extend:SI (reg:HI 1)))
""
"if (expand_a_shift (QImode, LSHIFTRT, operands)) DONE;else FAIL;")
-;; WARNING: The constraints on the scratch register say one is not needed
-;; for constant shifts of 1,2,3,4. Emit_a_shift() must know this.
-
-(define_insn "shiftbyn_QI"
+(define_insn ""
[(set (match_operand:QI 0 "register_operand" "=r,r")
(match_operator:QI 3 "nshift_operator"
[ (match_operand:QI 1 "register_operand" "0,0")
- (match_operand:QI 2 "nonmemory_operand" "IKM,rn")]))
+ (match_operand:QI 2 "nonmemory_operand" "KM,rn")]))
(clobber (match_scratch:QI 4 "=X,&r"))]
""
"* return emit_a_shift (insn, operands);"
[(set_attr "length" "20")
-;; ??? We'd like to indicate that cc is set here, and it is for simple shifts.
-;; However, for cases that loop or are done in pieces, cc does not contain
-;; what we want. Emit_a_shift is free to tweak cc_status as desired.
(set_attr "cc" "clobber")])
;; HI BIT SHIFTS
""
"if (expand_a_shift (HImode, ASHIFTRT, operands)) DONE;else FAIL;")
-;; WARNING: The constraints on the scratch register say one is not needed
-;; for constant shifts of 1,2,3,4. Emit_a_shift() must know this.
-
-(define_insn "shiftbyn_HI"
+(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r,r")
(match_operator:HI 3 "nshift_operator"
[ (match_operand:HI 1 "register_operand" "0,0")
- (match_operand:QI 2 "nonmemory_operand" "IKM,rn")]))
+ (match_operand:QI 2 "nonmemory_operand" "KM,rn")]))
(clobber (match_scratch:QI 4 "=X,&r"))]
""
"* return emit_a_shift (insn, operands);"
[(set_attr "length" "20")
-;; ??? We'd like to indicate that cc is set here, and it is for simple shifts.
-;; However, for cases that loop or are done in pieces, cc does not contain
-;; what we want. Emit_a_shift is free to tweak cc_status as desired.
(set_attr "cc" "clobber")])
;; SI BIT SHIFTS
""
"if (expand_a_shift (SImode, ASHIFTRT, operands)) DONE;else FAIL;")
-;; WARNING: The constraints on the scratch register say one is not needed
-;; for constant shifts of 1,2. Emit_a_shift() must know this.
-
-(define_insn "shiftbyn_SI"
+(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r,r")
(match_operator:SI 3 "nshift_operator"
[ (match_operand:SI 1 "register_operand" "0,0")
- (match_operand:QI 2 "nonmemory_operand" "IK,rn")]))
+ (match_operand:QI 2 "nonmemory_operand" "K,rn")]))
(clobber (match_scratch:QI 4 "=X,&r"))]
""
"* return emit_a_shift (insn, operands);"
[(set_attr "length" "20")
-;; ??? We'd like to indicate that cc is set here, and it is for simple shifts.
-;; However, for cases that loop or are done in pieces, cc does not contain
-;; what we want. Emit_a_shift is free to tweak cc_status as desired.
(set_attr "cc" "clobber")])
\f
;; -----------------------------------------------------------------