All registers that the compiler knows about must be given numbers,
even those that are not normally considered general registers.
- Reg 8 does not correspond to any hardware register, but instead
+ Reg 9 does not correspond to any hardware register, but instead
appears in the RTL as an argument pointer prior to reload, and is
eliminated during reloading in favor of either the stack or frame
pointer. */
-#define FIRST_PSEUDO_REGISTER 9
+#define FIRST_PSEUDO_REGISTER 10
/* 1 for registers that have pervasive standard uses
and are not available for the register allocator. */
#define FIXED_REGISTERS \
- { 0, 0, 0, 0, 0, 0, 0, 1, 1}
+ { 0, 0, 0, 0, 0, 0, 0, 1, 0, 1}
/* 1 for registers not available across function calls.
These must include the FIXED_REGISTERS and also any
h8 destroys r0,r1,r2,r3. */
#define CALL_USED_REGISTERS \
- { 1, 1, 1, 1, 0, 0, 0, 1, 1 }
+ { 1, 1, 1, 1, 0, 0, 0, 1, 1, 1 }
#define REG_ALLOC_ORDER \
- { 2, 3, 0, 1, 4, 5, 6, 7, 8}
+ { 2, 3, 0, 1, 4, 5, 6, 8, 7, 9}
+
+#define CONDITIONAL_REGISTER_USAGE \
+{ \
+ if (!TARGET_H8300S) \
+ fixed_regs[8] = call_used_regs[8] = 1;\
+}
/* Return number of consecutive hard regs needed starting at reg REGNO
to hold something of mode MODE.
This is ordinarily the length in words of a value of mode MODE
- but can be less for certain modes in special long registers. */
+ but can be less for certain modes in special long registers.
+
+ We pretend the MAC register is 32bits -- we don't have any data
+ types on the H8 series to handle more than 32bits. */
#define HARD_REGNO_NREGS(REGNO, MODE) \
- ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+ ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
/* Value is 1 if hard register REGNO can hold a value of machine-mode
MODE.
#define HARD_REGNO_MODE_OK(REGNO, MODE) \
(TARGET_H8300 ? (((REGNO)&1)==0) || (MODE==HImode) || (MODE==QImode) \
- : 1)
+ : REGNO == 8 ? MODE == SImode : 1)
/* Value is 1 if it is a good idea to tie two pseudo registers
when one has mode MODE1 and one has mode MODE2.
#define FRAME_POINTER_REQUIRED 0
/* Base register for access to arguments of the function. */
-#define ARG_POINTER_REGNUM 8
+#define ARG_POINTER_REGNUM 9
/* Register in which static-chain is passed to a function. */
#define STATIC_CHAIN_REGNUM 3
class that represents their union. */
enum reg_class {
- NO_REGS, GENERAL_REGS, ALL_REGS, LIM_REG_CLASSES
+ NO_REGS, GENERAL_REGS, MAC_REGS, ALL_REGS, LIM_REG_CLASSES
};
#define N_REG_CLASSES (int) LIM_REG_CLASSES
/* Give names of register classes as strings for dump file. */
#define REG_CLASS_NAMES \
-{ "NO_REGS", "GENERAL_REGS", "ALL_REGS", "LIM_REGS" }
+{ "NO_REGS", "GENERAL_REGS", "MAC_REGS", "ALL_REGS", "LIM_REGS" }
/* Define which registers fit in which classes.
This is an initializer for a vector of HARD_REG_SET
#define REG_CLASS_CONTENTS \
{ 0, /* No regs */ \
0x0ff, /* GENERAL_REGS */ \
- 0x1ff, /* ALL_REGS */ \
+ 0x100, /* MAC_REGS */ \
+ 0x3ff, /* ALL_REGS */ \
}
/* The same information, inverted:
Return the class number of the smallest class containing
reg number REGNO. This could be a conditional expression
- or could index an array.
-
- ??? What about the ARG_POINTER_REGISTER? */
+ or could index an array. */
-#define REGNO_REG_CLASS(REGNO) GENERAL_REGS
+#define REGNO_REG_CLASS(REGNO) (REGNO != 8 ? GENERAL_REGS : MAC_REGS)
/* The class value for index registers, and the one for base regs. */
#define INDEX_REG_CLASS NO_REGS
#define BASE_REG_CLASS GENERAL_REGS
-/* Get reg_class from a letter such as appears in the machine description. */
+/* Get reg_class from a letter such as appears in the machine description.
+
+ 'a' is the MAC register. */
-#define REG_CLASS_FROM_LETTER(C) (NO_REGS)
+#define REG_CLASS_FROM_LETTER(C) ((C) == 'a' ? MAC_REGS : NO_REGS)
/* The letters I, J, K, L, M, N, O, P in a register constraint string
can be used to stand for particular ranges of immediate operands.
so define REGISTER_MOVE_COST to be > 2 so that reload never
shortcuts. */
-#define REGISTER_MOVE_COST(CLASS1, CLASS2) 3
+#define REGISTER_MOVE_COST(CLASS1, CLASS2) \
+ (CLASS1 == MAC_REGS || CLASS2 == MAC_REGS ? 6 : 3)
\f
/* Stack layout; function entry, exit and calling. */
#define REGNO_OK_FOR_INDEX_P(regno) 0
#define REGNO_OK_FOR_BASE_P(regno) \
- ((regno) < FIRST_PSEUDO_REGISTER || reg_renumber[regno] >= 0)
+ (((regno) < FIRST_PSEUDO_REGISTER && regno != 8) || reg_renumber[regno] >= 0)
\f
/* Maximum number of registers that can appear in a valid memory address. */
This sequence is indexed by compiler's hard-register-number (see above). */
#define REGISTER_NAMES \
-{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "sp", "ap"}
+{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "sp", "mac", "ap"}
#define ADDITIONAL_REGISTER_NAMES { { "r7", 7 } }
;; none_0hit - insn does not affect cc but it does modify operand 0
;; This attribute is used to keep track of when operand 0 changes.
;; See the description of NOTICE_UPDATE_CC for more info.
-;; set - insn sets flags z,n. v,c are set to 0.
+;; set - insn sets flags z,n,v. c are set to 0.
;; (c may not really be set to 0 but that's ok, we don't need it anyway).
;; set_zn_c0 - insn sets z,n to usable values. v is unknown. c may or may not
;; be known (if it isn't that's ok, we don't need it anyway).
return \"push.l %S1\";
}"
[(set (attr "length") (if_then_else (eq_attr "cpu" "h8300") (const_int 2) (const_int 4)))
- (set_attr "cc" "set")])
+ (set_attr "cc" "set_zn_c0")])
(define_insn ""
[(set (match_operand:QI 0 "general_operand_dst" "=r,r,<,r,r,m")
[(const_int 2) (const_int 2) (const_int 2) (const_int 2)
(if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))
(if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))])
- (set_attr "cc" "set_zn_c0,set,set,set,set,set")])
+ (set_attr "cc" "set,set_zn_c0,set_zn_c0,set_zn_c0,set_zn_c0,set_zn_c0")])
(define_expand "movqi"
[(set (match_operand:QI 0 "general_operand_dst" "")
[(set_attr_alternative "length"
[(const_int 2) (const_int 2) (const_int 2)
(if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))])
- (set_attr "cc" "set_zn_c0,set,set,set")])
+ (set_attr "cc" "set,set_zn_c0,set_zn_c0,set_zn_c0")])
;; movhi
return \"push.l %S1\";
}"
[(set (attr "length") (if_then_else (eq_attr "cpu" "h8300") (const_int 2) (const_int 4)))
- (set_attr "cc" "set")])
+ (set_attr "cc" "set_zn_c0")])
(define_insn ""
[(set (match_operand:HI 0 "general_operand_dst" "=r,r,<,r,r,m")
[(const_int 2) (const_int 2) (const_int 2) (const_int 4)
(if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))
(if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))])
- (set_attr "cc" "set_zn_c0,set,set,set,set,set")])
+ (set_attr "cc" "set,set_zn_c0,set_zn_c0,set_zn_c0,set_zn_c0,set_zn_c0")])
(define_expand "movhi"
[(set (match_operand:HI 0 "general_operand_dst" "")
[(set_attr_alternative "length"
[(const_int 2) (const_int 2) (const_int 4)
(if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))])
- (set_attr "cc" "set_zn_c0,set,set,set")])
+ (set_attr "cc" "set,set_zn_c0,set_zn_c0,set_zn_c0")])
;; movsi
[(set_attr "length" "4,4,8,8,4,4")
(set_attr "cc" "clobber")])
-(define_insn "movsi_h8300h"
- [(set (match_operand:SI 0 "general_operand_dst" "=r,r,r,m,<,r")
- (match_operand:SI 1 "general_operand_src" "I,r,im,r,r,>"))]
- "(TARGET_H8300H || TARGET_H8300S)
+(define_insn "movsi_h8300hs"
+ [(set (match_operand:SI 0 "general_operand_dst" "=r,r,r,m,<,r,*a,*a,r")
+ (match_operand:SI 1 "general_operand_src" "I,r,im,r,r,>,I,r,*a"))]
+ "(TARGET_H8300S || TARGET_H8300H)
&& (register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode))"
"*
{
if (which_alternative == 0)
return \"sub.l %S0,%S0\";
+ if (which_alternative == 6)
+ return \"clrmac\";
+ if (which_alternative == 7)
+ return \"clrmac\;ldmac %1,macl\";
+ if (which_alternative == 8)
+ return \"stmac macl,%0\";
if (GET_CODE (operands[1]) == CONST_INT)
{
int val = INTVAL (operands[1]);
}
return \"mov.l %S1,%S0\";
}"
- [(set_attr "length" "2,2,10,10,4,4")
- (set_attr "cc" "set_zn_c0,set,set,set,set,set")])
+ [(set_attr "length" "2,2,10,10,4,4,2,6,4")
+ (set_attr "cc" "set,set_zn_c0,set_zn_c0,set_zn_c0,set_zn_c0,set_zn_c0,none_0hit,none_0hit,set_zn_c0")])
(define_insn "movsf_h8300h"
[(set (match_operand:SF 0 "general_operand_dst" "=r,r,r,m,<,r")
mov.l %S1,%S0
mov.l %S1,%S0"
[(set_attr "length" "2,2,10,10,4,4")
- (set_attr "cc" "set_zn_c0,set,set,set,set,set")])
+ (set_attr "cc" "set,set_zn_c0,set_zn_c0,set_zn_c0,set_zn_c0,set_zn_c0")])
\f
;; ----------------------------------------------------------------------
;; TEST INSTRUCTIONS
""
"mov.b %X0,%X0"
[(set_attr "length" "2")
- (set_attr "cc" "set")])
+ (set_attr "cc" "set_zn_c0")])
(define_insn "tsthi"
[(set (cc0) (match_operand:HI 0 "register_operand" "r"))]
""
"mov.w %T0,%T0"
[(set_attr "length" "2")
- (set_attr "cc" "set")])
+ (set_attr "cc" "set_zn_c0")])
(define_insn "tstsi"
[(set (cc0) (match_operand:SI 0 "register_operand" "r"))]
"TARGET_H8300H || TARGET_H8300S"
"mov.l %S0,%S0"
[(set_attr "length" "2")
- (set_attr "cc" "set")])
+ (set_attr "cc" "set_zn_c0")])
(define_insn "cmpqi"
[(set (cc0)
""
"add.b %X2,%X0"
[(set_attr "length" "2")
- (set_attr "cc" "set_zn_c0")])
+ (set_attr "cc" "set")])
(define_expand "addhi3"
[(set (match_operand:HI 0 "register_operand" "")
add.w %T2,%T0
mov.w %T1,%T0\;add.w %T2,%T0"
[(set_attr "length" "4,2,6")
- (set_attr "cc" "clobber,set_zn_c0,set_zn_c0")])
+ (set_attr "cc" "clobber,set,set")])
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r,r")
add.w %T2,%T0
add.w %T2,%T0"
[(set_attr "length" "4,2")
- (set_attr "cc" "set_zn_c0,set_zn_c0")])
+ (set_attr "cc" "set,set")])
(define_expand "addsi3"
[(set (match_operand:SI 0 "register_operand" "")
add.l %S2,%S0
add.l %S2,%S0"
[(set_attr "length" "6,2")
- (set_attr "cc" "set_zn_c0,set_zn_c0")])
+ (set_attr "cc" "set,set")])
;; ----------------------------------------------------------------------
;; SUBTRACT INSTRUCTIONS
sub.b %X2,%X0
add.b %G2,%X0"
[(set_attr "length" "2")
- (set_attr "cc" "set_zn_c0")])
+ (set_attr "cc" "set")])
(define_expand "subhi3"
[(set (match_operand:HI 0 "register_operand" "")
sub.w %T2,%T0
add.b %E2,%s0\;addx %F2,%t0"
[(set_attr "length" "2,4")
- (set_attr "cc" "set_zn_c0,clobber")])
+ (set_attr "cc" "set,clobber")])
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r,&r")
sub.w %T2,%T0
sub.w %T2,%T0"
[(set_attr "length" "2,4")
- (set_attr "cc" "set_zn_c0,set_zn_c0")])
+ (set_attr "cc" "set,set")])
(define_expand "subsi3"
[(set (match_operand:SI 0 "register_operand" "")
sub.l %S2,%S0
sub.l %S2,%S0"
[(set_attr "length" "2,6")
- (set_attr "cc" "set_zn_c0,set_zn_c0")])
+ (set_attr "cc" "set,set")])
\f
;; ----------------------------------------------------------------------
;; MULTIPLY INSTRUCTIONS
[(set_attr "length" "2")
(set_attr "cc" "none_0hit")])
+;; This is a "bridge" instruction. Combine can't cram enough insns
+;; together to crate a MAC instruction directly, but it can create
+;; this instruction, which then allows combine to create the real
+;; MAC insn.
+;;
+;; Unfortunately, if combine doesn't create a MAC instruction, this
+;; insn must generate reasonably correct code. Egad.
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=a")
+ (mult:SI
+ (sign_extend:SI
+ (mem:HI (post_inc:SI (match_operand:SI 1 "register_operand" "r"))))
+ (sign_extend:SI
+ (mem:HI (post_inc:SI (match_operand:SI 2 "register_operand" "r"))))))]
+ "TARGET_H8300S"
+ "clrmac\;mac %2,%1"
+ [(set_attr "length" "6")
+ (set_attr "cc" "none_0hit")])
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=a")
+ (plus (mult:SI
+ (sign_extend:SI (mem:HI
+ (post_inc:SI (match_operand:SI 1 "register_operand" "r"))))
+ (sign_extend:SI (mem:HI
+ (post_inc:SI (match_operand:SI 2 "register_operand" "r")))))
+ (match_operand:SI 3 "register_operand" "0")))]
+ "TARGET_H8300S"
+ "mac %2,%1"
+ [(set_attr "length" "4")
+ (set_attr "cc" "none_0hit")])
+
;; ----------------------------------------------------------------------
;; DIVIDE INSTRUCTIONS
;; ----------------------------------------------------------------------
and %X2,%X0
bclr %W2,%R0"
[(set_attr "length" "2,4")
- (set_attr "cc" "set,none_0hit")])
+ (set_attr "cc" "set_zn_c0,none_0hit")])
(define_expand "andqi3"
[(set (match_operand:QI 0 "bit_operand" "")
or %X2,%X0
bset %V2,%R0"
[(set_attr "length" "2,4")
- (set_attr "cc" "set,none_0hit")])
+ (set_attr "cc" "set_zn_c0,none_0hit")])
(define_expand "iorqi3"
[(set (match_operand:QI 0 "bit_operand" "=r,U")
xor %X2,%X0
bnot %V2,%R0"
[(set_attr "length" "2,4")
- (set_attr "cc" "set,none_0hit")])
+ (set_attr "cc" "set_zn_c0,none_0hit")])
(define_expand "xorqi3"
[(set (match_operand:QI 0 "bit_operand" "=r,U")
""
"not %X0"
[(set_attr "length" "2")
- (set_attr "cc" "set")])
+ (set_attr "cc" "set_zn_c0")])
(define_insn "one_cmplhi2"
[(set (match_operand:HI 0 "register_operand" "=r")
""
"*
{
- /* If we erroneously deleted a compare insn (which can happen if we need
- CC bits set that aren't), emit the compare. */
- if (restore_compare_p (operands[1]))
- return 0;
-
if (get_attr_length (insn) == 2)
return \"b%j1 %l0\";
else if (get_attr_length (insn) == 4)
""
"*
{
- /* If we erroneously deleted a compare insn (which can happen if we need
- CC bits set that aren't), emit the compare. */
- if (restore_compare_p (operands[1]))
- return 0;
-
if (get_attr_length (insn) == 2)
return \"b%k1 %l0\";
else if (get_attr_length (insn) == 4)
extu.l %S0
mov.w %T1,%T0\;extu.l %S0"
[(set_attr "length" "2,4")
- (set_attr "cc" "set,set")])
+ (set_attr "cc" "set_zn_c0,set_zn_c0")])
(define_expand "extendqihi2"
[(set (match_operand:HI 0 "register_operand" "")
exts.w %T0
mov.b %R1,%s0\;exts.w %T0"
[(set_attr "length" "2,4")
- (set_attr "cc" "set,set")])
+ (set_attr "cc" "set_zn_c0,set_zn_c0")])
;; The compiler can synthesize a 300H variant of this which is
;; just as efficient as one that we'd create
exts.l %S0
mov.w %T1,%T0\;exts.l %S0"
[(set_attr "length" "2,4")
- (set_attr "cc" "set,set")])
+ (set_attr "cc" "set_zn_c0,set_zn_c0")])
\f
;; ----------------------------------------------------------------------
;; SHIFTS
"(INTVAL(operands[2]) == INTVAL(operands[4])+1) && REGNO(operands[0]) +1 == REGNO(operands[3])"
"mov.w @(%u4,%T1),%T0"
[(set_attr "length" "6")
- (set_attr "cc" "set")])
+ (set_attr "cc" "set_zn_c0")])
(define_peephole
[(set (mem:QI (plus:HI (match_operand:HI 1 "register_operand" "r")
"(INTVAL(operands[2]) == INTVAL(operands[4])+1) && REGNO(operands[0]) +1 == REGNO(operands[3])"
"mov.w %T0,@(%u4,%T1)"
[(set_attr "length" "6")
- (set_attr "cc" "set")])
+ (set_attr "cc" "set_zn_c0")])
;; Notice a move which could be post incremented.
"REGNO(operands[1]) != REGNO(operands[0])"
"mov.b @%T1+,%X0"
[(set_attr "length" "2")
- (set_attr "cc" "set")])
+ (set_attr "cc" "set_zn_c0")])
(define_peephole
[(set (match_operand:HI 0 "register_operand" "")
"REGNO(operands[1]) != REGNO(operands[0])"
"mov.w @%T1+,%T0"
[(set_attr "length" "2")
- (set_attr "cc" "set")])
+ (set_attr "cc" "set_zn_c0")])
;; Notice a move which could be predecremented.
"REGNO(operands[1]) != REGNO(operands[0])"
"mov.b %X0,@-%T1"
[(set_attr "length" "2")
- (set_attr "cc" "set")])
+ (set_attr "cc" "set_zn_c0")])
(define_peephole
[(set (match_operand:HI 1 "register_operand" "")
"REGNO(operands[1]) != REGNO(operands[0])"
"mov.w %T0,@-%T1"
[(set_attr "length" "2")
- (set_attr "cc" "set")])
+ (set_attr "cc" "set_zn_c0")])