aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeffrey A Law <law@cygnus.com>1999-12-02 00:21:59 +0000
committerJeff Law <law@gcc.gnu.org>1999-12-01 17:21:59 -0700
commit705ac34f068eddf9493bc0ce8c34392667db1fdb (patch)
treee49cefcce7d7b3499134e5d15d195e9867f43066
parentd525dfdf293509387773497c46f672495ec2af7c (diff)
downloadgcc-705ac34f068eddf9493bc0ce8c34392667db1fdb.zip
gcc-705ac34f068eddf9493bc0ce8c34392667db1fdb.tar.gz
gcc-705ac34f068eddf9493bc0ce8c34392667db1fdb.tar.bz2
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
-rw-r--r--gcc/ChangeLog39
-rw-r--r--gcc/config/mn10300/mn10300.c54
-rw-r--r--gcc/config/mn10300/mn10300.h93
-rw-r--r--gcc/config/mn10300/mn10300.md525
-rw-r--r--gcc/config/mn10300/t-mn103006
-rw-r--r--gcc/invoke.texi10
6 files changed, 701 insertions, 26 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 5e8f864..18c6917 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,42 @@
+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.
diff --git a/gcc/config/mn10300/mn10300.c b/gcc/config/mn10300/mn10300.c
index 80236d2..2c325bf 100644
--- a/gcc/config/mn10300/mn10300.c
+++ b/gcc/config/mn10300/mn10300.c
@@ -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))]))
diff --git a/gcc/config/mn10300/mn10300.h b/gcc/config/mn10300/mn10300.h
index a7686ca..8e77acc 100644
--- a/gcc/config/mn10300/mn10300.h
+++ b/gcc/config/mn10300/mn10300.h
@@ -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 */
diff --git a/gcc/config/mn10300/mn10300.md b/gcc/config/mn10300/mn10300.md
index 54cc0db..27fdb68 100644
--- a/gcc/config/mn10300/mn10300.md
+++ b/gcc/config/mn10300/mn10300.md
@@ -56,6 +56,52 @@
}")
(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=dx,a,dx,a,dx,a,dx,a,dxa,m")
+ (match_operand:QI 1 "general_operand" "0,0,I,I,a,dx,dxi,ia,m,dxa"))]
+ "TARGET_AM33
+ && (register_operand (operands[0], QImode)
+ || register_operand (operands[1], QImode))"
+ "*
+{
+ switch (which_alternative)
+ {
+ case 0:
+ case 1:
+ return \"nop\";
+ case 2:
+ return \"clr %0\";
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ {
+ rtx xoperands[2];
+ xoperands[0] = operands[0];
+ xoperands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
+ output_asm_insn (\"mov %1,%0\", xoperands);
+ return \"\";
+ }
+
+ if (REGNO_REG_CLASS (true_regnum (operands[0])) == EXTENDED_REGS
+ && GET_CODE (operands[1]) == CONST_INT)
+ {
+ HOST_WIDE_INT val = INTVAL (operands[1]);
+
+ if (((val & 0x80) && ! (val & 0xffffff00))
+ || ((val & 0x800000) && ! (val & 0xff000000)))
+ return \"movu %1,%0\";
+ }
+ return \"mov %1,%0\";
+ case 8:
+ case 9:
+ return \"movbu %1,%0\";
+ }
+}"
+ [(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")])
+
+(define_insn ""
[(set (match_operand:QI 0 "general_operand" "=dx,*a,dx,*a,dx,*a,dx,*a,dx,m")
(match_operand:QI 1 "general_operand" "0,0,I,I,a,dx,dxi,ia,m,dx"))]
"register_operand (operands[0], QImode)
@@ -106,6 +152,52 @@
}")
(define_insn ""
+ [(set (match_operand:HI 0 "general_operand" "=dx,a,dx,a,dx,a,dx,a,dxa,m")
+ (match_operand:HI 1 "general_operand" "0,0,I,I,a,dx,dxi,ia,m,dxa"))]
+ "TARGET_AM33
+ && (register_operand (operands[0], HImode)
+ || register_operand (operands[1], HImode))"
+ "*
+{
+ switch (which_alternative)
+ {
+ case 0:
+ case 1:
+ return \"nop\";
+ case 2:
+ return \"clr %0\";
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ {
+ rtx xoperands[2];
+ xoperands[0] = operands[0];
+ xoperands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
+ output_asm_insn (\"mov %1,%0\", xoperands);
+ return \"\";
+ }
+
+ if (REGNO_REG_CLASS (true_regnum (operands[0])) == EXTENDED_REGS
+ && GET_CODE (operands[1]) == CONST_INT)
+ {
+ HOST_WIDE_INT val = INTVAL (operands[1]);
+
+ if (((val & 0x80) && ! (val & 0xffffff00))
+ || ((val & 0x800000) && ! (val & 0xff000000)))
+ return \"movu %1,%0\";
+ }
+ return \"mov %1,%0\";
+ case 8:
+ case 9:
+ return \"movhu %1,%0\";
+ }
+}"
+ [(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")])
+
+(define_insn ""
[(set (match_operand:HI 0 "general_operand" "=dx,*a,dx,*a,dx,*a,dx,*a,dx,m")
(match_operand:HI 1 "general_operand" "0,0,I,I,a,dx,dxi,ia,m,dx"))]
"register_operand (operands[0], HImode)
@@ -229,6 +321,16 @@
output_asm_insn (\"mov %1,%0\", xoperands);
return \"\";
}
+
+ if (REGNO_REG_CLASS (true_regnum (operands[0])) == EXTENDED_REGS
+ && GET_CODE (operands[1]) == CONST_INT)
+ {
+ HOST_WIDE_INT val = INTVAL (operands[1]);
+
+ if (((val & 0x80) && ! (val & 0xffffff00))
+ || ((val & 0x800000) && ! (val & 0xff000000)))
+ return \"movu %1,%0\";
+ }
return \"mov %1,%0\";
}
}"
@@ -263,6 +365,15 @@
case 3:
case 4:
case 5:
+ if (REGNO_REG_CLASS (true_regnum (operands[0])) == EXTENDED_REGS
+ && GET_CODE (operands[1]) == CONST_INT)
+ {
+ HOST_WIDE_INT val = INTVAL (operands[1]);
+
+ if (((val & 0x80) && ! (val & 0xffffff00))
+ || ((val & 0x800000) && ! (val & 0xff000000)))
+ return \"movu %1,%0\";
+ }
return \"mov %1,%0\";
}
}"
@@ -376,6 +487,11 @@
else
output_asm_insn (\"mov %L1,%L0\", operands);
}
+ else if ((REGNO_REG_CLASS (true_regnum (operands[0]))
+ == EXTENDED_REGS)
+ && (((val[0] & 0x80) && ! (val[0] & 0xffffff00))
+ || ((val[0] & 0x800000) && ! (val[0] & 0xff000000))))
+ output_asm_insn (\"movu %1,%0\", operands);
else
output_asm_insn (\"mov %L1,%L0\", operands);
@@ -392,6 +508,11 @@
|| GET_CODE (operands[1]) == CONST_DOUBLE)
&& val[0] == val[1])
output_asm_insn (\"mov %L0,%H0\", operands);
+ else if ((REGNO_REG_CLASS (true_regnum (operands[0]))
+ == EXTENDED_REGS)
+ && (((val[1] & 0x80) && ! (val[1] & 0xffffff00))
+ || ((val[1] & 0x800000) && ! (val[1] & 0xff000000))))
+ output_asm_insn (\"movu %1,%0\", operands);
else
output_asm_insn (\"mov %H1,%H0\", operands);
return \"\";
@@ -508,6 +629,11 @@
else
output_asm_insn (\"mov %L1,%L0\", operands);
}
+ else if ((REGNO_REG_CLASS (true_regnum (operands[0]))
+ == EXTENDED_REGS)
+ && (((val[0] & 0x80) && ! (val[0] & 0xffffff00))
+ || ((val[0] & 0x800000) && ! (val[0] & 0xff000000))))
+ output_asm_insn (\"movu %1,%0\", operands);
else
output_asm_insn (\"mov %L1,%L0\", operands);
@@ -524,6 +650,11 @@
|| GET_CODE (operands[1]) == CONST_DOUBLE)
&& val[0] == val[1])
output_asm_insn (\"mov %L0,%H0\", operands);
+ else if ((REGNO_REG_CLASS (true_regnum (operands[0]))
+ == EXTENDED_REGS)
+ && (((val[1] & 0x80) && ! (val[1] & 0xffffff00))
+ || ((val[1] & 0x800000) && ! (val[1] & 0xff000000))))
+ output_asm_insn (\"movu %1,%0\", operands);
else
output_asm_insn (\"mov %H1,%H0\", operands);
return \"\";
@@ -547,18 +678,29 @@
[(set_attr "cc" "set_znv")])
(define_insn ""
+ [(set (cc0) (zero_extend:SI (match_operand:QI 0 "memory_operand" "dx,!a")))]
+ "TARGET_AM33"
+ "* return output_tst (operands[0], insn);"
+ [(set_attr "cc" "set_znv")])
+
+(define_insn ""
[(set (cc0) (zero_extend:SI (match_operand:QI 0 "memory_operand" "dx")))]
""
"* return output_tst (operands[0], insn);"
[(set_attr "cc" "set_znv")])
(define_insn ""
+ [(set (cc0) (zero_extend:SI (match_operand:HI 0 "memory_operand" "dx,!a")))]
+ "TARGET_AM33"
+ "* return output_tst (operands[0], insn);"
+ [(set_attr "cc" "set_znv")])
+
+(define_insn ""
[(set (cc0) (zero_extend:SI (match_operand:HI 0 "memory_operand" "dx")))]
""
"* return output_tst (operands[0], insn);"
[(set_attr "cc" "set_znv")])
-
(define_insn "cmpsi"
[(set (cc0)
(compare (match_operand:SI 0 "register_operand" "!*d*a*x,dax")
@@ -597,6 +739,82 @@
[(set (match_operand:SI 0 "register_operand" "=dx,ax,ax,dax,xy,!dax")
(plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,dax")
(match_operand:SI 2 "nonmemory_operand" "J,J,L,daxi,i,dax")))]
+ "TARGET_AM33"
+ "*
+{
+ switch (which_alternative)
+ {
+ case 0:
+ case 1:
+ return \"inc %0\";
+ case 2:
+ return \"inc4 %0\";
+ case 3:
+ case 4:
+ return \"add %2,%0\";
+ case 5:
+ {
+ enum reg_class src1_class, src2_class, dst_class;
+
+ src1_class = REGNO_REG_CLASS (true_regnum (operands[1]));
+ src2_class = REGNO_REG_CLASS (true_regnum (operands[2]));
+ dst_class = REGNO_REG_CLASS (true_regnum (operands[0]));
+
+ /* I'm not sure if this can happen or not. Might as well be prepared
+ and generate the best possible code if it does happen. */
+ if (true_regnum (operands[0]) == true_regnum (operands[1]))
+ return \"add %2,%0\";
+ if (true_regnum (operands[0]) == true_regnum (operands[2]))
+ return \"add %1,%0\";
+
+ /* Catch cases where no extended register was used. These should be
+ handled just like the mn10300. */
+ if (src1_class != EXTENDED_REGS
+ && src2_class != EXTENDED_REGS
+ && dst_class != EXTENDED_REGS)
+ {
+ /* We have to copy one of the sources into the destination, then
+ add the other source to the destination.
+
+ Carefully select which source to copy to the destination; a naive
+ implementation will waste a byte when the source classes are
+ different and the destination is an address register. Selecting
+ the lowest cost register copy will optimize this sequence. */
+ if (REGNO_REG_CLASS (true_regnum (operands[1]))
+ == REGNO_REG_CLASS (true_regnum (operands[0])))
+ return \"mov %1,%0\;add %2,%0\";
+ return \"mov %2,%0\;add %1,%0\";
+ }
+
+ /* At least one register is an extended register. */
+
+ /* The three operand add instruction on the am33 is a win iff the
+ output register is an extended register, or if both source
+ registers are extended registers. */
+ if (dst_class == EXTENDED_REGS
+ || src1_class == src2_class)
+ return \"add %2,%1,%0\";
+
+ /* It is better to copy one of the sources to the destination, then
+ perform a 2 address add. The destination in this case must be
+ an address or data register and one of the sources must be an
+ extended register and the remaining source must not be an extended
+ register.
+
+ The best code for this case is to copy the extended reg to the
+ destination, then emit a two address add. */
+ if (src1_class == EXTENDED_REGS)
+ return \"mov %1,%0\;add %2,%0\";
+ return \"mov %2,%0\;add %1,%0\";
+ }
+ }
+}"
+ [(set_attr "cc" "set_zn,none_0hit,none_0hit,set_zn,none_0hit,set_zn")])
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=dx,ax,ax,dax,xy,!dax")
+ (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,dax")
+ (match_operand:SI 2 "nonmemory_operand" "J,J,L,daxi,i,dax")))]
""
"*
{
@@ -645,6 +863,36 @@
"")
(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=dax,!dax")
+ (minus:SI (match_operand:SI 1 "register_operand" "0,dax")
+ (match_operand:SI 2 "nonmemory_operand" "daxi,dax")))]
+ "TARGET_AM33"
+ "*
+{
+ if (true_regnum (operands[0]) == true_regnum (operands[1]))
+ return \"sub %2,%0\";
+ else
+ {
+ enum reg_class src1_class, src2_class, dst_class;
+
+ src1_class = REGNO_REG_CLASS (true_regnum (operands[1]));
+ src2_class = REGNO_REG_CLASS (true_regnum (operands[2]));
+ dst_class = REGNO_REG_CLASS (true_regnum (operands[0]));
+
+ /* If no extended registers are used, then the best way to handle
+ this is to copy the first source operand into the destination
+ and emit a two address subtraction. */
+ if (src1_class != EXTENDED_REGS
+ && src2_class != EXTENDED_REGS
+ && dst_class != EXTENDED_REGS
+ && true_regnum (operands[0]) != true_regnum (operands[2]))
+ return \"mov %1,%0\;sub %2,%0\";
+ return \"sub %2,%1,%0\";
+ }
+}"
+ [(set_attr "cc" "set_zn")])
+
+(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=dax")
(minus:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "nonmemory_operand" "daxi")))]
@@ -670,6 +918,22 @@
;; MULTIPLY INSTRUCTIONS
;; ----------------------------------------------------------------------
+(define_insn "mulsidi3"
+ [(set (match_operand:DI 0 "register_operand" "=dax")
+ (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "dax"))
+ (sign_extend:DI (match_operand:SI 2 "register_operand" "dax"))))]
+ "TARGET_AM33"
+ "mul %1,%2,%H0,%L0"
+ [(set_attr "cc" "set_zn")])
+
+(define_insn "umulsidi3"
+ [(set (match_operand:DI 0 "register_operand" "=dax")
+ (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "dax"))
+ (zero_extend:DI (match_operand:SI 2 "register_operand" "dax"))))]
+ "TARGET_AM33"
+ "mulu %1,%2,%H0,%L0"
+ [(set_attr "cc" "set_zn")])
+
(define_expand "mulsi3"
[(set (match_operand:SI 0 "register_operand" "")
(mult:SI (match_operand:SI 1 "register_operand" "")
@@ -678,6 +942,20 @@
"")
(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=dx,!dax")
+ (mult:SI (match_operand:SI 1 "register_operand" "%0,0")
+ (match_operand:SI 2 "nonmemory_operand" "dx,daxi")))]
+ "TARGET_AM33"
+ "*
+{
+ if (TARGET_MULT_BUG)
+ return \"nop\;nop\;mul %2,%0\";
+ else
+ return \"mul %2,%0\";
+}"
+ [(set_attr "cc" "set_zn")])
+
+(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=dx")
(mult:SI (match_operand:SI 1 "register_operand" "%0")
(match_operand:SI 2 "register_operand" "dx")))]
@@ -738,6 +1016,51 @@
"")
(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=dx,dx,!dax")
+ (and:SI (match_operand:SI 1 "register_operand" "%0,0,dax")
+ (match_operand:SI 2 "nonmemory_operand" "N,dxi,dax")))]
+ "TARGET_AM33"
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0xff)
+ return \"extbu %0\";
+ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0xffff)
+ return \"exthu %0\";
+ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0x7fffffff)
+ return \"add %0,%0\;lsr 1,%0\";
+ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0x3fffffff)
+ return \"asl2 %0\;lsr 2,%0\";
+ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0x1fffffff)
+ return \"add %0,%0\;asl2 %0\;lsr 3,%0\";
+ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0x0fffffff)
+ return \"asl2 %0\;asl2 %0\;lsr 4,%0\";
+ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0xfffffffe)
+ return \"lsr 1,%0\;add %0,%0\";
+ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0xfffffffc)
+ return \"lsr 2,%0\;asl2 %0\";
+ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0xfffffff8)
+ return \"lsr 3,%0\;add %0,%0\;asl2 %0\";
+ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0xfffffff0)
+ return \"lsr 4,%0\;asl2 %0\;asl2 %0\";
+ if (REG_P (operands[2]) && REG_P (operands[1])
+ && true_regnum (operands[0]) != true_regnum (operands[1])
+ && true_regnum (operands[0]) != true_regnum (operands[2])
+ && REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS
+ && REGNO_REG_CLASS (true_regnum (operands[1])) == DATA_REGS
+ && REGNO_REG_CLASS (true_regnum (operands[2])) == DATA_REGS)
+ return \"mov %1,%0\;and %2,%0\";
+ if (REG_P (operands[2]) && REG_P (operands[1])
+ && true_regnum (operands[0]) != true_regnum (operands[1])
+ && true_regnum (operands[0]) != true_regnum (operands[2]))
+ return \"and %1,%2,%0\";
+ if (REG_P (operands[2]) && REG_P (operands[0])
+ && true_regnum (operands[2]) == true_regnum (operands[0]))
+ return \"and %1,%0\";
+ return \"and %2,%0\";
+}"
+ [(set_attr "cc" "none_0hit,set_znv,set_znv")])
+
+(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=dx,dx")
(and:SI (match_operand:SI 1 "register_operand" "%0,0")
(match_operand:SI 2 "nonmemory_operand" "N,dxi")))]
@@ -780,6 +1103,31 @@
"")
(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=dx,!dax")
+ (ior:SI (match_operand:SI 1 "register_operand" "%0,dax")
+ (match_operand:SI 2 "nonmemory_operand" "dxi,dax")))]
+ "TARGET_AM33"
+ "*
+{
+ if (REG_P (operands[2]) && REG_P (operands[1])
+ && true_regnum (operands[0]) != true_regnum (operands[1])
+ && true_regnum (operands[0]) != true_regnum (operands[2])
+ && REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS
+ && REGNO_REG_CLASS (true_regnum (operands[1])) == DATA_REGS
+ && REGNO_REG_CLASS (true_regnum (operands[2])) == DATA_REGS)
+ return \"mov %1,%0\;or %2,%0\";
+ if (REG_P (operands[2]) && REG_P (operands[1])
+ && true_regnum (operands[0]) != true_regnum (operands[1])
+ && true_regnum (operands[0]) != true_regnum (operands[2]))
+ return \"or %1,%2,%0\";
+ if (REG_P (operands[2]) && REG_P (operands[0])
+ && true_regnum (operands[2]) == true_regnum (operands[0]))
+ return \"or %1,%0\";
+ return \"or %2,%0\";
+}"
+ [(set_attr "cc" "set_znv")])
+
+(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=dx")
(ior:SI (match_operand:SI 1 "register_operand" "%0")
(match_operand:SI 2 "nonmemory_operand" "dxi")))]
@@ -799,6 +1147,31 @@
"")
(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=dx,!dax")
+ (xor:SI (match_operand:SI 1 "register_operand" "%0,dax")
+ (match_operand:SI 2 "nonmemory_operand" "dxi,dax")))]
+ "TARGET_AM33"
+ "*
+{
+ if (REG_P (operands[2]) && REG_P (operands[1])
+ && true_regnum (operands[0]) != true_regnum (operands[1])
+ && true_regnum (operands[0]) != true_regnum (operands[2])
+ && REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS
+ && REGNO_REG_CLASS (true_regnum (operands[1])) == DATA_REGS
+ && REGNO_REG_CLASS (true_regnum (operands[2])) == DATA_REGS)
+ return \"mov %1,%0\;xor %2,%0\";
+ if (REG_P (operands[2]) && REG_P (operands[1])
+ && true_regnum (operands[0]) != true_regnum (operands[1])
+ && true_regnum (operands[0]) != true_regnum (operands[2]))
+ return \"xor %1,%2,%0\";
+ if (REG_P (operands[2]) && REG_P (operands[0])
+ && true_regnum (operands[2]) == true_regnum (operands[0]))
+ return \"xor %1,%0\";
+ return \"xor %2,%0\";
+}"
+ [(set_attr "cc" "set_znv")])
+
+(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=dx")
(xor:SI (match_operand:SI 1 "register_operand" "%0")
(match_operand:SI 2 "nonmemory_operand" "dxi")))]
@@ -815,7 +1188,14 @@
(not:SI (match_operand:SI 1 "register_operand" "")))]
""
"")
-
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=dx,!dax")
+ (not:SI (match_operand:SI 1 "register_operand" "0,0")))]
+ "TARGET_AM33"
+ "not %0"
+ [(set_attr "cc" "set_znv")])
+
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=dx")
(not:SI (match_operand:SI 1 "register_operand" "0")))]
@@ -1215,6 +1595,20 @@
"")
(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=dx,dx,dx,!dax,!dax,!dax")
+ (zero_extend:SI
+ (match_operand:QI 1 "general_operand" "0,dax,m,0,dax,m")))]
+ "TARGET_AM33"
+ "@
+ extbu %0
+ mov %1,%0\;extbu %0
+ movbu %1,%0
+ extbu %0
+ mov %1,%0\;extbu %0
+ movbu %1,%0"
+ [(set_attr "cc" "none_0hit")])
+
+(define_insn ""
[(set (match_operand:SI 0 "general_operand" "=dx,dx,dx")
(zero_extend:SI
(match_operand:QI 1 "general_operand" "0,d,m")))]
@@ -1233,6 +1627,20 @@
"")
(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=dx,dx,dx,!dax,!dax,!dax")
+ (zero_extend:SI
+ (match_operand:HI 1 "general_operand" "0,dax,m,0,dax,m")))]
+ "TARGET_AM33"
+ "@
+ exthu %0
+ mov %1,%0\;exthu %0
+ movhu %1,%0
+ exthu %0
+ mov %1,%0\;exthu %0
+ movhu %1,%0"
+ [(set_attr "cc" "none_0hit")])
+
+(define_insn ""
[(set (match_operand:SI 0 "general_operand" "=dx,dx,dx")
(zero_extend:SI
(match_operand:HI 1 "general_operand" "0,dx,m")))]
@@ -1253,6 +1661,18 @@
"")
(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=dx,dx,!dax,!dax")
+ (sign_extend:SI
+ (match_operand:QI 1 "general_operand" "0,dx,0,dax")))]
+ "TARGET_AM33"
+ "@
+ extb %0
+ mov %1,%0\;extb %0
+ extb %0
+ mov %1,%0\;extb %0"
+ [(set_attr "cc" "none_0hit")])
+
+(define_insn ""
[(set (match_operand:SI 0 "general_operand" "=dx,dx")
(sign_extend:SI
(match_operand:QI 1 "general_operand" "0,dx")))]
@@ -1270,6 +1690,18 @@
"")
(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=dx,dx,!dax,!dax")
+ (sign_extend:SI
+ (match_operand:HI 1 "general_operand" "0,dax,0,dax")))]
+ "TARGET_AM33"
+ "@
+ exth %0
+ mov %1,%0\;exth %0
+ exth %0
+ mov %1,%0\;exth %0"
+ [(set_attr "cc" "none_0hit")])
+
+(define_insn ""
[(set (match_operand:SI 0 "general_operand" "=dx,dx")
(sign_extend:SI
(match_operand:HI 1 "general_operand" "0,dx")))]
@@ -1292,6 +1724,39 @@
"")
(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=dax,dx,!dax")
+ (ashift:SI
+ (match_operand:SI 1 "register_operand" "0,0,dax")
+ (match_operand:QI 2 "nonmemory_operand" "J,dxi,dax")))]
+ "TARGET_AM33"
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 1)
+ return \"add %0,%0\";
+
+ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 2)
+ return \"asl2 %0\";
+
+ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 3
+ && REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS)
+ return \"asl2 %0\;add %0,%0\";
+
+ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 4
+ && REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS)
+ return \"asl2 %0\;asl2 %0\";
+
+ if (true_regnum (operands[1]) == true_regnum (operands[0]))
+ return \"asl %S2,%0\";
+
+ if (REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS
+ && REGNO_REG_CLASS (true_regnum (operands[1])) == DATA_REGS
+ && true_regnum (operands[0]) != true_regnum (operands[2]))
+ return \"mov %1,%0\;asl %S2,%0\";
+ return \"asl %2,%1,%0\";
+}"
+ [(set_attr "cc" "set_zn")])
+
+(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=dax,dx,dx,dx,dx")
(ashift:SI
(match_operand:SI 1 "register_operand" "0,0,0,0,0")
@@ -1314,6 +1779,25 @@
"")
(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=dx,!dax")
+ (lshiftrt:SI
+ (match_operand:SI 1 "register_operand" "0,dax")
+ (match_operand:QI 2 "nonmemory_operand" "dxi,dax")))]
+ "TARGET_AM33"
+ "*
+{
+ if (true_regnum (operands[1]) == true_regnum (operands[0]))
+ return \"lsr %S2,%0\";
+
+ if (REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS
+ && REGNO_REG_CLASS (true_regnum (operands[1])) == DATA_REGS
+ && true_regnum (operands[0]) != true_regnum (operands[2]))
+ return \"mov %1,%0\;lsr %S2,%0\";
+ return \"lsr %2,%1,%0\";
+}"
+ [(set_attr "cc" "set_zn")])
+
+(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=dx")
(lshiftrt:SI
(match_operand:SI 1 "register_operand" "0")
@@ -1331,6 +1815,25 @@
"")
(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=dx,!dax")
+ (ashiftrt:SI
+ (match_operand:SI 1 "register_operand" "0,dax")
+ (match_operand:QI 2 "nonmemory_operand" "dxi,dax")))]
+ "TARGET_AM33"
+ "*
+{
+ if (true_regnum (operands[1]) == true_regnum (operands[0]))
+ return \"asr %S2,%0\";
+
+ if (REGNO_REG_CLASS (true_regnum (operands[0])) == DATA_REGS
+ && REGNO_REG_CLASS (true_regnum (operands[1])) == DATA_REGS
+ && true_regnum (operands[0]) != true_regnum (operands[2]))
+ return \"mov %1,%0\;asr %S2,%0\";
+ return \"asr %2,%1,%0\";
+}"
+ [(set_attr "cc" "set_zn")])
+
+(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=dx")
(ashiftrt:SI
(match_operand:SI 1 "register_operand" "0")
@@ -1495,6 +1998,7 @@
{
int i, need_comma;
int d2, d3, a2, a3;
+ int exreg1;
need_comma = 0;
fputs (\"\\tret [\", asm_out_file);
@@ -1524,6 +2028,14 @@
fputs (\"a3\", asm_out_file);
need_comma = 1;
}
+ if (regs_ever_live[14] || regs_ever_live[15]
+ || regs_ever_live[16] || regs_ever_live[17])
+ {
+ if (need_comma)
+ fputc (',', asm_out_file);
+ fputs (\"exreg1\", asm_out_file);
+ need_comma = 1;
+ }
fprintf (asm_out_file, \"],%d\\n\", INTVAL (operands[0]));
return \"\";
}"
@@ -1536,6 +2048,7 @@
{
int i, need_comma;
int d2, d3, a2, a3;
+ int exreg1;
need_comma = 0;
fputs (\"\\tmovm [\", asm_out_file);
@@ -1565,6 +2078,14 @@
fputs (\"a3\", asm_out_file);
need_comma = 1;
}
+ if (regs_ever_live[14] || regs_ever_live[15]
+ || regs_ever_live[16] || regs_ever_live[17])
+ {
+ if (need_comma)
+ fputc (',', asm_out_file);
+ fputs (\"exreg1\", asm_out_file);
+ need_comma = 1;
+ }
fputs (\"],(sp)\\n\", asm_out_file);
return \"\";
}"
diff --git a/gcc/config/mn10300/t-mn10300 b/gcc/config/mn10300/t-mn10300
index 5dbb46f..0e3f74b 100644
--- a/gcc/config/mn10300/t-mn10300
+++ b/gcc/config/mn10300/t-mn10300
@@ -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
diff --git a/gcc/invoke.texi b/gcc/invoke.texi
index f1b06497..8213cf4 100644
--- a/gcc/invoke.texi
+++ b/gcc/invoke.texi
@@ -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