diff options
author | Jeffrey A Law <law@cygnus.com> | 1999-12-02 00:21:59 +0000 |
---|---|---|
committer | Jeff Law <law@gcc.gnu.org> | 1999-12-01 17:21:59 -0700 |
commit | 705ac34f068eddf9493bc0ce8c34392667db1fdb (patch) | |
tree | e49cefcce7d7b3499134e5d15d195e9867f43066 | |
parent | d525dfdf293509387773497c46f672495ec2af7c (diff) | |
download | gcc-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/ChangeLog | 39 | ||||
-rw-r--r-- | gcc/config/mn10300/mn10300.c | 54 | ||||
-rw-r--r-- | gcc/config/mn10300/mn10300.h | 93 | ||||
-rw-r--r-- | gcc/config/mn10300/mn10300.md | 525 | ||||
-rw-r--r-- | gcc/config/mn10300/t-mn10300 | 6 | ||||
-rw-r--r-- | gcc/invoke.texi | 10 |
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 |