Commit 705ac34f by Jeffrey A Law Committed by Jeff Law

mn10300.c (REG_SAVE_BYTES): Allocate space for AM33 registers.

        * mn10300.c (REG_SAVE_BYTES): Allocate space for AM33 registers.
        (asm_file_start): Emit .am33 into assembly file when compiling for
        the AM33.
        (print_operand_address): Handle POST_INC addresses.
        (can_use_return_insn, initial_offset): Check AM33 registers too.
        (expand_prologue): Check & save AM33 registers too.
        (expand_epilogue): Similarly.
        wise.
        (REG_CLASS_CONTENTS, REGNO_REG_CLASS): Likewise.
        (INDEX_REG_CLASS, REG_CLASS_FROM_LETTER): Likewise.
        (REGNO_OK_FOR_INDEX_P, PREFERRED_RELOAD_CLASS): Likewise.
        (PREFERRED_OUTPUT_RELOAD_CLASS, LIMIT_RELOAD_CLASS): Likewise.
        (REGISTER_MOVE_COST, REGISTER_NAMES): Likewise.
        (HAVE_POST_INCREMENT): Define.
        (GO_IF_LEGITIMATE_ADDRESS): Allow POST_INC addresses for the AM33.
        (GO_IF_MODE_DEPENDENT_ADDRESS): POST_INC is a mode dependent address.
        * mn10300.md (movqi, movhi, addsi, subsi): Add AM33 variants.
        (mulsi, andsi, iorsi, xorsi, notsi): Likewise.
        (ashiftsi, lshiftrtsi, ashiftrtsi): Likewise.
        (zero_extend to SI from QI/HI): Likewise.
        (sign_extend to SI from QI/HI): Likewise.
        (mulsidi3, umulsidi3): New patterns for the AM33.
        (tstsi with zero extension from QI/HI): Add AM33 variants.
        (movsi, movsf, movdi, movdf): Generate efficient code for the AM33 too.
        (return_internal_regs, store_movm): Handle new AM33 registers.
        * t-mn10300 (MULTILIB_OPTIONS, MULTILIB_DIRNAMES): Define.
        (LIBGCC, INSTALL_LIBGCC): Likewise.
        * invoke.texi: Document new flags.

From-SVN: r30748
parent d525dfdf
Wed Dec 1 16:51:22 1999 Jeffrey A Law (law@cygnus.com)
* mn10300.c (REG_SAVE_BYTES): Allocate space for AM33 registers.
(asm_file_start): Emit .am33 into assembly file when compiling for
the AM33.
(print_operand_address): Handle POST_INC addresses.
(can_use_return_insn, initial_offset): Check AM33 registers too.
(expand_prologue): Check & save AM33 registers too.
(expand_epilogue): Similarly.
(secondary_reload_class): Handle AM33 specific secondary reloads.
(output_tst): Emit efficient code for the AM33 too.
* mn10300.h (CPP_SPEC, TARGET_AM33): Define.
(TARGET_SWITCHES): Add -mam33 switch.
(FIRST_PSEUDO_REGISTER): Handle new AM33 registers.
(FIXED_REGISTERS, CALL_USED_REGISTERS): Likewise.
(REG_ALLOC_ORDER, CONDITIONAL_REGISTER_USAGE): Likewise.
(HARD_REGNO_MODE_OK, MODES_TIEABLE_P): Likewise.
(enum reg_class, REG_CLASS_NAMES): Likewise.
(REG_CLASS_CONTENTS, REGNO_REG_CLASS): Likewise.
(INDEX_REG_CLASS, REG_CLASS_FROM_LETTER): Likewise.
(REGNO_OK_FOR_INDEX_P, PREFERRED_RELOAD_CLASS): Likewise.
(PREFERRED_OUTPUT_RELOAD_CLASS, LIMIT_RELOAD_CLASS): Likewise.
(REGISTER_MOVE_COST, REGISTER_NAMES): Likewise.
(HAVE_POST_INCREMENT): Define.
(GO_IF_LEGITIMATE_ADDRESS): Allow POST_INC addresses for the AM33.
(GO_IF_MODE_DEPENDENT_ADDRESS): POST_INC is a mode dependent address.
* mn10300.md (movqi, movhi, addsi, subsi): Add AM33 variants.
(mulsi, andsi, iorsi, xorsi, notsi): Likewise.
(ashiftsi, lshiftrtsi, ashiftrtsi): Likewise.
(zero_extend to SI from QI/HI): Likewise.
(sign_extend to SI from QI/HI): Likewise.
(mulsidi3, umulsidi3): New patterns for the AM33.
(tstsi with zero extension from QI/HI): Add AM33 variants.
(movsi, movsf, movdi, movdf): Generate efficient code for the AM33 too.
(return_internal_regs, store_movm): Handle new AM33 registers.
* t-mn10300 (MULTILIB_OPTIONS, MULTILIB_DIRNAMES): Define.
(LIBGCC, INSTALL_LIBGCC): Likewise.
* invoke.texi: Document new flags.
Fri Nov 26 10:59:12 CET 1999 Jan Hubicka <hubicka@freesoft.cz>
* i386.md (addsi3_cc): Add "binary_operator_ok" to the condition.
......
......@@ -42,8 +42,10 @@ Boston, MA 02111-1307, USA. */
speed standpoint, so we want to optimize this sooner or later. */
#define REG_SAVE_BYTES (4 * regs_ever_live[2] \
+ 4 * regs_ever_live[3] \
+ 4 * regs_ever_live[6] \
+ 4 * regs_ever_live[7])
+ 4 * regs_ever_live[6] \
+ 4 * regs_ever_live[7] \
+ 16 * (regs_ever_live[14] || regs_ever_live[15] \
|| regs_ever_live[16] || regs_ever_live[17]))
void
asm_file_start (file)
......@@ -54,6 +56,9 @@ asm_file_start (file)
fprintf (file, "# -O%d\n", optimize);
else
fprintf (file, "\n\n");
if (TARGET_AM33)
fprintf (file, "\t.am33\n");
output_file_directive (file, main_input_filename);
}
......@@ -312,6 +317,10 @@ print_operand_address (file, addr)
{
switch (GET_CODE (addr))
{
case POST_INC:
print_operand_address (file, XEXP (addr, 0));
fputc ('+', file);
break;
case REG:
if (addr == stack_pointer_rtx)
print_operand_address (file, gen_rtx_PLUS (SImode,
......@@ -360,6 +369,10 @@ can_use_return_insn ()
&& !regs_ever_live[3]
&& !regs_ever_live[6]
&& !regs_ever_live[7]
&& !regs_ever_live[14]
&& !regs_ever_live[15]
&& !regs_ever_live[16]
&& !regs_ever_live[17]
&& !frame_pointer_needed);
}
......@@ -388,6 +401,8 @@ expand_prologue ()
single two byte instruction. */
if (regs_ever_live[2] || regs_ever_live[3]
|| regs_ever_live[6] || regs_ever_live[7]
|| regs_ever_live[14] || regs_ever_live[15]
|| regs_ever_live[16] || regs_ever_live[17]
|| frame_pointer_needed)
emit_insn (gen_store_movm ());
......@@ -432,6 +447,8 @@ expand_epilogue ()
size = 0;
}
else if ((regs_ever_live[2] || regs_ever_live[3]
|| regs_ever_live[14] || regs_ever_live[15]
|| regs_ever_live[16] || regs_ever_live[17]
|| regs_ever_live[6] || regs_ever_live[7])
&& size + REG_SAVE_BYTES > 255)
{
......@@ -448,6 +465,8 @@ expand_epilogue ()
stack requirements and is faster. */
if (regs_ever_live[2] || regs_ever_live[3]
|| regs_ever_live[6] || regs_ever_live[7]
|| regs_ever_live[14] || regs_ever_live[15]
|| regs_ever_live[16] || regs_ever_live[17]
|| frame_pointer_needed)
emit_jump_insn (gen_return_internal_regs (GEN_INT (size + REG_SAVE_BYTES)));
else
......@@ -554,6 +573,8 @@ secondary_reload_class (class, mode, in)
&& (mode == QImode || mode == HImode)
&& (class == ADDRESS_REGS || class == SP_REGS))
{
if (TARGET_AM33)
return DATA_OR_EXTENDED_REGS;
return DATA_REGS;
}
......@@ -562,6 +583,9 @@ secondary_reload_class (class, mode, in)
if (class != SP_REGS
&& class != ADDRESS_REGS
&& class != SP_OR_ADDRESS_REGS
&& class != SP_OR_EXTENDED_REGS
&& class != ADDRESS_OR_EXTENDED_REGS
&& class != SP_OR_ADDRESS_OR_EXTENDED_REGS
&& (in == stack_pointer_rtx
|| (GET_CODE (in) == PLUS
&& (XEXP (in, 0) == stack_pointer_rtx
......@@ -572,6 +596,8 @@ secondary_reload_class (class, mode, in)
&& (XEXP (in, 0) == stack_pointer_rtx
|| XEXP (in, 1) == stack_pointer_rtx))
{
if (TARGET_AM33)
return DATA_OR_EXTENDED_REGS;
return DATA_REGS;
}
......@@ -589,6 +615,8 @@ initial_offset (from, to)
{
if (regs_ever_live[2] || regs_ever_live[3]
|| regs_ever_live[6] || regs_ever_live[7]
|| regs_ever_live[14] || regs_ever_live[15]
|| regs_ever_live[16] || regs_ever_live[17]
|| frame_pointer_needed)
return REG_SAVE_BYTES;
else
......@@ -602,6 +630,8 @@ initial_offset (from, to)
{
if (regs_ever_live[2] || regs_ever_live[3]
|| regs_ever_live[6] || regs_ever_live[7]
|| regs_ever_live[14] || regs_ever_live[15]
|| regs_ever_live[16] || regs_ever_live[17]
|| frame_pointer_needed)
return (get_frame_size () + REG_SAVE_BYTES
+ (current_function_outgoing_args_size
......@@ -855,6 +885,26 @@ output_tst (operand, insn)
&& !reg_set_between_p (SET_DEST (set), temp, insn)
&& (REGNO_REG_CLASS (REGNO (SET_DEST (set)))
== REGNO_REG_CLASS (REGNO (operand)))
&& REGNO_REG_CLASS (REGNO (SET_DEST (set))) != EXTENDED_REGS
&& REGNO (SET_DEST (set)) != REGNO (operand)
&& (!past_call
|| !call_used_regs[REGNO (SET_DEST (set))]))
{
rtx xoperands[2];
xoperands[0] = operand;
xoperands[1] = SET_DEST (set);
output_asm_insn ("cmp %1,%0", xoperands);
return "";
}
if (REGNO_REG_CLASS (REGNO (operand)) == EXTENDED_REGS
&& REG_P (SET_DEST (set))
&& SET_SRC (set) == CONST0_RTX (GET_MODE (SET_DEST (set)))
&& !reg_set_between_p (SET_DEST (set), temp, insn)
&& (REGNO_REG_CLASS (REGNO (SET_DEST (set)))
!= REGNO_REG_CLASS (REGNO (operand)))
&& REGNO_REG_CLASS (REGNO (SET_DEST (set))) == EXTENDED_REGS
&& REGNO (SET_DEST (set)) != REGNO (operand)
&& (!past_call
|| !call_used_regs[REGNO (SET_DEST (set))]))
......
......@@ -32,6 +32,8 @@ Boston, MA 02111-1307, USA. */
#define CPP_PREDEFINES "-D__mn10300__ -D__MN10300__"
#define CPP_SPEC "%{mam33:-D__AM33__}"
/* Run-time compilation parameters selecting different hardware subsets. */
extern int target_flags;
......@@ -46,9 +48,16 @@ extern int target_flags;
/* Generate code to work around mul/mulq bugs on the mn10300. */
#define TARGET_MULT_BUG (target_flags & 0x1)
/* Generate code for the AM33 processor. */
#define TARGET_AM33 (target_flags & 0x2)
#define TARGET_SWITCHES \
{{ "mult-bug", 0x1, "Work around hardware multiply bug"}, \
{ "no-mult-bug", -0x1, "Do not work around hardware multiply bug"},\
{ "am33", 0x2}, \
{ "am33", -(0x1)},\
{ "no-am33", -0x2}, \
{ "", TARGET_DEFAULT, NULL}}
#ifndef TARGET_DEFAULT
......@@ -134,13 +143,13 @@ extern int target_flags;
All registers that the compiler knows about must be given numbers,
even those that are not normally considered general registers. */
#define FIRST_PSEUDO_REGISTER 10
#define FIRST_PSEUDO_REGISTER 18
/* 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, 0, 1, 1}
{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}
/* 1 for registers not available across function calls.
These must include the FIXED_REGISTERS and also any
......@@ -151,10 +160,19 @@ extern int target_flags;
like. */
#define CALL_USED_REGISTERS \
{ 1, 1, 0, 0, 1, 1, 0, 0, 1, 1}
{ 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0}
#define REG_ALLOC_ORDER \
{ 0, 1, 4, 5, 2, 3, 6, 7, 8, 9}
{ 0, 1, 4, 5, 2, 3, 6, 7, 10, 11, 12, 13, 14, 15, 16, 17, 8, 9}
#define CONDITIONAL_REGISTER_USAGE \
{ \
if (!TARGET_AM33) \
{ \
for (i = 10; i < 18; i++) \
fixed_regs[i] = call_used_regs[i] = 1; \
} \
}
/* Return number of consecutive hard regs needed starting at reg REGNO
to hold something of mode MODE.
......@@ -169,7 +187,9 @@ extern int target_flags;
MODE. */
#define HARD_REGNO_MODE_OK(REGNO, MODE) \
(REGNO_REG_CLASS (REGNO) == DATA_REGS \
((REGNO_REG_CLASS (REGNO) == DATA_REGS \
|| (TARGET_AM33 && REGNO_REG_CLASS (REGNO) == ADDRESS_REGS) \
|| REGNO_REG_CLASS (REGNO) == EXTENDED_REGS) \
? ((REGNO) & 1) == 0 || GET_MODE_SIZE (MODE) <= 4 \
: ((REGNO) & 1) == 0 || GET_MODE_SIZE (MODE) == 4)
......@@ -178,7 +198,9 @@ extern int target_flags;
If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
for any hard reg, then this must be 0 for correct output. */
#define MODES_TIEABLE_P(MODE1, MODE2) \
(MODE1 == MODE2 || (GET_MODE_SIZE (MODE1) <= 4 && GET_MODE_SIZE (MODE2) <= 4))
(TARGET_AM33 \
|| MODE1 == MODE2 \
|| (GET_MODE_SIZE (MODE1) <= 4 && GET_MODE_SIZE (MODE2) <= 4))
/* 4 data, and effectively 3 address registers is small as far as I'm
concerned. */
......@@ -207,6 +229,8 @@ extern int target_flags;
enum reg_class {
NO_REGS, DATA_REGS, ADDRESS_REGS, SP_REGS,
DATA_OR_ADDRESS_REGS, SP_OR_ADDRESS_REGS,
EXTENDED_REGS, DATA_OR_EXTENDED_REGS, ADDRESS_OR_EXTENDED_REGS,
SP_OR_EXTENDED_REGS, SP_OR_ADDRESS_OR_EXTENDED_REGS,
GENERAL_REGS, ALL_REGS, LIM_REG_CLASSES
};
......@@ -217,6 +241,9 @@ enum reg_class {
#define REG_CLASS_NAMES \
{ "NO_REGS", "DATA_REGS", "ADDRESS_REGS", \
"SP_REGS", "DATA_OR_ADDRESS_REGS", "SP_OR_ADDRESS_REGS", \
"EXTENDED_REGS", \
"DATA_OR_EXTENDED_REGS", "ADDRESS_OR_EXTENDED_REGS", \
"SP_OR_EXTENDED_REGS", "SP_OR_ADDRESS_OR_EXTENDED_REGS", \
"GENERAL_REGS", "ALL_REGS", "LIM_REGS" }
/* Define which registers fit in which classes.
......@@ -225,13 +252,18 @@ enum reg_class {
#define REG_CLASS_CONTENTS \
{ 0, /* No regs */ \
0x00f, /* DATA_REGS */ \
0x1f0, /* ADDRESS_REGS */ \
0x200, /* SP_REGS */ \
0x1ff, /* DATA_OR_ADDRESS_REGS */\
0x1f0, /* SP_OR_ADDRESS_REGS */\
0x1ff, /* GENERAL_REGS */ \
0x3ff, /* ALL_REGS */ \
0x0000f, /* DATA_REGS */ \
0x001f0, /* ADDRESS_REGS */ \
0x00200, /* SP_REGS */ \
0x001ff, /* DATA_OR_ADDRESS_REGS */\
0x003f0, /* SP_OR_ADDRESS_REGS */\
0x2fc00, /* EXTENDED_REGS */ \
0x2fc0f, /* DATA_OR_EXTENDED_REGS */ \
0x2fdf0, /* ADDRESS_OR_EXTENDED_REGS */ \
0x2fe00, /* SP_OR_EXTENDED_REGS */ \
0x2fff0, /* SP_OR_ADDRESS_OR_EXTENDED_REGS */ \
0x2fdff, /* GENERAL_REGS */ \
0x2ffff, /* ALL_REGS */ \
}
/* The same information, inverted:
......@@ -242,10 +274,11 @@ enum reg_class {
#define REGNO_REG_CLASS(REGNO) \
((REGNO) < 4 ? DATA_REGS : \
(REGNO) < 9 ? ADDRESS_REGS : \
(REGNO) == 9 ? SP_REGS : 0)
(REGNO) == 9 ? SP_REGS : \
(REGNO) < 18 ? EXTENDED_REGS : 0)
/* The class value for index registers, and the one for base regs. */
#define INDEX_REG_CLASS DATA_REGS
#define INDEX_REG_CLASS DATA_OR_EXTENDED_REGS
#define BASE_REG_CLASS SP_OR_ADDRESS_REGS
/* Get reg_class from a letter such as appears in the machine description. */
......@@ -253,6 +286,7 @@ enum reg_class {
#define REG_CLASS_FROM_LETTER(C) \
((C) == 'd' ? DATA_REGS : \
(C) == 'a' ? ADDRESS_REGS : \
(C) == 'x' ? EXTENDED_REGS : \
(C) == 'y' ? SP_REGS : NO_REGS)
/* Macros to check register numbers against specific register classes. */
......@@ -273,6 +307,8 @@ enum reg_class {
#define REGNO_OK_FOR_INDEX_P(regno) \
(((regno) >= 0 && regno < 4) \
|| ((regno) >= 10 && regno < 18) \
|| (reg_renumber[regno] >= 10 && reg_renumber[regno] < 18) \
|| (reg_renumber[regno] >= 0 && reg_renumber[regno] < 4))
......@@ -282,13 +318,15 @@ enum reg_class {
in some cases it is preferable to use a more restrictive class. */
#define PREFERRED_RELOAD_CLASS(X,CLASS) \
(X == stack_pointer_rtx && CLASS != SP_REGS ? ADDRESS_REGS : CLASS)
(X == stack_pointer_rtx && CLASS != SP_REGS \
? ADDRESS_OR_EXTENDED_REGS : CLASS)
#define PREFERRED_OUTPUT_RELOAD_CLASS(X,CLASS) \
(X == stack_pointer_rtx && CLASS != SP_REGS ? ADDRESS_REGS : CLASS)
(X == stack_pointer_rtx && CLASS != SP_REGS \
? ADDRESS_OR_EXTENDED_REGS : CLASS)
#define LIMIT_RELOAD_CLASS(MODE, CLASS) \
((MODE == QImode || MODE == HImode) ? DATA_REGS : CLASS)
(!TARGET_AM33 && (MODE == QImode || MODE == HImode) ? DATA_REGS : CLASS)
#define SECONDARY_RELOAD_CLASS(CLASS,MODE,IN) \
secondary_reload_class(CLASS,MODE,IN)
......@@ -645,6 +683,8 @@ extern struct rtx_def *mn10300_va_arg();
#endif
#define HAVE_POST_INCREMENT (TARGET_AM33)
/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
that is a valid memory address for an instruction.
The MODE argument is the machine mode for the MEM expression
......@@ -678,6 +718,11 @@ extern struct rtx_def *mn10300_va_arg();
goto ADDR; \
if (RTX_OK_FOR_BASE_P (X)) \
goto ADDR; \
if (TARGET_AM33 \
&& GET_CODE (X) == POST_INC \
&& RTX_OK_FOR_BASE_P (XEXP (X, 0)) \
&& (MODE == SImode || MODE == SFmode || MODE == HImode))\
goto ADDR; \
if (GET_CODE (X) == PLUS) \
{ \
rtx base = 0, index = 0; \
......@@ -719,7 +764,9 @@ extern struct rtx_def *legitimize_address ();
/* Go to LABEL if ADDR (a legitimate address expression)
has an effect that depends on the machine mode it is used for. */
#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) {}
#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) \
if (GET_CODE (ADDR) == POST_INC) \
goto LABEL
/* Nonzero if the constant value X is a legitimate general operand.
It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
......@@ -772,8 +819,9 @@ extern struct rtx_def *legitimize_address ();
case CONST_DOUBLE: \
return 8;
#define REGISTER_MOVE_COST(CLASS1, CLASS2) (CLASS1 != CLASS2 ? 4 : 2)
#define REGISTER_MOVE_COST(CLASS1, CLASS2) \
((CLASS1 == CLASS2 && (CLASS1 == ADDRESS_REGS || CLASS1 == DATA_REGS)) ? 2 :\
CLASS1 == CLASS2 && CLASS1 == EXTENDED_REGS ? 6 : 4)
/* A crude cut at RTX_COSTS for the MN10300. */
......@@ -923,7 +971,8 @@ do { char dstr[30]; \
This sequence is indexed by compiler's hard-register-number (see above). */
#define REGISTER_NAMES \
{ "d0", "d1", "d2", "d3", "a0", "a1", "a2", "a3", "ap", "sp" }
{ "d0", "d1", "d2", "d3", "a0", "a1", "a2", "a3", "ap", "sp", \
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7" }
/* Print an instruction operand X on file FILE.
look in mn10300.c for details */
......
......@@ -18,3 +18,9 @@ fp-bit.c: $(srcdir)/config/fp-bit.c
echo '#define FLOAT_BIT_ORDER_MISMATCH' >>fp-bit.c
echo '#endif' >> fp-bit.c
cat $(srcdir)/config/fp-bit.c >> fp-bit.c
MULTILIB_OPTIONS = mam33
MULTILIB_DIRNAMES = am33
LIBGCC = stmp-multilib
INSTALL_LIBGCC = install-multilib
......@@ -291,6 +291,8 @@ in the following sections.
@emph{MN10300 Options}
-mmult-bug
-mno-mult-bug
-mam33
-mno-am33
-mrelax
@emph{M32R/D Options}
......@@ -4641,6 +4643,14 @@ processors. This is the default.
Do not generate code to avoid bugs in the multiply instructions for the
MN10300 processors.
@table @code
@item -mam33
Generate code which uses features specific to the AM33 processor.
@item -mno-am33
Do not generate code which uses features specific to the AM33 processor. This
is the default.
@item -mrelax
Indicate to the linker that it should perform a relaxation optimization pass
to shorten branches, calls and absolute memory addresses. This option only
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment